mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 03:14:00 +00:00
refactor(space): separate satellite and mission layer components
This commit is contained in:
1 parent
61db945b21
commit
ce0568983a
44 files changed
+8767
-6095
No files matched your search
@@ -0,0 +1,182 @@
|
||||
import * as Cesium from 'cesium';
|
||||
import { satelliteClassColor } from '../../data/satelliteClass.js';
|
||||
|
||||
/**
|
||||
* Satellite Orbits — Real-time positions via CelesTrak TLE + SGP4 propagation.
|
||||
*
|
||||
* Loads six CelesTrak groups (~840 sats): stations, visual, GPS, GLONASS,
|
||||
* Galileo, and the geosynchronous belt. Optional dense mode (setParams
|
||||
* catalog:'dense') adds the Starlink shell as points-only extras.
|
||||
* Renders positions via PointPrimitiveCollection, orbital paths as polylines.
|
||||
* Click any satellite to track it with camera follow + orbital path.
|
||||
*
|
||||
* ISS gets special treatment: larger point, persistent host label, path shown by default.
|
||||
*/
|
||||
|
||||
export const ISS_NORAD = 25544;
|
||||
|
||||
export const ISS_OVERLAY_SOURCE_ID = 'satellites-iss';
|
||||
|
||||
export const ISS_OVERLAY_SOURCE_OPTIONS = Object.freeze({
|
||||
cohortLimit: 1,
|
||||
collisionCapacity: 1,
|
||||
moving: true,
|
||||
solveIntervalMs: 125,
|
||||
});
|
||||
|
||||
export const ORBIT_PATH_STEPS = 180;
|
||||
// points per orbital path
|
||||
|
||||
export const POSITION_UPDATE_MS = 1000;
|
||||
// re-propagate every 1s (SGP4 is smooth at this rate)
|
||||
|
||||
export const RING_ROTATION_MS = 1000;
|
||||
// re-align baked orbit rings to current GMST every 1s
|
||||
|
||||
/**
|
||||
* CelesTrak groups loaded as the core catalog, in dedupe-priority order:
|
||||
* a satellite that appears in multiple groups keeps the FIRST (most specific)
|
||||
* tag. `path` is the upstream GROUP name forwarded by the /api/celestrak
|
||||
* proxy; `tag` is the internal group key used for POINT_STYLES lookup.
|
||||
* Note: CelesTrak's GLONASS group is named 'glo-ops' (not
|
||||
* 'glonass-operational' — that name 404s upstream).
|
||||
*/
|
||||
|
||||
export const CATALOG_GROUPS = [
|
||||
{ tag: 'stations', path: 'stations' },
|
||||
{ tag: 'visual', path: 'visual' },
|
||||
{ tag: 'gps-ops', path: 'gps-ops' },
|
||||
{ tag: 'glonass', path: 'glo-ops' },
|
||||
{ tag: 'galileo', path: 'galileo' },
|
||||
{ tag: 'geo', path: 'geo' },
|
||||
];
|
||||
|
||||
// Dense-catalog mode (setParams({ catalog: 'dense' })): Starlink shell as
|
||||
// points-only extras — no labels, no detection-overlay participation, and a
|
||||
// relaxed propagation budget (round-robin, ~1/5 of core cadence per sat).
|
||||
|
||||
export const DENSE_GROUP_PATH = 'starlink';
|
||||
|
||||
export const DENSE_REFRESH_FRAMES = 300;
|
||||
// full dense pass spread over ~300 frames (~5s @ 60fps)
|
||||
|
||||
export const DENSE_CREATE_CHUNK = 1500;
|
||||
// satrec builds per macro-task while loading
|
||||
|
||||
/**
|
||||
* Tracked-entity camera offset, east-north-up meters (Entity.viewFrom).
|
||||
* Magnitude ≈ 726 km — the user-validated "slightly zoomed out" framing for
|
||||
* LEO: far enough that per-frame satellite motion doesn't stutter the camera
|
||||
* or smear the label, with +Z biasing the view down onto the satellite.
|
||||
* High orbits (MEO nav / GEO belt) scale this up so the ring stays in frame.
|
||||
*/
|
||||
|
||||
export const TRACK_VIEW_FROM_LEO = new Cesium.Cartesian3(
|
||||
-450000,
|
||||
-450000,
|
||||
350000,
|
||||
);
|
||||
|
||||
export const HIGH_ORBIT_ALTITUDE_M = 2000000;
|
||||
|
||||
export const TRACK_VIEW_FROM_HIGH_SCALE = 4;
|
||||
// ≈ 2900 km back for MEO/GEO
|
||||
|
||||
/**
|
||||
* Shared per-group point styling — single source of truth used by BOTH the
|
||||
* creation site (update) and tracking restore (_clearTracking) so deselecting
|
||||
* a satellite never loses the original palette (WS-D3).
|
||||
*
|
||||
* Colors come from `satelliteClass.js` so the dot, the class label on the
|
||||
* card, and the legend swatch on the layer row can never disagree. Only
|
||||
* pixelSize/outline live here — those encode per-group prominence, not class.
|
||||
* Converted once at module load; per-point color is a plain primitive
|
||||
* attribute, so classification costs nothing per frame.
|
||||
*/
|
||||
|
||||
export const POINT_OUTLINE = Cesium.Color.WHITE.withAlpha(0.3);
|
||||
|
||||
export const _classColor = (group) =>
|
||||
Cesium.Color.fromCssColorString(satelliteClassColor(group));
|
||||
|
||||
export const POINT_STYLES = {
|
||||
// The ISS keeps its own long-standing red hero styling rather than the
|
||||
// STATION class color: it is the object most users open this layer for, it
|
||||
// carries a permanent name label, and its size/outline already set it apart.
|
||||
// Its card still reads "STATION · ISS", so the class stays legible.
|
||||
iss: {
|
||||
pixelSize: 12,
|
||||
color: Cesium.Color.fromCssColorString('#ff4444'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 2,
|
||||
},
|
||||
stations: {
|
||||
pixelSize: 8,
|
||||
color: _classColor('stations'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
visual: {
|
||||
pixelSize: 6,
|
||||
color: _classColor('visual'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
// Nav constellations (GPS / GLONASS / Galileo) resolve to one shared NAV
|
||||
// color; 6px so the MEO shells read as clearly as the old visual group did.
|
||||
'gps-ops': {
|
||||
pixelSize: 6,
|
||||
color: _classColor('gps-ops'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
glonass: {
|
||||
pixelSize: 6,
|
||||
color: _classColor('glonass'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
galileo: {
|
||||
pixelSize: 6,
|
||||
color: _classColor('galileo'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
geo: {
|
||||
pixelSize: 5,
|
||||
color: _classColor('geo'),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
// Dense-mode extras (Starlink): dim, small, points-only.
|
||||
dense: {
|
||||
pixelSize: 3,
|
||||
color: _classColor('dense').withAlpha(0.9),
|
||||
outlineColor: POINT_OUTLINE,
|
||||
outlineWidth: 0,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Physically DOCKED vehicles are separate real tracks sharing one position: the
|
||||
* station and everything berthed to it sit within metres of each other. Their
|
||||
* ambient labels therefore stack underneath the tracked card, which is what the
|
||||
* owner saw. This radius is deliberately tight — it must catch a docked stack
|
||||
* and nothing else, so an unrelated satellite in a similar orbit is never
|
||||
* suppressed. Formation-flying pairs are km apart; a docked stack is ~100 m.
|
||||
*/
|
||||
|
||||
export const DOCKED_COMPANION_RADIUS_M = 2000;
|
||||
|
||||
/** The scan is O(points); the tracked label is rebuilt every frame, so throttle. */
|
||||
|
||||
export const DOCKED_SCAN_INTERVAL_MS = 1000;
|
||||
|
||||
/**
|
||||
* Shared-context refresh interval. The tracked satellite is re-propagated
|
||||
* every rendered frame; the voice context only needs to be current to about
|
||||
* the propagation cadence, so this refreshes on the same 1 s beat instead of
|
||||
* allocating a record 60 times a second.
|
||||
*/
|
||||
|
||||
export const CONTEXT_REFRESH_INTERVAL_MS = 1000;
|
||||
Reference in new issue
Block a user