Python'da çoklu çokgenlerin kesişimini verimli bir şekilde elde etme


12

Birden çok poligonun kesişimini almak istiyorum. Python'un shapelypaketini kullanarak, intersectionfonksiyonu kullanarak iki çokgenin kesişimini bulabilirim . Birden çok poligonun kesişimini elde etmek için benzer etkili bir fonksiyon var mı?

İşte ne demek istediğimi anlamak için bir kod snippet'i:

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) 

İki dairenin kesiştiği yerde bulunabilir circle1.intersection(circle2). Üç dairenin de kesişim noktasını bulabilirim circle1.intersection(circle2).intersection(circle3). Bununla birlikte, bu yaklaşım giderek daha fazla kod gerektirdiğinden çok sayıda poligon için satılamaz. Rastgele sayıda çokgen alan ve kesişimlerini döndüren bir işlev istiyorum.


im düşünce belki bir sözlükte koordinatları saklamak ve itertools ithalat kombinasyonları kullanırken döngü. Yakında
yayınlayacağım

"Kavşakları" ile ne demek istiyorsun? En az bir diğer çokgenle kesişen veya tüm girdilerin kesiştiği alanlar mı demek istediniz ?
jpmc26

En az bir değil tüm poligonların kesişimini kastediyorum.
kıymık

Bunu yukarıda açıklığa kavuşturmalısınız (belki bir örnek çıktı ile). Ben cevapların çoğu eminim yok istediğiniz gibi davranırlar. (Ve birkaç cevaplayıcının yanlış anlamış olması, sorunun açıklığa kavuşturulması gerektiğini gösteren delildir.)
jpmc26

1
@ jpmc26 Cevabımı rtree'nin kullanıldığı yere bir güncelleme ekledim. Yaklaşım artık daha verimli ve ölçeklenebilir. Bu yardımcı olur umarım!
Antonio Falciano

Yanıtlar:


7

Olası bir yaklaşım, çokgen çiftlerinin kombinasyonu, kavşakları ve son olarak tüm kavşakların basamaklı bir birlik aracılığıyla birleştirilmesini düşünmek olabilir ( burada önerildiği gibi ):

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

Daha verimli bir yaklaşım , birçok geometriyle başa çıkmak için (üç dairenin durumu değil), Rtree gibi bir uzamsal indeks kullanmalıdır :

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'nin istediğini yaptığını sanmıyorum. En az 2 poligonun kapladığı alanları geri verirken OP sadece setteki tüm çokgenlerin kapladığı alanları arar . Yorumlarda açıklamaya bakın.
jpmc26

3

Neden yineleme veya özyinelemeyi kullanmıyorsunuz? gibi bir şey :

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

Bu kodu deneyin. Bu oldukça basit bir kavram ve size aradığınızı alır inanıyorum.

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

ve çıktının şekil dosyası olarak saklanmasını istiyorsanız fiona kullanın:

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)})

bu çıktılar -

resim açıklamasını buraya girin


3
OP'nin istediğini yaptığını sanmıyorum. En az 2 poligonun kapladığı alanları geri verirken OP sadece setteki tüm çokgenlerin kapladığı alanları arar . Yorumlarda açıklamaya bakın. Ayrıca, kve anlayışlarınızda vdeğişken adları için zayıf seçimlerdir dict. Bu değişkenlerin her biri dic.items(), anahtar / değer çiftinin değil, farklı öğelerini ifade eder . Gibi bir şey a, bdaha az yanıltıcı olur.
jpmc26

1
ohh tamam evet ne demek istediğini anlamadım
ziggy

ve nokta de benim k v seçimleri hakkında alınan - ben sadece otomatik k kullanın v dictionary..didnt içinde döngü o kadar düşünmek
ziggy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.