I’m working my way through some of the Cesium examples and tutorials, and I have a working prototype that can load geoJson and perform some basic manipulation of polygons (change color from a button click). My question is, what is the relationship between entities and primitives? After loading my data, which contain 2 points and 1 polygon, I see that there are 5 primitives created:
Two primitives are “blank”: they have no appearance, instanceIds, or other properties that the other three entities have
One primitive is a billboard array for points
Two primitives appear almost identical for the one polygon. The only difference appears to be their _primitiveType. One is _primitiveType: 1 and the other is _primitiveType: 4. Are two primitives created for each polygon, one for the shape itself and one for the border? Or is something else going on?
I’m incorporating Cesium into a larger application, and eventually what I want to do is be able to click on something elsewhere in the application and pick/change/do something with the corresponding object in Cesium. Is there a recommended best practice for manipulating objects in Cesium? For example, if I want to change an entity that has a PointGraphic and replace the PointGraphic with an image billboard, should I remove the primitive and add a new one? Or is there a better updating method?
I’ve been meaning to answer this question for a while but have been rather swamped. Here is some insight into what is going. I’m hoping to eventually have full documentation on the subject but that’s part of a larger effort to improve our doc.
Entities are a means to generically represent data and visualization at a high level. This makes it easy to define what you want the data to look like without knowing about the underlying details. Visualizers (owned and driven by the DataSourceDisplay class inside of Viewer) are responsible for inspecting each entity and creating primitives under the hood to best represent them. For example, Polygons do in fact create a two primitives, one for the outline and one for the interior, but that’s not always the case. If you have 10,000 random polygons, you can have anywhere between 2 and 20,000 Primitives created for them depending on what visualization options are being used. We automatically batch items together to that they can be rendered efficiently. Creating a polygon under the hood is very different than creating a billboard, point, or label; so the entity interface tried to normalize the API so that everything works the same at the top.
In general, when you are using the DataSource layer, you do not directly change the primitives being created via entities, instead you change the entity itself. For example, if you have a Entity.point and you want it to be a billboard instead, you should set the point to undefined and create a BillboardGraphics and assign it to Entity.billboard. We do something similar in this Sandcastle example, which manipulates polygons to extrude them. Also, each primitive created by the entity visualization system has it’s “id” property assigned to the entity it represents. So if you want to know that an entity is clicked on, you can check the id property of the primitive returned from Scene.pick.
The empty primitives you see are the result of the Billboard/Point/Label visualizers, which create empty collection to start (though I’ve considered trying to change this so they only get created the first time they are used).
Of course you are free to create your own custom primitives alongside those created by the DataSource layer, but you shouldn’t change primitives that you yourself did not create.
I hope that helps, let me know if anything was unclear or if you’d like more explanation in other areas.
Ok, thanks. That helps a lot. However, I’m running into a problem when doing something that I thought would be relatively easy: replacing or changing the billboard after the datasource has loaded. E.g., building upon the Sandcastle geoJson example, change the color of a billboard:
There are two easily fixable issues here. Entities require Property instances, not direct data values. Also, image can (currently) only be a string, so you need to pass it the Data uri representation of the pin.
Here’s the fixed code:
billboard.image = new Cesium.ConstantProperty(pinBuilder.fromColor(Cesium.Color.CRIMSON, 48).toDataURL());
I definitely want to explore making this easier in future releases.
Yeah, I can see how that should be made easier. Or more examples in Sandcastle or expanded info in the reference documentation to show which type of Property a property is (Constant, Material, etc).