**
射線表示:
o + d *t
三角表示:
v0 + (v1 - v0)*u + (v2 - v0) * v
u >= 0;
v >= 0;
u + v < 1;
如果射線相交在三角內,則:
o + d *t = v0 + (v1 - v0)*u + (v2 - v0) * v
u >= 0;
v >= 0;
u + v < 1;
分析:uvt是3個未知數, v0,v1,v2,o,d是已知向量,是個3階行列式,可求uvt
可以做簡化
e1 = v1 - v0;
e2 = v2 - v0;
t = o - v0;
o + d *t = v0 + (v1 - v0)*u + (v2 - v0) * v
=》- d *t + e1*u + e2 * v = t
=》|-d e1 e2| t = t
| | u
| | v
三階行列式求解(克萊姆法則)
=》t = det|t e1 e2| / det|-d e1 e2|
u = det|-d t e2| / det|-d e1 e2|
v = det|-d e1 t| / det|-d e1 e2|
下面的推導只是為簡化函式
根據混合積公式(等價的代數余子式表示方法)
det|a b c| = axb *c = bxc *a = -axc *b //這裡3種轉換,只是為後面簡化成pq更方便
=》t = txe1 *e2 / dxe2 *e1
u = dxe2 *t / dxe2 *e1
v = txe1 *d / dxe2 *e1
簡化p = dxe2
q = txe1
=》t = q *e2 / p *e1
u = p *t / p *e1
v = q *d / p *e1
函式實現:
bool intersecttrangle(
const vec3& o, const vec3& d,
const vec3& v0, const vec3& v1, const vec3& v2,
float& t, float& u, float& v)
else
if(det < 0.0001f)
return false;
u = dot(p, t);
if(u < 0 || u > det)
return false;
vec3 q = cross(t, e1);
v = dot(q, d);
if(v < 0 || u + v > det)
return false;
t = dot(q, e2);
float invdet = 1.0f / det;
t *= invdet;
u *= invdet;
v *= invdet;
return true;
}**說明:
1,裡面有很多if為了提高**效率,
2,確保det>0,如果det<0則令det = -det,並對t做相應的調整,這樣做是為了方便後續計算,否則的話需要分別處理det>0和det<0兩種情況。
3,if(det < 0.0001f) 此時無解,三角與射線近乎平行,注意浮點數和0的比較,一般不用 == 0的方式,而是給定乙個epsilon值,並與這個值比較。
4,u = dot(p, t);這裡實際上u還沒有計算完畢,此時的值是dot(p,t),如果dot(p,t) > det, 那麼u > 1,無交點。
5,要確保u + v <= 1,也即 [dot(p,t) + dot(q, d)] / det 必須不能大於1,否則無交點。
交點座標:
根據上面**求出的t,u,v的值,交點的最終座標可以用下面兩種方法計算
o + dt
(1 - u - v)v0 + uv1 + vv2
*/
射線與三角型 多邊形相交測試
乙個點是否在多邊形裡面,只將這個點向任意方向作乙個射線,若與這條射線有奇數條邊相交則點在多邊形裡面,如果有偶數條邊相交則在外面 實際上兩個三角形合在一起,是乙個四邊形,對於這種多個圖形合在一起的圖形不要做公共邊的測試就行了,把他當成乙個多邊形 或者兩個三角形分開來測試也行。gameres論壇上的co...
圓與三角形(圓與三角形是否相交)
給出圓的圓心和半徑,以及三角形的三個頂點,問圓同三角形是否相交。相交輸出 yes 否則輸出 no 三角形的面積大於0 第1行 乙個數t,表示輸入的測試數量 1 t 10000 之後每4行用來描述一組測試資料。4 1 三個數,前兩個數為圓心的座標xc,yc,第3個數為圓的半徑r。3000 xc,yc ...
13 三角形判定
數學家告訴我們 三角形中,任意兩條邊之和一定大於第三邊。請寫乙個程式,輸入為三條線段的長度,輸出yes或者no代表這三條線段能否組成乙個三角形。輸入三條邊長a,b,c 如果 a加b大於c 並且 b加c大於a 並且 c加a大於b 就輸出yes 否則輸出no 輸入格式 輸入共一行,三個整數,代表三條線段...