Bắt giao nhau của nhiều đa giác một cách hiệu quả trong Python


11

Tôi muốn có được giao điểm của nhiều đa giác. Sử dụng shapelygói của Python , tôi có thể tìm thấy giao điểm của hai đa giác bằng cách sử dụng intersectionhàm. Có một chức năng hiệu quả tương tự để có được giao điểm của nhiều đa giác?

Đây là một đoạn mã để hiểu ý của tô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) 

Một giao điểm của hai vòng tròn có thể được tìm thấy bởi circle1.intersection(circle2). Tôi có thể tìm thấy giao điểm của cả ba vòng tròn bằng cách circle1.intersection(circle2).intersection(circle3). Tuy nhiên, cách tiếp cận này không thể bán được cho một số lượng lớn các đa giác vì nó đòi hỏi ngày càng nhiều mã hơn. Tôi muốn một hàm lấy số đa giác tùy ý và trả về giao điểm của chúng.


Tôi nghĩ có thể lưu trữ các coords trong một từ điển và lặp qua nó trong khi sử dụng từ các kết hợp nhập itertools. Tôi sẽ đăng sớm
ngoằn ngoèo

Bạn có ý nghĩa gì bởi "giao điểm của họ"? Bạn có nghĩa là tất cả các khu vực giao nhau với ít nhất một đa giác khác, hoặc các khu vực mà tất cả các đầu vào giao nhau?
jpmc26

Ý tôi là giao điểm của tất cả các đa giác, không phải ít nhất một.
bắn tung tóe

Bạn nên làm rõ điều này ở trên (có lẽ với một đầu ra ví dụ). Tôi khá chắc chắn hầu hết các câu trả lời không hành xử như bạn muốn. (Và thực tế một số người trả lời đã hiểu nhầm là bằng chứng đủ để câu hỏi cần được làm rõ.)
jpmc26

1
@ jpmc26 Tôi vừa thêm một bản cập nhật cho câu trả lời của mình, nơi rtree được sử dụng. Cách tiếp cận hiệu quả hơn và có thể mở rộng. Hi vọng điêu nay co ich!
Antonio Falciano

Câu trả lời:


6

Một cách tiếp cận khả thi có thể là xem xét sự kết hợp của các cặp đa giác, giao điểm của chúng và cuối cùng là sự kết hợp của tất cả các giao điểm thông qua liên kết xếp tầng (như được đề xuất ở đây ):

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

Một cách tiếp cận hiệu quả hơn nên sử dụng một chỉ số không gian, như Rtree , để đối phó với rất nhiều hình học (không phải là trường hợp của ba vòng tròn):

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

Tôi không tin điều này làm những gì OP muốn. Nó trả lại các khu vực có ít nhất 2 đa giác, trong khi OP chỉ tìm kiếm các khu vực được bao phủ bởi tất cả các đa giác trong tập hợp. Xem làm rõ trong ý kiến.
jpmc26

3

Tại sao không sử dụng phép lặp hoặc đệ quy? cái gì đó như :

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

Cho mã này một shot. Nó khá đơn giản trong khái niệm và tôi tin rằng sẽ mang lại cho bạn những gì bạn đang tìm kiếm.

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

và nếu bạn muốn đầu ra được lưu trữ dưới dạng shapefile, hãy sử dụng 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)})

đầu ra này -

nhập mô tả hình ảnh ở đây


3
Tôi không tin điều này làm những gì OP muốn. Nó trả lại các khu vực có ít nhất 2 đa giác, trong khi OP chỉ tìm kiếm các khu vực được bao phủ bởi tất cả các đa giác trong tập hợp. Xem làm rõ trong ý kiến. Ngoài ra, kvlà lựa chọn kém cho tên biến trong dictcách hiểu của bạn . Mỗi biến đó tham chiếu đến các yếu tố khác nhau dic.items(), không phải là cặp khóa-giá trị. Một cái gì đó như a, bsẽ ít gây hiểu lầm.
jpmc26

1
ohh okay yeah tôi không hiểu ý anh ấy
ngoằn ngoèo

và quan điểm tốt về các lựa chọn k, v của tôi - tôi chỉ tự động sử dụng k, v khi lặp qua từ điển..didnt cho nó nhiều suy nghĩ
ngoằn ngoèo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.