私はこの式を実装しようとしました: http://andrew.hedges.name/experiments/haversine/ apletは、私がテストしている2つのポイントに適しています。
しかし、私のコードは機能していません。
from math import sin, cos, sqrt, atan2
R = 6373.0
lat1 = 52.2296756
lon1 = 21.0122287
lat2 = 52.406374
lon2 = 16.9251681
dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))**2 + cos(lat1) * cos(lat2) * (sin(dlon/2))**2
c = 2 * atan2(sqrt(a), sqrt(1-a))
distance = R * c
print "Result", distance
print "Should be", 278.546
返される距離は5447.05546147です。どうして?
編集:ちょうどメモとして、2点間の距離をすばやく簡単に見つける方法が必要な場合は、 Kurtの答え Haversineを再実装する代わりに-以下の彼の投稿の理論的根拠を参照してください。
この回答は、OPが実行された特定のバグへの回答にのみ焦点を当てています。
Pythonでは、すべてのtrig関数 ラジアンを使用 であり、度ではないからです。
数値を手動でラジアンに変換するか、mathモジュールの radians
関数を使用できます。
from math import sin, cos, sqrt, atan2, radians
# approximate radius of earth in km
R = 6373.0
lat1 = radians(52.2296756)
lon1 = radians(21.0122287)
lat2 = radians(52.406374)
lon2 = radians(16.9251681)
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
distance = R * c
print("Result:", distance)
print("Should be:", 278.546, "km")
距離は278.545589351
kmの正しい値を返しています。
更新:2018年4月:Vincentyの距離はGeoPyバージョン 1.1 から廃止されることに注意してください-geopy.distance.distanceを使用する必要があります()代わりに!
上記の答えは Haversine式 に基づいています。これは、地球が球体であると仮定し、最大で約0.5%の誤差が生じます(help(geopy.distance)
による)。 Vincenty distance は WGS-84 などのより正確な楕円モデルを使用し、 geopy で実装されます。例えば、
import geopy.distance
coords_1 = (52.2296756, 21.0122287)
coords_2 = (52.406374, 16.9251681)
print geopy.distance.vincenty(coords_1, coords_2).km
デフォルトの楕円WGS-84を使用して、279.352901604
キロメートルの距離を出力します。 (.miles
または他のいくつかの距離単位のいずれかを選択することもできます)。
検索エンジン経由でここに来て、すぐに使用できるソリューションを探している人(私のような)の場合、 mpu
をインストールすることをお勧めします。 pip install mpu --user
経由でインストールし、次のように使用して haversine distance を取得します。
import mpu
# Point one
lat1 = 52.2296756
lon1 = 21.0122287
# Point two
lat2 = 52.406374
lon2 = 16.9251681
# What you were looking for
dist = mpu.haversine_distance((lat1, lon1), (lat2, lon2))
print(dist) # gives 278.45817507541943.
代替パッケージは gpxpy
です。
依存関係が必要ない場合は、次を使用できます。
import math
def distance(Origin, destination):
"""
Calculate the Haversine distance.
Parameters
----------
Origin : Tuple of float
(lat, long)
destination : Tuple of float
(lat, long)
Returns
-------
distance_in_km : float
Examples
--------
>>> Origin = (48.1372, 11.5756) # Munich
>>> destination = (52.5186, 13.4083) # Berlin
>>> round(distance(Origin, destination), 1)
504.2
"""
lat1, lon1 = Origin
lat2, lon2 = destination
radius = 6371 # km
dlat = math.radians(lat2 - lat1)
dlon = math.radians(lon2 - lon1)
a = (math.sin(dlat / 2) * math.sin(dlat / 2) +
math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) *
math.sin(dlon / 2) * math.sin(dlon / 2))
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
d = radius * c
return d
if __== '__main__':
import doctest
doctest.testmod()
geodesic
パッケージのgeopy
を使用する非常にシンプルで堅牢なソリューションにたどり着きました。プロジェクトで使用する可能性が高いため、追加のパッケージをインストールする必要はありません。
ここに私の解決策があります:
from geopy.distance import geodesic
Origin = (30.172705, 31.526725) # (latitude, longitude) don't confuse
dist = (30.288281, 31.732326)
print(geodesic(Origin, dist).meters) # 23576.805481751613
print(geodesic(Origin, dist).kilometers) # 23.576805481751613
print(geodesic(Origin, dist).miles) # 14.64994773134371
import numpy as np
def Haversine(lat1,lon1,lat2,lon2, **kwarg):
"""
This uses the ‘haversine’ formula to calculate the great-circle distance between two points – that is,
the shortest distance over the earth’s surface – giving an ‘as-the-crow-flies’ distance between the points
(ignoring any hills they fly over, of course!).
Haversine
formula: a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)
c = 2 ⋅ atan2( √a, √(1−a) )
d = R ⋅ c
where φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km);
note that angles need to be in radians to pass to trig functions!
"""
R = 6371.0088
lat1,lon1,lat2,lon2 = map(np.radians, [lat1,lon1,lat2,lon2])
dlat = lat2 - lat1
dlon = lon2 - lon1
a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2) **2
c = 2 * np.arctan2(a**0.5, (1-a)**0.5)
d = R * c
return round(d,4)