简体   繁体   中英

Algorithm to create polygons of enclosed areas

I have multiple circles (as list of connected vertices) at random positions.

When the circles intersect, closed areas are created (just like in a venn diagram http://en.wikipedia.org/wiki/Venn_diagram )

How do I generate separate polygons of all of these areas? The goal would be to be able to color every region with a separate polygon like in this example:

在此输入图像描述

在此输入图像描述

Is a general solution possible with iterative boolean intersection operations?

EDIT

The following simple snipped is a [NodeBox](http://nodebox.net/code/index.php/Home) script that draws intersecting ellipses.

oval(x0,y0,w,h) creates an ellipse.

According to the doc , boolean operations on paths like p[19].difference(p[17]) will give a "flat" result ("made up of numerous straight line segments").

Coordinates of a path can be added or changed.

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)    

You said language agnostic, so I'll answer that way. You can get what you want with boolean operations on polygons as you propose. If F is a set of non-intersecting polygons and P is a new polygon that overlaps one or more of F, then, you'd want to do this:

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

The idea is to use the new polygon p to split existing "flat" polygons in F into parts shared with p and not shared with p, then remove that overlap with the original polygon from p itself and continue. When you've done that, what's left of p is the part that had no overlap with anything in F, so we add that as a new polygon to F.

So to handle a random collection of circular polygons, you start with F containing one of them (which is certainly a flat collection!) and add more, one at a time, until done.

In practice, this is blindingly less efficient than a custom algorithm. A standard way to handle problems like this is the sweep line technique. Imagine a vertical line sweepling from left-to-right over the circles. As it "touches" a circle, it starts building a polygon. When it touches an intersection, one polygon closes, two continue, and a new one opens up (in the general case). When it reaches the righmost point of a circle, the associated polygon closes. A "closed" polygon is removed from the sweep line and added to an output list. Sweep line algorithms are not conceptually difficult, but implementation is fiddly with special cases abounding (particularly for lines parallel to the sweeper and when a vertex of one polygon lies on an edge of another, though a general technique for working these out is simulation of simplicity ).

"Generalized arrangement" is a term of computational geometry used to describe problems like this. A generalized arrangement is a collection of lines, segments, and/or polygons (normal arrangments are just sets of lines). For example, the CGAL library for generalized arrangements can do exactly your problem with high efficency. CGAL is a big, general libarary in C++, so there are some learning costs. Licensing for commercial purposes is tricky.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM