2010-09-12 19 views
53

estoy tratando de resolver esta tarea y se está tomando demasiado tiempo:Calculando la distancia entre dos puntos, usando la longitud de latitud, ¿qué estoy haciendo mal?

Aquí está mi intento, que es sólo un fragmento de mi código:

final double RADIUS = 6371.01; 
double temp = Math.cos(Math.toRadians(latA)) 
      * Math.cos(Math.toRadians(latB)) 
      * Math.cos(Math.toRadians((latB) - (latA))) 
      + Math.sin(Math.toRadians(latA)) 
      * Math.sin(Math.toRadians(latB)); 
    return temp * RADIUS * Math.PI/180; 

estoy usando esta fórmula para obtener la latitud y longitud: x = Deg + (Min + Sec/60)/60)

Gracias

Respuesta

118

El código de Java proporcionado por Dommer muestra resultados ligeramente incorrectos, pero los pequeños errores se suman si está procesando, digamos una pista de GPS. Aquí hay una implementación del método Haversine en Java que también tiene en cuenta las diferencias de altura entre dos puntos.

/** 
* Calculate distance between two points in latitude and longitude taking 
* into account height difference. If you are not interested in height 
* difference pass 0.0. Uses Haversine method as its base. 
* 
* lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters 
* el2 End altitude in meters 
* @returns Distance in Meters 
*/ 
public static double distance(double lat1, double lat2, double lon1, 
     double lon2, double el1, double el2) { 

    final int R = 6371; // Radius of the earth 

    double latDistance = Math.toRadians(lat2 - lat1); 
    double lonDistance = Math.toRadians(lon2 - lon1); 
    double a = Math.sin(latDistance/2) * Math.sin(latDistance/2) 
      + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) 
      * Math.sin(lonDistance/2) * Math.sin(lonDistance/2); 
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 
    double distance = R * c * 1000; // convert to meters 

    double height = el1 - el2; 

    distance = Math.pow(distance, 2) + Math.pow(height, 2); 

    return Math.sqrt(distance); 
} 
+6

¿Por qué no Math.toRadians() en lugar de deg2rad()? Sería realmente autosuficiente. –

+2

@DavidG: ¿Cuál es la unidad de la salida? –

+2

@Bala - Es malo, está en el comentario sobre el código en mi computadora pero falta aquí. Distancia en metros –

61

Aquí hay una Java function that calculates the distance between two lat/long points.

Editar

He encontrado another reference to the code.

Y, publicado a continuación, en caso de que desaparezca nuevamente.

private double distance(double lat1, double lon1, double lat2, double lon2, char unit) { 
     double theta = lon1 - lon2; 
     double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); 
     dist = Math.acos(dist); 
     dist = rad2deg(dist); 
     dist = dist * 60 * 1.1515; 
     if (unit == 'K') { 
     dist = dist * 1.609344; 
     } else if (unit == 'N') { 
     dist = dist * 0.8684; 
     } 
     return (dist); 
    } 

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ 
    /*:: This function converts decimal degrees to radians    :*/ 
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ 
    private double deg2rad(double deg) { 
     return (deg * Math.PI/180.0); 
    } 

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ 
    /*:: This function converts radians to decimal degrees    :*/ 
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ 
    private double rad2deg(double rad) { 
     return (rad * 180.0/Math.PI); 
    } 

    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n"); 
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilometers\n"); 
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Nautical Miles\n"); 
+1

desgracia - 404 No encontrado – svenkapudija

+0

actualiza con nuevo enlace y el código. – dommer

+3

funciona simplemente arregla la cotización de la unidad ... su char no es doble ... –

4

Aquí hay una página con ejemplos de JavaScript para varios cálculos esféricos. El primero en la página debe darle lo que necesita.

http://www.movable-type.co.uk/scripts/latlong.html

Este es el código Javascript

var R = 6371; // km 
var dLat = (lat2-lat1).toRad(); 
var dLon = (lon2-lon1).toRad(); 
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
     Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) * 
     Math.sin(dLon/2) * Math.sin(dLon/2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c; 

Donde 'd' llevará a cabo la distancia.

+0

¿Puede "a" alguna vez ser negativo? –

0

Esta wikipedia article proporciona las fórmulas y un ejemplo. El texto está en alemán, pero los cálculos hablan por sí mismos.

9

Nota: esta solución solo funciona para distancias cortas.

Traté de usar la fórmula publicada de dommer para una aplicación y encontré que funcionaba bien para largas distancias, pero en mis datos estaba usando todas las distancias muy cortas, y la publicación de dommer hizo muy mal. Necesitaba velocidad, y los geocalcos más complejos funcionaban bien pero eran demasiado lentos. Entonces, en el caso de que necesite velocidad y todos los cálculos que está haciendo son cortos (quizás < 100m más o menos). Encontré esta pequeña aproximación para que funcione bien. asume que el mundo es plano, así que no lo use para largas distancias, funciona al aproximar la distancia de una sola Latitud y Longitud a la Latitud dada y devolver la distancia pitagórica en metros.

public class FlatEarthDist { 
    //returns distance in meters 
    public static double distance(double lat1, double lng1, 
             double lat2, double lng2){ 
    double a = (lat1-lat2)*FlatEarthDist.distPerLat(lat1); 
    double b = (lng1-lng2)*FlatEarthDist.distPerLng(lat1); 
    return Math.sqrt(a*a+b*b); 
    } 

    private static double distPerLng(double lat){ 
     return 0.0003121092*Math.pow(lat, 4) 
      +0.0101182384*Math.pow(lat, 3) 
       -17.2385140059*lat*lat 
      +5.5485277537*lat+111301.967182595; 
    } 

    private static double distPerLat(double lat){ 
      return -0.000000487305676*Math.pow(lat, 4) 
       -0.0033668574*Math.pow(lat, 3) 
       +0.4601181791*lat*lat 
       -1.4558127346*lat+110579.25662316; 
    } 
} 
1
package distanceAlgorithm; 

public class CalDistance { 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
    CalDistance obj=new CalDistance(); 
    /*obj.distance(38.898556, -77.037852, 38.897147, -77.043934);*/ 
     System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "M") + " Miles\n"); 
     System.out.println(obj.distance(38.898556, -77.037852, 38.897147, -77.043934, "K") + " Kilometers\n"); 
     System.out.println(obj.distance(32.9697, -96.80322, 29.46786, -98.53506, "N") + " Nautical Miles\n");  
    } 
    public double distance(double lat1, double lon1, double lat2, double lon2, String sr) { 


      double theta = lon1 - lon2; 
      double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta)); 
      dist = Math.acos(dist); 
      dist = rad2deg(dist); 
      dist = dist * 60 * 1.1515; 
      if (sr.equals("K")) { 
      dist = dist * 1.609344; 
      } else if (sr.equals("N")) { 
      dist = dist * 0.8684; 
      } 
      return (dist); 
     } 
    public double deg2rad(double deg) { 
      return (deg * Math.PI/180.0); 
     } 
    public double rad2deg(double rad) { 
      return (rad * 180.0/Math.PI); 
     } 


    } 
Cuestiones relacionadas