Python 根据纬度/经度获取两点之间的距离
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19412462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting distance between two points based on latitude/longitude
提问by gwaramadze
I tried implementing this formula: http://andrew.hedges.name/experiments/haversine/The aplet does good for the two points I am testing:
我尝试实施这个公式:http://andrew.hedges.name/experiments/haversine/aplet 对我正在测试的两点有好处:
Yet my code is not working.
然而我的代码不起作用。
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
The distance it returns is 5447.05546147. Why?
它返回的距离是5447.05546147。为什么?
采纳答案by Michael0x2a
Edit:Just as a note, if you just need a quick and easy way of finding the distance between two points, I strongly recommend using the approach described in Kurt's answerbelow instead of re-implementing Haversine -- see his post for rationale.
编辑:请注意,如果您只需要一种快速简便的方法来找到两点之间的距离,我强烈建议您使用下面Kurt 的回答中描述的方法,而不是重新实现Haversine——请参阅他的帖子以了解基本原理。
This answer focuses just on answering the specific bug OP ran into.
该答案仅侧重于回答 OP 遇到的特定错误。
It's because in Python, all the trig functions use radians, not degrees.
这是因为在 Python 中,所有的三角函数都使用弧度,而不是度数。
You can either convert the numbers manually to radians, or use the radians
function from the math module:
您可以手动将数字转换为弧度,也可以使用radians
math 模块中的函数:
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")
The distance is now returning the correct value of 278.545589351
km.
距离现在返回正确的278.545589351
公里值。
回答by Martin Thoma
For people (like me) coming here via search engine and just looking for a solution which works out of the box, I recommend installing mpu
. Install it via pip install mpu --user
and use it like this to get the haversine distance:
对于通过搜索引擎来到这里并只是寻找开箱即用的解决方案的人(像我一样),我建议安装mpu
. 通过安装它pip install mpu --user
并像这样使用它来获得半正弦距离:
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.
An alternative package is gpxpy
.
另一个包是gpxpy
.
If you don't want dependencies, you can use:
如果你不想要依赖,你可以使用:
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 __name__ == '__main__':
import doctest
doctest.testmod()
The other alternative package is [haversine][1]
另一个替代包是 [haversine][1]
from haversine import haversine, Unit
lyon = (45.7597, 4.8422) # (lat, lon)
paris = (48.8567, 2.3508)
haversine(lyon, paris)
>> 392.2172595594006 # in kilometers
haversine(lyon, paris, unit=Unit.MILES)
>> 243.71201856934454 # in miles
# you can also use the string abbreviation for units:
haversine(lyon, paris, unit='mi')
>> 243.71201856934454 # in miles
haversine(lyon, paris, unit=Unit.NAUTICAL_MILES)
>> 211.78037755311516 # in nautical miles
They claim to have performance optimization for distances between all points in two vectors
他们声称对两个向量中所有点之间的距离进行了性能优化
from haversine import haversine_vector, Unit
lyon = (45.7597, 4.8422) # (lat, lon)
paris = (48.8567, 2.3508)
new_york = (40.7033962, -74.2351462)
haversine_vector([lyon, lyon], [paris, new_york], Unit.KILOMETERS)
>> array([ 392.21725956, 6163.43638211])
回答by Kurt Peek
Update: 04/2018:Note that Vincenty distance is deprecated since GeoPy version 1.13- you should use geopy.distance.distance() instead!
更新:04/2018:请注意,自 GeoPy 1.13版以来,Vincenty 距离已被弃用- 您应该改用 geopy.distance.distance() !
The answers above are based on the Haversine formula, which assumes the earth is a sphere, which results in errors of up to about 0.5% (according to help(geopy.distance)
). Vincenty distanceuses more accurate ellipsoidal models such as WGS-84, and is implemented in geopy. For example,
上面的答案基于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
will print the distance of 279.352901604
kilometers using the default ellipsoid WGS-84. (You can also choose .miles
or one of several other distance units).
将279.352901604
使用默认椭球 WGS-84打印公里的距离。(您也可以选择.miles
或 其他几种距离单位之一)。
回答by Sudhirln92
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 = sin2(Δφ/2) + cos φ1 ? cos φ2 ? sin2(Δλ/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)
回答by Ramy M. Mousa
I arrived at a much simpler and robust solution which is using geodesic
from geopy
package since you'll be highly likely using it in your project anyways so no extra package installation needed.
我找到了一个更简单和强大的解决方案,它使用geodesic
from geopy
package 因为无论如何你很可能在你的项目中使用它,所以不需要额外的包安装。
Here is my solution:
这是我的解决方案:
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