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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:41:18  来源:igfitidea点击:

Getting distance between two points based on latitude/longitude

pythongeocodinggeogeography

提问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 对我正在测试的两点有好处:

enter image description here

在此处输入图片说明

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 radiansfunction from the math module:

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

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.545589351km.

距离现在返回正确的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 --userand 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.352901604kilometers using the default ellipsoid WGS-84. (You can also choose .milesor 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 geodesicfrom geopypackage since you'll be highly likely using it in your project anyways so no extra package installation needed.

我找到了一个更简单和强大的解决方案,它使用geodesicfrom geopypackage 因为无论如何你很可能在你的项目中使用它,所以不需要额外的包安装。

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

geopy

地理