- satellites: Celestrak TLE -> SGP4 -> time-dynamic entities w/ glowing orbit paths; per-source cap + reordering so COSMOS/ISS aren't starved by the 72-sat Gaofen fleet (now ~97 sats, diverse); chunked propagation, orbital InfoBox - aircraft: global OpenSky ADS-B -> BillboardCollection primitive (6444 planes verified), altitude-banded, quota/scrub/visibility-gated polling, click overlay - ships: [DEMO] fleet through Hormuz incl. toll-route carrier, dark-vessel AIS gap, Fujairah idle cluster; optional aisstream.io live path - infra: choke-point rings, Petroline + Habshan-Fujairah pipelines, 9 facilities - events: [DEMO] time-anchored pulsing markers that appear as the slider crosses - authored + adversarially hardened via parallel agent workflow Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
88 lines
3.2 KiB
JavaScript
88 lines
3.2 KiB
JavaScript
// SPEC §6.5 — DEMO time-anchored event markers.
|
|
// Each marker's availability starts at its event time (now + offset) and runs to
|
|
// ctx.stop, so it APPEARS as the timeline slider crosses its moment. Every marker
|
|
// is an ILLUSTRATIVE PLACEHOLDER for a future real event feed — NOT a real record.
|
|
|
|
export default function create(ctx) {
|
|
const { viewer, CONFIG, lib, ui, Cesium, now, stop } = ctx;
|
|
|
|
const eventsDS = new Cesium.CustomDataSource('events');
|
|
viewer.dataSources.add(eventsDS);
|
|
|
|
const DISCLAIMER =
|
|
'ILLUSTRATIVE PLACEHOLDER — this is a DEMO marker, not a real strike/event ' +
|
|
'record. It stands in for a future real event feed.';
|
|
|
|
// offsetHours = when the marker appears (relative to wall-clock now).
|
|
const markers = [
|
|
{
|
|
name: 'Command installation strike [DEMO]',
|
|
lon: 51.4, lat: 32.6, offsetHours: -3,
|
|
blurb: 'Simulated ground strike on a command installation (inland Iran, approx coords).',
|
|
},
|
|
{
|
|
name: 'Recon satellite pass correlation [DEMO]',
|
|
lon: 51.4, lat: 32.6, offsetHours: -2,
|
|
blurb: 'Simulated correlation of a recon satellite pass with the site above (approx coords).',
|
|
},
|
|
{
|
|
name: 'Tanker incident [DEMO]',
|
|
lon: 56.5, lat: 26.5, offsetHours: 1,
|
|
blurb: 'Simulated tanker incident in the Strait of Hormuz (approx coords).',
|
|
},
|
|
{
|
|
name: 'Air-defense activation [DEMO]',
|
|
lon: 54.4, lat: 27.2, offsetHours: 3,
|
|
blurb: 'Simulated air-defense radar activation near the northern Gulf coast (approx coords).',
|
|
},
|
|
];
|
|
|
|
const color = lib.cz(CONFIG.colors.event);
|
|
let added = 0;
|
|
|
|
for (const m of markers) {
|
|
const eventTime = Cesium.JulianDate.addHours(now, m.offsetHours, new Cesium.JulianDate());
|
|
const when = m.offsetHours < 0
|
|
? `now ${m.offsetHours}h`
|
|
: `now +${m.offsetHours}h`;
|
|
|
|
eventsDS.entities.add({
|
|
name: m.name,
|
|
position: Cesium.Cartesian3.fromDegrees(m.lon, m.lat),
|
|
availability: new Cesium.TimeIntervalCollection([
|
|
new Cesium.TimeInterval({ start: eventTime, stop }),
|
|
]),
|
|
point: {
|
|
// Browser-time pulse: correct to run at render time (per SPEC note).
|
|
pixelSize: new Cesium.CallbackProperty(() => 8 + 4 * Math.sin(Date.now() / 300), false),
|
|
color,
|
|
outlineColor: Cesium.Color.WHITE,
|
|
outlineWidth: 1.5,
|
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
},
|
|
label: {
|
|
text: m.name,
|
|
font: '12px sans-serif',
|
|
fillColor: Cesium.Color.WHITE,
|
|
outlineColor: Cesium.Color.BLACK,
|
|
outlineWidth: 3,
|
|
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
|
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
|
pixelOffset: new Cesium.Cartesian2(0, -14),
|
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
|
},
|
|
description:
|
|
`<p><strong>${m.name}</strong></p>` +
|
|
`<p>${m.blurb}</p>` +
|
|
`<p>Appears at: ${when} (${m.lat.toFixed(2)}, ${m.lon.toFixed(2)}).</p>` +
|
|
`<p style="color:#ff9f40"><strong>${DISCLAIMER}</strong></p>`,
|
|
});
|
|
added += 1;
|
|
}
|
|
|
|
ui.addLayer('events', 'Events [DEMO]', true, (on) => { eventsDS.show = on; });
|
|
ui.setStatus('events', `${added} markers [DEMO]`, 'ok');
|
|
|
|
return { id: 'events' };
|
|
}
|