Я реализовал функцию расстояния WGS84, используя среднюю начальную и конечную высоту как постоянную высоту. Если вы уверены, что по вашему пути будет относительно мало изменений высоты, это работает приемлемо хорошо (ошибка относительно разницы высот ваших двух точек LLA).
Вот мой код (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);
}
На практике мы обнаружили, что разница высот редко делает большую разницу, наши пути, как правило, 1-2ке долго с высотой варьирования порядка 100 м и мы видим около 5 м изменения в среднем по сравнению с использованием немодифицированного эллипсоида WGS84.
Edit:
Чтобы добавить к этому, если вы ожидаете большие изменения высоты над уровнем моря, вы можете конвертировать ваши координаты WGS84 в ECEF (земля центрированных земля фиксировано) и оценить пути прямой линии, как показано в нижней части моего функция. Преобразование точки в ECEF просто сделать:
/// <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;
}
Изменить 2:
меня спрашивали о некоторых других переменных в моем коде:
// 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
класс я для преобразования координат LatLonAlt в координаты ECEF и определения констант выше.
Я не смотрел на WGS84 уравнений, поэтому я не пишу это как ответ. Тем не менее, мне кажется, что вы должны иметь возможность настроить радиус или два, чтобы ваши измерительные точки были «новой» поверхностью. Это, вероятно, будет работать лучше всего, если ваши измерения высоты основаны на GPS; если на основе механических средств (например, давления воздуха), то «уровень моря» может иметь очень мало отношения к модельному геоиду. – kdgregory
Вы когда-нибудь придумывали хорошее решение? – lnafziger