Is Cesium Ion Global terrain and then sampling reasonably accurate?

Hi,

I’m using the Cesium global terrain in an app I’m working on, but I’m getting some odd readings using it, especially when I’m sampling the ground level at sea. I’ve been working mostly inland, but just did some work along the coast and the terrain sampling of the sea gives a consistently 20±2m up and down the coast (this is in Australia outside of Sydney and south to Wollongong, if important). I wrote a function that does three different methods;

1. cartesian = scene.pickPosition(screenCursorPosition);
   radian = Cartographic.fromCartesian (cartesian)
   height1 = radian.height;

2. height2 = scene.sampleHeight(radian);

3. arr = [radian];
   await scene.sampleHeightMostDetailed(arr);
   height3 = arr[0].height;

Is there any methods I’ve missed? They all give the same odd results (height1 is sometimes off by ± 30cm to height2 and height3, height2 and height3 are usually the same). As an example, here I’ve sampled just off the coastline (yellow dotted line; coords included) which gives 20.7m height;

I understand the difficulty of precision over land, but I was surprised to see this at sea level? Thoughts on this before I dig further? Maybe quantization issues, or less likely some geoid thing? If there’s no obvious answers, I’ll make a sandcastle thing, maybe with some choice sample points from around the world and sample those?

Cheers,

Alex

Hi @Alexander_Johannesen,

I believe what you’re seeing is expected. Take a look at this forum post, and also the docs for sampleTerrain, which point out:

As is typical of the Cartographic type, the supplied height is a height above the reference ellipsoid (such as Ellipsoid.WGS84) rather than an altitude above mean sea level. In other words, it will not necessarily be 0.0 if sampled in the ocean.

And using the calculator linked in the post, with the cartographic position from the image you posted, I get:

Which is consistent with your observation that the sampled height is ~20m off.

Hope that helps clarify any confusion.

Best,
Matt

Thanks for your reply. It certainly answers some part of it, although I’m a bit surprised. So what we’re saying here is that Cesium is ellipsoid accurate, but not geoid accurate? One would think that the global terrain would have been adjusted to geoid models, but you’re saying it is not and will globally be incorrect, even within the parameters of ellipsoid correctness?

Cheers,

Alex

So what we’re saying here is that Cesium is ellipsoid accurate, but not geoid accurate.

That’s my understanding, yes. Although maybe it’s more accurate to say that the accuracy has to do with the terrain provider? Like, the Cesium World Terrain is height-referenced based on the WGS84 Ellipsoid, but you could maybe provide a custom terrain data source adjusted for MSL.

you’re saying it is not and will globally be incorrect, even within the parameters of ellipsoid correctness

I’m not sure what you mean by this last part, exactly.

Thanks, they makes sense. So this was using the cesium world terrain, but I do have a local Australian terrain which is might try a hybrid model with, but I’ll check height accuracy of it. Just a pain that cesium only supports one terrain model at a time.

Cheers,

Alex

I’m not super familiar with use cases for multiple terrain models, but if you think it would be a valuable addition to CesiumJS, I’d encourage you to open a feature request in the github repo!

Oh, there’s tons of use cases, including things like resolution and precision coverage of certain areas over large maps, or my current app that has a global ok quality terrain map, but needs specific areas (kilometers of pipes and lines) at a much higher accuracy that I pull from internal maps as needed.

There was a Cesium toolkit someone talked about a couple of months back that had a mixed terrain plugin, which is a fantastic effort that might be worth including. I’ll see if I can find it again, I would very much like to join in on that to fill in some of the Cesium gaps.

Cheers,

Alex

1 Like

Hi @Alexander_Johannesen, thanks for your observations. I wanted to clarify one thing:

One would think that the global terrain would have been adjusted to geoid models, but you’re saying it is not and will globally be incorrect, even within the parameters of ellipsoid correctness?

I don’t know if “correct” or “incorrect” is the right term here. To describe a terrain height, we need to make a choice between two references:

  1. Height above the WGS84 ellipsoid. This is typically the measurement you would get from a satellite.
  2. Height above the geoid. This is the value you would get from a ground-based survey.

Cesium uses heights above the WGS84 ellipsoid, as discussed in this older thread. This means that if you have a terrain source which returns geoid heights, those heights need to be converted to ellipsoid heights before rendering them in Cesium. As discussed in the thread, the geoid itself is a large file, so it usually makes sense to do the conversion as a pre-processing step on the input terrain dataset.

For Cesium to render geoid-referenced heights directly, we would have to load the geoid file at render time, in order to render each point at the correct screen position. So far, we have found it more efficient to convert heights to ellipsoid values instead.

1 Like

Hi there,

I don’t know if “correct” or “incorrect” is the right term here

I agree, it’s a tricky subject. And of course doing heights above the ellipsoid is easier, I think we all understand that, and I appreciate that there’s a difference between height above ellipsoid, geoid, and the ever moving target of sea level. No matter what we do, there’s pros and cons to our choices.

I guess a non-geophysics person might be stumped at seeing their sea level (which to normal people is their 0m reference) be ±20m off that. I know there’s several normalised versions of this, but like you say, all of them are tricky in real-time.

I’ll try to see if I can find both geoid and tide data for any given area of interest. I do have a 5x5m terrain map of Australia (GDA94) that I can try to combine with various geoids in trying to get a more fluid accuracy. I wonder if there’s a way in Cesium to draw the tide limits on the terrain using some band? Doesn’t have to be real-time, but maybe as a transparent zone? Hmm, I have to determine how much time I can use on something that may not be important enough. :slight_smile: My life in a nutshell.

Cheers,

Alex

1 Like

The other problem with coastal areas with the larger global datasets is interpolation across a coarse elevation sample grid.

E.g. About 2-3 years ago, Google’s Elevation API (which from memory was EGM96 back then, and I think EGM2008 now) - would return 0-20 m of elevation on the sea closest to the coast where I live (coastal Sydney). Their API also showed the sample cell spacing was 90 m, which meant the orange zone in the sea got interpolated up to the next inland sample to give elevations along the red line. This can be quite substantial in hilly coastal areas.

I patch in LiDAR data sets to Cesium terrain in the area of interest. I however work with areas around 10 km², so can just set Cesium’s georeference origin height to the height above the WGS84 ellipsoid at the centre of the area of interest, and by the time I get to the borders, the differences between Cesium’s WGS84 height the GeoId based vertical datum the LiDAR is in is minimal (but stilll requires stitching).

For showing the tide limits on the terrain - just get or construct them in Geojson and use Cesium’s geojson raster overlay.

I obtain the EGM2008 Geoid via a local GDAL install with an appropriately sized dataset (can be large).

2 Likes