4

I've seen online that buffer(0) should "fix" bowties. Shapely finds the intersection point of the bowtie, but only keeps the top-right portion. Looking for a workaround, I tried reversing the order of my points. Surprisingly (to me), the same top-right portion of the bowtie was still the one kept. I don't understand. Any help appreciated.

I would like to retain the entire bowtie as two triangles (ore one six-sided polygon--either would be useful). Looking for a workaround for this "problem."

#!/usr/bin/env python3

from shapely.geometry.polygon import Polygon

bowtie_plot = [(1, 0), (0, 1), (0, -1), (-1, 0)]

bowties = [
        Polygon(bowtie_plot),
        Polygon(bowtie_plot[::-1])
        ]

cleaned = [
        bowties[0].buffer(0),
        bowties[1].buffer(0)
        ]

print('cleaned[0] exterior = {}'.format(list(cleaned[0].exterior.coords)))
# cleaned[0] exterior = [(0.0, 0.0), (-1.0, 1.0), (1.0, 1.0), (0.0, 0.0)]

print('cleaned[1] exterior = {}'.format(list(cleaned[1].exterior.coords)))
# cleaned[1] exterior = [(0.0, 0.0), (-1.0, 1.0), (1.0, 1.0), (0.0, 0.0)]

# ADDITIONAL INFORMATION BELOW
# here's what shapely *can* do with intersecting lines:
# a star shape made of five intersecting lines and five points

from math import sin, cos, pi

star = Polygon(
        [(cos(x*pi*4/5), sin(x*pi*4/5)) for x in range(5)]
        ).buffer(0)

# after buffering, becomes a star shape made out of ten lines and ten points
# shapely found all intersections and corrected the polygon.
print('list exterior = {}'.format(list(star.exterior.coords)))

After thinking about it, I can understand why a bowtie is treated differently than a star, but I'm interested in finding a workaround.

Shay
  • 1,368
  • 11
  • 17
  • Have you tried closing the polygon. I don't know shapely but I looked at one of their Polygon examples and it appears that they close the polygon (have the same first and last point). – CrazyCasta Jan 11 '14 at 03:54
  • Possible duplicate of [Splitting self-intersecting polygon only returned one polygon in Shapely](https://stackoverflow.com/questions/35110632/splitting-self-intersecting-polygon-only-returned-one-polygon-in-shapely) – Georgy Aug 23 '19 at 06:30

2 Answers2

2

Your bowtie is not a valid shapely Polygon. Read that documentation, and the documentation for LinearRing (just above the Polygon documentation). In particular, note the examples of valid and invalid LinearRings.

If you create the bowtie like this:

In [46]: bt = [(1,0), (0,1), (0,0), (-1,0), (0, -1), (0,0)]

In [47]: poly = Polygon(bt)

then buffer(0) returns a MultiPolygon:

In [48]: poly.buffer(0)
Out[48]: <shapely.geometry.multipolygon.MultiPolygon at 0x4a40050>
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
0

buffer(0) does not always produce a MultiPolygon:

from shapely.wkt import loads

bt = loads('POLYGON ((0 0, 2 2, 2 0, 0 2, 0 0))')<br>
bt.buffer(0).wkt 

produces 'POLYGON ((1 1, 2 2, 2 0, 1 1))'
Jason Sturges
  • 15,855
  • 14
  • 59
  • 80