Shapelyを使用して個々のラインセグメントを1つのLineStringに溶接します。


13

私はpythonでShapelyを使用していMultiLineStringて、たくさんのLinestringオブジェクトを与えられています。すべてのLineStringオブジェクトが2つの頂点のみを持つ単純なラインであり、それらがすべて1つの単一ラインの一部であること(ブランチはないこと)を保証できます。

「ドットをつなげて」単一のを作成しますLineString。このために再帰溶接方法を書く必要がありますか、それとももっと速い方法がありますか?

回答:


20

あなたは使用することができるshapelyのが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]]
ジェームズ

個々の行のリストをループして、新しいマージされた行contains()が個々の行かどうかを確認できます。含まれていないものはマージされません。たとえばmerged_line.contains(line_a)、ブール値を返すTrueか、またはFalse
songololo

どうもありがとう。行がmerged_linesに含まれているかどうかをどのように確認しますか?
ジェームズ

1
ああ、「。contains(line_a)」が事前に作成された関数であることを理解していませんでした。完璧です。どうもありがとう !
ジェームズ

1
申し訳ありませんが、再度迷惑をかけます...しかし、「近い」(互いから特定の最大距離内にある)行をマージする人を知っていますか?マージする必要がある多くの行が表示されているので、私は尋ねていますが、それらの間の小さなギャブのために、それらはマージされません。
ジェームズ

2

shapely.ops.linemerge()メソッドを使用してShapelyでできると思います。

入力として行のリストを取り、それらをマージできるようです。前に 'polygonize'メソッドを使用しましたが、行のリストを取得します。

こちらのドキュメントをご覧ください:http : //toblerity.org/shapely/manual.html#shapely.ops.linemerge


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)

それが誰かを助けることを願って


0

shapely.ops.linemerge線が連続している場合(「先端」が構成線の「尾」と一致する場合)に機能しますが、非連続の場合(先端と尾の間にギャップがある場合)、別のMultiLineStringを返します。構成線が適切に順序付けられている場合(1行が次の行の開始近くで終わる)、先端と後部のギャップがある場合、座標を抽出し、それらを使用して新しい単純な線を作成できます。このアプローチは、より複雑なサブライン(つまり、3つ以上のポイントを持つサブライン)で構成されるマルチラインでも機能します。

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])
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.