我正在使用 Shapely 多边形,我需要一种方法来删除较大多边形内的所有较小多边形。我尝试使用.contains()Shapely 提供的方法,但True如果较小的多边形不完全位于较大的多边形内,则该方法不会返回。
基本上,我想要一个方法.contains(),但是True如果多边形位于图片上的外部多边形的边界上,它会返回
.
以下是以 wkt 格式呈现的图片中的多边形:
绿色一:
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))`
Run Code Online (Sandbox Code Playgroud)
红色一:
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))
Run Code Online (Sandbox Code Playgroud)
我也尝试使用该.intersects()方法,但它返回True给定多边形之外的多边形,这些多边形具有一些我不想要的公共边界。
我希望您了解我的需求,如果有人知道解决方案,我将不胜感激。
通常,contains在测试一个多边形是否在另一个多边形内部并且它们具有共同边界时,该方法应该有效。例如,如果您采用以下简单示例,它将按预期工作:
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
Run Code Online (Sandbox Code Playgroud)
但经常发生的情况是,由于精度错误,内部多边形仅从外部露出一点点,而测试失败。
例如,在这里,我绘制了多边形并放大了左上角的交点:
import matplotlib.pyplot as plt
plt.plot(*green.exterior.xy, c='g')
plt.plot(*red.exterior.xy, c='r')
Run Code Online (Sandbox Code Playgroud)
您可以看到线条并不完美地相互重叠:
有几种方法可以处理这个问题。例如,第一个是在如何处理 Shapely 中的舍入错误和GitHub 上的一些Shapely 问题中提出的:
缩小较小的多边形或稍微扩展较大的多边形:
big.contains(small.buffer(-1e-14))
# True
big.buffer(1e-14).contains(small)
# True
Run Code Online (Sandbox Code Playgroud)检查位于较大多边形之外的较小多边形的面积是否接近于零:
small.difference(big).area < 1e-14
# True
Run Code Online (Sandbox Code Playgroud)检查较小多边形的每个顶点到较大多边形的距离是否接近于零:
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
Run Code Online (Sandbox Code Playgroud)可能有更多的方法来执行测试,但我认为这些就足够了。