Search code examples
javascriptcanvascesiumjs

Trim interpolated polyline where terrain is intersecting in Cesium


I'm trying to create an arc which will stop when it intersects terrain. Two variables arc1 and arc2 where arc1 is without terrain intersection and arc2 is with terrain intersection.

arc1 is working properly but arc2 is not stopping where it intersects the terrain.

var viewer = new Cesium.Viewer("cesiumContainer", {
  infoBox: false, //Disable InfoBox widget
  selectionIndicator: false, //Disable selection indicator
  shouldAnimate: true, // Enable animations
  terrainProvider: Cesium.createWorldTerrain(),
});

//Enable lighting based on the sun position
viewer.scene.globe.enableLighting = true;

//Enable depth testing so things behind the terrain disappear.
viewer.scene.globe.depthTestAgainstTerrain = true;

// Cartesian3: start, mid and end points for polyline
var controls = [{x:-1942111.383043348,y:-4780646.881480431,z:3737538.9114379627},
                {x:-1847333.0834675943,y:-5281519.814050422,z:3579120.5547780637},
                {x:-1611854.2607850158,y:-5380130.367796415,z:3146339.4631628506}];


// Applying interpolation
var spline = Cesium.HermiteSpline.createNaturalCubic({
        times: [0.0, 0.5, 1],
        points: controls,
    });

var ppos = []; //Interpolated polyline cordinates
for (var i = 0; i <= 50; i++) {
    var cartesian3 = spline.evaluate(i / 50);
    ppos.push(cartesian3);
}

/* Terrain and Polyline Intersection Detection */
var cartographic = [];
var cartographic_real = [];
ppos.forEach(p => {
    let dh = Cesium.Cartographic.fromCartesian(p);
    dh.height = 0;
    cartographic.push(dh);
    cartographic_real.push(Cesium.Cartographic.fromCartesian(p));
});

// collecting actual terrain heights
Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, cartographic).then((raisedPositionsCartograhpic) => {
    var t = true;
    var rpos = []; // 
    cartographic_real.forEach((p, i) => {
        if(t) rpos.push(ppos[i]);
        // If terrain height is more than polyline cordinate height
        if (i > 0 && t && (raisedPositionsCartograhpic[i].height - p.height)) {
          t = false;
          
          console.log("Stopped at:", p.height);
          console.log(rpos);
          drawNewArc(rpos);

        }
    });
});

/* --- */

function drawNewArc(rpos)
{
  var arc1 = {};
  arc1.polyline = { // Actual line without terrain intersection
          positions: ppos,
          width: 3,
          material: Cesium.Color.RED.withAlpha(0.5),
      }
  
  var arc2 = {};
  arc2.polyline = { // This should stop where it intersects terrain
          positions: rpos,
          width: 3,
          material: Cesium.Color.GREEN.withAlpha(1.0),
      }
  
  var entity = viewer.entities.add(arc1);
  var entity2 = viewer.entities.add(arc2);
}

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(-112.081,36.097,10000)});

I want the Green polyline to stop when it hits any terrain.

example

I think I need to get and match all the points of the arc. I don't know how to get all the points of the Green arc.

Here is the complete code link in sandcastle:


Solution

  • Got Success after repairing various mistakes in the code like:

    Polyline segmentation was incorrect:

    for (var i = 0; i <= 50; i++) {
    

    Height matching condition was not correct:

    if (i > 0 && t && (raisedPositionsCartograhpic[i].height - p.height)) {
    

    Here is the complete working code link . It can also have mistakes and there must be a better solution to achieve the objective. If someone has any better and fast solution, please kindly post here.