算法解析
这个算法的原理是利用点到线段端点的公式进行逆向计算。假设有三角形ABC和点O。
若点O在三角形ABC内部,则必有以下条件成立:
{
A
O
⃗
=
α
×
A
B
⃗
+
β
×
A
C
⃗
,
α
和
β
均
为
常
数
α
≥
0
β
≥
0
α
+
β
≤
1
\begin{cases} \vec{AO} = \alpha \times \vec{AB} + \beta \times \vec{AC},{\alpha和\beta均为常数}&\\ \alpha \geq 0& \\ \beta \geq 0& \\ \alpha + \beta \leq 1 \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧AO=α×AB+β×AC,α和β均为常数α≥0β≥0α+β≤1
于是判断点是否在三角形内部,只需要求出
α
\alpha
α和
β
\beta
β的值并判断其是否满足上述条件即可
算法代码
// 二维图像上的一个三角形
struct Triangle {
Point a,b,c,center;
double r;
Triangle(Point p1, Point p2, Point p3, int mode = 0) {
// 计算外接圆半径(利用向量法求外接圆圆心和半径)
if(mode == 1) {
double A = pow(p1.x, 2) + pow(p1.y, 2);
double B = pow(p2.x, 2) + pow(p2.y, 2);
double C = pow(p3.x, 2) + pow(p3.y, 2);
double G = (p3.y-p2.y) * p1.x + (p1.y-p3.y) * p2.x + (p2.y-p1.y) * p3.x;
center.x = ((B-C) * p1.y + (C-A) * p2.y + (A-B) * p3.y) / (2*G);
center.y = ((C-B) * p1.x + (A-C) * p2.x + (B-A) * p3.x) / (2*G);
r = sqrt(pow(p1.x-center.x, 2) + pow(p1.y-center.y, 2));
}
else {
center.x = 0;
center.y = 0;
r = 0;
}
a.x = p1.x;
a.y = p1.y;
b.x = p2.x;
b.y = p2.y;
c.x = p3.x;
c.y = p3.y;
}
};
// 二维图像上的一个点
class Point{
public:
double x, y;
Point(double a, double b) {
x = a;
y = b;
}
Point(){
x = 0;
y = 0;
}
bool operator==(const Point& other) {
return x == other.x && y == other.y;
}
};
// 传入一个三角形和一个点,返回点是否在三角形内
bool checkPointInTriangle(Triangle& t, Point& p) {
Point v0(t.c.x-t.a.x, t.c.y-t.a.y),
v1(t.b.x-t.a.x, t.b.y-t.a.y),
v2(p.x-t.a.x, p.y-t.a.y);
double u, v;
u = (dot(v1,v1)*dot(v2,v0)-dot(v1,v0)*dot(v2, v1)) / (dot(v0, v0)*dot(v1,v1)-dot(v0,v1)*dot(v1,v0));
v = (dot(v0,v0)*dot(v2,v1)-dot(v0,v1)*dot(v2, v0)) / (dot(v0, v0)*dot(v1,v1)-dot(v0,v1)*dot(v1,v0));
return u >= 0 && v >= 0 && u + v <= 1;
}
// 向量点乘
double dot(Point& a, Point& b) {
return a.x*b.x+a.y*b.y;
}