ADR-061 — Surface hotspots are regions, not points (axis-aligned region_bounds on SurfaceSite)
Status · Accepted Date · 2026-05-30 Closes into ·
static/data/schemas/surface-site.schema.json(schema additions) +src/types/surface-site.ts(TS type additions) Related · RFC-017 (Surface Hotspots, v0.7 — this ADR supersedes the disc/point geometry choice made there), Issue #283 (Surface hotspots v2 epic), Issue #284 (follow-on base sphere texture LOD) Triggered by · Visual review of v0.7 surface hotspots (2026-05-30): the current disc primitive is dishonest about both image footprint and semantic extent; selection halos decouple from content; layer transitions read as stickers, not terrain
Context
The original surface-hotspots design (PRD-014 / RFC-017) modelled each site as a point — (lat, lon) plus an optional location_uncertainty_m radius. The Tier-2 patches (hotspot-surface-patch.ts) render this point as a circular CircleGeometry disc on the sphere, with a larger regional ring beneath. The disc diameter is fixed (1 km detail, 3 km regional context) and explicitly stylized — the source modal admits "3:1 ratio is a stylized 'you are HERE' callout — at true scale HiRISE would be a sub-pixel speck inside the CTX disc."
Reviewing the actual experience in May 2026 surfaced four failures (full analysis in #283):
- The disc shape encodes nothing about the data — it is neither true footprint nor named region.
- At mid-zoom, the hard-edged circle reads as a sticker pasted on the sphere, not as terrain data.
- On the moon, the selection halo decouples from the disc into a giant blue ring floating in empty space around the much smaller dark disc.
- At deepest zoom, nothing communicates that the user has crossed the imagery's resolving power — they read "Mars is blurry" instead of "I'm zooming past pixels."
NASA's two reference families solve these honestly by encoding shape:
- Image-extent rectangles (Perseverance location map): each HiRISE swath is drawn at its actual rectangular ground footprint.
- Region-of-interest rectangles (Lunar South Pole moonbase plan): named areas — "Connecting Ridge", "Haworth", "Malapert Massif" — are translucent quads bounded by the semantic region.
Decision
Each surface site gains an optional region_bounds — an axis-aligned { lat_min, lat_max, lon_min, lon_max } quad — plus region_kind (enum: landing_ellipse | traverse_bbox | roi_quad | image_swath) and region_bearing_deg (for rotated ellipses).
- Schema (
surface-site.schema.json): all three fields added as optional. Anif/thenrule enforcesregion_boundsrequireskind: 'surface'. Antimeridian-crossing regions are split into two entries in v1 (lat_min ≤ lat_max and lon_min ≤ lon_max enforced). - TypeScript (
src/types/surface-site.ts): mirrored asRegionBounds+RegionKindtypes + three optional fields onSurfaceSite. - Field ordering:
region_bounds+region_kindsit immediately afterlat/lonin both schema and serialized JSON to keep geometry grouped (enforced by the Slice 1 backfill script'sreorder()). - Backward compat: all three fields are optional. Sites without
region_boundscontinue to render via the legacy disc primitive until Slice 3 of #283 replaces it. The backfill script (scripts/mockups/backfill-region-bounds.mjs) populates 19 moon and 16 mars surface sites with documented landing ellipses and rover traverse bboxes — sources cited inline in the script.
Alternatives considered
- Polygon vertices (
Array<{lat, lon}>) — strictly more expressive (arbitrary shape), but 95% of sites are landing ellipses or rover wander envelopes that an AABB captures adequately. Polygons add complexity (winding order, self-intersection checks) without payoff for v1. Can be added later (region_polygonalongsideregion_bounds) if a real need surfaces. - Rotated ellipse (
{cx, cy, a, b, bearing}) — closer to the actual physical shape of a Mars descent ellipse, but harder to backfill (no public source publishes ellipses in this canonical form) and harder to render as a click target on a curved sphere. Decided to store the AABB and add an optionalregion_bearing_degfor rendering hint — the actual ellipse can be drawn inside the box when bearing is set. - Reuse
location_uncertainty_m— would have meant keeping the circle and just changing visual treatment. Rejected because the shape is the dishonesty; keeping a circle means accepting it.
Consequences
- Slices 2–6 of #283 can now consume the new schema without further data changes.
- TA.md ADR table needs updating to mark ADR-059, ADR-060, ADR-062 still reserved (this ADR claims ADR-061 from the v0.7 RFC-017 reservation pool).
- One inaccurate forward-reference in
src/types/surface-site.ts(a comment that misattributed ADR-061 to the Tier 3 panorama field) is fixed in this same change. - The legacy disc primitive in
hotspot-surface-patch.tsstays for now — Slice 3 of #283 replaces it. During the transition, both rendering paths exist; the dispatcher picks based onregion_boundspresence.