I'm working with Shapely polygons and I need a way to delete all smaller polygons contained within a bigger polygon. I tried using the .contains()
method which Shapely provides, but the method doesn't return True
if a given smaller polygon isn't completely inside of the bigger, "parent" polygon.
Basically, I want a method like .contains()
but that it returns True
in case the inner polygon shares boundaries with the outer polygon like on the example image below.
.
Here are the polygons from the picture presented in wkt format:
The green one:
POLYGON Z ((14.4265764858233823 45.3396418051734784 0.0000000000000000, 14.4267228266679606 45.3395430970275015 0.0000000000000000, 14.4266753563381904 45.3394727193694536 0.0000000000000000, 14.4265290154936121 45.3395714275154376 0.0000000000000000, 14.4265764858233823 45.3396418051734784 0.0000000000000000))`
The red one:
POLYGON Z ((14.4265450394689161 45.3395951840357725 0.0000000000000000, 14.4265695507109317 45.3395786509942837 0.0000000000000000, 14.4265802185605700 45.3395944667317679 0.0000000000000000, 14.4265982245953417 45.3395823215079616 0.0000000000000000, 14.4265715327703994 45.3395427492501426 0.0000000000000000, 14.4265290154936121 45.3395714275154376 0.0000000000000000, 14.4265450394689161 45.3395951840357725 0.0000000000000000))
I also tried using the .intersects()
method but it returns True
for polygons outside of a given polygon which have some common boundaries, which I do not want.
I hope you understand what I need and I'm thankful if someone knows a solution to this.
Normally the contains
method should work when testing if one polygon is inside another and they have common borders. For example, if you would take the following simple example, it would work as expected:
from shapely.geometry import Polygon
a = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
b = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
a.contains(b)
# True
But quite often what happens is that due to precision errors the inner polygon comes out just a tiny bit from the outer and the test fails.
Here, for example, I plotted your polygons and zoomed in on the upper left intersection point:
import matplotlib.pyplot as plt
plt.plot(*green.exterior.xy, c='g')
plt.plot(*red.exterior.xy, c='r')
You can see that lines don't lie on each other perfectly:
There are several ways to deal with this problem. The first one, for example, was proposed in How to deal with rounding errors in Shapely and in some Shapely issues on GitHub:
Shrink the smaller polygon or extend the bigger one a bit:
big.contains(small.buffer(-1e-14))
# True
big.buffer(1e-14).contains(small)
# True
Check that area of the smaller polygon that lies outside of the bigger one is close to zero:
small.difference(big).area < 1e-14
# True
Check if distances of each vertex of a smaller polygon to the bigger polygon are close to zero:
from shapely.geometry import Point
vertices = map(Point, small.exterior.coords)
distances = map(big.distance, vertices)
all(distance < 1e-14 for distance in distances)
# True
Probably there are more ways to perform the test, but I think these will suffice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With