mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-12 14:22:21 +00:00
feat(live): flights, military and vessels follow the world clock when their source declares a timeline
A live source may now declare a timeline: it can answer a snapshot at a
given time (source.timeline = { coverage(), stepMs, subscribe? }, read by
readSnapshotTimeline). While such a layer is on it follows the world clock
and registers the coverage. At the live edge it polls exactly as before;
away from it the layer asks for getSnapshot({ ...query, atMs }) at the step
at or before the clock time and shows that snapshot instead of polling.
src/time/snapshotTimeline.js owns the following: a seek, time going
backwards or leaving live replaces every contact with the snapshot at the
new time (play waits on it, for at most 8 s); playing on keeps one
snapshot ahead and gates play on it, applying those snapshots as polls so
contacts move smoothly; outside coverage the layer is empty; back at live
it is cleared and polls at once. One load at a time, and a load the
source drops for a newer one is not a failure.
While following, aircraft are drawn at the clock time with no render
delay, records and absences are judged at the clock, track requests carry
atMs, and vessels move between fixes along the great circle. The world
clock counts jumps (seeks and returns to live) in getState().
A source with no timeline never follows the clock, and every layer stays
live, unchanged.
This commit is contained in:
1 parent
962f7293c6
commit
57ff81f723
49 files changed
+2185
-239
No files matched your search
@@ -19,7 +19,12 @@ import {
|
||||
FOCUS_UPDATE_MS,
|
||||
LABEL_GRID_PX,
|
||||
CARD_MIN_SEP_PX,
|
||||
followsClock,
|
||||
} from './policy.js';
|
||||
import { vesselPositionAt } from './motion.js';
|
||||
|
||||
/** How often vessels move on as the world clock plays (wall ms). */
|
||||
const FOLLOW_POSITION_MS = 250;
|
||||
|
||||
export function createRendering({
|
||||
vesselState,
|
||||
@@ -42,20 +47,16 @@ export function createRendering({
|
||||
visual = { billboard: record.billboard || null };
|
||||
visualRecords.set(record, visual);
|
||||
}
|
||||
// Following the world clock, a vessel is drawn where it was at the time.
|
||||
const { lat, lon } = followsClock(vesselState)
|
||||
? vesselPositionAt(record, vesselState.worldNow())
|
||||
: record;
|
||||
const heightM = components.queries.vesselDatumHeightM(
|
||||
components.tracking.currentGeoidN(record.lat, record.lon),
|
||||
components.tracking.currentGeoidN(lat, lon),
|
||||
VESSEL_LIFT_M,
|
||||
);
|
||||
visual.position = Cesium.Cartesian3.fromDegrees(
|
||||
record.lon,
|
||||
record.lat,
|
||||
heightM,
|
||||
);
|
||||
visual.surfacePosition = Cesium.Cartesian3.fromDegrees(
|
||||
record.lon,
|
||||
record.lat,
|
||||
0,
|
||||
);
|
||||
visual.position = Cesium.Cartesian3.fromDegrees(lon, lat, heightM);
|
||||
visual.surfacePosition = Cesium.Cartesian3.fromDegrees(lon, lat, 0);
|
||||
visual.normal = Cesium.Ellipsoid.WGS84.geodeticSurfaceNormal(
|
||||
visual.position,
|
||||
new Cesium.Cartesian3(),
|
||||
@@ -212,9 +213,27 @@ export function createRendering({
|
||||
// own label publication requests a frame, and scheduling on that would loop.
|
||||
function installRuntime(viewer) {
|
||||
if (state.preRenderRemover || !viewer) return;
|
||||
state.preRenderRemover = viewer.scene.preRender.addEventListener(() =>
|
||||
updateVisibility(),
|
||||
);
|
||||
state.preRenderRemover = viewer.scene.preRender.addEventListener(() => {
|
||||
if (followsClock(vesselState)) followClockPositions();
|
||||
updateVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
// As the world clock plays, vessels between two fixes move on along them.
|
||||
let followedAtWallMs = -Infinity;
|
||||
let followedAtMs = null;
|
||||
function followClockPositions() {
|
||||
const wallMs = performance.now();
|
||||
if (wallMs - followedAtWallMs < FOLLOW_POSITION_MS) return;
|
||||
followedAtWallMs = wallMs;
|
||||
const atMs = vesselState.worldNow();
|
||||
if (atMs === followedAtMs) return;
|
||||
followedAtMs = atMs;
|
||||
for (const record of state.records.all) {
|
||||
if (!record.motion) continue;
|
||||
const visual = prepareRecordVisual(record);
|
||||
if (visual.billboard) visual.billboard.position = visual.position;
|
||||
}
|
||||
}
|
||||
|
||||
function scheduleTrailingVisibilityPass(now) {
|
||||
|
||||
Reference in new issue
Block a user