Best implementation for dynamic shapes?

Hello, I am currently working an application that is using a Cesium Viewer. I need to be able to display a collection of shapes that will be updated dynamically. I am having trouble understanding the best way to do this.

I currently am using Entities and using CallbackProperties to allow for the updating of shapes.

You can through this into a sandcastle to get an idea of how I am doing this. There is a polygon object that is being used as the basis for the cesiumCallback, and it is getting edited by another piece of code. (simulated with the setTimeout)

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

var polygon = {};

polygon.coordinates = [

{longitude: 0, latitude: 0, altitude: 0},

{longitude: 10, latitude: 10, altitude: 0},

{longitude: 10, latitude: 0, altitude: 0}

];

// converts generic style options to cesium one (aka color -> material)

var polOpts = {};

// function for getting location

polOpts.hierarchy = new Cesium.CallbackProperty(function() {

var hierarchy = ;

for (var i = 0; i < polygon.coordinates.length; i++) {

var coordinate = polygon.coordinates[i];

hierarchy.push(Cesium.Cartesian3.fromDegrees(coordinate.longitude, coordinate.latitude, coordinate.altitude));

}

return hierarchy;

}, false);

viewer.entities.add({polygon: polOpts});

setInterval(function(polygon){

polygon.coordinates[0].longitude–;

}.bind(this, polygon), 1000);

``

The polygon being passed in is a class that generically describes a polygon, so it has an array of coordinates and style options, as well as a render method that calls this method renderPolygon passing in itself.

This method of rendering shapes works for everything I need it to, but it is not very performant. There are two cases for shapes updating, one type of shape will be updated over a long period of time, as a slow rate like once every few seconds. The other is shapes that will will get updated many times, like thousands, in a few seconds, then not change again for a long time, if ever.

I had two ideas for how to fix this.

Idea 1:

Have two methods, a renderDynamicPolygon and a renderStaticPolygon.

The renderDynamicPolygon method would do the above functionality, using the cesiumCallbackProperties. This would be used for shapes that are getting updated many times during the short time they are being updated.

The renderStaticPolygon method would replace the entities properties that are using callbackProperties with constant values, once the updating is done.

This creates a lot of other work to make sure shapes are in the right state, and doesn’t help the shapes that are being updated slowly over a long period of time.

Idea 2:

Similarly to how the primitives work, I tried removing the old entity and adding it again with its updated properties each time its need to be updated, but this resulted in flickering, and unlike primitives, i could not find a async property for entities.

I also tried using primitives. It worked great for polylines, I would simply remove the old one and add a new one with the updated properties. I was also using the async = false to ensure there was no flickering. This issue I ran into here was not all shapes can be created using primitives. (Is this true?)

The other thing I tried was using the geometry instance using the geometry and appearance. After going through the tutorial on the cesium website I was able to render a few shapes, and could update the appearance, but found it close to impossible to figure out how to update the shapes correctly, and also have a very hard time getting them to look correct. Shapes need to have the right shape, a fill color and opacity and a stroke color, opacity and weight. I tried to use the polygonOutlineGeometry, but had not luck.

What would be the best way to implement this? Are one of these options headed the right way or is there some other method of doing this I have not uncovered yet?

Thanks!

Zac

Hello Zac,

Just to make sure I understand what’s going on, why doesn’t a callback property work in all cases? Is it slowing down the system?

Your first proposed solution seems alright to me. I can’t think of the a better solution off the top of my head.

Alternatively, if you wanted to abandon the entities API, you could use the primitive API if you only need Polyline and Polygon types. The primitives should update when you change the positions property, you don’t need to delete and re-add the primitive each time it changes.

Best,

-Hannah

Hello, in 2D or in columbus modes, there is an issue to update a primitive without delete and recreate it. https://groups.google.com/forum/#!searchin/cesium-dev/how$20to$20make$20a$20primitive$20object/cesium-dev/0J2KnPB5v64/QKoxEtxshwsJ

Hi Hannah,
You mention that primitives can be updated instead of delete/re-added. I am also playing around with some rectangles which need to be updateable but found that if I want to set for example the rotation property of the (RectangleGeometry) of my existing primitive, which should be in the geometryInstances array, I find that this array is empty. I found that after the primitive is added to the scene (and visualized), the geometryInstances array is cleared for some reason.

How can we update primitives in this way?

Best,
Lucas

Hi Hannah,

Thanks for the response.

So the issue I am having with the callback property is performance. It seems unnecessary to check these properties many times a second, when they may not change for hours. I would rather the workflow of removing and re-adding a shape when needed so shapes that do not need to be updated are not taking up time.

The shape set I am working with is polyline, freehand line, rectangle, polygon, and circle. Path shapes need to have a color, opacity and width, and closed shapes need a stroke width, color, opacity and fill color and opacity. From what I have read in the Cesium documentation, this seems hard to support with primitives.

I was un aware that the polygon class you linked is a primitive. How can you tell this from the API? Are there primitives for these other shape types?

Zac

Hello Lucas,

The RectangleGeometry is part of the Geometry and Appearances API, which is lower level than the Primitive API. You will have to delete and re-add a RectangleGeometry in order to get it to update.

The Primitive API is really old and will eventually be replaced with the Entity API. It only contains methods for drawing polylines, polygons, points, billboards and labels.

We recommend using the Entity API wherever possible.

-Hannah

Hi Zac,

Based on what you described, it sounds like your best bet is sticking with what you are doing with the Entity API. I don’t think you would need two different methods for creating each entity, you can just change the positions property between a CallbackProperty and an array of static values as needed. Like I said to Lucas above, the Primitive API is really really old and it doesn’t include all of the primitive types you need. The Entity API will completely replace it once we have all of the features worked out.

I hope this helps! If anything is unclear, I’d be happy to answer any more questions you have.

Best,

Hannah

Hannah,

It is very helpful to know that the primitive api is getting outdated and that the entity api is the right way to go.

While its not ideal I can do the replacing of callbackProperties with constants when needed. This will take care one of my cases. This is the case where I am implementing drawing shapes, so they can use callbackProperties during the drawing process then I can replace the properties with constants once this process is finished.

I have another case that this might not work well for. I have Rectangle on the globe showing a field of view, and this could be being updated for a long time period at a rate of 20 times a second to once every few seconds. I would like to only update this shape when it needs to be, and not using the callbackProperties.

What is the correct way to update a property on an entity?

In this sample code I have one circle starting a 0, 0 and moving due west, and a second starting at 0,0 moving due east.

The first circle is being moved using a callback property, the second by setting the entities position property to a new constant.

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

// Circle with callback property
var circle = {center:{longitude: 0, latitude: 0, altitude: 0}};
var circleOpts = {
position: new Cesium.CallbackProperty(function() {
return Cesium.Cartesian3.fromDegrees(
circle.center.longitude,
circle.center.latitude,
circle.center.altitude);
}, false),
ellipse: {
radius: 100000,
semiMinorAxis: 300000.0,
semiMajorAxis: 300000.0
}
};

viewer.entities.add(circleOpts);

// circle with constant center
circleOpts.position = Cesium.Cartesian3.fromDegrees(
circle.center.longitude,
circle.center.latitude,
circle.center.altitude);

var constantCircle = viewer.entities.add(circleOpts);

var lon = 0;
setInterval(function(circle, otherCircle){
circle.center.longitude-=.1;
lon += .1
constantCircle.position = Cesium.Cartesian3.fromDegrees(lon,0,0);
}.bind(this, circle, constantCircle, lon), 100);

``

  1. Is creating the new Cartesian3 and setting the entities position property to that new Cartesian3 the ‘correct’ / best way to update the entity?

  2. This doesn’t seem like it can handle allot of updates, if the setInterval code is replaces with:

setInterval(function(circle, otherCircle){
circle.center.longitude-=1;
lon += 1
constantCircle.position = Cesium.Cartesian3.fromDegrees(lon,0,0);
}.bind(this, circle, constantCircle, lon), 10);

``

The second circle is never moved and there is no error thrown, do you have any ideas on what could be causing this?

Thank you very much for your help, Cesium has been great so far but I cannot find these answers in the documentation or on the forum.

Zac

Hannah, can you clarify your comments on the Primitive API vs the Entity API regarding status and plans? I certainly understand that the current push is to get people to use the higher-level Entity API, but my understanding was that all of its abilities were built on TOP of the Primitive API, and that there’s a number of settings and abilities in the Primitive API that are not exposed by the Entity API.

Our current app is built entirely on the Primitive API, for a couple reasons. First, when we started, Cesium b17 was the latest and the Primitive API was the only thing available. Second, we’re doing our own data management (using Backbone models), and have built our own custom Backbone Views that render Cesium primitives instead of HTML.

Is there actually a plan to deprecate the Primitive API at some point? I would find that highly surprising, and very concerning.

Zac,

Yes, the code you pasted above looks good to me!

For #2, I think the reason it isn’t being drawn is because the program is trying to draw it asynchronously and the position is updating before the asynchronous draw is completed. For a case that is updating that frequently, you should use a CallbackProperty anyway.

-Hannah

Hello Mark,

The Entity API is built on top of Geometry and Appearances, not the Primitive API. (Primitives are also built on top of Geometry and Appearances.)

So there’s no need to worry, but that is part of the reason we’ve been encouraging people to use entities instead of primitives.

-Hannah

Hannah is mistaken. The Entity API is built directly on top of the Primitive API and does not do anything that the Primitive API cannot do (with enough code written on top of it). For a full explanation of this for anyone interested, I would recommend reading the What is the Entity API? (http://cesiumjs.org/2015/02/02/Visualizing-Spatial-Data/) section of the Visualizing-Spatial-Data tutorial.

The Primitive API is not going anywhere (and it never will). The main reason we encourage people to use the Entity API is that it is simply easier to use for a variety of standard use cases and allows for complex data-driven and time-dynamic visualization with very little code. Ultimately, the APIs serve two fundamentally difference purposes (as the link above discusses).

As time goes on, we will continue to improve both the Primitive and Entity APIs in major ways and neither of them are going anywhere. We also hope to make large strides to in documentation and modular separation to alleviate any confusion that has developed between the two and give a clear learning path for new users. Unfortunately that will most likely not happen until Cesium 2.0 (which is still just an idea at this point and not something we are actively working towards).

As far as the implementation of dynamic shapes, this is an area that Cesium is limited in for both the Primitive and Entity APIs. The performance limitations of JavaScript also play a role.

At the Primitive API level, we need to implement dynamic buffers, which will improve the efficiency of streaming ever-changing data to the video-card. Constantly changing primitive geometry also introduces large garbage collection churn. Primitives have no problem dealing with data that changes occasionally, but you need to be smart about how you manage and batch your geometry and how you go about making the changes.

At the Entity API level, we need to provide better heuristics for dealing with shapes that only change occasionally versus shapes that change every frame. Entity visualization only has two modes (static data and change-every-frame data). We also do two much work if you simply modify an existing static geometry that has already been placed in a batch with a lot of other geometry.

These are all solvable problems, but they take time. Right now most of our efforts are split between making sure all Cesium visualization is terrain aware (so terrain can be on by default and everything “just works”) and development of 3D Tiles (so the large scale visualizations that many users are trying to create are actually possible in a web browser). Once these two things are done (or at least farther along) I have no doubt that major improvement for dynamic-geometry will be one of the next big-ticket items we take on.

This ended up being a much longer post than I planned on, but I hoped it cleared up any confusion anyone might have had and provided some insight into curren behavior and plans.

Thanks,

Matt

1 Like

Thanks for the response, Matthew. That’s what I thought the situation was, and I appreciate the explanation.

And Hannah, no worries - just got kind of confused and concerned for a minute :slight_smile: Appreciate your explanations and contributions to the group as well.

Whoops! I guess I got mixed up somewhere. Thanks for clearing that up Matt =)

Hello,

Update: Based on feedback I implemented the initial rendering of entities to use cesium CallbackProperty(s). Then once they are done being updated, calling a function that replaces the callbacks with a constant value. When this happens, the entity flashes. Furthermore, if i do this for multiple entities, each prior entity that was changed to use constants flash too.

What is a good approach to updating an entities properties without it flickering. By update I mean only once, after set it wont change. I am currently doing something like this:

// render using callback properties at first
var entity.providerEntity = mapContext.entities.add({
ellipse: {
semiMinorAxis: new Cesium.CallbackProperty(this._getRadius.bind(this, circle), false),
semiMajorAxis: new Cesium.CallbackProperty(this._getRadius.bind(this, circle), false),
}),
position: new Cesium.CallbackProperty(this._getCenter.bind(this, circle), false)
});

// then later set the properties to constants
function(entity) {
var r = this._getRadius(entity);

entity.providerEntity.ellipse.semiMinorAxis = r;

entity.providerEntity.ellipse.semiMinorAxis = r;

entity.providerEntity.position = this._getCenter(entity);
}.bind(this, entity)

``

I tried using the request animation frame, but it seemed to have no effect.

Any thoughts would be greatly appreciated.

Thanks!

Zac

Rob, I answered this question in your other post here: https://groups.google.com/d/msg/cesium-dev/Y8LO_34yvBA/xbhBArFCEQAJ

In the future, please only post your questions once. Thanks.

This thread got a little hijacked. I am still looking for a solution to the flickering that happens when the callback properties are updated. I have tried using the setCallback too, but no luck.

Anyone have any ideas?

Thanks

I am having this same exact problem. Did you ever find a resolution? I am currently using a CallbackProperty to animate a polyline property and overriding that CallbackProperty with a ConstantProperty when I determine the animation is finished.

I am seeing the same flicker when I assign the property to a ConstantProperty.

The reason I am overriding the CallbackProperty in the first place is performance. When drawing 4k polylines in this fashion my framerate drops to about 5fps. If I "turn off" the CallbackProperty when it has finished animating, the visualization runs at 45fps.

Any suggestions on how to avoid this flicker, or any idea what may be causing it?

A few more details -- the flicker only seems to occur when dealing with the "positions" property of the polyline. I seem to be able to replace a CallbackProperty that supplies the "width" by a ConstantProperty that supplies a "width" and not cause a flickering of the polylines.

Ralabate2,

No I have not been able to remedy the flicker when the position properties
cesium callback property is updated. For now I have decided to live with
the flicker.

I am still trying to find a solution.