Dynamically growing with time path entity

Hello,

I’m new to Cesium and need to display a path (polyline) (showing a model or billboard time-bound to it) which gets added new points to it as time passes (the polyline is a trajectory which keeps dynamically growing when new positions are available as time passes).

I made a test in the SandCastle.

To reproduce it please open the ‘Interpolation demo’ (needed to have the 3D model available in the SandCastle itself) found at

then replace the code with mine (running on Cesium 1.47, chrome Version 67.0.3396.99 (Official Build) (64-bit) and Windows 7 64bit):

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

scene3DOnly: true,

selectionIndicator: false,

baseLayerPicker: false,

creditsDisplay: false

//sceneModePicker: true

});

var startPos = {lat: 42.341456, lon: -7.242144};

var deltaPos = { dlat: 42.341530 - startPos.lat, dlon: -7.241753 - startPos.lon };

var currPos = startPos;

var sampledPosProp = new Cesium.SampledPositionProperty();

var sampledPosPropEnt = null;

var start = null;

var clock = new Cesium.Clock({

startTime : Cesium.JulianDate.fromIso8601(“2013-12-25”),

currentTime : Cesium.JulianDate.fromIso8601(“2013-12-25”),

stopTime : Cesium.JulianDate.fromIso8601(“2013-12-26”),

clockRange : Cesium.ClockRange.LOOP_STOP,

clockStep : Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER

});

var addNewSample = function() {

currPos.lat += deltaPos.dlat;

currPos.lon += deltaPos.dlon;

clock.tick();

var stop = clock.currentTime;

//console.log(stop+’ ‘+currPos.lat+’ '+currPos.lon);

var position = Cesium.Cartesian3.fromDegrees(currPos.lon, currPos.lat, 0.0);

sampledPosProp.addSample(stop,position);

if(start===null){

start = stop.clone();

} else {

let oldSampledPosPropEnt=sampledPosPropEnt;

viewer.timeline.zoomTo(start, stop);

sampledPosPropEnt = viewer.entities.add({

//Set the entity availability to the same interval as the simulation time.

availability : new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({

start : start,

stop : stop

})]),

//Use our computed positions

position : sampledPosProp,

//Automatically compute orientation based on position movement.

orientation : new Cesium.VelocityOrientationProperty(sampledPosProp),

//Load the Cesium plane model to represent the entity

model : {

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

minimumPixelSize : 64

},

//Show the path as a yellow line sampled in 1 second increments.

path : {

resolution : 1,

material : new Cesium.PolylineGlowMaterialProperty({

glowPower : 0.1,

color : Cesium.Color.YELLOW

}),

width : 10

}

});

if(oldSampledPosPropEnt!==null){

viewer.entities.remove(oldSampledPosPropEnt);

}else{

//console.log(‘zooming!’);

//viewer.flyTo(sampledPosPropEnt);

viewer.camera.lookAt(position, new Cesium.Cartesian3(0.0, 0.0, 1000.0));

}

}

};

clock.canAnimate=true;

clock.shouldAnimate=true;

setInterval(addNewSample,2000);

Waiting a couple a seconds after load the trajectory should be visible.

Clicking anywhere on the timeline you should now see the airplane model and changing the timeline cursor position should move it on the simulated trajectory.

This code has 2 major drawbacks:

1 - it has to destroy and recreate the entity so that the new point (added at each new time interval elapsed) is displayed (performance hit)

2 - each time the entity is destroyed and recreated the airplane model is so and that shows up with an unpleasant airplane model flickering.

I wouldn’t like to have to resort to the basic polyline primitive because I should code on my own all the model/polyline display and timeline synch logic which is already existing in the entity used above.

I’d also like to have have the picking feature available later.

Anyway to check if it would be possible I tried the code in

https://groups.google.com/forum/#!msg/cesium-dev/CclK7a5cLmI/gCmd4Km4834J (first Peter Sweeney post)

but not even in this case the polyline gets properly displayed after new points are added to it (it looks like it’s static).

What is the proper way (or alternatives) to accomplish my goal?

TIA for any help or hints.

Hi there,

Welcome to the Cesium community!

You shouldn’t need to create and destroy an entity each time they are updated. Their purpose is they expose properties, like position, color, etc. These properties can be dynamic, like a sampledPositionProperty, which mean you only need to update that property. For more background, take a look at the Visualizing Spatial Data tutorial, in particular the section on the Property System.

I would also take a look at the CallbackProperty, which I think may be more suited to your use case than the sampledPositionProperty.

Also, I would not recommend calling clock.tick() directly. This is an internal function that’s called when the scene updates and renders.

Thanks,

Gabby

HI Gabby,

thanks very much.

in the posted code I update that property (a samplePositionProperty: sampledPosProp) with a new point as it is available.

The problem is that its entity does not show it on the display.

I had to destroy and recreate a new entity using that very same samplePositionProperty contents (after its update with each new point) so that it would be finally shown as that is visible in my code.

Don’t know why but without the tick() method call my clock instance doesn’t get updated as well: it stays at the initial time forever.

The Polyline entity’s positions property looks to be a constant one in fact:

viewer.entities.add({ polyline: }).polyline.positions.isConstant returns true.

That makes me think that’s a constantProperty not meant for further updates (in fact even if the Cartesian3D bound to it contains the last added point, as I checked printing it, it’s not displayed).

May you point me out some code which shows how to add new points to an existing polyline entity so that those new points are then properly displayed on the terrain as they are added without needing to destroy and recreate the entity itself to make it happen?

Thanks so much for your help

Hi all,

in spite of

viewer.entities.add({ polyline: }).polyline.positions.isConstant returning true

adding new points to the polyline.positions property works (they are displayed after addition).

I was doing something wrong before…

So it’s solved (at least for polylines…).

Thanks

To make sure the clock is advancing by default, set the shouldAnimate property to true when creating the viewer:

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

shouldAnimate : true

});

``

Also make sure you specify that the property is not constant when creating the callback property:

polyline : {

// This callback updates positions each frame.

positions : new Cesium.CallbackProperty(function(time, result) {

endLongitude = startLongitude + 0.001 * Cesium.JulianDate.secondsDifference(time, startTime);

return Cesium.Cartesian3.fromDegreesArray([startLongitude, startLatitude, endLongitude, startLatitude], Cesium.Ellipsoid.WGS84, result);

    }, false),

width : 5,

material : Cesium.Color.RED

}

``

The callback property will work for any entity property, so this can apply to other types besides polylines.