Skip to content

feat(app): ship terrain on the AWS DEM, with a terrain button and an exaggeration setting - #586

Open
khagele wants to merge 3 commits into
efiten:masterfrom
khagele:feat/396-terrain
Open

feat(app): ship terrain on the AWS DEM, with a terrain button and an exaggeration setting#586
khagele wants to merge 3 commits into
efiten:masterfrom
khagele:feat/396-terrain

Conversation

@khagele

@khagele khagele commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Closes #396

The problem

Master has no terrain. #247 pulled it: the DEM source kept the map in a load loop and froze weaker GPUs. #394 decided on 2026-08-21 that it comes back on the AWS terrarium tiles with the exaggeration at 7, adjustable and switchable off, and left one thing open: what the map does when the DEM host is slow. This issue asked for the control; the scope check in the thread makes it carry the terrain too, since no implementation issue existed.

My changes in this PR

  • app/src/terrain.js: the DEM source (AWS Open Data terrarium, attribution, capped at z10, the low-poly knob measured in spike results: terrain + near-horizontal tilt POC (branch, findings, open decisions) #335), the exaggeration steps 1, 2, 4, 7, 10 with 7 as the default, hillshadeFor (shading tracks the geometry, exaggeration / 10) and terrainPlan: hillshade follows the switch; the mesh needs the switch, DEM tiles for the view and a 3D view. The switch is the 3D view itself (below).
  • Map (app/src/huntmap.js): the source and a hillshade layer under the signal overlays, re-mounted on every style load like the sky; demReady flips on the first sourcedata for the view and resets on a style swap; DEM tile errors are swallowed so the map stays flat rather than stalled. setView drops the mesh before the tilt back and sets it after the tilt up has settled, since easeTo({pitch}) is a no-op under a mesh (docs/2026-07-11-3d-mode.md). The plan is applied once the overlays are mounted, not on isStyleLoaded(), which stays false while tiles load.
  • The 3D view is the terrain switch. No button of its own (Kasper, 2026-09-06: 3D takes the terrain and the exaggeration along at once, the same rule the map follows in web: 3D on the MapLibre map, parity with the app (view, extrusions, terrain, rotation) #595). In 2D nothing is drawn; in 3D the hillshade comes with the view and the mesh once the tiles are in. The first commit had a sixth FAB on by default, the second flipped it off, the third removes it with its loader, CSS and onboarding ring entry; the history is kept so the three states are reviewable.
  • Exaggeration in Settings, Radio section beside the attenuator, persisted, lighting the settings dot off the default; the slope caveat is on the control.
  • Decision log docs/2026-09-05-terrain-ships.md, which also records the decide: which terrain elevation source, if any (#293 blocker) #394 decision as that issue asked. Changelog entry in both copies.

Verification

Suite Result
app vitest 907 passed, build and eslint clean
web vitest parity.test.js 57 passed
web e2e whatsnew.spec.js, --fail-on-flaky-tests 13 passed (the changelog copies)

New tests, mutation-checked: terrainPlan goes red with the tile gate removed and with the 3D gate removed; hillshadeFor with the clamp removed; the settings dot with the exaggeration line removed. The splash test that pins the onboarding ring against SPLASH_FAB_IDS caught the FAB both on its way in and on its way out.

Browser at 780 px with the DEM reachable (first cut, with the button): 2D mounts with the hillshade visible and no mesh; one view tap eases to pitch 60 and the mesh appears at 7 once two DEM tiles are in; back to 2D the mesh goes before the tilt returns to 0. The final cut is verified on the map side in #596 against the same terrainPlan: 2D flat and unshaded, 3D shaded with the mesh at the Settings exaggeration. idle keeps firing with terrain in, which the theme switch waits on. Exaggeration 4 from Settings: stored, row active, settings dot on, shading 0.4.

Not in this PR, and to check on a phone

🤖 Generated with Claude Code

khagele and others added 2 commits September 5, 2026 12:41
…exaggeration setting

Terrain was pulled in efiten#247 because the DEM source kept the map loading and
froze weak GPUs. efiten#394 decided it comes back on the AWS terrarium tiles,
capped at z10, exaggeration 7 by default because the Low Countries show no
relief otherwise. This adds the source and a hillshade layer under the
signal overlays, a sixth FAB that turns terrain on and off, and the
exaggeration steps in Settings with the slope caveat on the control.

The mesh waits: hillshade follows the button, setTerrain needs the button,
DEM tiles for the view and a 3D view, so a slow host leaves the map flat
rather than stalled. Leaving 3D drops the mesh before the tilt back, and
entering 3D sets it once the tilt has settled, since easeTo({pitch}) is a
no-op under a mesh.

Closes efiten#396

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Kasper (2026-09-06): the button is the opt-in, not the opt-out. The
loader answers on only for a stored '1'; the hint, the decision log and
the release note say so.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Kasper (2026-09-06): 3D takes the terrain and the exaggeration along at
once, the same rule the map follows in efiten#595. The sixth FAB goes, with
its loader, its CSS and its place in the onboarding ring; huntmap's plan
reads mode3D as the switch and the map only takes the exaggeration.
Settings keeps the exaggeration. Decision log and release note follow.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@efiten

efiten commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Master moved: #569, #574, #580, #581 and #589 are merged, master is at f14d205. The conflict is the changelog arrays plus the tail of web/parity.test.js, where master (#580, #589) and this branch each append a describe block. Both are wanted; #580 and #589 were resolved by keeping master's block then this one's.

Notes below are from reading this PR's diff against master before those merges. Not a full audit, and the green checks are not part of it.

map.on('error', ...) silences the console for every map error, not only DEM tiles. MapLibre's Evented.fire only calls console.error when the map has no error listener; registering one takes that path away for style-load failures, basemap tile errors and source errors too. And ErrorEvent carries no preventDefault, so the guard never runs and the DEM errors it is aimed at are suppressed by the registration itself. Logging non-DEM errors from inside the handler restores the reporting the map had before.

The FAB is added and then removed inside the branch. Net result is the 3D view as the switch, which is the decision. Since merges here are squashed, the commit that lands, and the release note release-please builds from it, will read "with a terrain button and an exaggeration setting". docs/2026-09-05-terrain-ships.md's own title says "with a button and one setting" while its body says the opposite.

terrainPlan({ on: mode3D, ready, mode3D, ... }) passes the same value twice. After the switch moved to the view, on and mode3D cannot differ on either surface, so the parameter no longer separates anything.

The DEM cap at z10, the hillshade-follows-geometry ratio and the mesh-off-before-tilt ordering all read as described. The AWS attribution is satisfied: huntmap.js:90 adds an AttributionControl.

Ordering: this branch's commits, and #588's, are inside #596 and #593. This also touches the same FAB stack offsets in app/src/styles/app.css that #579 and #583 do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

app: terrain exaggeration must be a Settings control, not a URL flag

2 participants