web-dev-qa-db-ja.com

2つの(緯度、経度)ポイント間の距離をすばやく推定するにはどうすればよいですか?

2つの(緯度、経度)ポイント間の距離の推定値を取得できるようにします。これはA *グラフ検索用であり、fastにしたいので、アンダーシュートしたいです。ポイントは最大で800 km離れます。

52
fread2281

Haversine Formula in Python(2つのGPSポイント間のベアリングと距離) 提供Python質問に答える実装。

I以下の実装を使用して、古いラップトップで1秒未満で100,000回の反復を実行しました。あなたの目的にはこれで十分だと思います。ただし、パフォーマンスを最適化する前に、プロファイルを作成する必要があります。

_from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    # Radius of earth in kilometers is 6371
    km = 6371* c
    return km_

haversine(lat1, long1, lat2, long2) * 0.90または必要な要素を過小評価するため。あなたの過小評価にエラーを導入することがどのように役立つかわかりません。

105
Aaron D

距離が比較的小さいため、正距円筒法による距離近似を使用できます。この近似は、Haversine公式を使用するよりも高速です。したがって、参照ポイント(lat1/lon1)からテストしているポイント(lat2/lon2)までの距離を取得するには、次の式を使用します。重要な注意:すべての緯度/経度ポイントをラジアンに変換する必要があります。

R = 6371  // radius of the earth in km
x = (lon2 - lon1) * cos( 0.5*(lat2+lat1) )
y = lat2 - lat1
d = R * sqrt( x*x + y*y )

「R」はkm単位であるため、距離「d」はkm単位になります。

参照: http://www.movable-type.co.uk/scripts/latlong.html

35
TreyA

速度の1つのアイデアは、調整されたlong/latを3D(x、y、z)座標に変換することです。ポイントを前処理した後、ポイント間のユークリッド距離を、実際の距離のアンダーシュートをすばやく計算して使用します。

7

最高速度の場合、座標距離に Rainbow table のようなものを作成できます。作業している領域を既に知っているように聞こえるので、それらを事前に計算することは可能かもしれません。次に、最も近い組み合わせをロードして、それを使用することができます。

たとえば、米国本土では、経度は55度のスパンで、緯度は20であり、1100の整数ポイントになります。可能なすべての組み合わせ間の距離は ハンドシェイクの問題 であり、(n-1)(n)/ 2または約600kの組み合わせで回答されます。これは、保存および取得するのにかなり適しているようです。要件に関する詳細情報を提供していただければ、より具体的な情報を提供できます。

3
Aaron D

ポイント間の距離が比較的小さい場合(メートルから数kmの範囲)、高速アプローチの1つは

from math import cos, sqrt
def qick_distance(Lat1, Long1, Lat2, Long2):
    x = Lat2 - Lat1
    y = (Long2 - Long1) * cos((Lat2 + Lat1)*0.00872664626)  
    return 111.138 * sqrt(x*x + y*y)

緯度、経度はラジアン、距離はkmです。

Haversine距離からの偏差は1%程度ですが、速度の向上は10倍以上です。

0.00872664626 = 0.5 * pi/180、

111.138-Equatorの1度に対応する距離です。これを次のように中央値に置き換えることができます https://www.cartographyunchained.com/cgsta1/ または単純なルックアップテーブルに置き換えることができます。

2

2点間のヘイバーシン距離を計算するには、次のように単純に mpu.haversine_distance() ライブラリを使用できます。

>>> import mpu
>>> munich = (48.1372, 11.5756)
>>> berlin = (52.5186, 13.4083)
>>> round(mpu.haversine_distance(munich, berlin), 1)
>>> 504.2
0
Chiefir

次のコードを使用してください。

def distance(lat1, lng1, lat2, lng2):
    #return distance as meter if you want km distance, remove "* 1000"
    radius = 6371 * 1000 

    dLat = (lat2-lat1) * math.pi / 180
    dLng = (lng2-lng1) * math.pi / 180

    lat1 = lat1 * math.pi / 180
    lat2 = lat2 * math.pi / 180

    val = sin(dLat/2) * sin(dLat/2) + sin(dLng/2) * sin(dLng/2) * cos(lat1) * cos(lat2)    
    ang = 2 * atan2(sqrt(val), sqrt(1-val))
    return radius * ang
0
uher