Polyline At Height

If I have billboards loaded at a certain height above the terrain, how can I then draw a polyline using the same positions as the billboards based on the following? When I use the positions from the billboards, the polyline ends up much higher than the billboards.

var terrainModels = Cesium.createDefaultTerrainProviderViewModels();
var viewer = new Cesium.Viewer('cesiumContainer', {
    selectedTerrainProviderViewModel: terrainModels[1],
    timeline: false,
    navigationHelpButton: false,
    baseLayerPicker: true,
    animation: false,
    fullscreenButton: false,
    scene3DOnly: true
});

var pb = new Cesium.PinBuilder();
var PB_SIZE = 40;
var pbName = "BB 1";
var pbColor = Cesium.Color.BLUE;

var myPositions = [[-86.361, 36.3981, 7.62],
                   [-86.3613, 36.398, 7.62],
                   [-86.3615, 36.3979, 7.62]];

var bbs = viewer.scene.primitives.add(
    new Cesium.BillboardCollection({
        scene: viewer.scene
    })
);

bbs.add({
    id: pbName,
    position: Cesium.Cartesian3.fromDegrees(myPositions[0][0], myPositions[0][1], myPositions[0][2]),
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    image: pb.fromText(pbName, pbColor, PB_SIZE).toDataURL()
});

pbName = "BB 2";
bbs.add({
    id: pbName,
    position: Cesium.Cartesian3.fromDegrees(myPositions[1][0], myPositions[1][1], myPositions[1][2]),
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    image: pb.fromText(pbName, pbColor, PB_SIZE).toDataURL()
});

pbName = "BB 3";
bbs.add({
    id: pbName,
    position: Cesium.Cartesian3.fromDegrees(myPositions[2][0], myPositions[2][1], myPositions[2][2]),
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    image: pb.fromText(pbName, pbColor, PB_SIZE).toDataURL()
});

Hello,

Polylines aren’t aware of the terrain height, so their heights are all relative to the WGS84 ellipsoid. I think that’s where your error is coming from.

Until we have better support for polylines on terrain, this is the best work around:

Query the terrain for the positions using Cesium.sampleTerrain (this demo will show you how to use the sampleTerrain function: http://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Terrain.html&label=Showcases)

Once sampleTerrain has computed the positions, add the relative height to each position and use those positions to create the polyline

Let me know if this is unclear and I can whip up a quick example.

Best,

Hannah

I tried the following but I'm still misunderstanding something.

var terrainModels = Cesium.createDefaultTerrainProviderViewModels();
var viewer = new Cesium.Viewer('cesiumContainer', {
    selectedTerrainProviderViewModel: terrainModels[1],
    timeline: false,
    navigationHelpButton: false,
    baseLayerPicker: true,
    animation: false,
    fullscreenButton: false,
    scene3DOnly: true
});

var pb = new Cesium.PinBuilder();
var PB_SIZE = 40;
var pbName = "BB 1";
var pbColor = Cesium.Color.BLUE;

var myPositions = [[-86.361, 36.3981, 7.62],
                   [-86.3613, 36.398, 7.62],
                   [-86.3615, 36.3979, 7.62]];

var bbs = viewer.scene.primitives.add(
    new Cesium.BillboardCollection({
        scene: viewer.scene
    })
);

bbs.add({
    id: pbName,
    position: Cesium.Cartesian3.fromDegrees(myPositions[0][0], myPositions[0][1], myPositions[0][2]),
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    image: pb.fromText(pbName, pbColor, PB_SIZE).toDataURL()
});

pbName = "BB 2";
bbs.add({
    id: pbName,
    position: Cesium.Cartesian3.fromDegrees(myPositions[1][0], myPositions[1][1], myPositions[1][2]),
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    image: pb.fromText(pbName, pbColor, PB_SIZE).toDataURL()
});

pbName = "BB 3";
bbs.add({
    id: pbName,
    position: Cesium.Cartesian3.fromDegrees(myPositions[2][0], myPositions[2][1], myPositions[2][2]),
    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
    heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
    image: pb.fromText(pbName, pbColor, PB_SIZE).toDataURL()
});

var ellipsoidProvider = new Cesium.EllipsoidTerrainProvider();
var coordsToRads = ;
for (var startIdx = 0; startIdx < myPositions.length; startIdx++)
{
    // converting degrees to radians
    coordsToRads.push(Cesium.Cartographic.fromDegrees(myPositions[startIdx][0],
                                                      myPositions[startIdx][1],
                                                      myPositions[startIdx][2]));

}

Cesium.sampleTerrain(ellipsoidProvider, 9, coordsToRads).then(function() {
    for (var i = 0; i < coordsToRads.length; i++)
    {
        console.log("before coordsToRads[" + i + "].height = " + coordsToRads[i].height);
        coordsToRads[i].height = myPositions[i][2];
        console.log("after coordsToRads[" + i + "].height = " + coordsToRads[i].height);
    }
    var tmpPolyline = viewer.entities.add({
        polyline: {
            material: Cesium.Color.DEEPPINK,
            width: 10,
            positions: Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(coordsToRads)
        }
    });
});

Correction:

    coordsToRads[i].height = myPositions[i][2];

should be:
     coordsToRads[i].height += myPositions[i][2];