回答
添加此答案的完整性,因爲在撰寫本文時,這裏沒有答案包含直接解決問題的工作代碼示例。
雖然其他答案在這裏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;
}
}
當然!這樣形成的矩陣中的第三個向量與另外兩個正交,所以行列式是棱鏡的面積,其基礎是由兩個平面的法線形成的平行四邊形。該平行四邊形的面積是叉積的大小,該棱柱的高度也是叉積的大小。因此,交易量是平方的交叉乘積。然而,'if(det!= 0)'不是檢查平行平面的方法,因爲它很可能是由於舍入錯誤而變成1.1212e-12。 –
@EvgeniSergeev,對 - 在實踐中進行這些計算時,您需要將其與一個epsilon進行比較,在答案中指出。 – ideasman42
你爲什麼要做交叉產品來計算r_point?由於我們定義了與平面1垂直的第3個平面,而且2不是'''p3.normal.cross(p2.normal)= p1.normal'''和'''p1.normal.cross(p3_normal)= p2.normal '''? – Ghetolay
線的交叉產品是方向的交叉線。現在你需要在十字路口的一個點。
您可以通過在叉積上取一個點,然後減去平面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
的平面的方程爲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)
該方法通過零避免了分裂,只要兩個平面不平行。
如果這些是平面:
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
很好的答案。對於3個平面相交的封閉形式解決方案實際上是在圖形寶石1,第305頁。 – bobobobo
查找就行了
點如果要獲得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平面)
的交集獲取線
一旦你有共同的2面相交的點,線只是去
P + T * d
其中P是點交點,t可以從(-inf,inf)去,d是兩個原始平面的法線的叉積的方向矢量。
路口的紅色和藍色平面之間的線看起來像這樣
效率和穩定性
「穩健」(第2方式)通過我的計算需要48個基本OPS,VS第一種方式(x,y的隔離)使用的36個基本操作。在這兩種方式之間穩定性和#計算之間有一個折衷。
如果B 爲0並且您沒有檢查,將(0,inf,inf)從呼叫返回到第一種方式將會非常具有災難性。因此,在if
語句中添加並確保不以第一種方式除以0可能會以代碼膨脹和增加的分支(可能會非常昂貴)爲代價提供穩定性。 3平面相交法幾乎是無分支的,不會給你無窮無盡的印象。
注意:等式'z =(( - B2/B1)* D1 - D2)/(C2 * B2/B1)* C1 )'不正確 - 它應該讀取'z =((B2/B1)* D1 - D2)/(C2 - B2/B1 * C1)' – chopper
基於行列式的方法很整齊,但很難理解它爲什麼起作用。
這是另一種更直觀的方法。
這個想法是先從原點走到第一個平面上的最近點(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)
應該工作得很好。
- 1. 兩架飛機的交集
- 2. VTK:一架飛機和一架Polydata之間的相交處
- 3. 如何計算兩架飛機之間的角度?
- 4. 如何找到兩架飛機的交點
- 5. 交換機和總線架構之間的區別?
- 6. 兩個截面飛機的交集
- 7. 兩條線之間的交點,Wolfram Mathematica
- 8. 這兩條線是否會在笛卡爾飛機中相交
- 9. 兩個線程之間交替
- 10. 檢測兩個3d飛機之間的碰撞
- 11. Three.js能在一架飛機上投下另一架飛機嗎?
- 12. 通過無線連接的兩臺計算機之間的信息交換
- 13. 線與折線之間的交點
- 14. 我怎樣才能找到三架飛機的交點?
- 15. 填充兩條相交的線之間的區域?
- 16. 旋轉飛機使其平行於另一架飛機
- 17. 在3D引擎中與旋轉飛機相交的拋物線
- 18. 如何獲取兩個.csv文件之間的相交線?
- 19. 如何創建在兩種顏色之間交替的虛線?
- 20. 如何計算兩條線之間的交點
- 21. 交換兩個線程之間的DATAS在Python
- 22. 座標中兩條直線之間的交點
- 23. 如何模擬兩臺計算機之間的無線連接?
- 24. 計算兩臺攝像機之間的基線距離(圖像)
- 25. 交換機的inputType到數對飛
- 26. 在飛機上的3D正交投影
- 27. 線與矩形之間的交點
- 28. 樣條和直線之間的交點
- 29. 2個對象之間的相交線
- 30. 2個線程之間的交替
你有結果方程的線? – hcb
它在代碼中的作用與它在數學中完全相同,只是表示形式不同。 –
我讀過http://members.tripod.com/vector_applications/xtion_of_two_planes/,但我無法通過編程獲得 – AMH