3d tiles under terrain and single layer pickering

1,652 views
Skip to first unread message

pcarrera...@gmail.com

unread,
May 23, 2018, 4:09:41 AM5/23/18
to cesium-dev
1. A concise explanation of the problem you're experiencing.


Hello everyone. I am new to Cesium and during the realization of my app I had 2 problems. First, my app has a 3dTiles layer with 3d buildings and a geojsondatasoure layer with the scope of the project. I just want to get information by picking the buildings, but if the 2 layers are active I can not; the geojson datasource stays on top of me and does not let me select the buildings (photo 1). What I can do? The second problem comes with 3d buildings and their attachment to the model of elevations. With the ellipsoid there is no problem, the problem comes with cesium world terrain. They are sunk under the ground. I have tried with heightOffset but some continue sunk or overraised. Is there any way to individually place each building on the ground? Thank you very much, Pol

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



<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Use correct character set. -->
  <meta charset="utf-8">
  <!-- Tell IE to use the latest, best version. -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>Hello World!</title>
  <script src="../Build/Cesium/Cesium.js"></script>
  <style>
      @import url(../Build/Cesium/Widgets/widgets.css);
      html, body, #cesiumContainer {
          width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
      }

      #toolbar {
         background: rgba(42, 42, 42, 0.8);
         padding: 4px;
         border-radius: 4px;
     }
     #toolbar input {
         vertical-align: middle;
         padding-top: 2px;
         padding-bottom: 2px;
     }
     #toolbar .header {
         font-weight: bold;
     }

     h2 {
         color: black;
     }

     p {
         color: black;
     }



     



</style>
</head>
<body>


<div id="toolbar">

    <input type="checkbox" value="false" data-bind="checked: debugBoundingVolumesEnabled, valueUpdate: 'input'"  id="showCheckbox"> Àmbit
    <input type="checkbox" value="true" data-bind="checked: edgeStylingEnabled, valueUpdate: 'input'" id="showCheckbox1"> 3dBuildings



   
    </div>



<div id="cesiumContainer"></div>




<script>


var extent = Cesium.Rectangle.fromDegrees(2.200423178619758, 41.427599, 2.210423178619758, 41.417599);

  Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
  Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;





var terrain = Cesium.createDefaultTerrainProviderViewModels();

    var viewer = new Cesium.Viewer('cesiumContainer', {

        mapProjection : new Cesium.WebMercatorProjection(),
        timeline: false,
        animation: false,
        baseLayerPicker: true,

        scene3DOnly: true,
        terrainProviderViewModels: terrain,
        selectedTerrainProviderViewModel: terrain[1]
        //shadows:true



        });


var initialPosition = Cesium.Cartesian3.fromDegrees (2.200423178619758, 41.417599, 1000);
    var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(21.27879878293835, -21.34390550872461, 0.0716951918898415);
    viewer.scene.camera.setView({
        destination: initialPosition,
        orientation: initialOrientation,

        endTransform: Cesium.Matrix4.IDENTITY

    });


Cesium.GeoJsonDataSource.clampToGround = true;
  var ambit = new Cesium.GeoJsonDataSource(); ambit.load('SampleData/ambit5.json',{

stroke: Cesium.Color.BLACK,
    fill:Cesium.Color.RED.withAlpha(0.1),
    strokeWidth: 50,
    markerSymbol: '?'


});

var botoambit = document.getElementById('showCheckbox');
    botoambit.addEventListener('change', function() {

        if (botoambit.checked) {
            // Show if not shown.
            if (!viewer.dataSources.contains(ambit)) {
                viewer.dataSources.add(ambit);
            }
        } else {

            if (viewer.dataSources.contains(ambit)) {
                viewer.dataSources.remove(ambit);
            }
        }
    }, false);


    var edificis = new Cesium.Cesium3DTileset({ url: 'SampleData/model_bo/tileset.json' });
     tileset = viewer.scene.primitives.add(edificis);
    edificis.show=false;
    var botoedificis = document.getElementById('showCheckbox1');
        botoedificis.addEventListener('change', function() {

            if (botoedificis.checked) {
                // Show if not shown.
                if (!viewer.dataSources.contains(edificis)) {

    edificis.show=true;
                }
            } else {
                    edificis.show=false;

            }
        }, false);



var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'] = 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'white';

// Information about the currently selected feature
var selected = {
    feature: undefined,
    originalColor: new Cesium.Color()
};

// Information about the currently highlighted feature
var highlighted = {
    feature: undefined,
    originalColor: new Cesium.Color()
};

// An entity object which will hold info about the currently selected feature for infobox display
var selectedEntity = new Cesium.Entity();

// Color a feature yellow on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
    // If a feature was previously highlighted, undo the highlight
    if (Cesium.defined(highlighted.feature)) {
        highlighted.feature.color = highlighted.originalColor;
        highlighted.feature = undefined;
    }

    // Pick a new feature
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if (!Cesium.defined(pickedFeature)) {
        nameOverlay.style.display = 'none';
        return;
    }

    // A feature was picked, so show it's overlay content
    nameOverlay.style.display = 'block';
    nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
    nameOverlay.style.left = movement.endPosition.x + 'px';
    var name = pickedFeature.getProperty('REFCAT');
    if (!Cesium.defined(name)) {
        name = pickedFeature.getProperty('id');
    }
    nameOverlay.textContent = name;

    // Highlight the feature if it's not already selected.
    if (pickedFeature !== selected.feature) {
        highlighted.feature = pickedFeature;
        Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
        pickedFeature.color = Cesium.Color.YELLOW;
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// Color a feature on selection and show metadata in the InfoBox.
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
    // If a feature was previously selected, undo the highlight
    if (Cesium.defined(selected.feature)) {
        selected.feature.color = selected.originalColor;
        selected.feature = undefined;
    }

    // Pick a new feature
    var pickedFeature = viewer.scene.pick(movement.position);
    if (!Cesium.defined(pickedFeature)) {
        clickHandler(movement);
        return;
    }

    // Select the feature if it's not already selected
    if (selected.feature === pickedFeature) {
        return;
    }
    selected.feature = pickedFeature;

    // Save the selected feature's original color
    if (pickedFeature === highlighted.feature) {
        Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
        highlighted.feature = undefined;
    } else {
        Cesium.Color.clone(pickedFeature.color, selected.originalColor);
    }

    // Highlight newly selected feature
    pickedFeature.color = Cesium.Color.LIME;

    // Set feature infobox description
    var featureName = pickedFeature.getProperty('REFCAT');
    selectedEntity.name = featureName;
    selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>';
    viewer.selectedEntity = selectedEntity;
    selectedEntity.description = '<table class="cesium-infoBox-defaultTable"><tbody>' +
                                 '<tr><th>PLAN</th><td>' + pickedFeature.getProperty('PLAN_') + '</td></tr>' +
                                 '<tr><th>DESCRIPCIO</th><td>' + pickedFeature.getProperty('DESCRIP_12') + '</td></tr>' +
                                 '<tr><th>PARCELA</th><td>' + pickedFeature.getProperty('PARCELA') + '</td></tr>' +
                                '<tr><th>AREA</th><td>' + pickedFeature.getProperty('AREA') + '</td></tr>' +
                                '<tr><th>CODI INE</th><td>' + pickedFeature.getProperty('CODI_INE') + '</td></tr>' +

                                '<tr><th>COORX</th><td>' + pickedFeature.getProperty('COORX') + '</td></tr>' +
                                '<tr><th>COORY</th><td>' + pickedFeature.getProperty('COORY') + '</td></tr>' +
                                '<tr><th>DELEGACIO</th><td>' + pickedFeature.getProperty('DELEGACIO') + '</td></tr>' +

                                '<tr><th>DATAALTA</th><td>' + pickedFeature.getProperty('FECHAALTA') + '</td></tr>' +

                                '<tr><th>MASSA</th><td>' + pickedFeature.getProperty('MASA') + '</td></tr>' +
                                '<tr><th>NOM_MUNICIPI</th><td>' + pickedFeature.getProperty('NOMMUNI_1') + '</td></tr>' +

                                '<tr><th>NORMATIVA</th><td>' + pickedFeature.getProperty('NORMATIV') + '</td></tr>' +
                                '<tr><th>NUMERO</th><td>' + pickedFeature.getProperty('NUMERO') + '</td></tr>' +

                                '<tr><th>PGM</th><td>' + pickedFeature.getProperty('PGM') + '</td></tr>' +

                                '<tr><th>VIA</th><td>' + pickedFeature.getProperty('VIA') + '</td></tr>' +
                                '<tr><th>ZMAX</th><td>' + pickedFeature.getProperty('Z_Max') + '</td></tr>' +
                                '<tr><th>ZMIN</th><td>' + pickedFeature.getProperty('Z_Min') + '</td></tr>' +
                '</tbody></table>';
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);


tileset.style = new Cesium.Cesium3DTileStyle({
color : {
conditions : [
["(${DESCRIP_12}) === 'Zona industrial'","rgb(250,0,0)"] ,
                  ["String(${DESCRIP_12}) === 'Densificacio Urbana Semiintensiva'","rgb(250, 100, 0)"] ,
["String(${DESCRIP_12}) === 'Equipaments comunitaris i dotacions'","rgb(66, 8, 181)"] ,
    ["String(${DESCRIP_12}) === 'Equipaments en Ordenacio  en volumetria especifica'","rgb(66, 135, 181)"] ,
      ["String(${DESCRIP_12}) === 'Ordenacio'","rgb(155, 135, 181)"] ,
        ["String(${DESCRIP_12}) === 'Ordenacio en volumetria especifica'","rgb(155, 100, 118)"] ,
          ["String(${DESCRIP_12}) === 'Ordenacio en volumetria especifica en centre direccional'","rgb(155, 100, 75)"] ,
            ["String(${DESCRIP_12}) === 'Ordenaciol en filera'","rgb(155, 109, 9)"] ,
              ["String(${DESCRIP_12}) === 'Parcs i jardins urbans'","rgb(156, 204, 43)"] ,
                ["String(${DESCRIP_12}) === 'Proteccia de sistemes generals'","rgb(110, 129, 140)"] ,
                  ["String(${DESCRIP_12}) === 'Renovacia urbana: transformacio'","rgb(188, 251, 41)"] ,
                    ["String(${DESCRIP_12}) === 'Sistema de serveis tecnics'","rgb(15, 75, 41)"] ,
                      ["String(${DESCRIP_12}) === 'Sistema ferroviari'","rgb(222, 75, 181)"] ,
                        ["String(${DESCRIP_12}) === 'Sistema portuari'","rgb(15, 75, 181)"] ,
                          ["String(${DESCRIP_12}) === 'Sistema portuari - Zona maritimo-terrestre'","rgb(1, 216, 255)"] ,
                            ["String(${DESCRIP_12}) === 'Sistema viari basic'","rgb(189, 216, 255)"] ,

["true", 'color("white")']
]
}
/*color : {
conditions : [
["Number(${MUNICIPIO}) = 245", "rgb(250,0,0)"]
]
}*/
});


var heightOffset = 50;

tileset.readyPromise.then(function(tileset) {
    var boundingSphere = tileset.boundingSphere;
    //viewer.camera.viewBoundingSphere(boundingSphere, new Cesium.HeadingPitchRange(0, -2.0, 0));
    //viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
    // Position tileset
    var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
    var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
    var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
    var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
    console.log(tileset.modelMatrix);
});



</script>
</body>
</html>



----------------------------------------------------

The ambit5.json file contains the project framework and the tileset.json contains the buildings. thank you very much again



unter...@gmail.com

unread,
May 24, 2018, 5:37:47 AM5/24/18
to cesium-dev
I have a similar problem; but instead of 3DTile I am using a simpe box.
On WGS84 Ellipsoid the box is clipped to the ground; when on WorldTerrain the box is partwise beneath the surface.
You can confirm this:
- setting to WGS84-Ellipsoid
- Click "onEllipsoid"
--> the box is clipped to ground
- click "magnitude 10"
- click "up"
--> the box is "flying" over the surface

- setting to Cesium World Terrain
- click "onTerrain"
--> part of the box is beneath surface:
- click "magnitude 10"
- click "up"
--> the box is comimg more up but still partwise under surface


This is the code:
var viewer = new Cesium.Viewer('cesiumContainer');
var CC3 = Cesium.Cartesian3;
var magnitude = 1;

var box_height = 30;

var thebox = viewer.entities.add({
name : 'building',
position: Cesium.Cartesian3.fromDegrees(-90.1922703175, 38.6286636758, box_height/2),
box : {
dimensions : new Cesium.Cartesian3(40, 30, box_height),
material : Cesium.Color.RED,
outline : true,
outlineColor : Cesium.Color.BLACK
}
});
viewer.zoomTo(viewer.entities);

//var terrainProvider = new Cesium.CesiumTerrainProvider({
// url : '//assets.agi.com/stk-terrain/world',
requestVertexNormals : true
//});

var terrainProvider = Cesium.createWorldTerrain();

function getVector(name)
{
var GD_full_transform = Cesium.Transforms.eastNorthUpToFixedFrame(thebox._position._value, viewer.scene.globe.ellipsoid, new Cesium.Matrix4());
var GD_rot_transform = Cesium.Matrix4.getRotation(GD_full_transform,new Cesium.Matrix3());
if(name=="east"){return Cesium.Matrix3.getColumn(GD_rot_transform,0,new CC3());}
if(name=="north"){return Cesium.Matrix3.getColumn(GD_rot_transform,1,new CC3());}
if(name=="up"){return Cesium.Matrix3.getColumn(GD_rot_transform,2,new CC3());}
}
function move(scalar,unitVector)
{
var mycarte = thebox._position._value;
var relMove = CC3.multiplyByScalar(unitVector,scalar,new CC3());
CC3.add(mycarte,relMove,mycarte);
thebox.position = mycarte;
var mycarto = new Cesium.Cartographic();
mycarto = viewer.scene.globe.ellipsoid.cartesianToCartographic(thebox._position._value);
console.log("lon "+mycarto.longitude/Math.PI*180);
console.log("lat "+mycarto.latitude/Math.PI*180);
console.log("alt "+mycarto.height);
}

function setOnTerrain()
{
var mycarte = thebox._position._value;
thebox.position = mycarte;
var mycarto = new Cesium.Cartographic();
mycarto = viewer.scene.globe.ellipsoid.cartesianToCartographic(thebox._position._value);
//takes the terrain, a precision value and the point of interest
Cesium.sampleTerrain(terrainProvider, 11, [mycarto]).then(function(){
console.log("setting to terrain height: "+(mycarto.height));
mycarto.height += box_height/2;
thebox.position = viewer.scene.globe.ellipsoid.cartographicToCartesian(mycarto);
});
}

function setOnEllipsoid()
{
var mycarte = thebox._position._value;
thebox.position = mycarte;
var mycarto = new Cesium.Cartographic();
mycarto = viewer.scene.globe.ellipsoid.cartesianToCartographic(thebox._position._value);
mycarto.height = box_height/2;
console.log("setting to ellipsoid height: "+(mycarto.height));
thebox.position = viewer.scene.globe.ellipsoid.cartographicToCartesian(mycarto);
}

Sandcastle.addToolbarButton('magnitude 1', function()
{magnitude=1;});
Sandcastle.addToolbarButton('magnitude 10', function()
{magnitude=10;});

Sandcastle.addToolbarButton('east', function()
{move(magnitude,getVector("east"));});
Sandcastle.addToolbarButton('west', function()
{move(-magnitude,getVector("east"));});
Sandcastle.addToolbarButton('north', function()
{move(magnitude,getVector("north"));});
Sandcastle.addToolbarButton('south', function()
{move(-magnitude,getVector("north"));});
Sandcastle.addToolbarButton('up', function()
{move(magnitude,getVector("up"));});
Sandcastle.addToolbarButton('down', function()
{move(-magnitude,getVector("up"));});
Sandcastle.addToolbarButton('onTerrain', function()
{setOnTerrain();});
Sandcastle.addToolbarButton('onEllipsoid', function()
{setOnEllipsoid();});


What is wrong?

Gabby Getz

unread,
May 25, 2018, 9:34:42 AM5/25/18
to cesium-dev
Hi all, 

Pol, I don't think you attached that image, seeing it would help!

unterzwerg, I don't understand what problem you are having. Do you not want the box to be below terrain at all?

Thanks,
Gabby

pol carrera balsells

unread,
May 25, 2018, 10:19:47 AM5/25/18
to cesiu...@googlegroups.com
Hello Gabby,

 I have not remembered to put the images as an example, I'm sorry. In this email I attached 4 images where it is clear how the buildings look in WSG84 and in Cesium World Terrain as well as the problem that I have with the picking when having selected both the buildings and the scope of the project.

Thank you very much,

Pol
buildings+ambit picking.jpg
picking_buildings.jpg
buildings_WSG84_ellipsoid.JPG
buildings_cesium_world_terrain.JPG

Sean Lilley

unread,
May 27, 2018, 11:48:28 AM5/27/18
to cesium-dev
unterzwerg - try using sampleTerrainMostDetailed. The box lines up perfectly after doing that.


On Thursday, May 24, 2018 at 5:37:47 AM UTC-4, unter...@gmail.com wrote:

Sean Lilley

unread,
May 27, 2018, 2:17:19 PM5/27/18
to cesium-dev
Hey Pol,

For the issue where the GeoJSON is preventing picking buildings, you can use drillPick to get the building that's underneath the GeoJSON. Also in Cesium 1.46 the GeoJSON will no longer drape over 3D Tiles by default so this may not be a problem once you upgrade.

For the second issue, Cesium doesn't support clamping 3D Tiles to terrain. The most common workaround is to adjust the height of the tileset like in this Sancastle demo. You can determine a good height to use by calling sampleTerrainMostDetailed.

unter...@gmail.com

unread,
May 28, 2018, 5:39:46 AM5/28/18
to cesium-dev
Hello Gabby,
thanks for answering
I want the box to be ABOVE the terrain at all; the box should be positioned on the ground.

unter...@gmail.com

unread,
May 28, 2018, 5:50:57 AM5/28/18
to cesium-dev
Thank you!!!
I suppose that works!

pol carrera balsells

unread,
May 29, 2018, 4:43:35 AM5/29/18
to cesiu...@googlegroups.com

Hi, Sean. Thank you for answering so quickly. I have been working on the heights with the sampleTerrainMostDetailed to adjust the height of the buildings in the terrain model through a button. ------ var buttonheight = document.getElementById ('showCheckbox2');         buttonheight.addEventListener ('change', function () { var cartographic = Cesium.Cartographic.fromCartesian (tileset.boundingSphere.center); var promise = Cesium.sampleTerrainMostDetailed (viewer.terrainProvider, [cartographic]);      Cesium.when (promise, function (updatedPositions) { var cartographic = updatedPositions [0]; var surface = Cesium.Cartesian3.fromRadians (cartographic.longitude, cartographic.latitude, 0.0); var offset = Cesium.Cartesian3.fromRadians (cartographic.longitude, cartographic.latitude, cartographic.height); var translation = Cesium.Cartesian3.subtract (offset, surface, new Cesium.Cartesian3 ()); tileset.modelMatrix = Cesium.Matrix4.fromTranslation (translation); });         }, false); ----------------------------------------- The problem, I think, is that in cartographic var just pick up the position of the bounding sphere. Is there a method to collect the positions of the buildings one by one? I think this would improve the adjustment. Here is a picture of the result:


some buildings are anchored to the ground ... others not yet. Greetings, Pol




--
You received this message because you are subscribed to the Google Groups "cesium-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sean Lilley

unread,
May 29, 2018, 7:58:44 PM5/29/18
to cesium-dev
There isn't a way to adjust individual buildings right now. The next closest thing is setting the transform of individual tiles. Just be careful though because the transforms are applied hierarchically, so the parent tile transform affects the child tile transform.

To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+...@googlegroups.com.

pol carrera balsells

unread,
May 31, 2018, 3:46:19 AM5/31/18
to cesiu...@googlegroups.com
Thanks Sean.

I'm gonna left the buildings on the WGS84 Ellipsoid. Transformations of individual tiles sounds too complicated for me. 

Cheers,

Pol

To unsubscribe from this group and stop receiving emails from it, send an email to cesium-dev+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages