Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 计算直线是否与凸多边形相交的渐近最优算法_Algorithm_Line_Computational Geometry_Asymptotic Complexity_Convex Polygon - Fatal编程技术网

Algorithm 计算直线是否与凸多边形相交的渐近最优算法

Algorithm 计算直线是否与凸多边形相交的渐近最优算法,algorithm,line,computational-geometry,asymptotic-complexity,convex-polygon,Algorithm,Line,Computational Geometry,Asymptotic Complexity,Convex Polygon,检测直线是否与凸多边形相交的O(n)算法包括检查多边形的任何边是否与直线相交,并查看相交数是奇数还是偶数 是否有一种渐进更快的算法,例如O(logn)1?边界框可能被证明是有用的 回想一下,仿射空间的凸面部分是其所有包络超平面的交点:您可以通过仅考虑包络超平面子集的交点来获得多边形的近似值(请阅读“边界凸面多边形”),测试直线与该近似值的交点,并在必要时进行细化 如果您希望交叉口数量较少,则所有这些都会更好。您只需找到一个位于直线左侧的点a和另一个位于右侧的点。剩下的问题是如何快速找到这些点。从

检测直线是否与凸多边形相交的O(n)算法包括检查多边形的任何边是否与直线相交,并查看相交数是奇数还是偶数


是否有一种渐进更快的算法,例如O(logn)1?

边界框可能被证明是有用的

回想一下,仿射空间的凸面部分是其所有包络超平面的交点:您可以通过仅考虑包络超平面子集的交点来获得多边形的近似值(请阅读“边界凸面多边形”),测试直线与该近似值的交点,并在必要时进行细化


如果您希望交叉口数量较少,则所有这些都会更好。

您只需找到一个位于直线左侧的点a和另一个位于右侧的点。剩下的问题是如何快速找到这些点。

从凸多边形中随机选取两点a和B

  • 如果它们位于直线的另一侧,则它们相交
  • 如果它们在同一侧,则在两个多边形部分(如顺时针AB和BA)上执行:
    • 创建一条与穿过a的线l平行的线
    • 在多边形上找到距l最大距离处的点,这与在函数中找到最大值相同,该函数先单调非减,然后单调非增。这可以通过三元搜索在O(logn)中完成

如果这两个最远的点位于直线的另一侧,则直线与多边形相交,否则不相交


顺便说一句,你也可以在O(logn)中找到实际的交点。
lhf的答案几乎是正确的。这是一个版本,可以解决他的问题

让多边形具有逆时针顺序的顶点v0、v1、…、vn。让点x0和x1在直线上

注意两件事:首先,可以在恒定时间内找到两条线的交点(并确定其存在性)。第二,确定一个点是在直线的左侧还是右侧可以在固定时间内完成

我们将遵循lhf的相同基本思想得到一个O(logn)算法。基本情况是当多边形有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(logn)的运行时。

我认为给出了一个清晰的O(logn)解决方案。在垂直于给定直线的方向上找出极值。

该算法无效。1) 顶点AB和BA的序列可能对三元搜索无效。2) 在这些多段线上具有与l的最大距离的点并不保证这些点位于所研究线的对边上。即使当直线穿过多边形时,距离也不应为绝对距离(因此一侧为负,另一侧为正),或者对于一侧,l穿过A,另一侧穿过B。非绝对距离会有所帮助,但并非所有情况下都如此。看见CW顺序的A->B对于三元搜索无效,因为它是递增、递减和最终递增的。@创建一条与经过A的线l平行的线:如果B在这条线上,则此算法失败…@pouncep:不,这不是问题。请澄清多边形的左/右半部分是什么。假设顺序为CCW,使用术语v0->vk或vk->v0可能更好。每次我说左/右半部分我都会澄清,我列出了那半部分的顶点。具体来说,左半部分是不在直线(v0,v(n/2)),{v0,v1,…,v(n/2)}右侧的顶点。我使用术语“不在右边”,因为它是直线左边的顶点集加上直线上的顶点集。+1,直到我找到一个相反的例子。注:我认为澄清是错误的。按逆时针顺序,右半部分为v0->v(n/2)。如何选择x0和x1?我的意思是,如果我们选择x0和x1在多边形之外,那么相交