一种检测直线与凸多边形是否相交的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}。边界框可能会很有用。
回想一下,仿射空间的凸部分是所有包络超平面的交集:您可以通过仅考虑包络超平面子集的交集来获得多边形的近似(称为“边界凸多边形”),测试您的线与此近似的交点,并在必要时进行细化。
如果您预计交点数量较少,则所有这些都能更好地发挥作用。
你只需要找到一点A在这条线的左侧,另一个点在右侧。剩下的问题是如何快速找到这些点。
从凸多边形中随机选取两个点A和B。
如果这两个最远的点在您的直线的不同侧,则直线与多边形相交,否则不相交。
顺便说一句,您也可以在O(log n)的时间复杂度内找到实际的交点。