Python 多个多边形的形状相交,其中多个多边形的百分比相交?
我正在使用Shapely的多边形来处理人工生成的数据。要求多人围绕图像中的某些特征绘制多边形。因此,对于每个图像,我们有n个Python 多个多边形的形状相交,其中多个多边形的百分比相交?,python,polygon,shapely,Python,Polygon,Shapely,我正在使用Shapely的多边形来处理人工生成的数据。要求多人围绕图像中的某些特征绘制多边形。因此,对于每个图像,我们有n个多多边形,其中n等于每个图像的参与者数量 我可以绘制每个多多边形 fig, ax = plt.subplots() for ii, multi_poly in enumerate(multi_polys): for poly in multi_poly.geoms: x,y = poly.exterior.xy plt.plot(x
多多边形,其中n等于每个图像的参与者数量
我可以绘制每个多多边形
fig, ax = plt.subplots()
for ii, multi_poly in enumerate(multi_polys):
for poly in multi_poly.geoms:
x,y = poly.exterior.xy
plt.plot(x,y, c=colors[ii])
我们可以看到,在某些位置,多多边形
重叠,而在其他位置则没有重叠
我希望得到这些多边形的重叠或相交。
这应该是微不足道的,因为我可以做如下事情:
intersection = multi_a.intersection(multi_b) \
.intersection(multi_c) \
.intersection(multi_d) \
.inters...
我可以在上一张图上画出这个交叉点,我们可以看到:
这看起来不错。但是,此方法仅返回所有多多边形重叠的区域。有没有办法得到75%多边形重叠的交点?或者50%的重叠
代码示例:以下虚拟数据给出了此图:
P1 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
P2 = Polygon([(2.5, 2), (3, 2), (3, 3), (2.5, 3)])
multi_a = MultiPolygon([P1, P2])
P1 = Polygon([(-1, -1), (-1, 2),(2, 2), (2, -1)])
P2 = Polygon([(3, 3), (4, 2), (4, 4), (3, 4)])
multi_b = MultiPolygon([P1,P2])
P1 = Polygon([(-2, 4), (2.2, 4),(2.2, -2), (-2, -2)])
P2 = Polygon([(-1.5, 3), (-1.1, 3), (-1.5, -1), (-1.1, -1)])
multi_c = MultiPolygon([P1,P2])
P1 = Polygon([(2.5, -1), (3.2, -1),(3.2, -2), (-2, -2)])
P2 = Polygon([(3, 0), (4, 0), (3, 1), (4, 1)])
multi_d = MultiPolygon([P1,P2])
在这四个多边形上,由于没有一个点是所有四个多边形都占据的,因此交点方法将不返回交点。然而,蓝色正方形(用黄色标记突出)被蓝色、橙色和绿色多边形占据。因此,75%的多多边形在此位置重叠
有没有办法(最好使用Shapely)得到75%多边形重叠的位置
公认的答案在某些情况下似乎不成立。
我发现了问题:contain形状的边界有时与内部多边形重叠。我可以将if geom.contains(polygon):
替换为if geom.contains(polygon.buffer(-1)):
并且它完全按照预期工作
一种方法是分割所有几何体,以获得XY平面上非相交区域的平面列表,然后查看每个区域包含多少原始几何体。任何包含至少某些阈值数量的原始几何图形的区域都可以添加到结果中。结合使用代码和插图更容易解释这一点
首先,我们需要解决一个问题。您组合的示例中有两个无效几何图形,这将导致Shapely在尝试查询空间关系时抛出错误(例如,调用包含或相交)。您可以检查使用是否有效
属性,并通过调用解释有效性
获取更详细的信息:
从shapely.geometry导入多边形
从shapely.validation导入解释有效性
P2=多边形([-1.5,3),(-1.1,3),(-1.5,-1),(-1.1,-1)])
>>>P2.u有效吗
假的
>>>解释有效性(P2)
'自相交[-1.3 1]'
基本上,当这些形状应该是多个多边形时,将它们表示为多边形并不令人满意:
P1 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
P2 = Polygon([(2.5, 2), (3, 2), (3, 3), (2.5, 3)])
multi_a = MultiPolygon([P1, P2])
P1 = Polygon([(-1, -1), (-1, 2),(2, 2), (2, -1)])
P2 = Polygon([(3, 3), (4, 2), (4, 4), (3, 4)])
multi_b = MultiPolygon([P1,P2])
P1 = Polygon([(-2, 4), (2.2, 4),(2.2, -2), (-2, -2)])
P2 = Polygon([(-1.5, 3), (-1.1, 3), (-1.3, 1)])
P3 = Polygon([(-1.5, -1), (-1.3, 1), (-1.1, -1)])
multi_c = MultiPolygon([P1,P2,P3])
P1 = Polygon([(2.5, -1), (3.2, -1),(3.2, -2), (-2, -2)])
P2 = Polygon([(3, 0), (4, 0), (3.5, 0.5)])
P3 = Polygon([(3.5, 0.5), (3, 1), (4, 1)])
multi_d = MultiPolygon([P1,P2,P3])
因此,为了使示例有效,一些多重多边形将有3个而不是2个组成多边形:
P1 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
P2 = Polygon([(2.5, 2), (3, 2), (3, 3), (2.5, 3)])
multi_a = MultiPolygon([P1, P2])
P1 = Polygon([(-1, -1), (-1, 2),(2, 2), (2, -1)])
P2 = Polygon([(3, 3), (4, 2), (4, 4), (3, 4)])
multi_b = MultiPolygon([P1,P2])
P1 = Polygon([(-2, 4), (2.2, 4),(2.2, -2), (-2, -2)])
P2 = Polygon([(-1.5, 3), (-1.1, 3), (-1.3, 1)])
P3 = Polygon([(-1.5, -1), (-1.3, 1), (-1.1, -1)])
multi_c = MultiPolygon([P1,P2,P3])
P1 = Polygon([(2.5, -1), (3.2, -1),(3.2, -2), (-2, -2)])
P2 = Polygon([(3, 0), (4, 0), (3.5, 0.5)])
P3 = Polygon([(3.5, 0.5), (3, 1), (4, 1)])
multi_d = MultiPolygon([P1,P2,P3])
希望您的真实源数据具有有效的几何图形(或者您可以通过某种方式将其转换为有效的几何图形-顺便说一句,这是Shapely 1.8中即将推出的功能,通过实现,但尚未发布),因为否则下面描述的方法将无法工作
这样一来,第一步就是从形状列表中获取非相交区域的平面列表。为此,我们从相交形状的原始列表开始(请注意,多个形状重叠处的阴影较深):
使用(结合使用)将其转换为行:
结果是:
从图片上看可能不清楚,但想法是这些几何体都不相交-其中一些多边形中有洞(在一个形状先前包含另一个形状的情况下)。这代表了“XY平面上非相交区域的平面列表”,我在开始时提到过
到目前为止,流程的代码如下所示:
从shapely.geometry导入多边形,多多边形
从shapely.ops导入linemerge、一元联合、多边形化
#此处的原始形状定义(已剪下)。。。
形状=[多个a、多个b、多个c、多个d]
线=一元联合(linemerge([geom.external for shape in shape for geom in shape.geoms]))
多边形=列表(多边形化(线))
接下来,我们检查多边形
列表中的每个结果区域,并检查与原始列表相交的形状数。如果它高于阈值(此处定义为0.75*len(shapes)
),则我们将其添加到结果中:
threshold=0.75*len(形状)
def重叠(多边形、形状):
对于shape.geom中的geom:
如果几何体包含(多边形):
返回真值
返回错误
结果=[]
对于多边形中的多边形:
包含_形状=[]
对于形状中的形状:
如果重叠(多边形、形状):
包含形状。附加(形状)
如果len(包含_形状)>=阈值:
结果追加(多边形)
如果您正在处理一个大型数据集,那么在这样的嵌套循环中检查交叉点可能会非常慢(O(N^2)
),因此您可能可以使用以下方法来加快速度:
从shapely.strtree导入strtree
#(前面的代码用于获取多边形的展平列表…)
tree=STRtree([geom for shape in shape for geom in shape.geom])
结果=[]
对于多边形中的多边形:
matches=[o.wkt表示树中的o.query(polygon),如果o.contains(polygon)]
如果len(匹配)>=阈值:
结果追加(多边形)
您好。这个答案似乎正是我所需要的-但是,当我将它应用于我自己的数据时,它不起作用。我不确定我这方面或解决方案方面是否存在问题。我在原始问题中添加了一小部分我发现了问题并将其添加到原始问题中