z-index of markers, points, billboards

I note in the demo programs/sandbox that when one toggles on the terrain provider the markers or points or kml elements become obscured by the terrain at many/most angles. for example this kml sample:

So 2 related questions:

  1. is there a trivial way to ensure that the markers will NOT be obscured…perhaps z-index’ing…?

  2. in general, is there a way to put markers anchored to the terrain, whatever height that may be at? (e.g., so a marker in a valley would appear low down in the valley (but unobscured) while one on a mountain top would appear as such as well when the terrain layer was ‘on’).

thanks.

Hello Ben,

The billboards are obscured because their positions are at the height of the ellipsoid surface, which is often below the height of the terrain. However, you can find the height of the terrain and position billboards accordingly. Take a look at this sandcastle example: https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Terrain.html&label=Showcases

The code for ‘Sample Everest Terrain’ shows how to get the positions for billboards on terrain. The function Cesium.sampleTerrain takes in a terrain provider, level of detail, and a list of Cartographic positions. It returns a promise because it runs asynchonously to find the height of each position, and when the promise resolves a list of the updated positions is returned to the callback function.

Hope this helps!

-Hannah

Thanks very much, this is helpful in principle, good to know.

Practically speaking, though, when i request the height asynchronously, the process does not return and i see an error:

Uncaught TypeError: Cannot read property ‘toString’ of undefined , Cesium.js:430

Any insight? my code is below.

//— request async heightmap
function requestHeightMap() {
//-----add some points to be sampled for height ----
var terrainSamplePositions = ;
var pos =new Cesium.Cartographic(-157.8127, 21.302);//long,lat
terrainSamplePositions.push(pos);
//request heightmap now, process result in callback
console.log(‘calling for async heightmap…’);
console.log(‘saved positions: ‘+terrainSamplePositions.toString());
// when(Cesium.sampleTerrain(terrainProvider, LOD, pos_array),callback)
Cesium.when(Cesium.sampleTerrain(viewer.terrainProvider, 9, terrainSamplePositions), sampleTerrainSuccessCallback);
}
//----------callback when height is computed for markers-------------------
function sampleTerrainSuccessCallback() {
console.log(‘in success callback…’);
var ellipsoid = Cesium.Ellipsoid.WGS84;
viewer.scene.globe.depthTestAgainstTerrain = true;
viewer.entities.suspendEvents();
viewer.entities.removeAll();
//for each position that was resampled to include height:
console.log(’…there are ‘+terrainSamplePositions.length+’ elements resampled…’);
for (var i = 0; i < terrainSamplePositions.length; ++i) {
var position = terrainSamplePositions[i];
viewer.entities.add({
name : position.height.toFixed(1),
position : ellipsoid.cartographicToCartesian(position),
billboard : {
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
scale : 1.0,
image : ‘http://localhost:8080/grid/cesium/Apps/flag.png’ // /grid/cesium/Apps/flag.png’
},
label : {
text : position.height.toFixed(1),
horizontalOrigin : Cesium.HorizontalOrigin.CENTER,
scale : 0.3,
pixelOffset : new Cesium.Cartesian2(0, -14),
fillColor : Cesium.Color.RED,
outlineColor : Cesium.Color.WHITE
}
});
}
viewer.entities.resumeEvents();
}

``

Yes, the problem is with this line:

var pos =new Cesium.Cartographic(-157.8127, 21.302);//long,lat

Cartographic is expecting values in Radians instead of Degrees. Instead, use

var pos = Cesium.Cartographic.fromDegrees(-157.8127, 21.302);//long,lat

And that should fix your problem.

Thanks this part now works for me.

Side note: interestingly (though i did not extensively delve into this) I found that inlining the callback function directly worked as expected, but a little unexpectedly (but not show-stopping-ly) referencing the function by name didn’t work so well. So this worked:

Cesium.when(Cesium.sampleTerrain(viewer.terrainProvider, 9, terrainSamplePositions), function(){
console.log(‘in success callback…there are ‘+terrainSamplePositions.length+’ elements resampled…’);
var ellipsoid = Cesium.Ellipsoid.WGS84;
(etc)(etc)

``

Your callback function needed an argument for terrainSamplePositions since it was out of scope of the other variable. ie, doing function sampleTerrainSuccessCallback(terrainSamplePositions) {… should fix that problem.