我目前正在处理gps数据和精确的高度测量。 我想计算两个连续点之间的距离。有很多 有关使用WGS84椭球等计算两点之间距离的信息。
但是,我没有找到任何将海拔高度更改考虑在内的信息 距离计算。
有没有人知道描述这种方法的一些网站,论文,书籍等? 感谢
编辑:在计算距离时,Sql Server 2008地理扩展也会忽略高度信息。
答案 0 :(得分:8)
我使用起始高度和结束高度的平均值作为恒定高度来实现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椭球相比
编辑:
除此之外,如果您确实希望进行较大的高度变化,可以将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坐标的类,并定义了上面的常量。
答案 1 :(得分:1)
您可能不关心大型2D距离分离的高度。因此,如果你得到的dist超过20(或大约50)km,那么谁在乎高度差异(取决于你的需求情况)。比如说20公里,除了高度差之外还要加入简单的毕达哥拉斯。顺利喂它。
答案 2 :(得分:0)
我建议使用WGS84的任何距离都会给你更高的准确度,高度差异无关紧要。在高度差异很重要的任何距离上你应该只使用直线近似。
答案 3 :(得分:0)
为了做到这一点,您必须解决的第一个问题是如何定义高度变化。正规方程是有效的,因为它们位于二维表面上,但是增加第三维意味着最短距离的简单定义不再适用,例如现在第三维是“在游戏中”,你的最短距离可以穿过原始椭球。 它有点快速和肮脏,但你最好的解决方案可能是假设所有的变化率沿着椭圆体上的原始2D路径是恒定的。然后,您可以将2D距离计算为长度,计算出高度变化率,然后只需使用毕达哥拉斯来计算长度的增加,其中三角形的一侧是2D距离,高度是第二长度。
答案 4 :(得分:0)
对于初学者,您需要一个模型来告诉您两个点之间的线上高度如何变化。没有这样的模型,你就没有任何一致的两点之间的距离定义。
如果你有一个线性模型(距离点之间距离的50%也意味着你向上移动了50%的高度),那么你可能会假装整个东西是一个直角三角形;即为了确定高度变化如何影响距离,你就好像世界是平坦的。沿地面的距离是基础,高度变化是三角形的高度,斜边是从点到点估计的真实行进距离。
如果你想进一步改进,那么你可以注意到上面的模型非常适合无限小的距离,这意味着你可以迭代距离的每个增量,微积分式,每次使用当前的高度到计算地面距离,然后使用相同的三角比来计算行程距离的海拔变化贡献。我可能会在一个包含10到100个段的for()循环中执行此操作,并且可能通过反复试验确定获得真实值的epsilon所需的件数。也可以计算出线积分来计算出这个模型下两点之间的实际距离。