判断点在一个面域的内部
前言
作者在学习工作中,经常需要和几何相关内容打交道,因此分享自己在编程过程中遇到的一些问题和解决方法,也十分欢迎各位私信与我交流,另外如有不懂得地方也可以找我,在下会积极回复。
问题分析
通常来说,人眼能一眼就看出一个点是否处于面内,但是如何让计算机知道呢?
奇偶判断法
通过待判断点向任意方向发射一条射线,射线与面域相交的交点个数若为奇数,则判断该点在内部,反之则在外部。
相交判断
那么另一个问题来了,如何判断射线和一条直线是否相交呢
1.直线两端点应在射线两侧
如上图,第一步应保证端点a,b分别在射线两侧,而判断点在线的方位,常用叉积的办法。这可以通过分别计算向量a、b与射线方向向量的叉积,若两叉积异号则证明在两侧。
2.一条向量与射线向量在另一向量的同侧
通过第一步操作,我们能把射线区域限定在上述斜线区域,但是明显能观察到,只有在绿色区域才会与直线相交,因此我们需要继续增加约束,排除棕色区域。
例如上图绿色区域,向量b和射线向量都在向量a的下侧。
代码实现
C#
public static bool IsInterected(Point origin,Vector rayDirection,Line line)
{
Point pointA = Line.FirstPoint;
Point pointB = Line.LastPoint;
//计算向量a,b
Vector vectorA = pointA - origin;
Vector vectorB = pointB - origin;
//判断两端点在射线两侧
double crossValueA = vectorA.crossProduct(rayDirection).Z;
double crossValueB = vectorB.crossProduct(rayDirection).Z;
if(crossValueA*crossValueB>0)
return false;
//判断B向量与射线向量是否在A向量的同侧
double crossValueAB = vectorA.crossProduct(vectorB).Z;
if(crossValueA*crossValueAB<0)
return false;
return true;
}
public static bool IsPointIn(Line[] face,Point point)
{
//任取一个射线方向向量
Vector rayDir = new Vector(1,1.21,0);
//记录交点个数
int intersectCount = 0;
foreach(var item in face)
{
if(IsInterected)
intersectCount++;
}
//奇偶判断
if(intersectCount%2==0)
return false;
return true;
}