refactor(vessels,satellites,awareness): take vector maths from src/geo

Moves the Cartesian3/Cartographic/Matrix3/Matrix4/Math calls of the vessel, satellite and Contacts (awareness) layers, plus flights controller/enrichment, to src/geo. The satellites-layer package boundary now owns the src/geo modules. Awareness keeps Cesium.Cartesian3.clone for the resolved subject position, which reaches the installations anchor (anchor.test pins a Cesium instance).
This commit is contained in:
German Khokhlov committed 2026-10-15 00:17:17 +04:00
1 parent 1a69368ae6
commit 2b83606765
15 files changed
+97 -86

No files matched your search

+15 -1
View File
@@ -1104,7 +1104,21 @@
"src/layers/satellites/state.js", "src/layers/satellites/state.js",
"src/layers/satellites/testing.js", "src/layers/satellites/testing.js",
"src/layers/satellites/tracking.js", "src/layers/satellites/tracking.js",
"src/data/inputOwnership.js" "src/data/inputOwnership.js",
"src/geo/index.js",
"src/geo/math.js",
"src/geo/ellipsoid.js",
"src/geo/cartographic.js",
"src/geo/cartesian2.js",
"src/geo/cartesian3.js",
"src/geo/matrix3.js",
"src/geo/matrix4.js",
"src/geo/quaternion.js",
"src/geo/transforms.js",
"src/geo/scaleToGeodeticSurface.js",
"src/geo/check.js",
"src/geo/debug.js",
"src/geo/developerError.js"
], ],
"external": ["cesium", "satellite.js"] "external": ["cesium", "satellite.js"]
}, },
+3 -2
View File
@@ -1,4 +1,5 @@
import * as Cesium from 'cesium'; import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { VESSEL_FOCUS_RADIUS_M } from './policy.js'; import { VESSEL_FOCUS_RADIUS_M } from './policy.js';
export function createFocus({ state: layerState, services, parts, source }) { export function createFocus({ state: layerState, services, parts, source }) {
@@ -74,7 +75,7 @@ export function createFocus({ state: layerState, services, parts, source }) {
layerId, layerId,
id: String(known.id || known.mmsi), id: String(known.id || known.mmsi),
label: known.label || known.name || known.callsign || String(id), label: known.label || known.name || known.callsign || String(id),
position: Cesium.Cartesian3.clone(known.position), position: geo.cartesian3.clone(known.position),
}); });
return true; return true;
} }
@@ -120,7 +121,7 @@ export function createFocus({ state: layerState, services, parts, source }) {
let closestDistance = Infinity; let closestDistance = Infinity;
for (const candidate of candidates) { for (const candidate of candidates) {
if (!candidate?.position) continue; if (!candidate?.position) continue;
const distance = Cesium.Cartesian3.distance( const distance = geo.cartesian3.distance(
cameraPosition, cameraPosition,
candidate.position, candidate.position,
); );
+20 -20
View File
@@ -1,4 +1,5 @@
import * as Cesium from 'cesium'; import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { import {
createCyberSonarSampler, createCyberSonarSampler,
isCyberContactSonarActive as isCyberSonarActive, isCyberContactSonarActive as isCyberSonarActive,
@@ -132,7 +133,7 @@ export function createRendering({
const cameraHeading = layerState.viewer.camera.heading || 0; const cameraHeading = layerState.viewer.camera.heading || 0;
const headingDeg = const headingDeg =
(Math.round(Cesium.Math.toDegrees(cameraHeading)) + 360) % 360; (Math.round(geo.math.toDegrees(cameraHeading)) + 360) % 360;
layerState.compassRing.style.setProperty( layerState.compassRing.style.setProperty(
'--compass-rotation', '--compass-rotation',
`${-headingDeg}deg`, `${-headingDeg}deg`,
@@ -141,8 +142,8 @@ export function createRendering({
layerState.compassHeading.style.left = `${geometry.centerX}px`; layerState.compassHeading.style.left = `${geometry.centerX}px`;
layerState.compassHeading.style.top = `${geometry.centerY - compassRadius + 39}px`; layerState.compassHeading.style.top = `${geometry.centerY - compassRadius + 39}px`;
for (const label of layerState.compassLabels) { for (const label of layerState.compassLabels) {
const bearing = Cesium.Math.toRadians(Number(label.dataset.bearing)); const bearing = geo.math.toRadians(Number(label.dataset.bearing));
const angle = bearing - cameraHeading - Cesium.Math.PI_OVER_TWO; const angle = bearing - cameraHeading - geo.math.PI_OVER_TWO;
const labelRadius = compassRadius - 17; const labelRadius = compassRadius - 17;
label.style.left = `${geometry.centerX + Math.cos(angle) * labelRadius}px`; label.style.left = `${geometry.centerX + Math.cos(angle) * labelRadius}px`;
label.style.top = `${geometry.centerY + Math.sin(angle) * labelRadius}px`; label.style.top = `${geometry.centerY + Math.sin(angle) * labelRadius}px`;
@@ -166,19 +167,19 @@ export function createRendering({
marker.hidden = true; marker.hidden = true;
continue; continue;
} }
const direction = Cesium.Cartesian3.subtract( const direction = geo.cartesian3.subtract(
item.position, item.position,
layerState.subject.position, layerState.subject.position,
layerState.DIRECTION_SCRATCH[index], layerState.DIRECTION_SCRATCH[index],
); );
if (Cesium.Cartesian3.magnitudeSquared(direction) < 1) { if (geo.cartesian3.magnitudeSquared(direction) < 1) {
marker.hidden = true; marker.hidden = true;
continue; continue;
} }
Cesium.Cartesian3.normalize(direction, direction); geo.cartesian3.normalize(direction, direction);
const projection = celestialScreenAngle( const projection = celestialScreenAngle(
Cesium.Cartesian3.dot(direction, layerState.viewer.camera.rightWC), geo.cartesian3.dot(direction, layerState.viewer.camera.rightWC),
Cesium.Cartesian3.dot(direction, layerState.viewer.camera.upWC), geo.cartesian3.dot(direction, layerState.viewer.camera.upWC),
marker._lastAngle, marker._lastAngle,
); );
if (projection.stable) marker._lastAngle = projection.angle; if (projection.stable) marker._lastAngle = projection.angle;
@@ -201,12 +202,12 @@ export function createRendering({
marker._arrow.style.transform = `translate(-50%, -50%) rotate(${projection.angle}rad)`; marker._arrow.style.transform = `translate(-50%, -50%) rotate(${projection.angle}rad)`;
marker._label.style.transform = `translate(-50%, -50%) translate(${-Math.cos(projection.angle) * 56}px, ${-Math.sin(projection.angle) * 56}px)`; marker._label.style.transform = `translate(-50%, -50%) translate(${-Math.cos(projection.angle) * 56}px, ${-Math.sin(projection.angle) * 56}px)`;
const label = formatAwarenessLabel(item); const label = formatAwarenessLabel(item);
const subjectCartographic = Cesium.Cartographic.fromCartesian( const subjectCartographic = geo.cartographic.fromCartesian(
layerState.subject.position, layerState.subject.position,
undefined, undefined,
layerState.SUBJECT_CARTOGRAPHIC_SCRATCH, layerState.SUBJECT_CARTOGRAPHIC_SCRATCH,
); );
const targetCartographic = Cesium.Cartographic.fromCartesian( const targetCartographic = geo.cartographic.fromCartesian(
item.position, item.position,
undefined, undefined,
layerState.TARGET_CARTOGRAPHIC_SCRATCH[index], layerState.TARGET_CARTOGRAPHIC_SCRATCH[index],
@@ -214,10 +215,10 @@ export function createRendering({
const bearing = const bearing =
subjectCartographic && targetCartographic subjectCartographic && targetCartographic
? bearingBetweenCoordinates( ? bearingBetweenCoordinates(
Cesium.Math.toDegrees(subjectCartographic.latitude), geo.math.toDegrees(subjectCartographic.latitude),
Cesium.Math.toDegrees(subjectCartographic.longitude), geo.math.toDegrees(subjectCartographic.longitude),
Cesium.Math.toDegrees(targetCartographic.latitude), geo.math.toDegrees(targetCartographic.latitude),
Cesium.Math.toDegrees(targetCartographic.longitude), geo.math.toDegrees(targetCartographic.longitude),
) )
: null; : null;
const bearingText = Number.isFinite(bearing) const bearingText = Number.isFinite(bearing)
@@ -243,9 +244,9 @@ export function createRendering({
function renderVisual(subject) { function renderVisual(subject) {
if (!layerState.viewer || !subject?.position) return; if (!layerState.viewer || !subject?.position) return;
const cartographic = Cesium.Cartographic.fromCartesian(subject.position); const cartographic = geo.cartographic.fromCartesian(subject.position);
if (!cartographic) return; if (!cartographic) return;
const groundCenter = Cesium.Cartesian3.fromRadians( const groundCenter = geo.cartesian3.fromRadians(
cartographic.longitude, cartographic.longitude,
cartographic.latitude, cartographic.latitude,
0, 0,
@@ -256,12 +257,11 @@ export function createRendering({
// Move it only after a meaningful displacement so live tracking does not // Move it only after a meaningful displacement so live tracking does not
// churn ten large geometries for sub-pixel motion every 750 ms. // churn ten large geometries for sub-pixel motion every 750 ms.
if ( if (
Cesium.Cartesian3.distance(layerState.visual.center, groundCenter) >= geo.cartesian3.distance(layerState.visual.center, groundCenter) >= 250
250
) { ) {
for (const entity of layerState.visual.entities) for (const entity of layerState.visual.entities)
entity.position.setValue(groundCenter); entity.position.setValue(groundCenter);
Cesium.Cartesian3.clone(groundCenter, layerState.visual.center); geo.cartesian3.clone(groundCenter, layerState.visual.center);
// Content actually changed — buy exactly one frame instead of holding. // Content actually changed — buy exactly one frame instead of holding.
governorRequestRender('awareness-visual'); governorRequestRender('awareness-visual');
} }
@@ -289,7 +289,7 @@ export function createRendering({
layerState.visual = { layerState.visual = {
key, key,
entities, entities,
center: Cesium.Cartesian3.clone(groundCenter), center: geo.cartesian3.clone(groundCenter),
}; };
governorRequestRender('awareness-visual'); governorRequestRender('awareness-visual');
} }
+6 -8
View File
@@ -1,18 +1,16 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
export function createState({ services }) { export function createState({ services }) {
const state = {}; const state = {};
state.DIRECTION_SCRATCH = Array.from( state.DIRECTION_SCRATCH = Array.from({ length: 3 }, () =>
{ length: 3 }, geo.cartesian3.create(),
() => new Cesium.Cartesian3(),
); );
state.SUBJECT_CARTOGRAPHIC_SCRATCH = new Cesium.Cartographic(); state.SUBJECT_CARTOGRAPHIC_SCRATCH = geo.cartographic.create();
state.TARGET_CARTOGRAPHIC_SCRATCH = Array.from( state.TARGET_CARTOGRAPHIC_SCRATCH = Array.from({ length: 3 }, () =>
{ length: 3 }, geo.cartographic.create(),
() => new Cesium.Cartographic(),
); );
Object.assign(state, { Object.assign(state, {
+5 -4
View File
@@ -3,6 +3,7 @@ import {
AWARENESS_RELATIONSHIP, AWARENESS_RELATIONSHIP,
} from '../../data/militaryAwarenessEngine.js'; } from '../../data/militaryAwarenessEngine.js';
import * as Cesium from 'cesium'; import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { import {
AWARENESS_QUERY_LIMIT, AWARENESS_QUERY_LIMIT,
SOURCE_LABEL, SOURCE_LABEL,
@@ -218,7 +219,7 @@ export function createSubject({ state: layerState, services, parts, source }) {
subject, subject,
parts.history.historySourceItem(subject), parts.history.historySourceItem(subject),
), ),
position: Cesium.Cartesian3.clone(subject.position), position: geo.cartesian3.clone(subject.position),
}); });
layerState.navigationIndex = layerState.navigationHistory.length - 1; layerState.navigationIndex = layerState.navigationHistory.length - 1;
} }
@@ -389,7 +390,7 @@ export function createSubject({ state: layerState, services, parts, source }) {
const labelChanged = nextLabel !== layerState.subject.label; const labelChanged = nextLabel !== layerState.subject.label;
layerState.subject = { ...layerState.subject, position, label: nextLabel }; layerState.subject = { ...layerState.subject, position, label: nextLabel };
const movementM = layerState.lastEvaluatedPosition const movementM = layerState.lastEvaluatedPosition
? Cesium.Cartesian3.distance(layerState.lastEvaluatedPosition, position) ? geo.cartesian3.distance(layerState.lastEvaluatedPosition, position)
: Infinity; : Infinity;
if ( if (
!parts.model.awarenessRefreshRequired({ !parts.model.awarenessRefreshRequired({
@@ -413,7 +414,7 @@ export function createSubject({ state: layerState, services, parts, source }) {
} }
layerState.results = evaluateSubject(layerState.subject, sources); layerState.results = evaluateSubject(layerState.subject, sources);
layerState.sourceRevision = nextSourceRevision; layerState.sourceRevision = nextSourceRevision;
layerState.lastEvaluatedPosition = Cesium.Cartesian3.clone( layerState.lastEvaluatedPosition = geo.cartesian3.clone(
position, position,
layerState.lastEvaluatedPosition, layerState.lastEvaluatedPosition,
); );
@@ -448,7 +449,7 @@ export function createSubject({ state: layerState, services, parts, source }) {
id: record.properties?.mmsi || record.id, id: record.properties?.mmsi || record.id,
label: record.label || record.id, label: record.label || record.id,
memberNames: record.properties?.memberNames || [], memberNames: record.properties?.memberNames || [],
position: Cesium.Cartesian3.fromDegrees(longitude, latitude, 0), position: geo.cartesian3.fromDegrees(longitude, latitude, 0),
}; };
} }
+3 -3
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
export function createController({ export function createController({
flightState, flightState,
@@ -17,8 +17,8 @@ export function createController({
const cartographic = viewer?.camera?.positionCartographic; const cartographic = viewer?.camera?.positionCartographic;
return cartographic return cartographic
? { ? {
latitude: Cesium.Math.toDegrees(cartographic.latitude), latitude: geo.math.toDegrees(cartographic.latitude),
longitude: Cesium.Math.toDegrees(cartographic.longitude), longitude: geo.math.toDegrees(cartographic.longitude),
} }
: {}; : {};
} }
+3 -5
View File
@@ -1,6 +1,7 @@
import { classifyAircraft } from '../../data/aircraftClass.js'; import { classifyAircraft } from '../../data/aircraftClass.js';
import { horizonOccluder } from '../../data/iconOrientation.js'; import { horizonOccluder } from '../../data/iconOrientation.js';
import * as Cesium from 'cesium'; import * as Cesium from 'cesium';
import * as geo from '../../geo/index.js';
import { import {
ENRICH_MAX_INFLIGHT, ENRICH_MAX_INFLIGHT,
ENRICH_DISPATCH_GAP_MS, ENRICH_DISPATCH_GAP_MS,
@@ -200,10 +201,7 @@ export function createEnrichment({
if (!/^[0-9a-f]{6}$/i.test(icao24)) continue; // adsbdb keys are 6-char hex only if (!/^[0-9a-f]{6}$/i.test(icao24)) continue; // adsbdb keys are 6-char hex only
if (flightState.records.data.get(icao24)?.onGround) continue; // ground traffic never spends ambient budget (click-to-enrich still works) if (flightState.records.data.get(icao24)?.onGround) continue; // ground traffic never spends ambient budget (click-to-enrich still works)
if (!bb.position || !occluder.isPointVisible(bb.position)) continue; // beyond the limb if (!bb.position || !occluder.isPointVisible(bb.position)) continue; // beyond the limb
Cesium.Cartesian3.clone( geo.cartesian3.clone(bb.position, flightState._scratchModelBS.center);
bb.position,
flightState._scratchModelBS.center,
);
if ( if (
cull.computeVisibility(flightState._scratchModelBS) === cull.computeVisibility(flightState._scratchModelBS) ===
Cesium.Intersect.OUTSIDE Cesium.Intersect.OUTSIDE
@@ -211,7 +209,7 @@ export function createEnrichment({
continue; // off-screen continue; // off-screen
cand.push([ cand.push([
icao24, icao24,
Cesium.Cartesian3.distanceSquared(camPos, bb.position), geo.cartesian3.distanceSquared(camPos, bb.position),
]); ]);
} }
cand.sort((a, b) => a[1] - b[1]); // nearest first — what the user is looking at resolves first cand.sort((a, b) => a[1] - b[1]); // nearest first — what the user is looking at resolves first
+5 -5
View File
@@ -3,7 +3,7 @@ import {
satelliteClassLabel, satelliteClassLabel,
satelliteClassLegend, satelliteClassLegend,
} from '../../data/satelliteClass.js'; } from '../../data/satelliteClass.js';
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { ISS_NORAD, POINT_STYLES } from './policy.js'; import { ISS_NORAD, POINT_STYLES } from './policy.js';
export function createControls({ state: layerState, services, parts, source }) { export function createControls({ state: layerState, services, parts, source }) {
@@ -195,7 +195,7 @@ export function createControls({ state: layerState, services, parts, source }) {
return { return {
noradId, noradId,
name: sat.name.trim(), name: sat.name.trim(),
position: Cesium.Cartesian3.fromDegrees( position: geo.cartesian3.fromDegrees(
pos.longitude, pos.longitude,
pos.latitude, pos.latitude,
pos.altitude, pos.altitude,
@@ -227,15 +227,15 @@ export function createControls({ state: layerState, services, parts, source }) {
layerState._catalog.get(noradId)?.group === 'dense' layerState._catalog.get(noradId)?.group === 'dense'
) )
continue; continue;
const carto = Cesium.Cartographic.fromCartesian(point.position); const carto = geo.cartographic.fromCartesian(point.position);
if (!carto) continue; if (!carto) continue;
const sat = layerState._catalog.get(noradId); const sat = layerState._catalog.get(noradId);
result.push({ result.push({
id: noradId, id: noradId,
label: sat ? sat.name.trim() : String(noradId), label: sat ? sat.name.trim() : String(noradId),
position: point.position, position: point.position,
latitude: Cesium.Math.toDegrees(carto.latitude), latitude: geo.math.toDegrees(carto.latitude),
longitude: Cesium.Math.toDegrees(carto.longitude), longitude: geo.math.toDegrees(carto.longitude),
altitudeM: carto.height, altitudeM: carto.height,
}); });
} }
+14 -14
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { import {
gstime, gstime,
propagate, propagate,
@@ -24,16 +24,16 @@ export function createOrbits({ state: layerState, services, parts, source }) {
function orbitFrameModelMatrix( function orbitFrameModelMatrix(
gmstAtBake, gmstAtBake,
nowDate, nowDate,
result = new Cesium.Matrix4(), result = geo.matrix4.create(),
) { ) {
const deltaGmst = gstime(nowDate) - gmstAtBake; const deltaGmst = gstime(nowDate) - gmstAtBake;
const rotation = Cesium.Matrix3.fromRotationZ( const rotation = geo.matrix3.fromRotationZ(
-deltaGmst, -deltaGmst,
layerState._scratchRingRotation, layerState._scratchRingRotation,
); );
return Cesium.Matrix4.fromRotationTranslation( return geo.matrix4.fromRotationTranslation(
rotation, rotation,
Cesium.Cartesian3.ZERO, geo.cartesian3.ZERO,
result, result,
); );
} }
@@ -55,7 +55,7 @@ export function createOrbits({ state: layerState, services, parts, source }) {
if (!posVel.position || typeof posVel.position === 'boolean') return null; if (!posVel.position || typeof posVel.position === 'boolean') return null;
const gmst = gstime(date); const gmst = gstime(date);
const geo = eciToGeodetic(posVel.position, gmst); const geodetic = eciToGeodetic(posVel.position, gmst);
const velocity = const velocity =
posVel.velocity && typeof posVel.velocity !== 'boolean' posVel.velocity && typeof posVel.velocity !== 'boolean'
? posVel.velocity ? posVel.velocity
@@ -65,9 +65,9 @@ export function createOrbits({ state: layerState, services, parts, source }) {
: null; : null;
return { return {
longitude: degreesLong(geo.longitude), longitude: degreesLong(geodetic.longitude),
latitude: degreesLat(geo.latitude), latitude: degreesLat(geodetic.latitude),
altitude: geo.height * 1000, // km → meters altitude: geodetic.height * 1000, // km → meters
speedMps: Number.isFinite(speedMps) ? speedMps : null, speedMps: Number.isFinite(speedMps) ? speedMps : null,
}; };
} catch { } catch {
@@ -101,12 +101,12 @@ export function createOrbits({ state: layerState, services, parts, source }) {
try { try {
const posVel = propagate(satrec, t); const posVel = propagate(satrec, t);
if (!posVel.position || typeof posVel.position === 'boolean') continue; if (!posVel.position || typeof posVel.position === 'boolean') continue;
const geo = eciToGeodetic(posVel.position, fixedGmst); const geodetic = eciToGeodetic(posVel.position, fixedGmst);
positions.push( positions.push(
Cesium.Cartesian3.fromDegrees( geo.cartesian3.fromDegrees(
degreesLong(geo.longitude), degreesLong(geodetic.longitude),
degreesLat(geo.latitude), degreesLat(geodetic.latitude),
geo.height * 1000, geodetic.height * 1000,
), ),
); );
} catch { } catch {
+4 -4
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { satelliteClassLabel } from '../../data/satelliteClass.js'; import { satelliteClassLabel } from '../../data/satelliteClass.js';
import { ISS_NORAD } from './policy.js'; import { ISS_NORAD } from './policy.js';
@@ -62,11 +62,11 @@ export function createRecords({ state, parts }) {
} }
const point = state._points.get(noradId); const point = state._points.get(noradId);
if (!point?.position) return null; if (!point?.position) return null;
const carto = Cesium.Cartographic.fromCartesian(point.position); const carto = geo.cartographic.fromCartesian(point.position);
if (!carto) return null; if (!carto) return null;
return { return {
lat: Cesium.Math.toDegrees(carto.latitude), lat: geo.math.toDegrees(carto.latitude),
lon: Cesium.Math.toDegrees(carto.longitude), lon: geo.math.toDegrees(carto.longitude),
altitudeM: carto.height, altitudeM: carto.height,
speedMps: null, speedMps: null,
}; };
+5 -5
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
export function createState({ services }) { export function createState({ services }) {
const { setOverlayEntries, setOverlaySourceVisible, clearOverlaySource } = const { setOverlayEntries, setOverlaySourceVisible, clearOverlaySource } =
@@ -58,7 +58,7 @@ export function createState({ services }) {
state._activeFocusCount = 0; state._activeFocusCount = 0;
state._scratchFocusScreen = new Cesium.Cartesian2(); state._scratchFocusScreen = geo.cartesian2.create();
state._enabled = false; state._enabled = false;
@@ -141,7 +141,7 @@ export function createState({ services }) {
state._trackedFrameGeo = null; state._trackedFrameGeo = null;
// { longitude, latitude, altitude } or null // { longitude, latitude, altitude } or null
state._trackedFrameCartesian = new Cesium.Cartesian3(); state._trackedFrameCartesian = geo.cartesian3.create();
/** Optional deterministic clock used only by the production-frame test seam. */ /** Optional deterministic clock used only by the production-frame test seam. */
@@ -149,9 +149,9 @@ export function createState({ services }) {
// Scratch variables // Scratch variables
state._scratchCartesian = new Cesium.Cartesian3(); state._scratchCartesian = geo.cartesian3.create();
state._scratchRingRotation = new Cesium.Matrix3(); state._scratchRingRotation = geo.matrix3.create();
/** Update the explicit model only when the rounded altitude line changes. */ /** Update the explicit model only when the rounded altitude line changes. */
/** Epoch of the last shared-context refresh for the tracked satellite. */ /** Epoch of the last shared-context refresh for the tracked satellite. */
+5 -5
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { viewAreaRadiusKm } from './viewArea.js'; import { viewAreaRadiusKm } from './viewArea.js';
/** /**
@@ -18,16 +18,16 @@ export function vesselViewArea(viewer) {
if (canvas?.clientWidth && canvas?.clientHeight) { if (canvas?.clientWidth && canvas?.clientHeight) {
try { try {
const hit = camera.pickEllipsoid( const hit = camera.pickEllipsoid(
new Cesium.Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 2), geo.cartesian2.create(canvas.clientWidth / 2, canvas.clientHeight / 2),
scene.globe?.ellipsoid, scene.globe?.ellipsoid,
); );
if (hit) center = Cesium.Cartographic.fromCartesian(hit); if (hit) center = geo.cartographic.fromCartesian(hit);
} catch { } catch {
/* the camera position stands in */ /* the camera position stands in */
} }
} }
const lat = Cesium.Math.toDegrees(center.latitude); const lat = geo.math.toDegrees(center.latitude);
const lon = Cesium.Math.toDegrees(center.longitude); const lon = geo.math.toDegrees(center.longitude);
if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null; if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
return { lat, lon, radiusKm }; return { lat, lon, radiusKm };
} }
+2 -2
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { import {
AIS_DEGRADED_STATUSES, AIS_DEGRADED_STATUSES,
AIS_HEALTHY_STATUSES, AIS_HEALTHY_STATUSES,
@@ -316,7 +316,7 @@ export function createQueries({
continue; continue;
const position = visual.billboard?.position || visual.position; const position = visual.billboard?.position || visual.position;
if (!position) continue; if (!position) continue;
const distanceM = Cesium.Cartesian3.distance(centerCartesian, position); const distanceM = geo.cartesian3.distance(centerCartesian, position);
if (!Number.isFinite(distanceM) || distanceM > range) continue; if (!Number.isFinite(distanceM) || distanceM > range) continue;
entries.push({ entries.push({
mmsi: record.mmsi, mmsi: record.mmsi,
+2 -2
View File
@@ -1,6 +1,6 @@
import { createVesselFeed } from './ingestion.js'; import { createVesselFeed } from './ingestion.js';
import { VesselRecords } from './records.js'; import { VesselRecords } from './records.js';
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { DEFAULT_AIS_RUNTIME } from './policy.js'; import { DEFAULT_AIS_RUNTIME } from './policy.js';
export function createVesselState({ source, services }) { export function createVesselState({ source, services }) {
@@ -18,7 +18,7 @@ export function createVesselState({ source, services }) {
vesselState._lastCamPoseSig = ''; vesselState._lastCamPoseSig = '';
vesselState._scratchFocusScreen = new Cesium.Cartesian2(); vesselState._scratchFocusScreen = geo.cartesian2.create();
vesselState.DEFAULT_VESSEL_OVERLAY_HOST = Object.freeze({ vesselState.DEFAULT_VESSEL_OVERLAY_HOST = Object.freeze({
setEntries: setOverlayEntries, setEntries: setOverlayEntries,
+5 -6
View File
@@ -1,4 +1,4 @@
import * as Cesium from 'cesium'; import * as geo from '../../geo/index.js';
import { import {
TRAIL_HEIGHT_M, TRAIL_HEIGHT_M,
VESSEL_LIFT_M, VESSEL_LIFT_M,
@@ -44,7 +44,7 @@ export function createTracking({
currentGeoidN(record.lat, record.lon), currentGeoidN(record.lat, record.lon),
TRAIL_HEIGHT_M, TRAIL_HEIGHT_M,
); );
return Cesium.Cartesian3.fromDegrees(record.lon, record.lat, heightM); return geo.cartesian3.fromDegrees(record.lon, record.lat, heightM);
} }
/** /**
@@ -66,7 +66,7 @@ export function createTracking({
currentGeoidN(record.lat, record.lon), currentGeoidN(record.lat, record.lon),
VESSEL_LIFT_M, VESSEL_LIFT_M,
); );
visual.position = Cesium.Cartesian3.fromDegrees( visual.position = geo.cartesian3.fromDegrees(
record.lon, record.lon,
record.lat, record.lat,
heightM, heightM,
@@ -146,7 +146,7 @@ export function createTracking({
currentGeoidN(lat, lon), currentGeoidN(lat, lon),
TRAIL_HEIGHT_M, TRAIL_HEIGHT_M,
); );
older.push(Cesium.Cartesian3.fromDegrees(lon, lat, heightM)); older.push(geo.cartesian3.fromDegrees(lon, lat, heightM));
} }
if (!older.length) return; if (!older.length) return;
@@ -170,8 +170,7 @@ export function createTracking({
const next = vesselTrailPosition(record); const next = vesselTrailPosition(record);
if (!next) return; if (!next) return;
const last = state.trailPositions[state.trailPositions.length - 1]; const last = state.trailPositions[state.trailPositions.length - 1];
if (last && Cesium.Cartesian3.distance(last, next) <= TRAIL_MIN_MOVE_M) if (last && geo.cartesian3.distance(last, next) <= TRAIL_MIN_MOVE_M) return;
return;
state.trailPositions.push(next); state.trailPositions.push(next);
if (state.trailPositions.length > TRAIL_MAX_POINTS) if (state.trailPositions.length > TRAIL_MAX_POINTS)
state.trailPositions.shift(); state.trailPositions.shift();