adds routing engine
This commit is contained in:
@@ -14,14 +14,15 @@
|
||||
export let map: Map | null = null;
|
||||
export let options = {};
|
||||
export let graticule: AutoGraticule | null = null;
|
||||
export let crosshair: boolean = false;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
let L: any;
|
||||
let controlElevation: any;
|
||||
|
||||
$: if (trail?.expand.gpx_data && controlElevation) {
|
||||
controlElevation.clear();
|
||||
$: if (trail?.expand.gpx_data !== undefined && controlElevation) {
|
||||
controlElevation.clear();
|
||||
controlElevation.load(trail.expand.gpx_data);
|
||||
}
|
||||
|
||||
@@ -31,7 +32,9 @@
|
||||
await import("leaflet.awesome-markers");
|
||||
//@ts-ignore
|
||||
await import("$lib/vendor/leaflet-elevation/src/index.js");
|
||||
const AutoGraticule = (await import("$lib/vendor/leaflet-graticule/leaflet-auto-graticule")).default;
|
||||
const AutoGraticule = (
|
||||
await import("$lib/vendor/leaflet-graticule/leaflet-auto-graticule")
|
||||
).default;
|
||||
|
||||
map = L.map("map", { preferCanvas: true }).setView(
|
||||
[trail?.lat ?? 0, trail?.lon ?? 0],
|
||||
@@ -43,6 +46,10 @@
|
||||
dispatch("zoomend", map);
|
||||
});
|
||||
|
||||
map!.on("click", function (e) {
|
||||
dispatch("click", e);
|
||||
});
|
||||
|
||||
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
|
||||
attribution: "© OpenStreetMap contributors",
|
||||
}).addTo(map);
|
||||
@@ -99,7 +106,7 @@
|
||||
iconColor: "white",
|
||||
}),
|
||||
},
|
||||
graticule: false
|
||||
graticule: false,
|
||||
};
|
||||
|
||||
const elevation_options = Object.assign(
|
||||
@@ -115,16 +122,21 @@
|
||||
markers.push(marker);
|
||||
}
|
||||
|
||||
if(elevation_options.graticule) {
|
||||
if (elevation_options.graticule) {
|
||||
graticule = new AutoGraticule();
|
||||
graticule.addTo(map!);
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="map-container" class="flex flex-col">
|
||||
<div id="map" class="rounded-xl z-0 basis-full"></div>
|
||||
<div
|
||||
id="map"
|
||||
class="rounded-xl z-0 basis-full"
|
||||
style={crosshair
|
||||
? "position: relative; outline-style: none;cursor: crosshair !important"
|
||||
: "position: relative; outline-style: none;"}
|
||||
></div>
|
||||
<div class="flex items-center justify-between">
|
||||
<slot />
|
||||
<div class="basis-[300px] flex-grow flex-shrink-0" id="elevation"></div>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
const tabs = [
|
||||
$_("description"),
|
||||
$_("waypoints"),
|
||||
$_("waypoints", { values: { n: 2 } }),
|
||||
$_("photos"),
|
||||
$_("summit-book"),
|
||||
...($currentUser ? [$_("comment", { values: { n: 2 } })] : []),
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Distanz",
|
||||
"documentation": "Dokumentation",
|
||||
"download-gpx": "GPX herunterladen",
|
||||
"draw-on-map": "",
|
||||
"dutch": "Niederländisch",
|
||||
"easy": "Einfach",
|
||||
"edit": "Bearbeiten",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Auf der Karte anzeigen",
|
||||
"slogan": "Speichere deine Abenteuer!",
|
||||
"sort": "Sortieren",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "Gipfelbuch",
|
||||
"text": "Text",
|
||||
"trail": "{n, plural, =1 {Route} other {Routen}}",
|
||||
@@ -136,7 +138,7 @@
|
||||
"upload-file": "Datei hochladen",
|
||||
"upload-gpx": "GPX hochladen",
|
||||
"username": "Nutzername",
|
||||
"waypoints": "Wegpunkte",
|
||||
"waypoints": "{n, plural, =1 {Wegpunkt} other {Wegpunkte}}",
|
||||
"welcome_to": "Willkommen bei",
|
||||
"wrong-username-or-password": "Falscher Nutzername oder falsches Passwort"
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Distance",
|
||||
"documentation": "Documentation",
|
||||
"download-gpx": "Download GPX",
|
||||
"draw-on-map": "Draw on map",
|
||||
"dutch": "Dutch",
|
||||
"easy": "Easy",
|
||||
"edit": "Edit",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Show on map",
|
||||
"slogan": "Save your adventures!",
|
||||
"sort": "Sort",
|
||||
"stop-drawing": "Stop drawing",
|
||||
"summit-book": "Summit Book",
|
||||
"text": "Text",
|
||||
"trail": "{n, plural, =1 {Trail} other {Trails}}",
|
||||
@@ -136,7 +138,7 @@
|
||||
"upload-file": "Upload file",
|
||||
"upload-gpx": "Upload GPX",
|
||||
"username": "Username",
|
||||
"waypoints": "Waypoints",
|
||||
"waypoints": "{n, plural, =1 {Waypoint} other {Waypoints}}",
|
||||
"welcome_to": "Welcome to",
|
||||
"wrong-username-or-password": "Wrong username or password"
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Distance",
|
||||
"documentation": "Documentation",
|
||||
"download-gpx": "Télécharger le GPX",
|
||||
"draw-on-map": "",
|
||||
"dutch": "Néerlandais",
|
||||
"easy": "Facile",
|
||||
"edit": "Editer",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Voir sur la carte",
|
||||
"slogan": "Sauvegarder vos aventures !",
|
||||
"sort": "Trier",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "Livre du sommet",
|
||||
"text": "Texte",
|
||||
"trail": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Távolság",
|
||||
"documentation": "Dokumentáció",
|
||||
"download-gpx": "GPX letöltése",
|
||||
"draw-on-map": "",
|
||||
"dutch": "Holland",
|
||||
"easy": "Könnyű",
|
||||
"edit": "Szerkesztés",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Mutatás térképen",
|
||||
"slogan": "Mentse el a kalandjait!",
|
||||
"sort": "Rendezés",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "Csúcspont könyv",
|
||||
"text": "Szöveg",
|
||||
"trail": "{n, plural, =1 {Útvonal} other {Útvonalak}}",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Afstand",
|
||||
"documentation": "Documentatie",
|
||||
"download-gpx": "GPX-bestand downloaden",
|
||||
"draw-on-map": "",
|
||||
"dutch": "Nederlands",
|
||||
"easy": "Makkelijk",
|
||||
"edit": "Bewerken",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Tonen op kaart",
|
||||
"slogan": "Bewaar je avonturen!",
|
||||
"sort": "Sorteren",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "Bergtopboek",
|
||||
"text": "Tekst",
|
||||
"trail": "{n, plural, =1 {wandelroute} other {wandelroutes}}",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Dystans",
|
||||
"documentation": "Dokumentacja",
|
||||
"download-gpx": "Popierz GPX",
|
||||
"draw-on-map": "",
|
||||
"dutch": "Niderlandzki",
|
||||
"easy": "Łatwy",
|
||||
"edit": "Edytuj",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Pokaż na mapie",
|
||||
"slogan": "Zapisz swoją wyprawę!",
|
||||
"sort": "Sortowanie",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "Logbook",
|
||||
"text": "Tekst",
|
||||
"trail": "{n, plural, =1 {Szlak} other {Szlaki}}",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "Distância",
|
||||
"documentation": "Documentação",
|
||||
"download-gpx": "Baixar GPX",
|
||||
"draw-on-map": "",
|
||||
"dutch": "Holandês",
|
||||
"easy": "Fácil",
|
||||
"edit": "Editar",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "Mostrar no mapa",
|
||||
"slogan": "Guarde as suas aventuras!",
|
||||
"sort": "Ordenar",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "Livro da cimeira",
|
||||
"text": "Texto",
|
||||
"trail": "{n, plural, =1 {Percurso} other {Percursos}}",
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"distance": "距离",
|
||||
"documentation": "文档",
|
||||
"download-gpx": "下载 GPX",
|
||||
"draw-on-map": "",
|
||||
"dutch": "荷兰语",
|
||||
"easy": "简单",
|
||||
"edit": "编辑",
|
||||
@@ -128,6 +129,7 @@
|
||||
"show-on-map": "地图中展示",
|
||||
"slogan": "保存你的冒险!",
|
||||
"sort": "排序",
|
||||
"stop-drawing": "",
|
||||
"summit-book": "详细日程",
|
||||
"text": "文本",
|
||||
"trail": "{n, plural, =1 {路线} other {路线}}",
|
||||
|
||||
31
web/src/lib/models/valhalla.ts
Normal file
31
web/src/lib/models/valhalla.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
interface ValhallaResponse {
|
||||
trip: {
|
||||
legs: {
|
||||
shape: string[];
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
class ValhallaRoute {
|
||||
type: "Feature";
|
||||
properties: {};
|
||||
geometry: {
|
||||
type: "LineString";
|
||||
coordinates: number[][];
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.type = "Feature"
|
||||
this.properties = {}
|
||||
this.geometry = {
|
||||
type: "LineString",
|
||||
coordinates: []
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
}
|
||||
|
||||
export {type ValhallaResponse, ValhallaRoute}
|
||||
79
web/src/lib/stores/valhalla_store.ts
Normal file
79
web/src/lib/stores/valhalla_store.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { ValhallaRoute, type ValhallaResponse } from "$lib/models/valhalla";
|
||||
import { ClientResponseError } from "pocketbase";
|
||||
|
||||
|
||||
|
||||
export const route: ValhallaRoute = new ValhallaRoute();
|
||||
|
||||
|
||||
export function clearRoute() {
|
||||
route.geometry.coordinates = [];
|
||||
}
|
||||
|
||||
export async function calculateRouteBetween(startLat: number, startLon: number, endLat: number, endLon: number) {
|
||||
const requestBody = {
|
||||
"directions_type": "none",
|
||||
"locations": [{ "lat": startLat, "lon": startLon }, { "lat": endLat, "lon": endLon }],
|
||||
"costing": "pedestrian", "costing_options": { "pedestrian": { "max_hiking_difficulty": 6, "use_ferry": 0 } }
|
||||
}
|
||||
const r = await fetch("/api/v1/valhalla", { method: "POST", body: JSON.stringify(requestBody) })
|
||||
if (!r.ok) {
|
||||
throw new ClientResponseError(await r.json())
|
||||
}
|
||||
const response: ValhallaResponse = await r.json();
|
||||
|
||||
appendToRoute(response);
|
||||
}
|
||||
|
||||
function appendToRoute(valhallaResponse: any) {
|
||||
const routeGeometry = decodeShape(valhallaResponse.trip.legs[0].shape);
|
||||
|
||||
for (const point of routeGeometry) {
|
||||
route.geometry.coordinates.push([point[1], point[0]])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function decodeShape(shape: string, precision: number = 6) {
|
||||
var index = 0,
|
||||
lat = 0,
|
||||
lng = 0,
|
||||
coordinates = [],
|
||||
shift = 0,
|
||||
result = 0,
|
||||
byte = null,
|
||||
latitude_change,
|
||||
longitude_change,
|
||||
factor = Math.pow(10, precision);
|
||||
|
||||
while (index < shape.length) {
|
||||
byte = null;
|
||||
shift = 0;
|
||||
result = 0;
|
||||
|
||||
do {
|
||||
byte = shape.charCodeAt(index++) - 63;
|
||||
result |= (byte & 0x1f) << shift;
|
||||
shift += 5;
|
||||
} while (byte >= 0x20);
|
||||
|
||||
latitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||
|
||||
shift = result = 0;
|
||||
|
||||
do {
|
||||
byte = shape.charCodeAt(index++) - 63;
|
||||
result |= (byte & 0x1f) << shift;
|
||||
shift += 5;
|
||||
} while (byte >= 0x20);
|
||||
|
||||
longitude_change = ((result & 1) ? ~(result >> 1) : (result >> 1));
|
||||
|
||||
lat += latitude_change;
|
||||
lng += longitude_change;
|
||||
|
||||
coordinates.push([lat / factor, lng / factor]);
|
||||
}
|
||||
|
||||
return coordinates;
|
||||
};
|
||||
Reference in New Issue
Block a user