Suelde segmentos de línea individuales en un LineString usando Shapely
13
Estoy usando Shapely en python y me dan un MultiLineStringcon un montón de Linestringobjetos. Puedo garantizar que todos los LineStringobjetos son líneas simples con solo 2 vértices y que todos forman parte de una sola línea (sin ramas).
Quiero "conectar los puntos" y crear uno solo LineString. ¿Necesito escribir un método de soldadura recursiva para esto o hay una forma más rápida?
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))
¿Cómo puedo saber qué cadena lineal se fusionó? Quiero recibir una lista como: fusionada = [[line_a, line_b], [line_c]]
james
Puede recorrer una lista de sus líneas individuales y verificar si la nueva línea combinada contains()las líneas individuales. Los que no están contenidos no se habrían fusionado. por ejemplo, merged_line.contains(line_a)que devolvería un booleano TrueoFalse
songololo
muchas gracias. ¿Cómo verifica si la línea está contenida en merged_lines?
james
1
ah, no entendí que ".contains (line_a)" era una función preescrita. Perfecto. Muchas gracias !
James
1
lo siento, para molestarlo nuevamente ... pero ¿sabe a quién fusionar las líneas que están "cerca" (dentro de una cierta distancia máxima entre sí)? Pregunto porque veo muchas líneas que deberían fusionarse, pero debido a una pequeña separación entre ellas, no se fusionan.
James
2
Creo que podrías hacerlo con Shapely usando el método shapely.ops.linemerge ().
Parece que podría tomar una lista de líneas como entrada y fusionarlas. Utilicé el método 'polygonize' antes y toma una lista de líneas.
¿Sabes cómo combinar líneas que están "cerca" (dentro de una cierta distancia máxima entre sí)?
James
polygonize_full funciona algo mejor, pero como resultado obtuve algunas estructuras de datos extrañas
danuker
1
shapely.ops.linemerge()falló en algunas de mis líneas, así que tuve que hacerlo manualmente. Parece fallar para las líneas que "regresaron" a sí mismas, es decir, pasando por el mismo punto más de una vez. Para mi caso, sé que las líneas están en el orden correcto, por lo que fue fácil escribir una pequeña función para fusionarlas.
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.linemergefunciona si las líneas son contiguas (las "puntas" coinciden con las "colas" de las líneas constituyentes), pero si no son contiguas (si hay un espacio entre las puntas y las colas), devuelve otra MultiLineString. Si sus líneas constituyentes están bien ordenadas (con una línea que termina cerca del comienzo de la línea siguiente) pero tienen un espacio de punta a cola, puede extraer las coordenadas y usarlas para hacer una nueva línea simple. Este enfoque también funciona para líneas múltiples hechas de sublíneas más complejas (es decir, sublíneas con más de dos puntos).
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()
las líneas individuales. Los que no están contenidos no se habrían fusionado. por ejemplo,merged_line.contains(line_a)
que devolvería un booleanoTrue
oFalse
Creo que podrías hacerlo con Shapely usando el método shapely.ops.linemerge ().
Parece que podría tomar una lista de líneas como entrada y fusionarlas. Utilicé el método 'polygonize' antes y toma una lista de líneas.
Eche un vistazo al documento aquí: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge
fuente
shapely.ops.linemerge()
falló en algunas de mis líneas, así que tuve que hacerlo manualmente. Parece fallar para las líneas que "regresaron" a sí mismas, es decir, pasando por el mismo punto más de una vez. Para mi caso, sé que las líneas están en el orden correcto, por lo que fue fácil escribir una pequeña función para fusionarlas.Espero que ayude a alguien
fuente
shapely.ops.linemerge
funciona si las líneas son contiguas (las "puntas" coinciden con las "colas" de las líneas constituyentes), pero si no son contiguas (si hay un espacio entre las puntas y las colas), devuelve otra MultiLineString. Si sus líneas constituyentes están bien ordenadas (con una línea que termina cerca del comienzo de la línea siguiente) pero tienen un espacio de punta a cola, puede extraer las coordenadas y usarlas para hacer una nueva línea simple. Este enfoque también funciona para líneas múltiples hechas de sublíneas más complejas (es decir, sublíneas con más de dos puntos).fuente