1
votes

I am working with several convex polygons that overlap each other and I need to combine them back together to form one single polygon that may be convex or concave.

The problem is always as follows:

1) The polygons that I need to merge together are always convex.

2) The vertices of each polygon are defined in clockwise order.

3) The polygons are never in any specific order.

4) The final polygon can only be simple convex or concave polygon, i.e. no self-intersection, no duplicate vertices or holes in the shape.

Here is an example of the kind of polygons that I am working with.

![overlapping convex polygons]"image removed")

My current approach is to start from the first polygon and vertex by vertex I loop through all vertices of all of the polygons to find overlap. If there is no overlap, I store the vertex for the final outline and continue.

Upon finding overlapping vertices, I determine which polygon to continue to by measuring the angles of the possible paths and by choosing the one that leads towards the outside of the shape.

This method works until I encounter polygons that do not have vertices overlapping each other, but instead one polygon's vertex is overlapping another polygon's side, as is the case with the rectangle in the image.

I am currently planning on solving these situations by running line intersect checks for all shapes that I have not yet processed, but I am convinced that this cannot be the easiest or the best method in terms of performance.

Does someone know how I should approach this problem in a more efficient manner and/or universal manner?

2
Could your source polygons not only touch each other but intersect?Egor Skriptunoff
The source polygons are exported from PhysicsEditor, which takes concave or convex shapes and splits them to several convex shapes. The individual convex shapes can never be within each other any more than they are in the image above.user10133166
It sounds, then, like the polygons are not overlapping, just incident on each other.Sneftel
How is the question related to Lua?lhf
I am programming the algorithm that does this in Lua.user10133166

2 Answers

1
votes

Given a vertex, you could speed up the search of an "overlapping" vertex or edge as follows:

Finding vertices

Assuming that the coordinates are exact, in the sense that if two vertices overlap, they have exactly the same x and y coordinates, without any "error" of imprecision, then it would be good to first create a hash by x-coordinate, and then for each x-entry you would have a hash by y-coordinate. The value of that inner hash would be a list of polygons that have that vertex.

That structure can be built in O(n) time, and will allow you to find a matching vertex in constant time.

Only if that gives no match, you would go to the next algorithm:

Finding edges

In a pre-processing step (only once), create a segment tree for these polygons where a "segment" corresponds to a min/max x-coordinate range for a particular polygon.

Given a vertex, use the segment tree to find the polygons that are in the right x-coordinate range, i.e. where the x-coordinate of the vertex is within the min/max range of x-coordinates of the polygon.

Iterate those polygons, and eliminate those that do not have an y-coordinate range that has the y-coordinate of the vertex.

If no polygons remain, the vertex does not participate in any edge of another polygon.

You cannot get more than one polygon here, since that would mean another polygon shares the vertex, which is a case already covered by the hash-based algorithm.

If you get just one polygon, then continue your search by going through the edges of that polygon to find a match -- which is what you already planned on doing (line intersect check), but now you would only need to do it for one polygon.

You could speed that line intersect check up a little bit by first filtering the edges to those that have the right x-range. For convex polygons you would end up with at most two edges. At most one of those two will have the right y-range. If you get such an edge, check whether the vertex is really on that edge.

0
votes

I solved this issue and I'm posting the answer here in case someone else runs into this issue as well.

My first step was to implement a pre-processing loop based on trincot's suggestions.

  1. I calculated the minimum and maximum x and y bounds for each individual shape.
  2. I used these values to determine all overlapping shapes and I stored a simple array for each shape that I could later use to only look at shapes that can overlap each other.

Then, for the actual loop that determines the outline of the final polygon:

  1. I start from the first shape and simply compare its vertices to those of the nearby shapes. If there is at least one vertex that isn't shared by another vertex, it must be on the outer edge and the loop starts from there. If there are only overlapping vertices, then I add the first shape to a table for all checked shapes and repeat this process with another shape until I find a vertex that is on the outer edge.
  2. Once the starting vertex is found, the main loop will check the vertices of the starting shape one by one and measure how far from the given vertex is from every nearby shapes' edges. If the distance is zero, then the vertex either overlaps with another shape's vertex or the vertex lies on the side of another shape.
  3. Upon finding the aforementioned type of vertex, I add the previous shape's number to the table of checked shapes so that it isn't checked again. Then, I check if there are other shapes that share this particular vertex. If there are, then I determine the outermost shape and continue from there, starting back from step 2.
  4. Once all shapes have been checked, I check that all non-overlapping vertices from the starting shape were indeed added to the outline. If they weren't, I add them at the end.

There may be computationally faster methods, but I found this one to be simple to write, that it meets all of my requirements and it is fast enough for my needs.