Сварка отдельных сегментов линии в одну LineString с помощью Shapely

13

Я использую Shapely в Python, и мне дают MultiLineStringс кучей Linestringобъектов. Я могу гарантировать, что все LineStringобъекты являются простыми линиями, имеющими только 2 вершины, и что все они являются частью одной отдельной линии (без ветвей).

Я хочу «соединить точки» и создать сингл LineString. Мне нужно написать метод рекурсивной сварки для этого или есть более быстрый способ?

Raychaser
источник

Ответы:

20

Вы можете использовать shapely«S ops.linemergeдля достижения этой цели :

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))
Сонгололо
источник
Как я могу узнать, какая строка была объединена? Я хочу получить список вроде: merged = [[line_a, line_b], [line_c]]
james
Вы можете перебрать список ваших отдельных строк и проверить, соответствуют ли новые объединенные строки contains()отдельным линиям. Те, которые не содержались, не были бы объединены. например, merged_line.contains(line_a)который будет возвращать логическое значение TrueилиFalse
songololo
большое спасибо. Как проверить, содержится ли строка в merged_lines?
Джеймс
1
ах, я не понял, что ".contains (line_a)" - это заранее написанная функция. идеально. Большое спасибо !
Джеймс
1
извините, что беспокою вас снова ... но знаете ли вы, кто объединяет линии, которые "близки" (в пределах определенного максимального расстояния друг от друга)? Я спрашиваю, потому что я вижу много строк, которые должны быть объединены, но из-за небольшого разрыва между ними они не объединены.
Джеймс
2

Я думаю, что вы можете сделать это с помощью Shapely, используя метод shapely.ops.linemerge ().

Похоже, что он может принять список строк в качестве входных данных и объединить их. Я использовал метод 'polygonize' ранее, и он принимает список строк.

Посмотрите документ здесь: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge

TurboGraphxBeige
источник
1
Вы знаете, как объединять линии, которые «близки» (в пределах определенного максимального расстояния друг от друга)?
Джеймс
polygonize_full работает несколько лучше, но в результате я получил несколько странных структур данных
danuker
1

shapely.ops.linemerge()не удалось для некоторых из моих строк, поэтому мне пришлось сделать это вручную. Кажется, что он не работает для линий, которые «вернулись» к себе, т. Е. Проходят одну и ту же точку более одного раза. Для моего случая я знаю, что строки расположены в правильном порядке, поэтому было легко написать небольшую функцию для их объединения.

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)

Надеюсь, это поможет кому-то

oflyt
источник
0

shapely.ops.linemergeработает, если линии являются смежными («подсказки» совпадают с «хвостами» составляющих линий), но если они не являются смежными (если есть промежуток между кончиками и хвостами), он возвращает другую MultiLineString. Если ваши составляющие линии хорошо упорядочены (с одной линией, заканчивающейся рядом с началом следующей строки), но имеют разрыв от кончика до хвоста, вы можете извлечь координаты и использовать их для создания новой простой линии. Этот подход также работает для многолинейных линий, состоящих из более сложных сублиней (т. Е. Сублиней, содержащих более двух точек).

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])
Патман
источник