Distance galbée différente de Geopy / Haversine

8

J'exécute une analyse spécifique où nous utilisons galbée pour créer des tampons autour des points (emplacements de magasin), puis vérifie si d'autres points (emplacements d'utilisateur) sont présents dans cette valeur de tampon. Quand je vérifie la distance en utilisant galbée, elle se révèle être différente de la distance que j'obtiens de geopy. La formule haversine est d'accord avec Geopy et une vérification sur Google Maps en utilisant la fonction de mesure de distance donne également environ la même distance

Voici un exemple:

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
Formule Haversine ( http://www.movable-type.co.uk/scripts/latlong.html ): 84.88

Laquelle a raison? En forme ou autres? De plus, une telle différence (~ 22%) est-elle attendue? Ou est-ce que je manque quelque chose?

Harish
la source

Réponses:

10

Parce que les principes et les algorithmes sont différents (regardez la distance géographique )

  1. Utilisez la distance euclidienne dans un plan cartésien et la distance la plus courte entre deux points dans un plan est une ligne droite qui contient les deux points.
 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 et Haversine utilisent soit la distance géodésique (sur un ellipsoïde, Vincenty) ou la distance du grand cercle (la distance la plus courte le long de la surface d'une sphère) entre deux points. La distance la plus courte à la surface d'une sphère est le long du grand cercle qui contient les deux points.

    Par conséquent, il est normal que les distances euclidiennes Shapely, Numpy et Scipy diffèrent des distances Vincenty, Great Circle et Haversine et les différences entre les distances Vincenty, Great Circles et Haversine sont liées au choix d'un ellipsoïde et à bien d'autres choses.

    Vous pouvez également modifier l'ellipsoïde

 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

Ou utilisez d'autres bibliothèques comme géodistance

 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)

Vous pouvez voir que toutes les différences sont centimétriques. Avec une précision métrique, toutes les valeurs = 85 mètres.

  1. Laquelle a raison? Tout cela, car cela dépend du contexte: si vous travaillez avec des données projetées (plan cartésien), vous utilisez la distance euclidienne (Shapely, Numpy, Scipy et bien d'autres), sinon, l'une des autres.

    Ils sont aussi de nombreuses autres distances ( distances spatiales Scipy )

Nouveau

À l'appui de la réponse de 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
gène
la source
Bonne réponse. Juste une petite note sur votre point n ° 3 lors de l'utilisation de la projection EPSG:3857- Shapely n'est pas le bon choix ici. Web Mercator n'est pas conforme et ne doit pas être utilisé pour calculer les distances.
Mintx
3

Et voici un autre calcul de distance de GeographicLib :

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

Je considère que c'est la bonne, à moins de 15 nanomètres.

Mike T
la source