1157 Stimmen

Die Distanz zwischen zwei Breitengrad-Längengrad-Punkten berechnen? (Haversine-Formel)

Wie berechne ich die Entfernung zwischen zwei Punkten, die durch Breiten- und Längengrad angegeben sind?

Zur Klarstellung möchte ich die Entfernung in Kilometern; die Punkte verwenden das WGS84-System und ich möchte die relativen Genauigkeiten der verfügbaren Methoden verstehen.

0 Stimmen

Für eine bessere Genauigkeit - siehe stackoverflow.com/questions/1420045/…

4 Stimmen

Beachten Sie, dass Sie die Haversine-Formel nicht auf einem Rotationsellipsoid wie WGS 84 anwenden können. Sie können diese Methode nur auf einer Kugel mit einem Radius anwenden.

8 Stimmen

Die meisten Antworten hier verwenden einfache sphärische Trigonometrie, daher sind die Ergebnisse im Vergleich zu den WGS84-Ellipsoidentfernungen, die im GPS-System verwendet werden, ziemlich grob. Einige der Antworten beziehen sich zwar auf die Vincenty-Formel für Ellipsoide, aber dieser Algorithmus wurde für die Verwendung auf Schreibtischrechnern aus den 1960er Jahren entwickelt und weist Stabilitäts- und Genauigkeitsprobleme auf; wir haben jetzt bessere Hardware und Software. Bitte sehen Sie GeographicLib für eine hochwertige Bibliothek mit Implementierungen in verschiedenen Sprachen.

1377voto

Dieser Link könnte Ihnen helfen, da er die Verwendung der Haversine-Formel zur Berechnung der Entfernung beschreibt.

Auszug:

Dieses Skript [in Javascript] berechnet Großkreisentfernungen zwischen den beiden Punkten - das heißt, die kürzeste Entfernung über die Erdoberfläche - unter Verwendung der 'Haversine'-Formel.

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius der Erde in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad unten
  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; // Entfernung in km
  return d;
}

function deg2rad(deg) {
  return deg * (Math.PI/180)
}

60 Stimmen

Behandelt diese Berechnung/Methode die Tatsache, dass die Erde ein Spheroid ist (keine perfekte Kugel)? Die ursprüngliche Frage bezog sich auf die Entfernung zwischen Punkten auf einem WGS84-Globus. Ich bin mir nicht sicher, wie viel Fehler entsteht, wenn man eine perfekte Kugel verwendet, aber ich vermute, es kann je nach Lage der Punkte auf der Erde ziemlich viel sein, daher ist die Unterscheidung zu beachten.

19 Stimmen

Die Haversine-Formel berücksichtigt nicht, dass die Erde ein Spheroid ist, daher wird aufgrund dieser Tatsache ein gewisser Fehler eingeführt. Es kann nicht garantiert werden, dass sie genauer als 0,5% korrekt ist. Das kann jedoch ein akzeptables Fehlerlevel sein oder auch nicht.

2 Stimmen

Umschloss die Logik in eine Funktion, damit sie standardmäßig in JS verwendet werden kann, verwende es jetzt tatsächlich in NodeJS...

504voto

Salvador Dali Punkte 197375

Ich musste viele Entfernungen zwischen den Punkten für mein Projekt berechnen, also habe ich versucht, den Code zu optimieren, den ich hier gefunden habe. Im Durchschnitt läuft meine neue Implementierung in verschiedenen Browsern 2 Mal schneller als die am meisten hochgestimmte Antwort.

function distance(lat1, lon1, lat2, lon2) {
  const r = 6371; // km
  const p = Math.PI / 180;

  const a = 0.5 - Math.cos((lat2 - lat1) * p) / 2
                + Math.cos(lat1 * p) * Math.cos(lat2 * p) *
                  (1 - Math.cos((lon2 - lon1) * p)) / 2;

  return 2 * r * Math.asin(Math.sqrt(a));
}

Sie können mit meinem jsPerf spielen und die Ergebnisse hier sehen.

Kürzlich musste ich das Gleiche in Python machen, also hier ist eine Python-Implementierung:

from math import cos, asin, sqrt, pi

def distance(lat1, lon1, lat2, lon2):
    r = 6371 # km
    p = pi / 180

    a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2
    return 2 * r * asin(sqrt(a))

Und der Vollständigkeit halber: Haversine auf Wikipedia.

2 Stimmen

Der oben genannte JS-Code scheint 40 Meilen daneben zu liegen, wenn ich ihn von km in Meilen umrechne.

1 Stimmen

@AngularM und haben Sie berechnet, dass es falsch ist? Mit was haben Sie es verglichen?

0 Stimmen

Ich habe es mit Google Maps verglichen. Es schien 40 Meilen weniger im Vergleich zu Google Maps für London nach Birmingham zu sein.

78voto

Hier ist eine C# Implementierung:

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

    /// 
    /// Konvertiert Grad in Radiant um
    /// 
    /// Grad
    /// Der Äquivalent in Radianten
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// 
    /// Berechnet die Entfernung zwischen zwei Orten.
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    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;
    }

}

15 Stimmen

Sie verwenden den Äquatorradius, aber Sie sollten den mittleren Radius verwenden, der 6371 km beträgt

7 Stimmen

Sollte das nicht sein double dlon = Radians(lon2 - lon1); und double dlat = Radians(lat2 - lat1); ?

0 Stimmen

Ich stimme Chris Marisic zu. Ich habe den originalen Code verwendet und die Berechnungen waren falsch. Ich habe den Aufruf hinzugefügt, um die Deltas in Radianten umzuwandeln und jetzt funktioniert es richtig. Ich habe eine Bearbeitung eingereicht und warte darauf, dass sie von anderen überprüft wird.

72voto

whostolebenfrog Punkte 935

Hier ist eine Java-Implementierung der Haversine-Formel.

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

Beachten Sie, dass hier die Antwort auf den nächsten km gerundet wird.

2 Stimmen

Wenn wir den Abstand zwischen zwei Punkten in Metern berechnen würden, was wäre der genauere Weg? 6371000 als Radius der Erde zu verwenden (Durchschnittlicher Radius der Erde beträgt 6371000 Meter) oder Kilometer in Meter von Ihrer Funktion umzurechnen?

0 Stimmen

Wenn Sie Meilen wünschen, multiplizieren Sie das Ergebnis mit 0.621371

43voto

Stephen Watson Punkte 1680

Vielen Dank für all dies. Ich habe den folgenden Code in meiner Objective-C iPhone-App verwendet:

const double PIx = 3,141592653589793;
const double RADIO = 6371; // Durchschnittlicher Radius der Erde in km

double convertToRadians(double val) {

   return val * PIx / 180;
}

-(double)KilometerZwischenOrt1:(CLLocationCoordinate2D) ort1 undOrt2:(CLLocationCoordinate2D) ort2 {

        double dlon = convertToRadians(ort2.longitude - ort1.longitude);
        double dlat = convertToRadians(ort2.latitude - ort1.latitude);

        double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(ort1.latitude))) * cos(convertToRadians(ort2.latitude)) * pow(sin(dlon / 2), 2);
        double winkel = 2 * asin(sqrt(a));

        return winkel * RADIO;
}

Latitude und Longitude sind in Dezimalzahlen angegeben. Ich habe min() für den asin() Aufruf nicht verwendet, da die Entfernungen, die ich benutze, so klein sind, dass es nicht erforderlich ist.

Es gab falsche Antworten, bis ich die Werte in Radian umgewandelt habe - jetzt sind sie fast gleich wie die Werte, die aus der Apple Map-App erhalten werden :-)

Zusätzliches Update:

Wenn Sie iOS4 oder neuer verwenden, bietet Apple einige Methoden, um dies zu tun, sodass die gleiche Funktionalität mit folgendem Code erreicht werden würde:

-(double)KilometerZwischenOrt1:(CLLocationCoordinate2D) ort1 undOrt2:(CLLocationCoordinate2D) ort2 {

    MKMapPoint  start, finish;

    start = MKMapPointForCoordinate(ort1);
    finish = MKMapPointForCoordinate(ort2);

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}

2 Stimmen

IOS SDK hat seine eigene Implementierung: developer.apple.com/library/ios/documentation/CoreLocation/…‌​:

0 Stimmen

Ich denke, dass die Klammern um pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude)) falsch sind. Entfernen Sie diese und das Ergebnis entspricht dem, was ich erhalte, wenn ich andere Implementierungen auf dieser Seite verwende, oder implementieren Sie die Haversine-Formel von Grund auf neu von Wikipedia.

0 Stimmen

Verwendend die Koordinaten (40.7127837, -74.0059413) für NYC und (34.052234, -118.243685) für LA, mit dem () rundherum addiert, erhalte ich 3869.75. Ohne sie erhalte ich 3935.75, was ziemlich genau dem entspricht, was eine Websuche ergibt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X