From 703c331d44f94465b89c9d2e3d21051a0dc265a4 Mon Sep 17 00:00:00 2001 From: vcoppe Date: Thu, 9 May 2024 00:02:27 +0200 Subject: [PATCH] routing off with elevation --- website/src/lib/components/Map.svelte | 42 +++++------------ .../toolbar/tools/routing/Routing.ts | 47 +++++++++++++++---- website/src/lib/db.ts | 10 ++-- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/website/src/lib/components/Map.svelte b/website/src/lib/components/Map.svelte index d6c47760..0a163176 100644 --- a/website/src/lib/components/Map.svelte +++ b/website/src/lib/components/Map.svelte @@ -26,32 +26,6 @@ unit: $distanceUnits }); - function toggleTerrain() { - if ($map) { - if ($map.getPitch() > 0) { - if (!$map.getSource('mapbox-dem')) { - $map.addSource('mapbox-dem', { - type: 'raster-dem', - url: 'mapbox://mapbox.mapbox-terrain-dem-v1', - tileSize: 512, - maxzoom: 14 - }); - } - if (!$map.getTerrain()) { - $map.setTerrain({ source: 'mapbox-dem', exaggeration: 1 }); - $map.setFog({ - color: 'rgb(186, 210, 235)', - 'high-color': 'rgb(36, 92, 223)', - 'horizon-blend': 0.1, - 'space-color': 'rgb(156, 240, 255)' - }); - } - } else { - $map.setTerrain(null); - } - } - } - onMount(() => { let newMap = new mapboxgl.Map({ container: 'map', @@ -98,10 +72,20 @@ newMap.addControl(scaleControl); - newMap.on('style.load', toggleTerrain); - newMap.on('pitch', toggleTerrain); - newMap.on('style.load', () => { + newMap.addSource('mapbox-dem', { + type: 'raster-dem', + url: 'mapbox://mapbox.mapbox-terrain-dem-v1', + tileSize: 512, + maxzoom: 14 + }); + newMap.setTerrain({ source: 'mapbox-dem' }); + newMap.setFog({ + color: 'rgb(186, 210, 235)', + 'high-color': 'rgb(36, 92, 223)', + 'horizon-blend': 0.1, + 'space-color': 'rgb(156, 240, 255)' + }); // add dummy layer to place the overlay layers below newMap.addLayer({ id: 'overlays', diff --git a/website/src/lib/components/toolbar/tools/routing/Routing.ts b/website/src/lib/components/toolbar/tools/routing/Routing.ts index 21a6759d..8bfbbc34 100644 --- a/website/src/lib/components/toolbar/tools/routing/Routing.ts +++ b/website/src/lib/components/toolbar/tools/routing/Routing.ts @@ -1,8 +1,9 @@ import type { Coordinates } from "gpx"; -import { TrackPoint } from "gpx"; +import { TrackPoint, distance } from "gpx"; import { get, writable } from "svelte/store"; import { settings } from "$lib/db"; import { _ } from "svelte-i18n"; +import { map } from "$lib/stores"; const { routing, routingProfile, privateRoads } = settings; @@ -38,14 +39,7 @@ export function route(points: Coordinates[]): Promise { if (get(routing)) { return getRoute(points, brouterProfiles[get(routingProfile)], get(privateRoads)); } else { - return new Promise((resolve) => { - resolve(points.map(point => new TrackPoint({ - attributes: { - lat: point.lat, - lon: point.lon - } - }))); - }); + return getIntermediatePoints(points); } } @@ -101,4 +95,37 @@ function getSurface(message: string): string { return fields[i].substring(8); } return "unknown"; -}; \ No newline at end of file +}; + +function getIntermediatePoints(points: Coordinates[]): Promise { + let route: TrackPoint[] = []; + let step = 0.05; + + for (let i = 0; i < points.length - 1; i++) { // Add intermediate points between each pair of points + let dist = distance(points[i], points[i + 1]) / 1000; + for (let d = 0; d < dist; d += step) { + let lat = points[i].lat + d / dist * (points[i + 1].lat - points[i].lat); + let lon = points[i].lon + d / dist * (points[i + 1].lon - points[i].lon); + route.push(new TrackPoint({ + attributes: { + lat: lat, + lon: lon + } + })); + } + } + + route.push(new TrackPoint({ + attributes: { + lat: points[points.length - 1].lat, + lon: points[points.length - 1].lon + } + })); + + route.forEach((point) => { + point.setSurface("unknown"); + point.ele = get(map)?.queryTerrainElevation(point.getCoordinates()) ?? undefined; + }); + + return new Promise((resolve) => resolve(route)); +} \ No newline at end of file diff --git a/website/src/lib/db.ts b/website/src/lib/db.ts index 5fe268a6..7a4bdb34 100644 --- a/website/src/lib/db.ts +++ b/website/src/lib/db.ts @@ -110,9 +110,9 @@ function dexieStore(querier: () => T | Promise, initial?: T): Readable export type GPXFileWithStatistics = { file: GPXFile, statistics: GPXStatistics }; // Wrap Dexie live queries in a Svelte store to avoid triggering the query for every subscriber, also takes care of the conversion to a GPXFile object -function dexieGPXFileStore(querier: () => GPXFile | undefined | Promise): Readable { +function dexieGPXFileStore(querier: () => GPXFile | undefined | Promise): Readable & { destroy: () => void } { let store = writable(undefined); - liveQuery(querier).subscribe(value => { + let query = liveQuery(querier).subscribe(value => { if (value !== undefined) { let gpx = new GPXFile(value); let statistics = gpx.getStatistics(); @@ -127,7 +127,8 @@ function dexieGPXFileStore(querier: () => GPXFile | undefined | Promise, patch } } -export const fileObservers: Writable>> = writable(new Map()); +export const fileObservers: Writable & { destroy: () => void }>> = writable(new Map()); const fileState: Map = new Map(); // Used to generate patches // Observe the file ids in the database, and maintain a map of file observers for the corresponding files @@ -185,6 +186,7 @@ liveQuery(() => db.fileids.toArray()).subscribe(dbFileIds => { $files.set(id, dexieGPXFileStore(() => db.files.get(id))); }); deletedFiles.forEach(id => { + $files.get(id)?.destroy(); $files.delete(id); fileState.delete(id); });