1. A concise explanation of the problem you're experiencing.
I am attempting to show a sensor's swathe as a UAV flies. The swathe for the UAV's flight is fully computed with points corresponding to a specific JulianDate and I would like the polygon showing the swathe to update every so often when the UAV hits the next point in the coordinate/JulianDate pair (start with showing no swathe and then update the polygon to show up-to-date what the sensor has seen).
My question pertains to understanding the relationship between Entities and how they correspond to Primitives. I have achieved my goal using entities and updating the polygon's hierarchy through a CallbackProperty. However, this would create a "blinking" effect as the polygon (swathe) was updated. This led me to look into Primitives and its asynchronous characteristic. I have read that setting asynchronous to false rids the blinking/flickering effect. So I switched over to using Primitives. However, I have run into issues with removing the primitive and adding a new one. I find that it the new primitive being added has an undefined geometryInstance.
I would be fine using entities with the callback (I understand using entities is more computationally expensive) if there was no flicker or blinking when it updated the polygon's shape. I would like to know more about how to control primitives, update the shape of them (e.g. PolygonGeometryUpdater), their performance, and the pros and cons in comparison to using Entities (entities seem much more versatile).
2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.
Below is a link to a jsfiddle. Might be easier to look through the code in there.
https://jsfiddle.net/parsonsbrett0/k018zbgy/2/
Using Entities:
// the original add of the empty swathe
viewer.entities.add({
id: result.objectsWithinCzml.id,
name: result.objectsWithinCzml.name + 'swathe',
polygon: {
hierarchy: new Cesium.CallbackProperty(callbackSwathe, false),
material: Cesium.Color.GREEN.withAlpha(0.5),
height: 0,
outline: true // height is required for outline to display
}
});
// update the callback to allow a non static return
function onSimulationClockChange() {
// run every 60 seconds of simulation
var currentTime = viewer.clock.currentTime;
for (var i = 0; i < vehicles.length; i++) {
if (vehicles[i].swathe !== null) {
if (Cesium.JulianDate.compare(currentTime, Cesium.JulianDate.fromDate(moment(vehicles[i].swathe.item1[vehicles[i].swathe.item1.length - 1]).toDate())) <= 0 && viewer.entities.getById(vehicles[i].id).polygon.hierarchy.isConstant) {
viewer.entities.getById(vehicles[i].id).polygon.hierarchy.setCallback(callbackSwathe, false);
clockChange = currentTime;
}
}
}
}
// callback to update the swathe to the current time and also update the callback to keep the final swathe shown if the current time is after the flight end time
function callbackSwathe() {
//alert('this is it');
// run every 60 seconds of simulation
var currentTime = viewer.clock.currentTime;
var swathe = vehicles.find(x => x.id === this.id).swathe;
var fullSwathe;
var currentSwathe;
var timeDifference = Cesium.JulianDate.secondsDifference(currentTime, clockChange);
if (timeDifference >= parseFloat($('#StepTime').val()) || timeDifference < 0) {
clockChange = currentTime;
if (Cesium.JulianDate.compare(currentTime, Cesium.JulianDate.fromDate(moment(swathe.item1[swathe.item1.length - 1]).toDate())) <= 0) {
// get the vehicle's full swathe
fullSwathe = Cesium.Cartesian3.unpackArray(swathe.item2);
// get the date to show up to;
var dateToIndex = binarySearchSwatheTime(swathe.item1, currentTime); // just returns an index
// get the vehicle's to date swathe
currentSwathe = new Cesium.PolygonHierarchy(fullSwathe.slice(0, dateToIndex + 1).concat(fullSwathe.slice(fullSwathe.length - dateToIndex - 1)));
return currentSwathe;
} else {
if (!this.isConstant) {
this.setCallback(callbackSwathe, true);
fullSwathe = Cesium.Cartesian3.unpackArray(swathe.item2);
return new Cesium.PolygonHierarchy(fullSwathe);
}
}
}
}
Using Primitives:
// the original add of the empty swathe
var instance = new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy()
}),
id: result.objectsWithinCzml.id,
attributes: {
color: new Cesium.ColorGeometryInstanceAttribute(0.0, 0.5, 0, 0.5)
}
});
viewer.scene.primitives.add(new Cesium.GroundPrimitive({
geometryInstances: instance,
appearance: new Cesium.PerInstanceColorAppearance(),
asynchronous: false
}));
function onSimClockChange() {
// run every 60 seconds of simulation
var currentTime = viewer.clock.currentTime;
var timeDifference = Cesium.JulianDate.secondsDifference(currentTime, clockChange);
if (timeDifference >= parseFloat($('#StepTime').val()) || timeDifference < 0) {
clockChange = currentTime;
for (var i = 0; i < vehicles.length; i++) {
if (vehicles[i].swathe !== null) {
if (Cesium.JulianDate.compare(currentTime, Cesium.JulianDate.fromDate(moment(vehicles[i].swathe.item1[vehicles[i].swathe.item1.length - 1]).toDate())) <= 0) {
// assign to the geometry now.
var primitives = viewer.scene.primitives;
for (var j = 0; j < primitives.length; j++) {
var currentPrimitive = primitives.get(j);
if (currentPrimitive.hasOwnProperty('geometryInstances')) {
if (currentPrimitive.geometryInstances.id === vehicles[i].id) {
var fullSwathe = Cesium.Cartesian3.unpackArray(vehicles[i].swathe.item2);
// get the date to show up to;
var dateToIndex = binarySearchSwatheTime(vehicles[i].swathe.item1, currentTime);
primitives.remove(currentPrimitive);
viewer.scene.primitives.add(new Cesium.GroundPrimitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(fullSwathe.slice(0, dateToIndex + 1).concat(fullSwathe.slice(fullSwathe.length - dateToIndex - 1)))
}),
id: vehicles[i].id,
attributes: {
color: new Cesium.ColorGeometryInstanceAttribute(0.0, 0.5, 0, 0.5)
}
}),
appearance: new Cesium.PerInstanceColorAppearance(),
asynchronous: false
}));
break;
}
}
}
}
}
}
}
}
3. Context. Why do you need to do this? We might know a better way to accomplish your goal.
I am trying to update a polygon's points dynamically and without a flicker when updating.
4. The Cesium version you're using, your operating system and browser.
"cesium": "^1.52.0"
Windows 10 Pro Version 1809 OS build 17763.292
Google Chrome Version 71.0.3578.98