Determine if there is functional terrain loaded

1. A concise explanation of the problem you’re experiencing.

We have a couple of context menu options that need to be enabled/disabled based on whether or not we have functional terrain. Outside of calling something like sampleTerrain to get the height at our object’s point, I haven’t found a way to verify the terrain is functional. Since sampleTerrain just returns 0 when there’s no terrain, we would end up disabling the context menu options for something that happens to be at sea level when we do have terrain.

I thought I would be able to use the ready property on a terrain provider to know if it was working, but I found that it returns true whether it works or not. I’m wondering if there’s a simple flag or non-computational-heavy method that can be checked. If there isn’t, is there something I can use in conjunction with sampleTerrain to avoid the sea level conflict?

I’m pretty new to Cesium in general, so I’ve been poking my way around and Googling with little luck.

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

Since I’m checking the height, I’m currently using:

Cesium.sampleTerrain(terrainProvider, 1, positions);

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

In order to determine if specific context menu options that are dependent on terrain can be turned on or not.

4. The Cesium version you’re using, your operating system and browser.

Version 1.62, Windows 10, Chrome/Chromium

Can you elaborate a bit more on what you mean by functional terrain? You can check if the terrain tiles have loaded yet using this boolean on the Globe instance:

https://cesium.com/docs/cesiumjs-ref-doc/Globe.html?classFilter=globe#tilesLoaded

This will be true once a scene is complete, and become false again if the camera moves and new tiles need to be requested.

You can also listen on this tile progress load event to see how many tiles are left before the scene completes:

https://cesium.com/docs/cesiumjs-ref-doc/Globe.html?classFilter=globe#tileLoadProgressEvent

sampleTerrain will actually return undefined if there is no terrain loaded there (for example if you call that on the other side of the globe, or just something not in view, where no tiles have been requested yet from the server). It sounds like what you’re looking for is to know the extents of your custom terrain. Are you creating your terrain on Cesium ion? Those extents are computed on Cesium ion but not yet exposed. There’s a feature request for this here: https://github.com/AnalyticalGraphicsInc/cesium-ion-community/issues/152

Sure! I mean that the terrain is actually loaded. So if a config is wrong for the terrain, it can be selected, but terrain will not actually load (stays flat).

I did look at that Boolean, but it will still return true if the base maps have loaded, so it's not specific to terrain. Your terrain could fail to load, but once the base map tiles are loaded, it will still be true.

SampleTerrain should return undefined as you said, but I always see 0 when no terrain is selected, or it is selected but fails to load. I don't know if this is a bug or if there's some other weird thing going on that's causing it.

We have a few different terrains we can load. There's the cesium terrain, a local geoserver, and stk terrain.

I think we might be referring to different things. CesiumJS can only load one terrain provider at a time. Can you post the code you’re using to add these terrain datasets to your scene?

Normally what you’d do if you want to combine terrain datasets is do this offline, so you have one tileset that you’re loading into CesiumJS.

We're loading one at a time, it's just that we can switch between them by selecting which one we want in a dojo grid. So we're not combining terrain datasets. Does that clear up that portion?

Yes, that clears that up! It sounds like what you need here is to listen on the readyPromise of the terrain provider to see if it succeeded loading:

https://cesium.com/docs/cesiumjs-ref-doc/TerrainProvider.html#readyPromise

However, if a terrain provider fails to load, CesiumJS won’t display the globe at all, like in this example where you can toggle between a working/broken terrain provider:

So it sounds like your terrain may be failing in a way that CesiumJS isn’t detecting (or is silently ignoring). Would you able to share a sample of your terrain that reproduces this? Otherwise, if you can trace where it’s failing in any of these classes and open a PR to fix this that would be appreciated!

I removed the API key from our config for stk terrain and got the expected result of the promise failing when it tries to call sampleTerrain (and no globe). The one that always "succeeds" is our own geo server cache that's built on arcgisImageServerTerrainProvider, which cesium removed support for at some point (as I found out from a co-worker).

What I now suspect is going on is a promise inside the arcgis file that's resolving the promise with some incorrect criteria. That's something I'll need to look into, but am currently working other tasks at the moment.

Unfortunately, it's difficult to paste any code here because Google groups is blocked by the companies proxy lol. So I have to access it from my phone.