mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
docs(street-level): shorten docs and comments before merge
Trim the doc text this PR adds (README, CHANGELOG, CURRENT-STATE, KNOWN-ISSUES, SECURITY, DATA_SOURCES, .env.example, the CI job comment), drop code comments that restate the code, cut design-note JSDoc to a line or two, and drop review tags from test names. Comments only; no code changes. Also: README key count (seven keys, two metered), CURRENT-STATE's gate paragraph (CI runs a production build with a dummy token), the stacked doc above meshBoxInRange and the orphaned inMeshRange line in coverage.js, and a duplicate ALPR row in DATA_SOURCES that a merge had brought back. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c65feda4b1
commit
4ea6631425
85 files changed
+701
-1520
No files matched your search
+56
-102
@@ -1474,10 +1474,10 @@ This is the current runtime/source-of-truth snapshot for the project.
|
||||
> samples, `enabling` throughout, panel non-numeric) and across a failing
|
||||
> one. Its `status: 'idle'` is not what saves it — the lifecycle is; the
|
||||
> module has no `loading` status at all.
|
||||
> Any new dependency that can be slow must report `loading` and `lastUpdate`
|
||||
> honestly for the contract to hold, and must be pinned against the shape its
|
||||
> own module really returns — a fixture that invents a status the module cannot
|
||||
> emit guards nothing (that is exactly how a hole here survived a green suite).
|
||||
> Any new dependency that can be slow must report `loading` and `lastUpdate`
|
||||
> honestly for the contract to hold, and must be pinned against the shape its
|
||||
> own module really returns — a fixture that invents a status the module cannot
|
||||
> emit guards nothing (that is exactly how a hole here survived a green suite).
|
||||
> - **A held ground snap is dropped when measured ground contradicts it
|
||||
> (2026-08-23):** the WARM hold described below answers on DISTANCE travelled,
|
||||
> which is only a proxy for whether the value still describes the ground. A
|
||||
@@ -2928,114 +2928,68 @@ its criteria cannot be silently ignored.
|
||||
| Dams ▰ | OpenInfraMap/OSM extract (bundled) | `src/data/localLayers.js` | — | static |
|
||||
| Submarine Cables ◠ | TeleGeography public map (bundled) | `src/data/telegeographySubmarineCables.js` | — | static |
|
||||
| FIRMS Active Fires ▲ | NASA FIRMS live (VIIRS ×3 NRT + MODIS NRT, trailing 24h) | `src/data/firmsHeatmap.js` | `/api/firms` (`FIRMS_MAP_KEY`) | 10 min (proxy TTL 30 min) |
|
||||
| Street Level 📷 | Provider-neutral street-level imagery; Mapillary registered (vector tiles + Graph API + MapillaryJS) | `src/layers/streetLevel/` (core) + `src/layers/streetLevel/providers/mapillary/` via `src/app/layers/streetLevel.js` | `/api/mapillary/status`, `/api/mapillary/tiles/coverage/{z}/{x}/{y}` (`MAPILLARY_CLIENT_TOKEN`) | camera-driven (320 ms debounce, ≤9 coverage tiles, cached 24 h) |
|
||||
| Street Level 📷 | Street-level imagery; Mapillary is the first provider (vector tiles, Graph API, MapillaryJS) | `src/layers/streetLevel/` via `src/app/layers/streetLevel.js` | `/api/mapillary/status`, `/api/mapillary/tiles/coverage/{z}/{x}/{y}` (`MAPILLARY_CLIENT_TOKEN`) | camera-driven (320 ms debounce, ≤9 tiles, cached 24 h) |
|
||||
| Wind 🌬 | NOAA GFS 10 m wind (keyless, 0.25°→1° grid; animated particles) | `src/data/wind.js` | `/api/wind` | 1 h (forecast cycle) |
|
||||
| Fire Perimeters 🔥 | NIFC WFIGS current interagency perimeters (keyless, paged past the 2000-record cap); InciWeb catalog + incident page origin and update time checks for verified incident-page links | `src/layers/perimeters/` via `src/app/layers/perimeters.js` | `/api/fire-perimeters` + `/api/fire-perimeters/inciweb/*` | 5 min (server caches: catalog 1 h; publication 30 min) |
|
||||
|
||||
Fire Perimeters uses capped, timed server reads with stale-on-error caching and a per-client limit. Unchanged snapshots retain geometry; link checks cancel on disable or selection change, and the row legend shows reported containment.
|
||||
|
||||
Street Level lives in the right context rail next to CCTV as an ordinary
|
||||
collapsible panel (`#street-level-panel`, layer share token `0`, option owner
|
||||
`street-level`, panel `ui` token `t`) and starts collapsed. It opens itself
|
||||
only when the user (or voice, or a tool) switches the layer on or a photo
|
||||
opens, never on a saved-state restore, and never stores those automatic opens. It is modelled on the iD editor's photo
|
||||
overlay: one panel, a PROVIDERS chip per registered imagery provider, shared
|
||||
360°/flat and captured-since filters (stored as relative days so a link keeps
|
||||
its meaning), one viewer host, and one on-globe credit per active provider.
|
||||
Each source has one colour (`PROVIDER_COLORS` in
|
||||
`src/layers/streetLevel/policy.js`: Mapillary green `#05cb63`, Panoramax
|
||||
purple, Google Street View blue), used for its chip, coverage lines, overview
|
||||
points, image cones and its single legend swatch; 360° cones are rings, and
|
||||
the selected sequence is GEV cyan. Share options: `m` (Mapillary on/off), `p` (a/p/f panorama mode), `s`
|
||||
(since, days). Only Mapillary is registered in this build. Without
|
||||
`MAPILLARY_CLIENT_TOKEN` the header reads KEY REQUIRED, the Mapillary chip
|
||||
turns amber and the controls stay disabled; with it, coverage draws as
|
||||
ground-clamped sequence lines (z0–5 overview points from orbit, z11–14
|
||||
sequences below 60 km) and the proxy strips the unused `image` point layer
|
||||
from z14 tiles in transit (12 MB → ~80 KB). Concurrent requests for one tile
|
||||
share a single upstream fetch that owns its own abort controller: a request
|
||||
that is abandoned leaves at once without cancelling the others, and the fetch
|
||||
is cancelled only when its last waiter leaves.
|
||||
Street Level is a collapsible right-rail panel (`#street-level-panel`, layer
|
||||
token `0`, option owner `street-level`, panel `ui` token `t`) that starts
|
||||
collapsed. It opens itself only when the user, voice or a tool switches the
|
||||
layer on or a photo opens, never on a restore, and those opens are not stored.
|
||||
Like the iD editor's photo overlay, it has one chip per registered provider,
|
||||
shared 360°/flat and captured-since filters (relative days, so a link keeps its
|
||||
meaning), one viewer host and one on-globe credit per active provider. Each
|
||||
provider draws in one colour (`PROVIDER_COLORS` in
|
||||
`src/layers/streetLevel/policy.js`); 360° cones are rings and the selected
|
||||
sequence is GEV cyan. Share options: `m` (Mapillary), `p` (`a`/`p`/`f`
|
||||
panoramas), `s` (since, days). Only Mapillary is registered. Without
|
||||
`MAPILLARY_CLIENT_TOKEN` the panel reads KEY REQUIRED and the controls are
|
||||
disabled. With it, coverage draws as z0–5 overview points from orbit and z11–14
|
||||
sequence lines below 60 km; the proxy strips the unused `image` layer from z14
|
||||
tiles (12 MB → ~80 KB) and shares one upstream fetch between concurrent
|
||||
requests for a tile.
|
||||
|
||||
On Google 3D (`photoreal`) at street zoom the layer switches its surface mode
|
||||
from `draped` to `terrain` (`getUIState().surface`; in below 1,400 m above the
|
||||
ground, out above 1,800 m, so the mode does not flap). Draped ground polylines
|
||||
and clamped billboards land on the top of the photoreal mesh, so on a street
|
||||
under trees or an overpass the coverage appears to float at roof height. In
|
||||
terrain mode `src/layers/streetLevel/groundCast.js` places lines, cones and the
|
||||
position marker on the bare earth from the terrain service
|
||||
(`/api/terrain/heights`) plus 2 m, and the mesh hides whatever is behind
|
||||
buildings and trees. Heights are sampled on the ground-floor grid (0.001°,
|
||||
~111 m), shared with other layers' cache, and interpolated bilinearly; a z14
|
||||
tile needs at most a few hundred lookups, sent once per tile and aborted when
|
||||
the tile is dropped. A tile is drawn draped first and swapped for its cast
|
||||
lines when the heights arrive; a geoid fallback (terrain proxy down) counts as
|
||||
unknown and leaves the lines draped. The bare-earth grid cannot see a
|
||||
freeway in a trench, a steep street between grid corners or the road under a
|
||||
tree, so `src/layers/streetLevel/meshSampler.js` then samples the rendered
|
||||
Google 3D surface (`scene.sampleHeight`, overlays excluded) once per ~11 m
|
||||
cell within 900 m of the camera, nearest first, in idle time within a 6 ms
|
||||
budget, and `refineHeights` blends it in: mesh up to 3 m above bare earth is
|
||||
the road and is followed 1 m above it; a higher mesh (canopy, deck, roof) takes
|
||||
the road's offset from bare earth carried across from the road samples on
|
||||
either side; anything else stays bare earth + 2 m. Tiles touched by new
|
||||
samples are redrawn one per idle slice with the same no-blink swap. Roads on
|
||||
elevated decks are still drawn at ground level under the deck. Cones and the marker keep drawing over
|
||||
buildings so they stay clickable. Framing or following a photo also checks the
|
||||
sampled mesh height against the bare earth: `sampleHeight` can return values
|
||||
kilometres underground before the tiles under the photo have loaded, and such
|
||||
a sample is ignored.
|
||||
On Google 3D (`photoreal`) at street zoom (in below 1,400 m above ground, out
|
||||
above 1,800 m) the surface mode switches from `draped` to `terrain`: draped
|
||||
lines land on roofs and tree tops, so `groundCast.js` instead places lines,
|
||||
cones and the marker 2 m above the bare earth from `/api/terrain/heights`, and
|
||||
the mesh hides what is behind buildings and trees. A tile is drawn draped until
|
||||
its heights arrive; a geoid fallback leaves it draped. Within 900 m of the
|
||||
camera, `meshSampler.js` samples the rendered surface (`scene.sampleHeight`,
|
||||
~11 m cells, nearest first, 6 ms idle budget) so lines also follow trenches,
|
||||
steep streets and roads under trees. Roads on elevated decks are still drawn at
|
||||
ground level. Framing a photo ignores mesh samples far below the bare earth
|
||||
(unloaded tiles).
|
||||
|
||||
The panel has no separate ON/OFF or nearest-photo buttons. The header pill is
|
||||
the layer switch, and a provider chip is lit only while the layer is on: with
|
||||
one provider it is the layer switch too, and with several, darkening the last
|
||||
lit chip turns the layer off while leaving that provider switched on. The
|
||||
viewer sits first, under the header, with its tools (EXPAND, FIT/FILL, FOLLOW,
|
||||
close) in a bar above the image so the provider's own overlays stay clear;
|
||||
the settings follow. FOLLOW is offered only while the map stack is Google 3D
|
||||
(`photoreal`): the layer takes the application map stack controller through
|
||||
`attachMapStackController`, subscribes to stack switches, disables the button
|
||||
with a MAP SOURCE hint on other stacks, and stops following when the stack
|
||||
leaves Google 3D. SINCE is a stepped range input (any date, 10, 5, 3, 2 and
|
||||
1 years, 6, 3 and 1 months) whose readout names the cut-off date. The panel is
|
||||
portable (`street-level-panel` spec in `PanelPositionControls`, minimum
|
||||
320 × 280, `dockOnCollapse`): in a resized window the viewer takes the spare
|
||||
height and only `.sl-settings` scrolls, and a user's collapse, a header
|
||||
double-click or SHRINK after EXPAND docks it at its default size (cockpit
|
||||
entry, restores and the Cyber accordion never dock a floating window). At
|
||||
phone width (≤720 px) the rail is the band between mid-screen and the credit
|
||||
line, so the viewer's height is derived from that band instead of 16:10 and
|
||||
the whole photo and caption fit without scrolling.
|
||||
The header pill is the layer switch. With one provider its chip is a layer
|
||||
switch too; with several, darkening the last lit chip turns the layer off. The
|
||||
viewer sits under the header with EXPAND, FIT/FILL, FOLLOW and close above the
|
||||
image. FOLLOW needs the Google 3D map stack (`attachMapStackController`) and
|
||||
stops when the stack changes. SINCE is a stepped slider whose readout names the
|
||||
cut-off date. The panel is portable (`street-level-panel` spec, minimum
|
||||
320 × 280, `dockOnCollapse`): a floating window gives spare height to the
|
||||
viewer, and collapsing it, double-clicking the header or SHRINK after EXPAND
|
||||
docks it. At phone width (≤720 px) the viewer height is derived from the rail
|
||||
band so the whole photo fits.
|
||||
|
||||
Street-level providers implement the contract documented in
|
||||
`src/layers/streetLevel/registry.js`: a definition (`id`, `name`, `label`,
|
||||
`requiresKeyId`, `pickPrefix`, `colors` (`{coverage}`, the source's one
|
||||
colour), `credit`, `capabilities`, `externalUrl`, `create`) whose `create(context)` returns an instance with
|
||||
`status`, `init`/`activate`/`deactivate`/`destroy`, `refreshCoverage`,
|
||||
`setFilter`, optional `setSurface`, `coverageStats`, `handlePick`, optional
|
||||
sequence selection,
|
||||
`nearestImage`, and a viewer adapter (`mount`/`open`/`close`/`unmount`/
|
||||
`resize`/`onPose`) that emits a provider-neutral pose. The core routes clicks
|
||||
by pick prefix, swaps viewer adapters in the one host, adds and removes each
|
||||
provider's Cesium credit, and fans the filter out to every provider. The
|
||||
context also carries `getSurface()` and `groundCaster` (bare-earth heights),
|
||||
so a provider can draw on the ground in terrain mode. Adding a
|
||||
provider: implement the definition, register it in
|
||||
Providers implement the contract in `src/layers/streetLevel/registry.js`. The
|
||||
core routes clicks by pick prefix, swaps viewer adapters in the one host,
|
||||
manages each provider's credit and fans the filter out to every provider. To
|
||||
add a provider: implement the definition, register it in
|
||||
`src/app/layers/streetLevel.js`, add its boolean option to the `street-level`
|
||||
group in `src/data/layerState.js` and its modules to
|
||||
`scripts/package-boundaries.json`; the chip, credit and legend follow. Once a
|
||||
keyless provider registers, `requiresKeyId` on the layer becomes null and the
|
||||
key gate moves to the chips, by design.
|
||||
`scripts/package-boundaries.json`. Once a keyless provider registers, the
|
||||
layer's `requiresKeyId` becomes null and the key gate moves to the chips.
|
||||
|
||||
Street Level has two browser gates. `npm run qa:street-level -- --url <dev
|
||||
server>` is the live run: with `MAPILLARY_CLIENT_TOKEN` it covers everything
|
||||
up to opening, expanding and closing a photo. `npm run
|
||||
qa:street-level:fixtures -- --url <dev server>` is hermetic: the page's
|
||||
Mapillary status and coverage-tile requests are answered from generated
|
||||
fixtures (`providers/mapillary/coverageFixture.mjs`), so it needs no token or
|
||||
Mapillary network, skips only the photo steps, and asserts that the 360° and
|
||||
SINCE filters actually remove sequences. CI runs the fixture gate and
|
||||
`qa:panel-resize` against a key-less dev server.
|
||||
Street Level has two browser gates. `npm run qa:street-level -- --url <server>`
|
||||
runs against real Mapillary and needs `MAPILLARY_CLIENT_TOKEN`. `npm run
|
||||
qa:street-level:fixtures -- --url <server>` answers every Mapillary request
|
||||
from fixtures (`providers/mapillary/coverageFixture.mjs`,
|
||||
`scripts/fixtures/street-level/`), so it needs no network and covers the whole
|
||||
photo flow. CI runs the fixture gate and `qa:panel-resize`
|
||||
against a production build served by `vite preview` with a dummy token.
|
||||
|
||||
Directions is a keyless front end to the routing the voice agent already
|
||||
uses. Its row chips are the whole interface: DRIVE / WALK / BIKE pick the
|
||||
@@ -4465,7 +4419,7 @@ easier to meet (detection is now on more often), but does not create it.
|
||||
samples and constant elevation during E/N drag; one shared-floor resolution on
|
||||
release; late one-shot shared-cell work is permitted during viewshed idle. The
|
||||
A+B harness intentionally excludes citywide LOD assertions.
|
||||
- Panel positions have a versioned storage name, `godsEyeView.v8.panelPos.<panel-id>`. The rails lay docked panels out adaptively and write nothing for them; a portable panel (CCTV, Street Level) persists `{ left, top, width, height, floating: true }` under that key once a header drag lifts it out of the rail, and a header double-click removes the record again. Double presses are detected in the header's `pointerdown` handler (two presses within 400 ms and 6 px, no drag between), because that handler's `preventDefault()` suppresses the mouse events a native `dblclick` needs. A spec with `dockOnCollapse` (Street Level) also docks when collapsed while floating. The rail's startup move of panels into `#right-context-rail` leaves a restored floating window's geometry alone. Collapsed state does persist for every panel at `godsEyeView.v6.panelCollapsed.<panel-id>` (`'0'` open, `'1'` closed, absent means the panel's own default).
|
||||
- Panel positions have a versioned storage name, `godsEyeView.v8.panelPos.<panel-id>`. Docked panels store nothing; a portable panel (CCTV, Street Level) stores `{ left, top, width, height, floating: true }` once a header drag lifts it out of the rail, and a header double-click removes it. Double presses are detected in the header's `pointerdown` handler, because its `preventDefault()` suppresses native `dblclick`. Collapsed state persists for every panel at `godsEyeView.v6.panelCollapsed.<panel-id>` (`'0'` open, `'1'` closed, absent means the panel's own default).
|
||||
- Legacy draggable-panel position keys may remain in local storage for backward compatibility, but the map-mode right rail ignores them unless they describe a portable panel's floating window; collapsed states still persist at `godsEyeView.v6.panelCollapsed.<panel-id>`.
|
||||
- Flight/military tracked entities cache dead-reckoned positions per frame to avoid callback desync flicker.
|
||||
- Aircraft 3D-model and tracking invariants are covered by `npm run test:track`; run this before touching `flights.js`, `militaryFlights.js`, `detection.js`, or `trackedReadout.js`.
|
||||
|
||||
Reference in new issue
Block a user