You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: document 3D terrain view in Map Analysis (#3826 Phase 2)
Adds user-facing docs for the new pitched-terrain MapLibre GL view: a
"3D terrain view" section in map-analysis.md (toggle, exaggeration
slider, requirements, basemap fallback, what's deferred to a later
phase), a settings.md note that the elevation source also powers 3D
and that JSON point sources don't support it, the two new
GET /api/elevation/capabilities and GET /api/elevation/tiles/{z}/{x}/{y}
endpoints in REST_API.md, and a README.md feature-list entry.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018e4dtLyWeYJYJ7SbgFvGG1
- **Modern UI** - Catppuccin theme with message reactions and threading
251
251
- **Interactive Maps** - Unified node positions and network topology visualization across all sources
252
252
- **Terrain Link Profile** - Two-point terrain elevation, line-of-sight, and Fresnel-zone link-budget planning tool in Map Analysis, with per-source frequency/RX-sensitivity auto-detection and a configurable DEM source
253
+
- **3D Terrain View** - Pitched-terrain MapLibre GL view in Map Analysis with DEM/hillshade rendering, adjustable exaggeration, and clickable node markers, available when a tile-based elevation source is configured
253
254
- **Multi-Database Support** - SQLite (default), PostgreSQL, and MySQL via Drizzle ORM
254
255
- **Notifications** - Web Push and Apprise integration for 100+ services, with inactive-node and low-battery alerts
255
256
- **Automation** - Autoresponders, scheduled announcements, timers, and geofence triggers with rich message templates, plus an airtime-utilization cutoff that automatically pauses bot traffic when the mesh is busy
Copy file name to clipboardExpand all lines: docs/api/REST_API.md
+47Lines changed: 47 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -607,6 +607,53 @@ Probes a candidate DEM source URL and reports what it found. Requires `settings:
607
607
608
608
A failing probe still returns HTTP 200 — the probe outcome (`data.success: false` plus `data.error`) is the payload, not a request error.
609
609
610
+
### Get 3D Terrain Capabilities
611
+
612
+
#### GET /api/elevation/capabilities
613
+
614
+
Reports whether the [Map Analysis 3D terrain view](../features/map-analysis.md#3d-terrain-view) can be offered, without exposing the configured `elevationSourceUrl` (a secret setting). Public (no authentication), no outbound network calls — derived from settings already loaded server-side.
615
+
616
+
**Response:**
617
+
```json
618
+
{
619
+
"success": true,
620
+
"data": {
621
+
"enabled": true,
622
+
"terrainTiles": true,
623
+
"provider": "terrarium"
624
+
}
625
+
}
626
+
```
627
+
628
+
-`enabled` — mirrors the admin's **Enable terrain elevation** setting.
629
+
-`provider` — `"terrarium"` or `"json"`, auto-detected from the configured (or default) elevation source URL, same detection used by `POST /test`.
630
+
-`terrainTiles` — `true` only when `enabled`**and**`provider === "terrarium"`. A JSON point-API source can power the 2D Link Profile but has no tiles to build a 3D surface from, so `terrainTiles` is `false` in that case even though `enabled` is `true`.
631
+
632
+
### Get Terrain Tile
633
+
634
+
#### GET /api/elevation/tiles/{z}/{x}/{y}
635
+
636
+
Proxies a single Terrarium-encoded DEM tile from the configured (or default) elevation source, for MapLibre GL's `raster-dem` terrain source in the 3D view. Public (no authentication), rate-limited to **600 requests/minute per IP** in production (private/internal IPs exempt) — a single 3D view load legitimately fetches dozens of tiles.
637
+
638
+
Returns raw `image/png` bytes on success (**not** the `{success, data}` envelope) with:
-`403 ELEVATION_DISABLED` — the admin has disabled elevation.
651
+
-`409 TERRAIN_TILES_UNAVAILABLE` — the configured elevation source is a JSON point API, which has no tiles to serve. There is no fallback to the public Terrarium source in this case.
652
+
-`400 INVALID_TILE_COORDS` — `z`, `x`, or `y` isn't a valid integer, or `x`/`y` falls outside `[0, 2^z − 1]` for the given zoom (zoom is capped at 15, the source's native maximum).
653
+
-`502 TILE_FETCH_FAILED` — the upstream tile fetch failed (network error, non-OK response, or the SSRF guard blocked the request).
654
+
655
+
The resolved source URL (and any embedded API key) is never included in a response or error message.
Copy file name to clipboardExpand all lines: docs/features/map-analysis.md
+36Lines changed: 36 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,6 +45,7 @@ The toolbar runs across the top of the canvas. From left to right:
45
45
|**Time slider toggle**| Show/hide the floating time-window slider. |
46
46
|**Measure**| Straight-line distance between two positioned nodes. Disabled until at least two positioned nodes exist; mutually exclusive with Link Profile. |
47
47
|**Link Profile**| Terrain, Fresnel clearance, and link-budget verdict between two points. See [Terrain Link Profile](#terrain-link-profile). Only shown when the server has elevation enabled. |
48
+
|**3D** (box icon) | Toggle between the flat 2D map and a pitched-terrain 3D view. See [3D terrain view](#3d-terrain-view). Disabled with a tooltip when elevation is off or the configured elevation source can't serve DEM tiles. |
48
49
|**Layer buttons (×8)**| Toggle each visualization layer on/off. The right-edge chevron opens a popover for layer-specific options (lookback window, sub-options). |
49
50
|**Progress bar**| Shows aggregate loading state while any layer is fetching. |
50
51
|**Inspector toggle**| Show/hide the right-side detail panel. |
@@ -244,6 +245,41 @@ For a node seen by several sources (say, a Meshtastic radio *and* an MQTT bridge
244
245
245
246
The terrain data (SRTM-derived, roughly 90 m per pixel) is a bare-earth elevation model — it does **not** account for buildings, trees, or other vegetation, so a "Clear" verdict is a first-pass estimate of geometric line-of-sight, not a guarantee of a working RF link. Node GPS altitude is not factored into antenna height; only the DEM terrain height plus your entered AGL value is used.
246
247
248
+
## 3D terrain view
249
+
250
+
::: tip New in 4.14
251
+
:::
252
+
253
+
The toolbar's **3D** button (box icon) switches the canvas from the flat Leaflet map to a pitched-terrain [MapLibre GL](https://maplibre.org/) view — the current basemap draped over a real elevation surface with hillshading, so you can tilt and rotate to see how terrain actually sits between nodes.
254
+
255
+
### Requirements
256
+
257
+
The button is disabled with an explanatory tooltip unless all of the following hold:
258
+
259
+
-**Elevation is enabled** on the server (**Settings → Elevation / Terrain**). If it isn't, the tooltip reads *"Elevation is disabled."*
260
+
-**The configured elevation source serves DEM tiles.** 3D terrain needs a Terrarium-encoded tile source (the default public AWS/Mapzen source, or a custom tile-template URL). If the admin has instead configured an Open-Topo-Data-style **JSON point API** — which the 2D [Terrain Link Profile](#terrain-link-profile) tool can still use — there's no tile source to build a 3D surface from, and the tooltip reads *"3D terrain is unavailable with the configured elevation source."* There is deliberately no fallback to the public terrarium tiles in this case: an admin who configured a JSON source did so on purpose (often for an air-gapped or cost-controlled deployment), and silently routing 3D traffic elsewhere would leak requests to a provider they explicitly opted away from.
261
+
-**Your browser supports WebGL.** If it doesn't, the 3D map degrades to a plain-language message and the view automatically switches back to 2D rather than showing a blank canvas.
262
+
263
+
### Using the 3D view
264
+
265
+
-**Navigate** with the built-in MapLibre control: drag to pan, scroll/pinch to zoom, right-drag (or two-finger drag) to pitch and rotate. A compass resets bearing to north.
266
+
-**Terrain exaggeration** — a slider (0–2×, default **1.3×**) vertically stretches the DEM so subtle elevation changes read more clearly. It's a per-session view setting, not persisted between visits.
267
+
-**Node markers** render with short-name labels at their real position, draped onto the terrain surface. Click a marker to select it — the same inspector panel used in 2D opens with that node's details.
268
+
-**Basemap** — the 3D view reuses whichever raster tileset you have selected for the 2D map. If your selected tileset is **vector-only**, 3D can't drape a vector style over terrain yet, so it substitutes the default OpenStreetMap raster basemap and shows a small note; your 2D tileset selection is unaffected.
269
+
270
+
The **2D/3D toggle state persists per-browser** alongside the rest of your Map Analysis toolbar configuration.
271
+
272
+
### What's not in 3D yet
273
+
274
+
The 3D view is a foundation, not full layer parity. Not yet available while in 3D mode (all still work normally after switching back to 2D):
275
+
276
+
- Neighbor links and traceroute paths
277
+
- Coverage heatmap, position trails, range rings, hop shading, and the SNR overlay
278
+
- The time slider
279
+
- Launching the Terrain Link Profile tool directly from the 3D canvas
280
+
281
+
These are planned for a follow-up phase of the 3D map work.
282
+
247
283
## Time slider
248
284
249
285
The slider appears bottom-center when enabled. It has two handles defining a `[start, end]` window inside the loaded lookback range. Movement is purely client-side — no refetch — and applies only to time-bounded layers (trails, heatmap, SNR overlay, traceroutes, neighbors). Markers, rings, and hop shading always reflect the current state.
- Implausible DEM samples (below −500 m or above 9000 m — an artifact of open-water/void pixels in some tile sets, not real terrain) are discarded server-side and shown as gaps in the Link Profile chart rather than distorting it.
471
471
- The `POST /api/elevation/profile` endpoint used by the tool is public (unauthenticated) but rate-limited to 20 requests/minute per IP in production (requests from private/internal IPs are exempt); the Test button's endpoint requires `settings:write`.
472
472
473
+
::: tip Also powers the 3D terrain view (New in 4.14)
474
+
This same elevation source drives Map Analysis's [3D terrain view](/features/map-analysis#3d-terrain-view). A **tile-template** URL (the default Terrarium source, or a custom one) works for both the 2D Link Profile chart and the 3D pitched-terrain map. A **JSON point API** source only supports the 2D Link Profile — there are no tiles to build a 3D surface from, so the 3D toggle stays disabled with an explanatory tooltip for that configuration (no fallback to the default tile source is attempted).
0 commit comments