16

So, I'm using cesium and I want to add a polygon or line to represent a property boundary on a terrain surface.

My polygon works fine on the flat/Ellipsoid surface, unfortunately however the polygon doesn't automagically drape over the surface when the terrain layer is shown.

Fair enough, I don't actually have the z/height values - so I'm using the sampleTerrain.js promise method to interpolate the height values based on the terrain. This part works fine, I get my height values. But then what?

I've tried creating a polygon entity with my height-laden positions, but to no avail - it just ignores the height values. When I read the docs, I can really see any reference to height values being ingested - all the "positions" array are two dimensional?

The only reference to height values being considered is in the PolygonOutlineGeometry, which has a promising looking property called perPositionHeight.

This is essentially what I want - I don't want to set the height of the whole poly, I want every points height value to be used..

Here's one of my unsuccessful attempts:

Entity/Polygon:

var entity = viewer.entities.add({
    polygon : {
        hierarchy : cartesianPositions, //array of positions with z values
        outline : true,
        outlineColor : Cesium.Color.RED,
        outlineWidth : 9,
        material : Cesium.Color.BLUE.withAlpha(0.0),
   }
});


Bottom line: I just want a polygon or polyline entity that sits nicely on the surface of the terrain.

EDIT:

Using the Orange Polygon example in the comments of the accepted answer combined with sampleTerrain.js, I've been able to simulate 'draping' a polygon onto terrain, with a list of positions that did not have z values, here's a crude example:

var positions = []; // xy position array    

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

// go off and sample the terrain layer to get interpolated z values for each position..
var promise = Cesium.sampleTerrain(cesiumTerrainProvider, 11, positions);
Cesium.when(promise, function(updatedPositions) {

    var cartesianPositions = Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(updatedPositions);

        var entity = viewer.entities.add({
            polygon : {
                  hierarchy : cartesianPositions,
                  outline : true,
                  outlineColor : Cesium.Color.RED,
                  outlineWidth : 9,
                  perPositionHeight: true,
                  material : Cesium.Color.BLUE.withAlpha(0.0),
            }
        });

    viewer.flyTo(entity);   

});
danwild
  • 1,886
  • 1
  • 26
  • 31
  • why do you have `alpha(0.0)` if you want to see the polygon? according to [Cesium spec](http://cesiumjs.org/Cesium/Build/Documentation/Color.html) 0.0 is _zero intensity_ – Kirill Slatin Apr 28 '15 at 13:15
  • I've intentionally hidden the surface of the polygon, as I am more interested in the border, which *is* visible. This is not really relevant to my question. – danwild Apr 28 '15 at 23:31
  • I'm using the same code, but some of the path segments still are under the ground. Does someone know the reason? – sabrina Dec 16 '15 at 09:01
  • Hey @sabrina, might be worthwhile putting up a jsfiddle to demonstrate the problem, or better still ditch this approach and use the great new GroundPrimitives as suggested in the accepted answer. Also consider asking a new question if need be (feel free to email me a link to the question and I'll take a look tomorrow). – danwild Dec 16 '15 at 10:03
  • Hi @Daniel. I've just understood my problem (but still didn't find a solution)... the positions (path's vertex) are perfectly on the ground; the problem is that the line connecting two points sometimes intersects the ground, going under it. – sabrina Dec 16 '15 at 10:12
  • @Daniel here is my new question: http://stackoverflow.com/questions/34310007/cesium-path-onto-terrain-line-connecting-2-points-goes-under-the-terrain – sabrina Dec 16 '15 at 10:52

2 Answers2

8

As of version 1.13 cesium now supports GroundPrimitives. They will drape over terrain.

It looks like this: http://cesiumjs.org/images/2015/09-01/groundPrimitives.gif

This the example Cesium gives:

var rectangleInstance = new Cesium.GeometryInstance({
  geometry : new Cesium.RectangleGeometry({
    rectangle : Cesium.Rectangle.fromDegrees(-140.0, 30.0, -100.0, 40.0)
  }),
  id : 'rectangle',
  attributes : {
    color : new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5)
  }
});
scene.primitives.add(new Cesium.GroundPrimitive({
  geometryInstance : rectangleInstance
}));
emackey
  • 11,818
  • 2
  • 38
  • 58
Zac
  • 2,201
  • 24
  • 48
  • 1
    Is it possibile to use GroundPrimitives also for paths? This is my code: var target = viewer.entities.add({ position: sample, path: { resolution: 60, material:Cesium.Color.BLUE, width: 4, trailTime: 360, leadTime: 0 } }); where sampe is a Cesium.SampledPositionProperty, so the path is extending over time. How can I drape the path over terrain? – sabrina Dec 16 '15 at 10:31
  • You'll need to use a primitive type and add it to the scene.primitives collection. Looks like you are creating an entity. – Zac Dec 18 '15 at 18:43
  • @emackey Is there a way of achieving this using CZML? – Slaiyer Apr 10 '17 at 11:24
  • @Slaiyer I don't think so, currently. Try asking on the Cesium forum. – emackey Apr 10 '17 at 14:43
5

Cesium does not support vector data on terrain yet. It is being actively worked on and most features should start to appear in Cesium 1.10 which will be out on June 1st. Anything that doesn't make that release should be in 1.11 on July 1st.

For Polygons specifically, you can follow along with the GitHub pull request: https://github.com/AnalyticalGraphicsInc/cesium/pull/2618

For Billboards and Labels, check out: https://github.com/AnalyticalGraphicsInc/cesium/pull/2653

Polylines haven't been started yet but will be as soon as the above two are finished.

Matthew Amato
  • 1,992
  • 17
  • 21
  • Ok, no formal support yet - but the fact that sampleTerrain.js exists says to me that there must be a way to do this, surely? Why would somebody use cesium over openlayers if cesium cannot handle points in 3 dimensional space? – danwild Apr 28 '15 at 23:32
  • My apologies, I misread your question. To use the height values from the positions set the perPositionHeight property to true. The orange polygon in this example does what you want: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Polygon.html&label=Geometries – Matthew Amato Apr 28 '15 at 23:56
  • I'll add that what we are adding is the ability to drape vector data directly on terrain, i.e. as if it's laying on the ground. Setting perPositionHeight will not cause the polygon to conform to terrain, it will simply raise the heights to the specified heights so that you can have polygons in the air. – Matthew Amato Apr 28 '15 at 23:58
  • Ok, understood - thanks for your insight Matthew. So can you confirm that the `perPositionHeight` could be a valid approach when combined with sampleTerrain.js interpolating the "ground" heights? (effectively rendering the poly "in the air" but at the same height as the terrain elevation). – danwild Apr 29 '15 at 00:18
  • Oops sorry missed your first comment, I'll check it out thanks – danwild Apr 29 '15 at 00:19
  • Hey Matthew - sorry. I changed accepted answer, as the API has obviously changed. Though I I've noticed a few helpful tips of yours sprinkled across the interwebs - so thanks again for your help! – danwild Sep 23 '15 at 04:22