Các đường giao nhau để có giao cắt bằng Python với QGIS?


10

Tôi có một bộ các dòng đại diện cho các tuyến xe buýt. Một số dòng được chồng chéo và đi trên cùng một con đường.

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

Tôi có thể trích xuất các nút. nhập mô tả hình ảnh ở đây

Tuy nhiên, tôi quan tâm đến việc chỉ trích xuất các giao cắt như thế này: nhập mô tả hình ảnh ở đây

Tôi có thể làm cái này như thế nào? Tôi đang tìm cách với QGIS hoặc Python.

Tôi đã thử phương thức giao nhau từ Python Python nhưng điều này về cơ bản chỉ trả về cho tôi các đỉnh.

Các phương pháp dòng nút giao thông từ QGIS trả về cho tôi những cửa nếu hai dòng vượt qua. Tuy nhiên, trong trường hợp hai tuyến xe buýt đi xa một phần trên tuyến đường của họ trên cùng một con đường, điều đó không cho tôi biết họ chỉ đến nơi họ hợp nhất.


Bạn đã thử công cụ giao cắt đường trong QGIS: Công cụ phân tích véc tơ> Giao lộ dòng ... Nó sẽ không cung cấp cho bạn các nút kết thúc và bắt đầu của một dòng, nhưng tất cả các giao điểm.
Jakob

Vâng, tôi đã viết về điều này trong câu hỏi.
ustroetz

Tôi không rõ về những gì bạn đang hỏi, một phần vì tất cả các dòng được ký hiệu theo cùng một cách trong hình ảnh của bạn - Tôi không thể phân biệt các tuyến đường khác nhau để hiểu các nút bạn đang xem hoặc tại sao có quá nhiều nút trong hình ảnh thứ hai. Là các tuyến đường trùng khớp trên đường? Có phải tất cả chúng là các đoạn đường hai điểm, hoặc polylines liên tục? Tôi lưu ý hành vi mà bạn mô tả giống như công cụ Intersect của ArcGIS - các dòng / dòng có đầu ra của các dòng cung cấp cho bạn sự chồng chéo, nhưng các dòng / dòng có đầu ra điểm chỉ cho giao cắt.
Chris W

Dựa vào đó, để có được những gì tôi nghĩ bạn muốn, bạn có thể phải sử dụng cả hai phương pháp. Lấy các giao điểm (dòng / dòng = điểm) và sau đó lấy các phần trùng lặp (dòng / dòng = dòng) và trích xuất các nút bắt đầu / kết thúc cho các dòng chồng chéo đó. Đó phải là tất cả các điểm / nút bạn đang tìm kiếm.
Chris W

Câu trả lời:


19

Các nút:

Bạn muốn hai thứ, điểm cuối của polylines (không có nút trung gian) và điểm giao nhau. Có một vấn đề khác, một số điểm cuối của polylines cũng là điểm giao nhau:

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

Một giải pháp là sử dụng Python và các mô-đun ShapelyFiona

1) Đọc shapefile:

from shapely.geometry import Point, shape
import fiona
lines = [shape(line['geometry']) for line in fiona.open("your_shapefile.shp")]

2) Tìm điểm cuối của các dòng ( làm thế nào để có được điểm cuối của một đa tuyến? ):

endpts = [(Point(list(line.coords)[0]), Point(list(line.coords)[-1])) for line  in lines]
# flatten the resulting list to a simple list of points
endpts= [pt for sublist in endpts  for pt in sublist] 

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

3) Tính toán các giao điểm (lặp qua các cặp hình học trong lớp với mô đun itertools ). Kết quả của một số giao điểm là MultiPoints và chúng tôi muốn có một danh sách các điểm:

import itertools
inters = []
for line1,line2 in  itertools.combinations(lines, 2):
  if  line1.intersects(line2):
    inter = line1.intersection(line2)
    if "Point" == inter.type:
        inters.append(inter)
    elif "MultiPoint" == inter.type:
        inters.extend([pt for pt in inter])
    elif "MultiLineString" == inter.type:
        multiLine = [line for line in inter]
        first_coords = multiLine[0].coords[0]
        last_coords = multiLine[len(multiLine)-1].coords[1]
        inters.append(Point(first_coords[0], first_coords[1]))
        inters.append(Point(last_coords[0], last_coords[1]))
    elif "GeometryCollection" == inter.type:
        for geom in inter:
            if "Point" == geom.type:
                inters.append(geom)
            elif "MultiPoint" == geom.type:
                inters.extend([pt for pt in geom])
            elif "MultiLineString" == geom.type:
                multiLine = [line for line in geom]
                first_coords = multiLine[0].coords[0]
                last_coords = multiLine[len(multiLine)-1].coords[1]
                inters.append(Point(first_coords[0], first_coords[1]))
                inters.append(Point(last_coords[0], last_coords[1]))

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

4) Loại bỏ trùng lặp giữa điểm cuối và điểm giao nhau (như bạn có thể thấy trong hình)

result = endpts.extend([pt for pt in inters  if pt not in endpts])

5) Lưu shapefile kết quả

from shapely.geometry import mapping
# schema of the shapefile
schema = {'geometry': 'Point','properties': {'test': 'int'}}
# creation of the shapefile
with fiona.open('result.shp','w','ESRI Shapefile', schema) as output:
    for i, pt in enumerate(result):
        output.write({'geometry':mapping(pt), 'properties':{'test':i}})

Kết quả cuối cùng:

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

Các đoạn đường

Nếu bạn cũng muốn các phân đoạn giữa các nút, bạn cần "planarize" ( Đồ thị phẳng , không có cạnh nào giao nhau) shapefile của bạn. Điều này có thể được thực hiện bởi các unary_union chức năng của kiểu dáng cân đối

from shapely.ops import unary_union
graph = unary_union(lines)

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


Cảm ơn @gene đã trả lời chi tiết. Tôi đã chỉnh sửa phần mà nó đi qua các loại geometrie khác nhau. Trong trường hợp của tôi, giao lộ cũng trả về các dòng, hình học, v.v. Nhưng điều này phụ thuộc vào dữ liệu đầu vào. Tôi đã không đủ rõ ràng trong câu hỏi của tôi.
ustroetz

Câu trả lời chính xác. Tôi có thể thêm rằng không cần thiết phải làm như sau: result = endpts.extend([pt for pt in inters if pt not in endpts])vì có vẻ như .extendphương thức sửa đổi endpt. Trong trường hợp của tôi result = Nonesau hoạt động đó. Nó endptskết thúc có chứa kết quả giải quyết
user32882
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.