2011-06-20 88 views
12

如何找到兩架飛機之間的交線?兩架飛機之間的交線

我知道數學的想法,我做了法向量

但飛機之間的交叉產品如何從所得到的向量的行編程

+0

你有結果方程的線? – hcb

+0

它在代碼中的作用與它在數學中完全相同,只是表示形式不同。 –

+0

我讀過http://members.tripod.com/vector_applications/xtion_of_two_planes/,但我無法通過編程獲得 – AMH

回答

8

添加此答案的完整性,因爲在撰寫本文時,這裏沒有答案包含直接解決問題的工作代碼示例。

雖然其他答案在這裏already covered the principles


查找兩個平面之間的線路可以使用3平面的交點算法的簡化版本來計算。

2'nd,「更健壯的方法」從bobobobo's答案引用3平面交叉口。

雖然這可以很好地用於2個平面(其中第三平面可以使用的前兩個叉積來計算),可以進一步降低對於2平面版本的問題。

  • 無需使用3×3矩陣行列式,
    代替我們可以使用叉積的平方長度,第一和第二平面之間(其是3'rd平面的方向)
  • 無需包含第三架飛機的距離,
    (計算最終位置)
  • 不需要否定距離。
    通過交換交叉產品訂單來保存一些cpu-cycles。

包括此代碼示例,因爲它可能不會立即顯而易見。

// Intersection of 2-planes: a variation based on the 3-plane version. 
// see: Graphics Gems 1 pg 305 
// 
// Note that the 'normal' components of the planes need not be unit length 
bool isect_plane_plane_to_normal_ray(
     const Plane& p1, const Plane& p2, 
     // output args 
     Vector3f& r_point, Vector3f& r_normal) 
{ 
    // logically the 3rd plane, but we only use the normal component. 
    const Vector3f p3_normal = p1.normal.cross(p2.normal); 
    const float det = p3_normal.length_squared(); 

    // If the determinant is 0, that means parallel planes, no intersection. 
    // note: you may want to check against an epsilon value here. 
    if (det != 0.0) { 
     // calculate the final (point, normal) 
     r_point = ((p3_normal.cross(p2.normal) * p1.d) + 
        (p1.normal.cross(p3_normal) * p2.d))/det; 
     r_normal = p3_normal; 
     return true; 
    } 
    else { 
     return false; 
    } 
} 
+0

當然!這樣形成的矩陣中的第三個向量與另外兩個正交,所以行列式是棱鏡的面積,其基礎是由兩個平面的法線形成的平行四邊形。該平行四邊形的面積是叉積的大小,該棱柱的高度也是叉積的大小。因此,交易量是平方的交叉乘積。然而,'if(det!= 0)'不是檢查平行平面的方法,因爲它很可能是由於舍入錯誤而變成1.1212e-12。 –

+0

@EvgeniSergeev,對 - 在實踐中進行這些計算時,您需要將其與一個epsilon進行比較,在答案中指出。 – ideasman42

+0

你爲什麼要做交叉產品來計算r_point?由於我們定義了與平面1垂直的第3個平面,而且2不是'''p3.normal.cross(p2.normal)= p1.normal'''和'''p1.normal.cross(p3_normal)= p2.normal '''? – Ghetolay

-2

線的交叉產品是方向的交叉線。現在你需要在十字路口的一個點。

您可以通過在叉積上取一個點,然後減去平面A *的法向距離平面A的距離和平面B的法向距離平面b的距離。清潔器:

P =點上交叉乘積

交點=([P] - ([正常平面A] * [從p到平面的距離) - ([正常平面B的] * [從p到平面B的距離))

編輯:

您有兩個平面與兩條法線:

N1 and N2 

叉積是相貫線的方向:

C = N1 x N2 

上面的類有一個函數來計算點和平面之間的距離。用它來獲得到兩個平面第C一些點p的距離:

p = C //p = 1 times C to get a point on C 
d1 = plane1.getDistance(p) 
d2 = plane2.getDistance(p) 

交線:

resultPoint1 = (p - (d1 * N1) - (d2 * N2)) 
resultPoint2 = resultPoint1 + C 
+0

我會告訴你我理解什麼1.獲得交叉產品2.獲得這個交叉產品的點,然後得到交點[p]的意思是這個幅度是真的,我有個問題我需要兩點畫線,如何得到第二點 – AMH

+0

這個交點是一點。交叉積是線的方向,所以第二個點將是交叉點+ x *交叉積,例如交叉點+ 1 *交叉積 – hcb

+0

對不起,p = C // p = 1倍C得到一個點C的意思是,好吧,我用n1和n2的交叉乘積得到C,爲什麼我用p = c – AMH

17

的平面的方程爲ax + by + cz + d = 0,其中(A,B,c)是飛機的法線,d是到原點的距離。這意味着滿足該方程的每個點(x,y,z)都是該平面的一員。

給定兩個平面:

P1: a1x + b1y + c1z + d1 = 0 
P2: a2x + b2y + c2z + d2 = 0 

兩者之間的交叉點是驗證兩個方程的點的集合。要找到這條線上的點,你可以簡單地爲x選擇一個值,任何值,然後求解y和z的方程。

y = (-c1z -a1x -d1)/b1 
z = ((b2/b1)*(a1x+d1) -a2x -d2)/(c2 - c1*b2/b1) 

如果您x=0,這得到簡單:

y = (-c1z -d1)/b1 
z = ((b2/b1)*d1 -d2)/(c2 - c1*b2/b1) 
+0

Upvoted實際顯示你的數學。 =) –

+1

如何獲取行的開始和結束,並且第二個點 – AMH

+3

x = 0可能不總是有效。例如。如果生成的線平行於y-z平面。 – Onur

6

該方法通過零避免了分裂,只要兩個平面不平行。

如果這些是平面:

A1*x + B1*y + C1*z + D1 = 0 
A2*x + B2*y + C2*z + D2 = 0 

1)找到平行於交線的向量。這也是垂直於其他兩個平面的第三平面的法線:

(A3,B3,C3) = (A1,B1,C1) cross (A2,B2,C2) 

2)形成3個方程組的系統。這些描述了在一個點相交的3個平面:

A1*x1 + B1*y1 + C1*z1 + D1 = 0 
A2*x1 + B2*y1 + C2*z1 + D2 = 0 
A3*x1 + B3*y1 + C3*z1 = 0 

3)解決它們以找到x1,y1,z1。這是相交線上的一點。

4)交線的參數方程爲:

x = x1 + A3 * t 
y = y1 + B3 * t 
z = z1 + C3 * t 
+0

很好的答案。對於3個平面相交的封閉形式解決方案實際上是在圖形寶石1,第305頁。 – bobobobo

10

查找就行了

點如果要獲得2面的路口,你需要上線和一個點該線的方向。

找到該線的方向非常簡單,只需跨過相交的2個平面的2個法線。

lineDir = n1 × n2 

但是那條線穿過原點,並且沿着您的平面交點運行的線可能不會。因此,Martinho's答案提供了一個很好的開始找到交點(基本上任何點是在兩個飛機上)線上的點。

如果你想看看如何解決這個推導,這裏的數學背後:

首先令x = 0。現在我們在2個方程中有2個未知數,而不是2個方程中的3個未知數(我們任意選擇了一個未知數)。

乙 Y + C Z + d = 0

然後平面方程(因爲我們選擇x = 0的甲條款消除)乙 Y + C Z + d = 0

我們想要y和z,使得這兩個方程都可以正確求解(= 0),因爲給定的B ,C 。

所以,只要乘以(-B/B )頂部當量得到

-B Y +(-B/B )* C Z +(-B/B )* d = 0

乙 Y + C Z + d = 0

添加等式獲得

Z =((-B/B )* D -D )/(C * B/B )* C )

扔你發現到第一方程的Z現在找到ý作爲

Y =(-D - ç 1個 Z)/ B 1

注意最佳變量使得0與最低係數一樣,因爲它無論如何不會傳遞任何信息。因此,如果C 和C 均爲0,則選擇z = 0(而不是x = 0)將是更好的選擇。

如果B = 0(這不是不太可能),上述解決方案仍然可能出現故障。您可以添加一些if語句來檢查B = 0,如果是,請確保解決其中一個其他變量。

溶液中使用的3個平面

user's答案相交,爲3層的平面相交處的閉合形式解實際上是在圖形寶石1的公式爲:

P_intersection =((point_on1 •N1)(N 2×N 3)+(point_on2•N2)(N3×N1)+(point_on3•N3)(N1×N2))/ DET(N1,N2,N3)

實際上point_on1•N1 = -d1(假設你寫你的飛機Ax + By + Cz + D = 0,而不是= -D)。所以,你可以把它改寫爲:

P_intersection =((-d1)(N2×N3)+(-D2)(N3×N1)+(-D3)(N1×N2))/ DET( N1,N2,N3)

相交3架飛機的函數:

// Intersection of 3 planes, Graphics Gems 1 pg 305 
static Vector3f getIntersection(const Plane& plane1, const Plane& plane2, const Plane& plane3) 
{ 
    float det = Matrix3f::det(plane1.normal, plane2.normal, plane3.normal) ; 

    // If the determinant is 0, that means parallel planes, no intn. 
    if(det == 0.f) return 0 ; //could return inf or whatever 

    return (plane2.normal.cross(plane3.normal)*-plane1.d + 
      plane3.normal.cross(plane1.normal)*-plane2.d + 
      plane1.normal.cross(plane2.normal)*-plane3.d)/det ;    
} 

證明它的工作原理(黃點是在這裏RGB平面)

enter image description here

的交集

獲取線

一旦你有共同的2面相交的點,線只是去

P + T * d

其中P是點交點,t可以從(-inf,inf)去,d是兩個原始平面的法線的叉積的方向矢量。

路口的紅色和藍色平面之間的線看起來像這樣

enter image description here

效率和穩定性

「穩健」(第2方式)通過我的計算需要48個基本OPS,VS第一種方式(x,y的隔離)使用的36個基本操作。在這兩種方式之間穩定性和#計算之間有一個折衷。

如果B 爲0並且您沒有檢查,將(0,inf,inf)從呼叫返回到第一種方式將會非常具有災難性。因此,在if語句中添加並確保不以第一種方式除以0可能會以代碼膨脹和增加的分支(可能會非常昂貴)爲代價提供穩定性。 3平面相交法幾乎是無分支的,不會給你無窮無盡的印象。

+0

注意:等式'z =(( - B2/B1)* D1 - D2)/(C2 * B2/B1)* C1 )'不正確 - 它應該讀取'z =((B2/B1)* D1 - D2)/(C2 - B2/B1 * C1)' – chopper

0

基於行列式的方法很整齊,但很難理解它爲什麼起作用。

這是另一種更直觀的方法。

這個想法是先從原點走到第一個平面上的最近點(p1),然後從那裏走到兩個平面相交線上的最近點。 (沿着我打電話下面一v向量。)

Given 
===== 
First plane: n1 • r = k1 
Second plane: n2 • r = k2 

Working 
======= 
dir = n1 × n2 
p1 = (k1/(n1 • n1)) * n1 
v = n1 × dir 
pt = LineIntersectPlane(line = (p1, v), plane = (n2, k2)) 

LineIntersectPlane 
================== 
#We have n2 • (p1 + lambda * v) = k2 
lambda = (k2 - n2 • p1)/(n2 • v) 
Return p1 + lambda * v 

Output 
====== 
Line where two planes intersect: (pt, dir) 

這應該給出相同的點作爲基礎決定的方法。兩者之間幾乎肯定有聯繫。至少分母n2 • v是相同的,如果我們應用「標量三重乘積」規則。所以這些方法可能與條件數字相似。

不要忘記檢查(幾乎)平行飛機。例如:如果使用單位法線,if (dir • dir < 1e-8)應該工作得很好。