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.

1voto

Kristian K Punkte 354

Die Funktionen, die für eine genaue Berechnung der Entfernung zwischen Breiten- und Längengradpunkten benötigt werden, sind komplex und es gibt viele Fallstricke. Ich würde nicht Haversine oder andere sphärische Lösungen empfehlen, aufgrund der großen Ungenauigkeiten (die Erde ist keine perfekte Kugel). Die Vincenty-Formel ist besser, aber kann in einigen Fällen auch Fehler verursachen, selbst wenn sie korrekt codiert ist.

Statt die Funktionen selbst zu codieren, empfehle ich die Verwendung von geopy, das das sehr genaue geographiclib für Distanzberechnungen implementiert hat (Paper vom Autor).

#pip install geopy
from geopy.distance import geodesic
NY = [40.71278,-74.00594]
Beijing = [39.90421,116.40739]
print("WGS84: ",geodesic(NY, Beijing).km) #WGS84 ist Standard
print("Intl24: ",geodesic(NY, Beijing, ellipsoid='Intl 1924').km) #geopy enthält verschiedene Ellipsoide
print("Benutzerdefiniertes Ellipsoid: ",geodesic(NY, Beijing, ellipsoid=(6377., 6356., 1 / 297.)).km) #benutzerdefiniertes Ellipsoid

#unterstützte Ellipsoide:
#Modell            Hauptachse (km)   Nebenachse (km)     Abplattung
#'WGS-84':        (6378.137,    6356.7523142,  1 / 298.257223563)
#'GRS-80':        (6378.137,    6356.7523141,  1 / 298.257222101)
#'Airy (1830)':   (6377.563396, 6356.256909,   1 / 299.3249646)
#'Intl 1924':     (6378.388,    6356.911946,   1 / 297.0)
#'Clarke (1880)': (6378.249145, 6356.51486955, 1 / 293.465)
#'GRS-67':        (6378.1600,   6356.774719,   1 / 298.25)

Der einzige Nachteil dieser Bibliothek ist, dass sie keine vektorisierten Berechnungen unterstützt. Für vektorisierte Berechnungen können Sie das neue geovectorslib verwenden.

#pip install geovectorslib
from geovectorslib import inverse
print(inverse(lats1,lons1,lats2,lons2)['s12'])

Lats und Lons sind numpy Arrays. Geovectorslib ist sehr genau und extrem schnell! Ich habe jedoch noch keine Lösung für die Änderung der Ellipsoide gefunden. Das WGS84 Ellipsoid wird als Standard verwendet, was für die meisten Anwendungsfälle die beste Wahl ist.

1voto

Oleg Khalidov Punkte 4760

Dart-Sprache:

import 'dart:math' show cos, sqrt, asin;

double calculateDistance(LatLng l1, LatLng l2) {
  const p = 0.017453292519943295;
  final a = 0.5 -
      cos((l2.latitude - l1.latitude) * p) / 2 +
      cos(l1.latitude * p) *
          cos(l2.latitude * p) *
          (1 - cos((l2.longitude - l1.longitude) * p)) /
          2;
  return 12742 * asin(sqrt(a));
}

1voto

Ryan Punkte 2079

FSharp-Version, die Meilen verwendet:

let radialDistanceHaversine location1 location2 : float = 
                let degreeToRadian degrees = degrees * System.Math.PI / 180.0
                let earthRadius = 3959.0
                let deltaLat = location2.Latitude - location1.Latitude |> degreeToRadian
                let deltaLong = location2.Longitude - location1.Longitude |> degreeToRadian
                let a =
                    (deltaLat / 2.0 |> sin) ** 2.0
                    + (location1.Latitude |> degreeToRadian |> cos)
                    * (location2.Latitude |> degreeToRadian |> cos)
                    * (deltaLong / 2.0 |> sin) ** 2.0
                atan2 (a |> sqrt) (1.0 - a |> sqrt)
                * 2.0
                * earthRadius

0voto

bherto39 Punkte 1036

Hier ist eine einfache JavaScript-Funktion, die hilfreich sein könnte, von diesem Link... irgendwie relevant, aber wir verwenden das Google Earth JavaScript-Plugin anstelle von Karten

function getApproximateDistanceUnits(point1, point2) {

    var xs = 0;
    var ys = 0;

    xs = point2.getX() - point1.getX();
    xs = xs * xs;

    ys = point2.getY() - point1.getY();
    ys = ys * ys;

    return Math.sqrt(xs + ys);
}

Die Einheiten sind jedoch keine Entfernungen, sondern ein Verhältnis zu Ihren Koordinaten. Es gibt andere damit verbundene Berechnungen, die Sie für die getApproximateDistanceUnits-Funktion ersetzen können Link hier

Dann verwende ich diese Funktion, um zu sehen, ob ein Breiten- und Längengrad innerhalb des Radius liegt

function isMapPlacemarkInRadius(point1, point2, radi) {
    if (point1 && point2) {
        return getApproximateDistanceUnits(point1, point2) <= radi;
    } else {
        return 0;
    }
}

Ein Punkt kann wie folgt definiert sein

 $$.getPoint = function(lati, longi) {
        var location = {
            x: 0,
            y: 0,
            getX: function() { return location.x; },
            getY: function() { return location.y; }
        };
        location.x = lati;
        location.y = longi;

        return location;
    };

dann können Sie prüfen, ob ein Punkt innerhalb einer Region mit einem Radius liegt, sagen wir:

 // platziere es auf der Karte, wenn es innerhalb des Bereichs eines angegebenen Radius liegt, angenommen, 100.000.000 Einheiten
        var iconpoint = Map.getPoint(pp.latitude, pp.longitude);
        var centerpoint = Map.getPoint(Settings.CenterLatitude, Settings.CenterLongitude);

        // ungefähr ~200 Einheiten, um nur die Hälfte des Globus vom Standard-Mittelradius aus anzuzeigen
        if (isMapPlacemarkInRadius(centerpoint, iconpoint, 120)) {
            addPlacemark(pp.latitude, pp.longitude, pp.name);
        }
        else {
            otherSidePlacemarks.push({
                latitude: pp.latitude,
                longitude: pp.longitude,
                name: pp.name
            });

        }

0voto

Anurag Punkte 85
function distance($lat1, $lon1, $lat2, $lon2) { 
    $pi80 = M_PI / 180; 
    $lat1 *= $pi80; $lon1 *= $pi80; $lat2 *= $pi80; $lon2 *= $pi80; 
    $dlat = $lat2 - $lat1; 
    $dlon = $lon2 - $lon1; 
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);  
    $km = 6372.797 * 2 * atan2(sqrt($a), sqrt(1 - $a)); 
    return $km; 
}

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