三維座標下判斷P點是否在三角形ABC中

2021-09-24 16:13:10 字數 4634 閱讀 3262

在網上找的都是二位座標下的,我寫個三維的吧

1.面積法

同二位座標下一樣,只需要判斷三角形abc的面積是否等於s_abp+s_bcp+s_acp。當然此方法需要開好幾個根,不僅效率很低,還會損失精度,所以我使用的輸入型別是int,並把誤差控制到10e(-8)。裡面還用到了一點向量的知識,但很好理解。**如下:

1 #include2 #include3 #include4

using

namespace

std;

5class

point618

int getx(void)

19int gety(void)

20int getz(void)

21};

22class

vector3

2330

void sety(int y)

31void setz(int z)

32int getx(void)

33int gety(void)

34int getz(void)

35};

36vector3 tovector3(point m, point n)

3744

bool

istri(point a, point b, point c)

4554

double

distance(point m, point n)

5561

double

s(point a,point b,point c)

6270

bool

pointintri(point a, point b, point c, point p)

7181

82int main(void)83

111else

112 cout << "

abc三點一線,組不成三角形

"<

113 cout << "

輸入q退出,輸入c繼續

"<

114char

sign;

115 cin >>sign;

116if (sign == '

q')break

;117

}118 system("

pause");

119return0;

120 }

2.向量法先考慮abcp四點共面,如下圖:(我是知識的搬運工。。。)

然後我們再考慮如何判斷四點共面:求出ab與ac的叉積,再判斷ap與叉積是否垂直,即點積是否為0

#include#include

using

namespace

std;

class

point

double getx(void)

double gety(void)

double getz(void)

};class

vector3

void sety(double y)

void setz(double z)

double getx(void)

double gety(void)

double getz(void)

vector3 cross(vector3 b)

//向量積,即叉乘

double dot(vector3 a)//

向量點乘

};vector3 tovector3(point m, point n)

bool side(point a,point b, point c, point p)//

是否在同一側

bool

pointintri(point a, point b, point c, point p)

bool

issnamedirction(vector3 ab, vector3 bc)

bool

issnameplane(point a, point b, point c, point p)

bool

istri(point a, point b, point c)

int main(void

)

else

cout

<< "

點p都abc所確定的平面,更不可能在三角形abc內

"<

}else

cout

<< "

abc三點一線,組不成三角形

"<

cout

<< "

輸入q退出,輸入c繼續

"<

char

sign;

cin >>sign;

if (sign == '

q')break

; }

system(

"pause");

return0;

}

2.1向量法plus上個方法直接從二維推到了三維,其實我們被忽悠了,判斷向量是否同向我們不是一直用λ的嗎?上乙個**中的issnamedirction函式就是從此轉換過來的。(他忽悠我們的目的是在二維中減少運算)再考慮當四點不共面時,可知原來的兩個叉積所成的夾角為(0,,180),又考慮四點在同一平面內p卻在三角形外,兩叉積夾角為180。所以我們只需要判斷三次兩叉積同向即可,更改side函式內**,並刪除issnameplane函式,side函式**如下

bool side(point a, point b, point c, point p)//是否在同一側

若四點共面,可知ap=u * ac + v * ab(以兩點表示的都是向量)

如果係數u或v為負值,那麼相當於朝相反的方向移動,即ba或ca方向。那麼如果想讓p位於三角形abc內部,u和v必須滿足什麼條件呢?有如下三個條件

u >= 0   v >= 0  u + v <= 1

證明如下圖;當p在bc邊上(幫你理解,證明不規範)

由三角形bpp'與三角形abc相似得p'p=u*ac,得p'b=u*ab,即u*ab+v*ab=ab,得u+v=1,只要u和v乙個在變小都會使p在三角形內,反之即會在外,於是得u+v<=1

令v0 = ac, v1 = ab, v2 = ap,則v2 = u * v0 + v * v1,現在是乙個方程,兩個未知數,無法解出u和v,將等式兩邊分別點乘v0和v1的到兩個等式

(v2) • v0 = (u * v0 + v * v1) • v0

(v2) • v1 = (u * v0 + v * v1) • v1

注意到這裡u和v是數,而v0,v1和v2是向量,所以可以將點積展開得到下面的式子。

v2 • v0 = u * (v0 • v0) + v * (v1 • v0)  // 式1

v2 • v1 = u * (v0 • v1) + v * (v1• v1)   // 式2

解這個方程得到

u = ((v1•v1)(v2•v0)-(v1•v0)(v2•v1)) / ((v0•v0)(v1•v1) - (v0•v1)(v1•v0))

v = ((v0•v0)(v2•v1)-(v0•v1)(v2•v0)) / ((v0•v0)(v1•v1) - (v0•v1)(v1•v0))

由柯西不等式:對任意向量v0, v1: v0^2 * v1^2 >= (v0 • v1)^2。又v0, v1不共線,所以等號不成立,即公共分母》0

設 a = v0 • v0, b = v1 • v1, c = v0 • v1,d = v2 • v0, e = v2 • v1, 公共分母 f = a * b - c* c,令x = b * d - c * e; y = a * e - c * d

則:u = x / f, v = y / f           由: u >= 0, v >= 0, u + v <= 1, 和f > 0有:x >= 0, y >= 0, x + y - f <= 0

重寫pointintri函式**

bool pointintri(point a, point b, point c, point p)

需要注意:我們開始推理時預設四點共面,若四點不共面,最開始的等式ap=u * ac + v * ab,便不可能存在。所以我們要保留2.1的issnameplane函式。

3.射線和三角形的相交檢測

射線和三角形的相交檢測具體過程就檢視鏈結

大致思路先確定射線op是否與三角形abc相交,若相交再判斷交點是否為p。我猜這個才是實際中用到的吧(還有個內角和法,效率跟第一種方法差不多,不講了,有興趣的參考文獻裡有)。

總結:哎,英語沒學好same啊,多加了個n。。。

三維座標下判斷P點是否在三角形ABC中

在網上找的都是二位座標下的,我寫個三維的吧 1.面積法 同二位座標下一樣,只需要判斷三角形abc的面積是否等於s abp s bcp s acp。當然此方法需要開好幾個根,不僅效率很低,還會損失精度,所以我使用的輸入型別是int,並把誤差控制到10e 8 裡面還用到了一點向量的知識,但很好理解。如下...

判斷點是否在三角形內

概述 給定三角形abc和一點p x,y,z 判斷點p是否在abc內。這是遊戲設計中乙個常見的問題。需要注意的是,這裡假定點和三角形位於同乙個平面內。本文介紹三種不同的方法,由淺入深 一 內角和法 連線點p和三角形的三個頂點得到三條線段pa,pb和pc,求出這三條線段與三角形各邊的夾角,如果所有夾角之...

判斷點是否在三角形內

給定三角形abc和一點p x,y,z 判斷點p是否在abc內。這是遊戲設計中乙個常見的問題。需要注意的是,這裡假定點和三角形位於同乙個平面內。本文介紹三種不同的方法,由淺入深 連線點p和三角形的三個頂點得到三條線段pa,pb和pc,求出這三條線段與三角形各邊的夾角,如果所有夾角之和為180度,那麼點...