refactor(flights,military,localAdsb): take vector maths from src/geo

Dead reckoning, the grounded display floor, snapshot rendering, queries and layer scratch state now use src/geo. Outputs are bit-identical to the previous batch (frozen-clock probe over flights, military, local ADS-B and orbits); per-frame paths are as fast as base 132b9e96 or faster (see docs/migration/phase1a-report.md).
This commit is contained in:
German Khokhlov committed 2026-10-15 00:17:56 +04:00
1 parent 2b83606765
commit ee8b94d987
9 files changed
+151 -143

No files matched your search

+36 -35
View File
@@ -1,4 +1,5 @@
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import {
COURSE_HOLD_SPEED_MPS,
lerpAngleDeg,
@@ -95,7 +96,7 @@ export function createMotion({
continue;
info.renderAltitudeM = lifted;
flightState._cullPositions.delete(icao24); // above the ellipsoid now (or floors say otherwise next poll)
const position = Cesium.Cartesian3.fromDegrees(
const position = geo.cartesian3.fromDegrees(
info.rawLon,
info.rawLat,
lifted,
@@ -103,7 +104,7 @@ export function createMotion({
const history = flightState._positionHistory.get(icao24);
const newest = history?.[history.length - 1];
if (newest)
newest.position = Cesium.Cartesian3.clone(position, newest.position);
newest.position = geo.cartesian3.clone(position, newest.position);
const bb = flightState._billboards.get(icao24);
if (bb) bb.position = position;
}
@@ -134,7 +135,7 @@ export function createMotion({
flightState._drSpeedMps < COURSE_HOLD_SPEED_MPS;
flightState._drExtrapolating = false;
return position
? Cesium.Cartesian3.clone(position, result || new Cesium.Cartesian3())
? geo.cartesian3.clone(position, result || geo.cartesian3.create())
: null;
}
const history = flightState._positionHistory.get(icao24);
@@ -146,7 +147,7 @@ export function createMotion({
return null;
}
const out = result || new Cesium.Cartesian3();
const out = result || geo.cartesian3.create();
// Render one poll interval behind real time so we interpolate between
// two KNOWN fixes whenever possible (see RENDER_DELAY_SEC rationale).
const renderTime = Cesium.JulianDate.addSeconds(
@@ -176,7 +177,7 @@ export function createMotion({
// a slow turner's nose advances continuously through the segment instead
// of snapping once per poll. Helicopters always use the reported track
// (rotorcraft chords are noise-dominated at their typical speeds).
const chordLenM = Cesium.Cartesian3.distance(a.position, b.position);
const chordLenM = geo.cartesian3.distance(a.position, b.position);
const segSpeed =
span > 0 ? chordLenM / span : (info && info.velocity) || 0;
const fallbackTrack = (info && info.true_track) || 0;
@@ -193,7 +194,7 @@ export function createMotion({
flightState._drSpeedMps = segSpeed;
flightState._drCourseHold = segSpeed < COURSE_HOLD_SPEED_MPS;
flightState._drExtrapolating = false;
return Cesium.Cartesian3.lerp(a.position, b.position, t, out);
return geo.cartesian3.lerp(a.position, b.position, t, out);
}
}
@@ -274,24 +275,24 @@ export function createMotion({
flightState._drExtrapolating = true;
if (speed === 0 || dt === 0) {
flightState._drCourseDeg = heading;
return Cesium.Cartesian3.clone(fix.position, out);
return geo.cartesian3.clone(fix.position, out);
}
// Constant-rate-turn arc (straight line when turnRateDps ≈ 0) — a plane in a
// standard-rate turn is ~90° of arc wrong per 30 s if extrapolated straight.
arcOffsetEnu(speed, heading, turnRateDps, dt, flightState._scratchArc);
flightState._drCourseDeg = flightState._scratchArc.endCourseDeg;
Cesium.Cartesian3.fromElements(
geo.cartesian3.fromElements(
flightState._scratchArc.east,
flightState._scratchArc.north,
0,
flightState._scratchOffset,
);
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(
const enu = geo.transforms.eastNorthUpToFixedFrame(
fix.position,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchEnu,
);
return Cesium.Matrix4.multiplyByPoint(enu, flightState._scratchOffset, out);
return geo.matrix4.multiplyByPoint(enu, flightState._scratchOffset, out);
}
/**
@@ -320,7 +321,7 @@ export function createMotion({
const camera = flightState._viewer?.camera;
const scene = flightState._viewer?.scene;
if (!camera?.positionWC || !position || !scene) return 28;
const rangeM = Cesium.Cartesian3.distance(camera.positionWC, position);
const rangeM = geo.cartesian3.distance(camera.positionWC, position);
if (parts.rendering._modelOwnsVisual(icao24)) {
const spec = parts.rendering._modelSpec(
flightState.records.data.get(icao24)?.klass,
@@ -398,9 +399,9 @@ export function createMotion({
const speed = (info && info.velocity) || 0;
// Plausible single-frame motion (m): real velocity × frame Δt, ×4 slack + 25 m base.
const plausible = speed * dtSec * 4 + 25;
if (Cesium.Cartesian3.distance(raw, flightState._drPrevRaw) > plausible) {
if (geo.cartesian3.distance(raw, flightState._drPrevRaw) > plausible) {
// Discontinuity — re-anchor so the DISPLAYED position stays continuous, then decay.
Cesium.Cartesian3.subtract(
geo.cartesian3.subtract(
flightState._drPrevDisplay,
raw,
flightState._drCorrection,
@@ -408,19 +409,19 @@ export function createMotion({
flightState._drCorrectionStartMs = nowMs;
}
} else {
Cesium.Cartesian3.fromElements(0, 0, 0, flightState._drCorrection);
geo.cartesian3.fromElements(0, 0, 0, flightState._drCorrection);
flightState._drCorrectionStartMs = nowMs - DR_CORRECTION_MS; // fully decayed
}
const elapsed = nowMs - flightState._drCorrectionStartMs;
const factor =
elapsed >= DR_CORRECTION_MS ? 0 : 1 - elapsed / DR_CORRECTION_MS;
let display = Cesium.Cartesian3.multiplyByScalar(
let display = geo.cartesian3.multiplyByScalar(
flightState._drCorrection,
factor,
flightState._trackedPosHolder,
);
Cesium.Cartesian3.add(raw, display, display);
geo.cartesian3.add(raw, display, display);
// Same display floor the fleet pass applies — otherwise selecting a correctly
// floored grounded billboard swapped it for an unfloored tracked entity and
// dropped the cyan target back under the mesh. Applied HERE, at the single
@@ -439,8 +440,8 @@ export function createMotion({
nowMs,
);
Cesium.Cartesian3.clone(raw, flightState._drPrevRaw);
Cesium.Cartesian3.clone(display, flightState._drPrevDisplay);
geo.cartesian3.clone(raw, flightState._drPrevRaw);
geo.cartesian3.clone(display, flightState._drPrevDisplay);
flightState._drPrevMs = nowMs;
flightState._drReconcileValid = true;
flightState._cachedDRPosition = display;
@@ -530,7 +531,7 @@ export function createMotion({
!parts.rendering._modelOwnsVisual(flightState._trackedIcao)
)
return null;
return Cesium.Matrix4.getTranslation(
return geo.matrix4.getTranslation(
flightState._trackedModel.modelMatrix,
flightState._scratchTrailClip,
);
@@ -767,7 +768,7 @@ export function createMotion({
state.probeMs = null; // re-ground may probe immediately
state.out = null;
state.effectiveM = null;
Cesium.Cartesian3.clone(Cesium.Cartesian3.ZERO, state.in); // invalidate the memo
geo.cartesian3.clone(geo.cartesian3.ZERO, state.in); // invalidate the memo
} else if (_seedExpired(state, nowMs)) {
flightState._displayFloorState.delete(icao24); // airborne long enough to be anywhere
}
@@ -832,22 +833,22 @@ export function createMotion({
return pos;
}
const state = flightState._displayFloorState.get(icao24);
const carto = Cesium.Cartographic.fromCartesian(
const carto = geo.cartographic.fromCartesian(
pos,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchDisplayCarto,
);
// Boundary hysteresis: a position jittering across a cell edge would flip
// floors at fleet-tick rate (see stickyFloorCell).
const cell = stickyFloorCell(
Cesium.Math.toDegrees(carto.latitude),
Cesium.Math.toDegrees(carto.longitude),
geo.math.toDegrees(carto.latitude),
geo.math.toDegrees(carto.longitude),
state?.cell,
);
const floor = cachedGroundFloor(cell.lat, cell.lon);
const next = state || {
cell,
in: new Cesium.Cartesian3(),
in: geo.cartesian3.create(),
out: null,
effectiveM: null,
heldM: null,
@@ -943,25 +944,25 @@ export function createMotion({
if (
state &&
state.effectiveM === effective &&
Cesium.Cartesian3.equals(pos, state.in)
geo.cartesian3.equals(pos, state.in)
) {
return state.out || pos;
}
const lifted = displayFloorHeightM(carto.height, effective);
next.cell = cell;
next.effectiveM = effective;
Cesium.Cartesian3.clone(pos, next.in);
geo.cartesian3.clone(pos, next.in);
if (lifted == null) {
next.out = null;
} else {
// The cache OWNS its output: returning a shared scratch would let the next
// contact in the fleet loop overwrite a position already handed out.
next.out = Cesium.Cartesian3.fromRadians(
next.out = geo.cartesian3.fromRadians(
carto.longitude,
carto.latitude,
lifted,
Cesium.Ellipsoid.WGS84,
next.out || new Cesium.Cartesian3(),
geo.ellipsoid.WGS84,
next.out || geo.cartesian3.create(),
);
}
if (!state) flightState._displayFloorState.set(icao24, next);
@@ -1044,13 +1045,13 @@ export function createMotion({
flightState._drCourseDeg != null
? flightState._drCourseDeg
: info.true_track || 0;
const c = Cesium.Cartographic.fromCartesian(
const c = geo.cartographic.fromCartesian(
dr,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchCorridorCarto,
);
const lat = Cesium.Math.toDegrees(c.latitude);
const lon = Cesium.Math.toDegrees(c.longitude);
const lat = geo.math.toDegrees(c.latitude);
const lon = geo.math.toDegrees(c.longitude);
const cells = corridorFloorCells(
corridorPathLatLon({
extrapolating,
+14 -13
View File
@@ -1,6 +1,7 @@
import { approxDistanceKm as _approxDistanceKm } from './recordPolicy.js';
import { displayedKinematics } from '../../data/motionModel.js';
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { isExplicitLayerStateOrigin } from '../../data/layerState.js';
import { modelVisualAnchor } from '../../data/modelVisualAnchor.js';
import {
@@ -141,18 +142,18 @@ export function createQueries({
reportedSpeedMps: info?.velocity,
reportedTrackDeg: info?.true_track,
});
const carto = Cesium.Cartographic.fromCartesian(
const carto = geo.cartographic.fromCartesian(
basePos,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchCarto,
);
if (!carto) return null;
return {
icao24,
callsign: String(info?.callsign || '').trim() || null,
position: Cesium.Cartesian3.clone(basePos),
latitude: Cesium.Math.toDegrees(carto.latitude),
longitude: Cesium.Math.toDegrees(carto.longitude),
position: geo.cartesian3.clone(basePos),
latitude: geo.math.toDegrees(carto.latitude),
longitude: geo.math.toDegrees(carto.longitude),
// The cockpit instrument reports aviation altitude, not the Cesium
// ellipsoid height of the camera/ground-clamped render position. The
// latter can be slightly negative over terrain near the surface.
@@ -430,7 +431,7 @@ export function createQueries({
object = {
sourceId: icao24,
type: 'AIR',
_weldPos: new Cesium.Cartesian3(),
_weldPos: geo.cartesian3.create(),
};
flightState._detectionObjects.set(icao24, object);
}
@@ -453,7 +454,7 @@ export function createQueries({
Number.isFinite(model.computedScale)
? model.computedScale
: spec.scale,
object._weldPos || (object._weldPos = new Cesium.Cartesian3()),
object._weldPos || (object._weldPos = geo.cartesian3.create()),
)
: bb.position;
if (!pos) continue;
@@ -572,7 +573,7 @@ export function createQueries({
const pos = trackedPos || bb.position;
if (!pos) continue;
const distance = Cesium.Cartesian3.distance(center, pos);
const distance = geo.cartesian3.distance(center, pos);
if (distance > maxRange) continue;
const info = flightState.records.data.get(icao24);
@@ -653,9 +654,9 @@ export function createQueries({
for (const [icao24, bb] of flightState._billboards) {
const pos = bb.position;
if (!pos) continue;
const carto = Cesium.Cartographic.fromCartesian(
const carto = geo.cartographic.fromCartesian(
pos,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchCarto,
);
if (!carto) continue;
@@ -664,8 +665,8 @@ export function createQueries({
id: icao24, // identity (trackById resolves this)
label: _contactLabel(icao24, info),
position: pos,
latitude: Cesium.Math.toDegrees(carto.latitude),
longitude: Cesium.Math.toDegrees(carto.longitude),
latitude: geo.math.toDegrees(carto.latitude),
longitude: geo.math.toDegrees(carto.longitude),
altitudeM: carto.height,
airline: info?.airline ?? null,
typeName: info?.typeName ?? null,
@@ -864,7 +865,7 @@ export function createQueries({
described.callsign ||
_toCleanText(described.registration) ||
described.icao24,
position: Cesium.Cartesian3.clone(described.position),
position: geo.cartesian3.clone(described.position),
};
},
+10 -9
View File
@@ -1,4 +1,5 @@
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { cyberSonarBaseAlpha } from '../../cyberSonar.js';
import {
turnRateFromFixHistory,
@@ -33,10 +34,10 @@ export function createFlightSnapshotRenderer({
const viewerCarto =
(viewer || flightState._viewer)?.camera?.positionCartographic || null;
const viewerLatDeg = viewerCarto
? Cesium.Math.toDegrees(viewerCarto.latitude)
? geo.math.toDegrees(viewerCarto.latitude)
: null;
const viewerLonDeg = viewerCarto
? Cesium.Math.toDegrees(viewerCarto.longitude)
? geo.math.toDegrees(viewerCarto.longitude)
: null;
const floorWarmPoints = [];
@@ -76,7 +77,7 @@ export function createFlightSnapshotRenderer({
floorWarmPoints,
},
);
const position = Cesium.Cartesian3.fromDegrees(
const position = geo.cartesian3.fromDegrees(
meta.rawLon,
meta.rawLat,
meta.renderAltitudeM,
@@ -86,7 +87,7 @@ export function createFlightSnapshotRenderer({
flightState._cullPositions.set(
icao24,
meta.renderAltitudeM < 10
? Cesium.Cartesian3.fromDegrees(meta.rawLon, meta.rawLat, 12)
? geo.cartesian3.fromDegrees(meta.rawLon, meta.rawLat, 12)
: null,
);
const isTracked = icao24 === flightState._trackedIcao;
@@ -109,7 +110,7 @@ export function createFlightSnapshotRenderer({
history.push({
time: fixTime,
epochMs: fixEpochMs,
position: position.clone(),
position: geo.cartesian3.clone(position),
velocity: meta.velocity,
track: meta.true_track,
});
@@ -125,7 +126,7 @@ export function createFlightSnapshotRenderer({
// Round 2 (owner): ground traffic appends too — taxi history stays
// live after touchdown (grounded flights positions are already
// surface-clamped via the surfaceM chain, so the ground leg drapes).
if (isTracked) tracking._appendTrailFix(position.clone());
if (isTracked) tracking._appendTrailFix(geo.cartesian3.clone(position));
} else {
const modelOwnsGroundVisual = rendering._modelOwnsVisual(icao24);
if (!modelOwnsGroundVisual) {
@@ -149,7 +150,7 @@ export function createFlightSnapshotRenderer({
meta.turnRateDps = turnRateFromFixHistory(history);
if (isTracked)
tracking._appendTrailFix(
Cesium.Cartesian3.clone(synthetic.position),
geo.cartesian3.clone(synthetic.position),
);
}
}
@@ -188,7 +189,7 @@ export function createFlightSnapshotRenderer({
// lifted onto the floor under that delayed position. Creating it at
// the raw fix drew it ahead until the next fleet tick snapped it back;
// skipping the floor started a taxiing contact low and then raised it.
const delayed = motion._deadReckon(icao24, new Cesium.Cartesian3());
const delayed = motion._deadReckon(icao24, geo.cartesian3.create());
const displayed =
(delayed &&
motion._floorGroundedDisplayPosition(
@@ -206,7 +207,7 @@ export function createFlightSnapshotRenderer({
scale: rendering._fleetBillboardScale(icao24, meta.klass),
// Screen-projected rotation lands on the next fleet tick.
rotation: 0,
alignedAxis: Cesium.Cartesian3.ZERO,
alignedAxis: geo.cartesian3.ZERO,
color: isTracked
? Cesium.Color.CYAN
: rendering._fleetBillboardColor(icao24),
+22 -21
View File
@@ -1,6 +1,7 @@
import { FlightRecords } from './records.js';
import { createFlightFeed } from './ingestion.js';
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { ENRICH_AMBIENT_BUDGET_CEIL } from './policy.js';
export function createFlightState({ source, services }) {
@@ -31,9 +32,9 @@ export function createFlightState({ source, services }) {
flightState._groundSnap = createGroundSnap();
flightState._scratchGroundCarto = new Cesium.Cartographic();
flightState._scratchGroundCarto = geo.cartographic.create();
flightState._scratchGroundPos = new Cesium.Cartesian3();
flightState._scratchGroundPos = geo.cartesian3.create();
/** @type {Cesium.PrimitiveCollection|null} */
@@ -84,10 +85,10 @@ export function createFlightState({ source, services }) {
flightState._scratchModelHpr = new Cesium.HeadingPitchRoll(0, 0, 0);
flightState._scratchModelMtx = new Cesium.Matrix4();
flightState._scratchModelMtx = geo.matrix4.create();
flightState._scratchModelBS = new Cesium.BoundingSphere(
new Cesium.Cartesian3(),
geo.cartesian3.create(),
1.0,
);
// frustum-visibility test
@@ -238,25 +239,25 @@ export function createFlightState({ source, services }) {
// Scratch (reusable) variables — avoid per-frame heap allocation
// ---------------------------------------------------------------------------
flightState._scratchOffset = new Cesium.Cartesian3();
flightState._scratchOffset = geo.cartesian3.create();
flightState._scratchCarto = new Cesium.Cartographic();
flightState._scratchCarto = geo.cartographic.create();
flightState._scratchEnu = new Cesium.Matrix4();
flightState._scratchEnu = geo.matrix4.create();
flightState._scratchArc = { east: 0, north: 0, endCourseDeg: 0 };
flightState._scratchRenderTime = new Cesium.JulianDate();
flightState._scratchFleetPos = new Cesium.Cartesian3();
flightState._scratchFleetPos = geo.cartesian3.create();
flightState._scratchSonarScreen = new Cesium.Cartesian2();
flightState._scratchSonarScreen = geo.cartesian2.create();
flightState._scratchDrRaw = new Cesium.Cartesian3();
flightState._scratchDrRaw = geo.cartesian3.create();
flightState._scratchWarmupTime = new Cesium.JulianDate();
flightState._trackedPosHolder = new Cesium.Cartesian3();
flightState._trackedPosHolder = geo.cartesian3.create();
// ---------------------------------------------------------------------------
// Per-frame cache for the tracked entity's dead-reckoned position.
@@ -341,13 +342,13 @@ export function createFlightState({ source, services }) {
flightState._enrichAmbientRefillAnchorMs = 0;
flightState._drCorrection = new Cesium.Cartesian3(0, 0, 0);
flightState._drCorrection = geo.cartesian3.create(0, 0, 0);
flightState._drCorrectionStartMs = 0;
flightState._drPrevRaw = new Cesium.Cartesian3();
flightState._drPrevRaw = geo.cartesian3.create();
flightState._drPrevDisplay = new Cesium.Cartesian3();
flightState._drPrevDisplay = geo.cartesian3.create();
flightState._drPrevMs = 0;
@@ -359,18 +360,18 @@ export function createFlightState({ source, services }) {
/** @type {Cesium.Cartesian3} Scratch for the tracked model's rendered translation. */
flightState._trackedVisualPos = new Cesium.Cartesian3();
flightState._trackedVisualPos = geo.cartesian3.create();
flightState._trackedTrailPos = new Cesium.Cartesian3();
flightState._trackedTrailPos = geo.cartesian3.create();
/** Scratch for the tracked model's world-space origin (the envelope centre). */
flightState._scratchTrailClip = new Cesium.Cartesian3();
flightState._scratchTrailClip = geo.cartesian3.create();
/** Scratch for the shortened trail-head start. Owned by the head-segment
* callback alone, so nothing else can overwrite it mid-frame. */
flightState._scratchTrailHead = new Cesium.Cartesian3();
flightState._scratchTrailHead = geo.cartesian3.create();
/** Hysteresis latch for the tracked contact's zoom regime, plus the selection it
* belongs to. Scoped per selection so a NEW target re-evaluates against the ENTER
@@ -388,7 +389,7 @@ export function createFlightState({ source, services }) {
/** @type {Cesium.Cartographic} Scratch for the grounded display-floor read. */
flightState._scratchDisplayCarto = new Cesium.Cartographic();
flightState._scratchDisplayCarto = geo.cartographic.create();
/** @type {Map<string, {cell: {lat: number, lon: number}, effectiveM: number|null,
* in: Cesium.Cartesian3, out: Cesium.Cartesian3|null, heldM: number|null,
@@ -415,11 +416,11 @@ export function createFlightState({ source, services }) {
/** @type {Cesium.Cartographic} Scratch for the corridor's display-end read. */
flightState._scratchCorridorCarto = new Cesium.Cartographic();
flightState._scratchCorridorCarto = geo.cartographic.create();
/** @type {Cesium.Cartesian3} Scratch for the corridor's dead-reckon probe. */
flightState._scratchCorridorPos = new Cesium.Cartesian3();
flightState._scratchCorridorPos = geo.cartesian3.create();
/** IR hot-target mode (owner playtest 2026-08-16): the NVG/FLIR post-styles
* map LUMINANCE, so mid-gray textured models read cold and vanish into
+5 -5
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import {
COURSE_HOLD_SPEED_MPS,
TURN_MIN_SPEED_MPS,
@@ -38,8 +38,8 @@ const COAST_MAXIMUM_SEC = 60;
const KT_TO_MPS = 1852 / 3600;
const EARTH_RADIUS_M = 6_371_008.8;
const DEG = Math.PI / 180;
const _chordFrom = new Cesium.Cartesian3();
const _chordTo = new Cesium.Cartesian3();
const _chordFrom = geo.cartesian3.create();
const _chordTo = geo.cartesian3.create();
function finite(value) {
return Number.isFinite(value) ? value : null;
@@ -58,8 +58,8 @@ function telemetryTime(record) {
}
function chordCourse(from, to) {
Cesium.Cartesian3.fromDegrees(from.lon, from.lat, 0, undefined, _chordFrom);
Cesium.Cartesian3.fromDegrees(to.lon, to.lat, 0, undefined, _chordTo);
geo.cartesian3.fromDegrees(from.lon, from.lat, 0, undefined, _chordFrom);
geo.cartesian3.fromDegrees(to.lon, to.lat, 0, undefined, _chordTo);
return courseBetweenCartesians(_chordFrom, _chordTo);
}
+18 -17
View File
@@ -1,4 +1,5 @@
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import {
lerpAngleDeg,
speedRamp,
@@ -63,7 +64,7 @@ export function createMotion({
return null;
}
const out = result || new Cesium.Cartesian3();
const out = result || geo.cartesian3.create();
// Render one poll interval behind real time so we interpolate between
// two KNOWN fixes whenever possible (see RENDER_DELAY_SEC rationale).
const renderTime = Cesium.JulianDate.addSeconds(
@@ -93,7 +94,7 @@ export function createMotion({
// a slow turner's nose advances continuously through the segment instead
// of snapping once per poll. Helicopters always use the reported track
// (rotorcraft chords are noise-dominated at their typical speeds).
const chordLenM = Cesium.Cartesian3.distance(a.position, b.position);
const chordLenM = geo.cartesian3.distance(a.position, b.position);
const segSpeed =
span > 0 ? chordLenM / span : (info && info.speedMps) || 0;
const fallbackTrack = (info && info.track) || 0;
@@ -109,7 +110,7 @@ export function createMotion({
: trackCourse;
flightState._drSpeedMps = segSpeed;
flightState._drCourseHold = segSpeed < COURSE_HOLD_SPEED_MPS;
return Cesium.Cartesian3.lerp(a.position, b.position, t, out);
return geo.cartesian3.lerp(a.position, b.position, t, out);
}
}
@@ -181,24 +182,24 @@ export function createMotion({
flightState._drCourseHold = speed < COURSE_HOLD_SPEED_MPS;
if (speed === 0 || dt === 0) {
flightState._drCourseDeg = heading;
return Cesium.Cartesian3.clone(fix.position, out);
return geo.cartesian3.clone(fix.position, out);
}
// Constant-rate-turn arc (straight line when turnRateDps ≈ 0) — a plane in a
// standard-rate turn is ~90° of arc wrong per 30 s if extrapolated straight.
arcOffsetEnu(speed, heading, turnRateDps, dt, flightState._scratchArc);
flightState._drCourseDeg = flightState._scratchArc.endCourseDeg;
Cesium.Cartesian3.fromElements(
geo.cartesian3.fromElements(
flightState._scratchArc.east,
flightState._scratchArc.north,
0,
flightState._scratchOffset,
);
const enu = Cesium.Transforms.eastNorthUpToFixedFrame(
const enu = geo.transforms.eastNorthUpToFixedFrame(
fix.position,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchEnu,
);
return Cesium.Matrix4.multiplyByPoint(enu, flightState._scratchOffset, out);
return geo.matrix4.multiplyByPoint(enu, flightState._scratchOffset, out);
}
/**
@@ -226,7 +227,7 @@ export function createMotion({
const camera = flightState._viewer?.camera;
const scene = flightState._viewer?.scene;
if (!camera?.positionWC || !position || !scene) return 28;
const rangeM = Cesium.Cartesian3.distance(camera.positionWC, position);
const rangeM = geo.cartesian3.distance(camera.positionWC, position);
if (parts.rendering._modelOwnsVisual(icao24)) {
const spec = parts.rendering._modelSpec(
flightState.records.data.get(icao24)?.klass,
@@ -305,9 +306,9 @@ export function createMotion({
const speed = (info && info.speedMps) || 0;
// Plausible single-frame motion (m): real velocity × frame Δt, ×4 slack + 25 m base.
const plausible = speed * dtSec * 4 + 25;
if (Cesium.Cartesian3.distance(raw, flightState._drPrevRaw) > plausible) {
if (geo.cartesian3.distance(raw, flightState._drPrevRaw) > plausible) {
// Discontinuity — re-anchor so the DISPLAYED position stays continuous, then decay.
Cesium.Cartesian3.subtract(
geo.cartesian3.subtract(
flightState._drPrevDisplay,
raw,
flightState._drCorrection,
@@ -315,22 +316,22 @@ export function createMotion({
flightState._drCorrectionStartMs = nowMs;
}
} else {
Cesium.Cartesian3.fromElements(0, 0, 0, flightState._drCorrection);
geo.cartesian3.fromElements(0, 0, 0, flightState._drCorrection);
flightState._drCorrectionStartMs = nowMs - DR_CORRECTION_MS; // fully decayed
}
const elapsed = nowMs - flightState._drCorrectionStartMs;
const factor =
elapsed >= DR_CORRECTION_MS ? 0 : 1 - elapsed / DR_CORRECTION_MS;
const display = Cesium.Cartesian3.multiplyByScalar(
const display = geo.cartesian3.multiplyByScalar(
flightState._drCorrection,
factor,
flightState._trackedPosHolder,
);
Cesium.Cartesian3.add(raw, display, display);
geo.cartesian3.add(raw, display, display);
Cesium.Cartesian3.clone(raw, flightState._drPrevRaw);
Cesium.Cartesian3.clone(display, flightState._drPrevDisplay);
geo.cartesian3.clone(raw, flightState._drPrevRaw);
geo.cartesian3.clone(display, flightState._drPrevDisplay);
flightState._drPrevMs = nowMs;
flightState._drReconcileValid = true;
flightState._cachedDRPosition = display;
@@ -409,7 +410,7 @@ export function createMotion({
!parts.rendering._modelOwnsVisual(flightState._trackedIcao)
)
return null;
return Cesium.Matrix4.getTranslation(
return geo.matrix4.getTranslation(
flightState._trackedModel.modelMatrix,
flightState._scratchTrailClip,
);
+14 -13
View File
@@ -1,5 +1,6 @@
import { displayedKinematics } from '../../data/motionModel.js';
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { isExplicitLayerStateOrigin } from '../../data/layerState.js';
import { aircraftIncludedInNearby } from '../../data/aircraftNearbyPolicy.js';
import { modelVisualAnchor } from '../../data/modelVisualAnchor.js';
@@ -102,9 +103,9 @@ export function createQueries({
reportedSpeedMps: info?.speedMps,
reportedTrackDeg: info?.track,
});
const carto = Cesium.Cartographic.fromCartesian(
const carto = geo.cartographic.fromCartesian(
basePos,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchCarto,
);
if (!carto) return null;
@@ -115,9 +116,9 @@ export function createQueries({
// getTrackedSubject and the voice narration can read it straight off the
// descriptor instead of reaching back into `_flightData`.
registration: _toCleanText(info?.registration) || null,
position: Cesium.Cartesian3.clone(basePos),
latitude: Cesium.Math.toDegrees(carto.latitude),
longitude: Cesium.Math.toDegrees(carto.longitude),
position: geo.cartesian3.clone(basePos),
latitude: geo.math.toDegrees(carto.latitude),
longitude: geo.math.toDegrees(carto.longitude),
// Keep the cockpit readout on the reported aviation altitude. Render
// terrain height is a separate visual datum and may be below zero.
altitudeM: Number.isFinite(info?.altitudeM)
@@ -360,7 +361,7 @@ export function createQueries({
const pos = trackedPos || bb.position;
if (!pos) continue;
const distance = Cesium.Cartesian3.distance(center, pos);
const distance = geo.cartesian3.distance(center, pos);
if (distance > maxRange) continue;
const info = flightState.records.data.get(icao24);
@@ -444,7 +445,7 @@ export function createQueries({
sourceId: icao24,
type: 'AIR',
tier: 'military',
_weldPos: new Cesium.Cartesian3(),
_weldPos: geo.cartesian3.create(),
};
flightState._detectionObjects.set(icao24, object);
}
@@ -464,7 +465,7 @@ export function createQueries({
Number.isFinite(model.computedScale)
? model.computedScale
: spec.scale,
object._weldPos || (object._weldPos = new Cesium.Cartesian3()),
object._weldPos || (object._weldPos = geo.cartesian3.create()),
)
: bb.position;
if (!pos) continue;
@@ -590,9 +591,9 @@ export function createQueries({
for (const [icao24, bb] of flightState._billboards) {
const pos = bb.position;
if (!pos) continue;
const carto = Cesium.Cartographic.fromCartesian(
const carto = geo.cartographic.fromCartesian(
pos,
Cesium.Ellipsoid.WGS84,
geo.ellipsoid.WGS84,
flightState._scratchCarto,
);
if (!carto) continue;
@@ -606,8 +607,8 @@ export function createQueries({
_toCleanText(info?.registration) ||
icao24,
position: pos,
latitude: Cesium.Math.toDegrees(carto.latitude),
longitude: Cesium.Math.toDegrees(carto.longitude),
latitude: geo.math.toDegrees(carto.latitude),
longitude: geo.math.toDegrees(carto.longitude),
altitudeM: carto.height,
});
if (result.length >= limit) break;
@@ -782,7 +783,7 @@ export function createQueries({
// Same label chain as getNearby/getDetectableObjects: a callsign-less
// contact reads as its registration, never as the raw ICAO hex.
label: described.callsign || described.registration || described.icao24,
position: Cesium.Cartesian3.clone(described.position),
position: geo.cartesian3.clone(described.position),
};
},
+12 -11
View File
@@ -1,4 +1,5 @@
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { CLASS_SCALE_2D } from '../../data/aircraftClass.js';
import {
turnRateFromFixHistory,
@@ -52,7 +53,7 @@ export function createMilitarySnapshotRenderer({
: false,
},
);
const position = Cesium.Cartesian3.fromDegrees(
const position = geo.cartesian3.fromDegrees(
meta.rawLon,
meta.rawLat,
meta.renderAltitudeM,
@@ -61,7 +62,7 @@ export function createMilitarySnapshotRenderer({
flightState._cullPositions.set(
icao24,
meta.renderAltitudeM < 10
? Cesium.Cartesian3.fromDegrees(meta.rawLon, meta.rawLat, 12)
? geo.cartesian3.fromDegrees(meta.rawLon, meta.rawLat, 12)
: null,
);
const isTracked = icao24 === flightState._trackedIcao;
@@ -84,7 +85,7 @@ export function createMilitarySnapshotRenderer({
history.push({
time: fixTime,
epochMs: fixEpochMs,
position: position.clone(),
position: geo.cartesian3.clone(position),
velocity: meta.speedMps,
track: meta.track,
});
@@ -99,7 +100,7 @@ export function createMilitarySnapshotRenderer({
// (owner): ground traffic appends too — taxi history stays live
// after touchdown; _appendTrailFix floors grounded positions at
// the surface so the ground leg drapes instead of diving.
if (isTracked) tracking._appendTrailFix(position.clone());
if (isTracked) tracking._appendTrailFix(geo.cartesian3.clone(position));
} else {
const modelOwnsGroundVisual = rendering._modelOwnsVisual(icao24);
if (!modelOwnsGroundVisual) {
@@ -120,7 +121,7 @@ export function createMilitarySnapshotRenderer({
meta.turnRateDps = turnRateFromFixHistory(history);
if (isTracked)
tracking._appendTrailFix(
Cesium.Cartesian3.clone(synthetic.position),
geo.cartesian3.clone(synthetic.position),
);
}
}
@@ -151,7 +152,7 @@ export function createMilitarySnapshotRenderer({
// projected back to that delayed time. Creating it at the raw fix drew
// it ahead until the next fleet tick snapped it back.
const displayed =
motion._deadReckon(icao24, new Cesium.Cartesian3()) || position;
motion._deadReckon(icao24, geo.cartesian3.create()) || position;
const bb = flightState._billboardCollection.add({
position: displayed,
image: aircraftIcon(rendering._iconKind(icao24, meta.klass)),
@@ -163,7 +164,7 @@ export function createMilitarySnapshotRenderer({
(meta.onGround ? GROUND_SCALE : 1),
// Screen-projected rotation lands on the next fleet tick.
rotation: 0,
alignedAxis: Cesium.Cartesian3.ZERO,
alignedAxis: geo.cartesian3.ZERO,
color: isTracked ? TRACKED_ICON_COLOR : MIL_ICON_COLOR,
sizeInMeters: false,
scaleByDistance: rendering._normalBillboardScaleByDistance(),
@@ -217,7 +218,7 @@ export function createMilitarySnapshotRenderer({
continue;
info.renderAltitudeM = lifted;
flightState._cullPositions.delete(icao24);
const liftedPos = Cesium.Cartesian3.fromDegrees(
const liftedPos = geo.cartesian3.fromDegrees(
info.rawLon,
info.rawLat,
lifted,
@@ -225,7 +226,7 @@ export function createMilitarySnapshotRenderer({
const hist = flightState._positionHistory.get(icao24);
const newest = hist?.[hist.length - 1];
if (newest)
newest.position = Cesium.Cartesian3.clone(liftedPos, newest.position);
newest.position = geo.cartesian3.clone(liftedPos, newest.position);
const bbStale = flightState._billboards.get(icao24);
if (bbStale) bbStale.position = liftedPos;
}
@@ -242,10 +243,10 @@ export function createMilitarySnapshotRenderer({
flightState._trackedModel,
].filter(Boolean),
viewerLat: viewerCarto
? Cesium.Math.toDegrees(viewerCarto.latitude)
? geo.math.toDegrees(viewerCarto.latitude)
: undefined,
viewerLon: viewerCarto
? Cesium.Math.toDegrees(viewerCarto.longitude)
? geo.math.toDegrees(viewerCarto.longitude)
: undefined,
});
}
+20 -19
View File
@@ -1,6 +1,7 @@
import { MilitaryFlightRecords } from './records.js';
import { createMilitaryFeed } from './ingestion.js';
import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
export function createFlightState({ source, services }) {
const { createGroundSnap } = services.groundSnap;
@@ -28,9 +29,9 @@ export function createFlightState({ source, services }) {
flightState._groundSnap = createGroundSnap();
flightState._scratchGroundCarto = new Cesium.Cartographic();
flightState._scratchGroundCarto = geo.cartographic.create();
flightState._scratchGroundPos = new Cesium.Cartesian3();
flightState._scratchGroundPos = geo.cartesian3.create();
/** @type {Cesium.PrimitiveCollection|null} */
@@ -81,10 +82,10 @@ export function createFlightState({ source, services }) {
flightState._scratchModelHpr = new Cesium.HeadingPitchRoll(0, 0, 0);
flightState._scratchModelMtx = new Cesium.Matrix4();
flightState._scratchModelMtx = geo.matrix4.create();
flightState._scratchModelBS = new Cesium.BoundingSphere(
new Cesium.Cartesian3(),
geo.cartesian3.create(),
1.0,
);
// frustum-visibility test
@@ -215,25 +216,25 @@ export function createFlightState({ source, services }) {
// -- Scratch variables (reused each frame to avoid GC pressure) --
flightState._scratchOffset = new Cesium.Cartesian3();
flightState._scratchOffset = geo.cartesian3.create();
flightState._scratchCarto = new Cesium.Cartographic();
flightState._scratchCarto = geo.cartographic.create();
flightState._scratchEnu = new Cesium.Matrix4();
flightState._scratchEnu = geo.matrix4.create();
flightState._scratchArc = { east: 0, north: 0, endCourseDeg: 0 };
flightState._scratchRenderTime = new Cesium.JulianDate();
flightState._scratchFleetPos = new Cesium.Cartesian3();
flightState._scratchFleetPos = geo.cartesian3.create();
flightState._scratchSonarScreen = new Cesium.Cartesian2();
flightState._scratchSonarScreen = geo.cartesian2.create();
flightState._scratchDrRaw = new Cesium.Cartesian3();
flightState._scratchDrRaw = geo.cartesian3.create();
flightState._scratchWarmupTime = new Cesium.JulianDate();
flightState._trackedPosHolder = new Cesium.Cartesian3();
flightState._trackedPosHolder = geo.cartesian3.create();
// -- Per-frame dead-reckoning cache for the tracked entity --
/** @type {Cesium.Cartesian3|null} Cached DR position for the current render frame */
@@ -285,13 +286,13 @@ export function createFlightState({ source, services }) {
flightState._displayCourse = new Map();
flightState._drCorrection = new Cesium.Cartesian3(0, 0, 0);
flightState._drCorrection = geo.cartesian3.create(0, 0, 0);
flightState._drCorrectionStartMs = 0;
flightState._drPrevRaw = new Cesium.Cartesian3();
flightState._drPrevRaw = geo.cartesian3.create();
flightState._drPrevDisplay = new Cesium.Cartesian3();
flightState._drPrevDisplay = geo.cartesian3.create();
flightState._drPrevMs = 0;
@@ -303,18 +304,18 @@ export function createFlightState({ source, services }) {
/** @type {Cesium.Cartesian3} Scratch for the tracked model's rendered translation. */
flightState._trackedVisualPos = new Cesium.Cartesian3();
flightState._trackedVisualPos = geo.cartesian3.create();
flightState._trackedTrailPos = new Cesium.Cartesian3();
flightState._trackedTrailPos = geo.cartesian3.create();
/** Scratch for the tracked model's world-space origin (the envelope centre). */
flightState._scratchTrailClip = new Cesium.Cartesian3();
flightState._scratchTrailClip = geo.cartesian3.create();
/** Scratch for the shortened trail-head start. Owned by the head-segment
* callback alone, so nothing else can overwrite it mid-frame. */
flightState._scratchTrailHead = new Cesium.Cartesian3();
flightState._scratchTrailHead = geo.cartesian3.create();
/** Hysteresis latch for the tracked contact's zoom regime, plus the selection it
* belongs to. Scoped per selection so a NEW target re-evaluates against the ENTER
@@ -350,6 +351,6 @@ export function createFlightState({ source, services }) {
/** @type {Cesium.Cartographic} Scratch for _trailFloorPosition (per-frame safe). */
flightState._scratchTrailCarto = new Cesium.Cartographic();
flightState._scratchTrailCarto = geo.cartographic.create();
return flightState;
}