mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge upstream/main into feature/catalonia-cctv-cameras
# Conflicts: # docs/CURRENT-STATE.md
This commit is contained in:
commit
3bae92fce7
211 files changed
+28142
-1997
No files matched your search
@@ -17,6 +17,8 @@ until deliberately adopted.
|
||||
Generated output, local configuration, browser evidence and bundled datasets are
|
||||
excluded. The formatter validates every entry before writing any file.
|
||||
|
||||
New world text labels must use the world-overlay host; Cesium text labels are forbidden.
|
||||
|
||||
## Current component ownership
|
||||
|
||||
Package imports use `gods-eye-view`; `package.json` is the authoritative
|
||||
@@ -668,8 +670,8 @@ An empty search array is a definitive miss. HTTP failures, malformed results
|
||||
and oversized responses remain retryable. Attribution identifies OpenStreetMap /
|
||||
Nominatim.
|
||||
|
||||
Overpass currently supplies traffic road geometry, ALPR camera records, military
|
||||
installation footprints, and annotation geometry (administrative boundaries,
|
||||
Vector tile sources supply traffic roads, ALPR records and keyless military
|
||||
areas. Operator-configured Overpass supplies named installations and annotation geometry (administrative boundaries,
|
||||
neighborhoods, streets, building/grounds outlines and monument candidates).
|
||||
Nominatim forward/reverse lookup does not replace those queries. Layer source
|
||||
interfaces select traffic, camera and installation ingestion separately;
|
||||
@@ -711,7 +713,9 @@ query-language strings or decoding backend tags and relation members.
|
||||
|
||||
Points use `{lat, lon}`. Options carry `signal`. A successful array, including an
|
||||
empty array, is definitive; `null` means a transient failure;
|
||||
`{rateLimited: true, retryAfterMs}` retains a provider's retry delay. Candidates
|
||||
`{rateLimited: true, retryAfterMs}` retains a provider's retry delay.
|
||||
`{unavailable:true, code:'OVERPASS_NOT_CONFIGURED', retryable:false}` is a
|
||||
capability miss that stops retries while preserving pins and offline geometry. Candidates
|
||||
carry `id`, `names` (`primary`, `english`, `official`, `alternate`, `short`),
|
||||
`coordinates` (objects with `lat` and `lon`), `building` and optional `heightM`,
|
||||
`center` and `point`. Administrative candidates use `category: 'administrative'`
|
||||
|
||||
+476
-40
@@ -224,6 +224,22 @@ Voice and HUD snapshots reuse the existing feedState classifier. Analyst follow-
|
||||
|
||||
Satellite and local infrastructure layers expose on-demand analyst records through their current factory owners. Analyst counts and ranks explicitly cover only bounded examined loaded records (default 2,000 per new layer, core satellite rows before dense extras); omitted records can change nearest/count and satellite distance is ground distance. Existing tools and result fields remain available.
|
||||
|
||||
Keyless terrain tiles retry when Re:Earth throttles them. The browser fetches
|
||||
`terrain.reearth.land/cesium-mesh/ellipsoid/{z}/{x}/{y}.terrain` directly; no
|
||||
proxy in this repository sees those requests (`/api/terrain/heights` is the
|
||||
separate point-height endpoint), and the upstream edge answers zoom-out bursts
|
||||
with HTTP 429 under load. `src/maps/terrain.js` hands Cesium a `Resource`
|
||||
whose retry policy (`src/maps/terrainRetry.js`) every derived tile fetch
|
||||
inherits: 429, 502, 503 and 504 replies retry up to three times, 750 ms
|
||||
doubling to a 15 s cap, with every retry waiting behind one shared cooldown
|
||||
plus up to 1.5 s of jitter, and `Retry-After` extending the cooldown when the
|
||||
upstream exposes it. One console warning is logged per cooldown window. Other
|
||||
failures keep Cesium's handling and the flat `EllipsoidTerrainProvider`
|
||||
fallback. `scripts/qa-terrain-429.mjs` reproduces the burst against a keyless
|
||||
dev server, counts real throttles with their headers as evidence, synthesises
|
||||
throttles with `--inject N` when the upstream is not throttling, and fails if
|
||||
a throttled tile never loads.
|
||||
|
||||
AIS encodes speed over ground in 0.1-knot units and course over ground in
|
||||
0.1-degree units, reserving the top code of each field for "not available", so
|
||||
those reports arrive as 102.3 knots and 360 degrees. Both are stored as unknown,
|
||||
@@ -303,7 +319,7 @@ are protected from fallback writes. Version 6 is the export format, with
|
||||
zero pitch, low camera heights, scope and detection edits preserved. See [the document contract](SCENE-DOCUMENT.md);
|
||||
see [Director](DIRECTOR.md) for camera, pack, action and sharing support.
|
||||
|
||||
Search framing and annotations request semantic map features from an explicit source. The Overpass adapter owns bounded queries, member/tag decoding and request deadlines; callers retain candidate ranking, outline caching, deferred retries and scene placement. Empty, transient and throttled outcomes remain distinct. Traffic sources return road records and installation sources return mapped records with freshness/saturation metadata, so their layers no longer decode upstream elements. ALPR already normalizes its records in the source. Default providers, footprints, road directions, exact-viewport retries and source attribution are unchanged.
|
||||
Search framing and annotations request semantic map features from an explicit source. The Overpass adapter owns bounded queries, member/tag decoding and request deadlines; callers retain candidate ranking, outline caching, deferred retries and scene placement. Empty, unavailable, transient and throttled outcomes remain distinct. Traffic sources return road records and installation sources return mapped records with freshness/saturation metadata, so their layers no longer decode upstream elements. ALPR already normalizes its records in the source. Traffic uses OpenFreeMap roads with optional matched TomTom congestion; ALPR uses an hourly OpenStreetMap extract. Keyless installations use military-area tiles. Detailed feature queries require operator-configured Overpass.
|
||||
|
||||
Nepal media preloads survive repeated camera-flight updates, but Stop, event disable and replacement remove abandoned frames and revoke pending Facebook sessions. Fallback evidence-card clicks respect the shared drawing-tool pointer lease.
|
||||
|
||||
@@ -426,12 +442,30 @@ selection, route/direct-line honesty and tool schemas are preserved. Node
|
||||
Google, OSRM and Nominatim adapters accept trusted construction-time configuration;
|
||||
request parameters cannot choose arbitrary upstream URLs. See APPLICATION.md.
|
||||
|
||||
Every ALPR native marker is repositioned on map-source changes, including canvas-owned saved appearances, while retaining its entity identity.
|
||||
|
||||
ALPR floor preparation and clamped markers share a per-cell queue, with at most one 64-cell terrain batch active per layer. Disabling or destroying the layer cancels its terrain consumer and discards queued cells. Repeated moves inside an outstanding query retain the displayed markers until the new snapshot is ready.
|
||||
|
||||
The optional **ALPR Cameras** layer shows community-mapped OpenStreetMap locations,
|
||||
not camera footage or plate records. City-scale queries use the existing Overpass
|
||||
provider, with capped results, retry, cached-data and incomplete-coverage notices.
|
||||
not camera footage or plate records. City-scale acquisition uses an hourly
|
||||
OpenStreetMap US/Canada extract, with available operator/brand/bearing
|
||||
attributes. The extract carries full attributes from z9 (z0-8 are geometry-only
|
||||
heat tiles); each view reads the finest zoom from z12 down to z9 that fits 16
|
||||
tiles, so a 30 km whole-city view loads about 1,000 Austin cameras and a
|
||||
neighbourhood reads z12 (about 2 m position precision). Each camera keeps the
|
||||
finest position seen, so zooming out never nudges a marker. The fetched tiles'
|
||||
bounds are the accepted coverage: later views inside it (and precise enough for
|
||||
it) reuse the records at once, without a request or debounce, and a still camera
|
||||
sees one marker update per move. Missing verification dates remain unknown; OSM edit dates do not
|
||||
stand in for verification. Outside coverage the row says "No ALPR data for this
|
||||
area". Reads cap tiles at 16 per country, concurrency at four per country,
|
||||
responses at 4 MiB, decoded cache at 64 entries/24 MiB per country with a one-hour
|
||||
TTL, and accepted records at 6,000; at most 1,500 cameras in view render,
|
||||
nearest the view centre first, and more than that reads "Coverage limited".
|
||||
Partial coverage remains explicit.
|
||||
Its `./layers/alpr` entry exposes a per-instance layer factory and bounded source
|
||||
adapter. Sources return normalized records, stale/coverage flags and their own
|
||||
attribution; rendering does not parse Overpass payloads. The standalone
|
||||
attribution; rendering does not parse tile payloads. The standalone
|
||||
registration supplies selection, picking, terrain and
|
||||
render services. Selected cards and Data attribution identify OpenStreetMap.
|
||||
Layer state and the existing voice layer tools include `alpr-cameras`.
|
||||
@@ -440,8 +474,28 @@ screen. Cyan camera badges use Manjunath's camera artwork; selection switches to
|
||||
larger coral badge with corner brackets and an animated tactical card. Numeric
|
||||
mapped bearings draw illustrative 90 m direction wedges (not measured coverage).
|
||||
The shared overlay paints gradients for at most 64 nearby cameras, promoting the
|
||||
selected camera; farther cameras retain native Cesium badges and ground-clamped
|
||||
wedges. Unknown bearings never acquire a wedge. Asset URLs resolve relative to
|
||||
selected camera; farther cameras keep native Cesium badges without wedges.
|
||||
Native ground-clamped wedges (a ground polyline plus a classification polygon per
|
||||
camera) cost about 40 ms per frame for 200 downtown cameras on photoreal tiles
|
||||
and were removed. Badges sit on the cached ground floor (validated mesh or DEM,
|
||||
+1.5 m) rather than ground clamping, which re-sampled every badge whenever a
|
||||
tile streamed in; floors resolve before new badges appear (bounded wait), and a
|
||||
badge whose cell has not resolved clamps until it does, then moves in place.
|
||||
Overlay anchors start on the same floor and write marker properties only on
|
||||
change. Once the camera is still and tiles have settled, each overlay anchor is
|
||||
replaced once by the rendered surface under it (two depth samples per paint,
|
||||
accepted only within -30/+40 m of the floor cell), so badges do not float or
|
||||
sink on slopes; wedge corners follow their own floor cells instead of staying
|
||||
level with the apex. Unknown bearings never acquire a wedge. The row reads
|
||||
`N nearby · M on screen`; when every loaded camera is outside the view it adds
|
||||
"None on screen — nearby cameras are outside the view" instead of looking
|
||||
unloaded. `scripts/qa-alpr-journey.mjs` drives an Austin journey with ALPR off,
|
||||
then on (cold and warm), and asserts time to cameras, marker stability while
|
||||
still, and frame time within 10% of ALPR off. It also checks rendered frames:
|
||||
marker pixels in the recorded clip against the ALPR-off pass, and, at the end
|
||||
of every hold, the screen against the same scene after forcing frames, so a
|
||||
state change without a render request fails (`--self-test-drop-renders` proves
|
||||
it does). Asset URLs resolve relative to
|
||||
the reusable layer, and the caller supplies overlay and map-stack services.
|
||||
The ALPR row uses the same header layout as other data layers. **SHOW NEAREST**
|
||||
frames and selects the nearest loaded camera; it is
|
||||
@@ -452,8 +506,8 @@ Coverage follows a bounded neighborhood around the screen-center ground point,
|
||||
with a radius of twice the camera-to-ground range (at least 1 km), rather than
|
||||
extending to the horizon. Sky, dateline-crossing and wider-than-city views do not
|
||||
query. Movement within an accepted or pending query reuses it. Markers retain
|
||||
their Cesium identity and ground clamping while their geometry is unchanged;
|
||||
refreshes preserve selection without replaying a click event.
|
||||
their Cesium identity while their geometry is unchanged; refreshes preserve
|
||||
selection without replaying a click event.
|
||||
|
||||
Data Centers, Dams and Submarine Cables release their built Cesium data sources
|
||||
and record references when disabled. Parsed datasets remain cached for the layer
|
||||
@@ -470,6 +524,8 @@ Each layer owns its state and visibility listener; destruction cancels source
|
||||
reads and pending initialization. Malformed health responses retain prior health.
|
||||
Existing catalog fallback, camera poses, frame pacing and coverage controls remain.
|
||||
|
||||
Traffic owns its rendered-surface observer only while enabled, removes it on disable/destroy, and caches surface identity without allocating on unchanged frames.
|
||||
|
||||
Traffic and bikeshare expose factories through `./layers/traffic` and
|
||||
`./layers/bikeshare`. Traffic separates road requests, ingestion, animation,
|
||||
flow matching, styling, viewport lifecycle and development timing. Each source
|
||||
@@ -693,6 +749,18 @@ and result presentation. Existing search providers and camera handoff policy are
|
||||
preserved. Replacing or closing a POI row cancels its pending expansion frame;
|
||||
destruction releases listeners, pending searches and the orbit indicator.
|
||||
|
||||
Contacts and mapped-site search feedback filter subject-window installation matches by surface distance from the current subject position, within the stated 100 km radius; the retained tile-fetch square is only a loading window.
|
||||
|
||||
Search arrivals (location bar and voice) end above the rendered surface.
|
||||
Precise places without a detailed outline used to frame a 250 m landmark shot
|
||||
from a sea-level target, which left Camp Mabry about 1 m above the 171 m mesh
|
||||
and a Denver coordinate underground. Search now resolves the application's
|
||||
ground-floor elevation (bounded wait, same ellipsoidal datum) before framing and
|
||||
warms the cell; after landing, `src/cameraGroundGuard.js` samples the rendered
|
||||
surface under the target and the camera once tiles stream in and lifts the eye
|
||||
to 120 m clearance, holding heading and pitch. Navigation ownership changes (Director, tracking, keyboard/UI controls and direct camera flights), layer/app teardown, and pointer/wheel gestures cancel the check and remove its listeners. `scripts/qa-context-arrivals.mjs` types Camp Mabry
|
||||
and a Denver coordinate and requires at least 60 m clearance.
|
||||
|
||||
## Layer panel ownership
|
||||
|
||||
Layer rows, feed feedback, counts, focus-preserving chips and toggle listeners
|
||||
@@ -1121,8 +1189,34 @@ fetching, trailing-24-hour filtering and partial-success caching are unchanged.
|
||||
|
||||
## Installations and map-source guidance
|
||||
|
||||
- On an uncached Overpass failure, mapped installations keep their existing
|
||||
30–240 second retry backoff. The top status and Contacts row explain the
|
||||
- Keyless mapped installations use OpenFreeMap `landuse` military polygons,
|
||||
merge touching parcels and tile fragments into one "Military area" marker;
|
||||
tiles carry no site names. The marker uses an area-weighted centroid, moved
|
||||
inside a footprint when necessary. Source-feature aliases retain ids across
|
||||
pans (4096-entry cap); grouping admits at most 2048 fragments per view and
|
||||
reports saturation if that cap is reached. Tile-buffer geometry is clipped to each core and
|
||||
artificial clipping edges never become outlines. Fills, boundary polylines
|
||||
and markers clamp to the visible globe or photoreal mesh. Wide views start
|
||||
at z10, local views at z12, stepping down no further than z9 to fit the
|
||||
16-tile view cap: OpenMapTiles carries `landuse=military` only from z9, so a
|
||||
view too wide for 16 z9 tiles is a "Zoom in" state, never an empty area.
|
||||
Camera changes debounce for 180 ms, with a final moveEnd check; identical
|
||||
windows reuse the active load. Disabling or returning Contacts to passive mode
|
||||
clears its anchor; passive refreshes cannot reclaim it. Background repaints
|
||||
refresh context records without publishing a new selection.
|
||||
Installation tiles decode only the `landuse` layer. Reloads keep the Cesium
|
||||
entities of sites whose geometry is unchanged, so outlines and fills do not
|
||||
blink. While Contacts has a subject, the layer loads a window around it
|
||||
instead of the camera view (100 km half-width at mid latitudes, shrinking so
|
||||
it fits 16 z9 tiles), moves it only after the subject travels 20 km, and
|
||||
ignores camera `moveEnd`; clearing the subject returns to the viewport. The
|
||||
row status names what was found ("3 mapped sites within 100 km of the
|
||||
contact", "No mapped sites in view") and tile failures read "Map tiles
|
||||
temporarily unavailable". Google Places
|
||||
search/classification stays separate and unchanged. Configured Overpass can
|
||||
still supply named sites; a not-configured miss switches to tiles once.
|
||||
Retryable tile/configured-upstream failures retain the existing 30–240 second
|
||||
backoff, extended when Retry-After requires it. The top status and Contacts row explain the
|
||||
outage and scheduled countdown; an active retry says "Retrying mapped
|
||||
sites" and successful recovery clears the previous error. Known upstream
|
||||
rate limits, timeouts, and query failures are distinguished without exposing
|
||||
@@ -1307,7 +1401,7 @@ This is the current runtime/source-of-truth snapshot for the project.
|
||||
> Without the predicate that window prints an all-clear `0`.
|
||||
> - **Mapped installations never reaches that window.**
|
||||
> `militaryInstallations.enable()` is synchronous and the manager awaits
|
||||
> `update()`, which owns the first Overpass fetch, so the lifecycle stays
|
||||
> `update()`, which owns the first mapped-data fetch, so the lifecycle stays
|
||||
> `enabling` for the whole fetch and the pre-existing `enabling` branch
|
||||
> covers it. Confirmed live on :4272 across a held 17 s first fetch (34
|
||||
> samples, `enabling` throughout, panel non-numeric) and across a failing
|
||||
@@ -2084,7 +2178,7 @@ down | auth-failed` (plus the unchanged `missing-key`/`unsupported`) with
|
||||
> then checks fresh memory, identical in-flight work, and fresh disk entries
|
||||
> before invoking its local 90/min limiter. Cache and single-flight responses
|
||||
> therefore do not spend quota; upstream-bound misses retain the existing
|
||||
> limiter, mirror, stale, and sanitization behavior.
|
||||
> limiter, configured-upstream, stale, and sanitization behavior. An unconfigured transport serves dated stale data or a non-retryable capability error.
|
||||
> - **CCTV world-click focus:** clicking an in-world CCTV icon or ambient card
|
||||
> activates it and routes the camera flight through the panel FOCUS policy.
|
||||
> Aircraft/satellite tracking releases outside cockpit; cockpit retains the
|
||||
@@ -2752,11 +2846,11 @@ its criteria cannot be silently ignored.
|
||||
| Live Flights ✈️ | OpenSky Network; bounded adsb.lol regional fallback | `src/data/flights.js` | `/api/opensky` (OAuth + fallback) | 30s |
|
||||
| Military Flights 🎖️ | adsb.lol /v2/mil | `src/data/militaryFlights.js` | `/api/adsblol/mil` | 15s |
|
||||
| Live AIS Vessels 🚢 | AISStream websocket | `src/data/aisLiveVessels.js` | `/api/ais-live` | 60s (+800ms visibility pass) |
|
||||
| Mapped Installations ⌖ | OpenStreetMap mapped context; on-demand Google Maps Places supplement | `src/data/militaryInstallations.js` | `/api/military-installations`, `/api/google/text-search` | viewport-driven + user search; while unavailable, auto-retry 30 s → 240 s backoff |
|
||||
| Mapped Installations ⌖ | OpenFreeMap military areas; optional configured Overpass names and Google Places search | `src/data/militaryInstallations.js` | OpenFreeMap tiles, `/api/military-installations`, `/api/google/text-search` | viewport-driven; transient errors back off, missing capability switches to tiles |
|
||||
| Earthquakes | USGS | `src/data/earthquakes.js` | — | 60s |
|
||||
| Satellites | CelesTrak | `src/data/satellites.js` | `/api/celestrak` | 120s |
|
||||
| Space Missions (30d) | Launch Library 2 + CelesTrak | `src/data/rocketLaunches.js` | `/api/launches` + `/api/celestrak/active` | 5 min |
|
||||
| Traffic | OSM Overpass (+ optional TomTom live flow) | `src/data/traffic.js` | `/api/overpass` + `/api/tomtom` | viewport-driven |
|
||||
| Traffic | Selectable TomTom / OpenStreetMap / Hybrid roads; optional TomTom flow (BYOK) | `src/data/traffic.js` | browser-direct OpenFreeMap tiles; `/api/tomtom` for flow | viewport-driven; capped tile cache |
|
||||
| CCTV | Austin + Caltrans (CA) + TfL London + Ontario 511 + Fintraffic (FI) + DriveBC (BC) + TxDOT (TX) + Estonia (Tallinn, Tarktee) + Live Traffic NSW + Open Calgary Open Data + Catalonia (Servei Català de Trànsit) + Street View fallback | `src/data/cctv.js` | `/api/cctv` | 10s (active) |
|
||||
| Radio | Radio Browser (public-domain station directory) | `src/data/radio.js` | `/api/radio/stations`, `/api/radio/click/:uuid` | 45 min directory refresh |
|
||||
| Transit 🚌 | Operator GTFS-Realtime VehiclePositions (7 keyless regions, `src/data/transitFeeds.js`) | `src/layers/transit/` via `src/app/layers/transit.js` | `/api/transit` | 15s (poll + delayed playback) |
|
||||
@@ -3365,10 +3459,11 @@ silently demoting every later lookup for the session.
|
||||
- Aircraft cohort membership uses every locally loaded, selectable contact inside the 250 km window, including a plane hidden only by horizon culling or because its 3D model owns the visual. Counts and navigation therefore do not change with the current camera angle or billboard/model handoff.
|
||||
- Nearby examples in the context panel are focus controls: they use their owning layer's existing selection/tracking path, then frame that contact. Static-installation distances use ellipsoidal surface distance so the count matches the ground-projected context disk.
|
||||
- Context selection transfers camera ownership by subject type: selecting a civilian or military flight keeps that layer's moving follow camera, while selecting an AIS vessel or mapped installation first releases any prior aircraft tracker and performs only the source layer's one-time framing. The camera therefore remains user-controlled after non-aircraft selection instead of continuing to move with the previously selected plane.
|
||||
- Selected AIS vessels use their layer-owned full-detail presentation model in the shared world-overlay host; mapped installations use the tracked-readout aesthetic. Both remain crisp above post-processing without duplicate selected labels; non-selected AIS cards retain their source-owned grid/visibility selection and are host-batched with other world cards.
|
||||
- Selected AIS vessels use their layer-owned full-detail presentation model in the shared world-overlay host; mapped installations promote their own entry to a selected card. Both remain crisp above post-processing without duplicate selected labels; non-selected AIS cards retain their source-owned grid/visibility selection and are host-batched with other world cards.
|
||||
- Space Mission ascent replay uses the compact rocket/thrust overlay only through orbit insertion. Once the replay enters its orbit phase, that vehicle glyph is replaced by a fixed-size cyan dot following the same orbit path and callout.
|
||||
- While a subject is selected, an inner keyhole compass rotates against camera heading and up to three cyan shafted bearing arrows lock to its single faint tick-marked rim, with their labels inset just inside the circle. Labels explicitly separate the geographic bearing (`BRG`) from the contact's reported course (`CRS`) so the pointer direction is not confused with aircraft heading. They point toward the nearest observed/mapped examples; each cohort displays up to ten examples while retaining the complete locally loaded in-range cohort for navigation, with three visible at a time and a ten-second page rotation shared by the panel and arrows. This distinct neutral-context color avoids implying that all context indicators are military-flight symbols. `PREVIOUS`, `FOCUS`, and `NEXT` controls navigate selection history or the next nearby cohort example through the existing tracker. NEXT uses a cycle-scoped visited set and starts a deterministic new walk after exhausting the current candidates instead of re-admitting the nearest visited contact.
|
||||
- Installations are viewport-bounded OSM map features (`military=airfield|naval_base|range|barracks|base` and `landuse=military`), capped to a 10° non-dateline request and 700 upstream features. The proxy caches five minutes and serves a one-hour stale fallback. Empty, stale, unavailable, and zoom-too-wide states remain visibly distinct.
|
||||
- With a selected subject, Contacts hands the installation layer the subject position every refresh. The layer loads a window around the subject (see Installations and map-source guidance), because a follow or Cockpit camera never fires `moveEnd` and often looks at the horizon: a first load from a globe view used to leave the row at "?" for the whole track. The row and the Cockpit scope read `WITHIN 100 KM` instead of `CURRENT VIEWPORT ONLY`, and an empty window reads "none mapped within 100 km; not a complete 250 km survey". `scripts/qa-context-arrivals.mjs` flies synthetic aircraft over Camp Mabry and Fort Cavazos from a wide start, presses CONTACTS, Cockpit and SEARCH NEARBY SITES, and records a clip.
|
||||
- The selected-only visual is one static, unfilled blue circle. It marks the 250 km proximity context window only; it is not coverage or a radar/weapon envelope. Missing broadcasts and unmapped sites are explicitly not evidence of absence.
|
||||
- The right rail's collapsed Display, CCTV, and Context controls use the same compact sizing language as the left rail's collapsed Data Layers and Scenes controls. These compact-state widths do not constrain expanded panel or child-content widths.
|
||||
|
||||
@@ -3483,13 +3578,97 @@ silently demoting every later lookup for the session.
|
||||
- **Track trails**: server accumulates per-MMSI ring buffers (`/api/ais-live/track?mmsi=`, Float32+Uint32, 64 samples, 30s/25m thinning); aircraft backfill proxies `/api/opensky-track` (OAuth, own credit bucket) and `/api/adsblol/trace` (tar1090 readsb, ~24h history, ODbL — credit adsb.lol).
|
||||
- Shared `src/data/pickRegistry.js` stops the two flight layers' click handlers from fighting over the camera.
|
||||
|
||||
### Overpass proxy mirror rotation (September 2026)
|
||||
### Optional Overpass configuration
|
||||
|
||||
- `/api/overpass` fans out across four public mirrors. `overpassPayloadIsData()` governs cache reads, writes, and stale fallback: only a 2xx that is neither rate-limited nor a body-level runtime error qualifies. Previously stored refusals are ignored on both fresh and stale reads, so upgrading does not require manually clearing the disk cache.
|
||||
- HTTP refusals such as 406 now rotate alongside the existing network, rate-limit, and runtime-error cases. A refusal from one mirror no longer prevents reaching healthy alternatives or persists under the seven-day road/month-long boundary cache TTLs. Concurrent identical queries share one mirror sequence; if it fails, both the initiating and joined callers can use the same last-good data.
|
||||
- A refusal every mirror agrees on is still reported with the first mirror's status and body, so a genuinely malformed query says what upstream said — but only after every mirror has had the chance to answer it. `fetchOverpassPayload` takes injectable endpoints and fetch so the rotation is tested without a live mirror (`src/overpassProxy.test.mjs`).
|
||||
- Every mirror is asked with a User-Agent that names the application, its version and the project address (`OVERPASS_USER_AGENT` in `server/providers/overpass/constants.js`), which is what the OSM API usage policy asks for. Mirrors may refuse a client they cannot identify; such a refusal is never treated as data and costs the fan-out that mirror, so the header is what keeps the list at full strength.
|
||||
- When the fan-out has nothing left to offer, the traffic row says which upstream declined and how: `Overpass rate-limited`, `Overpass timed out`, or `Overpass refused the road query (HTTP 406)`; the proxy's own 502 (every mirror unreachable) and 503 (local limiter busy) read `Overpass mirrors unreachable` and `Overpass temporarily unavailable`. Street Traffic draws on two upstreams — OpenStreetMap for geometry, TomTom for flow — so a row that only said "road data unavailable" sent readers to check a TomTom key that was never the problem (#661). `roadRequestError` in `src/layers/traffic/source.js` owns the mapping and tags the error with its status. A refusal whose code is unreadable — the layer takes its source by injection, so an adapter may not supply one — reports `Overpass temporarily unavailable` rather than printing `HTTP undefined`, and anything the layer did not classify at all (a dropped connection, a malformed snapshot) still reads `Road data temporarily unavailable`, because a platform exception is not a sentence to put on a panel.
|
||||
Public Overpass instances are not used by default. `OVERPASS_UPSTREAMS` is a
|
||||
server-only comma-separated list of HTTP(S) instances the operator runs or pays
|
||||
for, resolved lazily after env loading. It replaces the empty default list;
|
||||
there is no built-in fallback. Local/private instances are allowed. The stable
|
||||
`gods-eye-view/…` User-Agent is unchanged. URLs never appear in response headers
|
||||
or upstream errors, including old cached endpoint metadata.
|
||||
|
||||
The shared transport guards `/api/overpass` and `/api/military-installations`.
|
||||
With no configured upstream, each route serves existing cache data (including
|
||||
expired entries, marked stale with the original cache/retrieval date) without
|
||||
refresh. An annotation miss returns HTTP 503, `OVERPASS_NOT_CONFIGURED`,
|
||||
`retryable:false`; installations return that capability as HTTP 200 and select
|
||||
the working vector-tile source without a failed-network console entry.
|
||||
`GET /api/overpass/status` answers `{configured}`; the browser asks once per
|
||||
page and, when nothing is configured, returns the unavailable result for
|
||||
annotation and location-feature queries without sending them (so no 503 is
|
||||
logged). An older server without the probe is queried as before. The probe
|
||||
times out after 3 s; a failed or timed-out probe is retried after 30 s, and
|
||||
queries in between go to the server. Each query stops waiting on the probe
|
||||
when its own signal aborts.
|
||||
Configured endpoints have per-instance cooldowns for 406/429, honoring
|
||||
Retry-After; absent delays back off from 30 seconds to five minutes. Empty
|
||||
`elements` is a valid answer. Existing byte, query, concurrency and cache caps
|
||||
remain. Consumer capability misses never schedule automatic retries.
|
||||
|
||||
Operator-configured Overpass area and focus-footprint queries use body-level
|
||||
`out geom` (with `center` for focus), preserving relation member outlines.
|
||||
Member geometry is printed only inside a box around the point (6 km for
|
||||
neighbourhoods, 3 km for street areas, 1.5 km for focus footprints); a
|
||||
relation cut by the box does not close and falls back to its pin.
|
||||
Street Traffic and ALPR never use Overpass. Installations switch once to vector
|
||||
tiles after a capability miss. Annotation and location-feature sources retain
|
||||
a distinct unavailable result and stop querying for that source lifetime.
|
||||
`scripts/qa-overpass-offload.mjs <dev-url>` checks Austin road dots, ALPR,
|
||||
Camp Mabry markers/outlines, at most 12 Fort Cavazos installation markers,
|
||||
an area annotation with zero console errors (and zero `/api/overpass` queries
|
||||
when unconfigured), and zero browser requests to external Overpass/Nominatim hosts. It waits for
|
||||
visible photoreal tilesets, dismisses first launch and measures at least 150
|
||||
street-view dots within -3/+25 m of sampled mesh height, for both keyed and
|
||||
keyless OpenFreeMap roads (an isolated page overrides only TomTom key availability).
|
||||
Keyed Austin defaults to Hybrid (`roadSource: TomTom + OpenStreetMap`) with positive flow coverage.
|
||||
It records milliseconds from enabling Street Traffic to first rendered dots at
|
||||
2 km on a fresh page for each mode, plus warmed street-view timings and orbit screenshots;
|
||||
`src/overpassOffload.test.mjs` separately proves server-handler zero egress.
|
||||
All QA modes record per-view request counts, decoded response-body bytes,
|
||||
transferred bytes and browser cache hits for OpenFreeMap TileJSON/tiles, ALPR
|
||||
extract metadata/tiles and local `/api/tomtom/*` responses. `--tour` measures
|
||||
Austin, London, Dubai, San Diego, Tokyo and São Paulo with all three layers on,
|
||||
at 450 m and -35° pitch (São Paulo: 1250 m), then revisits Austin to measure
|
||||
cache reuse. The tour disables camera collision adjustment and asserts the actual
|
||||
latitude, longitude, altitude and pitch so remote terrain cannot shift a revisit.
|
||||
`--compare` captures TomTom, OpenStreetMap and Hybrid at identical close tilted
|
||||
photoreal views: Twin Peaks, Lombard Street, Loop 360, Dubai and Shibuya. The
|
||||
mode order rotates per view so each mode meets cold caches somewhere. It records
|
||||
first-dot latency (null where TomTom has no roads), projected dots,
|
||||
surface-aligned dots (-3/+25 m), floaters, sinkers and missing samples, saving
|
||||
`qa-shots/compare-<view>-<mode>.png` and `overpass-offload-compare-result.json`.
|
||||
The comparison also clicks a real row chip and verifies its stored preference.
|
||||
`--pan` runs 20 settled Austin moves: ten 150–300 m steps, five 1–2 km steps,
|
||||
and five exact returns. It records OFM requests/bytes, flow tile requests, all
|
||||
local API calls and dots per move, rejects repeat XYZ downloads and any new
|
||||
OFM request on a return, and checks small-pan tiles against admitted bounds.
|
||||
Its TomTom session ceiling is 32 browser flow requests (0.53% of the default
|
||||
6,000/day upstream budget); cached server responses also count toward this
|
||||
conservative session bound. `--profile` captures cold/warm Austin at 450 m,
|
||||
-35 degrees with settled mesh. Development `roads:*` phase measures include
|
||||
status, TileJSON, per-tile fetch/decode, parsing and surface sample counts/CPU
|
||||
time, slice maxima and cache hits; no obsolete zero-valued parse-time sampling
|
||||
aggregate is emitted. The six-city tour records first-dot and on-mesh counts
|
||||
and asserts the 4 s cold / 2.5 s cached-return deadlines.
|
||||
Reports go to `qa-shots/overpass-offload-result.json` and separate
|
||||
acceptance/tour/pan/profile result files, with a console summary table. These are browser
|
||||
session measurements; TomTom upstream usage still depends on the server cache
|
||||
and budget. MB uses decimal bytes; transfer totals include response headers.
|
||||
|
||||
Configured Overpass responses still use `overpassPayloadIsData()` for cache
|
||||
admission and stale fallback: refusals and body-level errors are never data.
|
||||
Identical requests share a configured endpoint sequence and last-good fallback;
|
||||
all configured endpoints retain the stable application User-Agent. HTTP refusals
|
||||
rotate only among those configured endpoints, honoring their cooldowns.
|
||||
|
||||
Street Traffic reports OpenFreeMap road failures separately from TomTom flow:
|
||||
`OpenFreeMap tiles rate-limited`, `OpenFreeMap tiles timed out`, or
|
||||
`OpenFreeMap tiles unavailable (HTTP 406)`. `RoadRequestError` retains a numeric
|
||||
`status` (null when absent); malformed snapshots and network failures read
|
||||
`OpenFreeMap tiles unavailable`, never `HTTP undefined`. Detailed-pass failures
|
||||
retain the major roads and display the same upstream reason with reduced coverage.
|
||||
The TomTom /api proxy still reports key unavailability (503), daily budget (429),
|
||||
and unreachable upstream (502/504) separately from road geometry.
|
||||
|
||||
### Share-link v2 layer state (August 2026)
|
||||
|
||||
@@ -3498,11 +3677,33 @@ silently demoting every later lookup for the session.
|
||||
with compact fields for enabled layers, allowlisted layer options, panel state,
|
||||
and the active preset's allowlisted shader controls. An absent layer field uses
|
||||
deterministic defaults; an explicit empty field means no enabled layers.
|
||||
- The registry seals only after all 16 production layers register, and every
|
||||
layer has an explicit serialization disposition. Unknown enabled-layer tokens
|
||||
reject the layer payload; unknown option tokens are ignored. Restoration
|
||||
- The registry seals only after every production layer registers, and every
|
||||
layer has an explicit serialization disposition. Unknown, empty, or repeated
|
||||
enabled-layer tokens reject the whole layer payload (`l=` alone is the valid
|
||||
explicit-empty form); unknown option tokens are ignored. Restoration
|
||||
settles independently per layer so one failed or unavailable source cannot
|
||||
block its siblings.
|
||||
- Layer tokens are permanent public compatibility identifiers. The reservation
|
||||
JSON ledger at `src/data/layerStateTokenReservations.json` pins all existing
|
||||
one-character assignments (all letters plus `1` and
|
||||
`2` on current `main`) even if a layer is later removed. New layers allocate
|
||||
the remaining unreserved single-character digits first (`0`, then `3`
|
||||
through `9` on current `main`), then the next unreserved two-character
|
||||
base-36 token (`00` through `zz`) after rebasing onto the merge-time `main`;
|
||||
the dot-delimited v2 codec accepts both widths without changing existing
|
||||
links or the schema version. The contributor
|
||||
check reads the complete published JSON ledger from `origin/main`, including
|
||||
retired reservations, so later assignments cannot silently replace published
|
||||
ones. The pre-ledger base is accepted only at its known source blob; unknown
|
||||
historical shapes fail closed.
|
||||
Pull-request CI runs this check against `origin/main`.
|
||||
- `scripts/qa-layer-token-twochar.mjs` simulates exhaustion of the earlier
|
||||
digit slots and injects a no-network `00` layer only into isolated dev-browser
|
||||
responses. It proves encoding, a cold-recipient reload, restoration, explicit
|
||||
OFF, and legacy-token compatibility. This is synthetic
|
||||
end-to-end evidence, not production allocation: `00` remains unreserved until
|
||||
the first eligible real layer receives it after the free digits through the
|
||||
normal allocation process and passes its own application share/reload check.
|
||||
- Stable visible options are limited to aircraft 3D mode, selected civilian and
|
||||
military flight IDs, Satellite catalog and selection, CCTV coverage/projection/
|
||||
auto-hop, and Radio filter/volume. Playback and tuning, live-data health,
|
||||
@@ -3716,7 +3917,36 @@ are omitted rather than framing the wrong part of the globe.
|
||||
|
||||
- Runtime entry: `src/main.js` calls `initAnnotations({ viewer, tileset })`, exposes `window.__gevAnnotations`, and passes the engine into the voice action runner.
|
||||
- Engine contract: `src/annotations/annotationEngine.js` owns annotation state, TTL/fade lifecycle, concurrent anchor resolution, duplicate detection keyed on geometry, cancellation on clear/newer generations, and a hard cap of 120 live marks. Deferred outline upgrades drain FIFO at concurrency 2; queued work retains the owning abort controller and is discarded on a generation change before it can fetch.
|
||||
- Resolver contract: `src/annotations/annotationResolver.js` converts names/coords/screen pixels into world anchors and optional geometry. The resolver is type-aware: Google Geocode/Places gives a centroid + scope, OSM/Overpass supplies admin/place/footprint/street/enclosing-area geometry, route requests use `/api/route`, and ambiguous/far results are rejected or recovered near the current view instead of drawing misleading blobs. Only explicitly country/state/county-scoped asks bypass near-view recovery and proximity gating; state scope requires a leading `state of …`/`the state of …` phrase, while bare names, proper names ending in “State,” and administrative geocode result types alone remain guarded. Overpass throttles remain distinct from normal transients: `Retry-After` is honored for one retry, and a repeated throttle ends only that mark's outline upgrade.
|
||||
- Resolver contract: `src/annotations/annotationResolver.js` converts names/coords/screen pixels into world anchors and optional geometry. The resolver is type-aware: Google Geocode/Places gives a centroid + scope, operator-configured OSM/Overpass supplies admin/place/footprint/street/enclosing-area geometry, route requests use `/api/route`, and ambiguous/far results are rejected or recovered near the current view instead of drawing misleading blobs. Only explicitly country/state/county-scoped asks bypass near-view recovery and proximity gating; state scope requires a leading `state of …`/`the state of …` phrase, while bare names, proper names ending in “State,” and administrative geocode result types alone remain guarded. Overpass throttles remain distinct from normal transients: `Retry-After` is honored for one retry, and a repeated throttle ends only that mark's outline upgrade.
|
||||
- With no detailed-feature capability, annotations retain their pins and say
|
||||
"Detailed outline unavailable"; location focus reports the same result without
|
||||
retrying. Missing capability never synthesizes an outline from a radius.
|
||||
Manual geometry, bundled neighborhoods, Natural Earth regions and bundled
|
||||
state/province/county outlines remain.
|
||||
- County queries rank eligible US counties and international admin-1 units together, retaining exact aliases and country/state qualifiers.
|
||||
- Bundled administrative outlines (`src/data/adminBoundaries.js`): states and
|
||||
provinces worldwide (Natural Earth admin-1,
|
||||
`src/data/local_data/natural_earth/states_provinces.json`) and US counties
|
||||
and county equivalents (US Census Bureau,
|
||||
`src/data/local_data/us_census_counties/counties.json`), both public domain
|
||||
and rebuilt by `scripts/build-admin-packs.mjs`. An area ask whose words name
|
||||
a unit ("Texas", "TX", "State of Texas", "Bavaria", "Travis County, Texas",
|
||||
"Orleans Parish") is drawn from the pack before any geocode: no network
|
||||
request, no proximity gate, no outline pending. Same-named units go to the
|
||||
state/country qualifier, then the one under or nearest the camera
|
||||
("Washington County"); every qualifier must place the unit ("Travis County
|
||||
Courthouse, Texas" is not the county). A bare name answers alone only for a
|
||||
prominent unit (a US state, a Canadian province, Bavaria) or a city-state
|
||||
(Berlin, Vienna), and never when it is also a country or a city
|
||||
("Georgia", "New York", "Santa Fe", "Victoria") or a generic word
|
||||
("North"); those, and smaller units ("Kent", "Long Island"), are left to
|
||||
the geocoder. When the geocoder types the place as a state or county, the
|
||||
unit carrying the name and containing the geocoded point is drawn from the
|
||||
pack before any Overpass query (a US county first, so "New York County" is
|
||||
Manhattan). Outlines keep every part and hole (`anno.polygons`: Hawaii's islands,
|
||||
Berlin inside Brandenburg). Each pack loads on the first ask that needs it,
|
||||
never at start-up; the analyst region lookup uses the same packs. Gate:
|
||||
`scripts/qa-admin-outlines.mjs`.
|
||||
- Renderer contract: `src/annotations/hybridAnnotationRenderer.js` routes draped `area`/`route` geometry to world-space Cesium rendering and reticles/pins/arrows/callouts to the screen-space SVG renderer. Area labels are screen-space callouts so all captions share one visual language; progressive outline upgrades convert the existing screen group in place when the anchor snaps to the resolved centroid.
|
||||
- Tooling: voice has `annotate_map` and `clear_annotations` tools. Annotations accumulate and persist by default; clearing is explicit only. Partial failures, approximate synthesized zones, and route fallbacks are returned as structured tool results so the voice layer can be honest.
|
||||
- Console/dev API: `window.__gevAnnotations.tour()`, `.demo()`, `.annotate()`, `.clear()`, `.count()`, and `.list()` are the deterministic no-mic test surface.
|
||||
@@ -3839,8 +4069,8 @@ are omitted rather than framing the wrong part of the globe.
|
||||
- `AISSTREAM_API_KEY` is server-side only; the browser reads the same-origin `/api/ais-live` cache.
|
||||
- `/api/google/nearby-places` keeps the Google key out of Places requests issued for voice scene context.
|
||||
- `/api/google/text-search` keeps the Google key server-side for view-biased Places recovery used by annotation resolution.
|
||||
- `/api/overpass` is bounded by body/response caps, per-client/global rate limits, concurrency limits, mirror fallback, in-flight dedupe, cache bounds, and static validation that every selector is spatially bounded.
|
||||
- `/api/military-installations` uses an independent limiter with the same 90-per-client/300-global one-minute bounds, so viewport installation refreshes never consume `/api/overpass` annotation/traffic capacity.
|
||||
- `/api/overpass` is bounded by body/response caps, per-client/global rate limits, concurrency limits, operator-configured upstreams, in-flight dedupe, cache bounds, and static validation that every selector is spatially bounded.
|
||||
- `/api/military-installations` uses an independent limiter with the same 90-per-client/300-global one-minute bounds, so viewport installation refreshes never consume `/api/overpass` annotation capacity.
|
||||
- `/api/route` proxies bounded OSRM route requests for annotation routes, with profile allowlisting, distance caps, response caps, caching, and sanitized "no route found" errors.
|
||||
- Track endpoints: `/api/ais-live/track?mmsi=` (server-accumulated ring buffers; sub-route handled before the rows snapshot), `/api/opensky-track?icao24=` (OAuth, 60s cache, sanitized errors, independent OpenSky credit bucket), `/api/adsblol/trace?hex=` (60s cache, 5MB cap, ODbL attribution required in UI).
|
||||
- Realtime debug logs redact API keys, bearer tokens, client secrets, and image data URLs before writing to disk; request bodies are size-capped.
|
||||
@@ -3925,12 +4155,12 @@ are omitted rather than framing the wrong part of the globe.
|
||||
be enabled, and a civilian or military aircraft must be tracked. The visible
|
||||
Cockpit actions and the `C` shortcut use the same gate, so ordinary standalone
|
||||
flight-layer selection cannot enter a context-dependent cockpit.
|
||||
- **Aircraft cockpit view:** selecting a commercial or military aircraft reveals a `COCKPIT` action (`C`). Cockpit mode temporarily releases Cesium's orbit-follow transform and drives a first-person camera from the tracked aircraft's existing smoothed display position and course. Its concave helmet-visor HUD shows callsign, UTC time, coordinates, curved roll/pitch guides, and a seven-division heading tape. Ambient commercial and military AIR contacts use a Cockpit near/far band selected by the shared Display 3D mode: Proximity admits at 150 km and retains to 185 km; All admits at 400 km and retains to 450 km. The shared 3D toggle now applies in Cockpit: Off keeps in-range contacts as rotating 2D aircraft silhouettes, while On lets a ready admitted glTF take over without a drawing gap. The Cockpit model cap remains 60 and can only lower the map budget; in-range contacts that are capped or still loading remain 2D silhouettes instead of degrading to out-of-range dots. Contacts outside the selected band use small rotation-free cyan-white pips for civilian aircraft and amber pips for military. The pilot's own airframe is not drawn in first person, and exiting clears the Cockpit band and restores normal map silhouettes/models. The normal left accordion remains available for Layers and Scenes and keeps the same 26vh HUD-aligned anchor used in map mode, independent of whether the bottom-left Contact card is expanded or collapsed; the right-rail CCTV and Context chooser are hidden to avoid duplicating or overlapping the cockpit presentation. When the intelligence HUD is enabled, its classification, scene summary, collection/orbit metadata, coordinates, and imaging-status text remain visible as reduced peripheral cockpit telemetry; the optical center and flight instruments stay clear, and turning the HUD off still hides it. Ground speed, exact heading, and rendered altitude form one compact lower-center instrument cluster, keeping the horizon and peripheral view open. A second live altitude tape hugs the inside-right visor rim: its rail and nine moving ticks are derived from the same responsive keyhole radius, remain 20 px inside the circular edge even on wide displays, fade deeply at both vertical ends, and move continuously behind a fixed current-altitude pointer; its interval tightens automatically near the surface and it is suppressed on narrow screens. Cockpit mode also has a weather-backed transparent volumetric-cloud pass derived from the supplied FBM/domain-warped R&D shader. It renders at no more than 520×320, uses 24 ray steps/three FBM octaves at 12 FPS, is clipped to the visor, fails clear when Open-Meteo is unavailable, and stops its animation completely on cockpit exit. It does not restore the prior CPU weather canvases, precipitation, scene fog, or any map-mode effect. When Contacts is active for the tracked aircraft, the compact `CONTACT` rail adds the 250 km subject window, four cohort counts, nearest observed/mapped example with relative bearing and distance, freshness, explicit uncertainty, and Previous and Next controls plus its own collapse control. The mirrored right rail is a three-page **cockpit briefing carousel**: source-backed live signals, location-matched regional headlines, and local place/current-weather context from OpenStreetMap Nominatim and Open-Meteo. It is manual-first: Previous, Next, and direct page controls are always available, and the visible `CYCLE OFF` / `CYCLE ON` control starts or stops the nine-second page cycle. The cycle pauses on hover or keyboard focus and stops while collapsed, hidden, or outside cockpit mode; live signal data continues refreshing either way. Empty news matches and unavailable news use compact text states rather than reserving an empty media frame; partial local data remains explicit. Article links open their original publisher, and no headline is treated as verified risk intelligence. On desktop both cockpit rails use the same width and share a bottom-aligned safe baseline in opposite corners above the peripheral MGRS/GSD/time telemetry, leaving both that text and the lower-center instrument cluster readable. They collapse independently to slim tabs without stopping live data updates. Narrow screens use separated top/bottom fallbacks. Empty-space globe clicks are inert while cockpit owns the camera; `C`, `Escape`, or `EXIT COCKPIT` explicitly exits and restores the same tracked entity and standard follow camera. Unknown feeds remain unknown, selection loss still exits safely without inventing a replacement track, and the cockpit never presents the summary as threat scoring or an all-clear. This is a desktop first-person presentation, not a WebXR session.
|
||||
- **Aircraft cockpit view:** selecting a commercial or military aircraft reveals a `COCKPIT` action (`C`). Cockpit mode temporarily releases Cesium's orbit-follow transform and drives a first-person camera from the tracked aircraft's existing smoothed display position and course. Its concave helmet-visor HUD shows callsign, UTC time, coordinates, curved roll/pitch guides, and a seven-division heading tape. Ambient commercial and military AIR contacts use a Cockpit near/far band selected by the shared Display 3D mode: Proximity admits at 150 km and retains to 185 km; All admits at 400 km and retains to 450 km. The shared 3D toggle now applies in Cockpit: Off keeps in-range contacts as rotating 2D aircraft silhouettes, while On lets a ready admitted glTF take over without a drawing gap. The Cockpit model cap remains 60 and can only lower the map budget; in-range contacts that are capped or still loading remain 2D silhouettes instead of degrading to out-of-range dots. Contacts outside the selected band use small rotation-free cyan-white pips for civilian aircraft and amber pips for military. The pilot's own airframe is not drawn in first person, and exiting clears the Cockpit band and restores normal map silhouettes/models. The normal left accordion remains available for Layers and Scenes and keeps the same 26vh HUD-aligned anchor used in map mode, independent of whether the bottom-left Contact card is expanded or collapsed; the right-rail CCTV and Context chooser are hidden to avoid duplicating or overlapping the cockpit presentation. When the intelligence HUD is enabled, its classification, scene summary, collection/orbit metadata, coordinates, and imaging-status text remain visible as reduced peripheral cockpit telemetry; the optical center and flight instruments stay clear, and turning the HUD off still hides it. Ground speed, exact heading, and rendered altitude form one compact lower-center instrument cluster, keeping the horizon and peripheral view open. A second live altitude tape hugs the inside-right visor rim: its rail and nine moving ticks are derived from the same responsive keyhole radius, remain 20 px inside the circular edge even on wide displays, fade deeply at both vertical ends, and move continuously behind a fixed current-altitude pointer; its interval tightens automatically near the surface and it is suppressed on narrow screens. Cockpit mode also has a weather-backed transparent volumetric-cloud pass derived from the supplied FBM/domain-warped R&D shader. It renders at no more than 520×320, uses 24 ray steps/three FBM octaves at 12 FPS, is clipped to the visor, fails clear when Open-Meteo is unavailable, and stops its animation completely on cockpit exit. It does not restore the prior CPU weather canvases, precipitation, scene fog, or any map-mode effect. When Contacts is active for the tracked aircraft, the compact `CONTACT` rail adds the 250 km subject window, four cohort counts, nearest observed/mapped example with relative bearing and distance, freshness, explicit uncertainty, and Previous and Next controls plus its own collapse control. The mirrored right rail is a three-page **cockpit briefing carousel**: source-backed live signals, location-matched regional headlines, and physical-region/current-weather context from bundled Natural Earth polygons and Open-Meteo. It is manual-first: Previous, Next, and direct page controls are always available, and the visible `CYCLE OFF` / `CYCLE ON` control starts or stops the nine-second page cycle. The cycle pauses on hover or keyboard focus and stops while collapsed, hidden, or outside cockpit mode; live signal data continues refreshing either way. Empty news matches and unavailable news use compact text states rather than reserving an empty media frame; partial local data remains explicit. Article links open their original publisher, and no headline is treated as verified risk intelligence. On desktop both cockpit rails use the same width and share a bottom-aligned safe baseline in opposite corners above the peripheral MGRS/GSD/time telemetry, leaving both that text and the lower-center instrument cluster readable. They collapse independently to slim tabs without stopping live data updates. Narrow screens use separated top/bottom fallbacks. Empty-space globe clicks are inert while cockpit owns the camera; `C`, `Escape`, or `EXIT COCKPIT` explicitly exits and restores the same tracked entity and standard follow camera. Unknown feeds remain unknown, selection loss still exits safely without inventing a replacement track, and the cockpit never presents the summary as threat scoring or an all-clear. This is a desktop first-person presentation, not a WebXR session.
|
||||
- **Cockpit left-panel clearance:** the Cockpit Contact card and peripheral HUD participate in the adaptive left accordion's live obstacle measurements, including live viewport-height changes. Expanding Layers or Scenes keeps the active panel in the available upper-left corridor with internal scrolling; it does not cover the Contact card, lower Cockpit controls, or Cesium credit line. Outside Cockpit the hidden card does not alter the normal corridor.
|
||||
- **Cockpit Context scope:** the 250 km radius applies to the air/sea proximity cohorts. Installation counts come only from the currently loaded viewport and are labeled `CURRENT VIEWPORT ONLY` in the cockpit as well as the normal Context panel; neither surface presents them as a complete 250 km installation survey.
|
||||
- **Cockpit camera anchor:** first-person mode does not write feed-boundary corrections directly into the camera. A cockpit-only inertial anchor advances from the selected aircraft's displayed course and speed, then converges toward the authoritative delayed track with correction capped below forward motion. The displayed kinematics are derived from the same consecutive fix segment as the rendered position, with raw feed speed/course used only as fallback; a transient zero/missing feed speed therefore cannot freeze a visibly moving aircraft after layer enable or a map/cockpit handoff. Rendered altitude continues to come from that interpolated track position. Late ADS-B fixes and short render stalls can remove drift without accelerating or reversing the view. Camera placement runs before scene update/culling at a bounded 20 Hz so a moving cockpit does not force Photoreal 3D Tiles to retraverse on every display frame; textual instruments update at 10 Hz and context/layout work at 4 Hz. Every far Cockpit contact pip shares one stable Cesium texture-atlas entry and skips unused screen-projected course calculations, while only in-range 2D aircraft silhouettes pay the screen-projected rotation cost; ambient glTF collections are hidden/retained rather than synchronously destroyed at cockpit entry, and context rails lay out only on explicit content/state changes and viewport resize. The deliberate 15/30-second layer interpolation delays and per-Cesium-frame position caches remain unchanged.
|
||||
- **Cockpit route, vision, and view controls:** visible on-screen `COCKPIT`, `RESET`, and `EXIT COCKPIT` controls replace reliance on the `C` shortcut. RESET uses the same canonical globe route as the map and voice actions, exits Cockpit, and releases its camera ownership rather than exposing the hidden map-style top action. When the tracked commercial flight has a plausible ADSBDB route, the top of the right briefing rail shows a compact `FROM → TO` airport strip and the visor shows a centered estimated-destination chevron with its relative bearing; absent or implausible route data hides the strip and cue rather than guessing. The cockpit-local vision control is an interactive `PREV / CURRENT / NEXT` carousel over the inherited map preset, `CRT`, `NVG`, `FLIR`, and `NOIR`; its previous/next actions wrap, and activating the current value advances to the next style. The inherited entry is named directly, such as `NOIR`, and retains that map shader. There is no empty `NONE` entry. CRT, NVG, FLIR, and NOIR temporarily activate the existing Cesium post-process stages, while returning to the inherited entry or exiting Cockpit restores the pre-entry visual style. The regional-news page uses a free Google News RSS locality query first, with the existing GDELT query retained only as a fail-soft fallback; linked headlines remain reporting, not verified incidents or risk intelligence.
|
||||
- **Cockpit weather status:** the earlier multi-canvas atmospheric compositor remains fail-closed and is not attached to the live viewer. Cockpit clouds are a separate transparent WebGL pass with a capped 520×320 framebuffer, 24 ray steps, three FBM octaves, and a 12 FPS ceiling. It defaults off and starts only when local storage explicitly contains the persisted `WX ON` opt-in (`'1'`). When opted in, observations refresh after five minutes or 25 km of aircraft movement, fail transparent when unavailable or clear, and stop on exit or disable. `WX OFF` governs atmospheric rendering only: the briefing still fetches source-backed Nominatim, headline, and Open-Meteo local-information data, aborting and replacing any in-flight request when the selected aircraft changes. No weather effect runs in map mode and no synthetic fallback is shown.
|
||||
- **Cockpit weather status:** the earlier multi-canvas atmospheric compositor remains fail-closed and is not attached to the live viewer. Cockpit clouds are a separate transparent WebGL pass with a capped 520×320 framebuffer, 24 ray steps, three FBM octaves, and a 12 FPS ceiling. It defaults off and starts only when local storage explicitly contains the persisted `WX ON` opt-in (`'1'`). When opted in, observations refresh after five minutes or 25 km of aircraft movement, fail transparent when unavailable or clear, and stop on exit or disable. `WX OFF` governs atmospheric rendering only: the briefing still fetches source-backed Natural Earth region, headline, and Open-Meteo local-information data, aborting and replacing any in-flight request when the selected aircraft changes. No weather effect runs in map mode and no synthetic fallback is shown.
|
||||
- **Cockpit trail visibility:** entering cockpit hides the selected aircraft's trail body and head so they cannot cross the first-person view; exit restores them. This cockpit-only presentation change does not alter the normal map-mode invariant that aircraft trails render through terrain using their depth-fail material.
|
||||
- **Aircraft course slew:** civilian and military 3D models retain the 60°/s course limiter, but each rendered frame can consume at most 250 ms of accumulated slew time. A long tile/render stall therefore catches up over multiple visible frames instead of turning one delayed frame into a heading snap.
|
||||
- **Manual-first cockpit briefing:** the right-side Live Signals / Regional News / Local Info carousel does not advance automatically on page load. Previous, Next, and direct page controls remain available; the visible `CYCLE OFF` / `CYCLE ON` toggle explicitly starts or stops the nine-second page cycle, which still pauses on hover/focus and while collapsed, hidden, or outside cockpit mode. Live signal data continues refreshing in either state.
|
||||
@@ -4077,7 +4307,7 @@ easier to meet (detection is now on more often), but does not create it.
|
||||
`SIMULATED — traffic service unreachable`; a total flow-fetch failure in live
|
||||
mode sets `error` (DEGRADED · `SIMULATED — <reason>`) and zeroes the stale
|
||||
coverage number. `stats.loading` covers outstanding flow work as well as the
|
||||
road fetch, so a failure landing after the 250 ms paint race still ends the
|
||||
road fetch, so a flow failure landing after the first paint still ends the
|
||||
shared loading batch as LOAD FAILED. Harnesses must gate on `!stats.error`,
|
||||
never on `mode === 'live'` alone.
|
||||
- Traffic runs in `sim` mode (white dots, hardcoded speeds) unless `TOMTOM_API_KEY`
|
||||
@@ -4085,14 +4315,168 @@ easier to meet (detection is now on more often), but does not create it.
|
||||
TomTom flow vector tiles via the budget-governed `/api/tomtom` proxy
|
||||
(`.gev-cache/tomtom/`, 120 s TTL, `TOMTOM_DAILY_TILE_BUDGET` default 6k/day,
|
||||
sized so a 31-day month stays inside TomTom's 200K/month free allowance),
|
||||
decoded client-side (`flowTiles.js`), matched onto Overpass roads
|
||||
(`flowMatch.js`), and rendered as green/amber/red dot color + speed/density
|
||||
scaling (`trafficFlowStyle.js`); closures spawn no dots; unmatched roads stay
|
||||
white. Road fetch bounds center on the camera look-at point (`trafficBounds.js`).
|
||||
decoded client-side for green/amber/red dot color and speed/density scaling
|
||||
(`trafficFlowStyle.js`).
|
||||
- Road source (`src/layers/traffic/roadModes.js`): the Street Traffic row has
|
||||
TomTom / OSM / Hybrid chips (`roadMode` param, stored in the existing layer
|
||||
state `lo` field, no new share token); `?trafficRoads=tomtom|osm|hybrid`
|
||||
overrides restored state until the user picks a chip. With no stored choice
|
||||
the default is Hybrid with a TomTom key and OSM without one; share links
|
||||
without a road-source choice (including older ones) likewise use the
|
||||
installation's default (Hybrid when keyed, OpenStreetMap when keyless). Without a key
|
||||
every choice draws OSM roads and the status says the choice needs a key.
|
||||
TomTom draws only flow-tile lines with their own flow; roads without flow
|
||||
are not drawn and the status says so. A `full`-coverage flow line carries
|
||||
both travel directions, a `one_side` line the direction it is drawn in.
|
||||
OSM draws OpenFreeMap roads with flow matched onto them (below). Hybrid
|
||||
draws eligible TomTom motor-road lines and adds OpenFreeMap roads only where no eligible TomTom line
|
||||
runs within 35 m in the same travel direction (30 degrees), tested every
|
||||
10 m; only uncovered stretches of at least 40 m are kept, and they are
|
||||
simulated. When exactly one side is a motorway/trunk mainline (TomTom
|
||||
`Motorway`/`International road`; OSM ramps count as ordinary roads) the
|
||||
radius is 15 m, so public frontage roads beside a freeway stay. Flow values are ignored for this test, so an uncertain overlap
|
||||
drops the OpenFreeMap copy, never the TomTom line; opposite carriageways
|
||||
stay. OpenFreeMap tiles stream first and are drawn plain until flow
|
||||
arrives, then one replacing snapshot applies the TomTom lines and dedupe.
|
||||
Status examples: `LIVE · Roads: TomTom · Roads without flow hidden`,
|
||||
`LIVE · Roads: TomTom + OpenStreetMap · Flow 81%`; Hybrid with no TomTom
|
||||
line in view names OpenStreetMap alone. TomTom mode skips the z14 detail
|
||||
pass and never requests OpenFreeMap unless it falls back without a key.
|
||||
Matching reuses `flowMatch.js`: seven road samples, a 35 m nearest-segment
|
||||
radius, 30 degree travel-bearing tolerance, and a bounded
|
||||
3x3 probe in a 100 m spatial grid. At least half the samples must match;
|
||||
the median flow level supplies speed/color and any matched closure stops
|
||||
dots in that travel direction. Two-way roads have independent forward/reverse
|
||||
records; one-way direction is enforced. Equal-distance candidates with
|
||||
contradictory flow/closure are left simulated. Matching runs only on load/refresh, never per frame.
|
||||
Flow stays at z12 with the same 16-tile cap, 120-second cache and server
|
||||
daily budget. Lines are clipped to tile cores before caching and to the
|
||||
look-at viewport fetch box before road conversion or matching. Unmatched
|
||||
roads retain white simulated dots at free-flow speeds (unless the explicit
|
||||
uncovered-roads hide option is enabled). Cached OSM road snapshots are
|
||||
rematched on every load; TomTom and Hybrid views are recomposed from the
|
||||
bounded tile caches each load because their roads carry flow. A snapshot
|
||||
is cached only when the load drew plain OpenStreetMap roads, and the cache
|
||||
is not read before the TomTom status probe settles (except for an explicit
|
||||
OSM choice), so Hybrid fill is never replayed as OSM roads. Failed flow
|
||||
refreshes clear old matches and report simulation. `flowCoveragePct` is the
|
||||
percentage of shown dots on roads with flow, including all unmatched dots in
|
||||
the denominator and excluding dots hidden by closures. The OSM keyed status
|
||||
reads `LIVE · Roads: OpenStreetMap · Flow: TomTom · N% cov`. Road fetch
|
||||
coverage follows a 5×5 ellipsoid sample of the central screen square.
|
||||
Horizon rays are capped at 10 km from nadir (reduced if necessary to fit
|
||||
16 z12 tiles); polygon-intersecting tiles load nearest first. Up to 16 z14
|
||||
tiles provide near detail, with z12 roads beyond them. Cached tiles serve
|
||||
revisits without requests, and settled coverage replaces the box-overlap gate.
|
||||
- OSM geometry (OSM mode and Hybrid fill) comes from OpenFreeMap's immutable versioned tiles:
|
||||
successful TileJSON metadata prefetched at enable and cached for the source lifetime, z12 wide pass and
|
||||
z14 detail below 4.5 km. The nearest 16 intersecting detail tiles cover the
|
||||
near field; coarse roads remain outside successfully loaded detail cores.
|
||||
Partial coverage retains coarse roads under missing tiles and retries at most
|
||||
three times with bounded backoff, reusing successful tiles. A failed detail pass retains major roads and separately
|
||||
reports "Detailed roads unavailable". OpenMapTiles admits motorway, trunk,
|
||||
primary, secondary, tertiary and minor roads, excluding access restrictions,
|
||||
path subclasses, indoor ways and tunnels. Bridges and ramps inherit the motor
|
||||
road's eligibility; the ramp flag alone never admits a path. Service ways,
|
||||
including untyped ones, parking aisles, driveways, drive-throughs and alleys,
|
||||
are excluded: their tiles do not establish public through traffic. TomTom
|
||||
admits only its eight named motor-road types, rejecting Non public road,
|
||||
Parking road, Walkway road and unknown categories for geometry, flow matching
|
||||
and Hybrid deduplication. Eligibility follows provider classification; omitted
|
||||
or incorrect upstream restrictions remain a source limitation.
|
||||
Only eligible road geometry receives dots;
|
||||
reverse one-way lines are reversed. The shared tile source caps each view at
|
||||
16 tiles per pass (32 OpenFreeMap tiles total), four concurrent requests and 4 MiB per response. OpenFreeMap retains
|
||||
up to 192 decoded tiles/64 MiB (four times body bytes as a storage estimate);
|
||||
other tile sources retain the 64-tile/24 MiB defaults. Identical source-version/XYZ
|
||||
requests share one download/decode, with independent caller cancellation. Parsed road views have a separate 24 MiB/64-entry cap; incomplete
|
||||
views are not retained as complete snapshots. Buffer geometry is clipped and sub-12 m line slivers dropped; tile
|
||||
road fragments are not stitched. Roads preserve bends and insert
|
||||
waypoints at most 150 m apart, splitting paths at 80 vertices. A cancellable
|
||||
preparation pass paints decoded tiles independently. Explicit enable starts
|
||||
acquisition immediately; camera gestures retain the 320 ms settle debounce,
|
||||
but moveEnd starts the final view immediately. Detail acquisition runs alongside
|
||||
the major preview, using the same bounded tile cache. Once dots exist they stay
|
||||
alive until the detail snapshot replaces them, avoiding repeated preview picks.
|
||||
Status/flow and roads start
|
||||
concurrently; neither TileJSON repeat reads nor flow impose a paint barrier.
|
||||
Only dot-budget-admitted roads crossing the canvas (100 px margin), within
|
||||
the bounded reticle range, receive surface work. Near and upper-screen roads
|
||||
share the height-station budget, with fewer dots on distant roads.
|
||||
Roads split into deterministic chunks no longer than 600 m, preserving every
|
||||
bend while keeping dot budgets on nearby street sections. Height stations
|
||||
are at most 150 m apart along the road, with heights
|
||||
interpolated over the preserved intervening bends. On photoreal maps, surface
|
||||
preparation first reuses rendered depth. Up to four height/projection iterations
|
||||
must converge within 2 m of the road coordinate; foreground hits, invalid heights,
|
||||
off-canvas points and translucent-depth picking fall back to the existing mesh
|
||||
sampler. Depth and settled-height certification require a completed render of
|
||||
the current camera and surface. This avoids redrawing a pick frustum for every visible station. Preparation yields after a 12 ms slice (an individual synchronous Cesium pick
|
||||
cannot be preempted). Validated coordinate heights use a per-scene 40,000-point
|
||||
LRU across loads. The LRU belongs to the surface it sampled (the terrain
|
||||
provider, or the set of visible 3D tilesets), so a map-provider switch
|
||||
drops it. Each height records its detail band (log2 of the camera-to-point
|
||||
distance in 100 m steps); a point seen from a closer band is re-sampled
|
||||
against the finer mesh, and a failed finer sample keeps the coarser one.
|
||||
Revisits at the same or a coarser band sample nothing. Provisional shared-floor estimates remain hidden until a
|
||||
local rendered-mesh/terrain sample resolves; a globally loading tileset does
|
||||
not block streets whose mesh is already present. Non-finite/out-of-band
|
||||
(+/-9000 m) samples defer their road and show a local-surface status, never
|
||||
an OpenFreeMap failure. Samples floor on cached ground/visible terrain.
|
||||
Samples acquired during refinement are revalidated when the visible mesh settles.
|
||||
Shared floor cells are read only; raw mesh samples never enter their cache.
|
||||
Roads retain their dot populations by source, geometry and travel direction.
|
||||
Partial tiles add roads without clearing the point collection; full source
|
||||
snapshots replace the accumulated graph in every road mode; completed
|
||||
snapshots retire only roads that disappeared. Density changes apply at most
|
||||
768 additions/removals per animation frame, with 180 ms growth/fades. The
|
||||
total cap stays 6,000 at street level and scales by (1,000 / altitude)^2
|
||||
above 1 km (about 667 at 3 km, minimum 400). Surface admission shares that
|
||||
budget, plus a deterministic 1,000-unique-height-station ceiling, nearest roads
|
||||
first (`surfaceBudgetOmitted` reports roads outside that ceiling). Below 4.5 km the wide pass prepares a 32-road preview before the
|
||||
complete detail pass; previews never wait/retry missing mesh or retire existing
|
||||
roads. Full coarse coverage remains available above that band.
|
||||
Flow matching is memoized for admitted roads within each camera load. Surviving
|
||||
dots keep their identity, road, direction and progress. Flow updates change
|
||||
color, speed and closures in place. Dots use normal depth testing, including
|
||||
jammed traffic, so buildings occlude roads behind them. Surface preparation is reused within a
|
||||
camera load. A local height estimate selects the provisional viewport in
|
||||
elevated cities; measured preview heights and rendered center depth refresh
|
||||
it before detail selection. It never admits unmeasured dots. Spacing uses
|
||||
height above that local surface, retaining street density at high elevations; later heights ease into separate retained waypoint arrays,
|
||||
bounded to 12 projected pixels per waypoint per frame near the canvas with reused
|
||||
scratch objects. Visible waypoints keep that limit even when a trial step leaves
|
||||
the canvas; unsafe near-plane steps shrink before publication. Off-screen corrections use bounded world-space easing and do not
|
||||
hold loading open. Road acquisition and body reads have cancellable deadlines. Queued tile paints
|
||||
and terrain callbacks share pass cancellation; expired passes cannot publish,
|
||||
while completed coarse roads remain available. The traffic status chip polls
|
||||
busy work every 100 ms and completes without a split-flap delay; idle and global
|
||||
status reads keep their 500 ms cadence. Refinement is one bounded pass, never a
|
||||
publish loop. That pass replaces early cached mesh heights even in the same
|
||||
distance band: tilesets can briefly report loaded before finer destination
|
||||
tiles begin streaming. Ordinary revisits still reuse validated cached heights.
|
||||
At a road endpoint the departing dot fades before a new simulated vehicle
|
||||
identity enters at the other end, preserving one-way travel. Detection uses
|
||||
those stable identities rather than collection slots. `visitMotionDots`
|
||||
exposes identity, road identity, primitive and source classification for the motion gate.
|
||||
`scripts/qa-traffic-motion.mjs` records timestamped CDP frames and checks
|
||||
cold/warm still-camera holds in all three road modes; `--baseline` also
|
||||
measures rebuild churn in older runtimes using primitive object identities.
|
||||
`--journey` adds the South Congress/downtown/Camp Mabry route, layer toggles,
|
||||
Capitol, greenbelt, commercial parking and corridor holds, with a 1.5-second
|
||||
steady-state limit including loading and population changes. It checks every
|
||||
shown dot against the allowed source classes and records phase timings.
|
||||
Positions and segment distances are precomputed, with no new animation-loop
|
||||
allocation. Visible-globe roads use cached terrain without offscreen mesh picks. The road-source label names the geometry being drawn, with partial/unavailable states shown plainly.
|
||||
- TileJSON caches successful metadata. Transient failures retry after a
|
||||
five-second cooldown; invalid metadata/origins stay unavailable until the
|
||||
source is cleared. Clear resets metadata and cancels pending requests.
|
||||
Every failed read cancels its body and aborts its owned request, including
|
||||
declared and streaming byte-cap failures.
|
||||
- Development captures opened with `?trafficDebug=1` mint an interaction anchor
|
||||
from the exact `camera.changed` event that arms each debounced load, then emit
|
||||
scheduling-correlated User Timing entries for production `response.json`, road
|
||||
parse, flow-race, dot construction, heat-line rebuild, and next-post-render
|
||||
parse, dot construction, heat-line rebuild, and next-post-render
|
||||
boundaries. Every trace is paired with the exact camera-change that scheduled
|
||||
its load; mismatches are counted drops. Cesium's `moveEnd` remains a diagnostic
|
||||
mark only: it arrives about 500 ms after stillness, typically after fetch has
|
||||
@@ -4164,11 +4548,11 @@ executable-path lookup before testing or passing the path to Chrome. Supported N
|
||||
|
||||
### Traffic city navigation
|
||||
|
||||
Traffic checks the final camera view on arrival and retries a failed road request
|
||||
while the camera is stationary, backing off from 1.5 to 30 seconds. Failed road
|
||||
requests report an unavailable source. Leaving the traffic altitude range or
|
||||
disabling the layer cancels pending work; superseded road and flow requests cannot
|
||||
release the current request or keep its loading indicator active.
|
||||
Traffic checks the final camera view on arrival. Retryable road failures get
|
||||
at most three parked retries with 1.5–30 second backoff; permanent capability
|
||||
misses stop both the retry timer and enable-time kick. New views can try again.
|
||||
Leaving the traffic altitude range or disabling cancels outstanding work.
|
||||
Superseded road/flow responses cannot publish or refill cleared caches.
|
||||
|
||||
### Optional frame-rate readout
|
||||
|
||||
@@ -4400,3 +4784,55 @@ Desktop wind now allows 7,200 baked native GPU paths (narrow viewports remain at
|
||||
Temperature uses stronger fixed −40..50°C colors; the underlying 1° forecast and
|
||||
numeric inspection values are unchanged. No volumetric cloud height or local rain
|
||||
arrival prediction is claimed. NOAA source limits are documented in DATA_SOURCES.
|
||||
|
||||
|
||||
Traffic source refinements: ALPR admits z9-z12 detail only when the view fits 16 tiles,
|
||||
returning explicit zoom guidance before I/O and allowing the next smaller view to
|
||||
load normally. Outside the US/Canada extracts the row reads “No ALPR data for this
|
||||
area — US and Canada only” and suppresses the nearby count. Military viewport
|
||||
membership checks every merged footprint. Different source identities require
|
||||
topological contact; identity aliases are zoom-scoped so coarse associations cannot join separated
|
||||
detailed parcels.
|
||||
|
||||
Country outlines use the lazy Natural Earth admin-0 pack. UK constituent
|
||||
countries use their own map-unit geometry; parent-country qualifiers stay separate
|
||||
from target aliases. The pack includes substantial
|
||||
islands. Names and aliases resolve offline; ambiguous Georgia follows the
|
||||
camera or an explicit country qualifier. Geocoded country boundaries require
|
||||
both a matching name and containment of the geocoded point.
|
||||
|
||||
Installation camera-load keys belong to their scheduled view; an older aborted
|
||||
request cannot clear a newer view’s pending key.
|
||||
|
||||
Name acquisition has a ten-second deadline and retry cooldown. Close views publish
|
||||
polygons immediately and enrich only the current view when names arrive.
|
||||
Military names load lazily from the separately licensed Overture/OSM pack when
|
||||
installation context needs them. Typed OSM ids join polygon fragments before
|
||||
merging; canonical group identity survives partial views independently of the
|
||||
largest named member supplying the title. Enrichment reconciles canonical ids
|
||||
to the named parent across zooms, migrating selection, context and marker ownership
|
||||
through explicit aliases. Geometry-union evidence stays zoom-scoped. Parent names and other member names
|
||||
remain available across same-zoom pans. Wide views use a viewport-culled, area-ranked grid of at most 512
|
||||
point primitives and 24 decluttered titles. Wide-point and polygon titles share
|
||||
one world-overlay source using the same ambient-card entries, paint lane and persistent
|
||||
label arbitration as datacenters and dams, with a 24-title source ceiling.
|
||||
Camera changes reproject existing markers and titles without source loads or
|
||||
per-frame allocation. Selection promotes the record’s own entry to a selected card;
|
||||
clicking empty ground restores its ambient title without a second readout. Selected
|
||||
footprints receive a 22% outline-colored classification fill on Google 3D tiles or
|
||||
the active terrain, removed on deselect/disable and rebound on map-source changes. Labels follow the host’s Clean-UI behavior; disable/destroy
|
||||
clears the source and removes marker listeners. Named point ids carry into polygon
|
||||
views; wide named points remain until their close polygons publish. Unnamed
|
||||
polygons remain “Military area”.
|
||||
|
||||
Tile sources accept a separate `tileFetchImpl` for public vector tiles; API
|
||||
requests retain `fetchImpl`. The exported Overpass ALPR source uses `/api/overpass`;
|
||||
the standalone layer defaults to the hourly tile source.
|
||||
|
||||
OSM-derived layers share one OpenStreetMap data attribution entry. Displayed
|
||||
OSM data retains a short inline OpenStreetMap credit, plus OpenMapTiles while
|
||||
OpenFreeMap tiles are used; its display follows the existing map-credit rules. Routing, Warendorf cameras,
|
||||
datacenters, dams and the Nepal locator retain that shared credit while displayed.
|
||||
|
||||
Military fragments stitch by source identity. Different mapped parcels merge only
|
||||
when their footprints touch or contain one another, never across a seam tolerance gap.
|
||||
Reference in new issue
Block a user