Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shapely polygon_.buffer(0) "loses" half my bowtie

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.

like image 464
Shay Avatar asked Feb 16 '26 04:02

Shay


1 Answers

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>
like image 89
Warren Weckesser Avatar answered Feb 18 '26 17:02

Warren Weckesser



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!