Verschweißen Sie einzelne Liniensegmente mit Shapely zu einer LineString


12

Ich benutze Shapely in Python und bekomme eine MultiLineStringmit ein paar LinestringObjekten. Ich kann garantieren, dass alle LineStringObjekte einfache Linien mit nur 2 Eckpunkten sind und dass sie alle Teil einer einzelnen Linie sind (keine Verzweigungen).

Ich möchte "die Punkte verbinden" und eine einzelne erstellen LineString. Muss ich dafür eine rekursive Schweißmethode schreiben oder gibt es einen schnelleren Weg?

Antworten:


19

Sie können shapely's verwenden ops.linemerge, um dies zu erreichen:

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

Woher kann ich wissen, welche Linienfolge zusammengeführt wurde? Ich möchte eine Liste wie folgt erhalten: merged = [[line_a, line_b], [line_c]]
James

Sie können eine Liste Ihrer einzelnen Zeilen durchlaufen und prüfen, ob die neue zusammengeführte Zeile contains()die einzelnen Zeilen enthält. Die nicht enthaltenen wären nicht zusammengeführt worden. zB merged_line.contains(line_a)was einen booleschen TrueoderFalse
songololo

Vielen Dank. Wie prüft man, ob die Zeile in den merged_lines enthalten ist?
James

1
ah, ich habe nicht verstanden, dass ".contains (line_a)" eine vorab geschriebene Funktion ist. perfekt. Vielen Dank !
James

1
Entschuldigung, um Sie wieder zu stören ... aber wissen Sie, wen Sie Linien zusammenführen sollen, die "nah" sind (innerhalb eines bestimmten maximalen Abstands voneinander)? Ich frage, weil ich viele Zeilen sehe, die zusammengeführt werden sollten, aber aufgrund einer kleinen Unterbrechung zwischen ihnen werden sie nicht zusammengeführt.
James

2

Ich denke, Sie könnten es mit Shapely tun, indem Sie die shapely.ops.linemerge () -Methode verwenden.

Es sieht so aus, als könnte eine Liste von Zeilen als Eingabe verwendet und zusammengeführt werden. Ich habe zuvor die Methode 'polygonize' verwendet und es wird eine Liste von Zeilen benötigt.

Schauen Sie sich das Dokument hier an: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge


1
Wissen Sie, wie Sie Linien zusammenführen, die "nah" sind (innerhalb eines bestimmten maximalen Abstands voneinander)?
James

polygonize_full funktioniert etwas besser, aber ich habe einige seltsame Datenstrukturen als Ergebnis
Danuker

1

shapely.ops.linemerge()Bei einigen meiner Leitungen ist ein Fehler aufgetreten, sodass ich es manuell ausführen musste. Es scheint für die Linien, die zu sich selbst "zurückgekehrt" sind, zu scheitern, dh den gleichen Punkt mehr als einmal zu durchlaufen. In meinem Fall weiß ich, dass die Zeilen in der richtigen Reihenfolge sind, sodass es einfach war, eine kleine Funktion zu schreiben, um sie zusammenzuführen.

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)

Hoffe es hilft jemandem


0

shapely.ops.linemergeFunktioniert, wenn die Linien zusammenhängend sind ("Tips" stimmen mit den "Tails" der konstituierenden Linien überein), aber wenn sie nicht zusammenhängend sind (wenn es eine Lücke zwischen den Tips und Tails gibt), wird ein weiterer MultiLineString zurückgegeben. Wenn Ihre konstituierenden Linien geordnet sind (wobei eine Linie nahe dem Beginn der nächsten Linie endet), aber eine Lücke von Spitze zu Ende aufweist, können Sie die Koordinaten extrahieren und daraus eine neue einfache Linie erstellen. Dieser Ansatz funktioniert auch für Mehrfachlinien, die aus komplexeren Unterlinien bestehen (dh Unterlinien mit mehr als zwei Punkten).

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])
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.