// 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]', // Offset from the strike site so the two markers/labels don't collide. lon: 52.0, lat: 32.95, offsetHours: -2, blurb: 'Simulated correlation of a recon satellite pass with the strike site to the southwest (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: 50000, }, label: { text: m.name, font: '11px 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), // Declutter at the global overview; sharpen when zoomed into the theater. translucencyByDistance: new Cesium.NearFarScalar(2.0e6, 1.0, 8.0e6, 0.0), disableDepthTestDistance: 50000, }, description: `

${m.name}

` + `

${m.blurb}

` + `

Appears at: ${when} (${m.lat.toFixed(2)}, ${m.lon.toFixed(2)}).

` + `

${DISCLAIMER}

`, }); added += 1; } ui.addLayer('events', 'Events [DEMO]', true, (on) => { eventsDS.show = on; }); ui.setStatus('events', `${added} markers [DEMO]`, 'ok'); return { id: 'events' }; }