设三角形的三个顶点分别为ABC,需要判断的点为P。这里有几种方法来进行判断:
方法1:用面积来判断。
点P与三角形三边的组成个了三个三角形:PAB,PAC,PBC。判断它们的面积之和是否与ABC的面积相等。如果相等则需要判断的点在三角形区域内部,否则就在三角形区域外部。
方法2:用角度来判断。
角APB,BPC,CPA之和是否等于360度,如果等于则需要判断的点在三角形区域内部,否则就在三角形区域外部。
方法3:用向量积来判断。
沿 △ABC 各有向边按一定方向走(顺时针或逆时针),判断点 P 是否在该边的某侧(右侧或左侧),若点 P 在三条边的同侧,则点 P 在 △ABC 内。沿 △ABC 各有向边按一定方向走(顺时针或逆时针),判断点 P 是否在该边的某侧(右侧或左侧),若点 P 在三条边的同侧,则点 P 在 △ABC 内。
方法1较直观,实现起来也比较容易,其中核心问题就是求三角形的面积。最简单的方法就是直接利用空间三角形三点的坐标利用向量的方法求解。三角形面积解决了判断交点是否在某个三角形区域内部的问题也就迎刃而解了。
用方法1来求三角形面积如下:
我们设三角形的三个顶点为A(x0,y0,z0),B(x1,y1,z1),C(x2,y2,z2)。我们将三角形的两条边AB和AC看成是向量。然后,我们以A为原点,进行坐标平移,得到向量AB(x1-x0,y1-y0,z1-z0),向量AC(x2-x0,y2-y0,z2-z0)。
在三维的情况下,直接代入公式,可得向量B和向量C叉乘结果为:
| i jk|
B x C= | x1-x0 y1-y0 z1-z0 |
| x2-x0 y2-y0z2-z0 |
= ((y1-y0)*(z2-z0) - (y2-y0)*z1- z0), (x2-x0)*(z1-z0) - (x1-x0)*(z2-z0), (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0))
它的模一半即为所要求的三角形面积S。
计算三角形面积代码实现如下:
float triangleArea(Point *PointA,Point*PointB,Point*PointC)
{
//已知三角形三点坐标ABC, 可求的向量AB 和向量AC
//向量AB 叉乘向量AC 得到向量AP
//则向量AP的模的一半即为三角形ABC的面积
PointAB; //向量AB
PointAC; //向量AC
PointAP; //向量AP
float m = 0.0; //向量AP的模
float area = 0.0; //三角形的面积
//计算向量AB
AB.x =PointB->x -PointA->x;
AB.y =PointB->y -PointA->y;
AB.z =PointB->z -PointA->z;
//计算向量AC
AC.x =PointC->x -PointA->x;
AC.y =PointC->y -PointA->y;
AC.z =PointC->z -PointA->z;
//计算向量AP
// i, j, k
// AB x1, y1, z1
// AC x2, y2, z2
// AP y1*z2 - y2*z1, x2*z1 - x1*z2, x1*y2 - x2*y1
AP.x = AB.y*AC.z - AC.y*AB.z;
AP.y = AC.x*AB.z - AB.x*AC.z;
AP.z = AB.x*AC.y - AC.x*AB.y;
//计算向量AP的模
m = sqrt(AP.x*AP.x + AP.y*AP.y + AP.x*AP.z);
//计算三角形的面积
area = m / 2;
return area;
}
判断空间中一个点是否在一个三角形区域内部: tA, tB, tC为三角形三个顶点 tP为欲判断点
bool isInTriangle(Point*tA,Point*tB,Point*tC,Point*tP)
{
float area1 = triangleArea(tA,tB,tC);
float area2 = triangleArea(tP, tB,tC);
float area3 = triangleArea(tA, tP, tC);
float area4 = triangleArea(tA, tB, tP);
//外点分别与三角形两点组成三角形面积和
float areaAll = area2 + area3 + area4;
//如果面积相差小于设定的阀值 则认为相等 面积相等则外点在三角形区域内
if(fabs(areaAll - area1) < area1 / 100.0)
{
//如果在三角形区域内则为有效点
return true;
}
return false;
}