Hàn các phân đoạn dòng riêng lẻ vào một LineString bằng Shapely


12

Tôi đang sử dụng Shapely trong python và tôi được tặng MultiLineStringmột loạt các Linestringđối tượng. Tôi có thể đảm bảo rằng tất cả các LineStringđối tượng là các dòng đơn giản chỉ có 2 đỉnh và chúng đều là một phần của một dòng duy nhất (không có nhánh).

Tôi muốn "kết nối các dấu chấm" và tạo một cái duy nhất LineString. Tôi có cần phải viết một phương pháp hàn đệ quy cho điều này hay có cách nào nhanh hơn không?

Câu trả lời:


19

Bạn có thể sử dụng shapely's ops.linemergeđể thực hiện điều này:

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

Làm thế nào tôi có thể biết linestring đã được hợp nhất? Tôi muốn nhận một danh sách như: merged = [[line_a, line_b], [line_c]]
james

Bạn có thể lặp qua danh sách các dòng riêng lẻ của mình và kiểm tra xem dòng mới được hợp nhất có phải là các dòng contains()riêng lẻ hay không. Những người không chứa sẽ không được hợp nhất. ví dụ: merged_line.contains(line_a)sẽ trả lại boolean TruehoặcFalse
songololo

cảm ơn rất nhiều. Làm thế nào để bạn kiểm tra nếu dòng được chứa trong merged_lines?
James

1
à, tôi không hiểu rằng ".contains (line_a)" là một hàm được viết sẵn. hoàn hảo. Cảm ơn rất nhiều !
James

1
xin lỗi, làm phiền bạn lần nữa ... nhưng bạn có biết ai là người hợp nhất các dòng "gần" (trong một khoảng cách tối đa nhất định với nhau) không? Tôi đang hỏi bởi vì tôi đang thấy nhiều dòng nên được hợp nhất, nhưng do một lỗ nhỏ giữa chúng, chúng không được hợp nhất.
james

2

Tôi nghĩ bạn có thể làm điều đó với Shapely bằng phương thức shapely.ops.linemerge ().

Có vẻ như nó có thể lấy một danh sách các dòng làm đầu vào và hợp nhất chúng. Tôi đã sử dụng phương pháp 'đa giác' trước đây và nó có một danh sách các dòng.

Hãy xem tài liệu ở đây: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge


1
Bạn có biết cách hợp nhất các dòng "gần" (trong một khoảng cách tối đa nhất định với nhau) không?
James

polygonize_full hoạt động tốt hơn một chút, nhưng kết quả là tôi đã nhận được một số dữ liệu lạ
danuker

1

shapely.ops.linemerge()thất bại đối với một số dòng của tôi vì vậy tôi phải làm bằng tay. Nó dường như thất bại đối với các dòng "trở lại" với chính nó, tức là, đi qua cùng một điểm nhiều hơn một lần. Đối với trường hợp của tôi, tôi biết rằng các dòng theo đúng thứ tự vì vậy thật dễ dàng để viết một hàm nhỏ để hợp nhất chúng.

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)

Hy vọng nó sẽ giúp được ai đó


0

shapely.ops.linemergehoạt động nếu các dòng liền kề nhau ("mẹo" trùng với "đuôi" của các dòng cấu thành), nhưng nếu chúng không liền nhau (nếu có một khoảng cách giữa các mẹo và đuôi) thì nó sẽ trả về MultiLineString khác. Nếu các dòng cấu thành của bạn được sắp xếp hợp lý (với một dòng kết thúc gần đầu dòng tiếp theo) nhưng có khoảng cách từ đầu đến đuôi, bạn có thể trích xuất tọa độ và sử dụng chúng để tạo một dòng đơn giản mới. Cách tiếp cận này cũng hoạt động đối với nhiều dòng được tạo bởi các dòng con phức tạp hơn (tức là các dòng con có nhiều hơn hai điểm).

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])
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.