90 lines
3.3 KiB
TypeScript
90 lines
3.3 KiB
TypeScript
import GPX from "$lib/models/gpx/gpx";
|
|
import type Track from "$lib/models/gpx/track";
|
|
import TrackSegment from "$lib/models/gpx/track-segment";
|
|
import Waypoint from "$lib/models/gpx/waypoint";
|
|
import { type ValhallaAnchor, type ValhallaHeightResponse, type ValhallaRouteResponse } from "$lib/models/valhalla";
|
|
import { APIError } from "$lib/util/api_util";
|
|
import { decodePolyline, encodePolyline } from "$lib/util/polyline_util";
|
|
|
|
|
|
const emtpyTrack: Track = { trkseg: [] }
|
|
export let route: GPX = new GPX({ trk: [emtpyTrack] });
|
|
export let anchors: ValhallaAnchor[] = [];
|
|
|
|
export function clearRoute() {
|
|
route = new GPX({ trk: [emtpyTrack] });
|
|
anchors = [];
|
|
}
|
|
|
|
export function setRoute(newRoute: GPX) {
|
|
route = newRoute
|
|
}
|
|
|
|
export async function calculateRouteBetween(startLat: number, startLon: number, endLat: number, endLon: number, costing: string = "pedestrian", autoRoute: boolean = true) {
|
|
|
|
let shape;
|
|
if (autoRoute) {
|
|
let costingBody;
|
|
switch (costing) {
|
|
case "bicycle":
|
|
costingBody = { "costing": "bicycle", "costing_options": { "bicycle": { "bicycle_type": "Hybrid", "use_roads": 0.5, "use_hills": 0.5, "avoid_bad_surfaces": 0.5, "use_ferry": 0 } } }
|
|
break;
|
|
case "auto":
|
|
costingBody = { "costing": "auto", "costing_options": { "auto": { "use_ferry": 0 } } }
|
|
default:
|
|
costingBody = { "costing": costing, "costing_options": { costing: { "max_hiking_difficulty": 6, "use_ferry": 0 } } }
|
|
break;
|
|
}
|
|
const requestBody = {
|
|
"directions_type": "none",
|
|
"locations": [{ "lat": startLat, "lon": startLon }, { "lat": endLat, "lon": endLon }],
|
|
...costingBody
|
|
}
|
|
|
|
let r = await fetch("/api/v1/valhalla/route", { method: "POST", body: JSON.stringify(requestBody) })
|
|
|
|
if (!r.ok) {
|
|
const response = await r.json();
|
|
throw new APIError(r.status, response.message, response.detail)
|
|
}
|
|
|
|
const routeResponse: ValhallaRouteResponse = await r.json();
|
|
shape = routeResponse.trip.legs[0].shape
|
|
} else {
|
|
shape = encodePolyline([[startLat, startLon], [endLat, endLon]])
|
|
}
|
|
|
|
const r2 = await fetch("/api/v1/valhalla/height", { method: "POST", body: JSON.stringify({ encoded_polyline: shape }) })
|
|
|
|
if (!r2.ok) {
|
|
const response = await r2.json();
|
|
throw new APIError(r2.status, response.message, response.detail)
|
|
}
|
|
|
|
const heightResponse: ValhallaHeightResponse = await r2.json()
|
|
const points = decodePolyline(shape);
|
|
const waypoints = points.map((p, i) => new Waypoint({ $: { lat: p[0], lon: p[1] }, ele: heightResponse.height[i] }))
|
|
|
|
return waypoints
|
|
}
|
|
|
|
export async function insertIntoRoute(waypoints: Waypoint[], index?: number) {
|
|
const segment = new TrackSegment({ trkpt: waypoints })
|
|
|
|
if (index) {
|
|
route.trk?.at(0)?.trkseg?.splice(index, 0, segment);
|
|
} else {
|
|
route.trk?.at(0)?.trkseg?.push(segment);
|
|
}
|
|
}
|
|
|
|
export async function editRoute(index: number, waypoints: Waypoint[]) {
|
|
const segment = route.trk?.at(0)?.trkseg?.at(index)
|
|
if (segment) {
|
|
segment.trkpt = waypoints
|
|
}
|
|
}
|
|
|
|
export function deleteFromRoute(index: number) {
|
|
route.trk?.at(0)?.trkseg?.splice(index, 1);
|
|
} |