15

GeoDjango または GeoPy を使用して、方向と距離に基づいてポイントを計算したいと思います。

たとえば、(-24680.1613, 6708860.65389) という点がある場合、Vincenty 距離式を使用して、北 1 キロ、東 1 キロ、南 1 キロ、西 1 キロのポイントを見つけたいと思います。

私が見つけることができる最も近いものは、distance.py ( https://code.google.com/p/geopy/source/browse/trunk/geopy/distance.py?r=105 ) の「目的地」関数です。これはどこにも文書化されていませんが、使用方法はまだわかりません。

どんな助けでも大歓迎です。

4

3 に答える 3

21

編集 2

さて、geopy を使用したすぐに使用できるソリューションがありますが、十分に文書化されていません。

import geopy
import geopy.distance

# Define starting point.
start = geopy.Point(48.853, 2.349)

# Define a general distance object, initialized with a distance of 1 km.
d = geopy.distance.VincentyDistance(kilometers = 1)

# Use the `destination` method with a bearing of 0 degrees (which is north)
# in order to go from point `start` 1 km to north.
print d.destination(point=start, bearing=0)

出力は48 52m 0.0s N, 2 21m 0.0s E(またはPoint(48.861992239749355, 2.349, 0.0)) です。

90 度の方位は東、180 度は南などに対応します。

古い回答:

簡単な解決策は次のとおりです。

def get_new_point():
    # After going 1 km North, 1 km East, 1 km South and 1 km West
    # we are back where we were before.
    return (-24680.1613, 6708860.65389)

ただし、それがすべての一般的な目的に役立つかどうかはわかりません。

さて、真剣に、geopy を使い始めることができます。まず最初に、geopy が認識している座標系で開始点を定義する必要があります。一見すると、特定の距離を特定の方向に「追加」することはできないように見えます。その理由は、距離の計算が単純な逆解のない問題だからだと思います。または、 https://code.google.com/p/geopy/source/browse/trunk/geopy/distance.py#217measureで定義されている関数をどのように反転しますか?

したがって、反復的なアプローチを採用することをお勧めします。

ここに記載されているように: https://stackoverflow.com/a/9078861/145400次のように、指定された 2 点間の距離を計算できます。

pt1 = geopy.Point(48.853, 2.349)
pt2 = geopy.Point(52.516, 13.378)
# distance.distance() is the  VincentyDistance by default.
dist = geopy.distance.distance(pt1, pt2).km

北に 1 キロメートル移動するには、緯度を正の方向に繰り返し変更し、距離を確認します。SciPy などの単純な反復ソルバーを使用して、このアプローチを自動化できgeopy.distance.distance().km - 1ます。

緯度をマイナス方向に変えることで南へ、経度を変えることで西と東に移動することは明らかだと思います。

私はそのような地理計算の経験がありません。この反復的なアプローチは、特定の距離だけ「北に行く」ための単純な直接的な方法がない場合にのみ意味があります。

編集:私の提案の実装例:

import geopy
import geopy.distance
import scipy.optimize


def north(startpoint, distance_km):
    """Return target function whose argument is a positive latitude
    change (in degrees) relative to `startpoint`, and that has a root
    for a latitude offset that corresponds to a point that is 
    `distance_km` kilometers away from the start point.
    """
    def target(latitude_positive_offset):
        return geopy.distance.distance(
            startpoint, geopy.Point(
                latitude=startpoint.latitude + latitude_positive_offset,
                longitude=startpoint.longitude)
            ).km - distance_km
    return target


start = geopy.Point(48.853, 2.349)
print "Start: %s" % start

# Find the root of the target function, vary the positve latitude offset between
# 0 and 2 degrees (which is for sure enough for finding a 1 km distance, but must
# be adjusted for larger distances).
latitude_positive_offset = scipy.optimize.bisect(north(start, 1),  0, 2)


# Build Point object for identified point in space.
end = geopy.Point(
    latitude=start.latitude + latitude_positive_offset,
    longitude=start.longitude
    )

print "1 km north: %s" % end

# Make the control.
print "Control distance between both points: %.4f km." % (
     geopy.distance.distance(start, end).km)

出力:

$ python test.py 
Start: 48 51m 0.0s N, 2 21m 0.0s E
1 km north: 48 52m 0.0s N, 2 21m 0.0s E
Control distance between both points: 1.0000 km.
于 2014-06-26T11:52:04.257 に答える
18

Jan-Philip Gehrcke 博士の回答に基づく、この質問の 2020 年の更新。

VincentyDistanceは公式に非推奨であり、完全に正確ではなく、時には不正確でもありました。

このスニペットは、最新 (および GeoPy の将来のバージョン - Vincenty は 2.0 で廃止予定) での使用方法を示しています。

import geopy
import geopy.distance

# Define starting point.
start = geopy.Point(48.853, 2.349)

# Define a general distance object, initialized with a distance of 1 km.
d = geopy.distance.distance(kilometers=1)

# Use the `destination` method with a bearing of 0 degrees (which is north)
# in order to go from point `start` 1 km to north.
final = d.destination(point=start, bearing=0)

final印刷すると返される新しいPointオブジェクトです48 51m 43.1721s N, 2 20m 56.4s E

ご覧のとおり、これは よりも正確でVincentyあり、極の近くでより良い精度を維持する必要があります。

それが役に立てば幸い!

于 2020-04-27T13:40:52.433 に答える