Air path of a plane and its ground projection

Hi,
I’m trying to get more familiar with Cesium and I met an issue that I unfortunately cannot interpret. The code below is intended to test a simple example when one can track a groud projection of an air path of a plane. In fact, the code execution demonstrates that the plane path and the groud path are not synchronized as expected. The plane path lacks behind the ground path. In the end, the plane starts blinking and disappears from the screen. Could you please help me to understand what implementation of such scenarion by Cesium should demonstrate the correct behavior?

Thanks,

Oleg

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

scene3DOnly : true,

shadows : true,

timeline: false,

terrainShadows : Cesium.ShadowMode.ENABLED

});

var terrainProvider = new Cesium.CesiumTerrainProvider({

url : ‘https://assets.agi.com/stk-terrain/world

});

viewer.terrainProvider = terrainProvider;

//---------------------- Start position of the plane ---------------------------

var startLongitude = 30, startLatitude = 20;

viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(startLongitude, startLatitude, 900)});

//------------ Array of (time, position) samples along the plane route ---------

var airPathArray = ;

//------------ Array of the points of the ground path under the plane ----------

var groundPathArray = ;

//----------- Every 1 second a new point on the plane route is created ---------

var pathHandler = setInterval(function(){

var timeNow = new Cesium.JulianDate.now();

//timeNow = Cesium.JulianDate.addSeconds(timeNow, 2, new Cesium.JulianDate());

// At start it takes initial coordinates

if(airPathArray.length == 0){

airPathArray.push({time: timeNow, degrees: {longitude: startLongitude, latitude: startLatitude},

position: new Cesium.Cartesian3.fromDegrees(startLongitude, startLatitude, 600)});

groundPathArray.push(startLongitude);

groundPathArray.push(startLatitude);

}

// New next point coordinates are randomly taken

else{

var lon = airPathArray[airPathArray.length - 1].degrees.longitude + 0.0005 * (1 - Math.random());

var lat = airPathArray[airPathArray.length - 1].degrees.latitude + 0.0005 * (1 - Math.random());

airPathArray.push({time: timeNow, degrees: {longitude: lon, latitude: lat}, position: new Cesium.Cartesian3.fromDegrees(lon, lat, 600)});

groundPathArray.push(lon, lat);

}

// The maximum number of the route points is fixed

if(airPathArray.length > 15){

airPathArray.shift();

groundPathArray.shift();

groundPathArray.shift();

}

// The updated route is ready for visualization

viewRoute();

}, 1000);

// Route visualization

function viewRoute() {

var trace = new Cesium.SampledPositionProperty();

for(var i = 0; i < airPathArray.length; i++)

trace.addSample(airPathArray[i].time, airPathArray[i].position);

plane.position = trace;

plane.position.setInterpolationOptions({

interpolationDegree : 1,

interpolationAlgorithm : Cesium.LinearApproximation

});

plane.orientation = new Cesium.VelocityOrientationProperty(trace);

goroundPath.corridor.positions = new Cesium.Cartesian3.fromDegreesArray(groundPathArray);

}

//--------------------------- CREATE A PLANE ENTITY ----------------------------

var plane = viewer.entities.add({

model : {

uri : ‘…/Apps/SampleData/models/CesiumAir/Cesium_Air.gltf’,

minimumPixelSize : 8,

color : Cesium.Color.WHITE

},

path : {

show : true,

leadTime : 0,

trailTime : 15,

width : 2,

resolution : 1,

material : new Cesium.PolylineGlowMaterialProperty({

glowPower : 0.25,

color : Cesium.Color.PALEGOLDENROD

})

},

});

//------------------------ CREATE A GROUND PATH ENTITY -------------------------

var goroundPath = viewer.entities.add({

corridor : {

width : 50.0,

material : Cesium.Color.BLUE.withAlpha(0.5)

}

});

Hi Oleg,

You’re right, the flickering is caused by a synchronicity problem – the render calls are not synced with your update function. The code below, which attaches a callback to the positions property of your corridor positions will be called whenever the positions are accessed, which should fix the flicker.

var viewer = new Cesium.Viewer(‘cesiumContainer’, {
scene3DOnly : true,
shadows : true,
timeline: false,
terrainShadows : Cesium.ShadowMode.ENABLED
});
var terrainProvider = new Cesium.CesiumTerrainProvider({
url : ‘https://assets.agi.com/stk-terrain/world
});
viewer.terrainProvider = terrainProvider;

//---------------------- Start position of the plane ---------------------------
var startLongitude = 30, startLatitude = 20;
viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(startLongitude, startLatitude, 900)});

//------------ Array of (time, position) samples along the plane route ---------
var airPathArray = ;
//------------ Array of the points of the ground path under the plane ----------
var groundPathArray = ;

//------------ Initialize arrays ----------
var timeNow = new Cesium.JulianDate.now();
airPathArray.push({time: timeNow, degrees: {longitude: startLongitude, latitude: startLatitude},
position: new Cesium.Cartesian3.fromDegrees(startLongitude, startLatitude, 600)});
groundPathArray.push(startLongitude);
groundPathArray.push(startLatitude);

//----------- Every 1 second a new point on the plane route is created ---------
var pathHandler = setInterval(function(){
var timeNow = new Cesium.JulianDate.now();
//timeNow = Cesium.JulianDate.addSeconds(timeNow, 2, new Cesium.JulianDate());
// At start it takes initial coordinates

// New next point coordinates are randomly taken
var lon = airPathArray[airPathArray.length - 1].degrees.longitude + 0.0005 * (1 - Math.random());
var lat = airPathArray[airPathArray.length - 1].degrees.latitude + 0.0005 * (1 - Math.random());
airPathArray.push({time: timeNow, degrees: {longitude: lon, latitude: lat}, position: new Cesium.Cartesian3.fromDegrees(lon, lat, 600)});
groundPathArray.push(lon, lat);
// The maximum number of the route points is fixed
if(airPathArray.length > 15){
airPathArray.shift();
groundPathArray.shift();
groundPathArray.shift();
}
// The updated route is ready for visualization
viewRoute();
}, 1000);

// Route visualization
function viewRoute() {
var trace = new Cesium.SampledPositionProperty();
for(var i = 0; i < airPathArray.length; i++)
trace.addSample(airPathArray[i].time, airPathArray[i].position);
plane.position = trace;
plane.position.setInterpolationOptions({
interpolationDegree : 1,
interpolationAlgorithm : Cesium.LinearApproximation
});
plane.orientation = new Cesium.VelocityOrientationProperty(trace);
}

//--------------------------- CREATE A PLANE ENTITY ----------------------------
var plane = viewer.entities.add({
model : {
uri : ‘…/Apps/SampleData/models/CesiumAir/Cesium_Air.gltf’,
minimumPixelSize : 8,
color : Cesium.Color.WHITE
},
path : {
show : true,
leadTime : 0,
trailTime : 15,
width : 2,
resolution : 1,
material : new Cesium.PolylineGlowMaterialProperty({
glowPower : 0.25,
color : Cesium.Color.PALEGOLDENROD
})
},
});

//------------------------ CREATE A GROUND PATH ENTITY -------------------------

function updatePositions() {
var positions = new Cesium.Cartesian3.fromDegreesArray(groundPathArray);
return positions;
}

var goroundPath = viewer.entities.add({
corridor : {
width : 50.0,
material : Cesium.Color.BLUE.withAlpha(0.5),
positions: new Cesium.CallbackProperty(updatePositions, false)
}
});

``

Hope that helps!

  • Rachel

Hi,
I’m trying to get more familiar with Cesium and I met an issue that I unfortunately cannot interpret. The code below is intended to test a simple example when one can track a groud projection of an air path of a plane. In fact, the code execution demonstrates that the plane path and the groud path are not synchronized as expected. The plane path lacks behind the ground path. In the end, the plane starts blinking and disappears from the screen. Could you please help me to understand what implementation of such scenarion by Cesium should demonstrate the correct behavior?
Thanks,
Oleg

var viewer = new Cesium.Viewer(‘cesiumContainer’, {
scene3DOnly : true,
shadows : true,
timeline: false,
terrainShadows : Cesium.ShadowMode.ENABLED
});
var terrainProvider = new Cesium.CesiumTerrainProvider({
url : ‘https://assets.agi.com/stk-terrain/world
});
viewer.terrainProvider = terrainProvider;

//---------------------- Start position of the plane ---------------------------
var startLongitude = 30, startLatitude = 20;
viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(startLongitude, startLatitude, 900)});

//------------ Array of (time, position) samples along the plane route ---------
var airPathArray = ;
//------------ Array of the points of the ground path under the plane ----------
var groundPathArray = ;

//----------- Every 1 second a new point on the plane route is created ---------
var pathHandler = setInterval(function(){
var timeNow = new Cesium.JulianDate.now();
//timeNow = Cesium.JulianDate.addSeconds(timeNow, 2, new Cesium.JulianDate());
// At start it takes initial coordinates
if(airPathArray.length == 0){
airPathArray.push({time: timeNow, degrees: {longitude: startLongitude, latitude: startLatitude},
position: new Cesium.Cartesian3.fromDegrees(startLongitude, startLatitude, 600)});
groundPathArray.push(startLongitude);
groundPathArray.push(startLatitude);
}
// New next point coordinates are randomly taken
else{
var lon = airPathArray[airPathArray.length - 1].degrees.longitude + 0.0005 * (1 - Math.random());
var lat = airPathArray[airPathArray.length - 1].degrees.latitude + 0.0005 * (1 - Math.random());
airPathArray.push({time: timeNow, degrees: {longitude: lon, latitude: lat}, position: new Cesium.Cartesian3.fromDegrees(lon, lat, 600)});
groundPathArray.push(lon, lat);
}
// The maximum number of the route points is fixed
if(airPathArray.length > 15){
airPathArray.shift();
groundPathArray.shift();
groundPathArray.shift();
}
// The updated route is ready for visualization
viewRoute();
}, 1000);

// Route visualization
function viewRoute() {
var trace = new Cesium.SampledPositionProperty();
for(var i = 0; i < airPathArray.length; i++)
trace.addSample(airPathArray[i].time, airPathArray[i].position);
plane.position = trace;
plane.position.setInterpolationOptions({
interpolationDegree : 1,
interpolationAlgorithm : Cesium.LinearApproximation
});
plane.orientation = new Cesium.VelocityOrientationProperty(trace);
goroundPath.corridor.positions = new Cesium.Cartesian3.fromDegreesArray(groundPathArray);
}

//--------------------------- CREATE A PLANE ENTITY ----------------------------
var plane = viewer.entities.add({
model : {
uri : ‘…/Apps/SampleData/models/CesiumAir/Cesium_Air.gltf’,
minimumPixelSize : 8,
color : Cesium.Color.WHITE
},
path : {
show : true,
leadTime : 0,
trailTime : 15,
width : 2,
resolution : 1,
material : new Cesium.PolylineGlowMaterialProperty({
glowPower : 0.25,
color : Cesium.Color.PALEGOLDENROD
})
},
});

//------------------------ CREATE A GROUND PATH ENTITY -------------------------
var goroundPath = viewer.entities.add({
corridor : {
width : 50.0,
material : Cesium.Color.BLUE.withAlpha(0.5)
}
});

For more info on Callback properties, see the docs here: https://cesiumjs.org/Cesium/Build/Documentation/CallbackProperty.html

Hi Rachel,
Thank you for the suggestion! It solves the problem, indeed.

Kind regards,

Oleg