As Cesium has matured, interoperability with external data sources such as CZML, GeoJSON, KML, CityGML, and others has become increasingly important. It's probably one of the most common topics on the mailing list. While we have made strides in this direction, larger changes need to take place in our internal architecture before we can really code full support for these formats. In the interest of open development, I wanted to provide a full overview of where we are and where I see things going over the next few months. Feedback, as always, is appreciated.
The current DynamicScene architecture in Cesium began with the sole purpose of visualizing our own still-in-progress CZML format. At the time we were only concerned with time-dynamic data. Time is a first-class citizen in Cesium and we wanted to be sure to showcase it. Many of us were also still fairly new to large scale JavaScript programming and we didn't have a clear picture on where it was all going.
Fast-forward 3 years and you get to where we are today, we have refactored parts of DynamicScene several times, added higher-level abstractions and plug-in support so that different data sources can be loaded regardless of format. We have out of the box support for GeoJSON and in-progress support for KML, neither of which are time-dynamic. Most importantly, we have a much clearer picture of what our ultimate goals are for both data sources and Cesium as a whole.
Along with the positive changes, we have accrued some technical debt that is preventing us from adding certain features. For example, the
Geometry & Appearances system is not yet being utilized by the DynamicScene layer. Among other things, this prevents us from adding new geometry features to CZML, finishing up native KML support, or improving GeoJSON performance. Most of this is due to the fact we have been trying to make small, backwards compatible changes to the codebase slowly over time and these features are extremely hard to implement incrementally. Since the last thing we want to do is introduce lots of breaking changes every release, it is time to take a step back and perform a large-scale refactor of the code.
Before refactoring the code; it's important to take inventory of the issues we want to address. Below is a list of the existing problems (in no particular order). Keep in mind that this does not include additional features that we plan on adding, but only features that are hard to add in the existing architecture. See the
DynamicScene & DataSource roadmap for a full list of planned features.
- DynamicScene and the objects contained in it are misnomers at this point, since we handle both static and dynamic data. This is easily changed, but is a breaking change that we will only want to make once. Better names should make usability much easier for new users.
- The current visualization system is very brute force, it re-evaluates almost everything every frame. We get away with this for sampled data, but it's incredibly inefficient for static or slow-changing data. The bookkeeping required to fix this is itself tedious and inefficient given the current architecture of DynamicObject. We need to fix this to efficiently support static geometry found, such as KML and CityGML.
- Property objects do not have any sort of change notification, for example, there's no way to know that a sample was added to a SampledProperty. This makes batching visualization impossible because two equal properties can become unequal without us detecting it.
- We have no way to know if a property is time-varying or not. We currently check for "instanceof ConstantProperty" in some places, but this is a hack. We also have no distinction between fast changing data (SampledProperty) and slow changing data (TimeIntervalCollectionProperty), which may be useful for caching purposes.
- It's not currently possible to have two types of the same primitive registered on a DynamicObject, i.e. you can't have 5 separate polygons representing Hawaii as a single DynamicObject.
- Since visualization relies on shared "position", "vertexPositions", and "orientation" properties at the root of DynamicObject, underlying graphics objects are limited in what they can do. For example, we can't currently support polygon hierarchies with holes with this method. This also makes it very hard to incrementally improve the current system without affected all objects that depend on these properties. It also means that objects are not self-contained, which makes tracking changes tedious and slow.
- DynamicObject is a dumping ground that has every potential property registered on it. This makes it a unwieldy. It would be better to support creation of streamlined mixed-in types just for the data being used.
- We inconsistently use ES5 properties versus getter/setter functions. We should switch to ES5 exclusively for the entire DataSource layer.
- There's no easy way to turn visualization of a DynamicObject "off" or turn individual graphics off. We added a `uiShow` property in the dataSourceBrower branch, but it's temporary until we do it for real.
- The visualizers currently monkey patch DynamicObject instances with extra bookkeeping data. This most-likely affects performance and also creates potential conflicts if two visualizers use the same property names.
- DataSources need to do a better job of throwing RuntimeErrors instead of DeveloperError, this is even more critical now that we are pre-processing out DeveloperError.
- We currently use the `position` and `viewFrom` properties to track an object with the camera, but not every object has a position, and `viewFrom` is not adequately defined.
None of the above issues are particularly difficult to fix, but they will have a good number of implications throughout the code. While there will certainly be some API breakage as a result, our goal is to make it trivial to migrate any existing Cesium applications over to the new code. If you are familiar with the current system, the refactor system will be extremely similar.
Finally, I wanted to mention that since CZML is simply a DataSource plug-in into Cesium, none of these changes affect the CZML format or capabilities itself. However, once all of these changes are made, it will be easy to perform a similar refactoring on the CZML format in order to address issues that have become obvious in the last few years. We may even potentially start a CZML version 2 in order to maintain backwards compatibility with the original unversioned format that's currently in use today.
Assuming no surprises, I think all of the above changes can be made in time for the April release of Cesium (maybe even March if things go really well). However, given the nature of the changes, we will most likely ask those interested to check out the branch before then. CZML enhancements would soon follow, either in the same release or the one right after (and KML after that).
Thanks for reading,
Matt