如何将大地位置转换为适用于Cesium地形模型的ECF位置

3

我试图在Cesium中放置一个位于珠穆朗玛峰顶部的点。截至昨晚,我最有可能使用的是我从PySatel.coord中借用的大地测量到地心坐标转换代码。今天早上再次审查后,它似乎是正确的:

a = 6378.137
b = 6356.7523142
esq = 6.69437999014 * 0.001
e1sq = 6.73949674228 * 0.001
f = 1 / 298.257223563


def geodetic2ecef(lat, lon, alt):
    """Convert geodetic coordinates to ECEF.

    Units are degrees and kilometers.
    """
    lat, lon = radians(lat), radians(lon)
    xi = sqrt(1 - esq * sin(lat))
    x = (a / xi + alt) * cos(lat) * cos(lon)
    y = (a / xi + alt) * cos(lat) * sin(lon)
    z = (a / xi * (1 - esq) + alt) * sin(lat)
    return x, y, z

我从维基百科上获取了珠穆朗玛峰顶部的经度/纬度/高度信息。在将对象定位到我的CZML中之前,我使用上述代码提供的ECF坐标乘以1000(m/km)。我得到的ECF位置是:[302995.41122130124,5640733.98308375,2981975.8695256836]。使用默认地形提供程序(在教程中描述),此点比珠穆朗玛峰峰顶高出很多。
以下是相关的CZML片段:
{"position": 
  {"cartesian": [302995.41122130124, 5640733.98308375, 2981975.8695256836]}, 
 "id": "ellipsoid-1", 
 "ellipsoid": 
   {
     "radii": {"cartesian": [3545.5375159540376, 
                              164.44985193756034, 
                              164.62702908803794]}, 
     "material": {"solidColor": {"color": {"rgba": [0, 255, 0, 100]}}}
   }, 
 "orientation": {"unitQuaternion": [0.00014107125875577922, 
                                    -0.011462389405915903, 
                                    -0.010254110199791062, 
                                    -0.70702315200093502]}
}

似乎是一个问题,需要在http://gis.stackexchange.com/上提问。 - Beachwalker
我考虑了一下 @Beachwalker。这是一种奇怪的技术混合,而且我不确定它最适合哪个部分,主要是因为我不知道我的错误在哪里。它可能是坐标转换、Cesium Javascript库或其他细节问题。 - Carl F.
2个回答

7
这里有几个因素起作用。
首先,Cesium用于地形的源数据可能对珠穆朗玛峰的高度低于预期。我们使用CGIAR SRTM数据集,因此他们FAQ中的这一项是相关的:
“为什么一些山区的山峰明显比它们应该的低?”
正如前面提到的,许多原始数据空缺集中在山区和雪覆盖区域。因此,高山区域中的许多山峰实际上是插值的。如果不使用高分辨率协变量进行插值,则插值无法识别数据空缺实际上是一个山峰,并倾向于“平坦化”山峰,导致该区域真实海拔高度被低估。这个问题在第四版中基本解决了。
他们说在v4中这个问题基本上得到了解决,而Cesium使用的就是这个版本,所以希望这个第一个因素不是真正的问题。
其次,我们处理用于Cesium的源地形数据可能会使山峰稍微平坦化。这个问题将很快得到纠正,希望在接下来的几个月内完成。
第三,维基百科提供的高度是相对于平均海平面(MSL)的海拔高度。 MSL是一个难以在数学上处理的复杂表面,因此您的geodetic2ecef并没有这样做。 相反,像Cesium一样,它假定高度相对于WGS84椭球体,这是一个更好的表面来处理。
NGA有一个网站,可以用来查找MSL相对于WGS84椭球体(也称为大地水准面高度)的高度: http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/intpt.html 它报告说,对于珠穆朗玛峰的顶峰(27°59'17" N,86°55'31" E),MSL低于WGS84 28.73米。 如果从维基百科报道的峰顶高度中减去该数字,则应该会更接近。

这个页面提供编程计算大地水准面高度的信息:

http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html

我建议使用15分钟大地水准面高度文件进行插值,而不是从系数计算高度。

还有一些其他与问题无关的注意事项:

  • Cesium有代码将经纬高(我们称之为Cartographic)转换为笛卡尔坐标。请参见Ellipsoid.cartographicToCartesian
  • 您可以在CZML中使用cartographicDegrees或cartographicRadians指定坐标,而不是笛卡尔坐标,然后Cesium会自动进行转换。但是,在指定高度时仍然必须调整大地水准面高度。另外,请不要忘记先输入经度。

事实证明这是多种因素的组合。正如你所建议的那样,峰顶处的DEM高程由于四舍五入(微小)而较低。此外,我使用的geodetic2ecef函数与Ellipsoid.js中的函数不匹配。我将算法从Ellipsoid.js移植到我的Python代码中,并切换到DEM报告的高程(GTOPO30的最大值),现在非常吻合。我仍然需要理解为什么这两个geodetic2ecef函数会产生不同的结果。 - Carl F.

1

Proj4js - 是著名的proj4库的一个移植版,可能适合您的需求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接