adds trail reversing
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type {
|
import type {
|
||||||
RoutingOptions,
|
RoutingOptions,
|
||||||
ValhallaBicycleCostingOptions
|
ValhallaBicycleCostingOptions,
|
||||||
} from "$lib/models/valhalla";
|
} from "$lib/models/valhalla";
|
||||||
import { formatSpeed } from "$lib/util/format_util";
|
import { formatSpeed } from "$lib/util/format_util";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
@@ -11,9 +11,11 @@
|
|||||||
import Toggle from "../base/toggle.svelte";
|
import Toggle from "../base/toggle.svelte";
|
||||||
interface Props {
|
interface Props {
|
||||||
options: RoutingOptions;
|
options: RoutingOptions;
|
||||||
|
onReverse: () => void;
|
||||||
|
onReset: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { options = $bindable() }: Props = $props();
|
let { options = $bindable(), onReverse, onReset }: Props = $props();
|
||||||
|
|
||||||
const modesOfTransport: SelectItem[] = [
|
const modesOfTransport: SelectItem[] = [
|
||||||
{ text: $_("hiking"), value: "pedestrian" },
|
{ text: $_("hiking"), value: "pedestrian" },
|
||||||
@@ -62,7 +64,7 @@
|
|||||||
if (!options.autoRouting) {
|
if (!options.autoRouting) {
|
||||||
showSettings = false;
|
showSettings = false;
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
let showSettings = $state(false);
|
let showSettings = $state(false);
|
||||||
|
|
||||||
@@ -92,7 +94,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="p-4 my-2 rounded-xl bg-background space-y-4">
|
<div class="px-6 py-4 my-2 rounded-xl bg-background space-y-4">
|
||||||
<Toggle bind:value={options.autoRouting} label={$_("enable-auto-routing")}
|
<Toggle bind:value={options.autoRouting} label={$_("enable-auto-routing")}
|
||||||
></Toggle>
|
></Toggle>
|
||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
@@ -107,10 +109,27 @@
|
|||||||
disabled={!options.autoRouting}
|
disabled={!options.autoRouting}
|
||||||
onclick={() => (showSettings = !showSettings)}
|
onclick={() => (showSettings = !showSettings)}
|
||||||
aria-label="Toggle routing settings"
|
aria-label="Toggle routing settings"
|
||||||
><i class="fa fa-cogs" class:text-gray-500={!options.autoRouting}></i></button
|
><i class="fa fa-cogs" class:text-gray-500={!options.autoRouting}
|
||||||
|
></i></button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-4">
|
||||||
|
<button
|
||||||
|
class="btn-icon tooltip"
|
||||||
|
type="button"
|
||||||
|
onclick={() => onReverse()}
|
||||||
|
aria-label="Reverse trail direction"
|
||||||
|
data-title={$_("reverse-direction")}
|
||||||
|
><i class="fa fa-arrow-right-arrow-left"></i></button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="btn-icon tooltip"
|
||||||
|
type="button"
|
||||||
|
onclick={() => onReset()}
|
||||||
|
aria-label="Reset route"
|
||||||
|
data-title={$_("reset")}><i class="fa fa-trash"></i></button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if showSettings}
|
{#if showSettings}
|
||||||
<div in:slide out:slide>
|
<div in:slide out:slide>
|
||||||
{#if options.modeOfTransport === "pedestrian" && options.pedestrianOptions}
|
{#if options.modeOfTransport === "pedestrian" && options.pedestrianOptions}
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Route entfernt aus",
|
"removed-trail-from": "Route entfernt aus",
|
||||||
"removed-trails-from": "Routen entfernt aus",
|
"removed-trails-from": "Routen entfernt aus",
|
||||||
"required": "Pflichtfeld",
|
"required": "Pflichtfeld",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Passwort zurücksetzen",
|
"reset-password": "Passwort zurücksetzen",
|
||||||
|
"reverse-direction": "Reverse direction",
|
||||||
"road": "Straße",
|
"road": "Straße",
|
||||||
"route": "{n, plural, =1 {Route} other {Routen}}",
|
"route": "{n, plural, =1 {Route} other {Routen}}",
|
||||||
"route-point": "Punkt auf Route",
|
"route-point": "Punkt auf Route",
|
||||||
@@ -349,12 +351,12 @@
|
|||||||
"upload-gpx": "GPX hochladen",
|
"upload-gpx": "GPX hochladen",
|
||||||
"upload-new-file": "Neue Datei hochladen",
|
"upload-new-file": "Neue Datei hochladen",
|
||||||
"uploaded": "hochgeladen",
|
"uploaded": "hochgeladen",
|
||||||
"use-hills": "",
|
"use-hills": "Hügel einbeziehen",
|
||||||
"use-roads": "Nutze Straßen",
|
"use-roads": "Nutze Straßen",
|
||||||
"username": "Nutzername",
|
"username": "Nutzername",
|
||||||
"view": "Ansehen",
|
"view": "Ansehen",
|
||||||
"visibilty-status": "Sichtbarkeit",
|
"visibilty-status": "Sichtbarkeit",
|
||||||
"walking-speed": "",
|
"walking-speed": "Laufgeschwindigkeit",
|
||||||
"waypoints": "{n, plural, =1 {Wegpunkt} other {Wegpunkte}}",
|
"waypoints": "{n, plural, =1 {Wegpunkt} other {Wegpunkte}}",
|
||||||
"welcome_to": "Willkommen bei",
|
"welcome_to": "Willkommen bei",
|
||||||
"width": "Breite",
|
"width": "Breite",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Removed trail from",
|
"removed-trail-from": "Removed trail from",
|
||||||
"removed-trails-from": "Removed trails from",
|
"removed-trails-from": "Removed trails from",
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
|
"reset": "Reset",
|
||||||
"reset-password": "Reset Password",
|
"reset-password": "Reset Password",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
@@ -349,12 +351,12 @@
|
|||||||
"upload-gpx": "Upload GPX",
|
"upload-gpx": "Upload GPX",
|
||||||
"upload-new-file": "Upload new file",
|
"upload-new-file": "Upload new file",
|
||||||
"uploaded": "uploaded",
|
"uploaded": "uploaded",
|
||||||
"use-hills": "",
|
"use-hills": "Use hills",
|
||||||
"use-roads": "Use Roads",
|
"use-roads": "Use Roads",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"view": "View",
|
"view": "View",
|
||||||
"visibilty-status": "Visibility status",
|
"visibilty-status": "Visibility status",
|
||||||
"walking-speed": "",
|
"walking-speed": "Walking speed",
|
||||||
"waypoints": "{n, plural, =1 {Waypoint} other {Waypoints}}",
|
"waypoints": "{n, plural, =1 {Waypoint} other {Waypoints}}",
|
||||||
"welcome_to": "Welcome to",
|
"welcome_to": "Welcome to",
|
||||||
"width": "Width",
|
"width": "Width",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Ruta borrada de",
|
"removed-trail-from": "Ruta borrada de",
|
||||||
"removed-trails-from": "Rutas borrada de",
|
"removed-trails-from": "Rutas borrada de",
|
||||||
"required": "Obligatorio",
|
"required": "Obligatorio",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Restablecer Contraseña",
|
"reset-password": "Restablecer Contraseña",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Carretera",
|
"road": "Carretera",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Removed trail from",
|
"removed-trail-from": "Removed trail from",
|
||||||
"removed-trails-from": "Removed trails from",
|
"removed-trails-from": "Removed trails from",
|
||||||
"required": "Required",
|
"required": "Required",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Reset Password",
|
"reset-password": "Reset Password",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Enlever l'itinéraire de",
|
"removed-trail-from": "Enlever l'itinéraire de",
|
||||||
"removed-trails-from": "Enlever les itinéraires de",
|
"removed-trails-from": "Enlever les itinéraires de",
|
||||||
"required": "Requis",
|
"required": "Requis",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Réinitialiser le mot de passe",
|
"reset-password": "Réinitialiser le mot de passe",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Route",
|
"road": "Route",
|
||||||
"route": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
|
"route": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
|
||||||
"route-point": "Étape",
|
"route-point": "Étape",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Eltávolított nyomvonal a",
|
"removed-trail-from": "Eltávolított nyomvonal a",
|
||||||
"removed-trails-from": "Eltávolított nyomvonalak a",
|
"removed-trails-from": "Eltávolított nyomvonalak a",
|
||||||
"required": "Kötelező",
|
"required": "Kötelező",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Reset Password",
|
"reset-password": "Reset Password",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Percorso rimosso da",
|
"removed-trail-from": "Percorso rimosso da",
|
||||||
"removed-trails-from": "Percorsi rimosso da",
|
"removed-trails-from": "Percorsi rimosso da",
|
||||||
"required": "Obbligatorio",
|
"required": "Obbligatorio",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Ripristinare Password",
|
"reset-password": "Ripristinare Password",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Route verwijderd van",
|
"removed-trail-from": "Route verwijderd van",
|
||||||
"removed-trails-from": "Routes verwijderd van",
|
"removed-trails-from": "Routes verwijderd van",
|
||||||
"required": "Verplicht",
|
"required": "Verplicht",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Wachtwoord opnieuw instellen",
|
"reset-password": "Wachtwoord opnieuw instellen",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Weg",
|
"road": "Weg",
|
||||||
"route": "{n, plural,=1 {Tocht} other {Tochten}}",
|
"route": "{n, plural,=1 {Tocht} other {Tochten}}",
|
||||||
"route-point": "Routepunt",
|
"route-point": "Routepunt",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Usunięto szlak z",
|
"removed-trail-from": "Usunięto szlak z",
|
||||||
"removed-trails-from": "Usunięto szlaki z",
|
"removed-trails-from": "Usunięto szlaki z",
|
||||||
"required": "Wymagane",
|
"required": "Wymagane",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Resetuj hasło",
|
"reset-password": "Resetuj hasło",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural,=1 {Trasa} other {Trasy}}",
|
"route": "{n, plural,=1 {Trasa} other {Trasy}}",
|
||||||
"route-point": "Punkt trasy",
|
"route-point": "Punkt trasy",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Trilha removida de",
|
"removed-trail-from": "Trilha removida de",
|
||||||
"removed-trails-from": "Trilhos removidos de",
|
"removed-trails-from": "Trilhos removidos de",
|
||||||
"required": "Obrigatório",
|
"required": "Obrigatório",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Reset Password",
|
"reset-password": "Reset Password",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "Трек удалён из",
|
"removed-trail-from": "Трек удалён из",
|
||||||
"removed-trails-from": "Removed trails from",
|
"removed-trails-from": "Removed trails from",
|
||||||
"required": "Обязательно",
|
"required": "Обязательно",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "Сбросить пароль",
|
"reset-password": "Сбросить пароль",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Шоссе",
|
"road": "Шоссе",
|
||||||
"route": "{n, plural, =1 {Маршрут} other {Маршрутов}}",
|
"route": "{n, plural, =1 {Маршрут} other {Маршрутов}}",
|
||||||
"route-point": "Точка маршрута",
|
"route-point": "Точка маршрута",
|
||||||
|
|||||||
@@ -278,7 +278,9 @@
|
|||||||
"removed-trail-from": "路线已删除自",
|
"removed-trail-from": "路线已删除自",
|
||||||
"removed-trails-from": "路线已删除自",
|
"removed-trails-from": "路线已删除自",
|
||||||
"required": "必填",
|
"required": "必填",
|
||||||
|
"reset": "",
|
||||||
"reset-password": "重置密码",
|
"reset-password": "重置密码",
|
||||||
|
"reverse-direction": "",
|
||||||
"road": "Road",
|
"road": "Road",
|
||||||
"route": "{n, plural, =1 {Route} other {Routes}}",
|
"route": "{n, plural, =1 {Route} other {Routes}}",
|
||||||
"route-point": "Route Point",
|
"route-point": "Route Point",
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export default class GPX {
|
|||||||
distance: totalDistance,
|
distance: totalDistance,
|
||||||
elevationGain: totalElevationGain,
|
elevationGain: totalElevationGain,
|
||||||
elevationLoss: totalElevationLoss,
|
elevationLoss: totalElevationLoss,
|
||||||
duration: totalDuration,
|
duration: Math.abs(totalDuration),
|
||||||
hash: this.generateMinHash(allPoints)
|
hash: this.generateMinHash(allPoints)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import Waypoint from "$lib/models/gpx/waypoint";
|
|||||||
import { type RoutingOptions, type ValhallaAnchor, type ValhallaHeightResponse, type ValhallaRouteResponse } from "$lib/models/valhalla";
|
import { type RoutingOptions, type ValhallaAnchor, type ValhallaHeightResponse, type ValhallaRouteResponse } from "$lib/models/valhalla";
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import { decodePolyline, encodePolyline } from "$lib/util/polyline_util";
|
import { decodePolyline, encodePolyline } from "$lib/util/polyline_util";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
|
||||||
|
|
||||||
const emtpyTrack: Track = { trkseg: [] }
|
const emtpyTrack: Track = { trkseg: [] }
|
||||||
@@ -100,6 +102,49 @@ export function deleteFromRoute(index: number) {
|
|||||||
route.features = route.getTotals();
|
route.features = route.getTotals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function reverseRoute() {
|
||||||
|
for (const trk of route.trk ?? []) {
|
||||||
|
for (const seg of trk.trkseg ?? []) {
|
||||||
|
seg.trkpt?.reverse()
|
||||||
|
}
|
||||||
|
trk.trkseg?.reverse()
|
||||||
|
}
|
||||||
|
route.trk?.reverse()
|
||||||
|
|
||||||
|
route.features = route.getTotals();
|
||||||
|
|
||||||
|
anchors.reverse();
|
||||||
|
|
||||||
|
anchors.forEach((a, i) => {
|
||||||
|
if (!a.marker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a.marker.getElement().textContent = "" + (i + 1);
|
||||||
|
|
||||||
|
const anchorPopupHeading = a.marker
|
||||||
|
.getPopup()
|
||||||
|
._content.getElementsByTagName("h5")[0];
|
||||||
|
if (anchorPopupHeading) {
|
||||||
|
anchorPopupHeading.textContent =
|
||||||
|
get(_)("route-point") + " #" + (i + 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetRoute() {
|
||||||
|
route = new GPX({ trk: [emtpyTrack] });
|
||||||
|
|
||||||
|
anchors.forEach((a) => {
|
||||||
|
if(!a.marker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.marker.remove();
|
||||||
|
})
|
||||||
|
|
||||||
|
anchors = []
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizeRouteTime() {
|
export function normalizeRouteTime() {
|
||||||
let currentTime = new Date();
|
let currentTime = new Date();
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,8 @@
|
|||||||
editRoute,
|
editRoute,
|
||||||
insertIntoRoute,
|
insertIntoRoute,
|
||||||
normalizeRouteTime,
|
normalizeRouteTime,
|
||||||
|
resetRoute,
|
||||||
|
reverseRoute,
|
||||||
route,
|
route,
|
||||||
setRoute,
|
setRoute,
|
||||||
} from "$lib/stores/valhalla_store";
|
} from "$lib/stores/valhalla_store";
|
||||||
@@ -854,6 +856,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reverseTrail() {
|
||||||
|
reverseRoute();
|
||||||
|
|
||||||
|
updateTrailWithRouteData();
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTrail() {
|
||||||
|
resetRoute();
|
||||||
|
|
||||||
|
updateTrailWithRouteData();
|
||||||
|
}
|
||||||
|
|
||||||
function updateTrailWithRouteData() {
|
function updateTrailWithRouteData() {
|
||||||
overwriteGPX = true;
|
overwriteGPX = true;
|
||||||
const totals = route.features;
|
const totals = route.features;
|
||||||
@@ -1276,9 +1290,12 @@
|
|||||||
<div
|
<div
|
||||||
in:scale={{ easing: backInOut }}
|
in:scale={{ easing: backInOut }}
|
||||||
out:scale={{ easing: backInOut }}
|
out:scale={{ easing: backInOut }}
|
||||||
class="absolute top-0 left-16 z-50"
|
class="absolute top-8 left-2 z-50"
|
||||||
>
|
>
|
||||||
<RoutingOptionsPopup bind:options={routingOptions}
|
<RoutingOptionsPopup
|
||||||
|
bind:options={routingOptions}
|
||||||
|
onReverse={reverseTrail}
|
||||||
|
onReset={resetTrail}
|
||||||
></RoutingOptionsPopup>
|
></RoutingOptionsPopup>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user