# Bowtie or hourglass polygon validity issue when self-crossing point is not defined

Using Python2.7 and shapely, let:

``````import shapely
coords = [(0, 0), (0, 2), (2, 0), (2, 2), (0, 0)]
bowtie = shapely.geometry.Polygon(coords)
bowtie.is_valid
``````

which gives this :

``````Self-intersection at or near point 1 1
Out[2]: False
``````

So let try the `buffer(0)` method as describer in the doc (http://toblerity.org/shapely/manual.html):

``````clean = bowtie.buffer(0)
type(clean)
``````

which gives that:

``````Out[4]: shapely.geometry.polygon.Polygon
``````

The difference between the example in the doc is that in the present case, the crossing point is not defined in the original coordinates, so it's not resulting in a multipolygon and it's not really consistent with these initial coordinates, as this command:

``````clean.wkt
``````

shows when it returns:

``````Out[16]: 'POLYGON ((0 0, 0 2, 1 1, 0 0))'
``````

And the resulting image for a more visual understanding:

With:
Red: original self-intersecting polygon
Teal: cleaned bowtie polygon with `buffer(0)` method (only one half of the original polygon. Take care of the different scaling effect on iPython...)

Question:
How to easily get the original shape back with a valid geometry so that we can perform further operations like intersections, etc?

• It seems that using slightly bigger buffer than zero has solved same kind of problems. Commented Jun 7, 2017 at 19:32
• I've also tried in this example with `buffer(0.1)` to `buffer(0.5)` by increment `0.1`; result is the same: `clean` is a simple polygon, not a multipolygon. Commented Jun 7, 2017 at 19:36
• You can use `GeometryCollection((bowtie, clean))` to plot both at once. Commented Jun 10, 2017 at 14:26

A different hack would be using only the exterior of the bowtie, intersecting it with itself (generating a MultiLineString), polygonizing that (generating Polygons) and finally aggregating into a MultiPolygon:

``````be = bowtie.exterior
mls = be.intersection(be)
polygons = polygonize(mls)
valid_bowtie = MultiPolygon(polygons)
print(valid_bowtie)

MULTIPOLYGON (((0 0, 0 2, 1 1, 0 0)), ((2 0, 1 1, 2 2, 2 0)))
``````

In my case, `exterior` was returning `LinearRing`, and anyway, intersection with itself didn't work because the original polygon isn't valid. I ended up finding this answer which was more helpful.

This is the code I came up with:

``````coords = [[0,0],[1,1],[0,1],[1,0],[0,0]]
line_non_simple = shapely.geometry.LineString(coords)
mls = shapely.ops.unary_union(line_non_simple)
polygons = list(shapely.ops.polygonize(mls))
shapely.geometry.MultiPolygon(polygons)
``````