How to Perform Analytical Queries on Live CesiumJS Data Layers
To perform analytical queries on live CesiumJS data layers in God’s Eye View, use the DataLayerManager’s resolveLayerTrackingTarget() method after enabling and refreshing the target layer via setEnabled() and refreshLayer().
God’s Eye View is an open-source CesiumJS application that renders real-time data overlays for aircraft, satellites, and vessels. To perform analytical queries on live CesiumJS data layers, the codebase implements a centralized DataLayerManager (src/data/manager.js) that coordinates layer lifecycle management and exposes a uniform API for interrogating specific entity states and cartographic positions.
Core Architecture of the Query System
The analytical capabilities rely on a modular architecture that separates data sources from visualization logic.
DataLayerManager Registry
The DataLayerManager class (src/data/manager.js#L18-L27) maintains a central registry (this.layers) storing layer entries with metadata including module, enabled, and initialized states. This registry serializes visibility changes and manages the deterministic lifecycle of each overlay.
Layer Module Interface
Individual data sources such as src/data/traffic.js and src/data/satellites.js implement a standard interface exposing init(), enable(), update(), disable(), and optionally resolveTrackingRestoreTarget(). When the manager needs to resolve a specific entity, it delegates to the layer module’s implementation.
Visibility Intent System
To guarantee deterministic enable/disable behavior, the manager uses a queued intent system implemented in _setEnabledWithIntent() (src/data/manager.js#L74-L89). This ensures that rapid state changes do not corrupt layer state before queries execute.
The Analytical Query API
The primary method for entity resolution is resolveLayerTrackingTarget() (src/data/manager.js#L438-L452). This function accepts a layerId, targetId (such as an ICAO callsign), and optional abort signals, returning a structured result object containing:
- status:
'found','missing','source-unavailable', or'cancelled' - Cartographic coordinates:
latitude,longitude,altitude - Metadata: Layer-specific entity properties
Before invoking this API, layers must be activated and refreshed to ensure data freshness.
Step-by-Step Query Workflow
Follow this sequence to query live CesiumJS data layers reliably:
-
Obtain the manager instance: Import or access the
DataLayerManagersingleton fromsrc/main.js. -
Enable the target layer: Activate the layer using
setEnabled()(src/data/manager.js#L58-L66):
await dataManager.setEnabled('flights', true);
- Refresh the layer data: Force a fresh update cycle using
refreshLayer()(src/data/manager.js#L91-L99) to guarantee the query sees the latest positions:
await dataManager.refreshLayer('flights');
- Resolve the tracking target: Call
resolveLayerTrackingTarget()with the entity identifier:
const result = await dataManager.resolveLayerTrackingTarget(
'flights',
'ABC123',
{ signal: AbortSignal.timeout(5000) }
);
- Interpret results: Check
result.status. If'found', the payload contains Cesium-compatible cartographic coordinates suitable for camera positioning or UI annotations.
Cesium Integration and Coordinate Systems
The query API returns geographic coordinates that integrate directly with CesiumJS geometric utilities.
Cartographic Conversion
Layer modules and utilities like src/worldFocus.js convert query results into Cesium cartesian positions using Cesium.Cartographic.fromDegrees():
const carto = Cesium.Cartographic.fromDegrees(longitude, latitude, altitude);
Alternatively, for direct camera positioning:
const position = Cesium.Cartesian3.fromDegrees(lon, lat, height);
viewer.camera.setView({ destination: position });
Entity Picking
For ad-hoc spatial queries, Cesium’s native picking API complements the analytical query system:
const picked = viewer.scene.pick(new Cesium.Cartesian2(x, y));
Practical Code Examples
Example 1: Simple Aircraft Lookup
This implementation demonstrates enabling the flights layer, refreshing data, and positioning the camera on the resolved entity:
async function lookupAircraft(callsign) {
// Enable the flights layer
await dataManager.setEnabled('flights', true);
// Force refresh for latest positions (src/data/manager.js#L91-L99)
await dataManager.refreshLayer('flights');
// Resolve the target entity (src/data/manager.js#L438)
const res = await dataManager.resolveLayerTrackingTarget('flights', callsign);
if (res.status === 'found') {
const { latitude, longitude, altitude } = res;
console.log(`Aircraft ${callsign} at ${latitude.toFixed(3)}°, ${longitude.toFixed(3)}°, ${altitude}m`);
// Camera transition to entity using Cesium utilities
viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, altitude + 500)
});
} else {
console.warn(`Lookup failed: ${res.status}`);
}
}
Example 2: Generic Layer Query Wrapper
Create a reusable abstraction for querying any live layer:
async function queryLayer(dm, layerId, entityId) {
// Ensure layer is active (src/data/manager.js#L58-L66)
const enabled = await dm.setEnabled(layerId, true);
if (!enabled) return null;
// Refresh to get freshest data
await dm.refreshLayer(layerId);
// Resolve and normalize result
const result = await dm.resolveLayerTrackingTarget(layerId, entityId);
return result.status === 'found' ? result : null;
}
Example 3: Computing Distance Between Live Entities
Combine multiple queries with Cesium’s geometric utilities:
async function distanceBetween(layerId, idA, idB) {
const a = await queryLayer(dataManager, layerId, idA);
const b = await queryLayer(dataManager, layerId, idB);
if (!a || !b) throw new Error('One or both entities not found');
const posA = Cesium.Cartesian3.fromDegrees(a.longitude, a.latitude, a.altitude);
const posB = Cesium.Cartesian3.fromDegrees(b.longitude, b.latitude, b.altitude);
return Cesium.Cartesian3.distance(posA, posB); // Returns meters
}
Summary
- DataLayerManager (
src/data/manager.js) serves as the central registry and query coordinator for all live CesiumJS data layers. - Analytical queries require three sequential operations:
setEnabled()to activate the layer,refreshLayer()to fetch current data, andresolveLayerTrackingTarget()to retrieve specific entity states. - Query results provide standardized status flags and cartographic coordinates compatible with CesiumJS camera and visualization APIs.
- Layer modules such as
src/data/traffic.jsimplement the entity-specific resolution logic that the manager delegates to during queries. - Coordinate conversion leverages
Cesium.Cartesian3.fromDegrees()to transform query results into 3-D world positions for camera manipulation or spatial analysis.
Frequently Asked Questions
How does DataLayerManager handle layer lifecycle during queries?
The manager implements a deterministic intent system in _setEnabledWithIntent() (src/data/manager.js#L74-L89) that queues visibility changes. This prevents race conditions when rapidly toggling layers or executing queries during initialization, ensuring that resolveLayerTrackingTarget() only runs against fully initialized data sources.
Why must I call refreshLayer before querying?
Live data layers in God’s Eye View operate on periodic update cycles. Calling refreshLayer() (src/data/manager.js#L91-L99) forces an immediate data fetch from the upstream source (such as aviation or satellite APIs), guaranteeing that resolveLayerTrackingTarget() returns the most recent entity position rather than cached or stale coordinates.
What properties does the query result object contain?
According to the implementation at src/data/manager.js#L438-L452, the result object includes a status string ('found', 'missing', 'source-unavailable', or 'cancelled'), geographic coordinates (latitude, longitude, altitude), and layer-specific metadata. When status equals 'found', the coordinates are ready for direct use with Cesium’s Cartesian3.fromDegrees() or Cartographic utilities.
Can I query layers that are not currently visible?
Yes, but you must first enable them. The setEnabled() method (src/data/manager.js#L58-L66) handles the full initialization lifecycle including module loading and first data fetch. Attempting to query a disabled layer will return a 'source-unavailable' status, as implemented in the resolution logic used by the voice assistant module (src/voice/gevRealtime.js).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →