Tôi đã triển khai hàm khoảng cách WGS84 bằng cách sử dụng mức trung bình của độ cao bắt đầu và kết thúc làm độ cao không đổi. Nếu bạn chắc chắn rằng sẽ có sự thay đổi độ cao tương đối nhỏ dọc theo con đường của bạn, công trình này chấp nhận tốt (lỗi liên quan đến chênh lệch độ cao của hai điểm LLA của bạn).
Dưới đây là mã của tôi (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);
}
Trên thực tế chúng tôi nhận thấy rằng sự khác biệt độ cao hiếm khi làm cho một sự khác biệt lớn, con đường của chúng tôi thường 1-2km dài với độ cao khác nhau về trình tự 100m và chúng ta thấy trung bình ~ 5m thay đổi so với sử dụng elliptic WGS84 chưa sửa đổi.
Edit:
Để thêm vào đó, nếu bạn làm điều mong đợi thay đổi độ cao lớn, bạn có thể chuyển đổi WGS84 bạn phối để ECEF (đất làm trung tâm trái đất cố định) và đánh giá con đường thẳng như thể hiện ở dưới cùng của tôi chức năng. Chuyển đổi một điểm đến ECEF là đơn giản để làm:
/// <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;
}
Chỉnh sửa 2:
tôi được hỏi về một số các biến khác trong mã của tôi:
// 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
là một lớp học tôi đã sử dụng để chuyển đổi từ tọa độ LatLonAlt sang tọa độ ECEF và xác định các hằng số ở trên.
Tôi đã không nhìn vào phương trình WGS84, vì vậy đang không viết những dòng này như một câu trả lời. Điều đó nói rằng, có vẻ như với tôi rằng bạn sẽ có thể tinh chỉnh bán kính hoặc hai để làm cho các điểm đo của bạn là bề mặt "mới". Điều này có lẽ sẽ hoạt động tốt nhất nếu các phép đo độ cao của bạn dựa trên GPS; nếu dựa trên các phương tiện cơ học (ví dụ, áp suất không khí), thì "mực nước biển" có thể có rất ít mối quan hệ với mô hình Geoid. – kdgregory
Bạn đã bao giờ nghĩ ra một giải pháp tốt cho điều này? – lnafziger