Unterschied im Zielort zwischen Pyproj und Geopy

8

Ich suche nach Möglichkeiten, um (in Python) den Zielort aus einem Punkt zu berechnen, dem Peilung und Reichweite gegeben sind.

Basierend auf dem Ergebnisvergleich der beiden Bibliotheken in Betreff ( geopyund pyproj) habe ich festgestellt, dass es einen zunehmenden Unterschied in der endgültigen Ausgabe gibt. Zum Beispiel liegt bei 100 km ungefähr in der Größenordnung von Dezimetern. Dies ist ein minimales Beispiel dafür, was ich meine:

from __future__ import absolute_import, division, print_function

long_1 = -1.729722
lat_1 = 53.320556
bearing = 96.021667
distance = 124.8  #in km

# using geopy

import geopy
from geopy.distance import VincentyDistance

origin = geopy.Point(lat_1, long_1)
destination = VincentyDistance(kilometers=distance).destination(origin, bearing)
gp_lat_2 = destination.latitude
gp_long_2 = destination.longitude

# using pyproj

from pyproj import Geod
g = Geod(ellps='WGS84')
prj_long_2, prj_lat_2, prj_bearing_2 = g.fwd(long_1, lat_1, bearing, distance*1000)

# results comparison
print("        | pyproj        | geopy")
print("long_2   %.6f     %.6f" % (prj_long_2, gp_long_2))
print("lat_2    %.6f     %.6f" % (prj_lat_2, gp_lat_2))

print("> DELTA pyproj, geopy")
print("delta long_2   %.7f" % (prj_long_2 - gp_long_2))
print("delta lat_2    %.7f" % (prj_lat_2 - gp_lat_2))

Ich habe diese Ergebnisse erhalten:

        | pyproj        | geopy
long_2   0.127201         0.127199
lat_2    53.188432        53.188432

> DELTA pyproj, geopy
delta long_2   0.0000021
delta lat_2    -0.0000002

Meine Hauptfrage ist, ob ich etwas falsch mache (beide Einstellungen sollten verwendet werden WGS84).

Wenn nicht, ist der Unterschied auf unterschiedliche verwendete Formeln zurückzuführen (Vincenty für geopyvs. Karney für pyproj)? ZB der hier genannte Rundungsfehler .

gmas80
quelle

Antworten:

6

Es sieht so aus, als hätten Sie alles richtig gemacht. Sie können die Fehler jeder Methode auswerten, indem Sie die inversen Berechnungen durchführen, um die Entfernung anhand der Ursprungs- und Zielkoordinaten zu ermitteln, und dann die Residuen der Entfernungen auswerten. Dies ist eine Rundreiseübung.

# For Vincenty's method:
geopy_inv_dist = geopy.distance.vincenty(origin, destination).m
# For Karney's method:
prj_inv_dist = g.inv(long_1, lat_1, prj_long_2, prj_lat_2)[2]  # s12

print("> inverse distance residule (m)")
print("geopy  %.7f" % (distance * 1000 - geopy_inv_dist))
print("prj    %.7f" % (distance * 1000 - prj_inv_dist))

Zeigt an:

> inverse distance residule (m)
geopy  0.1434377
prj    0.0000000

Sie sehen also, dass Vincentys Methode einen inversen Abstand bestimmt, der für dieselben Koordinaten über ein Dezimeter unterschiedlich ist. Karneys Methode weist Fehler bei der Maschinengenauigkeit auf, die weniger als 15 Nanometer beträgt. In diesem Beispiel beträgt der Fehler 0,1455 nm, was ungefähr dem Durchmesser eines Wasserstoffatoms entspricht.


Das Problem ist wahrscheinlich mit dem geopy Ziel Methode . Vergleichen wir eine zweite Implementierung der Vincenty-Methode mit der hier gezeigten PostGIS-Version 2.1 . (PostGIS Version 2.2 mit Proj 4.9 und höher verwendet Karneys Methoden ). Die Restwerte für die Hin- und Rückstrecke von PostGIS 2.1 betragen immer weniger als 1 cm. Für dieses Beispiel ist es 255 nm:

SELECT PostGIS_Version(),
  ST_AsText(origin) AS origin,
  ST_AsText(ST_Project(origin, distance, azimuth)) AS destination,
  ST_Distance(ST_Project(origin, distance, azimuth), origin) AS roundtrip_distance,
  distance - ST_Distance(ST_Project(origin, distance, azimuth), origin) AS postgis_residual
FROM (
  SELECT 124.8 * 1000 AS distance, radians(96.021667) AS azimuth,
    ST_SetSRID(ST_MakePoint(-1.729722, 53.320556), 4326)::geography AS origin
) AS f;
-[ RECORD 1 ]------+-----------------------------------------
postgis_version    | 2.1 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
origin             | POINT(-1.729722 53.320556)
destination        | POINT(0.12720134063267 53.1884316458524)
roundtrip_distance | 124799.999999745
postgis_residual   | 2.54993210546672e-007
Mike T.
quelle
Vielen Dank für diese äußerst gründliche, äußerst intelligente Antwort!
Jason Scheirer
@mike-t, danke für die nette Antwort! Ich mag die Idee einer dritten Quelle. Ich habe ein geopyTicket geöffnet : github.com/geopy/geopy/issues/140
gmas80