Get height of position on Cesium3DTileset / Clamp objects to Cesium3DTileset

Hello!
I have an issue with my data and Cesium3DTileset.
My script loads json output with polygons which are clamping to default terrain provider. But I also have a custom terrain layer which is basically a Cesium3DTileset and loaded like that:

phgr = new Cesium.Cesium3DTileset({
    url: `${schema_name}/tileset.json`, // URL from `Starting the Server` section.
    clampToGround: true
})
viewer.scene.primitives.add(phgr);

This terrain is a bit higher and differs from original terrain provider and my polygons are clamped to it by default, not to Cesium3DTileset layer.

So here how are my polygons look on default terrain:

And here is how it looks with Cesium3DTileset:

For getting height references of default terrain I used some found methods:

  1. Making a collection of entity positions.
  2. Using them in Cesium.when(Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, heights_list), function() {} to get a right height at polygon position and set it to polygon entity.

But how to get a height for a Cesium3DTileset on a same position? I tried scene.clampToHeight(position, [entity_s]) which was offered here: https://sandcastle.cesium.com/index.html?src=Clamp%20to%203D%20Tiles.html but it didn’t helped…

Well I’ve already figured out it myself.

Firstly I needed to make a check whether there is a Cesium3DTileset in current scene. I check it like that:

c3d_layers = viewer.scene.primitives._primitives.filter(pr => pr.constructor.name=='Cesium3DTileset')

Then I collect heights before setting a new height position of my data. If Cesium3DTileset exists in current scene, I check a height clamped to it and put its number into list. If there’s no Cesium3DTileset I push a raw cartesian position.

heights_list = []
for (var i = 0; i < pg_enitites.length; i++) {
    pg_entity = pg_enitites[i]
    var position
    if (c3d_layers.length>0) {
        cth = scene.clampToHeight(position, [pg_entity])
        pos_height = Cesium.Cartographic.fromCartesian(cth).height
        heights_list.push(pos_height);
    }else{
        heights_list.push(Cesium.Cartographic.fromCartesian(position));
    }
}

Finally I use sampleTerrainMostDetailed() method in a way like that

Cesium.when(Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, heights_list), function() {
    for (var i = 0; i < pg_enitites.length; i++) {
        var entity_s = pg_enitites[i];
        if (c3d_layers.length>0){
            terrainHeight = heights_list[i]
        }else{
            terrainHeight = heights_list[i].height
        }
        entity_s.polygon.height = terrainHeight;

    }
})

It’s not elegant at least at the point when heights_list is collecting. I could push raw heights there but the reason why I didn’t do this is next step with sampleTerrainMostDetailed() method. This method calculates entity’s position height itself based on default terrain. By default entity’s position height is 0 so as far as I understood sampleTerrainMostDetailed() calculates the topmost height of entity on default terrain. It woks if no Cesium3DTileset exist in scene. If it is Cesium takes a raw height number that was calculated before.

Here is a result:

1 Like