CompositeProperty with ConstantProperty slow to update

Hi,

I've got about 3000 elements (lines and polygons) being displayed in Cesium and each has time interval values associated with it. These are used with a TimeIntervalCollectionProperty to update the colours as time goes by. This seems to work fine.
I am trying to hide all elements that fall outside of a dynamic threshold. Since the value changes over time, I used a TimeIntervalCollectionProperty and then set the data to a ConstantProperty that I set to true or false depending on the filter threshold. This has an enormous lag. It seems that the show attribute is not updated for a few seconds after I set the ConstantProperty value. I have also used a CallbackProperty and this gives very fluid changes in the UI when moving my filter threshold, but the framerate suffers, I assume because it is polling more often.
Can anyone advise on the best approach for doing this?

Thanks

Matthew

Hi,
I’m not sure I explained this too well so I’ve tried to set some examples up in Sandcastle. These have a lot of data in them to try and exaggerate what I’m seeing so they are slow to load.

Each example loads in a lot of regions, sets their colour to change each month and displays some buttons to change the filter, that keeps regions visible.

The first example uses a TimeInterval with a CallbackProperty and this seems smooth enough but surely it is querying the CallbackProperty a lot of times, which won’t be efficient.

HTML Body (button added):

@import url(../templates/bucket.css);

Loading...

``

Javascript:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

// Lock clock to 2016

viewer.clock.currentTime = Cesium.JulianDate.fromIso8601(“2016-01-01”);

viewer.clock.startTime = Cesium.JulianDate.fromIso8601(“2016-01-01”);

viewer.clock.stopTime = Cesium.JulianDate.fromIso8601(“2016-12-31”);

viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;

viewer.timeline.updateFromClock();

viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime);

// Load regions

var datasource = new Cesium.GeoJsonDataSource(“Regions”);

var topojson = datasource.load(“https://raw.githubusercontent.com/martinjc/UK-GeoJSON/master/json/electoral/eng/topo_wards.json”, {

stroke: Cesium.Color.WHITE

});

var gradientValue = function(value) {

var red = 255;

var green = 255;

if(value < 0.5) {

// 255,0,0>255,255,0

var gRatio = value * 2;

green = 255 * gRatio;

} else {

// 255,255,0>0,255,0

var rRatio = (1.0 - value) * 2;

red = 255 * rRatio;

}

return Cesium.Color.fromBytes(red, green, 0, 128);

};

var filter = 1;

// Add temporal values to entities

topojson.then(function(datasource) {

viewer.dataSources.add(datasource).then(function(datasource) {

datasource.entities.values.forEach(function(entity) {

var values = [

[‘2016-01-01T00:00:00.00Z/2016-02-01T00:00:00.00Z’, Math.random()],

[‘2016-02-01T00:00:00.00Z/2016-03-01T00:00:00.00Z’, Math.random()],

[‘2016-03-01T00:00:00.00Z/2016-04-01T00:00:00.00Z’, Math.random()],

[‘2016-04-01T00:00:00.00Z/2016-05-01T00:00:00.00Z’, Math.random()],

[‘2016-05-01T00:00:00.00Z/2016-06-01T00:00:00.00Z’, Math.random()],

[‘2016-06-01T00:00:00.00Z/2016-07-01T00:00:00.00Z’, Math.random()],

[‘2016-07-01T00:00:00.00Z/2016-08-01T00:00:00.00Z’, Math.random()],

[‘2016-08-01T00:00:00.00Z/2016-09-01T00:00:00.00Z’, Math.random()],

[‘2016-09-01T00:00:00.00Z/2016-10-01T00:00:00.00Z’, Math.random()],

[‘2016-10-01T00:00:00.00Z/2016-11-01T00:00:00.00Z’, Math.random()],

[‘2016-11-01T00:00:00.00Z/2016-12-01T00:00:00.00Z’, Math.random()],

[‘2016-12-01T00:00:00.00Z/2017-01-01T00:00:00.00Z’, Math.random()]

];

var colourProperty = new Cesium.TimeIntervalCollectionProperty();

var showProperty = new Cesium.CompositeProperty();

values.forEach(function(entry) {

colourProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({

iso8601: entry[0],

isStartIncluded: true,

isStopIncluded: false,

data: gradientValue(entry[1])

}));

showProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({

iso8601: entry[0],

isStartIncluded: true,

isStopIncluded: false,

data: new Cesium.CallbackProperty(function() {

return entry[1] <= filter;

}, false)

}));

});

entity.polygon.material = new Cesium.ColorMaterialProperty(colourProperty);

entity.polygon.outlineColor = colourProperty;

entity.polygon.show = showProperty;

});

});

});

var setx = function(x) {

return function() {

console.log(x);

filter = x / 100;

};

};

var i;

for(i = 0; i !== 110; i += 10) {

var myButton = document.createElement(“input”);

myButton.type = “button”;

myButton.value = i + “%”;

myButton.onclick = setx(i);

document.getElementById(“button”).appendChild(myButton);

}

``

The second example uses a TimeInterval with a ConstantProperty and while this works when going through the timeline, clicking a button to change the filter takes a really long time before it has any effect. I expected this approach to be more efficient because there wouldn’t be a change to the data unless setValue() is called but it seems much less efficient. My guess would be that the setValue() event takes time to propagate up through the TimeIntervals but I didn’t think it would be how it is.

HTML Body (button added):

@import url(../templates/bucket.css);

Loading...

``

Javascript:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

// Lock clock to 2016

viewer.clock.currentTime = Cesium.JulianDate.fromIso8601(“2016-01-01”);

viewer.clock.startTime = Cesium.JulianDate.fromIso8601(“2016-01-01”);

viewer.clock.stopTime = Cesium.JulianDate.fromIso8601(“2016-12-31”);

viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;

viewer.timeline.updateFromClock();

viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime);

// Load regions

var datasource = new Cesium.GeoJsonDataSource(“Regions”);

var topojson = datasource.load(“https://raw.githubusercontent.com/martinjc/UK-GeoJSON/master/json/electoral/eng/topo_wards.json”, {

stroke: Cesium.Color.WHITE

});

var gradientValue = function(value) {

var red = 255;

var green = 255;

if(value < 0.5) {

// 255,0,0>255,255,0

var gRatio = value * 2;

green = 255 * gRatio;

} else {

// 255,255,0>0,255,0

var rRatio = (1.0 - value) * 2;

red = 255 * rRatio;

}

return Cesium.Color.fromBytes(red, green, 0, 128);

};

var filterCallbacks = {};

var createShowData = function(value) {

var boundedValue = Math.floor(value * 100);

if(boundedValue in filterCallbacks) {

return filterCallbacks[boundedValue];

} else {

var newCallback = new Cesium.ConstantProperty(true);

filterCallbacks[boundedValue] = newCallback;

return newCallback;

}

};

// Add temporal values to entities

topojson.then(function(datasource) {

viewer.dataSources.add(datasource).then(function(datasource) {

datasource.entities.values.forEach(function(entity) {

var values = [

[‘2016-01-01T00:00:00.00Z/2016-02-01T00:00:00.00Z’, Math.random()],

[‘2016-02-01T00:00:00.00Z/2016-03-01T00:00:00.00Z’, Math.random()],

[‘2016-03-01T00:00:00.00Z/2016-04-01T00:00:00.00Z’, Math.random()],

[‘2016-04-01T00:00:00.00Z/2016-05-01T00:00:00.00Z’, Math.random()],

[‘2016-05-01T00:00:00.00Z/2016-06-01T00:00:00.00Z’, Math.random()],

[‘2016-06-01T00:00:00.00Z/2016-07-01T00:00:00.00Z’, Math.random()],

[‘2016-07-01T00:00:00.00Z/2016-08-01T00:00:00.00Z’, Math.random()],

[‘2016-08-01T00:00:00.00Z/2016-09-01T00:00:00.00Z’, Math.random()],

[‘2016-09-01T00:00:00.00Z/2016-10-01T00:00:00.00Z’, Math.random()],

[‘2016-10-01T00:00:00.00Z/2016-11-01T00:00:00.00Z’, Math.random()],

[‘2016-11-01T00:00:00.00Z/2016-12-01T00:00:00.00Z’, Math.random()],

[‘2016-12-01T00:00:00.00Z/2017-01-01T00:00:00.00Z’, Math.random()]

];

var colourProperty = new Cesium.TimeIntervalCollectionProperty();

var showProperty = new Cesium.CompositeProperty();

values.forEach(function(entry) {

colourProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({

iso8601: entry[0],

isStartIncluded: true,

isStopIncluded: false,

data: gradientValue(entry[1])

}));

showProperty.intervals.addInterval(Cesium.TimeInterval.fromIso8601({

iso8601: entry[0],

isStartIncluded: true,

isStopIncluded: false,

data: createShowData(entry[1])

}));

});

entity.polygon.material = new Cesium.ColorMaterialProperty(colourProperty);

entity.polygon.outlineColor = colourProperty;

entity.polygon.show = showProperty;

});

});

});

var setx = function(x) {

return function() {

console.log(x);

Object.keys(filterCallbacks).forEach(function(key) {

filterCallbacks[key].setValue(x >= key);

});

};

};

var i;

for(i = 0; i <= 100; i += 10) {

var myButton = document.createElement(“input”);

myButton.type = “button”;

myButton.value = i + “%”;

myButton.onclick = setx(i);

document.getElementById(“button”).appendChild(myButton);

}

``

So I guess my question is… is that expected behaviour from the ComponentProperty, and is there a better way I can get the same sort of effect?

Matthew

Thanks for the great code examples! It’s definitely helpful seeing exactly what you are trying to do.
I don’t know the best answer, but I’m going to ask around and I’ll get back to you soon.

What kind of application are you working on? Your dataset looks really interesting.

-Hannah

Just a demo of Cesium to show how it can do things that have been done in other tools. The dataset is just an example of regional areas that I found.
We want to make big data dashboards that intuitively present data and allow people to navigate it and drill into it. Some of that data will include mapping. I like a Cesium/HTML5/WEBGL so I’m pushing to use it by setting up a demo.

Hi Matthew,

I recall a similar issue regarding inefficient updates of the show
attribute, which was due to geometries of all polylines having to be
regenerated whenever the show-state (or material) changed... this seems
to be due to the generic GeometryVisualizer being used, which
batches geometries in a very coarse-grained manner.

I may be able to contribute some code for a more fine-grained PolylineVisualizer, will have to let my client greenlight this first
though.

cheers,

  Manuel

Hello,

The application that I’m working on isn’t using the Entity API directly – a CZML data stream is the data provider. There was a big increase in performance with sending a delete czml rather than toggling the ‘show’ attribute.

{ id=, “delete”:true }

Matthew – With a more fine-grained PolylineVisualizer, would that impact performance (i.e. slower rendering)?

Thank you.

entity.polygon.material = new Cesium.ColorMaterialProperty(colourProperty);

In this statement, an error occured while rendering.

TypeError: Cannot read property ‘red’ of undefined

please help me. T.T

Can you post a code example for what you are trying to accomplish?

-Hannah

Have you checked out what the 'colourProperty' is, or maybe it's the wrong name of variable?