Diferença na localização de destino entre pyproj e geopy

8

Estou procurando maneiras de calcular (em Python) o local de destino a partir de um ponto determinado com o alcance e o alcance.

Com base na comparação de resultados das duas bibliotecas no assunto ( geopye pyproj), notei que há uma diferença crescente na saída final. Por exemplo, a 100 km é aproximadamente da ordem dos decímetros. Este é um exemplo mínimo do que quero dizer:

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

Eu obtive estes resultados:

        | 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

Minha principal pergunta é se estou fazendo algo errado (ambas as configurações devem estar sendo usadas WGS84).

Caso contrário, a diferença se deve a diferentes fórmulas em uso (Vincenty for geopyvs. Karney for pyproj)? Por exemplo, o erro de arredondamento citado aqui .

gmas80
fonte

Respostas:

6

Parece que você fez tudo corretamente. Você pode avaliar os erros de cada método executando os cálculos inversos para encontrar a distância, dadas as coordenadas de origem e destino, e depois avaliar os resíduos das distâncias. Este é um exercício de ida e volta.

# 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))

Shows:

> inverse distance residule (m)
geopy  0.1434377
prj    0.0000000

Assim, você pode ver que o método de Vincenty determina uma distância inversa que está acima de um decimetro diferente para as mesmas coordenadas. O método de Karney apresenta erros dentro da precisão da máquina, que é inferior a 15 nanômetros. Neste exemplo, o erro é de 0,1455 nm, que tem o diâmetro de um átomo de hidrogênio.


O problema provavelmente está no método de destino do geopy . Vamos comparar uma segunda implementação do método Vincenty com as versões 2.1 do PostGIS, mostradas aqui . (PostGIS versão 2.2 com Proj 4.9 e posterior usa os métodos de Karney ). Os resíduos da distância de ida e volta do PostGIS 2.1 são sempre menores que 1 cm. Para este exemplo, é 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
fonte
Obrigado por esta resposta extremamente completa e extremamente inteligente!
Jason Scheirer
@ Mike-t, obrigado pela resposta agradável! Eu gosto da idéia de uma terceira fonte .. Eu abri um geopy's bilhete: github.com/geopy/geopy/issues/140
gmas80