Cesium parity implementation and test plan¶
Review baseline: 73bcb847, September 6, 2026. The open issues are tracked by
#2259. An open tracker is not
proof that every requirement remains missing: feature picking has landed, and
plugin engine declarations and menu gating have also landed.
First implementation batch¶
| Issue | Change | Verification |
|---|---|---|
| #2275 | Ground cursor coordinates, optional elevation, ellipsoid fallback, and cleanup | Engine tests cover signed height, sky, fallback, morphing, and destruction; interaction tests cover store updates, preference changes, exit, and queued events; browser checks cover both themes and renderer swaps |
| #2279 | Field/expression labels, text size and color, halos, line/polygon anchors, zoom limits, opacity | Real Cesium graphics tests and a real US cities GeoJSON layer in the running app |
| #2291 | Projection follows the scene mode; native controls move between host corners, and a remount restores each control's last visibility and corner | Scene-mode tests, DOM lifecycle tests, hidden-control position restoration, remount tests, and browser fullscreen checks after moving the control |
The baseline browser reproduction of #2275 left the status bar at Coords: —
while pointing at the globe. The corrected browser reports longitude/latitude
and clears the readout on exit. The real US cities dataset produces 109 entities
and 109 labels. Since #3088 the globe also reads anchor (Cesium origins;
centred for line placement, as on the 2D map), maxWidth (word wrapping at
the em width, measured on a canvas), and the data-defined size, colour,
opacity and visibility overrides, which the in-place opacity restyle
preserves. Cesium labels have no rotation and no collision pass, so rotation,
allowOverlap (the globe always overlaps), the priority override, and text
along a line's path are not drawn; a line label sits at the line's midpoint.
Store points and labels also stop drawing through the Earth: their depth-test
distance follows the horizon (cesium-horizon.ts), verified with Natural Earth
populated places over East Asia, where the Americas' cities used to show
through. Scene-mode persistence is also not added here; #2291 describes it as
a possible follow-up.
Remaining work and ordering¶
September 11 audit: the open Cesium trackers are #2259, #2261, and #2262. The tileset styling requirement of #2290 landed in #2337 and native CZML in
2350. Although #2350 closed #2290, several requirements remain.¶
Clipping polygons and terrain sampling in the measurement tools remain outstanding; Ion terrain assets (#2552) are implemented as project-persisted terrain sources; Google Photorealistic 3D Tiles and the Asset Depot samples are now Ion quick picks in the Add Data dialog. The layer-format gaps listed below also remain, including ArcGIS vector tiles, drape picking, raw point clouds and splats, and deck.gl visualizations. Zarr layers render on the globe since #2261's zarr-cesium follow-up.
The control host now forwards camera and geographic pointer events and reports the actual canvas container dimensions. Since #3088 it records source and style-layer mutations into a shadow style, as the ArcGIS host does, instead of rejecting them: mirrored store layers draw through the layer sync and other GeoJSON overlays as ground-clamped entities. Custom layers are still refused, so controls that paint through MapLibre's WebGL context stay unmountable, and plugins still opt in through their engine declarations.
The Vite audit also found that excluding lerc from dependency optimization
externalized Cesium's LERC 2 import to the top-level LERC 4 package, preventing
the globe from opening. Both versions now remain in their respective dependency
graphs. The globe's COG loader supplies LERC 4's WASM URL explicitly, as the
2D raster loader already does. A real single-band Athens LERC DEM in
EPSG:2100 renders with a terrain colormap in both themes. The Layers panel
no longer applies its MapLibre-source placeholder warning to native Cesium
layers.
| Issues | Next work | Required evidence |
|---|---|---|
| #2276 | Implemented manual placement and shared extent drawing | Real pin drag and Done, rectangle drawing and Escape in both themes, renderer swaps, and Esri World Imagery extraction to a 22×12 EPSG:4326 GeoTIFF with nonconstant pixels; unit coverage includes antimeridian extents, pointer ownership, sky release, blur, and cancellation |
| #2277 | Engine-neutral capture, readiness, viewport/extent printing, video and tour recording | Nonblank 872×648 PNG; real print PNG; 11.6 s H.264 recording at 872×648; two-stop VP9 WebM tour; failed-layer and renderer-destruction capture tests. Atlas masks and map-series camera fitting retain their MapLibre gate. |
| #2278 (implemented) | Shared per-feature style evaluation | Real Natural Earth countries categorized by continent and populated places sized proportionally by population rendered on the globe and compared with the 2D map in both themes; unit tests evaluate the real core expressions for single, categorized, graduated, rule-based (with per-rule radius/width/colour/opacity overrides and the else rule), expression (including the invalid-expression fallback), proportional size, metre-unit strokes (zoom re-resolution), and simplestyle; layer-sync tests cover per-entity baking, point-to-circle conversion, in-place opacity restyle versus reload |
| #2280 (merged in #2298) | Filters, shared timeline, story opacity | Composed filters narrow together; clearing restores features; fades restore latest styles without mutating the project |
| #2281 (merged in #2299) | Extrusion and Z geometry | Known-height buildings and elevation profiles; scale/base/offset checks and terrain interactions |
| #2282 (implemented for points) | Clustering and large-vector primitives | Real populated-places clustering on the globe with counts and the clusterMaxZoom cutoff, and a 60k-point layer as one primitive batch, verified in both themes; unit tests cover the plan (point-only, markers, elevation, threshold), count abbreviation, bubble sizes, the cluster handler and refresh, batch building with feature refs, picking, quick filters, in-place opacity, removal, and the zoom toggle. Batched ground polygons and lines are not part of this pass (see #2311) |
| #2283 (implemented) | Raster protocol bridge | Real UC Berkeley COG (RGB, EPSG:3857) rendered pixel-identical to the 2D map, and a real raster PMTiles archive (Protomaps Terrarium z9) draped on the globe in both themes; unit tests cover template expansion, the registry path through a real addProtocol handler, back-pressure, destruction, empty tiles, the COG state-to-tiler mapping with automatic percentile stretch, the PMTiles header bounds, TMS templates, the unregistered-scheme error, and the raster symbology mapping. MBTiles and the native XYZ and WMS fetchers share the registry path and are desktop-only, so they are covered by the routing tests rather than the browser run; the WMS case additionally asserts that a natively-routed layer takes the bridge instead of WebMapServiceImageryProvider, since its source.url still holds the plain endpoint. |
| #2284 (implemented as a MapLibre drape) | Hybrid native/drape vector-tile path | Two real vector PMTiles archives (Protomaps Tilezen water and roads at z12, a global H3 building-count grid) draped on the globe in both themes with seam-free adjacent tiles, and the same project on the 2D map for comparison; unit tests cover the draped-kind predicate, the rebuild signature, tile-centre maths, the serialised render queue, stale-tile and destroy guards, the 512-px provider, and the layer-sync integration (one shared imagery layer, rebuild on change, teardown, no-drape error). Picking on draped content and ArcGIS VectorTileServer layers remain follow-ups. |
| #2285 (implemented) | Native I3S, point clouds, splats; deck.gl gating | Real Esri San Francisco buildings I3S scene layer rendered through I3SDataProvider (54 content tiles) and the real Autzen COPC decoded into a 381,256-point preview positioned over Eugene, both themes; unit tests cover URL classification, the bounded breadth-first octree walk with lazy sub-pages, reprojection through the archive WKT, 16-bit colour, abort, I3S/splat/point-cloud-tileset routing, in-place opacity, and removal mid-decode. The Add Data deck.gl builder is disabled without the customLayers capability. EPT, plain LAS/LAZ, and raw splat files stay "2D only" |
| #2286 (implemented) | Keyless and COG terrain | Real Mount Rainier Terrarium relief (~4,315 m), local DEM sample (835 m versus 839 m source pixel after grid resampling), shared tile edges, source replacement, and both themes |
| #2287 (implemented) | Native environment plugins | Sun clock and lighting on/off, atmosphere/sky box on/off and restore, spin start/stop, cloud imagery add/remove, and flight take-over/teardown verified in the real app in both themes; unit tests cover each Cesium branch against the real Cesium maths with a faked widget |
| #2288, #2262 | Enforce declared support in activation, URL dispatch, project restore, delayed controls, and command palette | Tests cover unsupported callbacks, renderer round trips, saved settings, and compatible-control remounting. The wider control facade and native plugin implementations remain separate work. |
| #2289 | Python/MCP/embed renderer authoring | Project round trips, renderer events, pane kinds, invalid inputs, and docs examples |
| #2290 (Ion assets implemented) | Cesium-native authoring features | Ion assets: Cesium OSM Buildings (asset 96188) and Bing Aerial (asset 2) added from the Add Data dialog on the globe in both themes, the same project reopened on the 2D map showing the "3D only" badge, a missing token surfacing as a layer error; unit tests cover the layer builder, the asset-id parser, the globe's tileset/imagery routing through IonResource/IonImageryProvider, rebuild on asset change, and the Python/MCP builders. Tileset styling and CZML have merged. Native KML/KMZ and elevation profiles are implemented: a real San Francisco landmarks KMZ retains its billboard styles and labels in both themes; a drawn 3.43 km profile samples World Terrain from -27 m to 74 m. Tests cover document loading, cancellation, opacity, cleanup, Python serialization, and terrain-provider replacement. Google Photorealistic 3D Tiles (asset 2275207) is one of the Ion quick picks, verified loading over San Francisco with the Google Maps credit in the Cesium attribution bar; the dropdown also carries six Asset Depot samples (Japan 3D Building Data, Melbourne Photogrammetry, Melbourne Point Cloud, Montreal Point Cloud, New York City 3D Buildings, Washington DC 2017), with New York City verified rendering over Manhattan and a depot asset the account has not added reported as a load error. Clipping polygons and Terrain Measure remain follow-ups; Ion terrain assets are implemented in #2552. |
| #2261, #2259 | Update umbrella completion only after child requirements are verified | Accurate supported-layer predicates and an explicit record of remaining gaps |
Recording control facade (#3088)¶
| Change | Verification |
|---|---|
| Shadow-style recording, layer events, overlay entities, rhumb arcs, horizon culling, text anchor/offset, store-derived style-layer ids, suppressed mouse-event re-dispatch, custom-layer refusal | Unit tests drive the host with real Cesium entities and data sources: per-graphic entity output, mirrored-layer suppression, layer-scoped picks through the engine's identify, dragPan restoring prior inputs, fitBounds, the recorded style round trip, and the custom-layer throw |
| Gridlines and the DGGS grids | H3 cells at resolutions 0 and 3 with labels and click-to-identify highlight; DGGAL ISEA3H and DGGRID grids; a world graticule whose ±180° parallels draw only as rhumb ground polylines, and screen-edge labels at zoom 5 |
| Store-mirrored web services | FEMA NFHL flood zones over New Orleans at zoom 15 (the service draws nothing at zoom 11); USGS Topo over Rocky Mountain NP; EnviroAtlas MSPA2011 across CONUS with the panel opacity reaching the imagery alpha; NASA GIBS Blue Marble bathymetry; Esri Wayback 2014 versus latest over Mission Rock |
| STAC | Earth Search Sentinel-2 C1 L2A: bbox drawn by drag with the camera held, 20 footprints, click-to-select highlight, and a true-color COG imported as a store cog record (mounting the raster control previously hung the page) |
| Catalogs | Ocean Data Platform vector tiles and 3,397 features in view; Earthdata GIS GPWv4 population density from an ImageServer exportImage template (a wms record the globe had sent to WebMapServiceImageryProvider); GeoLens signed IBTrACS vector tiles and Natural Earth GeoJSON; Hugging Face aerial.tif and a GeoJSON |
Known limits: a striped (non-tiled) GeoTIFF reports an error through the store import, as on ArcGIS, where the MapLibre raster control offers a conversion; the LiDAR and splat panels stay disabled on the globe.
Test gates¶
- Reproduce the missing behavior in the real app before changing it.
- Add focused tests at the engine boundary. Use actual Cesium math and graphics where possible; mock only the browser/GPU lifecycle that Node cannot provide.
- Exercise the app in both themes with real geospatial data. Verify the visible result as well as store/engine state, and test switching back to MapLibre.
- Run relevant existing suites, the production build, lint, and formatting hooks.
- Keep tracking issues open until all child requirements are complete. Do not advertise a new capability or supported layer kind before its workflow works.
Catalog audit: Source Coop, Open Data Catalogs, and ArcGIS Hub already declare both engines. STAC explicitly retains MapLibre dependencies for footprint picking. Planetary Computer and NASA Earthdata read their controls’ map; Hugging Face delegates file loading to the vector/raster controls. These are not automatically safe to ungate based on their catalog UI alone.
Keyless globes now use Mapzen Terrarium heightmaps; an Ion token selects World Terrain. Controls → Terrain exaggeration accepts local and HTTP COG DEMs on either renderer. Shared edge samples avoid cracks between heightmap tiles; requests and tile caches are bounded and disposed with the source.