一旦获得平面方程,就能够进行射线/多边形的交点。在计算射线/平面交叉后,下一步是肯定交点是否在多边形内。算法
有许多不一样的方法能够解决这个问题。Berlin[1]很好地概述了一些技术。这里给出的方法是在[14]中提出的“射线相交”算法的一个修改版本。该算法的工做原理是,从交点处向任意方向发射一束射线,并计算相交的线段数。若是交叉的数目是奇数,则点在多边形内;其余外。这就是所谓的Jordan曲线定理。图6描述了这个定理的用法。下面提出的改进算法优雅地处理了测试光线与多边形顶点相交的特殊状况。这是我本身的发明,彷佛是一个最佳的解决方案。测试
以点集定义定义多边形:spa
定义平面:3d
定义平面的法线(非必要法线):blog
平面与光线的交点:class
第一步是将多边形投射到二维平面上。在这个平面中,全部的点都由一对(U,V)指定。因此,咱们想要的是每一个[X Y Z]坐标都对应一个(U,V)。原理
一种方法是将平面绕一些轴旋转,直到法线与其余轴平行(好比Z)。在这以后,剩下的两个轴(在这个例子中是X和Y)能够用来生成(U,V)对。该方案的缺点是必须为每一个多边形生成和存储一个旋转矩阵,而且必须为每一个坐标执行一个矩阵乘法。方法
这些成本能够经过简单地丢弃[X Y Z]其中一个坐标并使用另外两个来消除。这个动做将多边形投射到由两个选定的坐标定义的平面上。多边形的面积没有保留,可是拓扑结构保持不变。选择扔掉哪一个坐标的定义以下:扔掉绝对值最大的坐标。例如,对于一个Pn=[0 -5 3]的多边形,Y坐标会被丢弃,X和Z被分配给U和V (U和V是任意的)。咱们将用最大的坐标做为主导坐标。im
一旦多边形被投射到平面上,内外测试就至关简单了。平移多边形使交点在原点,即从每一个顶点减去交点的坐标(Ui Vi)。将这些新顶点标记为(U',V')。如今想象一条光线从原点出发沿着+U轴运动。对多边形的每条边进行相交测试。若是边缘穿过光线,记录下来。若是相交的总数是奇数,则点在多边形内。这个操做如图7所示。技术
正如Berlin[1]所指出的那样,在光线上的顶点必须做为特殊的状况来处理。这些特殊状况能够经过定义它们的方式来避免。沿着+U'轴延伸的光线将平面分红两部分。然而,也有一些点在U轴上。必须对位于光线上的顶点(即V' = 0)添加声明,定义其位于+ V'端。这样光线上就没有点了,特殊状况就消失了。光线自己必须被从新定义为无限接近原始光线,但不能经过任何点。它如今是一条分界线,而不是一系列的点。
算法的第一次测试(D4)检查两顶点的v是否符号不一样。若是符号相同,则能够忽略(由于v符号相同则不会与u交叉)。若是两U都大于0,那么+U'轴必然与其交叉(D5)。不然,若是端点中的任何一个U>0(D6),则必须找到边与U'轴相交的准确U'位置(即此直线与U+的截距)。若是(D7)这个截距为正(即在+U'轴上),那么这条边确实与+U'相交。
该方法比较高效,由于大多数边缘能够被平凡地拒绝或接受。 只有当边缘从对角象限延伸时才须要进行严格的计算。
这个和其余内-外部测试算法的一个小问题是,在边缘上的相交点被任意地决定在内部或外部。这个问题是有解决办法的,可是在实践中,边缘上的交点大可能是不相关的。这是由于,若是一个交点落在两个多边形之间的边缘上,而且两个多边形都投影在同一个平面上,那么算法就会肯定这个点在一个多边形内,而且只在其中一个多边形内(不考虑精度偏差).
在图6中,五角星的中心五边形不被考虑在恒星内部,由于交叉的数量是偶数。多边形的另外一个定义是将这些点考虑到多边形内部。
要对这类多边形进行内外测试,须要对以前的算法作一个简单的修改。改变的是当+U'轴的边从+V'传递到-V'时增长NC,从-V'传递到+V'时减小NC。若是NC是0,点在多边形外面,不然它在多边形里面。
数字NC被称为圈数。想象这个多边形是由绳子构成的,一个铅笔点被放在交点上。若是弦被拉紧,圈数就是弦绕点的次数。NC的符号是旋转的方向:‘+’是顺时针,‘-’是逆时针。