问题
I'm trying to put a point at the top of Mount Everest in Cesium. My most likely candidate as of last night was the code I borrowed to do geodetic to ecef conversion (from PySatel.coord). Upon review this morning, it appears to be correct:
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
I pulled the lat / lon / alt for the peak of Mt. Everest from Wikipedia. I multiplied the ECF coordinates provided by the above code by 1000(m/km) before positioning the object in my CZML. I get an ECF location of: [302995.41122130124, 5640733.98308375, 2981975.8695256836]. With the default terrain provider (described in the tutorial), this point is significantly higher than the peak of Mt. Everest.
Here's the relevant CZML snippet:
{"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]}
}
回答1:
There are several factors at work here.
First, the source data that Cesium uses for terrain may have a lower than expected height for the peak of Mount Everest. We use the CGIAR SRTM dataset, so this item in their FAQ is relevant:
Why do some mountain regions have peaks significantly lower than they should be?
As mentioned earlier, many original data voids are concentrated in mountainous areas and in snow-covered regions. Hence, many peaks in high-mountain areas are actually interpolated. Without using a high resolution co-variable for the interpolation, the interpolation fails to identify that the data void is actually a peak, and tends to “flatten” the peak, leading to underestimates in the true elevation for that region. This issue is largely resolved in Version 4.
They say that it is largely resolved in v4, the version Cesium uses, so hopefully this first factor is not the actual problem.
Second, our processing of the source terrain data for use with Cesium may flatten the peak a bit. This problem will be corrected soon, hopefully within the next couple of months.
Third, Wikipedia provides the height as an elevation above mean sea level (MSL). MSL is a complicated surface that is hard to work with mathematically, so your geodetic2ecef is not doing so. Instead, it, like Cesium, is assuming that the altitude is relative to the WGS84 ellipsoid, which is a much nicer surface to work with.
NGA has a web site that can be used to find the height of MSL above the WGS84 ellipsoid, also known as the geoid height: http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/intpt.html
It reports that for the peak of Mount Everest (27° 59′ 17″ N, 86° 55′ 31″ E), MSL is 28.73 meters below WGS84. If you subtract that number from the altitude of the peak reported on Wikipedia, you should get closer, at least.
This page has information on computing geoid heights programmatically: http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html
I recommend interpolating over the 15-minute geoid height file instead of computing heights from coefficients.
A couple of other notes not directly related to the question:
- Cesium has code to convert LLA (we call it Cartographic) to Cartesian. See
Ellipsoid.cartographicToCartesian
. - You can specify coordinates in CZML in cartographicDegrees or cartographicRadians instead of cartesian, and then Cesium will do the conversion for you automatically. You still have to adjust for the geoid when specifying the height, however. Also, don't forget that longitude is first.
回答2:
Proj4js - a port of the famous proj4 library - might do the job for you.
来源:https://stackoverflow.com/questions/16299154/how-do-i-convert-a-geodetic-location-to-an-ecf-position-that-works-with-the-terr