36 Pregunta: ¿Calcular la distancia entre dos puntos de latitud-longitud? (Fórmula de Haversine)

pregunta creada en Mon, Sep 11, 2017 12:00 AM

¿Cómo calculo la distancia entre dos puntos especificados por latitud y longitud?

Para aclarar, me gustaría la distancia en kilómetros; los puntos utilizan el sistema WGS84 y me gustaría entender las precisiones relativas de los enfoques disponibles.

    
812
  1. Para mayor precisión, consulte stackoverflow.com/questions/1420045/…
    2017-07-21 07: 54: 19Z
  2. Tenga en cuenta que no puede aplicar una fórmula de Haversine en un elipsoide de revolución como WGS 84. Solo puede aplicar este método en una esfera con un radio.
    2018-07-23 02: 05: 23Z
  3. La mayoría de las respuestas aquí utilizan una trigonometría esférica simple, por lo que los resultados son bastante crudos en comparación con las distancias elipsoidales WGS84 utilizadas en el sistema GPS. Algunas de las respuestas se refieren a la fórmula de Vincenty para elipsoides, pero ese algoritmo fue diseñado para ser utilizado en las calculadoras de escritorio de la era de la década de 1960 y tiene estabilidad y amp; problemas de precisión; Tenemos mejor hardware y software ahora. Consulte GeographicLib para obtener una biblioteca de alta calidad con implementaciones en varios idiomas.
    2018-08-03 13: 26: 32Z
  4. @ MikeT - verdadero, aunque muchas de las respuestas aquí parecen ser útiles en distancias pequeñas : si toma lat /long de WGS 84, aplique Haversine como si esos puntos estuvieran en una esfera, ¿no obtiene respuestas cuyos errores solo se deben al factor de aplanamiento de la tierra, por lo que quizás dentro del 1% de una fórmula más precisa? Con la advertencia de que estas son distancias pequeñas, digamos dentro de una sola ciudad.
    2018-11-25 15: 27: 13Z
  5. Para estas formas de placa: Mono /.NET 4.5 /.NET Core /Windows Phone 8.x /Plataforma universal de Windows /Xamarin iOS /Xamarin Android vea stackoverflow.com/a/54296314/2736742
    2019-01-21 20: 02: 13Z
30 Respuestas                              30                         

Este enlace puede ser útil para usted, ya que detalla el use la Fórmula Haversine para calcular la distancia.

Extracto:

  

Este script [en Javascript] calcula distancias de círculo grande entre los dos puntos -   es decir, la distancia más corta sobre la superficie de la tierra - usando el   Fórmula "Haversine".

 
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in km
  return d;
}

function deg2rad(deg) {
  return deg * (Math.PI/180)
}
    
1016
2014-07-31 01: 25: 14Z
  1. ¿Este cálculo /método explica que la Tierra sea un esferoide (no una esfera perfecta)? La pregunta original pedía la distancia entre los puntos en un globo WGS84. No estoy seguro de cuánto se arrastra el error utilizando una esfera perfecta, pero sospecho que puede ser bastante dependiendo de dónde se encuentren los puntos en el globo, por lo que vale la pena tener en cuenta la distinción.
    2011-11-08 08: 33: 38Z
  2. La fórmula de Haversine no tiene en cuenta que la Tierra es un esferoide, por lo que recibirá un error debido a este hecho. No se puede garantizar correcto a mejor que 0.5%. Sin embargo, ese puede o no ser un nivel de error aceptable.
    2011-12-28 16:20:25Z
  3. ¿Hay alguna razón para usar Math.atan2(Math.sqrt(a), Math.sqrt(1-a)) en lugar de Math.asin(Math.sqrt(h)), cuál sería la implementación directa de la fórmula que usa el artículo de Wikipedia? ¿Es más eficiente y /o más numéricamente estable?
    2012-12-20 03: 47: 08Z
  4. @ UsmanMutawakil Bueno, las 38 millas que obtienes son la distancia en la carretera. Este algoritmo calcula una distancia en línea recta en la superficie de la tierra. Google Maps tiene una herramienta de distancia (abajo a la izquierda, "Labs") que hace lo mismo, úsala para comparar.
    2013-07-03 17: 35: 44Z
  5. @ Forte_201092: porque no es necesario, ya que (sin(x))² es igual a (sin(-x))²
    2014-05-30 09: 16: 06Z

Necesitaba calcular muchas distancias entre los puntos para mi proyecto, así que seguí adelante e intenté optimizar el código, que he encontrado aquí. En promedio, en diferentes navegadores mi nueva implementación se ejecuta 2 veces más rápido que la respuesta más votada.

 
function distance(lat1, lon1, lat2, lon2) {
  var p = 0.017453292519943295;    // Math.PI / 180
  var c = Math.cos;
  var a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

Puedes jugar con mi jsPerf y ver los resultados aquí .

Hace poco tuve que hacer lo mismo en python, así que aquí hay una implementación de python :

 
from math import cos, asin, sqrt
def distance(lat1, lon1, lat2, lon2):
    p = 0.017453292519943295     #Pi/180
    a = 0.5 - cos((lat2 - lat1) * p)/2 + cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2
    return 12742 * asin(sqrt(a)) #2*R*asin...

Y en aras de la integridad: Haversine en la wiki.

    
309
2019-03-19 08: 45: 18Z
  1. @ AngularM y es muy probable que Google calcule la distancia si va a tomar algunas carreteras y no una línea recta.
    2016-04-16 23: 53: 08Z
  2. Google calcula la distancia de conducción, esto calcula "a vuelo de pájaro"
    2016-08-09 22: 24: 30Z
  3. @ Ouadie y ¿mejorará la velocidad? Probablemente no, pero terminaré con un montón de "tus cosas no funcionan" para las personas que las copen en navegadores antiguos
    2017-01-27 19: 58: 42Z
  4. bueno, sí, pero ¿qué significa // 2 * R; R = 6371 km? ¿Y el método actual proporciona respuesta en km o millas? Necesita mejor documentacion. Gracias
    2017-08-22 20: 25: 37Z
  5. @ KhalilKhalaf, ¿estás bromeando o intentando hacer trolls aquí? km representa kilómetros. ¿Qué crees que significa R (especialmente si hablamos de un shpere)? Adivina en qué unidades será la respuesta si ya ves el km. Qué tipo de documentación está buscando aquí: hay literalmente 4 líneas allí.
    2017-08-22 21: 22: 35Z

Aquí hay una implementación de C #:

 
static class DistanceAlgorithm
{
    const double PIx = 3.141592653589793;
    const double RADIUS = 6378.16;

    /// <summary>
    /// Convert degrees to Radians
    /// </summary>
    /// <param name="x">Degrees</param>
    /// <returns>The equivalent in radians</returns>
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// <summary>
    /// Calculate the distance between two places.
    /// </summary>
    /// <param name="lon1"></param>
    /// <param name="lat1"></param>
    /// <param name="lon2"></param>
    /// <param name="lat2"></param>
    /// <returns></returns>
    public static double DistanceBetweenPlaces(
        double lon1,
        double lat1,
        double lon2,
        double lat2)
    {
        double dlon = Radians(lon2 - lon1);
        double dlat = Radians(lat2 - lat1);

        double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
        double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        return angle * RADIUS;
    }

}
    
63
2019-02-22 09: 52: 58Z
  1. Estás usando el radio ecuatorial, pero debes usar el radio medio, que es de 6371 km
    2009-07-10 12: 18: 21Z
  2. No debería ser double dlon = Radians(lon2 - lon1); y double dlat = Radians(lat2 - lat1);
    2010-01-15 15: 40: 33Z
  3. Estoy de acuerdo con Chris Marisic. Usé el código original y los cálculos fueron incorrectos. Agregué la llamada para convertir los deltas en radianes y ahora funciona correctamente. Envié una edición y estoy esperando a que sea revisada por pares.
    2011-12-04 04: 53: 28Z
  4. Envié otra edición porque lat1 & Lat2 también necesita ser convertido a radianes. También revisé la fórmula para la asignación a a para que coincida con la fórmula y el código que se encuentra aquí: movable-type.co.uk/scripts/latlong.html
    2011-12-04 06: 48: 13Z
  5. ¿el valor RADIUS debe ser 6371 como en las otras respuestas?
    2019-01-23 18: 02: 16Z

Aquí hay una implementación en java de la fórmula de Haversine.

 
public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
  double venueLat, double venueLng) {

    double latDistance = Math.toRadians(userLat - venueLat);
    double lngDistance = Math.toRadians(userLng - venueLng);

    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
      + Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
      * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);

    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}

Tenga en cuenta que aquí estamos redondeando la respuesta al km más cercano.

    
54
2016-11-29 09: 19: 04Z
  1. Si quisiéramos calcular la distancia entre dos puntos en metros, ¿cuál sería la forma más precisa? ¿Para usar 6371000 como el radio de la tierra? (el radio promedio de la tierra es de 6371000 metros) o convierta kilómetros a metros desde su función?
    2016-12-12 18: 29: 26Z

Muchas gracias por todo esto. Usé el siguiente código en mi aplicación para iPhone Objective-C:

 
const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km

double convertToRadians(double val) {

   return val * PIx / 180;
}

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

        double dlon = convertToRadians(place2.longitude - place1.longitude);
        double dlat = convertToRadians(place2.latitude - place1.latitude);

        double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
        double angle = 2 * asin(sqrt(a));

        return angle * RADIO;
}

La latitud y la longitud están en decimal. No usé min () para la llamada asin () ya que las distancias que estoy usando son tan pequeñas que no las requieren.

Dio respuestas incorrectas hasta que pasé los valores en radianes. Ahora son casi los mismos valores que los obtenidos en la aplicación Map de Apple :-)

Actualización adicional:

Si está utilizando iOS4 o posterior, Apple proporciona algunos métodos para hacer esto, de modo que se pueda lograr la misma funcionalidad con:

 
-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

    MKMapPoint  start, finish;


    start = MKMapPointForCoordinate(place1);
    finish = MKMapPointForCoordinate(place2);

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}
    
42
2014-07-31 01: 26: 41Z
  1. ¿Importa si lo uso en una aplicación de iOS en la que estoy trabajando? ACTUALIZADO :)
    2014-08-20 23: 00: 06Z
  2. Lo siento por el retraso (!), pero por supuesto está bien. :-)
    2015-04-24 11: 33: 30Z
  3. iOS SDK tiene su propia implementación: developer.apple.com/library/ios/documentation/CoreLocation/… :
    2016-03-27 12: 15: 26Z
  4. Creo que el paréntesis alrededor de pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude)) es incorrecto. Elimine esos, y el resultado coincide con lo que obtengo cuando uso otras implementaciones en esta página, o implemente la fórmula Haversine de Wikipedia desde cero.
    2019-01-17 19: 33: 00Z
  5. Usando las coordenadas (40.7127837, -74.0059413) para NYC y (34.052234, -118.243685) para LA, con el () alrededor de esa suma, obtengo 3869.75. Sin ellos, obtengo 3935.75, que es más o menos lo que aparece en una búsqueda web.
    2019-01-17 19: 39: 26Z

Esta es una función PHP simple que proporcionará una aproximación muy razonable (con un margen de error de +/- 1%).

 
<?php
function distance($lat1, $lon1, $lat2, $lon2) {

    $pi80 = M_PI / 180;
    $lat1 *= $pi80;
    $lon1 *= $pi80;
    $lat2 *= $pi80;
    $lon2 *= $pi80;

    $r = 6372.797; // mean radius of Earth in km
    $dlat = $lat2 - $lat1;
    $dlon = $lon2 - $lon1;
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
    $km = $r * $c;

    //echo '<br/>'.$km;
    return $km;
}
?>

Como se dijo antes; La tierra NO es una esfera. Es como un viejo y viejo béisbol con el que Mark McGwire decidió practicar, está lleno de abolladuras y golpes. Los cálculos más simples (como este) trcómetelo como una esfera.

Los diferentes métodos pueden ser más o menos precisos según dónde se encuentre en este ovoide irregular Y cuán separados están sus puntos (cuanto más cerca están, menor es el margen de error absoluto). Cuanto más precisa sea su expectativa, más complejas serán las matemáticas.

Para obtener más información: distancia geográfica de wikipedia

    
37
2017-06-22 20: 33: 20Z
  1. ¡Esto funciona perfectamente! Acabo de agregar $distance_miles = $km * 0.621371; ¡Y eso es todo lo que necesitaba para la distancia aproximada en millas! Gracias Tony.
    2014-08-08 05: 17: 57Z
  2. ¡Este código es 100% preciso, no como los demás! Lo probé todo.
    2017-07-08 07: 55: 26Z

Publico aquí mi ejemplo de trabajo.

Enumere todos los puntos en la tabla que tienen distancia entre un punto designado (usamos un punto aleatorio - lat: 45.20327, largo: 23.7806) menos de 50 KM, con latitud y amp; longitud, en MySQL (los campos de la tabla son coord_lat y coord_long):

Enumere todos los que tienen DISTANCIA < 50, en Kilómetros (considerado radio de la Tierra 6371 KM):

 
SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta 
FROM obiective 
WHERE coord_lat<>'' 
    AND coord_long<>'' 
HAVING distanta<50 
ORDER BY distanta desc

El ejemplo anterior se probó en MySQL 5.0.95 y 5.5.16 (Linux).

    
28
2014-07-31 01: 31: 00Z
  1. Creo que un buen enfoque podría ser el filtrado previo de los resultados mediante una aproximación, por lo que la fórmula pesada se aplica solo en algunos casos. Especialmente útil si tienes otras condiciones. Estoy usando esto para la aproximación inicial: stackoverflow.com/questions/1253499/…
    2017-05-19 20: 57: 36Z
  2. ¿Funciona para puntos que no son WGS84?
    2018-06-17 15: 56: 54Z

En las otras respuestas, una implementación en falta.

Calcular la distancia entre dos puntos es bastante sencillo con la función distm del paquete geosphere:

 
distm(p1, p2, fun = distHaversine)

donde:

 
p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid 

Como la Tierra no es perfectamente esférica, la Fórmula de Vincenty para elipsoides es probablemente la La mejor manera de calcular distancias. Así, en el paquete geosphere que usas entonces:

 
distm(p1, p2, fun = distVincentyEllipsoid)

Por supuesto, no necesariamente tiene que usar el paquete geosphere, también puede calcular la distancia en la base R con una función:

 
hav.dist <- function(long1, lat1, long2, lat2) {
  R <- 6371
  diff.long <- (long2 - long1)
  diff.lat <- (lat2 - lat1)
  a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
  b <- 2 * asin(pmin(1, sqrt(a))) 
  d = R * b
  return(d)
}
    
26
2018-06-15 13: 35: 00Z
  1. Para asegurarme de que tengo claro lo que dijo: el código que da al final del post: ¿Es eso una implementación de la fórmula de Vincenty? Por lo que sabe, ¿debería dar la misma respuesta que llamar a Vincenty en la geosfera? [No tengo geosfera u otra biblioteca; Solo busco un código para incluir en una aplicación multiplataforma. Por supuesto, verificaría algunos casos de prueba con una buena calculadora conocida.]
    2018-11-25 15: 16: 24Z
  2. @ ToolmakerSteve la función al final de mi respuesta es una implementación del método Haversine
    2018-11-25 15: 23: 29Z

El haversine es definitivamente una buena fórmula para la mayoría de los casos, otras respuestas ya lo incluyen, así que no voy a tomar el espacio. Pero es importante tener en cuenta que no importa qué fórmula se use (sí, no solo una). Debido a la gran variedad de precisión posible, así como el tiempo de cálculo requerido. La elección de la fórmula requiere un poco más de reflexión que una respuesta sencilla y sencilla.

Esta publicación de una persona de la NASA es la mejor que encontré al analizar las opciones

http://www.cs.nyu.edu/visual /home /proj /tiger /gisfaq.html

Por ejemplo, si solo está ordenando filas por distancia en un radio de 100 millas. La fórmula de la tierra plana será mucho más rápida que la haversine.

 
HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/

a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;

Note que solo hay un coseno y una raíz cuadrada. Vs 9 de ellos en la fórmula de Haversine.

    
9
2013-11-04 16: 20: 08Z

Puede usar la compilación en CLLocationDistance para calcular esto:

 
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]

- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
    CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
    return distanceInMeters;
}

En tu caso, si quieres kilómetros, simplemente divide por 1000.

    
7
2013-06-26 08: 43: 46Z

No me gusta agregar otra respuesta, pero la API de Google maps v.3 tiene geometría esférica (y más). Después de convertir su WGS84 a grados decimales, puede hacer esto:

 
<script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>  

distance = google.maps.geometry.spherical.computeDistanceBetween(
    new google.maps.LatLng(fromLat, fromLng), 
    new google.maps.LatLng(toLat, toLng));

No se sabe qué tan precisos son los cálculos de Google o incluso qué modelo se usa (aunque dice "esférico" en lugar de "geoide". Por cierto, la distancia de "línea recta" obviamente será diferente de la distancia si uno viaja sobre la superficie de la tierra, que es lo que todos parecen estar suponiendo.

    
7
2014-07-20 00: 10: 07Z
  1. la distancia está en metros. alternativamente, se puede usar computeLength ()
    2016-02-26 17: 08: 25Z

Implementación de Python El origen es el centro de los Estados Unidos contiguos.

 
from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)

Para obtener la respuesta en kilómetros, simplemente configure millas = falso.

    
6
2015-07-14 05: 52: 12Z
  1. Estás importando un paquete no estándar que hace todo el trabajo. No sé si eso es tan útil.
    2015-12-01 01: 23: 01Z
  2. El paquete está en el PyPI, el Índice de Paquetes de Python, como un paquete de python 3 junto con numpy y scikit-learn. No estoy seguro de por qué uno se ajusta a paquetes. Tienden a ser bastante útiles. Como fuente abierta, también se podrían examinar los métodos contenidos. Creo que a muchos les parecería útil este paquete, así que dejaré la publicación a pesar del voto negativo. Aclamaciones. :)
    2016-06-30 16: 55: 35Z

Podría haber una solución más simple y más correcta: el perímetro de la tierra es de 40,000 km en el ecuador, aproximadamente 37,000 en el ciclo de Greenwich (o cualquier longitud). Así:

 
pythagoras = function (lat1, lon1, lat2, lon2) {
   function sqr(x) {return x * x;}
   function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}

   var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
   var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
   var dy = 37000000.0 * (lat1 - lat2) / 360.0;

   return Math.sqrt(sqr(dx) + sqr(dy));
};

Estoy de acuerdo en que debería ajustarse, ya que yo mismo dije que es un elipsoide, por lo que el radio que se multiplica por el coseno varía. Pero es un poco más preciso. Comparado con Google Maps, redujo significativamente el error.

    
6
2016-02-10 07: 26: 41Z
  1. ¿Esta función devuelve la distancia?en km?
    2016-10-15 17: 34: 01Z
  2. Lo es, solo porque el ecuador y los ciclos de longitud están en Km. Para millas, simplemente divida 40000 y 37000 por 1.6. Sintiéndose geek, puedes convertirlo en Ris, multiplicar por aproximadamente 7 o parasang, dividiendo por 2.2 ;-)
    2016-10-17 04: 46: 20Z
  3. Esta parece ser la mejor respuesta ofrecida aquí. Deseo usarlo, pero me pregunto si hay una manera de verificar la exactitud de este algoritmo. He probado f (50,5,58,3). Da 832 km, mientras que movable-type.co.uk/scripts/latlong.html usando la fórmula 'haversine' da 899 km. ¿Hay una diferencia tan grande?
    2018-04-19 07: 44: 34Z
  4. Además, creo que el valor devuelto por el código anterior está en m, y no en km.
    2018-04-19 07: 45: 52Z
  5. @ ChongLipPhang - PRECAUCIÓN: el teorema de Pitágoras es solo una aproximación razonable para áreas pequeñas , ya que este teorema asume que la tierra es plana. Como caso extremo, comience en el ecuador y muévase 90 grados al este y 90 grados al norte. El resultado final, por supuesto, es el polo norte, y es lo mismo que moverse 0 grados al este y 90 grados al norte; por lo tanto, hacer sqrt (sqr (dx) + sqr (dy)) se volverá loco en el primer caso. ~ sqrt (10km sqr + 10km sqr) ~ = 14.4 km frente a la distancia correcta ~ 10km.
    2018-11-24 16: 39: 26Z

Todas las respuestas anteriores asumen que la tierra es una esfera. Sin embargo, una aproximación más precisa sería la de un esferoide oblato.

 
a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km

def Distance(lat1, lons1, lat2, lons2):
    lat1=math.radians(lat1)
    lons1=math.radians(lons1)
    R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
    x1=R*math.cos(lat1)*math.cos(lons1)
    y1=R*math.cos(lat1)*math.sin(lons1)
    z1=R*math.sin(lat1)

    lat2=math.radians(lat2)
    lons2=math.radians(lons2)
    R1=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
    x2=R*math.cos(lat2)*math.cos(lons2)
    y2=R*math.cos(lat2)*math.sin(lons2)
    z2=R*math.sin(lat2)

    return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5
    
6
2016-06-16 22: 25: 37Z

Aquí hay una implementación mecanografiada de la fórmula de Haversine

 
static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
    var deg2Rad = deg => {
        return deg * Math.PI / 180;
    }

    var r = 6371; // Radius of the earth in km
    var dLat = deg2Rad(lat2 - lat1);   
    var dLon = deg2Rad(lon2 - lon1);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2Rad(lat1)) * Math.cos(deg2Rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = r * c; // Distance in km
    return d;
}
    
5
2015-12-26 08: 13: 11Z

Este script [en PHP] calcula distancias entre los dos puntos.

 
public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
        $lat1 = $source[0];
        $lon1 = $source[1];
        $lat2 = $dest[0];
        $lon2 = $dest[1];

        $theta = $lon1 - $lon2;
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);

        if ($unit == "K") {
            return ($miles * 1.609344);
        }
        else if ($unit == "M")
        {
            return ($miles * 1.609344 * 1000);
        }
        else if ($unit == "N") {
            return ($miles * 0.8684);
        } 
        else {
            return $miles;
        }
    }
    
4
2017-02-21 07: 04: 55Z

Aquí está la implementación de SQL para calcular la distancia en km,

 
SELECT UserId, ( 3959 * acos( cos( radians( your latitude here ) ) * cos( radians(latitude) ) * 
cos( radians(longitude) - radians( your longitude here ) ) + sin( radians( your latitude here ) ) * 
sin( radians(latitude) ) ) ) AS distance FROM user HAVING
distance < 5  ORDER BY distance LIMIT 0 , 5;

Para obtener más información sobre la implementación mediante la programación de idioma, puede ir a través del script php proporcionado aquí

    
4
2019-06-11 13: 44: 48Z

Para calcular la distancia entre dos puntos en una esfera, debes hacer cálculo de Gran Círculo .

Hay una serie de bibliotecas C /C ++ para ayudar con la proyección de mapas en MapTools si necesita Reproyecta tus distancias a una superficie plana. Para ello, necesitará la cadena de proyección de los distintos sistemas de coordenadas.

También puede encontrar MapWindow una herramienta útil para visualizar los puntos. También como su código abierto es una guía útil sobre cómo usar la biblioteca proj.dll, que parece ser la biblioteca principal de proyecciones de código abierto.

    
3
2008-10-19 01: 30: 09Z

Aquí está la implementación de la respuesta aceptada portada a Java en caso de que alguien la necesite.

 
package com.project529.garage.util;


/**
 * Mean radius.
 */
private static double EARTH_RADIUS = 6371;

/**
 * Returns the distance between two sets of latitudes and longitudes in meters.
 * <p/>
 * Based from the following JavaScript SO answer:
 * http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
 * which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
 */
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
    double dLat = toRadians(lat2 - lat1);
    double dLon = toRadians(lon2 - lon1);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                    Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = EARTH_RADIUS * c;

    return d;
}

public double toRadians(double degrees) {
    return degrees * (Math.PI / 180);
}
    
3
2015-10-12 20: 59: 53Z

Como se señaló, un cálculo preciso debería tener en cuenta que la Tierra no es una esfera perfecta. Aquí hay algunas comparaciones de los diversos algoritmos ofrecidos aquí:

 
geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km

geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km

geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km

geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km

En distancias pequeñas, el algoritmo de Keerthana parece coincidir con el de Google Maps. Google Maps no parece seguir ningún algoritmo simple, lo que sugiere que puede ser el método más preciso aquí.

De todos modos, aquí hay una implementación de Javascript del algoritmo de Keerthana:

 
function geoDistance(lat1, lng1, lat2, lng2){
    const a = 6378.137; // equitorial radius in km
    const b = 6356.752; // polar radius in km

    var sq = x => (x*x);
    var sqr = x => Math.sqrt(x);
    var cos = x => Math.cos(x);
    var sin = x => Math.sin(x);
    var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));

    lat1 = lat1 * Math.PI / 180;
    lng1 = lng1 * Math.PI / 180;
    lat2 = lat2 * Math.PI / 180;
    lng2 = lng2 * Math.PI / 180;

    var R1 = radius(lat1);
    var x1 = R1*cos(lat1)*cos(lng1);
    var y1 = R1*cos(lat1)*sin(lng1);
    var z1 = R1*sin(lat1);

    var R2 = radius(lat2);
    var x2 = R2*cos(lat2)*cos(lng2);
    var y2 = R2*cos(lat2)*sin(lng2);
    var z2 = R2*sin(lat2);

    return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}
    
3
2018-04-19 09: 14: 27Z

Aquí está la implementación VB.NET, esta implementación le dará el resultado en KM o Millas según el valor Enum que pase.

 
Public Enum DistanceType
    Miles
    KiloMeters
End Enum

Public Structure Position
    Public Latitude As Double
    Public Longitude As Double
End Structure

Public Class Haversine

    Public Function Distance(Pos1 As Position,
                             Pos2 As Position,
                             DistType As DistanceType) As Double

        Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)

        Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)

        Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)

        Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)

        Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))

        Dim result As Double = R * c

        Return result

    End Function

    Private Function toRadian(val As Double) As Double

        Return (Math.PI / 180) * val

    End Function

End Class
    
2
2013-04-02 08: 35: 43Z

Condensé el cálculo al simplificar la fórmula.

Aquí está en Ruby:

 
include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }

# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
  from, to = coord_radians[from], coord_radians[to]
  cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
  sines_product = sin(to[:lat]) * sin(from[:lat])
  return earth_radius_mi * acos(cosines_product + sines_product)
end
    
2
2013-06-13 02: 28: 45Z
 
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; 
  var miles = d / 1.609344; 

if ( units == 'km' ) {  
return d; 
 } else {
return miles;
}}

La solución de Chuck, válida para millas también.

    
2
2013-11-08 06: 34: 35Z

Aquí está mi implementación de java para calcular la distancia a través de grados decimales después de alguna búsqueda. Utilicé el radio medio del mundo (de wikipedia) en km. Si quieres millas, usa el radio mundial en millas.

 
public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2) 
{
  double earthRadius = 6371.0d; // KM: use mile here if you want mile result

  double dLat = toRadian(lat2 - lat1);
  double dLng = toRadian(lng2 - lng1);

  double a = Math.pow(Math.sin(dLat/2), 2)  + 
          Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) * 
          Math.pow(Math.sin(dLng/2), 2);

  double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

  return earthRadius * c; // returns result kilometers
}

public static double toRadian(double degrees) 
{
  return (degrees * Math.PI) / 180.0d;
}
    
2
2014-02-12 20: 52: 42Z

En Mysql, use la siguiente función, pase los parámetros usando POINT(LONG,LAT)

 
CREATE FUNCTION `distance`(a POINT, b POINT)
 RETURNS double
    DETERMINISTIC
BEGIN

RETURN

GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters

END;
    
2
2014-05-28 08: 59: 44Z
 
function getDistanceFromLatLonInKm(position1, position2) {
    "use strict";
    var deg2rad = function (deg) { return deg * (Math.PI / 180); },
        R = 6371,
        dLat = deg2rad(position2.lat - position1.lat),
        dLng = deg2rad(position2.lng - position1.lng),
        a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(position1.lat))
            * Math.cos(deg2rad(position1.lat))
            * Math.sin(dLng / 2) * Math.sin(dLng / 2),
        c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
}

console.log(getDistanceFromLatLonInKm(
    {lat: 48.7931459, lng: 1.9483572},
    {lat: 48.827167, lng: 2.2459745}
));
    
2
2015-04-29 14: 22: 25Z

aquí hay un ejemplo en postgres sql (en km, para la versión de millas, reemplace 1.609344 por la versión 0.8684)

 
CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat  

float, blng  float)
  RETURNS float AS
$BODY$
DECLARE
    v_distance float;
BEGIN

    v_distance = asin( sqrt(
            sin(radians(blat-alat)/2)^2 
                + (
                    (sin(radians(blng-alng)/2)^2) *
                    cos(radians(alat)) *
                    cos(radians(blat))
                )
          )
        ) * cast('7926.3352' as float) * cast('1.609344' as float) ;


    RETURN v_distance;
END 
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;
    
2
2016-12-21 07: 34: 02Z

aquí hay un buen ejemplo para calcular la distancia con PHP http://www.geodatasource.com/desarrolladores /php :

 
 function distance($lat1, $lon1, $lat2, $lon2, $unit) {

     $theta = $lon1 - $lon2;
     $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
     $dist = acos($dist);
     $dist = rad2deg($dist);
     $miles = $dist * 60 * 1.1515;
     $unit = strtoupper($unit);

     if ($unit == "K") {
         return ($miles * 1.609344);
     } else if ($unit == "N") {
          return ($miles * 0.8684);
     } else {
          return $miles;
     }
 }
    
1
2013-01-15 01: 48: 23Z

Tuve un problema con math.deg en LUA ... si alguien sabe una solución, ¡limpia este código!

Mientras tanto, aquí hay una implementación de Haversine en LUA (¡usa esto con Redis!)

 
function calcDist(lat1, lon1, lat2, lon2)
    lat1= lat1*0.0174532925
    lat2= lat2*0.0174532925
    lon1= lon1*0.0174532925
    lon2= lon2*0.0174532925

    dlon = lon2-lon1
    dlat = lat2-lat1

    a = math.pow(math.sin(dlat/2),2) + math.cos(lat1) * math.cos(lat2) * math.pow(math.sin(dlon/2),2)
    c = 2 * math.asin(math.sqrt(a))
    dist = 6371 * c      -- multiply by 0.621371 to convert to miles
    return dist
end

¡salud!

    
1
2014-11-30 20: 56: 42Z

Aquí hay otro código convertido a Ruby :

 
include Math
#Note: from/to = [lat, long]

def get_distance_in_km(from, to)
  radians = lambda { |deg| deg * Math.PI / 180 }
  radius = 6371 # Radius of the earth in kilometer
  dLat = radians[to[0]-from[0]]
  dLon = radians[to[1]-from[1]]

  cosines_product = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(radians[from[0]]) * Math.cos(radians[to[1]]) * Math.sin(dLon/2) * Math.sin(dLon/2)

  c = 2 * Math.atan2(Math.sqrt(cosines_product), Math.sqrt(1-cosines_product)) 
  return radius * c # Distance in kilometer
end
    
1
2017-10-16 13: 21: 00Z
fuente colocada aquí