QGISでPythonを使用して交差する線を交差させますか?


10

バスラインを表す一連のラインがあります。いくつかの線が重なっており、同じ道を進んでいます。

ここに画像の説明を入力してください

ノードを抽出することができます。 ここに画像の説明を入力してください

ただし、このような交差点のみを抽出することに興味があります。 ここに画像の説明を入力してください

これどうやってするの?QGISまたはPythonを使用した方法を探しています。

GDAL Pythonの交差法を試しましたが、基本的には頂点のみが返されます。

QGIS のLine Intersectionsメソッドは、2本の線が交差する場合に交差を返します。ただし、2本のバス路線が同じ道路のルートの一部を進んでいる場合、それらが合流する場所を示すことはできません。


QGISの線交差ツールを試してみましたか:ベクトル分析ツール>線交差...
ヤコブ

ええ、私はこれについて質問で書きました。
ustroetz 2015年

すべての線が画像内で同じようにシンボル化されているため、あなたが何を求めているのかわかりません-どのようなノードを見ているか、なぜ多くのノードが存在するのかを理解するために異なるルートを区別することはできません2番目の画像。ルートは道路上で一致していますか?それらはすべて2点線セグメントですか、それとも連続ポリラインですか?説明した動作はArcGISのIntersectツールと同じであることに注意してください。ラインの出力があるライン/ラインはオーバーラップしますが、ポイント出力のあるライン/ラインは交差のみを提供します。
Chris W

これに基づいて、私が望むと思うものを取得するには、両方の方法を使用する必要があるかもしれません。交差点(line / line = point)を取得してからオーバーラップ(line / line = line)を取得し、それらのオーバーラップラインの開始ノードと終了ノードを抽出します。これらは、探しているすべてのポイント/ノードである必要があります。
Chris W

回答:


19

ノード:

ポリラインの終点(中間ノードなし)と交点の2つが必要です。追加の問題があり、いくつかのポリラインの終点も交点です:

ここに画像の説明を入力してください

解決策は、PythonとモジュールShapelyおよびFionaを使用することです

1)シェープファイルを読み取ります。

from shapely.geometry import Point, shape
import fiona
lines = [shape(line['geometry']) for line in fiona.open("your_shapefile.shp")]

2)線の終点を見つけます(ポリラインの終点はどのように取得しますか?):

endpts = [(Point(list(line.coords)[0]), Point(list(line.coords)[-1])) for line  in lines]
# flatten the resulting list to a simple list of points
endpts= [pt for sublist in endpts  for pt in sublist] 

ここに画像の説明を入力してください

3)交点を計算します(レイヤーのジオメトリのペアをitertoolsモジュールで繰り返します)。一部の交差の結果はマルチポイントであり、ポイントのリストが必要です。

import itertools
inters = []
for line1,line2 in  itertools.combinations(lines, 2):
  if  line1.intersects(line2):
    inter = line1.intersection(line2)
    if "Point" == inter.type:
        inters.append(inter)
    elif "MultiPoint" == inter.type:
        inters.extend([pt for pt in inter])
    elif "MultiLineString" == inter.type:
        multiLine = [line for line in inter]
        first_coords = multiLine[0].coords[0]
        last_coords = multiLine[len(multiLine)-1].coords[1]
        inters.append(Point(first_coords[0], first_coords[1]))
        inters.append(Point(last_coords[0], last_coords[1]))
    elif "GeometryCollection" == inter.type:
        for geom in inter:
            if "Point" == geom.type:
                inters.append(geom)
            elif "MultiPoint" == geom.type:
                inters.extend([pt for pt in geom])
            elif "MultiLineString" == geom.type:
                multiLine = [line for line in geom]
                first_coords = multiLine[0].coords[0]
                last_coords = multiLine[len(multiLine)-1].coords[1]
                inters.append(Point(first_coords[0], first_coords[1]))
                inters.append(Point(last_coords[0], last_coords[1]))

ここに画像の説明を入力してください

4)端点と交差点の間の重複を排除します(図からわかるように)

result = endpts.extend([pt for pt in inters  if pt not in endpts])

5)結果のシェープファイルを保存します

from shapely.geometry import mapping
# schema of the shapefile
schema = {'geometry': 'Point','properties': {'test': 'int'}}
# creation of the shapefile
with fiona.open('result.shp','w','ESRI Shapefile', schema) as output:
    for i, pt in enumerate(result):
        output.write({'geometry':mapping(pt), 'properties':{'test':i}})

最終結果:

ここに画像の説明を入力してください

線分

ノード間のセグメントも必要な場合は、シェープファイルを「平面化」する必要があります(平面グラフ、エッジが互いに交差しない)。これはShapelyのunary_union関数で実行できます

from shapely.ops import unary_union
graph = unary_union(lines)

ここに画像の説明を入力してください


詳細な回答をありがとう@gene。異なる形状タイプにまたがる部分を編集しました。私の場合、交差はライン、geometrycollectionsなども返します。ただし、これは入力データによって異なります。私の質問では十分に明確ではありませんでした。
ustroetz 2015年

すばらしい答えです。メソッドを変更しresult = endpts.extend([pt for pt in inters if pt not in endpts])ているように見えるため、次のことを実行する必要はありません。私の場合、手術後。それは、結果敷石を含むアップ終了する.extendendptresult = Noneendpts
user32882
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.