python - pygeocoder - nominatim
Obtener distancia entre dos puntos en funciĆ³n de la latitud/longitud (3)
Intenté implementar esta fórmula: http://andrew.hedges.name/experiments/haversine/ El aplet hace bien en los dos puntos que estoy probando:
Sin embargo, mi código no funciona.
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
La distancia que devuelve es 5447.05546147 . ¿Por qué?
Es porque en Python, todas las funciones trigonométricas usan radianes , no grados.
Puede convertir los números manualmente a radianes o usar la función radians
del módulo matemático:
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")
La distancia ahora está devolviendo el valor correcto de 278.545589351
km.
Edit: Solo como una nota, si has tropezado con este post porque solo necesitas una manera rápida y fácil de encontrar la distancia entre dos puntos, te recomiendo que utilices el enfoque recomendado en la respuesta de Kurt a continuación: consulta su post para una explicación. .
Para las personas (como yo) que vienen aquí a través del motor de búsqueda y que están buscando una solución que funcione de manera mpu
, recomiendo instalar mpu
. Instálelo a través de pip install mpu --user
y utilícelo de esta manera para obtener la distancia de recorrido :
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.
Un paquete alternativo es gpxpy
.
Si no quieres dependencias, puedes usar:
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()
Actualización: 04/2018: Tenga en cuenta que la distancia Vincenty está en desuso desde la versión 1.13 GeoPy. ¡Debe usar geopy.distance.distance () en su lugar!
Las respuestas anteriores se basan en la fórmula de Haversine , que supone que la Tierra es una esfera, lo que produce errores de hasta aproximadamente el 0,5% (según la help(geopy.distance)
). Vincenty distance utiliza modelos elipsoidales más precisos, como WGS-84 , y se implementa en geopy . Por ejemplo,
import geopy.distance
coords_1 = (52.2296756, 21.0122287)
coords_2 = (52.406374, 16.9251681)
print geopy.distance.vincenty(coords_1, coords_2).km
imprimirá la distancia de 279.352901604
kilómetros utilizando el elipsoide predeterminado WGS-84. (También puede elegir .miles
o una de varias otras unidades de distancia).