如何确定一个多边形是否完全包含另一个多边形?


9

我有2个多边形。我知道两个多边形的顶点坐标。检查一个是否完全在另一个内部的最佳方法是什么?例如,该算法仅应识别出以下黑色梯形

多边形示例


我现在不能给出详细的答案(可能以后再说),但是您应该看一下用于碰撞检测的分离轴定理的实现。可以对算法进行略微修改,以轻松检查您想要的内容。例如,codezealot.org
archives /

1
您不清楚您对多边形内部的多边形的了解。如果较小的多边形的所有点都在较大的多边形中,但它们的每一边都在一条直线上,那又在彼此之间又会怎样呢?i47.tinypic.com/4i0sgg.jpg
speedyGonzales 2012年

@speedyGonzales,这是内部调用的名称。
user960567 2012年

Answers:


5

有大量的源代码片段可用于执行“ 多边形内点 ” 测试的方法。原理来自约旦的多边形曲线定理(http://www-cgrl.cs.mcgill.ca/~godfried/teaching/cg-projects/97/Octavian/compgeom.html)。

天真的方法是:拥有该方法,将其调用PointInsidePolygon(Point p, Polygon poly)

  bool isInside = true;
  for each (Point p in innerPoly)
  {
    if (!PointInsidePolygon(p, outerPoly))
    {
      isInside = false; // at least one point of the innerPoly is outside the outerPoly
      break;
    }
  }
  if (!isInside) return false;
  // COMPULSORY EDGE INTERSECTION CHECK
  for each (innerEdge in innerPoly)
    for each (outerEdge in outerPoly)
    {
      if (EdgesIntersect(innerEdge, outerEdge))
      {
        isInside = false;
        break;
      }
    }

  return isInside;

从理论上讲,它不应该错过多边形的任何情况,但这不是最佳解决方案。

“ Edge”大小写备注

  • PointInsidePolygon(..) 如果该点在多边形的边界上(位于边缘或为顶点),则必须返回true

  • EdgesIntersect(..)如果innerEdge是的子集(在几何上),则必须返回false outerEdge。在这种情况下,边缘明显相交,但是出于算法目的,我们需要指出相交并没有破坏isInside变量背后的语义

一般建议

  • 如注释中所指出,在没有边缘与边缘相交检查的情况下,该方法可能会为某些凹面多边形(例如,V形四边形和矩形)返回假阳性,该矩形的所有顶点都在V形内,但与之相交,因此至少在某些区域之外)。

  • 在检查一个内部多边形的至少一个顶点在外部一个顶点之后,并且如果没有相交的边缘,则意味着满足了所寻求的条件。


1
当外部多边形为凹面时,这将返回假阳性。
sam hocevar 2012年

2
有趣的是,尽管Teodron和Knight666分别是错误的,但结合使用时,它们应该给出正确的答案。如果多边形的所有点都在另一个内部,并且它们的线不相交,则第一个多边形完全在另一个内部。
Hackworth 2012年

是的,它确实返回了假阳性,还需要考虑边缘相交。
teodron 2012年

这似乎是正确的答案。我认为不需要检查第二个循环条件。
user960567 2012年

这不适用于端点交叉点或边缘重叠。
Brandon Kohn

2

尝试与每条红线进行直线相交。用伪代码:

// loop over polygons
for (int i = 0; i < m_PolygonCount; i++)
{
    bool contained = false;

    for (int j = 0; j < m_Polygon[i].GetLineCount(); j++)
    {
        for (int k = 0; k < m_PolygonContainer.GetLineCount(); k++)
        {
            // if a line of the container polygon intersects with a line of the polygon
            // we know it's not fully contained
            if (m_PolygonContainer.GetLine(k).Intersects(m_Polygon[i].GetLine(j)))
            {
                contained = false;
                break;
            }
        }

        // it only takes one intersection to invalidate the polygon
        if (!contained) { break; }
    }

    // here contained is true if the polygon is fully inside the container
    // and false if it's not
}

但是,如您所见,随着您添加更多的多边形进行检查,该解决方案的速度会变慢。一个不同的解决方案可能是:

  • 将容器多边形渲染到具有白色的像素缓冲区。
  • 将子多边形渲染到具有白色的其他像素缓冲区。
  • 使用XOR掩码在多边形缓冲区上屏蔽容器缓冲区。
  • 计算白色像素的数量;如果大于0,则子多边形未完全包含在容器中。

该解决方案非常快,但是取决于您的实现(以及您要对检查结果进行的处理),哪种解决方案最适合您。


1
线相交不足以发现完全包含的多边形。
Kylotan 2012年

1
问题:如果多边形完全不相交,则没有边相交。在这种情况下能行吗?第二,基于图形的方法确实可以工作!
teodron
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.