J'ai implémenté une fonction de distance WGS84 en utilisant la moyenne de l'altitude de début et de fin comme altitude constante. Si vous êtes certain qu'il y aura relativement peu de variation d'altitude le long de votre chemin, cela fonctionnera bien (l'erreur est relative à la différence d'altitude de vos deux points LLA).
Voici mon code (C#):
/// <summary>
/// Gets the geodesic distance between two pathpoints in the current mode's coordinate system
/// </summary>
/// <param name="point1">First point</param>
/// <param name="point2">Second point</param>
/// <param name="mode">Coordinate mode that both points are in</param>
/// <returns>Distance between the two points in the current coordinate mode</returns>
public static double GetGeodesicDistance(PathPoint point1, PathPoint point2, CoordMode mode) {
// calculate proper geodesics for LLA paths
if (mode == CoordMode.LLA) {
// meeus approximation
double f = (point1.Y + point2.Y)/2 * LatLonAltTransformer.DEGTORAD;
double g = (point1.Y - point2.Y)/2 * LatLonAltTransformer.DEGTORAD;
double l = (point1.X - point2.X)/2 * LatLonAltTransformer.DEGTORAD;
double sinG = Math.Sin(g);
double sinL = Math.Sin(l);
double sinF = Math.Sin(f);
double s, c, w, r, d, h1, h2;
// not perfect but use the average altitude
double a = (LatLonAltTransformer.A + point1.Z + LatLonAltTransformer.A + point2.Z)/2.0;
sinG *= sinG;
sinL *= sinL;
sinF *= sinF;
s = sinG * (1 - sinL) + (1 - sinF) * sinL;
c = (1 - sinG) * (1 - sinL) + sinF * sinL;
w = Math.Atan(Math.Sqrt(s/c));
r = Math.Sqrt(s * c)/w;
d = 2 * w * a;
h1 = (3 * r - 1)/2/c;
h2 = (3 * r + 1)/2/s;
return d * (1 + (1/LatLonAltTransformer.RF) * (h1 * sinF * (1 - sinG) - h2 * (1 - sinF) * sinG));
}
PathPoint diff = new PathPoint(point2.X - point1.X, point2.Y - point1.Y, point2.Z - point1.Z, 0);
return Math.Sqrt(diff.X * diff.X + diff.Y * diff.Y + diff.Z * diff.Z);
}
En pratique, nous avons constaté que la différence d'altitude fait rarement une grande différence, nos chemins sont généralement 1-2km longue avec l'altitude variant de l'ordre de 100m et nous voyons environ ~ 5m de changement en moyenne par rapport à l'utilisation de l'ellipsoïde WGS84 non modifié.
Edit:
Pour ajouter à cela, si vous ne vous attendez grands changements d'altitude, vous pouvez convertir vos coordonnées WGS84 à ECEF (terre centré sur la Terre fixe) et évaluer les chemins en ligne droite comme indiqué au bas de mon fonction. Conversion d'un point à ECEF est simple:
/// <summary>
/// Converts a point in the format (Lon, Lat, Alt) to ECEF
/// </summary>
/// <param name="point">Point as (Lon, Lat, Alt)</param>
/// <returns>Point in ECEF</returns>
public static PathPoint WGS84ToECEF(PathPoint point) {
PathPoint outPoint = new PathPoint(0);
double lat = point.Y * DEGTORAD;
double lon = point.X * DEGTORAD;
double e2 = 1.0/RF * (2.0 - 1.0/RF);
double sinLat = Math.Sin(lat), cosLat = Math.Cos(lat);
double chi = A/Math.Sqrt(1 - e2 * sinLat * sinLat);
outPoint.X = (chi + point.Z) * cosLat * Math.Cos(lon);
outPoint.Y = (chi + point.Z) * cosLat * Math.Sin(lon);
outPoint.Z = (chi * (1 - e2) + point.Z) * sinLat;
return outPoint;
}
Edit 2:
On m'a demandé quelques-unes des autres variables dans mon code:
// RF is the eccentricity of the WGS84 ellipsoid
public const double RF = 298.257223563;
// A is the radius of the earth in meters
public const double A = 6378137.0;
LatLonAltTransformer
est une classe je convertir les coordonnées LatLonAlt en coordonnées ECEF et définir les constantes ci-dessus.
Je ne l'ai pas regardé les équations WGS84, donc je ne pas écrire cela comme une réponse. Cela dit, il me semble que vous devriez pouvoir ajuster un rayon ou deux pour que vos points de mesure soient la "nouvelle" surface. Cela fonctionnerait probablement mieux si vos mesures d'altitude sont basées sur le GPS; s'il est basé sur des moyens mécaniques (p. ex. la pression de l'air), alors le «niveau de la mer» peut avoir très peu de rapport avec le géoïde du modèle. – kdgregory
Avez-vous déjà trouvé une bonne solution pour cela? – lnafziger