假设平面上有许多凸多边形,也许是地图。这些多边形可以相互碰撞并共享边缘,但不能重叠。
要测试两个多边形 P 和 Q 是否重叠,首先我可以测试 P 中的每个边缘,看它是否与任何一个相交 Q 中的边缘。如果找到了交叉点,我声明 P 和 Q 相交。如果没有相交,那么我必须测试 P 完全由 Q 包含的情况,反之亦然。接下来是 P == Q 的情况。最后,情况是共享一些边缘,但不是全部。 (最后两种情况可能被认为是相同的一般情况,但这可能并不重要。)
我有一个算法可以检测两个线段相交的位置。如果这两个段是共线的,则不会认为它们与我的目的相交。
我是否正确列举了案件?有关测试这些案例的建议吗?
请注意,我不打算找到交叉的新凸多边形,我只想知道交叉是否存在。有许多记录良好的算法可以找到交集,但我不需要经过所有的努力。
答案 0 :(得分:25)
您可以使用this collision algorithm:
为了能够确定两个凸多边形是否相交(相互接触),我们可以使用分离轴定理。基本上:
- 如果两个凸多边形不相交,则存在一条在它们之间穿过的线。
- 只有当其中一个多边形的一边形成这样的直线时,才存在这样的直线。
第一个陈述很简单。由于多边形都是凸面的,因此除非它们相交,否则您将能够在一侧绘制一条多边形线而在另一侧绘制另一条多边形。第二个稍微不那么直观。请看图1.除非多边形的最近边彼此平行,否则它们彼此最接近的点是一个多边形的一个角最接近另一个多边形的一侧的点。然后,该侧将在多边形之间形成分离轴。如果两边是平行的,它们都是分离轴。
那么具体如何帮助我们决定多边形A和B是否相交?好吧,我们只是越过每个多边形的每一边,检查它是否形成一个分离轴。为此,我们将使用一些基本的矢量数学将两个多边形的所有点压缩到垂直于潜在分离线的直线上(见图2)。现在整个问题很方便一维。我们可以确定每个多边形的点所在的区域,如果这些区域不重叠,则该线是分离轴。
如果在检查两个多边形的每条线后,没有找到分离轴,则已经证明多边形相交并且必须对其进行某些操作。
答案 1 :(得分:4)
如果多边形总是凸的,首先计算从多边形的中心到中心绘制的线的角度。然后,您可以消除需要测试多边形的一半边缘的边缘线段与其他多边形相差180度。
消除边缘,从左边的多边形开始。从多边形中心垂直于前一个项目符号的线段获取线段,并触摸多边形的两侧。使用顶点p1和p2调用此线段p。然后,对于所有顶点,如果x坐标小于p1.x和p2.x那个顶点可以进入“安全桶”。
如果没有,你必须检查以确保它在线的“安全”一侧(只检查y坐标)
- 如果多边形中的线段具有“安全存储桶”中的所有顶点,则可以忽略它。
- 反转极性,使你对第二个多边形“正确”。
答案 2 :(得分:1)
您的测试用例应该可以工作,因为您正在检查多边形根本不相交(完全在外部或完全在内部)的情况,以及存在任何形式的部分交叉的情况(边缘总是在那里相交重叠)。
对于测试,我会确保测试每个可能的组合。从我看到的上面缺少的是单边共享,但另一边包含一个多边形。我还会为一些更复杂的多边形形状添加测试,从三 - >多方面,只是作为预防措施。
另外,如果你有一个U形聚合物完全围绕聚合物,但没有重叠,我相信你的情况会处理,但我会添加它作为支票。
答案 3 :(得分:1)
由于altCognito已经为您提供了解决方案,因此我只会指出您可能感兴趣的an excellent book on computational geometry。
答案 4 :(得分:1)
这是一个想法:
找到每个多边形的中心点
找到最靠近另一个中心点的每个多边形的两个点。它们将是凸多边形中的相邻点。这些定义了每个多边形的最近边缘,让我们调用点{A,B}和{Y,Z}
找到AB和YZ的交点。如果线段交叉(AB上的交点位于A和B之间),则多边形相交。如果AB和XY平行,则忽略此条件,下一步将捕获问题。
还需要检查一个案例,即当多边形交叉得足够大以致AB和XY完全相互过去并且实际上不相交时。 为了捕获这种情况,计算AB和XY到每个多边形中心点的垂直距离。如果任一中心点更接近相反多边形的线段,则多边形会重叠。
答案 5 :(得分:1)
答案 6 :(得分:0)
有多种方法可以检测凸多边形之间的交叉和/或遏制。这一切都取决于您希望算法的效率。考虑两个凸多边形R和B分别具有r和b顶点: