用于创建封闭区域的多边形的算法

时间:2013-12-21 16:22:38

标签: algorithm language-agnostic geometry polygon nodebox

我在随机位置有多个圆圈(作为连接顶点的列表)。

当圆相交时,会创建封闭区域(就像在维恩图http://en.wikipedia.org/wiki/Venn_diagram中一样)

如何生成所有这些区域的单独多边形?目标是能够使用单独的多边形为每个区域着色,如下例所示:

enter image description here

enter image description here

迭代布尔交叉运算是否可以得到通用解?

修改

以下简单剪辑是一个绘制相交椭圆的[NodeBox](http://nodebox.net/code/index.php/Home)脚本。

oval(x0,y0,w,h)创建一个椭圆。

根据doc,像p[19].difference(p[17])这样的路径上的布尔运算会产生“平坦”结果(“由许多直线段组成”)。

可以添加或更改路径的坐标。

size(500, 500)

p = []
s = 54
nofill()
stroke(0)
for k in xrange(10):
    w  = 10+k*s/2
    w2 = 10+k*s 
    h = 10+k*s
    h2= 10+k*s
    p.append( oval(WIDTH/2 - w/2, HEIGHT/2 - h/2, w,  h, draw=False))
    p.append( oval(WIDTH/2 - w2/2, HEIGHT/2 - h2/2, w2, h2, draw=False))


cp = p[19].difference(p[17]).intersect(p[18], flatness = 0.3)

for pi in p:
    drawpath(pi)

fill(color(1,0,0))
drawpath(cp)    

1 个答案:

答案 0 :(得分:3)

你说语言不可知,所以我会这样回答。您可以按照建议在多边形上使用布尔运算获得所需的结果。如果F是一组非相交的多边形而P是一个与F中的一个或多个重叠的新多边形,那么,你想要这样做:

Let p = P
for each polygon f in F
  Replace f by f-p and intersect(f, p).
  Set p = p-f
end
add p to F

这个想法是使用新的多边形p将F中现有的“平面”多边形分割为与p共享的部分而不与p共享,然后从p本身移除与原始多边形的重叠并继续。当你这样做时,p的左边是与F中的任何东西都没有重叠的部分,所以我们将它作为一个新的多边形添加到F中。

因此,要处理随机的圆形多边形集合,首先要使用包含其中一个圆形多边形的F(这当然是一个扁平集合!),然后一次添加一个,直到完成为止。

实际上,这比定制算法效率低得多。处理这类问题的标准方法是sweep line技术。想象一下在圆圈上从左到右横扫的垂直线。当它“触摸”一个圆圈时,它开始构建一个多边形。当它接触交叉点时,一个多边形关闭,两个继续,并且打开一个新的多边形(在一般情况下)。当它到达圆的最高点时,关联的多边形将关闭。从扫描线移除“闭合”多边形并将其添加到输出列表中。扫描线算法在概念上并不困难,但实现很繁琐,特殊情况比比皆是(特别是对于与扫描器平行的线以及当一个多边形的顶点位于另一个多边形的边缘时,尽管用于解决这些问题的一般技术是{{3 }})。

“广义排列”是用于描述这样的问题的计算几何术语。广义布置是线,线段和/或多边形的集合(正常布置仅是线组)。例如,simulation of simplicity可以高效地完成您的问题。 CGAL是C ++中的一个大型通用库,因此有一些学习成本。商业用途许可很棘手。