在Python中高效获取多个多边形的交集


12

我想得到多个多边形的交集。使用Python的shapely程序包,我可以使用intersection函数找到两个多边形的交点。是否有类似的有效函数来获取多个多边形的交集?

这是一个代码片段,以了解我的意思:

from shapely.geometry import Point

coord1 = ( 0,0 )
point1 = Point(coord1)
circle1 = point1.buffer(1)

coord2 = ( 1,1 )
point2 = Point(coord2)
circle2 = point2.buffer(1)

coord3 = ( 1,0 )
point3 = Point(coord3)
circle3 = point3.buffer(1) 

可以找到两个圆的交点circle1.intersection(circle2)。我可以找到所有三个圆的交点circle1.intersection(circle2).intersection(circle3)。但是,这种方法不适用于大量的多边形,因为它需要越来越多的代码。我想要一个接受任意数量的多边形并返回其交点的函数。


我想也许是将坐标存储在字典中,并在使用itertools导入组合时循环浏览。我会尽快发布
ziggy

“他们的路口”是什么意思?您是指所有与至少一个其他多边形相交的区域,还是所有输入都相交的区域?
jpmc26

我的意思是所有多边形的交集,而不是至少一个。
碎片

您应该在上面进行澄清(也许用示例输出)。我可以肯定,大多数答案都不会像您希望的那样。(而且一些回答者误解了的事实足以证明这个问题需要澄清。)
jpmc26

1
@ jpmc26我刚刚在使用rtree的答案中添加了更新。该方法现在更加高效和可扩展。希望这可以帮助!
Antonio Falciano

Answers:


7

一种可能的方法可以通过级联工会正在考虑对多边形,它们的交叉点和所有的路口终于工会的组合(如建议在这里):

from shapely.geometry import Point
from shapely.ops import cascaded_union
from itertools import combinations

circles = [
    Point(0,0).buffer(1),
    Point(1,0).buffer(1),
    Point(1,1).buffer(1),
]

intersection = cascaded_union(
    [a.intersection(b) for a, b in combinations(circles, 2)]
)
print intersection

一种更有效的方法应该使用一个空间索引,例如Rtree,以处理许多几何体(不是三个圆的情况):

from shapely.geometry import Point
from shapely.ops import cascaded_union
from rtree import index

circles = [
    Point(0,0).buffer(1),
    Point(1,0).buffer(1),
    Point(1,1).buffer(1),
]
intersections = []
idx = index.Index()

for pos, circle in enumerate(circles):
    idx.insert(pos, circle.bounds)

for circle in circles:
    merged_circles = cascaded_union([circles[pos] for pos in idx.intersection(circle.bounds) if circles[pos] != circle])
    intersections.append(circle.intersection(merged_circles))

intersection = cascaded_union(intersections)
print intersection

我不认为这能满足OP的要求。它会返回至少2个多边形所覆盖的区域,而OP仅在查找集合中所有多边形所覆盖的区域。请参阅注释中的说明。
jpmc26

3

为什么不使用迭代或递归?就像是 :

from shapely.geometry import Point

def intersection(circle1, circle2):
    return circle1.intersection(circle2)

coord1 = ( 0,0 )
point1 = Point(coord1)
circle1 = point1.buffer(1)

coord2 = ( 1,1 )
point2 = Point(coord2)    
circle2 = point2.buffer(1)


coord3 = ( 1,0 )
point3 = Point(coord3)
circle3 = point3.buffer(1)
circles = [circle1, circle2, circle3]
intersectionResult = None

for j, circle  in enumerate(circles[:-1]):

    #first loop is 0 & 1
    if j == 0:
        circleA = circle
        circleB = circles[j+1]
     #use the result if the intersection
    else:
        circleA = intersectionResult
        circleB = circles[j+1]
    intersectionResult = intersection(circleA, circleB)

result= intersectionResult

2

试一下这段代码。它的概念非常简单,我相信您会找到想要的东西。

from shapely.geometry import Point
from itertools import combinations
dic ={}
dic['coord1']=Point(0,0).buffer(1)
dic['coord2']=Point(1,1).buffer(1)
dic['coord3']=Point(1,0).buffer(1)
inter = {k[0]+v[0]:k[1].intersection(v[1]) for k,v in combinations(dic.items(),2)}
print inter

如果要将输出存储为shapefile,请使用fiona:

from shapely.geometry import Point,mapping
import fiona
from itertools import combinations
schema = {'geometry': 'Polygon', 'properties': {'Place': 'str'}}
dic ={}
dic['coord1']=Point(0,0).buffer(1)
dic['coord2']=Point(1,1).buffer(1)
dic['coord3']=Point(1,0).buffer(1)
inter = {k[0]+v[0]:k[1].intersection(v[1]) for k,v in combinations(dic.items(),2)}
print inter
with fiona.open(r'C:\path\abid', "w", "ESRI Shapefile", schema) as output:
    for x,y in inter.items():
        output.write({'properties':{'Place':x},'geometry':mapping(y)})

这输出-

在此处输入图片说明


3
我不认为这能满足OP的要求。它会返回至少2个多边形所覆盖的区域,而OP仅在查找集合中所有多边形所覆盖的区域。请参阅注释中的说明。另外,在您的理解中,对于变量名来说kv它们是较差的选择dict。这些变量各自引用的不同元素dic.items(),而不是键值对。这样的事情a, b将减少误导。
jpmc26

1
哦,是的,我不明白他的意思
ziggy

并指出了有关我的k,v选择的好方法-我只是在遍历字典时自动使用k,
v。.didnt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.