I’m working on transitioning a project to Cesium from the Google Earth API
I had to deal with and noticed a few posts and questions related to clamping features to terrain, like the KML altitudeMode clampToGround and I thought i would share my workaround.
I’m working with the data data directly in javscript rather than a kml.
I add the placemarks / billboards individually without elevation/altitude then follow up with a sampleTerrain request with a callback to update the position to include the elevation info for the billboard and label
the following should run in Sandcastle:
var viewer = new Cesium.Viewer(‘cesiumContainer’),
scene = viewer.scene,
billboards = scene.primitives.add(new Cesium.BillboardCollection()),
labels = scene.primitives.add(new Cesium.LabelCollection()),
ellipsoid = Cesium.Ellipsoid.WGS84,
pinBuilder = new Cesium.PinBuilder(),
data = [
{id: 'a001', label: 'point 1', longitude: -123 , latitude: 49.40 },
{id: 'a002', label: 'point 2', longitude: -123 , latitude: 49.45 },
{id: 'a003', label: 'point 3', longitude: -123 , latitude: 49.50 },
{id: 'a004', label: 'point 4', longitude: -123 , latitude: 49.55 },
{id: 'a005', label: 'point 5', longitude: -123 , latitude: 49.60 },
{id: 'a006', label: 'point 6', longitude: -123 , latitude: 49.65 }];
scene.terrainProvider = new Cesium.CesiumTerrainProvider({
url : '//cesiumjs.org/stk-terrain/tilesets/world/tiles'
});
var addPlacemarks = function(items){
var position,
cartesian ;
items.forEach(
function(item){
position = new Cesium.Cartographic( Cesium.Math.toRadians(item.longitude), Cesium.Math.toRadians(item.latitude));
cartesian = Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude) ;
Cesium.when(
Cesium.sampleTerrain(scene.terrainProvider, 11, [position]),
function(_item, _position) {
return function () {
_item._cesiumGroundElevation = Math.round(100 * _position.height)/100 ;
_item._cesiumBillboard.position = ellipsoid.cartographicToCartesian(_position);
_item._cesiumLabel.position = ellipsoid.cartographicToCartesian(_position);
};
}(item, position));
item._cesiumLabel =
labels.add({
position: cartesian ,
text: item.label,
id: 'label_' + item.id,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE
});
item._cesiumBillboard =
billboards.add({
image: pinBuilder.fromText(item.id, Cesium.Color.RED, 48),
position: cartesian ,
id: 'billboard_' + item.id,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
});
}
);
};
Sandcastle.addToolbarButton(‘Add Points’, function(){
var t = 0;
if(billboards.length > 0){
t = 500;
}
data.forEach(function(item){
if(item._cesiumBillboard){
billboards.remove(item._cesiumBillboard);
labels.remove(item._cesiumLabel);
}
});
setTimeout( function(){
addPlacemarks(data);
},t);
} );