sampleTerrainMostDetailed returns inconsistent heights

I’m calling sampleTerrainMostDetails() on the same dataset of 9222 lat/longs and receiving inconsistent return arrays.
Sometimes, it returns a height at every index as expected. Other times, it returns random amounts of “height: undefined”. One test has 463 undefineds, 198 for another, and 121 undefineds for another. Each time, for a different lat/long (I thought maybe particular lat/lons would be problematic, but that doesn’t seem to be the case).
Secondarily, the call always takes longer than 21 seconds to complete, which is a long time, but perhaps unavoidable.

How can I change my usage to be able to rely on the data from sampleTerrainMostDetails()?
The goal is to be able to place entities on top of the ground (whatever height Cesium drew the ground at), so if there’s a better/different way to do that, works for me.

I don’t think sampling at a lower detail is doable, as we are often looking at locations close to the ground, and getting the height wrong due to lack of precision would result in entities clipping below the ground or entirely underground.
Also, I am initializing cesium with “terrainProvider: createWorldTerrain()” to have actual terrain, so just height above ellipsoid values aren’t good enough.

Thank you,
Tawm

2 Likes

I vaguely remember that I had problems with the inconsistent heights. I kind of solved it by waiting a bit until

viewer.scene.globe.tilesLoaded === true

and only then calling sampleTerrainMostDetailed() . I am not sure if there is a direct connection though between tilesLoaded status or just the waiting did that.

However, I don’t remember the call taking this long - (always) taking 21 seconds sounds suspicious. It was always executed super quick for me.

sampleTerrainMostDetailed should be loading in the highest level of detail for the sampled points before sampling any points. Unless there are network failures or the server is returning inconsistent terrain tiles, it should return very similar results.

The 21 seconds also seems long.

@Tawn Could you provide some additional details about the scenario? What terrain are you sampling? Is this a web app, or a node app? Can you reproduce the issue using a Sandcastle code example?

Hi @Gabby_Getz, thanks for the reply.

This post got kind of long so here’s a TL;DR:
(1) A Sandcastle (link too long) that has a hardcoded array of 9000 lat/longs.
(2) This Sandcastle builds a list of 9000 lat/longs.
Both Sandcastles usually work under normal network conditions or seemingly anywhere in the USA via VPN. There are occasional failures.
Sandcastle 1 fails using a VPN through Mexico. Sandcastle 2 works through Mexico.
(2) is always faster than (1), succeed or fail?

Full answer:

I’m building a web app, sampling what I believe is the default Cesium terrain set.
I’ve created a Sandcastle which pretty accurately matches my use-case (Sandcastle 1 above).

In my testing, it is very rare that I run into any issues, the call is normally successful.
If there is a problem, it seems to be directly related to receiving a bunch of errors: “Failed to load resource: net::ERR_INSUFFICIENT_RESOURCES”.


(Note: this pic is from the above Sandcastle under normal network conditions; no VPN.)

I started investigating this problem because a teammate located in Mexico was getting undefined heights consistently. So I setup a VPN (Nord) through Mexico and started seeing the problem consistently.

In my testing today, I haven’t been able to get a successful call through the VPN and am getting results looking like the below picture; many failed calls and an inconsistent amount of undefined heights.

This test took 101 seconds and resulted in 2345 “height: undefined”:

This one took 49 seconds and resulted in 1615 “height: undefined”:

Further testing with a different Sandcastle (Sandcastle 2 above) in which I build a list of lat/longs instead of defining an array in a variable, results in much more consistent successful calls.
Still using the VPN, these calls only take about 5.5 seconds with no undefined heights.

Without VPN or using VPN through USA (Florida, Kansas City, San Francisco) result in successful calls in both Sandcastles. It should be noted that I am located in the USA; may affect speed.
Using a VPN through Mexico fails on the first Sandcastle and succeeds in the second.
That would potentially indicate that specific lat/longs are problematic, but the undefined heights are inconsistent, so probably not.

I’m at a loss. I hope I provided enough material to cover the troubleshooting cases.

Potential Discovery:
While attempting to post this, it kept failing due to length of Sandcastle 1 URL (encoded string including my 9000+ item array).
Cutting down the size of the array passed to sampleTerrainMostDetailed() seems to reduce the likelihood of a failure. It can still take a very long time though.

Success took 33 seconds:

However, this doesn’t explain why Sandcastle 2 is usually successful where Sandcastle 1 fails.

After probably 200 tests, I’ve made more “discoveries” that don’t make sense to me.

This Sandcastle has a hardcoded array of lat/longs to pass to sampleTerrainMostDetailed().
(^ I couldn’t post the Sandcastle URL since the it is just an encoded string of my code, it was too long. So this link is to a github file, the contents of which should be copy pasted into a blank Sandcastle.)

When running this Sandcastle normally, with no VPN, it works (almost) every time.
When running it while connected to a nearby VPN, I saw bizarre behavior.

While using a VPN, and requesting 7000+ heights (7315 exactly), I found that having my Chrome console log (Chrome Dev Tools, F12) opened seemed to have an impact on whether or not I would receive any “height: undefineds”.
If the Chrome console was closed, the call to sampleTerrainMostDetailed() failed every time.
If the Chrome console was open, the call succeeded every time.
This would lead me to believe there could be some sort of race condition happening in sampleTerrainMostDetailed() itself.

After enough calls, they started succeeding for an unknown reason. And not only that, they started succeeding in ~2 seconds where before they’d all been taking 15-20 seconds succeed or fail.
I took this to mean my calls started getting prioritized for some reason (if that’s even a thing in this instance), so I swapped my VPN to a different state.
After swapping, I saw the same behavior again. Calls failed with a closed Chrome console, and succeeded with an open console, all calls taking around 20-27 seconds.
Swapping back to my initial VPN location, same behavior with success/failures, now taking 15-18 seconds.

Eventually, I started playing with the amount of height requests being sent in a call.
I found that a threshold seems to exist at ~6700 items in a single request.
Having the console open still usually meant a successful call, but now a failed call would only be missing a few heights (1, 14, 10 undefined heights in my tests), and the calls would sometimes succeed (no undefined heights) even with the Chrome console closed.

I tried a different approach so that it would be easier to post here, and modified the above Sandcastle to just build a random collection of lat/longs. However, this sandcastle always succeeded, every time, even with the VPN connection, regardless of Chrome console being open, requesting 10,000 heights, and in about 4 seconds every time.
This leads me to believe even more that some local hangup is happening, since there isn’t a very long hardcoded array.

Very confusing results today, not really sure what to make of it.
Thanks for the assistance.

Thanks for all the info here, it’s very helpful!

Interesting. Can you check in the Network tab if you have Disable cache checked? This would affect the results such that when the console is open, you are making fresh network requests every time, but when the console is closed the previously cached network requests would be used.

This would also explain the difference in timing-- Cached requests don’t need to reach back to the server and will be quicker.

An issue with caching sounds like it is confirmed by the random set of lat/longs. If it’s random each time, there’s no cached result to fall back on.

Unfortunately I think the issue here is likely with the VPN-- Both the long request times and the undefined results. Clearing your cache often might help, but fundamentally in CesiumJS, this is streaming terrain tiles, and to do so we depend on web requests working normally.

We might be able to throw a more helpful error in cases like this, but I’m not sure its possible to completely work around this behavior in CesiumJS itself.