開始高度と終了高度の平均を一定高度として使用してWGS84距離関数を実装しました。あなたの道に沿って高度の変化が比較的少ないことが確かであれば、これはうまく機能します(エラーは2つの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);
}
私たちは高度差はほとんど大きな違いがないことを発見しました、私たちのパスは通常、100メートルのオーダーで様々な高度で長い1-2kmされていますそして修正されていないWGS84楕円体を使用した場合と比べて平均約5mの変化が見られます。
編集:
あなたが大規模な高度の変化を期待していた場合、あなたは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方程式を見ていないので、答えとしてこれを書いていないです。つまり、測定点を「新しい」サーフェスにするには、半径を2つ調整する必要があります。これはおそらく高度測定がGPSベースの場合に最も効果的です。機械的手段(例えば空気圧)に基づいている場合、「海面」はモデルジオイドとほとんど関係がない可能性があります。 – kdgregory
あなたはこのために良い解決策を思いついたことがありますか? – lnafziger