2010-09-12 14 views
53

Próbuję rozwiązać to zadanie i to zabiera zbyt dużo czasu:Obliczanie odległości między dwoma punktami, używając długości geograficznej, co robię źle?

Oto moja próba, to tylko fragment mojego kodu:

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; 

Używam tej formuły, aby uzyskać swobodę i Długość: x = DEG + (Min + s/60)/60)

Dzięki

Odpowiedz

118

Kod Java podany przez Dommer powyżej daje nieco niepoprawne wyniki, ale małe błędy sumują się, jeśli przetwarzasz, mówią ścieżkę GPS. Oto implementacja metody Haversine w Javie, która uwzględnia również różnice wysokości między dwoma punktami.

/** 
* 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

Dlaczego nie Math.toRadians() zamiast deg2rad()? Byłoby to naprawdę samo-zawierające się. –

+2

@DavidG: Jaka jest jednostka wyjścia? –

+2

@Bala - Mój zły, jest w komentarzu do kodu na moim komputerze, ale brakuje go tutaj. Odległość w metrach. –

61

Oto Java function that calculates the distance between two lat/long points.

Edit

znalazłem another reference to the code.

I, zamieszczone poniżej, na wypadek, gdyby znowu zniknął.

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

Niestety - 404 Not Found – svenkapudija

+0

aktualizowana o nowe łącza i kodu. – dommer

+3

działa tylko naprawić ofertę na jednostkę .. jej znak, więc pojedynczy cytat nie jest podwójny .. –

4

Oto strona z przykładami javascript dla różnych obliczeń sferycznych. Pierwszy na stronie powinien dać ci to, czego potrzebujesz.

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

Oto kod 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; 

Gdzie 'd' będą trzymać dystans.

+0

Czy "a" może być zawsze negatywne? –

0

Ta wikipedia article dostarcza formuły i przykład. Tekst jest w języku niemieckim, ale obliczenia mówią same za siebie.

9

Uwaga: to rozwiązanie działa tylko na krótkich dystansach.

Próbowałem użyć napisanej przez dommer formuły dla aplikacji i stwierdziłem, że dobrze działa na duże odległości, ale w moich danych wykorzystywałem wszystkie bardzo krótkie odległości, a post dommer bardzo źle. Potrzebowałem prędkości, a bardziej złożone geo-kalcy działały dobrze, ale były zbyt powolne. Tak więc, w przypadku, gdy potrzebujesz prędkości i wszystkich obliczeń, które robisz są krótkie (może < 100m lub więcej). Zauważyłem, że to małe przybliżenie działa świetnie. zakłada, że ​​świat jest płaski, więc nie używaj go na duże odległości, działa w przybliżeniu na odległość jednej szerokości i długości geograficznej na danej szerokości geograficznej i zwraca odległość pitagorejską w metrach.

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


    } 
Powiązane problemy