检测一条线是否与凸多边形相交的 O(n) 算法包括检查多边形的任何边缘是否与该线相交,并查看相交的数量是奇数还是偶数。
是否有渐近更快的算法,例如 O(log n) 算法?
检测一条线是否与凸多边形相交的 O(n) 算法包括检查多边形的任何边缘是否与该线相交,并查看相交的数量是奇数还是偶数。
是否有渐近更快的算法,例如 O(log n) 算法?
lhf 的答案接近正确。这是一个可以解决他的问题的版本。
让多边形按逆时针顺序有顶点 v0, v1, ..., vn。让点 x0 和 x1 在直线上。
注意两件事:首先,找到两条线的交点(并确定它的存在)可以在恒定时间内完成。其次,确定一个点是在一条线的左边还是右边可以在恒定时间内完成。
我们将遵循 lhf 的相同基本思想来获得 O(log n) 算法。基本情况是多边形有 2 个或 3 个顶点。这些都可以在恒定时间内处理。
确定直线 (v0,v(n/2)) 是否与直线 (x0,x1) 相交。
情况1:它们不相交。
在这种情况下,我们感兴趣的线位于分割多边形的线的左侧或右侧,因此我们可以递归到多边形的那一半。具体来说,如果 x0 在 (v0,v(n/2)) 的左侧,则右侧“一半”中的所有顶点 {v0, v1, ... v(n/2)} 都在同一侧(x0,x1),所以我们知道多边形的“一半”没有交集。
案例2:它们确实相交。
这种情况有点棘手,但我们仍然可以在恒定时间内将交叉点缩小到多边形的“一半”。有3个子情况:
案例 2.1:交点在点 v0 和 v(n/2) 之间
我们完了。该线与多边形相交。
案例2.2:交点更靠近v0(即在v0一侧的多边形之外)
确定线 (x0,x1) 是否与线 (v0,v1) 相交。
如果没有,那么我们就完成了,这条线不与多边形相交。
如果是,请找到交叉点,p。如果 p 位于线 (v0, v(n/2)) 的右侧,则递归到多边形的右“一半”,{v0, v1, ..., v(n/2)},否则递归向左“一半”{v0, v(n/2), ... vn}。
这种情况下的基本思想是多边形中的所有点都在线的一侧(v0,v1)。如果 (x0, x1) 在与 (v0, v(n/2)) 相交的一侧偏离 (v0, v1)。我们知道在那一侧不能与多边形相交。
案例 2.3:交点更接近 v(n/2)
这种情况的处理与案例 2.2 类似,但使用了 v(n/2) 的适当邻居。
我们完了。对于每个级别,这需要两个线交叉点、左右检查并确定点在线上的位置。每次递归将顶点数除以 2(技术上至少将它们除以 4/3)。所以我们得到了 O(log n) 的运行时间。
我认为这篇文章给出了一个明确的 O(log n) 解决方案。在垂直于给定线的方向上找到极值。
边界框可能被证明是有用的。
回想一下,仿射空间的凸部分是其所有包络超平面的交集:您可以通过仅考虑包络超平面子集的交集来获得多边形的近似值(阅读“边界凸多边形”),测试将您的线与此近似值相交,并在必要时进行细化。
如果您预计交叉路口数量较少,所有这些都会更好。
您只需要找到在线左侧的点 A 和右侧的另一个点。剩下的问题是如何快速找到这些点。
从凸 poligon 中随机取两个点 A 和 B。
如果这两个最远的点在您的线的不同侧,则线与 poligon 相交,否则不会
顺便说一句,您也可以在 O(log n) 中找到实际的交点。