Перетинаються лінії, щоб отримати перехрестя за допомогою Python з QGIS?


10

У мене є набір ліній, що представляють автобусні лінії. Деякі лінії перекриваються і беруть однакові дороги.

введіть тут опис зображення

Я вмію витягувати вузли. введіть тут опис зображення

Однак мені цікаво витягнути тільки такі переправи: введіть тут опис зображення

Як я можу це зробити? Я шукаю шляхи з QGIS або Python.

Я спробував метод перетину від GDAL Python, але це, в основному, повертає мені лише вершини.

Метод перетину ліній від QGIS повертає мені перехрестя, якщо дві лінії перетинаються. Однак у випадку, якщо дві автобусні лінії проходять далеку частину свого маршруту по одній дорозі, це не дає мені вказати, куди вони зливаються.


Ви спробували інструмент перетину ліній в QGIS: Інструмент векторного аналізу> Перехрестя ліній ... Він не дасть вам кінцевих та початкових вузлів лінії, але всіх перетинів.
Якоб

Так, я писав про це у запитанні.
ustroetz

Мені незрозуміло, про що ви запитуєте, частково тому, що всі лінії символізуються однаково на ваших зображеннях - я не можу розрізняти різні маршрути, крім того, щоб зрозуміти, які вузли ви дивитесь, або чому їх так багато в друге зображення. Чи збігаються маршрути на дорогах? Чи всі вони є двоточковими відрізками ліній чи суцільними полілініями? Зауважу, поведінка, яку ви описуєте, така ж, як інструмент «Перетинання» ArcGIS - лінії / лінії з виходом ліній дають вам перекриття, але лінії / лінії з точковим виходом дають лише перехрестя.
Кріс Ш

Виходячи з цього, щоб отримати те, що я думаю, ви хочете, вам, можливо, доведеться використовувати обидва методи. Отримайте перехрестя (лінія / лінія = точка), а потім отримайте перекриття (лінія / лінія = лінія) та витягніть вузли початку / кінця для цих ліній, що перекриваються. Це повинні бути всі точки / вузли, які ви шукаєте.
Chris W

Відповіді:


21

Вузли:

Вам потрібно дві речі, кінцеві точки поліліній (без проміжних вузлів) та точки перетину. Є додаткова проблема, деякі точки поліліній також є точками перетину:

введіть тут опис зображення

Рішенням є використання Python та модулів Shapely та Fiona

1) Прочитайте файл форми:

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

2) Знайдіть кінцеві точки ліній ( як можна було б отримати кінцеві точки полілінії? ):

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] 

введіть тут опис зображення

3) Обчисліть перетини (ітерація через пари геометрій у шарі за допомогою модуля itertools ). Результатом деяких перетинів є MultiPoints, і ми хочемо список точок:

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

введіть тут опис зображення

4) Усуньте дублікати між кінцевими точками та точками перетину (як ви бачите на малюнках)

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

5) Збережіть отриманий файл форми

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

Кінцевий результат:

введіть тут опис зображення

Відрізки рядків

Якщо ви також хочете відрізки між вузлами, вам потрібно "планувати" ( Планарний графік , без ребер не перетинаються один з одним) свій файл форми. Це можна зробити за допомогою функції unary_union Shapely

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

введіть тут опис зображення


Дякую @gene за детальну відповідь. Я відредагував частину, де вона надходить для різних типів геометрії. У моєму випадку перетин також повертає лінії, геометричніколекції тощо. Але це залежить від вхідних даних. Мені було недостатньо зрозуміло в моєму питанні.
ustroetz

Чудова відповідь. Можу додати, що робити це не потрібно: result = endpts.extend([pt for pt in inters if pt not in endpts])оскільки, здається, .extendметод змінюється endpt. У моєму випадку result = Noneпісля цієї операції. Саме в endptsкінцевому підсумку міститься результат
врегулювання
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.