Spawaj pojedyncze segmenty linii w jeden LineString za pomocą Shapely
13
Używam Shapely w pythonie i dostaję MultiLineStringmnóstwo Linestringobiektów. Mogę zagwarantować, że wszystkie LineStringobiekty są prostymi liniami z tylko 2 wierzchołkami i że wszystkie są częścią jednej pojedynczej linii (bez gałęzi).
Chcę „połączyć kropki” i stworzyć singiel LineString. Czy muszę do tego napisać metodę spawania rekurencyjnego, czy jest szybszy sposób?
Można użyć shapely„s ops.linemergedo osiągnięcia tego celu:
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))
Skąd mam wiedzieć, który łącznik został scalony? Chcę otrzymać listę w rodzaju: scalony = [[linia_a, linia_b], [linia_c]]
James
Możesz przeglądać listę poszczególnych linii i sprawdzać, czy nowa linia scalona contains()łączy poszczególne linie. Te niezawarte nie zostałyby połączone. np. merged_line.contains(line_a)który zwróciłby wartość logiczną TruelubFalse
songololo
wielkie dzięki. Jak sprawdzisz, czy linia jest zawarta w połączonych liniach?
James
1
ah, nie zrozumiałem, że „.contains (line_a)” to wcześniej napisana funkcja. doskonały. Wielkie dzięki !
James
1
przepraszam, że przeszkadzam jeszcze raz ... ale czy wiesz, kto połączyć linie, które są „blisko” (w pewnej maksymalnej odległości od siebie)? Pytam, ponieważ widzę wiele linii, które powinny zostać scalone, ale ze względu na małą przerwę między nimi, nie są one scalone.
James
2
Myślę, że można to zrobić za pomocą Shapely przy użyciu metody shapely.ops.linemerge ().
Wygląda na to, że może pobierać listę linii jako dane wejściowe i scalać je. Wcześniej użyłem metody „poligonizacji” i zajmuje ona listę linii.
Czy wiesz, jak scalać linie, które są „blisko” (w pewnej maksymalnej odległości od siebie)?
James
polygonize_full działa nieco lepiej, ale mam jakieś dziwne datastructures W efekcie
danuker
1
shapely.ops.linemerge()nie powiodło się dla niektórych moich linii, więc musiałem to zrobić ręcznie. Wydaje się, że zawodzi w przypadku linii, które „wróciły” do siebie, tzn. Przechodzą przez ten sam punkt więcej niż raz. W moim przypadku wiem, że wiersze są we właściwej kolejności, więc łatwo było napisać małą funkcję do ich scalenia.
from shapely.geometry importLineStringfrom typing importListdef merge_lines(lines:List[LineString])->LineString:
last =None
points =[]for line in merged_line:
current = line.coords[0]if last isNone:
points.extend(line.coords)else:if last == current:
points.extend(line.coords[1:])else:print('Skipping to merge {} {}'.format(last, current))returnNone
last = line.coords[-1]returnLineString(points)
shapely.ops.linemergedziała, jeśli linie są ciągłe („końcówki” pokrywają się z „ogonami” linii składowych), ale jeśli nie są one ciągłe (jeśli istnieje przerwa między końcami i ogonami), zwraca kolejną MultiLineString. Jeśli twoje linie składowe są dobrze uporządkowane (z jedną linią kończącą się w pobliżu początku następnej linii), ale mają odstęp od czubka do końca, możesz wyodrębnić współrzędne i użyć ich, aby utworzyć nową prostą linię. To podejście działa również w przypadku wielu linii wykonanych z bardziej złożonych podlinii (tj. Podlini z więcej niż dwoma punktami).
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])
contains()
łączy poszczególne linie. Te niezawarte nie zostałyby połączone. np.merged_line.contains(line_a)
który zwróciłby wartość logicznąTrue
lubFalse
Myślę, że można to zrobić za pomocą Shapely przy użyciu metody shapely.ops.linemerge ().
Wygląda na to, że może pobierać listę linii jako dane wejściowe i scalać je. Wcześniej użyłem metody „poligonizacji” i zajmuje ona listę linii.
Spójrz na dokument tutaj: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge
źródło
shapely.ops.linemerge()
nie powiodło się dla niektórych moich linii, więc musiałem to zrobić ręcznie. Wydaje się, że zawodzi w przypadku linii, które „wróciły” do siebie, tzn. Przechodzą przez ten sam punkt więcej niż raz. W moim przypadku wiem, że wiersze są we właściwej kolejności, więc łatwo było napisać małą funkcję do ich scalenia.Mam nadzieję, że to komuś pomoże
źródło
shapely.ops.linemerge
działa, jeśli linie są ciągłe („końcówki” pokrywają się z „ogonami” linii składowych), ale jeśli nie są one ciągłe (jeśli istnieje przerwa między końcami i ogonami), zwraca kolejną MultiLineString. Jeśli twoje linie składowe są dobrze uporządkowane (z jedną linią kończącą się w pobliżu początku następnej linii), ale mają odstęp od czubka do końca, możesz wyodrębnić współrzędne i użyć ich, aby utworzyć nową prostą linię. To podejście działa również w przypadku wielu linii wykonanych z bardziej złożonych podlinii (tj. Podlini z więcej niż dwoma punktami).źródło