395 votos

¿Cómo puedo calcular la distancia entre dos puntos de latitud y longitud?

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

Para mayor claridad, me gustaría que la distancia en kilómetros; los puntos utilizan el sistema WGS84 y me gustaría entender las precisiones relativas de los métodos disponibles.

495voto

Chuck Puntos 8847

Este enlace puede ser de ayuda para usted, como detalla el uso de la Haversine fórmula para calcular la distancia.

Extracto:

Esta secuencia de comandos [Javascript] calcula gran círculo distancias entre los dos puntos - es decir, la distancia más corta sobre la superficie de la tierra - el uso de la 'Haversine de la fórmula.

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

43voto

Aquí es un C # Aplicación:

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

    /// <summary>
    /// This class cannot be instantiated.
    /// </summary>
    private DistanceAlgorithm() { }

    /// <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;
    }
 

38voto

Stephen Watson Puntos 379

Muchas gracias por todo esto. He utilizado el siguiente código en mi Objective-C para iPhone de la aplicación:

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;
}

Latitud y Longitud están en decimal. Yo no uso min() para el asin() llamada como las distancias que estoy usando son tan pequeñas que no requieran.

Se dieron respuestas incorrectas hasta que me pasó en los valores en Radianes - ahora es casi el mismo que los valores obtenidos a partir de Apple, la app de Mapas :-)

Extra actualización:

Si usted está usando iOS4 o más tarde, a continuación, Apple proporcionar algunos métodos para hacerlo, de forma que la misma funcionalidad se lograría con:

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

    MKMapPoint  start, finish;


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

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}

34voto

whostolebenfrog Puntos 348

Aquí es una aplicación java de la fórmula Haversine.

 public final static double AVERAGE_RADIUS_OF_EARTH = 6371;
public int calculateDistance(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 * c));
}
 

Tenga en cuenta que aquí estamos juntando la respuesta a la más cercana km.

18voto

conualfy Puntos 318

He puesto aquí mi ejemplo de trabajo.

Lista de todos los puntos en la tabla de haber distancia entre un punto designado (usamos un punto al azar - lat:45.20327, largo:23.7806) a menos de 50 KM, con latitud y longitud, en MySQL (los campos de la tabla son coord_lat y coord_long):

Lista de todos DISTANCIA<50, en Kilómetros (considera la Tierra radio de 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 ha probado en MySQL 5.0.95 y 5.5.16 (Linux).

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: