从切割多边形生成新多边形(2D)

时间:2009-11-21 13:16:37

标签: algorithm polygon intersection computational-geometry

我遇到了这个小问题,我解决这个问题的算法并不适用于所有情况。有人知道如何解决这个问题吗?

以下是一个示例多边形:

example http://img148.imageshack.us/img148/8804/poly.png

形式描述

我们有一个CW顺序列表,用于定义多边形。我们还可以查询点是否是is_cut(p)的切割点,其中p是给定点。现在我们要计算由此“剪切”引起的新多边形。

算法应该这样做:

输入:{a, c1, b, c4, c, c5, d, c6, e, c3, f, c2}

输出:{a, c1, c2}{b, c4, c3, f, c2, c1}{d, c6, c5}{e, c3, c4, c, c5, c6}

这是我目前的算法:

follow your points, CW
if the point is a cut point
-> go back trough the list looking for cut points
--- if next cut point is connected to the current cut point 
    and not part of the current poly, follow it
--- else keep searching
else
-> continue until you hit your starting point.
that's a poly
do this for every non-cut-point

如果您从cf开始,则此算法无效。

4 个答案:

答案 0 :(得分:5)

首先,您应该计算切割线的哪些线段属于原始多边形的内部。这是一个经典问题,其解决方案很简单。鉴于您的点c1, c2, c3 ... c6按照此顺序排列在一行,则段c1-c2c3-c4等将始终属于多边形内部(*)。

现在我们可以构造用于切割多边形的简单递归算法。给定您的大输入数组{a,c1,b,c4,c,c5,d,c6,e,c3,f,c2},从任何多边形点开始,例如b;将其添加到数组 result 。向前遍历输入数组。如果遇到

  • 通常的多边形节点,将其推送到数组 result
  • ck节点,其中k为奇数,查找c(k+1)并继续从其位置移动。
  • ck节点,其中k甚至,查找c(k-1),跳转到其位置并继续前进。

对于最后两种情况,请按照您遇到的顺序将这些节点添加到 result 数组中。添加ck节点以设置 cut ,并将另一个节点(c(k+1)c(k-1)添加到全局集<中EM> done

如果你必须超越最后一个元素,请转到输入数组中的第一个元素。

迟早你会遇到你正在经历的初始节点。现在,在 result 数组中,您已经切割了多边形。记住它。以递归方式重复该过程,从属于 cut 集的每个节点的位置开始,并且不属于全局 done 集。< / p>

这就是我看到的解决方案。但它是计算几何学,所以它可能会变得比它看起来更复杂。


对于我们的示例,请从b开始:

  1. done={} ,从b开始。首次通过后,您将获得 result=[b,c4,c3,f,c2,c1] cut={c4,c2} done={c3,c1} ;递归到c4c2个节点。
  2. done={c3;c1} ,从c4开始(从1递归)。完成此过程后,您将获得 result=[c4,c,c5,c6,e,c3,c4] cut={c5,c3} done+={c6,c4} ;递归到c5
  3. done={c3;c1;c4;c6} ,从c2开始(从1递归)。完成此过程后,您将获得 result=[c2,a,c1] cut={c1} done+={c2} ;请勿递归到c1,因为它位于 done 集中;
  4. done={c3;c1;c4;c6;c2} ,从c5开始(从2递归)。完成此过程后,您将获得 result=[c5,d,c6] cut={c5} done+={c6} ;请勿递归到c5,因为它位于 done 集中;
  5. Voila - 你得到了你需要的4个多边形。


    (*)请注意,它需要更多的“数学”表示。例如,如果其中一个多边形顶点在线上,则顶点应该加倍,即如果c点更靠近右侧并且在红线上,则该线将具有{{1}它上面有点,多边形数组是[c1, c2, c3, c, c, c6]

    有时(不在此示例中),可能会导致剪切“空”多边形,例如[a, c1, b, c, c, c, d, c6, e, c3, f, c2]。如果您不需要它们,可以在后期消除它们。无论如何,它是具有大量边界情况的计算几何。我不能将它们全部包含在一个答案中......

答案 1 :(得分:3)

你可以应用Weiler Atherton剪辑(实际上是Pavel的建议),但是有一个很大的警告。

由于浮点误差,W / A裁剪算法非常难以正常工作 - 在裁剪线穿过顶点或精确地沿着多边形边缘的情况下,算法可能会变得混乱哪个“路径”围绕它应该遵循的多边形的边界,然后输出不正确的结果。

答案 2 :(得分:0)

1发现每个点都是

选择一个没有切割的pont(例如a)并设置它在左侧(它没有完美)

当你超过切点时,你可以达到变化。所以你找到左/右点。

问题是你还应该考虑点的顺序应该是预先确定的。 (例如顺时针方向)

2从cx的每个中段开始,顺时针和逆时针前进一次。

对于每个多边形,只在一个方向上击中一个方向。

如果你“溢出”c意味着你到达外部多项式。 如果定义位于polgon上的c0和cmax而不是

,则可以解决此问题
input =  {a, c1, c0 ,c1, b, c4, c, c5, d, c6, c7, c6, e, c3, f, c2}

答案 3 :(得分:0)

最简单的实施是Sutherland-Hodgman。它的一个问题是它在线的一侧留下连接多边形的零区域条。在你的例子中,这会给你类似的东西:

  

{a c2 c3 e c6 c5 c c4 c1}和{b c1 c2 f c3 c6 d c5 c4}

如果你能忍受这个或弄清楚如何将它们分解成你想要的部分,那么你会发现实际剪辑的代码将尽可能简单。

实现只需要两个堆栈,并且只需要通过多边形的顶点。在每个顶点,您检查是否已经从前一个顶点开始越过该线。如果是这样,计算交叉点并将其推到其中一个堆栈上。然后将新顶点推到其中一个堆栈上。真的很容易。