Week 18 · Mission GIS Engineer

3D globes: CesiumJS and orbital visualization

From 2D maps to 3D globes. CesiumJS is the open-source heavyweight champion. This week you put a real satellite into a real-time 3D orbital simulation.

Learning objectives

Primer

2D web maps work fine for showing where things are on Earth's surface. But satellites are NOT on Earth's surface — they're hundreds to thousands of kilometers above it, moving fast, in highly inclined orbits that wrap around the planet. To show where a satellite actually is in a way that makes intuitive sense, you need a 3D globe.

CesiumJS

CesiumJS (cesium.com) is the open-source 3D globe library that became the de-facto standard for serious 3D web GIS. NASA's Eyes on Asteroids, the FAA's traffic visualizations, every major satellite-tracker website with a 3D mode — all built on Cesium. The library is Apache 2.0 licensed; the commercial side is Cesium Ion, which hosts 3D tiles.

Cesium renders Earth as a WGS84 ellipsoid in WebGL. Coordinates are world-coordinate Cartesian (ECEF) internally; user-facing APIs accept lat/lon/altitude. The library handles all the camera math (orbit, zoom, tilt) so you don't have to.

Hello CesiumJS

<link rel="stylesheet" href="https://cesium.com/downloads/cesiumjs/releases/1.121/Build/Cesium/Widgets/widgets.css">
<script src="https://cesium.com/downloads/cesiumjs/releases/1.121/Build/Cesium/Cesium.js"></script>
<div id="cesiumContainer" style="width:100%;height:600px"></div>
<script>
  Cesium.Ion.defaultAccessToken = 'your-ion-token-or-empty-for-offline';
  const viewer = new Cesium.Viewer('cesiumContainer');
  viewer.entities.add({
    name: 'Cape Canaveral',
    position: Cesium.Cartesian3.fromDegrees(-80.6, 28.6, 0),
    point: { pixelSize: 10, color: Cesium.Color.ORANGE }
  });
</script>

Entities, time, and SampledPositionProperty

An Entity is Cesium's unit of "a thing on the globe". It has a position (which can be a function of time), graphics (point, billboard, polyline, polygon, model, etc.), and metadata.

A satellite is an entity whose position changes over time. You provide a series of timestamped positions; Cesium interpolates between them. The interpolation can be linear, Lagrange, or Hermite — for orbital motion, Hermite with high degree gives the smoothest result.

const positions = new Cesium.SampledPositionProperty();
positions.setInterpolationOptions({
  interpolationDegree: 7,
  interpolationAlgorithm: Cesium.HermitePolynomialApproximation
});

// For each propagated point from skyfield (or satellite.js):
for (const {time, lon, lat, alt} of orbital_points) {
  const jd = Cesium.JulianDate.fromIso8601(time);
  const xyz = Cesium.Cartesian3.fromDegrees(lon, lat, alt * 1000);
  positions.addSample(jd, xyz);
}

viewer.entities.add({
  name: 'ISS',
  position: positions,
  point: { pixelSize: 10, color: Cesium.Color.CYAN },
  path: { width: 2, material: Cesium.Color.CYAN.withAlpha(0.5),
          leadTime: 0, trailTime: 5400 }  // show 90-min trail
});

Time control

Cesium has a built-in Clock and an animation widget. The clock advances time; the SampledPositionProperty re-samples on each tick. The animation widget lets the user scrub, pause, and change playback speed.

viewer.clock.startTime = Cesium.JulianDate.fromIso8601('2026-05-11T00:00:00Z');
viewer.clock.stopTime  = Cesium.JulianDate.fromIso8601('2026-05-12T00:00:00Z');
viewer.clock.currentTime = viewer.clock.startTime.clone();
viewer.clock.multiplier = 60;  // 60x real time
viewer.clock.shouldAnimate = true;

Performance ceiling

Cesium can comfortably render ~10,000 simple entities at 60 fps on a modern desktop. Beyond that you need to use primitives (a lower-level API) instead of entities. The whole CelesTrak catalog (~10,000) renders fine; the Starlink constellation alone (~6,000) is also fine. Whole synthetic constellations of ~100,000 satellites need primitives.

The lab

You'll build a CesiumJS page that loads the current ISS TLE, uses satellite.js (the JavaScript SGP4 port) to propagate 24 hours, draws the orbital path as a polyline, and animates the ISS along it with the Cesium time control. By the end you'll have a working real-time satellite tracker — the foundation for Capstone 4 in Week 20.

Hands-on lab: ISS in 3D

Build a CesiumJS web page that loads the current ISS TLE, propagates 24 hours, draws the orbital path as a polyline, and animates the ISS along it with the Cesium time control.

Quiz

Test yourself. Answer key on the certificate-track page (Gold-tier feature: progress tracking and auto-grading).

Q1. CesiumJS uses:
  1. WebGL
  2. Canvas 2D
  3. SVG
  4. DOM
Q2. Cesium's coordinate system is:
  1. WGS84 (matching GPS)
  2. Web Mercator
  3. UTM
  4. Local tangent plane
Q3. An `Entity` in Cesium has:
  1. A position (possibly time-dependent), graphics, and metadata
  2. Only a position
  3. Only graphics
  4. Only metadata
Q4. Cesium Ion is:
  1. A 3D tile hosting service from Cesium (commercial)
  2. A free CDN
  3. A Cesium fork
  4. A QGIS plugin
Q5. To animate over time, use Cesium's:
  1. Clock + SampledPositionProperty
  2. setTimeout loop
  3. CSS animations
  4. WebSocket only