I'm looking for an algorithm that can take an area containing a set of non-overlapping convex polygons as input, and break the space outside of the polygons into a set of non-overlapping convex quadrilaterals. The quadrilaterals need to have the property that they (individually) use as much horizontal space as possible.
Here's the input:
Here's the desired output:
I feel like I have seen some variation of this algorithm used to calculate regions to be flood-filled in very old paint programs. Is there a pleasant way to do this in better than O(n^2)
time?
Edit: I realize there are some triangles in the output. I should probably state that quadrilaterals are the desired output, falling back to triangles only when it's physically impossible to use a quad.
I came up with a solution to this. In order to solve this efficiently, some sort of spatial data structure is needed in order to query which polygons are overlapped by a given rectangular area. I used a Quadtree. It's also necessary for the polygon data structure being used to be able to distinguish between internal and external edges. An edge is internal if it is common to two polygons.
The steps are as follows (assuming a coordinate system with the origin in the top-left corner):
(y0, y1)
of Y values, declare a rectangular area a
with
the the top left corner (0, y0)
and bottom right corner
(width, y1)
. Determine the set of polygons S
that are
overlapped by a
by querying the spatial data structure. For
each polygon p
in S
, determine the set of edges E
of p
that are overlapped by a
. For best results, ignore any edge in
E
with a normal that points directly up or down. For each
edge e
in E
, it's then necessary to determine the pair of
points at which e
intersects the top and bottom edges of a
.
This is achieved with a simple line intersection test,
treating the top and bottom edges of a
as simple horizontal
line segments. Join the intersection points to create a set of
new line segments, shown in red:L0 = (0, y0) → (0, y1)
and
L1 = (width, y0) → (width, y1)
. Working from left to right,
gather any line segments created in the preceding step into pairs,
ignoring any line segments that were created from internal edges.
If there were no intersecting external edges, then the only two
edges will be L0
and L1
. In this example strip, only four
edges remain:Repeating the above process for each horizontal strip achieves the desired result. Assuming a set of convex, non-overlapping polygons as input, the created polygons are guaranteed to be either triangles or quadrilaterals. If a horizontal strip contains no edges, the algorithm will create a single rectangle. If no polygons exist in the scene, the algorithm will create a single rectangle covering the whole scene.