adds height to route drawing
This commit is contained in:
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Distanz",
|
"distance": "Distanz",
|
||||||
"documentation": "Dokumentation",
|
"documentation": "Dokumentation",
|
||||||
"download-gpx": "GPX herunterladen",
|
"download-gpx": "GPX herunterladen",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "Route zeichnen",
|
||||||
"dutch": "Niederländisch",
|
"dutch": "Niederländisch",
|
||||||
"easy": "Einfach",
|
"easy": "Einfach",
|
||||||
"edit": "Bearbeiten",
|
"edit": "Bearbeiten",
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
"show-on-map": "Auf der Karte anzeigen",
|
"show-on-map": "Auf der Karte anzeigen",
|
||||||
"slogan": "Speichere deine Abenteuer!",
|
"slogan": "Speichere deine Abenteuer!",
|
||||||
"sort": "Sortieren",
|
"sort": "Sortieren",
|
||||||
"stop-drawing": "",
|
"stop-drawing": "Zeichnen beenden",
|
||||||
"summit-book": "Gipfelbuch",
|
"summit-book": "Gipfelbuch",
|
||||||
"text": "Text",
|
"text": "Text",
|
||||||
"trail": "{n, plural, =1 {Route} other {Routen}}",
|
"trail": "{n, plural, =1 {Route} other {Routen}}",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Distance",
|
"distance": "Distance",
|
||||||
"documentation": "Documentation",
|
"documentation": "Documentation",
|
||||||
"download-gpx": "Download GPX",
|
"download-gpx": "Download GPX",
|
||||||
"draw-on-map": "Draw on map",
|
"draw-a-route": "Draw a route",
|
||||||
"dutch": "Dutch",
|
"dutch": "Dutch",
|
||||||
"easy": "Easy",
|
"easy": "Easy",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Distance",
|
"distance": "Distance",
|
||||||
"documentation": "Documentation",
|
"documentation": "Documentation",
|
||||||
"download-gpx": "Télécharger le GPX",
|
"download-gpx": "Télécharger le GPX",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "",
|
||||||
"dutch": "Néerlandais",
|
"dutch": "Néerlandais",
|
||||||
"easy": "Facile",
|
"easy": "Facile",
|
||||||
"edit": "Editer",
|
"edit": "Editer",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Távolság",
|
"distance": "Távolság",
|
||||||
"documentation": "Dokumentáció",
|
"documentation": "Dokumentáció",
|
||||||
"download-gpx": "GPX letöltése",
|
"download-gpx": "GPX letöltése",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "",
|
||||||
"dutch": "Holland",
|
"dutch": "Holland",
|
||||||
"easy": "Könnyű",
|
"easy": "Könnyű",
|
||||||
"edit": "Szerkesztés",
|
"edit": "Szerkesztés",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Afstand",
|
"distance": "Afstand",
|
||||||
"documentation": "Documentatie",
|
"documentation": "Documentatie",
|
||||||
"download-gpx": "GPX-bestand downloaden",
|
"download-gpx": "GPX-bestand downloaden",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "",
|
||||||
"dutch": "Nederlands",
|
"dutch": "Nederlands",
|
||||||
"easy": "Makkelijk",
|
"easy": "Makkelijk",
|
||||||
"edit": "Bewerken",
|
"edit": "Bewerken",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Dystans",
|
"distance": "Dystans",
|
||||||
"documentation": "Dokumentacja",
|
"documentation": "Dokumentacja",
|
||||||
"download-gpx": "Popierz GPX",
|
"download-gpx": "Popierz GPX",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "",
|
||||||
"dutch": "Niderlandzki",
|
"dutch": "Niderlandzki",
|
||||||
"easy": "Łatwy",
|
"easy": "Łatwy",
|
||||||
"edit": "Edytuj",
|
"edit": "Edytuj",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "Distância",
|
"distance": "Distância",
|
||||||
"documentation": "Documentação",
|
"documentation": "Documentação",
|
||||||
"download-gpx": "Baixar GPX",
|
"download-gpx": "Baixar GPX",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "",
|
||||||
"dutch": "Holandês",
|
"dutch": "Holandês",
|
||||||
"easy": "Fácil",
|
"easy": "Fácil",
|
||||||
"edit": "Editar",
|
"edit": "Editar",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
"distance": "距离",
|
"distance": "距离",
|
||||||
"documentation": "文档",
|
"documentation": "文档",
|
||||||
"download-gpx": "下载 GPX",
|
"download-gpx": "下载 GPX",
|
||||||
"draw-on-map": "",
|
"draw-a-route": "",
|
||||||
"dutch": "荷兰语",
|
"dutch": "荷兰语",
|
||||||
"easy": "简单",
|
"easy": "简单",
|
||||||
"edit": "编辑",
|
"edit": "编辑",
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as xml2js from 'isomorphic-xml2js';
|
import * as xml2js from 'isomorphic-xml2js';
|
||||||
import Metadata from './metadata';
|
import Metadata from './metadata';
|
||||||
import Waypoint from './waypoint';
|
|
||||||
import Route from './route';
|
import Route from './route';
|
||||||
import Track from './track';
|
import Track from './track';
|
||||||
import { removeEmpty, allDatesToISOString } from './utils';
|
import { allDatesToISOString, calculateDistance, removeEmpty } from './utils';
|
||||||
|
import Waypoint from './waypoint';
|
||||||
|
|
||||||
const defaultAttributes = {
|
const defaultAttributes = {
|
||||||
version: '1.1',
|
version: '1.1',
|
||||||
@@ -72,9 +72,59 @@ export default class GPX {
|
|||||||
removeEmpty(this);
|
removeEmpty(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTotals() {
|
||||||
|
let totalElevationGain = 0;
|
||||||
|
let totalDuration = 0;
|
||||||
|
let totalDistance = 0;
|
||||||
|
|
||||||
|
for (const track of this.trk ?? []) {
|
||||||
|
for (const segment of track.trkseg ?? []) {
|
||||||
|
const points = segment.trkpt ?? [];
|
||||||
|
|
||||||
|
if (points.length >= 2) {
|
||||||
|
const startTime = points[0].time;
|
||||||
|
const endTime = points[points.length - 1].time
|
||||||
|
|
||||||
|
if (startTime && endTime) {
|
||||||
|
totalDuration += endTime.getTime() - startTime.getTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointLength = points.length
|
||||||
|
for (let i = 1; i < pointLength; i++) {
|
||||||
|
const prevPoint = points[i - 1];
|
||||||
|
const point = points[i];
|
||||||
|
const elevation = point.ele ?? 0
|
||||||
|
const previousElevation = prevPoint.ele ?? 0
|
||||||
|
const elevationDiff = elevation - previousElevation;
|
||||||
|
if (elevationDiff > 0) {
|
||||||
|
totalElevationGain += elevationDiff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const distance = calculateDistance(
|
||||||
|
prevPoint.$.lat ?? 0,
|
||||||
|
prevPoint.$.lon ?? 0,
|
||||||
|
point.$.lat ?? 0,
|
||||||
|
point.$.lon ?? 0,
|
||||||
|
);
|
||||||
|
totalDistance += distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { distance: totalDistance, elevationGain: totalElevationGain, duration: totalDuration }
|
||||||
|
}
|
||||||
|
|
||||||
static parse(gpxString: string): Promise<GPX | Error> {
|
static parse(gpxString: string): Promise<GPX | Error> {
|
||||||
return new Promise<GPX | Error>((resolve, reject) => xml2js.parseString(gpxString, {
|
return new Promise<GPX | Error>((resolve, reject) => xml2js.parseString(gpxString, {
|
||||||
explicitArray: false
|
explicitArray: false,
|
||||||
|
attrValueProcessors: [(str: string | number) => {
|
||||||
|
if (!isNaN(Number(str))) {
|
||||||
|
str = Number.isInteger(Number(str)) ? parseInt(String(str), 10) : parseFloat(String(str));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
]
|
||||||
}, (err, xml) => {
|
}, (err, xml) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
|
|||||||
@@ -20,4 +20,17 @@ function allDatesToISOString(obj: Record<string, any>) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export { removeEmpty, allDatesToISOString };
|
function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
|
||||||
|
const R = 6371; // Radius of the Earth in km
|
||||||
|
const dLat = (lat2 - lat1) * (Math.PI / 180); // Convert degrees to radians
|
||||||
|
const dLon = (lon2 - lon1) * (Math.PI / 180);
|
||||||
|
const a =
|
||||||
|
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||||
|
Math.cos((lat1 * (Math.PI / 180))) * Math.cos((lat2 * (Math.PI / 180))) *
|
||||||
|
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
||||||
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
const distance = R * c * 1000; // Distance in km
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { removeEmpty, allDatesToISOString, calculateDistance };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
interface ValhallaResponse {
|
interface ValhallaRouteResponse {
|
||||||
trip: {
|
trip: {
|
||||||
legs: {
|
legs: {
|
||||||
shape: string;
|
shape: string;
|
||||||
@@ -6,4 +6,8 @@ interface ValhallaResponse {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export { type ValhallaResponse }
|
interface ValhallaHeightResponse {
|
||||||
|
height: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type ValhallaRouteResponse, type ValhallaHeightResponse }
|
||||||
@@ -2,7 +2,7 @@ import GPX from "$lib/models/gpx/gpx";
|
|||||||
import type Track from "$lib/models/gpx/track";
|
import type Track from "$lib/models/gpx/track";
|
||||||
import TrackSegment from "$lib/models/gpx/track-segment";
|
import TrackSegment from "$lib/models/gpx/track-segment";
|
||||||
import Waypoint from "$lib/models/gpx/waypoint";
|
import Waypoint from "$lib/models/gpx/waypoint";
|
||||||
import { type ValhallaResponse } from "$lib/models/valhalla";
|
import { type ValhallaHeightResponse, type ValhallaRouteResponse } from "$lib/models/valhalla";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
|
|
||||||
|
|
||||||
@@ -20,13 +20,21 @@ export async function calculateRouteBetween(startLat: number, startLon: number,
|
|||||||
"locations": [{ "lat": startLat, "lon": startLon }, { "lat": endLat, "lon": endLon }],
|
"locations": [{ "lat": startLat, "lon": startLon }, { "lat": endLat, "lon": endLon }],
|
||||||
"costing": "pedestrian", "costing_options": { "pedestrian": { "max_hiking_difficulty": 6, "use_ferry": 0 } }
|
"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) })
|
let r = await fetch("/api/v1/valhalla/route", { method: "POST", body: JSON.stringify(requestBody) })
|
||||||
|
|
||||||
if (!r.ok) {
|
if (!r.ok) {
|
||||||
throw new ClientResponseError(await r.json())
|
throw new ClientResponseError(await r.json())
|
||||||
}
|
}
|
||||||
const response: ValhallaResponse = await r.json();
|
const routeResponse: ValhallaRouteResponse = await r.json();
|
||||||
const points = decodeShape(response.trip.legs[0].shape);
|
const shape = routeResponse.trip.legs[0].shape
|
||||||
const waypoints = points.map((p) => new Waypoint({ $: { lat: p[0], lon: p[1] } }))
|
r = await fetch("/api/v1/valhalla/height", { method: "POST", body: JSON.stringify({ encoded_polyline: shape }) })
|
||||||
|
|
||||||
|
if (!r.ok) {
|
||||||
|
throw new ClientResponseError(await r.json())
|
||||||
|
}
|
||||||
|
const heightResponse: ValhallaHeightResponse = await r.json()
|
||||||
|
const points = decodeShape(shape);
|
||||||
|
const waypoints = points.map((p, i) => new Waypoint({ $: { lat: p[0], lon: p[1] }, ele: heightResponse.height[i] }))
|
||||||
|
|
||||||
return waypoints
|
return waypoints
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,7 @@ import { Trail } from "$lib/models/trail";
|
|||||||
import { Waypoint } from "$lib/models/waypoint";
|
import { Waypoint } from "$lib/models/waypoint";
|
||||||
import GeoJsonToGpx from "$lib/vendor/geoJSONToGPX";
|
import GeoJsonToGpx from "$lib/vendor/geoJSONToGPX";
|
||||||
import { kml, tcx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
import { kml, tcx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||||
|
import cryptoRandomString from "crypto-random-string";
|
||||||
function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {
|
|
||||||
const R = 6371; // Radius of the Earth in km
|
|
||||||
const dLat = (lat2 - lat1) * (Math.PI / 180); // Convert degrees to radians
|
|
||||||
const dLon = (lon2 - lon1) * (Math.PI / 180);
|
|
||||||
const a =
|
|
||||||
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
||||||
Math.cos((lat1 * (Math.PI / 180))) * Math.cos((lat2 * (Math.PI / 180))) *
|
|
||||||
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
||||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
||||||
const distance = R * c * 1000; // Distance in km
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function gpx2trail(gpxString: string) {
|
export async function gpx2trail(gpxString: string) {
|
||||||
const gpx = await GPX.parse(gpxString);
|
const gpx = await GPX.parse(gpxString);
|
||||||
@@ -32,63 +20,32 @@ export async function gpx2trail(gpxString: string) {
|
|||||||
|
|
||||||
for (const wpt of gpx.wpt ?? []) {
|
for (const wpt of gpx.wpt ?? []) {
|
||||||
const wp = new Waypoint(wpt.$.lat ?? 0, wpt.$.lon ?? 0);
|
const wp = new Waypoint(wpt.$.lat ?? 0, wpt.$.lon ?? 0);
|
||||||
wp.name = wp.name
|
wp.id = cryptoRandomString({ length: 15 });
|
||||||
wp.description = wp.description;
|
wp.name = wpt.name
|
||||||
|
wp.description = wpt.desc;
|
||||||
trail.expand.waypoints.push(wp);
|
trail.expand.waypoints.push(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
let totalElevationGain = 0;
|
const totals = gpx.getTotals()
|
||||||
let totalDuration = 0;
|
|
||||||
let totalDistance = 0;
|
|
||||||
|
|
||||||
for (const track of gpx.trk ?? []) {
|
const points = gpx.trk?.at(0)?.trkseg?.at(0)?.trkpt
|
||||||
for (const segment of track.trkseg ?? []) {
|
const startPoint = points?.at(0);
|
||||||
const points = segment.trkpt ?? [];
|
|
||||||
|
|
||||||
if (points.length >= 2) {
|
|
||||||
const startTime = points[0].time;
|
|
||||||
const endTime = points[points.length - 1].time
|
|
||||||
|
|
||||||
if (startTime && endTime) {
|
|
||||||
totalDuration += endTime.getTime() - startTime.getTime();
|
|
||||||
if (!trail.date) {
|
|
||||||
trail.date = startTime.toISOString()
|
|
||||||
.substring(0, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pointLength = points.length
|
|
||||||
for (let i = 1; i < pointLength; i++) {
|
|
||||||
const prevPoint = points[i - 1];
|
|
||||||
const point = points[i];
|
|
||||||
const elevation = point.ele ?? 0
|
|
||||||
const previousElevation = prevPoint.ele ?? 0
|
|
||||||
const elevationDiff = elevation - previousElevation;
|
|
||||||
if (elevationDiff > 0) {
|
|
||||||
totalElevationGain += elevationDiff;
|
|
||||||
}
|
|
||||||
|
|
||||||
const distance = calculateDistance(
|
|
||||||
prevPoint.$.lat ?? 0,
|
|
||||||
prevPoint.$.lon ?? 0,
|
|
||||||
point.$.lat ?? 0,
|
|
||||||
point.$.lon ?? 0,
|
|
||||||
);
|
|
||||||
totalDistance += distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const startPoint = gpx.trk?.at(0)?.trkseg?.at(0)?.trkpt?.at(0);
|
|
||||||
if (startPoint) {
|
if (startPoint) {
|
||||||
trail.lat = startPoint.$.lat
|
trail.lat = startPoint.$.lat
|
||||||
trail.lon = startPoint.$.lon
|
trail.lon = startPoint.$.lon
|
||||||
}
|
}
|
||||||
|
|
||||||
trail.duration = totalDuration / 1000 / 60
|
const startTime = points?.at(0)?.time;
|
||||||
trail.elevation_gain = totalElevationGain;
|
const endTime = points?.at((points?.length ?? 1) - 1)?.time
|
||||||
trail.distance = totalDistance
|
|
||||||
|
if (startTime && endTime && !trail.date) {
|
||||||
|
trail.date = startTime.toISOString()
|
||||||
|
.substring(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
trail.duration = totals.duration / 1000 / 60
|
||||||
|
trail.elevation_gain = totals.elevationGain;
|
||||||
|
trail.distance = totals.distance
|
||||||
|
|
||||||
return trail
|
return trail
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ export const Elevation = L.Control.Elevation = L.Control.extend({
|
|||||||
case 'LineString': return this._addGeoJSONData(geom.coordinates, d.properties);
|
case 'LineString': return this._addGeoJSONData(geom.coordinates, d.properties);
|
||||||
case 'MultiLineString': return _.each(geom.coordinates, (coords, i) => this._addGeoJSONData(coords, d.properties, i));
|
case 'MultiLineString': return _.each(geom.coordinates, (coords, i) => this._addGeoJSONData(coords, d.properties, i));
|
||||||
case 'Point':
|
case 'Point':
|
||||||
default: return console.warn('Unsopperted GeoJSON feature geometry type:' + geom.type);
|
default: return console.warn('Unsupported GeoJSON feature geometry type:' + geom.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
web/src/routes/api/v1/valhalla/height/+server.ts
Normal file
20
web/src/routes/api/v1/valhalla/height/+server.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { env } from '$env/dynamic/public';
|
||||||
|
import { error, json, type NumericRange, type RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
|
||||||
|
export async function POST(event: RequestEvent) {
|
||||||
|
const data = await event.request.json()
|
||||||
|
if (!env.PUBLIC_VALHALLA_URL) {
|
||||||
|
return error(400, "PUBLIC_VALHALLA_URL not set")
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const r = await event.fetch(env.PUBLIC_VALHALLA_URL + '/height', { method: "POST", body: JSON.stringify(data) });
|
||||||
|
const response = await r.json();
|
||||||
|
if (!r.ok) {
|
||||||
|
throw error(r.status as NumericRange<400,500>, response);
|
||||||
|
}
|
||||||
|
return json(response);
|
||||||
|
} catch (e: any) {
|
||||||
|
throw error(e.status || 500, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -182,9 +182,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$form.expand.waypoints = [];
|
clearWaypoints();
|
||||||
$form.waypoints = [];
|
clearRoute();
|
||||||
|
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
|
|
||||||
reader.readAsText(selectedFile);
|
reader.readAsText(selectedFile);
|
||||||
@@ -205,6 +204,10 @@
|
|||||||
try {
|
try {
|
||||||
$form = await gpx2trail(gpxData);
|
$form = await gpx2trail(gpxData);
|
||||||
$form.expand.gpx_data = gpxData;
|
$form.expand.gpx_data = gpxData;
|
||||||
|
|
||||||
|
for (const waypoint of $form.expand.waypoints) {
|
||||||
|
saveWaypoint(waypoint);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
||||||
@@ -234,6 +237,14 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearWaypoints() {
|
||||||
|
for (const waypoint of $form.expand.waypoints) {
|
||||||
|
waypoint.marker?.remove();
|
||||||
|
}
|
||||||
|
$form.expand.waypoints = [];
|
||||||
|
$form.waypoints = [];
|
||||||
|
}
|
||||||
|
|
||||||
function openMarkerPopup(waypoint: Waypoint) {
|
function openMarkerPopup(waypoint: Waypoint) {
|
||||||
waypoint.marker?.openPopup();
|
waypoint.marker?.openPopup();
|
||||||
}
|
}
|
||||||
@@ -266,13 +277,13 @@
|
|||||||
if (drawingActive) {
|
if (drawingActive) {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
deleteFromRoute(index);
|
deleteFromRoute(index);
|
||||||
$form.expand.gpx_data = route.toString();
|
updateTrailWithRouteData();
|
||||||
const nextWaypoint = $form.expand.waypoints[index];
|
const nextWaypoint = $form.expand.waypoints[index];
|
||||||
nextWaypoint.icon = "circle-half-stroke";
|
nextWaypoint.icon = "circle-half-stroke";
|
||||||
saveWaypoint(nextWaypoint);
|
saveWaypoint(nextWaypoint);
|
||||||
} else if (index == $form.expand.waypoints.length) {
|
} else if (index == $form.expand.waypoints.length) {
|
||||||
deleteFromRoute(index - 1);
|
deleteFromRoute(index - 1);
|
||||||
$form.expand.gpx_data = route.toString();
|
updateTrailWithRouteData();
|
||||||
|
|
||||||
if ($form.expand.waypoints.length > 1) {
|
if ($form.expand.waypoints.length > 1) {
|
||||||
const previousWaypoint = $form.expand.waypoints[index - 1];
|
const previousWaypoint = $form.expand.waypoints[index - 1];
|
||||||
@@ -296,7 +307,6 @@
|
|||||||
$form.expand.waypoints[editedWaypointIndex] = savedWaypoint;
|
$form.expand.waypoints[editedWaypointIndex] = savedWaypoint;
|
||||||
} else {
|
} else {
|
||||||
savedWaypoint.id = cryptoRandomString({ length: 15 });
|
savedWaypoint.id = cryptoRandomString({ length: 15 });
|
||||||
|
|
||||||
$form.expand.waypoints = [...$form.expand.waypoints, savedWaypoint];
|
$form.expand.waypoints = [...$form.expand.waypoints, savedWaypoint];
|
||||||
}
|
}
|
||||||
const marker = createMarkerFromWaypoint(L, savedWaypoint, (event) => {
|
const marker = createMarkerFromWaypoint(L, savedWaypoint, (event) => {
|
||||||
@@ -374,9 +384,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function startDrawing() {
|
function startDrawing() {
|
||||||
$form.expand.gpx_data = "";
|
|
||||||
clearRoute();
|
|
||||||
drawingActive = true;
|
drawingActive = true;
|
||||||
|
if (!route.trk?.at(0)?.trkseg?.at(0)?.trkpt?.length) {
|
||||||
|
$form.expand.gpx_data = "";
|
||||||
|
clearWaypoints();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopDrawing() {
|
function stopDrawing() {
|
||||||
@@ -410,7 +422,7 @@
|
|||||||
previousWaypoint.icon = "circle";
|
previousWaypoint.icon = "circle";
|
||||||
saveWaypoint(previousWaypoint);
|
saveWaypoint(previousWaypoint);
|
||||||
}
|
}
|
||||||
$form.expand.gpx_data = route.toString();
|
updateTrailWithRouteData();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
show_toast({
|
show_toast({
|
||||||
@@ -451,6 +463,14 @@
|
|||||||
if (previousWaypoints) {
|
if (previousWaypoints) {
|
||||||
editRoute(waypointIndex - 1, previousWaypoints);
|
editRoute(waypointIndex - 1, previousWaypoints);
|
||||||
}
|
}
|
||||||
|
updateTrailWithRouteData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTrailWithRouteData() {
|
||||||
|
const totals = route.getTotals();
|
||||||
|
$form.distance = totals.distance;
|
||||||
|
$form.duration = totals.duration;
|
||||||
|
$form.elevation_gain = totals.elevationGain;
|
||||||
$form.expand.gpx_data = route.toString();
|
$form.expand.gpx_data = route.toString();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -475,12 +495,19 @@
|
|||||||
on:click={openFileBrowser}>{$_("upload-file")}</Button
|
on:click={openFileBrowser}>{$_("upload-file")}</Button
|
||||||
>
|
>
|
||||||
{#if PUBLIC_VALHALLA_URL}
|
{#if PUBLIC_VALHALLA_URL}
|
||||||
|
<div class="flex gap-4 items-center w-full">
|
||||||
|
<hr class="basis-full border-input-border" />
|
||||||
|
<span class="text-gray-500 uppercase">{$_("or")}</span>
|
||||||
|
<hr class="basis-full border-input-border" />
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
on:click={drawingActive ? stopDrawing : startDrawing}
|
on:click={drawingActive ? stopDrawing : startDrawing}
|
||||||
>
|
>
|
||||||
{drawingActive ? $_("stop-drawing") : $_("draw-on-map")}</button
|
{drawingActive
|
||||||
|
? $_("stop-drawing")
|
||||||
|
: $_("draw-a-route")}</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<input
|
<input
|
||||||
@@ -693,10 +720,11 @@
|
|||||||
trail={$form}
|
trail={$form}
|
||||||
crosshair={drawingActive}
|
crosshair={drawingActive}
|
||||||
options={{
|
options={{
|
||||||
hotline: false,
|
hotline: true,
|
||||||
autofitBounds: false,
|
autofitBounds: false,
|
||||||
trkStart: false,
|
trkStart: false,
|
||||||
trkEnd: false,
|
trkEnd: false,
|
||||||
|
speed: false,
|
||||||
}}
|
}}
|
||||||
bind:map
|
bind:map
|
||||||
on:click={(e) => handleMapClick(e.detail)}
|
on:click={(e) => handleMapClick(e.detail)}
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ export var Chart = L.Control.Elevation.Chart = L.Class.extend({
|
|||||||
.attr("width", x2 - x1 )
|
.attr("width", x2 - x1 )
|
||||||
.attr("height", this._height())
|
.attr("height", this._height())
|
||||||
.attr('class', 'gap')
|
.attr('class', 'gap')
|
||||||
.attr('fill-opacity', '0.8')
|
.attr('fill-opacity', '0.0')
|
||||||
.attr("fill", 'black'); // hide = black (mask)
|
.attr("fill", 'black'); // hide = black (mask)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user