Tuesday, August 19, 2014

Cesium in action

Cesium is a WebGL virtual globe and map engine.
You can use it to build time-aware GIS applications. What do I mean by "time-aware"?
Suppose you want to let the user playback scenarios on the map. For instance, meteor hits over the years or satellite/airplane tracking.
Most map engines don't "understand" time. The way to implement this kind of functionality using ArcGIS for JS for example, is using different layers for each discrete moment. This is very heavy, not easy to implement and shows only discrete moments.
Cesium, on the other hand, supports continuous playback (and even comes with a clock and timeline built-in!). Cesium offers a data format, called CZML, which is basically a regular JSON array. In this array, you can specify elements. These elements could be points, polylines, polygons, text labels, images or even 3D models. For each element you can specify properties that will determine the element's life span, position, size, color, texture and a bunch of other things.
For example, you could say that a blue point with a black border will appear for 5 seconds at 2014-05-05 18:00:00 at longitude 34, latitude 35, height 0. This is represented as the following CZML:


Seems simple, right? it is. CZML provides a way to paint a scenario for Cesium to play, and you can do amazing things with it, just look at the Cesium Samples Page.
The rest of this post is some issues and best practices with Cesium.
I used Cesium for the past few months to build a small analysis tool for some clients. They can load Excel files that specify times and coordinates of events. The application will allow playback of those events and some advanced processing of those events.
Our application needed to create CZMLs on the fly, so we wrapped CZML creation in a nice small JS API. It is bad to just create CZMLs with actual JSON. This could cause code duplication and performance issues.
Beware of interpolation! Cesium supports interpolation of some properties, which means that if the color of the point is yellow at 5PM and green at 6PM, when playing back you will see the color changes gradually from yellow to green, instead of changing momentarily at 6PM. That is awesome, sometimes. For us it was mostly annoying, because we didn't need it usually, so we had to do an annoying work-around of keeping the same color 5 seconds before the changing time. That way the interpolation would happen only during those 5 seconds, which is short enough to be unnoticeable.
Interpolation sometimes causes acute performance issues. We ran into such a problem in the evening, while loading the application with real data, which was large enough to make the playback hideously slow and then the engine would collapse and Cesium would throw a weird error and just stop working. We spent 5 hours fixing this problem... It turned out to be interpolation again. Luckily, we found out that the show property wasn't interpolatable and we used it to show a point in specific times, instead of changing the alpha of the color to make it disappear.
Also, we noticed that using the show property sometimes causes performance issues, if you put more than one interval in the show array. The workaround is to tell it when not to appear (negative infinity to start time 1, end time 1 to start time 2, end time 2 to positive infinity). Weird but works :)
Loading a Cesium data source is possibly a heavy action, because it reads and processes your CZML. If you have several data sources that gets updated, use multiple data sources for a viewer (yes, Cesium supports that: viewer.dataSources) and load only the relevant ones. We used to load all data sources, even when just one data source gets updated. Looking for performance bottlenecks in our application, we noticed this inefficiency. So we made this process modular, loading only dirty data sources.

Hope this helps someone!