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:

  1. Obtain the manager instance: Import or access the DataLayerManager singleton from src/main.js.

  2. Enable the target layer: Activate the layer using setEnabled() (src/data/manager.js#L58-L66):

await dataManager.setEnabled('flights', true);
  1. 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');
  1. Resolve the tracking target: Call resolveLayerTrackingTarget() with the entity identifier:
const result = await dataManager.resolveLayerTrackingTarget(
  'flights',
  'ABC123',
  { signal: AbortSignal.timeout(5000) }
);
  1. 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, and resolveLayerTrackingTarget() 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.js implement 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →