Weld segmen garis individual menjadi satu LineString menggunakan Shapely


13

Saya menggunakan Shapely in python dan saya diberi MultiLineStringdengan banyak Linestringobjek. Saya dapat menjamin bahwa semua LineStringobjek adalah garis-garis sederhana dengan hanya 2 simpul dan mereka semua adalah bagian dari satu garis tunggal (tanpa cabang).

Saya ingin "menghubungkan-titik" dan membuat satu LineString. Apakah saya perlu menulis metode pengelasan rekursif untuk ini atau apakah ada cara yang lebih cepat?

Jawaban:


20

Anda dapat menggunakan shapely's ops.linemergeuntuk mencapai hal ini:

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

Bagaimana saya bisa tahu linestring mana yang digabung? Saya ingin menerima daftar seperti: merger = [[line_a, line_b], [line_c]]
james

Anda bisa mengulang daftar garis individu Anda dan memeriksa apakah baris baru digabungkan garis contains()individu. Yang tidak mengandung tidak akan digabung. mis. merged_line.contains(line_a)yang akan mengembalikan boolean TrueatauFalse
songololo

Terima kasih banyak. Bagaimana Anda memeriksa apakah baris tersebut ada di merged_lines?
james

1
ah, saya tidak mengerti bahwa ".contains (line_a)" adalah fungsi yang sudah ditulis sebelumnya. sempurna. Terima kasih banyak !
james

1
maaf, mengganggu Anda lagi ... tetapi apakah Anda tahu siapa yang harus menggabungkan garis yang "dekat" (dalam jarak maksimum tertentu dari satu sama lain)? Saya bertanya karena saya melihat banyak baris yang harus digabung, tetapi karena ada celah kecil di antara mereka, mereka tidak bergabung.
james

2

Saya pikir Anda bisa melakukannya dengan Shapely menggunakan metode shapely.ops.linemerge ().

Sepertinya bisa mengambil daftar baris sebagai input dan menggabungkannya. Saya menggunakan metode 'polygonize' sebelumnya dan itu mengambil daftar garis.

Lihatlah dokumen di sini: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge


1
Apakah Anda tahu cara menggabungkan garis yang "dekat" (dalam jarak maksimum tertentu dari satu sama lain)?
james

polygonize_full bekerja agak lebih baik, tapi saya mendapat beberapa struktur data yang aneh
danuker

1

shapely.ops.linemerge()gagal untuk beberapa baris saya jadi saya harus melakukannya secara manual. Tampaknya gagal untuk garis yang "kembali" ke dirinya sendiri, yaitu, melewati titik yang sama lebih dari sekali. Untuk kasus saya, saya tahu bahwa garis berada dalam urutan yang benar sehingga mudah untuk menulis fungsi kecil untuk menggabungkannya.

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)

Semoga ini bisa membantu seseorang


0

shapely.ops.linemergeberfungsi jika garis bersebelahan ("tips" bertepatan dengan "ekor" garis konstituen), tetapi jika mereka tidak bersebelahan (jika ada celah antara ujung dan ekor) ia mengembalikan MultiLineString lainnya. Jika garis konstituen Anda tertata dengan baik (dengan satu garis berakhir di dekat awal baris berikutnya) tetapi memiliki celah tip-to-tail, Anda dapat mengekstrak koordinat dan menggunakannya membuat garis sederhana baru. Pendekatan ini juga berfungsi untuk multi-garis yang dibuat dari subline yang lebih kompleks (yaitu subline dengan lebih dari dua poin).

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])
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.