Intersezione di linee per ottenere incroci usando Python con QGIS?


10

Ho una serie di linee che rappresentano le linee di autobus. Alcune linee si sovrappongono e prendono le stesse strade.

inserisci qui la descrizione dell'immagine

Sono in grado di estrarre i nodi. inserisci qui la descrizione dell'immagine

Tuttavia sono interessato a estrarre solo incroci come questo: inserisci qui la descrizione dell'immagine

Come posso fare questo? Sto cercando modi con QGIS o Python.

Ho provato il metodo di intersezione da GDAL Python ma questo sostanzialmente mi restituisce solo i vertici.

Il metodo Intersezioni linea di QGIS mi restituisce gli incroci se due linee si incrociano. Tuttavia, nel caso in cui due linee di autobus finiscano per gran parte del loro percorso sulla stessa strada, non mi dà il punto in cui si fondono.


Hai provato lo strumento di intersezione di linee in QGIS: Strumento di analisi vettoriale> Intersezioni di linee ... Non ti darà la fine e i nodi iniziali di una linea, ma tutte le intersezioni.
Jakob,

Sì, ho scritto di questo nella domanda.
ustroetz,

Non sono chiaro su cosa stai chiedendo, in parte perché tutte le linee sono simboleggiate allo stesso modo nelle tue immagini - Non posso distinguere percorsi diversi per capire quali nodi stai guardando o perché ci sono così tanti nel seconda immagine. I percorsi sono coincidenti su strade? Sono tutti segmenti di linea a due punti o polilinee continue? Prendo atto che il comportamento che descrivi è lo stesso dello strumento Intersezione di ArcGIS : le linee / linee con l'output delle linee ti danno la sovrapposizione, ma le linee / linee con l'output dei punti danno solo incroci.
Chris W,

Sulla base di ciò, per ottenere quello che penso tu voglia, potresti dover usare entrambi i metodi. Prendi gli incroci (linea / linea = punto) e quindi ottieni le sovrapposizioni (linea / linea = linea) ed estrai i nodi di inizio / fine per quelle linee di sovrapposizione. Questi dovrebbero essere tutti i punti / nodi che stai cercando.
Chris W,

Risposte:


20

I nodi:

Volete due cose, i punti finali delle polilinee (senza nodi intermedi) e i punti di intersezione. Vi è un ulteriore problema, alcuni punti finali delle polilinee sono anche punti di intersezione:

inserisci qui la descrizione dell'immagine

Una soluzione è usare Python e i moduli Shapely e Fiona

1) Leggi lo shapefile:

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

2) Trova i punti finali delle linee ( come si ottengono i punti finali di una polilinea? ):

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] 

inserisci qui la descrizione dell'immagine

3) Calcola le intersezioni (iterando attraverso coppie di geometrie nel layer con il modulo itertools ). Il risultato di alcune intersezioni sono punti multipli e vogliamo un elenco di punti:

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

inserisci qui la descrizione dell'immagine

4) Elimina i duplicati tra i punti finali e i punti di intersezione (come puoi vedere nelle figure)

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

5) Salvare lo shapefile risultante

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

Risultato finale:

inserisci qui la descrizione dell'immagine

I segmenti di linea

Se vuoi anche i segmenti tra i nodi, devi "planarizzare" ( grafico planare , nessun bordo incrociato) il tuo shapefile. Questo può essere fatto dalla funzione unary_union di Shapely

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

inserisci qui la descrizione dell'immagine


Grazie @gene per la risposta dettagliata. Ho modificato la parte in cui passa sopra i diversi tipi di geometrie. Nel mio caso, l'intersezione restituisce anche linee, geometrie raccolte, ecc. Ma questo dipende dai dati di input. Non ero abbastanza chiaro nella mia domanda.
ustroetz,

Bella risposta. Potrei aggiungere che non è necessario eseguire le seguenti operazioni: result = endpts.extend([pt for pt in inters if pt not in endpts])poiché sembra che il .extendmetodo modifichi endpt. Nel mio caso result = Nonedopo quell'operazione. È quello endptsche finisce per contenere il risultato sett
user32882
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.