diff --git a/src/layers/flights/motion.js b/src/layers/flights/motion.js index ca7e9fe9d..14c828b54 100644 --- a/src/layers/flights/motion.js +++ b/src/layers/flights/motion.js @@ -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, diff --git a/src/layers/flights/queries.js b/src/layers/flights/queries.js index 5b64b2247..bd47e82cd 100644 --- a/src/layers/flights/queries.js +++ b/src/layers/flights/queries.js @@ -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), }; }, diff --git a/src/layers/flights/snapshotRenderer.js b/src/layers/flights/snapshotRenderer.js index e0c4b202d..c66e9ec3b 100644 --- a/src/layers/flights/snapshotRenderer.js +++ b/src/layers/flights/snapshotRenderer.js @@ -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), diff --git a/src/layers/flights/state.js b/src/layers/flights/state.js index 2978ceba4..f4777d002 100644 --- a/src/layers/flights/state.js +++ b/src/layers/flights/state.js @@ -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 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, ); diff --git a/src/layers/military/queries.js b/src/layers/military/queries.js index 421e9804d..f96b1fed7 100644 --- a/src/layers/military/queries.js +++ b/src/layers/military/queries.js @@ -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), }; }, diff --git a/src/layers/military/snapshotRenderer.js b/src/layers/military/snapshotRenderer.js index 8d1d9392b..c6f55c93e 100644 --- a/src/layers/military/snapshotRenderer.js +++ b/src/layers/military/snapshotRenderer.js @@ -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, }); } diff --git a/src/layers/military/state.js b/src/layers/military/state.js index f1a2d691f..74a5d0cdc 100644 --- a/src/layers/military/state.js +++ b/src/layers/military/state.js @@ -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; }