Saldare singoli segmenti di linea in una LineString usando Shapely


13

Sto usando Shapely in Python e mi viene dato un MultiLineStringcon un mucchio di Linestringoggetti. Posso garantire che tutti gli LineStringoggetti sono linee semplici con solo 2 vertici e che fanno tutti parte di un'unica linea (senza rami).

Voglio "collegare i punti" e creare un singolo LineString. Devo scrivere un metodo di saldatura ricorsivo per questo o c'è un modo più veloce?

Risposte:


20

Puoi usare shapely's ops.linemergeper raggiungere questo obiettivo:

from shapely import geometry, ops

# create three lines
line_a = geometry.LineString([[0,0], [1,1]])
line_b = geometry.LineString([[1,1], [1,0]])
line_c = geometry.LineString([[1,0], [2,0]])

# combine them into a multi-linestring
multi_line = geometry.MultiLineString([line_a, line_b, line_c])
print(multi_line)  # prints MULTILINESTRING ((0 0, 1 1), (1 1, 2 2), (2 2, 3 3))

# you can now merge the lines
merged_line = ops.linemerge(multi_line)
print(merged_line)  # prints LINESTRING (0 0, 1 1, 2 2, 3 3)

# if your lines aren't contiguous
line_a = geometry.LineString([[0,0], [1,1]])
line_b = geometry.LineString([[1,1], [1,0]])
line_c = geometry.LineString([[2,0], [3,0]])

# combine them into a multi-linestring
multi_line = geometry.MultiLineString([line_a, line_b, line_c])
print(multi_line)  # prints MULTILINESTRING ((0 0, 1 1), (1 1, 1 0), (2 0, 3 0))

# note that it will now merge only the contiguous portions into a component of a new multi-linestring
merged_line = ops.linemerge(multi_line)
print(merged_line)  # prints MULTILINESTRING ((0 0, 1 1, 1 0), (2 0, 3 0))

Come posso sapere quale stringa lineare è stata unita? Voglio ricevere un elenco come: merged = [[line_a, line_b], [line_c]]
james

È possibile scorrere un elenco di singole linee e verificare se la nuova linea unita è contains()singola. Quelle non contenute non sarebbero state unite. ad es. merged_line.contains(line_a)che restituirebbe un booleano TrueoFalse
songololo il

molte grazie. Come si controlla se la riga è contenuta in merged_lines?
Giacomo

1
ah, non ho capito che ".contains (line_a)" era una funzione pre-scritta. Perfetto. Molte grazie !
james

1
scusa, di disturbarti di nuovo ... ma sai chi unire le linee che sono "vicine" (entro una certa distanza massima l'una dall'altra)? Lo sto chiedendo perché sto vedendo molte righe che dovrebbero essere unite, ma a causa di una piccola gabbia tra loro, non vengono unite.
James,

2

Penso che potresti farlo con Shapely usando il metodo shapely.ops.linemerge ().

Sembra che potrebbe prendere un elenco di righe come input e unirle. Ho usato il metodo 'poligonizza' prima e ci vuole un elenco di righe.

Dai un'occhiata al documento qui: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge


1
Sai unire le linee "vicine" (entro una certa distanza massima l'una dall'altra)?
James,

polygonize_full funziona un po 'meglio, ma di conseguenza ho ottenuto alcune strane strutture di dati
danuker,

1

shapely.ops.linemerge()non è riuscito per alcune delle mie linee, quindi ho dovuto farlo manualmente. Sembra fallire per le linee che "sono tornate" a se stesse, cioè attraversando lo stesso punto più di una volta. Nel mio caso, so che le linee sono nell'ordine corretto, quindi è stato facile scrivere una piccola funzione per unirle.

from shapely.geometry import LineString
from typing import List


def merge_lines(lines: List[LineString]) -> LineString:
    last = None
    points = []
    for line in merged_line:
        current = line.coords[0]

        if last is None:
            points.extend(line.coords)
        else:
            if last == current:
                points.extend(line.coords[1:])
            else:
                print('Skipping to merge {} {}'.format(last, current))
                return None
        last = line.coords[-1]
    return LineString(points)

Spero che aiuti qualcuno


0

shapely.ops.linemergefunziona se le linee sono contigue (le "punte" coincidono con le "code" delle linee costituenti), ma se non sono contigue (se c'è una distanza tra le punte e le code) restituisce un altro MultiLineString. Se le tue linee costituenti sono ben ordinate (con una linea che termina vicino all'inizio della linea successiva) ma hanno un gap tip-to-tail, puoi estrarre le coordinate e usarle per creare una nuova linea semplice. Questo approccio funziona anche per le linee multiple composte da linee secondarie più complesse (ovvero linee secondarie con più di due punti).

import shapely

# Make a MultiLineString to use for the example
inlines = shapely.geometry.MultiLineString(
    [shapely.geometry.LineString([(0,0),(0,0.9)]), 
     shapely.geometry.LineString([(0,1),(1,1)])]
)

# Put the sub-line coordinates into a list of sublists
outcoords = [list(i.coords) for i in inlines]

# Flatten the list of sublists and use it to make a new line
outline = shapely.geometry.LineString([i for sublist in outcoords for i in sublist])
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.