簡體   English   中英

如何將點投影到 3D 平面上?

[英]How to project a point onto a plane in 3D?

我有一個 3D 點 (point_x,point_y,point_z),我想將它投影到 3D 空間中的 2D 平面上,該平面由點坐標 (orig_x,orig_y,orig_z) 和一元垂直向量 (normal_dx) 定義,normal_dy,normal_dz)。

我該如何處理?在此處輸入圖像描述

  1. 從您的orig創建一個向量到興趣點:

v = point-orig (in each dimension);

  1. 取該向量與單位法線向量n的點積:

dist = vx*nx + vy*ny + vz*nz; dist = 點到平面沿法線的標量距離

  1. 將單位法線向量乘以距離,然后從您的點中減去該向量。

projected_point = point - dist*normal;

用圖片編輯:我對你的圖片做了一些修改。 紅色是v dist是藍色和綠色的長度,等於v dot normal 藍色是normal*dist 綠色與藍色是相同的向量,它們只是繪制在不同的地方。 要找到plane_xyz,請從point開始並減去綠色向量。

點到平面的投影

這真的很容易,您所要做的就是找到從點P到平面的垂直(此處縮寫為|_ )距離,然后P平移平面法線方向上的垂直距離。 結果是翻譯后的P位於平面中。

舉一個簡單的例子(我們可以通過檢查來驗證):

設置 n=(0,1,0),P=(10,20,-5)。

在此處輸入圖像描述

投影點應為 (10,10,-5)。 您可以通過檢查看到 Pproj 與平面垂直 10 個單位,如果它在平面內,則 y=10。

那么我們如何分析地找到這個呢?

平面方程為Ax+By+Cz+d=0。 這個等式的意思是“為了使點 (x,y,z) 在平面內,它必須滿足 Ax+By+Cz+d=0”

上面繪制的平面的 Ax+By+Cz+d=0 方程是什么?

平面具有法線 n=(0,1,0)。 只需使用平面中已有的測試點即可找到 d:

(0)x + (1)y + (0)z + d = 0

點 (0,10,0) 在平面內。 代入上面,我們發現,d=-10。 平面方程為 0x + 1y + 0z - 10 = 0(如果簡化,則得到 y=10)。

d的一個很好的解釋是它表示您需要沿其法線平移平面以使平面通過原點的垂直距離

無論如何,一旦我們有了d ,我們可以通過以下等式找到任何點到平面的 |_ 距離:

在此處輸入圖像描述

|_ 到平面的距離有 3 類可能的結果:

  • 0:完全在平面上(幾乎不會發生浮點不准確問題)
  • +1:>0:在平面的前面(在正常側)
  • -1:<0:在平面后面(在正常的相反側)

反正,

在此處輸入圖像描述

您可以通過上圖中的檢查來驗證其是否正確

該答案是對兩個現有答案的補充。 我的目標是展示@tmpearce 和@bobobobo 的解釋如何歸結為同一件事,同時為那些只想復制最適合他們情況的方程式的人提供快速答案。

由法線n和點o定義的平面的方法

@tmpearce 在答案中解釋了此方法。

給定具有法線n和平面上的點o的平面的點法線定義,可以通過以下方式找到點p ',即平面上最靠近給定點p的點:

  1. p ' = p - ( n ⋅ ( p - o )) × n

由法線n和標量d定義的平面的方法

@bobobobo 在答案中解釋了這種方法。

給定由法線n和標量d定義的平面,點p ',即平面上最靠近給定點p的點,可以通過以下方式找到:

  1. p ' = p - ( np + d ) × n

相反,如果你有一個平面的點法線定義(平面由平面上的法線n和點o定義)@bobobobo 建議找到d

  1. d = - no

並將其代入等式 2。這會產生:

  1. p ' = p - ( np - no ) × n

關於差異的說明

仔細看看方程 1 和 4。通過比較它們,你會發現方程 1 使用n ⋅ ( p - o ),而方程 2 使用np - no 這實際上是寫下同一件事的兩種方式:

  1. n ⋅ ( p - o ) = np - no = np + d

因此,人們可以選擇將標量d解釋為好像它是“預計算”。 我解釋一下:如果一個平面的no已知,但o只用於計算n ⋅ ( p - o ),我們不妨用nd定義平面,然后計算np + d ,因為我們剛剛看到這是同一件事。

此外,使用d進行編程有兩個優點:

  1. 現在找到p ' 是一個更簡單的計算,尤其是對於計算機。 相比:
  • 使用no :3 次減法 + 3 次乘法 + 2 次加法
  • 使用nd :0 次減法 + 3 次乘法 + 3 次加法。
  1. 使用d將平面的定義限制為僅 4 個實數(3 表示n + 1 表示d ),而不是 6 (3 表示n + 3 表示o )。 這樣可以節省 ⅓ 內存。

僅提供平面原點和法向量是不夠的。 這確實定義了 3d 平面,但是這並沒有定義平面上的坐標系。

認為您可以相對於其原點圍繞法線向量旋轉您的平面(即,將法線向量放在原點並“旋轉”)。

但是,您可能會發現投影點到原點的距離(這顯然與旋轉無關)。

從 3d 點減去原點。 然后用法線方向做叉積。 如果您的法線向量被歸一化 - 結果向量的長度等於所需的值。

編輯

一個完整的答案需要一個額外的參數。 比如說,您還提供了表示平面上 x 軸的向量。 所以我們有向量nx 假設它們是標准化的。

原點用O表示,你的 3D 點是p

然后您的觀點通過以下方式預測:

x = ( p - O ) 點x

y = ( p - O ) 點 ( n交叉x )

令 V = (orig_x,orig_y,orig_z) - (point_x,point_y,point_z)

N = (normal_dx,normal_dy,normal_dz)

令 d = V.dotproduct(N);

投影點 P = V + dN

我認為你應該稍微改變一下描述飛機的方式。 事實上,描述平面的最佳方式是通過向量n和標量c

( x , n ) = c

常數 c 的(絕對值)是平面到原點的距離,等於 ( P , n ),其中P是平面上的任意點。

所以,讓P是你的原點A ' 是新點A在平面上的投影。 你需要做的是找到一個這樣的A ' = A - a* n滿足平面方程,即

( A - a* n , n ) = ( P , n )

求解 a,你會發現

一 = (, n ) - ( P , n ) = (, n ) - c

這使

A ' = A - [( A , n ) - c] n

用你的名字,這讀

c = orig_x*normal_dx + orig_y*normal_dy+orig_z*normal_dz;
a = point_x*normal_dx + point_y*normal_dy + point_z*normal_dz - c;
planar_x = point_x - a*normal_dx;
planar_y = point_y - a*normal_dy;
planar_z = point_z - a*normal_dz;

注意:如果您存儲 c=( P , n ) 而不是原點P ,則您的代碼將保存一個標量積,這意味着每個投影的觸發器基本上減少了 25%(如果此例程在您的代碼中多次使用)。

r為投影點, p為投影結果。 c為平面上的任意點,令n為平面的法線(不一定要歸一化)。 為某個標量 m 寫p = r + m d ,如果它們沒有解,則該標量 m 將被視為不確定。 由於 ( p - c )。 n = 0,因為平面上的所有點都滿足這一限制( r - c )。 n + m( d . n ) = 0 所以 m = [( c - r )。 n ]/[ d . n ] 使用點積 (.)。 但如果d n = 0 無解。 例如,如果dn相互垂直,則沒有可用的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM