检查点是在凸四边形多边形中还是在其上的最有效方法

时间:2012-09-27 20:15:08

标签: testing geometry polygon quad

我正在试图找出最有效/快速的方法来将大量凸四边形(四个给定的x,y点)添加到数组/列表中,然后检查这些四边形是否在一个点内或在那些四边形的边界上。

我最初尝试使用光线投射,但认为这有点矫枉过正,因为我知道我的所有多边形都是四边形,而且它们都是凸面的。

目前,我正在将每个四边形分成两个共享边缘的三角形,然后使用它们的区域检查点是在这两个三角形中的每个三角形上。

例如,

三角形ABC和测试点P. if(areaPAB + areaPAC + areaPBC == areaABC){return true; }

这似乎有点慢,因为我需要计算4个不同三角形的区域来运行检查,如果四边形的第一个三角形返回false,我必须再获得4个区域。 (我在检查中包含一些epsilon以弥补浮点错误)

我希望有一种更快的方法可能涉及对四边形进行一次点检查,而不是将其分成两个三角形。

我试图通过将多边形放入数组[,]来减少检查次数。添加多边形时,它会检查最小和最大x和y值,然后使用这些值,将相同的多边形放置到正确的数组位置。根据可用多边形检查点时,它会从列表数组中检索正确的列表。

我一直在搜索类似的问题,我认为我现在使用的可能是找出一个点是否在三角形中的最快方法,但我希望有一个更好的方法来测试总是凸起的四边形。我查找的每个多边形测试似乎都是针对多边形或不规则形状的多边形进行测试。

感谢您花时间阅读我冗长的问题,这是一个简单的问题。

2 个答案:

答案 0 :(得分:1)

我相信最快的方法是:

1:通过交叉产品符号查找所有向量对(DirectedEdge-CheckedPoint)的相互方向。如果所有四个符号都相同,那么点就在里面

增加:每个边缘

EV[i] = V[i+1] - V[i], where V[] - vertices in order
PV[i] = P - V[i]
Cross[i] = CrossProduct(EV[i], PV[i]) = EV[i].X * PV[i].Y - EV[i].Y * PV[i].X

如果点P相对于第i个边缘(V [i] -V [i + 1])位于左半平面中,则交叉[i]值为正,否则为负。如果所有Cross []值都为正,则点p在四边形内,顶点按逆时针顺序排列。 f所有Cross []值均为负值,则点p位于四边形内,顶点按顺时针顺序排列。如果值具有不同的符号,则点在四边形之外。

如果对于许多点查询,四元组相同,则 dmuir 建议预先计算每条边的均匀线方程。均匀线方程是a * x + b * y + c = 0.(a,b)是边缘的法向量。这个等式具有重要的属性:表达的符号 (a * P.x + b * Y + c)确定半平面,其中P点(对于交叉产品)

2:将四边形分割为2个三角形并对每个三角形使用矢量方法:根据基矢量表示CheckedPoint矢量。

P = a*V1+b*V2
当a,b> = 0并且它们的总和<= 1

时,

点在内部

两种方法都需要大约10-15次加法,6-10次乘法和2-7次比较(我不考虑浮点误差补偿)

答案 1 :(得分:1)

如果你有能力用每个四边形存储每个边缘的等式,那么你可以节省一点时间在MBo的答案上。

例如,如果你有四边形的每个边缘的向内指向法向量N和一个常数d(边缘上的一个顶点p的Np)那么点x就在四边形中如果每个边缘的Nx> = d。这样就可以进行2次乘法,每次加法一次加法和一次比较,并且每个点最多需要执行4次测试。这种技术适用于任何凸多边形。