Click or drag to resize

Visualization with Cesium

Cesium is an open-source JavaScript library, founded by AGI in 2011. Cesium provides a cross-platform, browser-based virtual globe with a focus on precision and time-dynamic data. DME Component Libraries also includes an enhanced commercial version of Cesium, Cesium Analytics SDK.

In DME Component Libraries, the Cesium Library provides the ability to generate CZML content from Platforms and other DefinitionalObjects, as well as analysis derived from them. CZML is a JSON-based data format designed by AGI to load static and time-dynamic data into Cesium.

This topic assumes basic familiarity with Cesium. Cesium documentation, tutorials, and code samples are available separately from the Cesium site.

Overview

The Cesium Library is built upon the same design patterns used throughout DME Component Libraries. It provides ObjectExtensions that describe how CZML properties are defined over time. These extensions are then added to individual Platforms and other ExtensibleObjects. Effectively, these extensions add CZML visualization information to your existing objects, after which they can be added to a CzmlDocument and serialized to CZML.

To understand how this works in practice, the following code sample demonstrates how to draw a label at the location of the International Space Station, and draw its orbit.

Java
EarthCentralBody earth = CentralBodiesFacet.getFromContext().getEarth();
TwoLineElementSet issTle =
        new TwoLineElementSet("1 25544U 98067A   10172.34241898  .00007451  00000-0  60420-4 0  3627\r\n" +
                              "2 25544  51.6459 209.3399 0009135 352.3227 186.5240 15.71934500664129");

Point issPoint = new Sgp4Propagator(issTle).createPoint();
Platform iss = new Platform();
iss.setName("ISS");
iss.setLocationPoint(issPoint);
iss.setOrientationAxes(new AxesVehicleVelocityLocalHorizontal(earth.getFixedFrame(), issPoint));

LabelGraphics issLabel = new LabelGraphics();
issLabel.setText(new ConstantCesiumProperty<>(iss.getName()));
issLabel.setFillColor(new ConstantCesiumProperty<>(Color.WHITE));

LabelGraphicsExtension labelExtension = new LabelGraphicsExtension(issLabel);
iss.getExtensions().add(labelExtension);

PolylineOutlineMaterialGraphics issPathMaterial = new PolylineOutlineMaterialGraphics();
issPathMaterial.setColor(new ConstantCesiumProperty<>(Color.WHITE));
issPathMaterial.setOutlineWidth(new ConstantCesiumProperty<>(1.0));
issPathMaterial.setOutlineColor(new ConstantCesiumProperty<>(Color.BLACK));

PathGraphics issPath = new PathGraphics();
issPath.setMaterial(new ConstantCesiumProperty<>(issPathMaterial));
issPath.setWidth(new ConstantCesiumProperty<>(2.0));
issPath.setLeadTime(new ConstantCesiumProperty<>(Duration.fromMinutes(44).getTotalSeconds()));
issPath.setTrailTime(new ConstantCesiumProperty<>(Duration.fromMinutes(44).getTotalSeconds()));
iss.getExtensions().add(new PathGraphicsExtension(issPath));

TimeInterval interval = new TimeInterval(new JulianDate(new GregorianDate(2009, 1, 1)),
                                         new JulianDate(new GregorianDate(2009, 1, 2)));
CzmlDocument czmlDocument = new CzmlDocument();
czmlDocument.setName("SimpleExample");
czmlDocument.setDescription("A simple example");
czmlDocument.setPrettyFormatting(true);
czmlDocument.setRequestedInterval(interval);
Clock clock = new Clock();
clock.setInterval(interval);
clock.setCurrentTime(interval.getStart());
czmlDocument.setClock(clock);

czmlDocument.getObjectsToWrite().add(iss);

try (Writer writer = Files.newBufferedWriter(outputPath.resolve("Example.czml"))) {
    czmlDocument.writeDocument(writer);
}

First, we create a Platform to represent the ISS, with its location determined by a TLE. We then add a LabelGraphicsExtension and a PathGraphicsExtension. These extensions define various graphical properties that determine how the object will be displayed in Cesium. Then, to write the CZML, we create a CzmlDocument, provide a name and description for the document, configure the time interval over which we want to write data for, add the ISS platform to the list of objects to write, and then finally write the CZML file to disk. If you were to load this file into Cesium, you would see something like the below:

Example CZML in Cesium
Cesium Properties

In the code above, we configure the graphical properties using instances of ConstantCesiumProperty<T>. In CZML, almost every value can be defined to vary over time, so graphical properties, such as FillColor (get / set), are actually instances of the abstract base class CesiumProperty<T>. ConstantCesiumProperty<T> is merely the simplest implementation, for cases where a value is constant with respect to time.

CesiumProperty<T> is a means to define how a particular graphical property of an object in your Cesium scene changes over time. This allows you to associate the results of your analysis with the desired appearance of the display and is a fundamental concept in the Cesium Library.

The following additional types of CesiumProperty<T> are available:

As an example, suppose we wanted the text of the ISS label to be green before January 1st, 2009, and red any time after that. The following example shows how to accomplish this using a TimeIntervalCesiumProperty<Color>:

Java
JulianDate colorChangeTime = new JulianDate(new GregorianDate(2009, 1, 1));
TimeIntervalCollection1<Color> intervals = new TimeIntervalCollection1<>();
Color green = new Color(0x008000);
intervals.add(new TimeInterval1<>(JulianDate.getMinValue(), colorChangeTime, green));
intervals.add(new TimeInterval1<>(colorChangeTime, JulianDate.getMaxValue(), Color.RED));
labelExtension.getLabelGraphics().setFillColor(new TimeIntervalCesiumProperty<>(intervals));
CZML Identifiers

By default, the identifiers for each CZML object will be auto-generated, but if you need more control, you can add an IdentifierExtension to configure the identifier for that object.

Java
iss.getExtensions().add(new IdentifierExtension("ISS"));
Links

So far we have mainly been using color, but the same model applies to all other CZML properties. Suppose we wanted to visualize when the ISS had line of sight to a point on the ground, for example, AGI headquarters. In DME Component Libraries, we model this as an Access problem, using LinkInstantaneous and a CentralBodyObstructionConstraint.

Java
Cartographic facilityLocation = new Cartographic(-1.3191780323141054, 0.69871349190638687, 0.0);
Point facilityPoint = new PointCartographic(earth, facilityLocation);
Platform facility = new Platform();
facility.setName("AGI HQ");
facility.setLocationPoint(facilityPoint);
facility.setOrientationAxes(new AxesEastNorthUp(earth, facilityPoint));

LabelGraphics facilityLabel = new LabelGraphics();
// Note: toCesiumProperty is a static import of CesiumProperty.toCesiumProperty 
facilityLabel.setText(toCesiumProperty(facility.getName()));
facilityLabel.setFillColor(toCesiumProperty(Color.WHITE));
facility.getExtensions().add(new LabelGraphicsExtension(facilityLabel));

LinkInstantaneous link = new LinkInstantaneous(facility, iss);
CentralBodyObstructionConstraint constraint = new CentralBodyObstructionConstraint(link, earth);

We can then use these analysis types directly to visualize the results in Cesium. First, we create an LinkGraphicsExtension to describe the graphical properties of our link, which will be represented using a polyline in CZML. In our example, we make the link yellow by configuring the link's material. See the next section for more information on materials. Next, we want to only show the link when the constraint is satisfied. Since CentralBodyObstructionConstraint is an AccessQuery, we define the Show (get / set) property as an AccessQueryCesiumProperty<Boolean>, indicating that the link graphics should be shown when access exists, and not otherwise. The following code sample shows this:

Java
AccessQueryCesiumProperty<Boolean> showProperty = new AccessQueryCesiumProperty<>();
showProperty.setQuery(constraint);
showProperty.setAccessExists(true);
showProperty.setAccessUnknown(false);
showProperty.setNoAccess(false);

LinkGraphics linkGraphics = new LinkGraphics();
linkGraphics.setShow(showProperty);
linkGraphics.setMaterial(toCesiumProperty(new SolidColorMaterialGraphics(Color.YELLOW)));
link.getExtensions().add(new LinkGraphicsExtension(linkGraphics));
Materials

In the above examples, we configured both PathGraphics and LinkGraphics using materials. A material defines how the surface of many Cesium graphical types will be rendered. For example, Cesium (and therefore CZML) defines a PolylineOutline material which renders an outlined polyline. In DME Component Libraries, this corresponds to the PolylineOutlineMaterialGraphics type. Alternatively, we could use a SolidColorMaterialGraphics, or any other material instead. Each material defines its own set of specialized graphical properties. For example, the PolylineGlowMaterialGraphics provides Color (get / set) and GlowPower (get / set) properties.

In addition to polyline material types, which implement the IPolylineMaterialGraphics interface, there are also more general material types, which implement the IMaterialGraphics interface. These materials are used for shape and volume rendering, such as CentralBodySurfaceRegionGraphics and SensorFieldOfViewGraphics. In fact, sensor visualization allows different materials to be used for different parts of the sensor volume. For example, the following code sample adds a sensor to our facility representing AGI, pointing at the ISS as it passes overhead. We make the primary sensor volume green, but we use a white grid material to represent the sensor dome.

Java
VectorFixed referenceVector = new VectorFixed(iss.getOrientationAxes(), Cartesian.toCartesian(UnitCartesian.getUnitZ()));
Axes sensorOrientation = new AxesTargetingLink(link, LinkRole.TRANSMITTER, referenceVector);
Platform sensor = new Platform();
sensor.setLocationPoint(facility.getLocationPoint());
sensor.setOrientationAxes(sensorOrientation);

RectangularPyramid rectangularPyramid = new RectangularPyramid();
rectangularPyramid.setXHalfAngle(Trig.degreesToRadians(8.0));
rectangularPyramid.setYHalfAngle(Trig.degreesToRadians(4.5));
rectangularPyramid.setRadius(500000.0);
sensor.getExtensions().add(new FieldOfViewExtension(rectangularPyramid));

SensorFieldOfViewGraphics fieldOfViewGraphics = new SensorFieldOfViewGraphics();

GridMaterialGraphics gridMaterial = new GridMaterialGraphics();
gridMaterial.setColor(toCesiumProperty(Color.WHITE));
gridMaterial.setCellAlpha(toCesiumProperty(0.0));
fieldOfViewGraphics.setDomeSurfaceMaterial(toCesiumProperty(gridMaterial));

Color transparentGreen = new Color(0x80008000, true);
SolidColorMaterialGraphics lateralSurfaceMaterial = new SolidColorMaterialGraphics(transparentGreen);
fieldOfViewGraphics.setLateralSurfaceMaterial(toCesiumProperty(lateralSurfaceMaterial));

sensor.getExtensions().add(new FieldOfViewGraphicsExtension(fieldOfViewGraphics));

When loaded in Cesium Analytics SDK, this looks like:

Example CZML with Sensor in Cesium
Code Sample

The Code Sample topic puts each of the pieces described above into one complete example.

Deleting Data

In advanced situations, you may need to delete data from a Cesium client via CZML documents processed into an existing client-side data source. This can also be necessary in order to replace data correctly, because processing data is an additive operation. As a result, by default, sampled properties have their samples merged with existing samples, which can produce incorrect visualization.

In order to delete data, objects must have stable identifiers. See the Identifiers section for more information on associating objects with identifiers.

There are several different mechanisms for deleting data:

The recommended approach to deleting an object is to use a placeholder ExtensibleObject, which has no extensions by default, then specify the identifier of the existing object, and add the extensions to delete the desired data, then add the placeholder object to the CzmlDocument.

Because CZML is generated for objects in order, you can then add a complete definition of the object using the same identifier. The generated CZML will contain a packet deleting the requested data, then a subsequent packet adding new data. Because Cesium processes packets in order, this will effectively replace the data.

Update Documents

The functionality described above is designed to produce a complete description of a set of objects to be visualized in Cesium. In most use cases, this conceptually simple way of transmitting information is sufficient, even in situations where objects may change their definition. A complete CzmlDocument can be written each time definitions change, and loaded into Cesium, replacing the previous document on the client. Since each document fully describes all objects, they are independent from any previous state.

In advanced situations with large amounts of data, producing complete documents can result in a large amount of CZML to be transmitted and processed. In these cases, update documents can be generated to send only data that has changed, which requires a more complex implementation but can significantly reduce the amount of data produced.

CzmlClientEntitySet represents the complete state of all entities for a specific Cesium client. Each client should have a separate instance associated with it, and the entity set should persist as long as the client is active.

Next, whenever the state of the objects change, create a complete CzmlDocument containing all objects, including all extensions, that should be visualized. Make sure that all objects have stable identifiers (see the Identifiers section) because identifiers will be used to correlate objects across updates.

Then, call add to add the new complete document to the entity set. This method returns a CzmlUpdateDocument which contains the changes between the previous state and the new document. This update document can be then written to the client and processed (without clearing existing data).

This technique is most useful when building a web application that uses Cesium as the front-end, with DME Component Libraries providing server-side analysis, to provide a common operational picture. A Cesium-based client could refresh its data on a schedule, or the server could push updates to clients when they occur. An entity set would be maintained associated with each Cesium client, and the update documents would then be written directly to the web service response to be processed by the client.

The following code sample shows the intended sequence of operations to create update documents for a single client. The details of the CZML document are omitted here.

Java
// Create an entity set for a specific Cesium client.
CzmlClientEntitySet entitySet = new CzmlClientEntitySet();

// Create a complete document containing all entities and all extensions.
CzmlDocument czmlDocument = createDocument();

// Add the document to the entity set, producing a CzmlUpdateDocument.
CzmlUpdateDocument updateDocument = entitySet.add(czmlDocument);

// Write the update document to a writer, such as a web service response.
updateDocument.writeDocument(getOutputWriter());

// Later...

// Create a new complete document containing all entities.
// Entities will be correlated by identifier.
czmlDocument = createDocument();

// Add the new complete document to the existing entity set.
// The update document will contain only the data that has changed
// since the previous document was added.
updateDocument = entitySet.add(czmlDocument);

// Write the new update document as before.
updateDocument.writeDocument(getOutputWriter());

List of Services and Extensions

The table below provides a list of all services and related extensions involved in writing CZML. While most generated CZML is supported by open-source Cesium, some features are only supported by Cesium Analytics SDK. Loading a CZML file with these features into open-source Cesium will simply cause the unsupported features to be ignored.

Service

Extension

Description

CZML Type

Availability

IAzimuthElevationMaskGraphicsService

AzimuthElevationMaskGraphicsExtension

Visualizes an AzimuthElevationMask at the object's position, oriented using the object's orientation. The geometry will be defined by the IAzimuthElevationMaskService service.

agi_fan

Cesium Analytics SDK

IBillboardGraphicsService

BillboardGraphicsExtension

Visualizes a 2D marker at the object's position.

billboard

Cesium

ICentralBodySurfaceCurveGraphicsService

CentralBodySurfaceCurveGraphicsExtension

Visualizes a surface curve on an central body. The geometry of the curve will be defined by the ICentralBodySurfaceCurveService service.

polyline

Cesium

ICentralBodySurfaceRegionGraphicsService

CentralBodySurfaceRegionGraphicsExtension

Visualizes the outline, interior and boundary wall of a surface region on an central body. The geometry of the region will be defined by the ICentralBodySurfaceRegionService service.

polygon

Cesium

ICesiumAvailabilityService

CesiumAvailabilityExtension

Overrides the auto-detected availability of a CZML object with the specified interval.

availability

Cesium

ICesiumCustomPropertiesService

CesiumCustomPropertiesExtension

Defines custom time-varying CZML properties for use by client-side code.

properties

Cesium

ICesiumDeleteService

CesiumDeleteExtension

Indicates that a CZML object with the associated identifier should be deleted from the client.

delete

Cesium

ICesiumDirectionService

GraphicalVector

Customizes details about how an vector's direction will be written to CZML.

orientation

Cesium

ICesiumFixedStepService

CesiumFixedStepExtension

Customizes the step size to use when sampling properties for an object, instead of using the value specified for CzmlDocument.Step (get / set).

Cesium

ICesiumOrientationService

CesiumOrientationExtension

Customizes details about how an object's orientation will be written to CZML.

orientation

Cesium

ICesiumPositionService

CesiumPositionExtension

Customizes details about how an object's position will be written to CZML.

position

Cesium

ICesiumReferenceFrameService

CesiumReferenceFrameExtension

Allows a CZML object's position to be written in the inertial frame.

position

Cesium

IDescriptionService

DescriptionExtension

Specifies the HTML description of an object.

description

Cesium

IEllipsoidGraphicsService

EllipsoidGraphicsExtension

Visualizes a 3D ellipsoid at the object's position, oriented using the object's orientation.

ellipsoid

Cesium

IFieldOfViewGraphicsService

FieldOfViewGraphicsExtension

Defines graphical properties for sensor volumes and footprints projected onto a central body, at the object's position, oriented using the object's orientation. The geometry of the sensor volume will be defined by the IFieldOfViewService service.

agi_conicSensor, agi_customPatternSensor, agi_rectangularSensor

Cesium Analytics SDK

IIdentifierService

IdentifierExtension

Specifies the identifier of the object, which must be unique. If not provided, a unique identifier will be generated automatically.

id

Cesium

ILabelGraphicsService

LabelGraphicsExtension

Visualizes text at the object's position.

label

Cesium

ILinkGraphicsService

LinkGraphicsExtension

Visualizes a polyline drawn connecting the two end points of a link. The geometry of the polyline will be defined by the ILinkService service.

polyline

Cesium

ILocationPointService

LocationPointExtension

Specifies the position for an object. Most graphical extensions require this information.

position

Cesium

IModelGraphicsService

ModelGraphicsExtension

Visualizes a 3D model in glTF format at the object's position, oriented using the object's orientation. See the glTF repository for more details on the glTF format.

model

Cesium

INameService

NameExtension

The name of the object, which does not have to be unique and is intended for user consumption.

name

Cesium

IOrientationAxesService

OrientationAxesExtension

Specifies the orientation of an object over time. Some 3D graphical extensions require this information.

orientation

Cesium

IParentService

ParentExtension

The parent object of the object.

parent

Cesium

IPathGraphicsService

PathGraphicsExtension

A path of an object as it moves over time.

path

Cesium

IPointGraphicsService

PointGraphicsExtension

Visualizes a 2D point at the object's position.

point

Cesium

ITilesetGraphicsService

TilesetGraphicsExtension

Visualizes a 3D tileset at the object's position, oriented using the object's orientation.

tileset

Cesium

IVectorGraphicsService

GraphicalVector

Defines the graphical properties of a 3D Vector, at the object's position. The geometry of the vector is defined by the IVectorService service.

agi_vector

Cesium Analytics SDK

IViewFromService

ViewFromExtension

Specifies the suggested initial camera view offset when tracking an object.

viewFrom

Cesium