I have a polygon, where some vertices are connected with lines (the startpoint and the endpoint are a vertice of the polygon). For each line (that connects vertices) are 4 rules:
Example: In the image, the red lines are bad lines, the black lines are polygon edges and the green line is a good line.
h
is good i
is bad, because it intersects the polygon j
is bad, because it intersects line h
and i
k
is bad, because it is an edge of the polygon g
is bad, because it is not contained by the polygon I have an array with the vertices of the polygon, and an array with the lines, like this:
polygon = [
{x: ..., y: ...},
...
]
lines = [
{
p1: {x: ..., y: ...},
p2: {x: ..., y: ...}
},
...
]
The lines
array contains only valid lines.
How can I get the polygons that are sliced by the lines.
I want something like this:
function getSlicedPolygons(polygon, lines){
// No check for valid lines, they are already valid
// Do the algorithm...
}
I start on the first vertex and go next until I reach a connected vertex. From that vertex, I go to the vertex that's connected at the other ending of the line. Now I go next until another vertex that's connected and so on until I reached the vertex where I started. Now I have the first polygon. I couldn't find the others...
Code (implementation, not real code):
function getSlicedPolygons(polygon, line){
var results = []
var ofl = 0; // Overflow counter, to prevent infinite looping
while(lines.length > 0){
// Iterate through polygon
var i = 0;
var r = []; // Array of new indices
var iterations = 0; // An overflow counter again
while(i < polygon.length){
r.push[i]
// findNextConnectionIndex(...) searches for a line
// that connects with this vertex and returns the index of
// the other connected vertex
var n = findNextConnectionIndex(i, polygon, lines) || i+1
i=n;
// Don't loop infinite
iterations++;
if(iterations > 10) break;
}
var result = [];
for(var z = 0; z<r.length; z++){
result.push(polygon[r[z]])
}
results.push(result)
// Now I should do something to get another polygon next
// time ...
// Don't loop infinite
ofl++;
if(ofl >= 10) break;
}
return results;
}
It returns the same polygon 10 times in an array...
Treat the polygon and its intersecting lines as an undirected graph with loops and apply a loop-detection algorithm to it. Since we know the connecting lines, things become a bit more simple and we can actually solve the problem in O(V)
.
This would be a model that suffices to explain the basic principle. We can transform our polygon into a rectangle that is sliced by the list of lines. Since no lines may intersect, this will also apply to the resulting rectangle. Now one can start in an corner of the graph and travel alongside both edges until on both paths a vertex of degree 3 is reached. Thus we've found our first polygon that results from slicing the original polygon. Go on from the two points reached in the previous step until you reach vertices of degree 3 are reached again. Terminate this step when the two paths meet and you've listed all possible polygons.
A diagram of running a single step of this process:
Start from an arbitrary point in the graph/polygon and traverse the vertices along the polygon in an arbitrary direction until a vertex of degree 3 is reached. Store the corresponding slicing line and proceed along the polygon until the vertex of degree 3 is reached. If it is the same slicing line, you've found a "corner" vertex, else store the new slicing line and repeat.
A working implementation in python:
def slice_polygon(poly, part):
# find the "corner point"
last_slice = None
last_pt = None
for pt in poly:
s = [x for x in part if pt in x]
if s:
if last_slice in s:
break
last_slice = s[0]
last_pt = pt
# find slicing starting from border-point
a = poly.index(last_pt)
b = (a + 1) % len(poly) # current positions on the polygon
sliced_poly = [] # current polygon
slicing = [] # list of all polygons that are created by the slicing
while a != b:
if not [x for x in part if poly[a] in x]:
# point doesn't lie on slicing-line => add to current polygon
sliced_poly.insert(0, poly[a]) # prepend point
a = (a - 1 + len(poly)) % len(poly) # advance a by one
elif not [x for x in part if poly[b] in x]:
# point doesn't lie on slicing-line => add to current polygon
sliced_poly.append(poly[b]) # append point
b = (b + 1 + len(poly)) % len(poly) # advance by one
else:
# append points of slicing line
sliced_poly.insert(0, poly[a])
sliced_poly.append(poly[b])
# store created polygon and start over
slicing.append(sliced_poly)
sliced_poly = []
# remove partitioning-line at which the algorithm stopped
part.remove([x for x in part if poly[a] in x and poly[b] in x][0])
# add last point to the current polygon, as it's not yet added to it
sliced_poly.append(poly[a])
# add last polygon to result-set
slicing.append(sliced_poly)
return slicing
# test
polygon = [(150, 110), (270, 40), (425, 90), (560, 150), (465, 290), (250, 290), (90, 220)]
partition = [((270, 40), (250, 290)), ((425, 90), (250, 290))]
print(slice_polygon(polygon, partition))
Output:
[[(425, 90), (560, 150), (465, 290), (250, 290)], [(270, 40), (425, 90), (250, 290)], [(90, 220), (150, 110), (270, 40), (250, 290)]]
Since there is a total of two "corner-points" (at least), we are guaranteed to find at least one, if we traverse the polygon once.
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.