Dealing with "cracks" in the unary_union of several imprecise Polygons?

Question:

I used shapely.ops.unary_union on a number of 6-sided shapely.geometry.Polygons, and obtained the following shape A:

An irregular polygon shaped with a "honeycomb" shape, with "cracks" in it.

Note how there are two "cracks" in the upper part. These are not intended, and are presumably caused by some floating-point edge cases.

If you construct another shape B that sits inside of A, and if A happens to intersect one of these "cracks", then A.covers(B) will be False!

In my particular case, this leads to a test suite failure, because A.covers(B) is supposed to be an invariant. Therefore I need to deal with this somehow. Is there some algorithm I can use to "seal" these cracks?

In practice, these "cracks" will not affect the functioning of the application, because we only care about the outer border of A covering B. Thus I am open to solutions that adjust the individual hexagons in order to make the cracks go away by introducing overlaps.

However, I cannot accept the outer border of this shape changing, because that would actually no longer be testing the application as it is intended to be used.

To summarize, I want the outcome to look like this (my hand-edited version):

The same polygon, without any cracks

Asked By: shadowtalker

||

Answers:

You can fix this by buffering and un-buffering the shape.

Here’s an example of a polygon with a small crack:

from shapely.geometry import Polygon
bad_polygon = Polygon([[0, 0], [1, 0], [1, 0.4999], [0.5, 0.5], [1, 0.5001], [1, 1], [0, 1], [0, 0]])

polygon crack

To fix it, expand the shape slightly, and contract it the same amount, using the buffer() method.

tol = 1e-4
bad_polygon.buffer(tol).buffer(-tol)

The value tol must be at least as large as half the distance across the crack at the crack’s widest point.

no crack

Answered By: Nick ODell
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.