Shapely: Linestringで最も近いポイントを取得する

作成日 2014年10月18日  ·  3コメント  ·  ソース: Toblerity/Shapely

こんにちは、
ポイントを指定して、ラインストリング上の最も近いポイントを取得しようとしています。 単純な線ストリングでは問題なく機能するようです。
Python 3.4.0(デフォルト、2014年4月11日、13:05:11)
Linux上の[GCC4.8.2]
詳細については、「help」、「copyright」、「credits」、または「license」と入力してください。

shapely.geometryからimportPoint、LineString
line = LineString([(0,0)、(5,7)、(12,6)])
p = Point(4,8)
np = line.interpolate(line.project(p))
print(np)
ポイント(5 7)

ただし、複雑な線ストリングの場合、意図した結果が得られません。eg

route = LineString([(19.119318,72.902800)、(19.119660,72.901455)、(19.119673,72.901401)、(19.119848,72.900553)、(19.119975,72.899972)、(19.120129,72.899675)、(19.120308,72.899385)、(19.120589、 72.899162)、(19.121131,72.898909)、(19.121597,72.898739)、(19.122330,72.898471)、(19.122696,72.898429)、(19.123296,72.897991)、(19.123680,72.897623)、(19.124095,72.897035)、(19.124402,72 、(19.124483,72.896177)、(19.124573,72.895796)、(19.124585,72.895470)、(19.124603,72.895014)、(19.124652,72.894291)、(19.124686,72.894067)、(19.124929,72.893177)、(19.124971,72.893049) 19.125097,72.892666)、(19.125214,72.892323)、(19.125450,72.891802)、(19.125757,72.891281)、(19.125951,72.890874)、(19.126170,72.890413)、(19.126833,72.889417)、(19.127319,72.888873)、(19 72.886714)、(19.129060,72.886402)、(19.129109,72.886299)、(19.129238,72.885913)、(19.129302,72.885370)、(19.129372,72.881686)、(19.129396,72.880652)、(19.129413,72.880540)、(19.129366、 、(19.129382,72.880070)、(19.129419,72.879849)、(19.129509,72.879205)、(19.129709,72。 877766)、(19.129969,72.876684)、(19.130029,72.876511)、(19.128367,72.875341)、(19.127365,72.874602)、(19.125882,72.873536)、(19.125160,72.873014)、(19.124815,72.872761)、(19.124413,72。 、(19.123149,72.871568)、(19.122517,72.871091)、(19.122162,72.870822)、(19.121981,72.870749)、(19.121736,72.870651)、(19.121013,72.870576)、(19.119933,72.870464)、(19.119596,72.870432)

list(route.coords)
[(19.119318、72.9028)、(19.11966、72.901455)、(19.119673、72.901401)、(19.119848、72.900553)、(19.119975、72.899972)、(19.120129、72.899675)、(19.120308、72.899385)、(19.120589、72.899162)、( 19.121131、72.898909)、(19.121597、72.898739)、(19.12233、72.898471)、(19.122696、72.898429)、(19.123296、72.897991)、(19.12368、72.897623)、(19.124095、72.897035)、(19.124402、72.896411)、(1 72.896177)、(19.124573、72.895796)、(19.124585、72.89547)、(19.124603、72.895014)、(19.124652、72.894291)、(19.124686、72.894067)、(19.124929、72.893177)、(19.124971、72.893049)、(19.125097、7 、(19.125214、72.892323)、(19.12545、72.891802)、(19.125757、72.891281)、(19.125951、72.890874)、(19.12617、72.890413)、(19.126833、72.889417)、(19.127319、72.888873)、(19.128909、72.886714) 19.12906、72.886402)、(19.129109、72.886299)、(19.129238、72.885913)、(19.129302、72.88537)、(19.129372、72.881686)、(19.129396、72.880652)、(19.129413、72.88054)、(19.129366、72.880167)、( 72.88007)、(19 .129419、72.879849)、(19.129509、72.879205)、(19.129709、72.877766)、(19.129969、72.876684)、(19.130029、72.876511)、(19.128367、72.875341)、(19.127365、72.874602)、(19.125882、72.873536)、(19 、72.873014)、(19.124815、72.872761)、(19.124413、72.872457)、(19.123149、72.871568)、(19.122517、72.871091)、(19.122162、72.870822)、(19.121981、72.870749)、(19.121736、72.870651)、(19.1210 )、(19.119933、72.870464)、(19.119596、72.870432)]

end = Point(19.125150,72.893218)

np = route.interpolate(route.project(end))

print(np)
ポイント(19.12493833590478 72.89314854771877)

結果は19.124929、72.893177になると思っていました。 それは私が間違っていることですか? 助けていただければ幸いです。

ありがとう!

最も参考になるコメント

返されるポイントは、元のポイントにライン上で最も近いポイントです。 最も近いポイントは、必ずしもLineString内の既存の頂点ではなく、この場合はそうではありません。

end = Point(19.125150,72.893218)
np = Point(19.12493833590478, 72.89314854771877)
expected = Point(19.124929, 72.893177)

print end.distance(np) # 0.000222767386696
print end.distance(expected) # 0.000224770994572

最も近い頂点を見つけたい場合は、最初にLineStringをMultiPointジオメトリに変換してから、 nearest_points操作を使用する必要があります(マイナーな浮動小数点エラーに注意してください)。

from shapely.ops import nearest_points
from shapely.geometry import MultiPoint
mp = MultiPoint(route)
print nearest_points(mp, end)[0] # POINT (19.124929 72.89317699999999)

このクエリでは、元のポイントと元のラインストリングの各頂点の間の距離を計算する必要があります。 非常に複雑なルートの場合、これはかなり遅くなる可能性があります。 この場合は、 rtreeモジュールの使用を検討する必要があります。このモジュールは、空間インデックスを使用して、この種のクエリを非常に高速にします。

http://toblerity.org/rtree/tutorial.html

全てのコメント3件

返されるポイントは、元のポイントにライン上で最も近いポイントです。 最も近いポイントは、必ずしもLineString内の既存の頂点ではなく、この場合はそうではありません。

end = Point(19.125150,72.893218)
np = Point(19.12493833590478, 72.89314854771877)
expected = Point(19.124929, 72.893177)

print end.distance(np) # 0.000222767386696
print end.distance(expected) # 0.000224770994572

最も近い頂点を見つけたい場合は、最初にLineStringをMultiPointジオメトリに変換してから、 nearest_points操作を使用する必要があります(マイナーな浮動小数点エラーに注意してください)。

from shapely.ops import nearest_points
from shapely.geometry import MultiPoint
mp = MultiPoint(route)
print nearest_points(mp, end)[0] # POINT (19.124929 72.89317699999999)

このクエリでは、元のポイントと元のラインストリングの各頂点の間の距離を計算する必要があります。 非常に複雑なルートの場合、これはかなり遅くなる可能性があります。 この場合は、 rtreeモジュールの使用を検討する必要があります。このモジュールは、空間インデックスを使用して、この種のクエリを非常に高速にします。

http://toblerity.org/rtree/tutorial.html

お返事ありがとうございます。

@snorfalorpagus 。 私はこのようなものを探していました。 浮動小数点エラーを取り除くための賢い提案はありますか? このツールにも同じ問題があります。

このページは役に立ちましたか?
0 / 5 - 0 評価