Note 01 — interface vision, reference scan, and the pose schema (Firewatch Camera Grid)

**Note** from Bead: Firewatch Camera Grid · [canonical source](https://redfish.acequia.io/guerin/.agents/65783732-7907-4a36-983a-3b015e75e80b/2026-06-13/notes/01-interface-references-and-schema.md) · session 2026-06-13 · discussion: Talk: Firewatch Camera Grid

Stephen's direction (2026-06-13): *"think of the transition from grid to geospatial layout that I think makes an interface interesting. esp as we filter by spatial and temporal bounds. i really want to see the scrubbing of the grid of images. this will also be an opportunity to select images from a camera in a bound and add them to a STAC. or bring in other sources."* + references: santafe.live origins / guerin SantaFeHistory, the phpDAV gallery, Lightroom, current STAC managers.

## The core interaction: grid ⇄ geospatial as one continuous space Not two modes (Lightroom's separate Library vs Map modules) but a **continuous morph** driven by the active **spatial + temporal filter bounds**: - **Grid pole** (no spatial filter): a contact-sheet of thumbnails — the files.gallery / Lightroom-Library / phpDAV experience. Good for "what frames exist, when." - **Geospatial pole** (spatial bound engaged): thumbnails *fly to their pose* on the map/3D terrain — each camera frame becomes a posed billboard + azimuth wedge at its viewpoint (the incident-viewer rendering). Good for "where, and looking which way." - **The morph is the feature.** Tightening a map bound animates the matching thumbnails from grid cells to geographic positions (and back). FLIP-style layout animation; the same DOM/scene items, re-laid-out. This is the thing Stephen wants to *see*. - **Temporal scrub of the grid.** The timeline is zoomed to the imagery date-time extent; scrubbing re-populates/re-orders the grid (and the posed billboards) in time — "scrubbing the grid of images." Grid cells are time-ordered; the playhead sweeps which frames are lit/centered. - **Filter = select = curate.** A spatial+temporal bound is simultaneously a *view filter* and a *selection*. "Select images from a camera in a bound → **add to a STAC**" falls right out: draw a bound (map rectangle + time range), the grid shows exactly those frames, hit "add to collection" → emit a STAC Collection/Items from the selection. Other sources (santafe photos, MISB frames, uploads) drop into the same grid and get posed the same way.

## Reference scan - **files.gallery** (the "phpDAV gallery"): single-file PHP directory gallery currently serving `guerin.acequia.io/SantaFeHistory/` (`<!-- www.files.gallery -->`). Strength = effortless browse/search/theme over a folder; weakness = no space/time/pose. It's the **grid pole** done well — the browsing ergonomics to match. - **santafe.live "Image Cache Manager"** (the fork target): Leaflet + canvas timeline + thumbnail grid + map, with per-image `imageMeta`/`imagePose` sidecars. Already has grid+map+timeline and the sidecar editor — the skeleton. It does NOT morph between grid and map (side-by-side panels) and the map is 2D only. - **Lightroom**: Library (grid + loupe + filmstrip + filter bar by metadata/time/flags + collections) and Map (GPS placement, select-on-map ↔ select-in-grid via the persistent filmstrip). Lesson: the *persistent selection/filmstrip* is what ties views together; collections = curated subsets (≈ our "add to STAC"). Gap we improve on: Lr's modules are discrete; we morph. - **STAC ecosystem**: STAC Browser (read-only SPA browser), STAC Index, QGIS STAC plugin, ArcGIS Pro — almost all **read/validate**, not author/curate. The *editing/curation manager* is the thin spot; that's the niche this fork fills (curate posed imagery → emit STAC). - **ArcGIS Oriented Imagery**: the standard our pose maps to (camera point + look direction + fov + near/far). See schema mapping below.

## Pose schema — santafe `imagePose` ≈ ArcGIS Oriented Imagery ≈ AlertWildfire telemetry santafe `imagePose/<id>.json` = `{id, imageId, Latitude, Longitude, Elevation, heading, pitch, roll, fov, fovy, far, lastupdate}`. This is essentially the ArcGIS **Oriented Imagery** field set already — so our derived sidecar feeds both the existing manager editor AND the future STAC oriented-imagery extension with no schema change. | santafe `imagePose` | ArcGIS Oriented Imagery | AlertWildfire telemetry frame | note | |---|---|---|---| | `Latitude`/`Longitude` | camera position | camera `lat`/`lon` (from `getCameraDataByLoc`) | fixed per camera | | `Elevation` | Camera Height | (DEM lookup; cams give none) | + "Cam +ft" like the viewer | | `heading` | Camera Heading (CW from north) | `camAzimuth` (e.g. 78.40) | likely direct; **verify CW-from-north** | | `pitch` | Camera Pitch (0=nadir,90=horizon,180=up) | `camElevation` (rel. horizon, +up) | **convention convert**: ArcGIS pitch ≈ 90 + camElevation; confirm santafe's own pitch convention before mapping | | `roll` | Camera Roll | (n/a, ~0) | 0 for AlertWildfire | | `fov` | Horizontal FOV | `camViewWidth` (e.g. 65.33) | direct | | `fovy` | Vertical FOV | derive from `fov` × aspect | | | `far` | Far Distance | (choose; e.g. slant to terrain) | | | — | Near/Image Rotation | — | minor, optional | **Convention caveat (learned the hard way on the attitude chain):** heading CW-from-north and the pitch zero-reference (nadir vs horizon) must be pinned with a ground-truth check before trusting the mapping — a sign/zero error here is exactly the bug that threw the MISB boresight 54–87° off. Plan a quick verify: derive a frame's pose, render its wedge, confirm it points where the image looks.

## Decisions locked (Stephen, 2026-06-13) - Deploy **bead-served** (`…/65783732…/app/`); git repo in the bead at `repo/`. - 3D map view on **TaosEngine** (converge with the incident-viewer; reuse camera glyph + az-wedge + posed-billboard work). - **Sidecars are source-of-truth now** (santafe `imagePose`/`imageMeta`), STAC generated/bound from them later. - **Sandy archive first** (`2026-CA-SandyFire/ops-alertcalifornia/`), camera-location file to place markers. - Fork mechanics: **copy santafe.live's app into `repo/` and adapt** (keep the working grid/timeline/map; swap the data layer to telemetry-derived sidecars; add the grid⇄geo morph + 3D + bound-select→STAC). - Derived sidecars written **bead-local and offered** (never into `incidents/**` without say-so).