# CesiumJS Ground-Snap Logic for Aircraft Contacts: Implementation and Caching Strategy

> Implement CesiumJS ground-snap logic for aircraft. Learn how to bridge altitude gaps, cache results by ICAO, and avoid per-frame overhead for grounded models. Read the guide.

- Repository: [Bilawal Sidhu/gods-eye-view](https://github.com/bilawalsidhu/gods-eye-view)
- Tags: implementation
- Published: 2026-08-30

---

**CesiumJS ground-snap logic for aircraft contacts bridges barometric altitude gaps by sampling photorealistic tileset heights once per aircraft, caching results in a Map keyed by ICAO, and applying movement thresholds and exponential back-off to keep models grounded without per-frame overhead.**

The **bilawalsidhu/gods-eye-view** repository implements sophisticated **CesiumJS ground-snap logic for aircraft contacts** to solve the classic problem of aircraft appearing to float or sink under photorealistic terrain. This system provides one-shot height sampling with intelligent caching to ensure 3D models sit precisely on runways and taxiways without draining the render budget.

## Why Ground-Snap Matters for 3D Aircraft Visualization

Barometric altitude reports often read 0 m for parked or taxiing aircraft, creating a disconnect from photorealistic terrain tilesets. Without correction, 3D models either hover above the tarmac or clip through the ground surface. The ground-snap subsystem resolves this by querying the actual mesh elevation and maintaining that reference through movement and state changes.

## Architecture of the Ground-Snap Subsystem

The implementation spans multiple modules with clear separation of concerns.

### Core Caching Logic

In [`src/data/groundSnap.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/groundSnap.js), the `createGroundSnap()` factory returns an object exposing `heightFor()`, `forget()`, and `clear()` methods (lines 58-66). This cache stores sampled heights in a JavaScript `Map` keyed by ICAO hexadecimal strings (lines 67-73).

### Terrain Sampling Integration

The `heightFor()` method calls `viewer.scene.sampleHeight()` only when the private `_tilesReady()` guard confirms the tileset is rendered (lines 45-55). This prevents sampling against incomplete geometry that would return erroneous elevations.

### Flight Layer Consumption

Both civilian and military flight layers instantiate ground-snap caches. In [`src/data/flights.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/flights.js) and [`src/data/militaryFlights.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/militaryFlights.js), each layer creates its own ground-snap instance during initialization (lines 65-66 and 38-40 respectively). The per-tick update loop queries `heightFor()` and hides the 3D model when `null` indicates unreliable terrain data (lines 1685-1693).

## How the Ground-Snap Cache Works

The system employs a multi-state caching strategy to balance accuracy against performance costs.

### Movement Invalidation Thresholds

Cached heights remain valid until the aircraft moves more than **MOVE_INVALIDATE_M = 50 m** from the sample location (lines 52-56). Upon exceeding this threshold, the measurement enters a *held* state rather than immediate discard.

### Hold-Over and Contradiction Detection

Held values persist for up to **HELD_SNAP_MAX_DRIFT_M = 250 m** of cumulative movement, preventing model popping during long taxi operations (lines 60-73). However, if a fresh `sampleHeight` call returns a value more than **HELD_SNAP_CONTRADICTION_M = 5 m** above the held measurement, the system drops the hold and marks the contact as *cold*, triggering a fresh sample (lines 78-86).

### Exponential Back-Off for Misses

When `sampleHeight` fails or tiles are unavailable, the system implements exponential back-off starting at **RETRY_BASE_MS = 2000 ms** and capping at **RETRY_MAX_MS = 30000 ms** (lines 124-132). This protects the tile server from flood requests during OSM fallback scenarios or rapid camera movements.

## Implementation Walkthrough

The following pattern demonstrates integration within a flight update loop:

```javascript
import { createGroundSnap } from './groundSnap.js';

// Instantiate per-layer cache
const groundSnap = createGroundSnap();

function updateAircraftPosition(viewer, icao, position, exclusions) {
  // Query cached or fresh terrain height
  const heightM = groundSnap.heightFor(viewer, icao, position, exclusions);
  
  if (heightM === null) {
    // No reliable ground data: hide depth-tested model
    return null;
  }
  
  // Place model at terrain height above ellipsoid
  return Cesium.Cartesian3.fromRadians(
    position.longitude,
    position.latitude,
    heightM
  );
}

// Cleanup when aircraft departs
groundSnap.forget(icao);

```

This code appears in production at [`src/data/flights.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/flights.js) line 1685 and [`src/data/militaryFlights.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/militaryFlights.js) line 1456.

## Performance Budgeting

To maintain frame rate stability during airport-scale bursts, the system enforces **SAMPLE_BUDGET_PER_WINDOW = 4** calls per 250 ms window (lines 29-33). This throttled sampling prevents fifty simultaneous aircraft arrivals from overwhelming the Cesium render thread.

## Summary

- **One-shot sampling** via `heightFor()` eliminates per-frame terrain queries, preserving render performance.
- **ICAO-keyed caching** in [`src/data/groundSnap.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/groundSnap.js) stores elevations in a `Map` with 50 m movement invalidation.
- **Hold-over logic** maintains the last known good height for up to 250 m of taxi movement.
- **Contradiction detection** at 5 m thresholds triggers cache invalidation when terrain geometry updates.
- **Exponential back-off** from 2 s to 30 s prevents server flooding during tile load failures.

## Frequently Asked Questions

### How does the ground-snap system handle aircraft that are taxiing long distances?

When an aircraft exceeds the **MOVE_INVALIDATE_M = 50 m** threshold, the cached height enters a held state rather than immediate eviction. The system continues serving this held value for up to **HELD_SNAP_MAX_DRIFT_M = 250 m** of total movement, preventing visual popping during extended taxi operations across large airports.

### What happens when the photorealistic tileset hasn't finished loading?

The `heightFor()` method checks a private `_tilesReady()` guard before calling `viewer.scene.sampleHeight()` (lines 45-55). If tiles are unavailable, the method returns `null`, causing the flight layer to hide the 3D model temporarily. Failed samples trigger exponential back-off starting at 2000 ms to avoid hammering the tile server.

### Why cache by ICAO instead of position coordinates?

ICAO hexadecimal strings provide stable identifiers for specific aircraft across multiple frames and position updates. This allows the system to track per-aircraft movement deltas and apply the 50 m invalidation threshold correctly, whereas position-based caching would fail to correlate samples as aircraft drift between grid cells.

### How does groundFloor.js interact with the ground-snap mechanism?

[`src/data/groundFloor.js`](https://github.com/bilawalsidhu/gods-eye-view/blob/main/src/data/groundFloor.js) provides cached mesh-floor cells for fast validation lookups. The `groundSnap` module validates measurements against `meshFloorPreferred()` to confirm whether a fresh sample or held value aligns with the preferred terrain representation (lines 50-51), ensuring consistency across the visualization stack.