Comment ArcGIS calcule la distance entre deux points avec une projection non équidistante?

10

Ceci est une question complémentaire à ma précédente, pouvez-vous suggérer des textes d'introduction bien écrits sur les projections du système de coordonnées?


Supposons que je travaille avec la projection cartographique CH1903, qui, pour autant que je sache, est conforme, mais pas équidistante. Cela signifie que les angles (la forme) ont été conservés, mais pas les zones, les distances ou l'échelle. (Au moins ceux-ci n'ont pas été conservés exactement ). Jusqu'ici tout va bien.

Je me demande quel type de calcul ArcGIS effectue lorsque je veux maintenant calculer la distance entre deux points. Dans ArcObjects, je pouvais utiliser l' IProximityOperatorinterface comme suit:

IPoint a = ...,
       b = ...;

double distance = ((IProximityOperator)a).ReturnDistance(b);

Question: Lorsque je travaille avec un système de référence qui ne préserve pas précisément les distances, que ferait ArcGIS lorsque je l'interroge sur la distance entre deux points (comme illustré ci-dessus)?

  • Fait-il simplement quelques calculs pythagoriciens (a 2 + b 2 = c 2 ) pour obtenir la distance, ce qui signifie que la distance renvoyée ne sera aussi précise que la projection le permet?

  • Ou va-t-il faire quelque chose de plus compliqué, comme une certaine forme de reprojection, pour obtenir une distance plus précise?

( La même question, mais plus généralement: une fois que les géométries ont été projetées, ArcGIS effectue-t-il tous les calculs simplement dans l'espace euclidien, ou la projection cartographique utilisée influence-t-elle toujours les calculs des distances, des angles, des zones, etc.?)

stakx
la source
2
Veuillez créer une nouvelle question au lieu de modifier votre original. Sinon, vous détournez tous les mécanismes de ce site: que signifient les évaluations lorsque deux questions ou plus sont en jeu dans un même fil? Que signifierait de marquer une réponse comme correcte? Etc.
whuber
1
@whuber: Bien que tout ce qui a été écrit dans ce fil soit toujours sur le sujet WRT la question d'origine posée, je suis d'accord qu'il y a maintenant vraiment deux questions posées ici. Il est trop tard pour changer cela maintenant, mais gardez vos conseils à l'esprit pour une prochaine fois.
stakx

Réponses:

10

Si vous voulez une méthode stable de calcul des distances géodésiques, je recommande le wrapper de Richie Carmichael pour le moteur de projection d'ESRI .

Mise à jour: je viens d'essayer le code de Richie avec ArcGIS 10.0 sur Vista64 et j'obtiens une exception après avoir appelé LoadLibrary. J'examinerai cela plus tard.

Pour l'instant cependant, voici un code en réponse aux questions dans les commentaires d'une autre réponse.

Le code compare IProximityOperator pour les points avec et sans références spatiales. Il montre ensuite comment utiliser une projection équidistante azimutale (le premier point étant le point de tangence) pour trouver la grande distance du cercle.

private void Test()
{
    IPoint p1 = new PointClass();
    p1.PutCoords(-98.0, 28.0);

    IPoint p2 = new PointClass();
    p2.PutCoords(-78.0, 28.0);

    Debug.Print("Euclidian Distance {0}", EuclidianDistance(p1, p2));
    Debug.Print("Distance with no spatialref {0}", GetDistance(p1, p2));

    ISpatialReferenceFactory srf = new SpatialReferenceEnvironmentClass();
    IGeographicCoordinateSystem gcs =
    srf.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_WGS1984);

    p1.SpatialReference = gcs;
    p2.SpatialReference = gcs;

    Debug.Print("Distance with spatialref {0}", GetDistance(p1, p2));
    Debug.Print("Great Circle Distance {0}", GreatCircleDist(p1, p2));

}
private double GetDistance(IPoint p1, IPoint p2)
{
    return ((IProximityOperator)p1).ReturnDistance(p2);
}

private double EuclidianDistance(IPoint p1, IPoint p2)
{
    return Math.Sqrt(Math.Pow((p2.X - p1.X),2.0) + Math.Pow((p2.Y - p1.Y), 2.0));
}

private double GreatCircleDist(IPoint p1, IPoint p2)
{
    ISpatialReferenceFactory srf = new SpatialReferenceEnvironmentClass();
    IProjectedCoordinateSystem pcs =
    srf.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_WGS1984N_PoleAziEqui);
    pcs.set_CentralMeridian(true, p1.X);
    ((IProjectedCoordinateSystem2)pcs).LatitudeOfOrigin = p1.Y;
    p1.SpatialReference = pcs.GeographicCoordinateSystem;
    p1.Project(pcs);
    p2.SpatialReference = pcs.GeographicCoordinateSystem;
    p2.Project(pcs);
    return EuclidianDistance(p1, p2);
}

Voici la sortie:

Euclidian Distance 20
Distance with no spatialref 20
Distance with spatialref 20
Great Circle Distance 1965015.61318737

Je pense qu'il serait intéressant de tester cela contre la DLL du moteur de projection (pe.dll). Publiera les résultats si jamais je fais fonctionner le code de Richie.

Mise à jour: Une fois que j'ai changé le code Richies pour compiler pour x86, je l'ai fait fonctionner. Intéressant ... la distance du grand cercle qu'il me donne est 1960273.80162999 - une différence significative par rapport à celle renvoyée par la méthode équidistante azimutale ci-dessus.

Kirk Kuykendall
la source
La raison de cet écart est probablement due au fait que le segment de ligne (dans le PCS) reliant les points n'est pas une géodésique projetée, qui serait curviligne lorsqu'elle est projetée. En conséquence, vous obtenez une valeur inférieure à ce que vous devriez. Un test de cette théorie est simple à faire: prendre une géodésique simple (comme l'équateur) et comparer deux calculs de la distance entre deux points largement séparés sur la géodésique. L'un est le calcul direct, comme dans votre code; l'autre divise la géodésique en segments, calcule directement les longueurs de segment et les additionne. Ce dernier devrait être plus précis.
whuber
9

Dans ArcGIS 10, consultez IGeometryServer2 qui a désormais GetDistanceGeodesic (distance géodésique entre deux géométries), GetLengthsGeodesic (retourne les longueurs géodésiques de chaque polyligne) et DensifyGeodesic (densifie une polyligne en traçant des points le long des lignes géodésiques reliant les sommets, utilise IPolycurve4: : GeodesicDensify).

Comme mentionné dans les autres réponses, ArcGIS utilise toujours principalement des calculs planaires.

Melita Kennedy


Quelques commentaires sur les autres réponses (pas encore assez de représentants pour commenter directement!).

La projection équidistante azimutale d'Esri prend en charge les ellipsoïdes. Le code GreatCircleDist crée un PCS qui utilise un GCS à base d'ellipsoïdes / sphéroïdes, donc les distances du centre / point d'origine seront des distances géodésiques, pas de grandes distances de cercle. Cela pourrait également être simplifié. Nous connaissons les coordonnées projetées du premier point car c'est le centre de la projection: 0,0. Donc, seul le 2e point doit être projeté. Une fonction EuclidianDistance simplifiée pourrait alors être utilisée.

J'ai vérifié les résultats par rapport aux fonctions géodésiques du pe.dll et cela correspondait. Il semble que l'application de Richie utilise une sphère, elle renvoie donc de grandes distances / coordonnées de cercle dans son application de test. C'est pourquoi les résultats ne correspondent pas. Je n'ai pas reconnu les valeurs de rayon; Je pense que je dois lui en parler!

mkennedy
la source
2
Melita - Ravie de vous voir ici!
Kirk Kuykendall du
1
Je suis d'accord, bienvenue à bord!
matt wilkie
8

La précision de toute réponse à propos d'ArcGIS est susceptible de changer à tout moment - pour autant que nous le sachions, de nouvelles procédures seront introduites dans le tout prochain Service Pack sans avertissement ni documentation. Cela dit, le logiciel ESRI utilise depuis longtemps les calculs euclidiens ( par exemple , la formule de Pythagore pour les distances) chaque fois que les coordonnées projetées sont utilisées. Souvent, dans des calculs comme celui que vous illustrez, le logiciel n'a même pas accès aux informations de projection, alors que faire d'autre?

Votre question elle-même semble suggérer que les calculs de distance euclidienne pour une projection équidistante sont corrects. Rien ne pouvait être plus loin de la vérité. Pour une projection équidistante à un point, la distance euclidienne au point de base est garantie égale à la distance géodésique; pour une projection équidistante à deux points, la distance euclidienne à l'un ou l'autre point de base est garantie égale à la distance géodésique. En contrepartie de ces garanties, la distorsion métrique entre toutes les autres paires de points est généralement considérablement augmentée par rapport aux autres projections que l'on pourrait choisir.

whuber
la source
@whuber: Merci d'avoir répondu. Concernant le premier paragraphe: J'ai pensé qu'ArcGIS pourrait voir que la projection cartographique CH1903 (qui utilise l'ellipsoïde Bessel 1841) est utilisée, puis projeter les points sur cet ellipsoïde via le datum, puis faire des calculs de distance sur l'ellipsoïde. D'après votre réponse, je suppose qu'ArcGIS ne fera pas tout cela et restera dans l'espace Euclidien XY pour effectuer des calculs. ( Et les autres logiciels SIG?) - 2ème paragraphe: Vous avez bien sûr raison, merci d'avoir clarifié ce point.
stakx
Un mécanisme de reprojection masqué n'est possible que si les objets ponctuels conservent des références à une projection. Je ne le crois pas.
whuber
@whuber: Serait-il suffisant (pour des calculs plus précis) de connaître l'ellipsoïde utilisé pour la projection? AFAIK, ArcGIS stocke une référence à la projection utilisée avec chaque classe d'entités (couche de données).
stakx
1
En fait, IPoint, qui dérive de IGeometry, a SpatialReference comme propriété. help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/… Cependant, je ne pense pas que ReturnDistance l'utilise. Il pourrait être utile de tester pour voir si cela a changé.
Kirk Kuykendall
1
@stakx J'ai mis à jour ma réponse pour inclure du code qui montre que la définition de spatialref n'a aucun impact sur ReturnDistance.
Kirk Kuykendall