【问题标题】:How do I determine if two convex polygons intersect?如何确定两个凸多边形是否相交?
【发布时间】:2010-10-19 16:23:42
【问题描述】:

假设在一个平面上有许多凸多边形,也许是一张地图。这些多边形可以相互碰撞并共享一条边,但不能重叠。

要测试两个多边形 PQ 是否重叠,首先我可以测试 P 中的每条边,看看它是否与任何一个相交Q 中的边。如果找到一个交集,我声明 PQ 相交。如果没有相交,那么我必须测试 P 完全被 Q 包含的情况,反之亦然。接下来是 P==Q 的情况。最后,有些情况共享一些边缘,但不是全部。 (这最后两种情况可能被认为是相同的一般情况,但这可能并不重要。)

我有一个算法可以检测两条线段相交的位置。如果这两个线段是共线的,则出于我的目的,它们不被视为相交。

我是否正确列举了这些案例?对这些案例的测试有什么建议吗?

请注意,我不是要找到作为交叉点的新凸多边形,我只想知道是否存在交叉点。找到交叉点的算法很多,但我不需要费尽心思。

【问题讨论】:

  • 在决定非垂直、非水平线段的共线性时要注意浮点精度问题,如果您选择这样做的话。

标签: geometry polygon convex


【解决方案1】:

您的测试用例应该可以工作,因为您正在检查多边形根本不相交(完全在外部或完全在内部)的情况,以及存在任何形式的部分相交的情况(如果存在边总是相交)是重叠的)。

对于测试,我会确保测试每个可能的组合。我看到的上面缺少的一个是共享的单个边缘,但另一个包含一个多边形。我还会为一些更复杂的多边形添加测试,从三面 -> 多面,作为预防措施。

另外,如果您有一个完全包围多边形但不重叠的 U 形多边形,我相信您的情况会处理这个问题,但我也会将其添加为检查。

【讨论】:

  • 谢谢。我确实用复杂的形状进行测试,而不是我在这里绘制的矩形。它们只是更容易绘制。不过,我所有的多边形都是凸的,所以我没有任何 U 形。
  • 您的算法应该可以正常工作。 MaxVT 引用的算法可能更快,但你的应该可以。它也应该同样容易地处理非凸多边形。
  • 是的,我也喜欢这个算法。我正在测试非常小的形状(四边形和三角形),因此更容易测试每个边缘是否可以成为分离轴。可能也更快。
【解决方案2】:
  • 如果多边形总是凸的,首先计算从多边形中心到中心绘制的线的角度。然后,您就无需在与其他多边形相距 180 度的一半多边形中测试边缘段。

  • 要消除边缘,从左侧的多边形开始。从多边形中心取与前一个子弹的线段垂直的线段,并接触多边形的两侧。将此线段称为 p,顶点为 p1 和 p2。那么,对于所有的顶点,如果x坐标小于p1.x和p2.x,那个顶点就可以进入“安全桶”。

  • 如果不是,您必须检查以确保它位于线的“安全”一侧(也只需检查 y 坐标)

-如果多边形中的一条线段的所有顶点都在“安全桶”中,则可以忽略它。

-反转极性,使第二个多边形“向右”。

【讨论】:

  • 1) 如何以编程方式消除这些边缘? 2) 这是上面说明的第三种情况。
  • 如果重叠量非常高,您的边缘消除方法似乎可能不起作用。
【解决方案3】:

你可以使用this collision algorithm:

为了能够确定两个凸多边形是否相交(相互接触),我们可以使用分离轴定理。本质上:

  • 如果两个凸多边形不相交,则它们之间存在一条线。
  • 只有当其中一个多边形的边之一形成这样的线时,这样的线才存在。

第一句话很简单。由于多边形都是凸面的,因此您可以绘制一条线,其中一个多边形在一侧,另一个多边形在另一侧,除非它们相交。第二个不太直观。看图 1。除非多边形的最近边彼此平行,否则它们彼此最接近的点是一个多边形的角最接近另一个多边形的边的点。然后这一边将形成多边形之间的分离轴。如果边平行,则它们都是分离轴。

那么这具体如何帮助我们确定多边形 A 和 B 是否相交?好吧,我们只是遍历每个多边形的每一边并检查它是否形成了一个分离轴。为此,我们将使用一些基本的向量数学将两个多边形的所有点压缩到一条垂直于潜在分隔线的线上(见图 2)。现在整个问题方便地是一维的。我们可以确定每个多边形的点所在的区域,如果这些区域不重叠,这条线就是一个分隔轴。

如果在检查两个多边形的每条线后,没有找到分离轴,则证明多边形相交并且必须对其进行处理。

【讨论】:

  • 不幸的是,您在回答中引用的网站现已关闭;您可能想要更改链接或将其从您的答案中删除。
  • 幸运的是,该页面已被 Wayback Machine 保存。如果此答案对您有所帮助,请向互联网档案馆捐款。
  • 在检查边 E 是否形成分隔线时,垂直/投影部分可以替换为矢量积(二维行列式)计算,这更容易 IMO:多边形A位于E的同一侧(即行列式的相同符号),多边形B的所有顶点位于E的另一侧。(行列式的另一个符号)。
  • “除非多边形的最近边彼此平行,否则它们彼此最接近的点是一个多边形的角最接近另一个多边形的边的点” ——这是不正确的。 A 中的一个点和 B 中的一个点对彼此最近,可能是两个角点。
【解决方案4】:

由于 altCognito 已经为您提供了解决方案,我只会指出您可能感兴趣的 an excellent book on computational geometry

【讨论】:

  • 谢谢,我在搜索中遇到了这个问题,我正在考虑购买它。我已经借了另一个补偿。几何。其他程序员的书。
【解决方案5】:

这是一个想法:

  • 找到每个多边形的中心点

  • 找到每个多边形中最靠近另一个多边形中心点的两个点。它们将是凸多边形中的相邻点。这些定义了每个多边形的最近边,我们称点 {A, B} 和 {Y, Z}

  • 找到线 AB 和 YZ 的交点。如果线段相交(AB 上的交点位于 A 和 B 之间),则您的多边形相交。如果 AB 和 XY 平行,忽略这个条件,下一步就会陷入这个问题。

  • 您还需要检查另一种情况,即多边形相交的程度足够大,以至于 AB 和 XY 完全相互超越并且实际上并不相交。 要捕获这种情况,请计算 AB 和 XY 到每个多边形中心点的垂直距离。如果任一中心点更靠近对面多边形的线段,则您的多边形会严重重叠。

【讨论】:

  • 我否决了这个答案,因为第二个项目符号不正确,根据以下使用两个凸四边形的具体示例: Quad #1: {-50, 3} {0, 4} {50 , 3} {0, 2};四边形 #2:{-1, -1} {-1, 1} {1, 1} {1, -1}。 Quad #2 的中心是原点,最近的两个点分别是 {0, 2} 和​​ {0, 4},它们不是 Quad #1 中的相邻点。
【解决方案6】:

【讨论】:

  • 它提供了比您需要的更多信息(两个 N 维凸多面体的最小距离,而不仅仅是该距离是否为 0(碰撞)),但没有显着的性能开销这样做。 MollyRocket 链接有一个很好的直观解释。
  • 这个答案引用了很多信息,但您确实应该将每个链接分成单独的句子或至少使用项目符号列表。
【解决方案7】:

有几种方法可以检测凸多边形之间的交集和/或包含。这完全取决于您希望算法的效率如何。考虑分别具有 r 和 b 个顶点的两个凸多边形 R 和 B:

  1. Sweep line 基于算法。正如您所提到的,您可以执行扫描线程序并保持多边形与扫描线相交所产生的间隔。如果在任何时候间隔重叠,则多边形相交。复杂度是 O((r + b) log (r + b)) 时间。
  2. Rotating Callipers 基于算法。有关详细信息,请参阅 herehere。复杂度为 O(r + b) 时间。
  3. 可以找到最有效的方法herehere。这些算法需要 O(log r + log b) 时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    • 2012-10-17
    • 2011-04-06
    • 2012-02-02
    • 1970-01-01
    • 2017-03-17
    • 2010-12-04
    相关资源
    最近更新 更多