render polygons on ground

I am new to Cesium (and javascript)

I have problems to show a polygon when WorldTerrain is selected.
This is my code:
  var viewer = new Cesium.Viewer('cesiumContainer',{
    terrainProvider : Cesium.createWorldTerrain()
  }
  );

  var polyBlue= new Cesium.GeoJsonDataSource.load('braunschweig_hillerse/groundrisk_polygons_subset0_0.geojson');
  
  polyBlue.then(
    function(polyBlue) {
      var polys_entities = polyBlue.entities.values;
      for (var i=0; i<polys_entities.length; i++)
      {
        var entity = polys_entities[i];
        var cartesianPositions = polys_entities[i].polygon.hierarchy;

        var cartographicPositions = viewer.scene.globe.ellipsoid.cartesianArrayToCartographicArray(cartesianPositions._value.positions);
        var positions=cartographicPositions;

        var promise = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, positions);
        Cesium.when(promise, function(updatePos){
          updatedPos = ;
          for (var j=0; j<positions.length; j++)
          {
            updatedPos.push(positions[j].longitude);
            updatedPos.push(positions[j].latitude);
            updatedPos.push(positions[j].height);
          }

          entity.polygon.hierarchy = Cesium.Cartesian3.fromRadiansArrayHeights(updatedPos);
          entity.polygon.perPositionHeight = true;
          entity.polygon.material = Cesium.Color.BLUE;

        });
      }

      viewer.dataSources.add(polyBlue);
    }
    );
  viewer.zoomTo(polyBlue);

    var redPolygon = viewer.entities.add({
    name : 'Red polygon on surface',
    polygon : {
      hierarchy : Cesium.Cartesian3.fromDegreesArray([ 10.51542928902906, 52.282576680786995,
                               10.51360289533807, 52.283340457479895,
                               10.506454502841559, 52.287258065060719,
                               10.506384657594938, 52.287307830839133 ,
                               10.506724121428361, 52.287491515158628 ,
                               10.507292056871016, 52.287079208668018 ,
                               10.50814087110892, 52.287028718589156 ,
                               10.50944165754134, 52.286649028335773 ,
                               10.511402209744249, 52.286920392423589,
                               10.512307139954732, 52.287488924617122,
                               10.512659788726039, 52.287851342544101,
                               10.512587524063067, 52.288884919379619,
                               10.514887515894781, 52.288714540362456,
                               10.516034142302827, 52.288290360082605,
                               10.516382511476439, 52.288796862699478 ,
                               10.516607475013146, 52.28891832323152,
                               10.518938678050964, 52.289034916457396,
                               10.518656542648899, 52.287880824536927 ,
                               10.516741456550458, 52.287638218263737,
                               10.51736756377977, 52.286776988722131 ,
                               10.517179622359482, 52.286700370146377,
                               10.516195628614165, 52.286630199576415,
                               10.515963675356858, 52.286535532208028,
                               10.515863528024767, 52.285156562017654,
                               10.515888526663229, 52.284952587890814,
                               10.516031218583566, 52.284867855978028,
                               10.517606299902435, 52.284907773873243 ,
                               10.517769012471801, 52.284866973472461,
                               10.515599728958165, 52.282670196291889,
                               10.515465987013249, 52.282640950763842,
                               10.51542928902906, 52.282576680786995 ]),
      material : Cesium.Color.RED
    }
  });

The coordinates read from geoJson file are nearly the same as the ones in "redPolygon".
When I choose Terrain "WGS84", both polygons are shown; the blue one above the red one.
When I choose Terrain "WorldTerrain", the blue one isn't shown correctly, only parts of it, while the red one is ok.

I have two questions:
1. Why is the blue one not shown correctly?
2. Why need the coordinates of the red one not to be changed? If the one of the blue are not changed when "World Terrain", it does not show up at all.

Thanks in advance for help.

Hi there,

It looks like your original geoJSON positions are “below” the world terrain.

So what your doing with the blue polygon is looping through each of the polygon positions in world space (an absolute x,y,z position), converting it to a cartographic position (an object with latitude, longitude, and height), then setting the height value to the surface of the terrain. Once you convert this back to a position in world space, the position is on terrain instead of below it, so you can now see it.

But since this is pretty common, you can just clamp you geometry to the terrain by setting:

viewer.scene.globe.depthTestAgainstTerrain = true;

``

Thanks,

Gabby

Hi Gabby,
thanks for your reply.

In my code I already convert the position of the polygon to Cartographic ones and get the corresponding terrain height by calling "SampleTerrainMostDetailed".
This does not work.

Just setting
    viewer.scene.globe.depthTestAgainstTerrain = true;
and do no conversion

lead to the blue polygon not to be shown at all.

I finally found out, that my problem has to do with
"viewer.dataSource.add"

dataSource.add seems not to work with
"viewer.scene.globe.depthTestAgainstTerrain = true"

If I load the geoJson-file and create for each loaded polygon a new Cesium.entity and a new cesium.polygonGraphics it works.

code-snipplet:

viewer.scene.globe.depthTestAgainstTerrain = true;

var groundriskPolygons = new Cesium.GeoJsonDataSource.load('...');

groundriskPolygons.then(
  function(groundriskPolygons) {
  var polys_entities = groundriskPolygons.entities.values;
  for (var i = 0; i < polys_entities.length; i++) {
       var entity = new Cesium.Entity();
       var poly = new Cesium.PolygonGraphics();
       poly.hierarchy polys_entities[i].polygon.hierarchy;
       poly.material = ...;
       entity.polygon = poly;
       viewer.entities.add(entity);
  }
    }
)

Is there no smarter way to do this?
Besides, I want to reference to "groundriskPolygons"

I think Cesium.GeoJsonDataSource.clampToGround is what you’re looking for.

You can also pass it as an options object parameter when loading the geojson:

viewer.dataSources.add(Cesium.GeoJsonDataSource.load('url.geojson', {
  clampToGround : true
}));

Hi,
thanks for your replay, but this does not work for me.

Here is another example-code:

  var viewer = new Cesium.Viewer('cesiumContainer',{
    terrainProvider : Cesium.createWorldTerrain()
  }
  );

  viewer.scene.globe.depthTestAgainstTerrain = true;
  Cesium.GeoJsonDataSource.clampToGround = true;
  
  var polyBlue= new Cesium.GeoJsonDataSource.load('braunschweig_hillerse/groundrisk_polygons_harz_subset0.geojson',
  {clampToGround : true});
  
  polyBlue.then(
    function(polyBlue) {

    var polys_entities = polyBlue.entities.values;
      for (var i=0; i<polys_entities.length; i++)
      {
        var entity = polys_entities[i];
        
        var area_0 = new Cesium.Entity();
        var poly_0 = new Cesium.PolygonGraphics();
        poly_0.hierarchy = entity.polygon.hierarchy;
        poly_0.material = Cesium.Color.BLUE;
        area_0.polygon = poly_0;
        viewer.entities.add(area_0);
        viewer.zoomTo(area_0);
      }

/*
      var polys_entities = polyBlue.entities.values;
      for (var i=0; i<polys_entities.length; i++)
      {
        var entity = polys_entities[i];
        
        entity.polygon.material = Cesium.Color.GREEN;
        }
      viewer.dataSources.add(polyBLUE);
*/
      }
  );

The blue polygon is shown; if I comment that part out and use the one actually commented nothing is shown.
What am I doing wrong?

This is my dataSource-file:
{
"type": "FeatureCollection",
"name": "groundrisk_polygons_harz_subset0",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "source": "CLC", "name": "Harz_wurmberg", "groundrisk": 80.0, "id": "217", "buffer": 0.0 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 10.610416, 51.758926 ], [ 10.61076, 51.761662 ], [ 10.616596, 51.761636 ], [ 10.614279, 51.757651 ] ] ] } }
]
}

Hi,
thanks for your reply, it works!

I fault was polyBLUE instead og polyBlue.

I now have the same problem with a cylinder.
Does "clampToGround" not work with CylinderGraphics?

I have points which I want to show as cylinders instead of billboards.
As long a I am showing billboards, it works fine. When I undefine billboards and add cylinders they appear beneath the surface.

code-snipplet:

viewer.scene.globe.depthTestAgainstTerrain = true;
Cesium.GeoJsonDataSource.clampToGround = true;
  
var pointRED= new Cesium.GeoJsonDataSource.load('braunschweig_hillerse/obstacle_points_harz_subset0.geojson',{clampToGround : true});
  
pointRED.then(
  function(pointRED) {
    var point_entities = pointRED.entities.values;
    var positions = getPointPositions(point_entities);
      
    for (var i=0; i<point_entities.length; i++)
      {
  var entity = point_entities[i];

  // change position, because origin of cylinder is in middle
  entity.position = Cesium.Cartesian3.fromRadians(positions[i].longitude,
            positions[i].latitude,
            positions[i].height +entity.properties.height/2.);

        var radius = entity.properties.radius;
        var color = Cesium.Color.RED;
        var length = entity.properties.height;

        entity.billboard = undefined;
        entity.cylinder = new Cesium.CylinderGraphics({
          material: color,
          length: length,
          topRadius: radius,
          bottomRadius: radius});
          
      }

      viewer.dataSources.add(pointRED);
      viewer.zoomTo(pointRED);
    }
  );

No, CylinderGraphics does not have clamp to ground options. These are the current geometry types that will clamp to terrain.

Thank you for your help.