fix(route-builder): use Swisstopo elevations for snapped routes

routeWaypoints passed BRouter's coarse, SRTM-based inline elevations
straight through, and the client only queried Swisstopo when a point
lacked an altitude — so snapped routes never hit the Swiss terrain model
and shipped a jagged profile that disagreed with the densified off-trail
path. Overwrite every routed point with enrichElevations (geo.admin.ch),
keeping the router's value only as a fallback where Swisstopo returns null
(hikes abroad). Disk-cached by coordinate list, so repeat snaps stay free.
This commit is contained in:
2026-05-22 18:51:02 +02:00
parent 35872d731a
commit 8f843833e0
2 changed files with 20 additions and 1 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "homepage",
"version": "1.84.0",
"version": "1.84.1",
"private": true,
"type": "module",
"scripts": {
+19
View File
@@ -217,6 +217,25 @@ export async function routeWaypoints(opts: {
clearTimeout(timeout);
}
// Swisstopo is the authoritative elevation source. BRouter ships its own
// (coarse, SRTM-based) elevations inline, which made snapped routes carry a
// jagged profile that disagreed with the densified off-trail path. Overwrite
// every point with the Swiss terrain model; coordinates outside Switzerland
// come back `null` and keep the router's elevation as a fallback (hikes
// abroad). `enrichElevations` is disk-cached by coordinate list, so repeated
// snaps are free.
const flat = segments.flat();
if (flat.length > 0) {
const elevs = await enrichElevations(flat.map((p) => [p[0], p[1]] as [number, number]));
let idx = 0;
for (const seg of segments) {
for (let i = 0; i < seg.length; i++) {
const e = elevs[idx++];
if (typeof e === 'number') seg[i] = [seg[i][0], seg[i][1], e];
}
}
}
const source = sources.size === 1 ? [...sources][0] : 'mixed';
return { segments, source };
}