Python 基于纬度/经度获取两点之间的距离

Python 基于纬度/经度获取两点之间的距离,python,geocoding,geo,geography,Python,Geocoding,Geo,Geography,我尝试实施这个公式: aplet有助于我测试的两点: 但我的代码不起作用 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) * (si

我尝试实施这个公式: aplet有助于我测试的两点:

但我的代码不起作用

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。为什么?

编辑:请注意,如果您只是需要一种快速简便的方法来计算两点之间的距离,我强烈建议您使用下面描述的方法,而不是重新实现哈弗森——请参阅他的帖子以了解其原理

这个答案只关注于回答OP遇到的特定bug


这是因为在Python中,所有的trig函数,而不是度

您可以手动将数字转换为弧度,也可以使用数学模块中的函数:

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。

对于通过搜索引擎来到这里并只是寻找现成解决方案的人,我建议安装。通过
pip Install mpu--user
安装它,并像这样使用它来获得:

另一种方案是

如果不需要依赖项,可以使用:

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()
另一个备选方案是

他们声称对两个向量中所有点之间的距离进行了性能优化

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])

更新:2018年4月:请注意,自GeoPy版本以来,Vincenty distance已被弃用-您应该改用GeoPy.distance.distance()


上面的答案基于,假设地球是一个球体,这会导致大约0.5%的误差(根据
帮助(geopy.distance)
)。使用更精确的椭球体模型,如,并在中实现。比如说,

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
或其他几个距离单位中的一个)。

我找到了一个更简单、更健壮的解决方案,它使用
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

有多种方法可以根据坐标(即纬度和经度)计算距离

安装和导入 来自geopy导入距离的

从数学输入sin、cos、sqrt、atan2、弧度
从sklearn.neights导入距离度量
导入osrm
将numpy作为np导入
定义坐标
lat1,lon1,lat2,lon2,R=20.9467,72.9520,21.1702,72.83116373.0
坐标_from=[lat1,lon1]
坐标_to=[lat2,lon2]
使用哈弗森
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))
距离哈弗公式=R*c
打印(‘使用哈弗公式的距离:’,距离_哈弗公式)
将haversine与sklearn一起使用
dist=DistanceMetric.get_metric('haversine'))
X=[[弧度(lat1),弧度(lon1)],[弧度(lat2),弧度(lon2)]]
距离=R*成对距离(X)
打印('distance using sklearn:',np.array(distance_sklearn).item(1))
使用OSRM
osrm\u client=osrm.client(host=)http://router.project-osrm.org')
坐标_osrm=[[lon1,lat1],[lon2,lat2]]#注意顺序是lon,lat
osrm\u response=osrm\u client.route(coordinates=coordinates\u osrm,overview=osrm.overview.full)
dist_osrm=osrm_response.get('routes')[0]。get('distance')/1000(公里)
打印('使用OSRM的距离:',dist_OSRM)
利用地质学
distance\u geopy=distance.distance(坐标从,坐标到).km
打印('使用地理位置的距离:',距离\地理位置)
距离地理大圆圈=距离大圆圈(坐标从,坐标到).km
打印(‘使用地质大圆的距离:’,距离(地质大圆))
输出
使用哈弗公式的距离:26.07547017310917
使用sklearn的距离:27.847882224769783
使用OSRM的距离:33.091699999996
使用geopy的距离:27.7528030550408
使用geopy大圆的距离:27.839182219511834
您可以使用,
point\u dist()
函数来计算两个(lat,lng)点之间的球面距离。我们可以设置返回单位(“km”、“m”或“rads”)。默认单位为公里

例如:

import H3

coords_1 = (52.2296756, 21.0122287)
coords_2 = (52.406374, 16.9251681)
distance = h3.point_dist(coords_1,coords_2) #278.4584889328128

希望这会有用

这在任何编程语言中都是正确的,在微分学中也是如此。使用度是一个例外,并且只用于人类的语言。对智者来说,这个公式要求所有的度都是正的<代码>弧度(abs(52.123))
应该可以…你确定所有的角度都是正的吗?我认为这是错误的。考虑如果LAT1,LUN1=10, 10(度)和LAT2,LoN2=- 10,-10(度)。通过在度数周围添加abs(),距离将为零,这是不正确的。也许你想取dlon和/或dlat的绝对值,但如果你看一下dlon,计算a时的dlat值,正弦是偶数函数,余弦平方是偶数函数,所以我也看不到取dlat或dlon的绝对值有什么好处。谢谢。你能用我提供的坐标代替纽波特和克利夫兰来更新你的答案吗。它将给未来的读者提供更好的理解。Newport和Cleveland的任意位置来自PyPI列表中的示例geopy文档:我不得不修改Kurt Peek的答案:需要大写:
print geopy.distance.VincetyDistance(coords_1,coords_2).km 279.352901604
您可能应该在代码中使用
geopy.distance.distance(…)
,这是当前最佳(=最精确)距离公式的别名。(目前为Vincenty。)在geopy-1.18.1输出中使用geopy.distance.Vincenty:Vincenty已被弃用,将在geopy 2.0中删除。使用
geopy.distance.geodesic
(o
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)
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 H3

coords_1 = (52.2296756, 21.0122287)
coords_2 = (52.406374, 16.9251681)
distance = h3.point_dist(coords_1,coords_2) #278.4584889328128