Shapely kullanarak ayrı satır segmentlerini tek bir LineString'e kaynaklayın


13

Shapely'yi python'da kullanıyorum ve bana MultiLineStringbir sürü Linestringnesne verildi. Tüm LineStringnesnelerin sadece 2 köşeli basit çizgiler olduğunu ve hepsinin tek bir çizginin parçası olduğunu (dallar olmadan) garanti edebilirim .

"Noktaları birleştirmek" ve bir tane oluşturmak istiyorum LineString. Bunun için özyinelemeli bir kaynak yöntemi yazmam gerekir mi yoksa daha hızlı bir yol var mı?

Yanıtlar:


20

Bunu yapmak için shapely'leri kullanabilirsiniz 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))

Hangi köpüğün birleştirildiğini nasıl bilebilirim? Şunun gibi bir liste almak istiyorum: merged = [[line_a, line_b], [line_c]]
james

Tek tek satırlarınızın bir listesini gözden geçirebilir ve yeni birleştirilmiş satırın contains()tek tek satırları olup olmadığını kontrol edebilirsiniz . İçermeyenler birleştirilmezdi. örneğin merged_line.contains(line_a)bir boolean döndürür TrueveyaFalse
songololo

çok teşekkürler. Satırın merged_lines'ta olup olmadığını nasıl kontrol edersiniz?
james

1
ah, ".contains (line_a)" nın önceden yazılmış bir işlev olduğunu anlamadım. mükemmel. Çok teşekkürler !
james

1
özür dilerim, seni tekrar rahatsız etmek ... ama kim "yakın" (birbirinden belirli bir maksimum mesafe içinde) hatları birleştirmek biliyor musunuz? Soruyorum çünkü birleştirilmesi gereken birçok çizgi görüyorum, ancak aralarındaki küçük bir gab nedeniyle, birleştirilmiyorlar.
james

2

Shapely ile shapely.ops.linemerge () yöntemini kullanarak yapabileceğinizi düşünüyorum.

Görünüşe göre satırların bir listesini girdi olarak alabilir ve birleştirebilir. Daha önce 'poligonize' yöntemini kullandım ve satırların bir listesini alır.

Buradaki dokümana bir göz atın: http://toblerity.org/shapely/manual.html#shapely.ops.linemerge


1
"Yakın" (birbirinden belirli bir maksimum mesafe dahilinde) olan çizgileri nasıl birleştireceğinizi biliyor musunuz?
james

polygonize_full biraz daha iyi çalışıyor, ancak sonuç olarak bazı garip
veri yapıları

1

shapely.ops.linemerge()bazı satırları için başarısız oldu, bu yüzden elle yapmak zorunda kaldı. Kendine "geri dönen" hatlar için başarısız görünüyor, yani aynı noktadan birden fazla geçiyor. Benim durumum için, satırların doğru sırada olduğunu biliyorum, bu yüzden onları birleştirmek için küçük bir işlev yazmak kolaydı.

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)

Umarım birine yardımcı olur


0

shapely.ops.linemergeçizgiler bitişikse ("uçlar" kurucu çizgilerin "kuyruklarıyla" çakışırsa), ancak bitişik olmadıkları takdirde (uçlar ve kuyruklar arasında boşluk varsa) başka bir MultiLineString döndürür. Kurucu çizgileriniz iyi sıralanmışsa (bir satır bir sonraki satırın başlangıcına yakın olacak şekilde) ancak uçtan uca bir boşluğa sahipse, koordinatları çıkarabilir ve bunları yeni bir basit çizgi oluşturabilirsiniz. Bu yaklaşım aynı zamanda daha karmaşık alt çizgilerden (yani ikiden fazla noktası olan alt çizgiler) yapılan çok satırlar için de geçerlidir.

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])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.