平面中判斷點在三角形內演算法(重心法)
阿新 • • 發佈:2021-06-12
目錄
\[\vec{V_0P} = u(\vec{V_0V_1}) + v(\vec{V_0V_2})
\]
\[\begin{cases}
D = (\vec{V_0V_1 \cdot \vec{V_0V_1}}) * (\vec{V_0V_2} \cdot \vec{V_0V_2}) - (\vec{V_0V_2} \cdot \vec{V_0V_1}) * (\vec{V_0V_1} \cdot \vec{V_0V_2}) \\
D1 = (\vec{V_0P} \cdot \vec{V_0V_1}) * (\vec{V_0V_2} \cdot \vec{V_0V_2}) - (\vec{V_0V_2} \cdot \vec{V_0V_1}) * (\vec{V_0P} \cdot \vec{V_0V_2}) \\
D2 = (\vec{V_0V_1 \cdot \vec{V_0V_1}}) * (\vec{V_0P} \cdot \vec{V_0V_2}) - (\vec{V_0P} \cdot \vec{V_0V_1}) * (\vec{V_0V_1} \cdot \vec{V_0V_2}) \\
\end{cases}
\]\[\begin{cases}
u = D1 / D \\
v = D2 / D \\
\end{cases}
\]
1. 概述
在文章《判斷點是否在三角形內》中還提到了一種判斷點在三角形內外的演算法——重心法。這種演算法同樣用到了三角形的空間向量方程,但是值得注意的是,這種演算法卻只能判斷平面中點在三角形的內外關係(已知空間向量方程,是可以判斷三維空間關係的:空間中判斷點在三角形內演算法(方程法))。
2. 詳論
2.1. 原理
重心法的推導過程與空間中判斷點在三角形內演算法(方程法))的推導過程比較相似。對於三個頂點為V0,V1,V2組成的空間三角形,對於三角形內的任一點P,有如下引數方程:
\[\vec{P} = (1 - u - v) \vec{V_0} + u \vec{V_1} + v \vec{V_2} \]變換位置,我們可以將其調整為:
將上式分別點乘\(\vec{V_0V_1}\)和\(\vec{V_0V_2}\),有:
\[\begin{cases} \vec{V_0P} \cdot \vec{V_0V_1} = u(\vec{V_0V_1 \cdot \vec{V_0V_1}}) + v(\vec{V_0V_2} \cdot \vec{V_0V_1}) \\ \vec{V_0P} \cdot \vec{V_0V_2} = u(\vec{V_0V_1} \cdot \vec{V_0V_2}) + v(\vec{V_0V_2} \cdot \vec{V_0V_2}) \\ \end{cases} \]很顯然,這是個2行2列的線性方程組,通過克萊姆法則來求解:
2.2. 實現
詳細的程式碼實現如下:
//空間三角形
//按照逆時針順序插入值並計算法向量
template <class T>
class Triangle
{
public:
Vec3<T> v0;
Vec3<T> v1;
Vec3<T> v2;
Triangle()
{
}
Triangle(Vec3<T> v0, Vec3<T> v1, Vec3<T> v2)
{
this->v0 = v0;
this->v1 = v1;
this->v2 = v2;
}
void Set(Vec3<T> v0, Vec3<T> v1, Vec3<T> v2)
{
this->v0 = v0;
this->v1 = v1;
this->v2 = v2;
}
// 判斷平面點P是否在平面三角形內(重心法)
bool PointInTriangle2D(Vec3<T>& P)
{
auto v01 = v1 - v0 ;
auto v02 = v2 - v0 ;
auto v0p = P - v0 ;
double dot00 = v01 * v01 ;
double dot01 = v01 * v02 ;
double dot02 = v01 * v0p ;
double dot11 = v02 * v02 ;
double dot12 = v02 * v0p ;
double D = (dot00 * dot11 - dot01 * dot01);
if(D == 0.0)
{
return false;
}
double inverDeno = 1 / D ;
double u = (dot11 * dot02 - dot01 * dot12) * inverDeno ;
if (u < 0 || u > 1)
{
return false ;
}
double v = (dot00 * dot12 - dot01 * dot02) * inverDeno ;
if (v < 0 || v > 1)
{
return false ;
}
return u + v <= 1 ;
}
};
2.3. 總結
本質上,這個演算法與空間中判斷點在三角形內演算法(方程法)是同一種演算法的不同推導,都是通過空間三角形中點的向量方程來求解的,但是是採用了不同的解法。不過為什麼一個可以判斷空間關係,一個只能判斷平面關係呢?關鍵在於點是否能讓向量方程成立,這個求解演算法可以求解u,v,但沒有保證空間內的向量方程能夠成立。