ChatGPT解决这个技术问题 Extra ChatGPT

根据纬度/经度获取两点之间的距离

我尝试实现这个公式: http://andrew.hedges.name/experiments/haversine/ aplet 对我正在测试的两点有好处:

https://i.stack.imgur.com/FGED4.png

然而我的代码不起作用。

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


j
jrreda

更新:04/2018:文森蒂距离是 deprecated since GeoPy version 1.13 - you should use geopy.distance.distance()

上面的答案是基于Haversine formula,它假设地球是一个球体,这会导致高达约 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.geodesic(coords_1, coords_2).km

将使用默认椭球 WGS-84 打印 279.352901604 公里的距离。 (您也可以选择 .miles 或其他几个距离单位之一)。


谢谢。您能否使用我提供的坐标而不是纽波特和克利夫兰来更新您的答案。它将让未来的读者更好地理解。
Newport 和 Cleveland 的任意位置来自 PyPI 列表中的示例 geopy 文档:pypi.python.org/pypi/geopy
我不得不修改 Kurt Peek 对此的回答:需要大写:print geopy.distance.VincentyDistance(coords_1, coords_2).km 279.352901604
您可能应该在代码中使用 geopy.distance.distance(…),它是当前最佳(=最准确)距离公式的别名。 (此刻的文森蒂。)
在 geopy-1.18.1 输出中使用 geopy.distance.vincenty:Vincenty 已弃用,将在 geopy 2.0 中删除。请改用 geopy.distance.geodesic(或默认的 geopy.distance.distance),这样更准确且始终收敛。
M
Michael0x2a

编辑:请注意,如果您只需要一种快速简便的方法来查找两点之间的距离,我强烈建议使用下面 Kurt's answer 中描述的方法,而不是重新实现 Haversine - - 请参阅他的帖子以了解基本原理。

该答案仅侧重于回答 OP 遇到的特定错误。

这是因为在 Python 中,所有的三角函数 use radians,而不是度数。

您可以手动将数字转换为弧度,或使用数学模块中的 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 公里的正确值。


在任何编程语言中都是如此,在微积分中也是如此。使用度数是个例外,仅用于人类语音。
明智的说法是,这个公式要求所有度数都是正数。 radians(abs(52.123)) 应该可以解决问题...
您确定所有度数(角度?)都是正数吗?我认为这是错误的。考虑 lat1, lon1 = 10, 10 (度) 和 lat2, lon2 = -10, -10 (度)。通过在度数周围添加 abs(),距离将为零,这是不正确的。也许你打算取 dlon 和/或 dlat 的绝对值,但是如果你在计算 a 时查看 dlon、dlat 值,sine 是偶函数,而 cosine squared 是偶函数,所以我不也可以看到采用 dlat 或 dlon 的绝对值有什么好处。
只是想知道上面的距离是两个位置之间的弧距还是平面距离?
有一个 breaking change 已删除 geopy.distance.vincenty,请改用 geopy.distance.geodesic。你会更新你的答案吗?
B
Boris Verkhovskiy

对于通过搜索引擎来到这里并只是寻找开箱即用的解决方案的人(如我),我建议安装 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 __name__ == '__main__':
    import doctest
    doctest.testmod()

另一个替代包是 haversine

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

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

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

有没有办法改变其中一个点的给定高度?
您可以简单地将高度差添加到距离中。不过,我不会那样做。
“里昂,巴黎,392.2172595594006 公里”,哇最后一个数字甚至不是氢原子的大小。非常精准!
哇,你能救我吗? ,是否可以在地图中的自定义点上获得相应的十进制度数?,例如:获取点 x,y 的十进制度数,例如距离(以米为单位)是 300 mts
R
Ramy M. Mousa

我得到了一个更简单和强大的解决方案,它使用来自 geopy 包的 geodesic,因为无论如何您很可能在您的项目中使用它,因此不需要额外的包安装。

这是我的解决方案:

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


感谢哥们提到纬度首先是经度。干杯!
R
Romil Patel

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

安装和导入

from geopy import distance
from math import sin, cos, sqrt, atan2, radians
from sklearn.neighbors import DistanceMetric
import osrm
import numpy as np

定义坐标

lat1, lon1, lat2, lon2, R = 20.9467,72.9520, 21.1702, 72.8311, 6373.0
coordinates_from = [lat1, lon1]
coordinates_to = [lat2, lon2]

使用半正弦波

dlon = radians(lon2) - radians(lon1)
dlat = radians(lat2) - radians(lat1)
    
a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
c = 2 * atan2(sqrt(a), sqrt(1 - a))
    
distance_haversine_formula = R * c
print('distance using haversine formula: ', distance_haversine_formula)

在 sklearn 中使用 hasrsine

dist = DistanceMetric.get_metric('haversine')
    
X = [[radians(lat1), radians(lon1)], [radians(lat2), radians(lon2)]]
distance_sklearn = R * dist.pairwise(X)
print('distance using sklearn: ', np.array(distance_sklearn).item(1))

使用 OSRM

osrm_client = osrm.Client(host='http://router.project-osrm.org')
coordinates_osrm = [[lon1, lat1], [lon2, lat2]] # note that order is lon, lat
    
osrm_response = osrm_client.route(coordinates=coordinates_osrm, overview=osrm.overview.full)
dist_osrm = osrm_response.get('routes')[0].get('distance')/1000 # in km
print('distance using OSRM: ', dist_osrm)

使用地理

distance_geopy = distance.distance(coordinates_from, coordinates_to).km
print('distance using geopy: ', distance_geopy)
    
distance_geopy_great_circle = distance.great_circle(coordinates_from, coordinates_to).km 
print('distance using geopy great circle: ', distance_geopy_great_circle)

输出

distance using haversine formula:  26.07547017310917
distance using sklearn:  27.847882224769783
distance using OSRM:  33.091699999999996
distance using geopy:  27.7528030550408
distance using geopy great circle:  27.839182219511834

S
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 = 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)

嗨,您认为有一种方法可以直接从模板中获取数据吗?
R
Ransaka Ravihara

您可以使用 Uber's H3,point_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, unit='m') # to get distance in meters

希望这会有用!


s
swatchai

在 2022 年,人们可以发布使用更新的 javascript 库解决此问题的实时 javascript 代码。一般的好处是用户可以在现代设备上运行的网页上运行并查看结果。

// 使用 WGS84 椭球模型进行计算 var geod84 = geodesic.Geodesic.WGS84; // 输入数据 lat1 = 52.2296756; lon1 = 21.0122287; lat2 = 52.406374; lon2 = 16.9251681; // 执行经典的“大地反演”计算 geod84inv = geod84.Inverse(lat1, lon1, lat2, lon2); // 给出解决方案(只有大地距离) console.log("距离是 " + (geod84inv.s12/1000).toFixed(5) + " km.");


s
swatchai

在 2022 年,可以发布使用更新的 Python 库(即 geographiclib)解决此问题的混合 javascript+python 代码。一般的好处是用户可以在现代设备上运行的网页上运行并查看结果。

async function main(){ let pyodide = await loadPyodide();等待 pyodide.loadPackage(["micropip"]); console.log(pyodide.runPythonAsync(`import micropip await micropip.install('geographiclib') from geodesic.geodesic import Geodesic lat1 = 52.2296756; lon1 = 21.0122287; lat2 = 52.406374; lon2 = 16.9251681; ans = Geodesic.WGS84.Inverse( lat1, lon1, lat2, lon2) dkm = ans["s12"] / 1000 print("测地线解", ans) print(f"距离 = {dkm:.4f} km.") `)); } 主要的();


L
Luisa Fernanda Velasquez Camac

最简单的方法是使用 hasrsine 包。


import haversine as hs


coord_1 = (lat, lon)
coord_2 = (lat, lon)
x = hs.haversine(coord_1,coord_2)
print(f'The distance is {x} km')

s
swatchai

另一种有趣的使用混合 javascript+python 通过 pyodidewebassembly 实现来获得使用 Python 库 pandas+geographiclib 的解决方案也是可行的。我使用 pandas 做了额外的努力来准备输入数据,当输出可用时,将它们附加到 solution 列。 Pandas 为满足常见需求的输入/输出提供了许多有用的功能。它的方法toHtml很方便在网页上呈现最终的解决方案

编辑我发现此答案中的代码在某些 iphone 和 ipad 设备上执行不成功。但在较新的中端 Android 设备上运行良好。我会找到一种方法来纠正这个问题并尽快更新。

我的旁注,我知道我的答案不像其他答案那样直接回答 OP 问题。但最近外界表示,StackOvereflow 中的很多答案已经过时,并试图引导人们远离这里。

async function main(){ let pyodide = await loadPyodide();等待 pyodide.loadPackage(["pandas", "micropip"]); console.log(pyodide.runPythonAsync(` import micropip import pandas as pd import js print("Pandas version: " + pd.__version__) await micropip.install('geographiclib') fromgeographiclib.geodesic import Geodesic importgeographiclib as gl print( "Geographiclib 版本:" + gl.__version__) data = {'Description': ['Answer to the question', 'Bangkok to Tokyo'], 'From_long': [21.0122287, 100.6], 'From_lat': [52.2296756, 13.8 ], 'To_long': [16.9251681, 139.76], 'To_lat': [52.406374, 35.69], 'Distance_km': [0, 0]} df1 = pd.DataFrame(data) collist = ['Description','From_long' ,'From_lat','To_long','To_lat'] div2 = js.document.createElement("div") div2content = df1.to_html(buf=None, columns=collist, col_space=None, header=True, index=True ) div2.innerHTML = div2content js.document.body.append(div2) arr="by Swatchai" def dkm(frLat,frLon,toLat,toLon): print("frLon,frLat,toLon, toLat:", frLon, "|", frLat, "|", toLon, "|", toLat) dist = Geodesic.WGS84.Inverse(frLat, frLon, toLat, toLon) 返回 dis t["s12"] / 1000 collist = ['Description','From_long','From_lat','To_long','To_lat','Distance_km'] dist = [] for ea in zip(df1['From_lat'] .values, df1['From_long'].values, df1['To_lat'].values, df1['To_long'].values): ans = dkm(*ea) print("ans=", ans) dist.append (ans) df1['Distance_km'] = dist # 更新内容 div2content = df1.to_html(buf=None, columns=collist, col_space=None, header=True, index=False) div2.innerHTML = div2content js.document.body .append(div2) # Using Haversine Formula from math import sin, cos, sqrt, atan2, radians, asin # 地球的近似半径,以公里为单位,来自维基百科 R = 6371 lat1 = 弧度(52.2296756) lon1 = 弧度(21.0122287) lat2 = 弧度(52.406374) lon2 = 弧度(16.9251681) # https://en.wikipedia.org/wiki/Haversine_formula def hav(angrad): return (1-cos(angrad))/2 h = hav(lat2-lat1)+cos (lat2)*cos(lat1)*hav(lon2-lon1) dist2 = 2*R*asin(sqrt(h)) print(f"距离公式 = {dist2:8.6f} km.") `)) ; } 主要的(); Pyodide 实现


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅