(出于我的目的,“多边形”不包括自相交的多边形或带孔的多边形-只是简单的(凹形或凸形)多边形。)
针对此问题,我发现了各种建议,这些建议主要基于以下方面:
如果Polygon1的边缘与Polygon2的边缘之间没有交集,并且Polygon2的至少一个顶点位于Polygon1的“内部”,则Polygon1包含Polygon2。
(例如,查看接受的答案here)
但是,细节在于魔鬼:
Polygon1的“内部”是否包含“ Polygon1的边缘”?显然 必须,否则在图F中(请参见下面的图像)Polygon2(红色)将没有 顶点“内部” Polygon1(蓝色),因此在上述测试失败时 它应该通过。
两个边缘的“相交”是否在一个边缘的末尾包含一个点 边缘(即一个顶点)?如果“是”,则下面的图A和E 有交叉路口,因此应该通过测试时未通过测试。但 如果为“否”,则图B,C和D没有交点,因此通过 他们何时应该失败的测试。
(NB图A,B和C在Polygon1的边缘上具有Polygon2的顶点,图D和E则相反)
我无法确定要正确区分这些不同情况的测试条件。我会为任何指示而感激吗?
答案 0 :(得分:3)
如果我们要检查多边形B是否在多边形A内:
就像您链接的答案中提到的那样,开始对每条边(每个多边形中的一条边)执行line intersection test。如果任何边相交(不包括位于边和公共顶点上的顶点),则B不在A内。
如果一个多边形的顶点V位于另一个多边形的边缘上,则将该边缘视为2条边缘,并将该顶点V作为该多边形的新顶点。
现在我们只需要考虑共同的顶点。
对于每个公共顶点V:
使用它来确定哪些边缘相邻。
如果EB1和EB2不相邻,则B不在A内。
如果EB2位于A上(也就是说,EB2位于EA2上,即它们具有相等的梯度),我们尚不知道B是否在A中。
在这种情况下,我们需要跟踪EB1在哪一侧,然后移至相邻的顶点VB(EB2的另一个顶点),并检查EB3(在EB2之后的边缘)是否在同一侧侧为EB1。如果它们在另一侧,则B不在A内。
如果EB3也在A上,我们需要检查EB4,依此类推,直到找到一个不是的EB4。
如果两个EB1都在EA1上,而EB2都在EA2上,则我们需要朝两个方向移动以确定我们需要在哪一侧。如果B的所有边都位于A上,则A等于B。
(注意:例如,如果EB2位于EA1而不是EA2上,则可以简单地重命名它们来满足上述条件)
所有这些都是在假设我们不允许与自身相交的多边形-允许这样做可能会破坏这一点。
这里可能有一些重要的细节,但这应该是一个不错的起点。
答案 1 :(得分:2)
扫掠线算法(几乎总是如此)为我们提供了最可靠,最有效的解决方案。
最简单的形式是,扫掠线找到所有线段的交点。对其进行扩展以检查多边形是否包含内容是微不足道的。您只需跟踪哪些线或点属于每个多边形。在算法的任何步骤中,扫掠线与每个多边形内部的交点都是垂直段的有限集合。您有以下情况:
这可以处理所有边缘情况。如果要将案例A,E和F归类为“内部”,则仅测试线段内部的交集(即线段(0,1)和(1,2)不相交,并且(0,1)在线段内部) (0,2))。否则,只需将上述情况视为适当的交集即可。
如果在某个步骤中有两个边缘是共线的并且平行于扫掠线并且它们相交,那么可能很难决定。但是,所有边缘情况都可以通过以下方法解决:通过计算扫掠线与多边形的交点,而不是在顶点处(与扫掠线算法一样),而不是在顶点之间(例如,在当前顶点与下一个顶点之间的中点)。这样,只考虑多边形内部(而不是边界)。
实际上,该算法将我们的多边形分解为一堆小梯形,夹在通过每个顶点绘制的平行(例如垂直)线之间。检查这些梯形是否相交,不相交或完全包含彼此很容易。可以找到插图here。
编辑:澄清了一些措辞。 编辑2:找到了一个极端情况;)
答案 2 :(得分:0)
我们可以遍历O(|EA| + |EB|)
中的边缘并播放“ catch:”,同时一个多边形的当前边缘在至少一个维度上延伸超过另一个多边形的边缘,然后沿着另一个多边形的下一个边缘移动多边形,然后再次切换。断言围堵,我们可以通过监视相交来判断围边以及边的哪一侧在其多边形内。
答案 3 :(得分:0)
非常感谢您的答复,尤其是对@Dukeling和@ n.m的答复。
我已经实现(在Python中)@ n.m提出的扫掠线解决方案。并将其发布在这里,以防其他人发现它有用。 (我发现比Dukeling的解决方案更容易编写代码。)在我的用例中,我知道哪个将包含多边形(如果有的话),因此不需要进行双向测试。
我已经用二十多个测试用例对其进行了测试,包括上图中的所有用例,以及它们在y = x中的反映。 但是,如果有人发现实施无法正常工作的任何极端情况,或者对代码效率进行了任何改进,都欢迎提出评论。
修改:
我删除了代码,因为我发现许多情况下它不起作用。最后,我寻求了一个更全面的解决方案,该解决方案给出了两个多边形A和B确定A是否包含B,A是否在B内部,A和B重叠或A和B不相交。
为了加快处理速度,它首先查看了边界框,这消除了一些可能性,然后,如果边界框相等,则它查看区域,然后再执行扫掠线算法。
代码很长,因此我不在这里包括它,但是如果有人感兴趣,您可以在https://github.com/andy31lewis/brySVG处将其视为positionRelativeTo
的{{1}}方法。已通过数百个测试用例进行了测试,并且看起来相当可靠。