Formliche Entfernung unterscheidet sich von Geopy / Haversine


8

Ich führe eine spezielle Analyse durch, bei der wir Shapely verwenden, um Puffer um Punkte (Speicherorte) zu erstellen und dann zu überprüfen, ob andere Punkte (Benutzerstandorte) in diesem Pufferwert vorhanden sind. Wenn ich die Entfernung mit Shapely überprüfe, stellt sich heraus, dass sie sich von der Entfernung unterscheidet, die ich von Geopy erhalte. Die Haversine-Formel stimmt mit Geopy überein, und eine Überprüfung von Google Maps mit der Funktion zum Messen der Entfernung ergibt ebenfalls ungefähr die gleiche Entfernung

Hier ist ein Beispiel:

from shapely.geometry import Point, shape
from pyproj import Proj, transform
from geopy.distance import vincenty, great_circle

pt_store=Point(transform(Proj(init='EPSG:4326'),Proj(init='EPSG:3857'),-76.799614, 39.435307))

pt_user=Point(transform(Proj(init='EPSG:4326'),Proj(init='EPSG:3857'),-76.79989,39.43604))

vincenty((39.435307,-76.799614),(39.43604,-76.79989)).meters
great_circle((39.435307,-76.799614),(39.43604,-76.79989)).meters
pt_store.distance(pt_user)

Vincenty: 84.77847691521336
Great_circle: 84.90640111682812
Shapely: 110.02637304449682
Haversine-Formel ( http://www.movable-type.co.uk/scripts/latlong.html ): 84,88

Welcher ist richtig? Formschön oder andere? Wird auch ein so großer Unterschied (~ 22%) erwartet? Oder fehlt mir etwas?

Antworten:


10

Weil die Prinzipien und Algorithmen unterschiedlich sind (siehe Geografische Entfernung )

  1. Verwenden Sie den euklidischen Abstand in einer kartesischen Ebene, und der kürzeste Abstand zwischen zwei Punkten in einer Ebene ist eine gerade Linie, die die beiden Punkte enthält.
 import numpy as np
 print np.linalg.norm(np.array(pt_user) - np.array(pt_store))
 110.02637304449682 # meters
 from scipy.spatial import distance
 print distance.euclidean(pt_user, pt_store)
 110.02637304449682 # meters
  1. Vincenty, Great Circle und Haversine verwenden entweder die geodätische Entfernung (auf einem Ellipsoid, Vincenty) oder die Großkreisentfernung (die kürzeste Entfernung entlang der Oberfläche einer Kugel) zwischen zwei Punkten. Der kürzeste Abstand auf der Oberfläche einer Kugel verläuft entlang des Großkreises, der die beiden Punkte enthält.

    Daher ist es normal, dass sich die euklidischen Abstände Shapely, Numpy und Scipy von den Abständen Vincenty, Great Circle und Haversine unterscheiden und die Unterschiede zwischen den Abständen Vincenty, Great Circles und Haversine mit der Wahl eines Ellipsoids und vielen anderen Dingen zusammenhängen.

    Sie können auch das Ellipsoid ändern

 print vincenty((39.435307,-76.799614),(39.43604,-76.79989),ellipsoid='WGS-84')
 0.0847784769149 km
 print vincenty((39.435307,-76.799614),(39.43604,-76.79989),ellipsoid='GRS-80')
 0.0847784769128 km

Oder verwenden Sie andere Bibliotheken als Geodistanz

 print geodistance.distanceVincenty(39.435307,-76.799614,39.43604,-76.79989, ellipsoid='WGS-84')
 (0.08477847691523362, -16.276730447136675) # distance, azimuth
 print geodistance.distanceHaversine(39.435307,-76.799614,39.43604,-76.79989)
 (0.08488248586585143, -16.214988211007256)

Sie können sehen, dass alle Unterschiede zentimetrisch sind. Mit metrischer Genauigkeit sind alle Werte = 85 Meter.

  1. Welcher ist richtig? Alles, weil es vom Kontext abhängt: Wenn Sie mit projizierten Daten (kartesische Ebene) arbeiten, verwenden Sie den euklidischen Abstand (Shapely, Numpy, Scipy und viele andere), wenn nicht einen der anderen.

    Sie sind auch viele andere Entfernungen ( Scipy Spatial Entfernungen )

Neu

Zur Unterstützung der Antwort von Mintx

pt_store=Point(transform(Proj(init='EPSG:4326'),Proj(init='EPSG:31370'),-76.799614, 39.435307))
pt_user=Point(transform(Proj(init='EPSG:4326'),Proj(init='EPSG:31370'),-76.79989,39.43604))
pt_store.distance(pt_user)
86.26511001003892

Gute Antwort. Nur eine kurze Anmerkung zu Ihrem dritten Punkt bei der Verwendung der Projektion EPSG:3857- Shapely ist hier die falsche Wahl. Web Mercator ist nicht konform und sollte nicht zur Berechnung von Entfernungen verwendet werden.
Mintx

3

Und hier ist eine weitere Entfernungsberechnung von GeographicLib :

from geographiclib.geodesic import Geodesic
g = Geodesic.WGS84.Inverse(39.435307, -76.799614, 39.43604, -76.79989)
print(g['s12'])  # 84.7784769689

Ich würde dies innerhalb von 15 Nanometern als das Richtige betrachten.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.