mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-01-15 14:18:41 +00:00
Compare commits
2 Commits
3c816567bc
...
graphhoppe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ca46b9d35 | ||
|
|
7c2e24bbc4 |
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Ignore files for PNPM, NPM and YARN
|
||||||
|
pnpm-lock.yaml
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
src/lib/components/ui
|
||||||
|
*.mdx
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"postinstall": "npm run build",
|
"postinstall": "npm run build",
|
||||||
"lint": "prettier --check . --config ../.prettierrc && eslint .",
|
"lint": "prettier --check . && eslint .",
|
||||||
"format": "prettier --write . --config ../.prettierrc"
|
"format": "prettier --write ."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1375,10 +1375,7 @@ export class TrackPoint {
|
|||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
setExtensions(extensions: Record<string, string>) {
|
setExtension(key: string, value: string) {
|
||||||
if (Object.keys(extensions).length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!this.extensions) {
|
if (!this.extensions) {
|
||||||
this.extensions = {};
|
this.extensions = {};
|
||||||
}
|
}
|
||||||
@@ -1388,8 +1385,12 @@ export class TrackPoint {
|
|||||||
if (!this.extensions['gpxtpx:TrackPointExtension']['gpxtpx:Extensions']) {
|
if (!this.extensions['gpxtpx:TrackPointExtension']['gpxtpx:Extensions']) {
|
||||||
this.extensions['gpxtpx:TrackPointExtension']['gpxtpx:Extensions'] = {};
|
this.extensions['gpxtpx:TrackPointExtension']['gpxtpx:Extensions'] = {};
|
||||||
}
|
}
|
||||||
|
this.extensions['gpxtpx:TrackPointExtension']['gpxtpx:Extensions'][key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
setExtensions(extensions: Record<string, string>) {
|
||||||
Object.entries(extensions).forEach(([key, value]) => {
|
Object.entries(extensions).forEach(([key, value]) => {
|
||||||
this.extensions['gpxtpx:TrackPointExtension']['gpxtpx:Extensions'][key] = value;
|
this.setExtension(key, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
src/lib/components/ui
|
|
||||||
src/lib/docs/**/*.mdx
|
|
||||||
**/*.webmanifest
|
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://shadcn-svelte.com/schema.json",
|
"$schema": "https://shadcn-svelte.com/schema.json",
|
||||||
"style": "default",
|
"style": "default",
|
||||||
"tailwind": {
|
"tailwind": {
|
||||||
"css": "src/app.css",
|
"css": "src/app.css",
|
||||||
"baseColor": "slate"
|
"baseColor": "slate"
|
||||||
},
|
},
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"components": "$lib/components",
|
"components": "$lib/components",
|
||||||
"utils": "$lib/utils",
|
"utils": "$lib/utils",
|
||||||
"ui": "$lib/components/ui",
|
"ui": "$lib/components/ui",
|
||||||
"hooks": "$lib/hooks",
|
"hooks": "$lib/hooks",
|
||||||
"lib": "$lib"
|
"lib": "$lib"
|
||||||
},
|
},
|
||||||
"typescript": true,
|
"typescript": true,
|
||||||
"registry": "https://shadcn-svelte.com/registry"
|
"registry": "https://shadcn-svelte.com/registry"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"lint": "prettier --check . --config ../.prettierrc && eslint .",
|
"lint": "prettier --check . && eslint .",
|
||||||
"format": "prettier --write . --config ../.prettierrc"
|
"format": "prettier --write ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lucide/svelte": "^0.544.0",
|
"@lucide/svelte": "^0.544.0",
|
||||||
|
|||||||
@@ -1,126 +1,126 @@
|
|||||||
@import 'tailwindcss';
|
@import "tailwindcss";
|
||||||
@import 'tw-animate-css';
|
@import "tw-animate-css";
|
||||||
|
|
||||||
@custom-variant dark (&:is(.dark *));
|
@custom-variant dark (&:is(.dark *));
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: hsl(0 0% 100%) /* <- Wrap in HSL */;
|
--background: hsl(0 0% 100%) /* <- Wrap in HSL */;
|
||||||
--foreground: hsl(240 10% 3.9%);
|
--foreground: hsl(240 10% 3.9%);
|
||||||
--muted: hsl(240 4.8% 95.9%);
|
--muted: hsl(240 4.8% 95.9%);
|
||||||
--muted-foreground: hsl(240 3.8% 46.1%);
|
--muted-foreground: hsl(240 3.8% 46.1%);
|
||||||
--popover: hsl(0 0% 100%);
|
--popover: hsl(0 0% 100%);
|
||||||
--popover-foreground: hsl(240 10% 3.9%);
|
--popover-foreground: hsl(240 10% 3.9%);
|
||||||
--card: hsl(0 0% 100%);
|
--card: hsl(0 0% 100%);
|
||||||
--card-foreground: hsl(240 10% 3.9%);
|
--card-foreground: hsl(240 10% 3.9%);
|
||||||
--border: hsl(240 5.9% 90%);
|
--border: hsl(240 5.9% 90%);
|
||||||
--input: hsl(240 5.9% 90%);
|
--input: hsl(240 5.9% 90%);
|
||||||
--primary: hsl(240 5.9% 10%);
|
--primary: hsl(240 5.9% 10%);
|
||||||
--primary-foreground: hsl(0 0% 98%);
|
--primary-foreground: hsl(0 0% 98%);
|
||||||
--secondary: hsl(240 4.8% 95.9%);
|
--secondary: hsl(240 4.8% 95.9%);
|
||||||
--secondary-foreground: hsl(240 5.9% 10%);
|
--secondary-foreground: hsl(240 5.9% 10%);
|
||||||
--accent: hsl(240 4.8% 95.9%);
|
--accent: hsl(240 4.8% 95.9%);
|
||||||
--accent-foreground: hsl(240 5.9% 10%);
|
--accent-foreground: hsl(240 5.9% 10%);
|
||||||
--destructive: hsl(0 72.2% 50.6%);
|
--destructive: hsl(0 72.2% 50.6%);
|
||||||
--destructive-foreground: hsl(0 0% 98%);
|
--destructive-foreground: hsl(0 0% 98%);
|
||||||
--ring: hsl(240 10% 3.9%);
|
--ring: hsl(240 10% 3.9%);
|
||||||
--sidebar: hsl(0 0% 98%);
|
--sidebar: hsl(0 0% 98%);
|
||||||
--sidebar-foreground: hsl(240 5.3% 26.1%);
|
--sidebar-foreground: hsl(240 5.3% 26.1%);
|
||||||
--sidebar-primary: hsl(240 5.9% 10%);
|
--sidebar-primary: hsl(240 5.9% 10%);
|
||||||
--sidebar-primary-foreground: hsl(0 0% 98%);
|
--sidebar-primary-foreground: hsl(0 0% 98%);
|
||||||
--sidebar-accent: hsl(240 4.8% 95.9%);
|
--sidebar-accent: hsl(240 4.8% 95.9%);
|
||||||
--sidebar-accent-foreground: hsl(240 5.9% 10%);
|
--sidebar-accent-foreground: hsl(240 5.9% 10%);
|
||||||
--sidebar-border: hsl(220 13% 91%);
|
--sidebar-border: hsl(220 13% 91%);
|
||||||
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
||||||
|
|
||||||
--support: rgb(220 15 130);
|
--support: rgb(220 15 130);
|
||||||
--link: rgb(0 110 180);
|
--link: rgb(0 110 180);
|
||||||
--selection: hsl(240 4.8% 93%);
|
--selection: hsl(240 4.8% 93%);
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: hsl(240 10% 3.9%);
|
--background: hsl(240 10% 3.9%);
|
||||||
--foreground: hsl(0 0% 98%);
|
--foreground: hsl(0 0% 98%);
|
||||||
--muted: hsl(240 3.7% 15.9%);
|
--muted: hsl(240 3.7% 15.9%);
|
||||||
--muted-foreground: hsl(240 5% 64.9%);
|
--muted-foreground: hsl(240 5% 64.9%);
|
||||||
--popover: hsl(240 10% 3.9%);
|
--popover: hsl(240 10% 3.9%);
|
||||||
--popover-foreground: hsl(0 0% 98%);
|
--popover-foreground: hsl(0 0% 98%);
|
||||||
--card: hsl(240 10% 3.9%);
|
--card: hsl(240 10% 3.9%);
|
||||||
--card-foreground: hsl(0 0% 98%);
|
--card-foreground: hsl(0 0% 98%);
|
||||||
--border: hsl(240 3.7% 15.9%);
|
--border: hsl(240 3.7% 15.9%);
|
||||||
--input: hsl(240 3.7% 15.9%);
|
--input: hsl(240 3.7% 15.9%);
|
||||||
--primary: hsl(0 0% 98%);
|
--primary: hsl(0 0% 98%);
|
||||||
--primary-foreground: hsl(240 5.9% 10%);
|
--primary-foreground: hsl(240 5.9% 10%);
|
||||||
--secondary: hsl(240 3.7% 15.9%);
|
--secondary: hsl(240 3.7% 15.9%);
|
||||||
--secondary-foreground: hsl(0 0% 98%);
|
--secondary-foreground: hsl(0 0% 98%);
|
||||||
--accent: hsl(240 3.7% 15.9%);
|
--accent: hsl(240 3.7% 15.9%);
|
||||||
--accent-foreground: hsl(0 0% 98%);
|
--accent-foreground: hsl(0 0% 98%);
|
||||||
--destructive: hsl(0 62.8% 30.6%);
|
--destructive: hsl(0 62.8% 30.6%);
|
||||||
--destructive-foreground: hsl(0 0% 98%);
|
--destructive-foreground: hsl(0 0% 98%);
|
||||||
--ring: hsl(240 4.9% 83.9%);
|
--ring: hsl(240 4.9% 83.9%);
|
||||||
--sidebar: hsl(240 5.9% 10%);
|
--sidebar: hsl(240 5.9% 10%);
|
||||||
--sidebar-foreground: hsl(240 4.8% 95.9%);
|
--sidebar-foreground: hsl(240 4.8% 95.9%);
|
||||||
--sidebar-primary: hsl(224.3 76.3% 48%);
|
--sidebar-primary: hsl(224.3 76.3% 48%);
|
||||||
--sidebar-primary-foreground: hsl(0 0% 100%);
|
--sidebar-primary-foreground: hsl(0 0% 100%);
|
||||||
--sidebar-accent: hsl(240 3.7% 15.9%);
|
--sidebar-accent: hsl(240 3.7% 15.9%);
|
||||||
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
|
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
|
||||||
--sidebar-border: hsl(240 3.7% 15.9%);
|
--sidebar-border: hsl(240 3.7% 15.9%);
|
||||||
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
||||||
|
|
||||||
--support: rgb(255 110 190);
|
--support: rgb(255 110 190);
|
||||||
--link: rgb(80 190 255);
|
--link: rgb(80 190 255);
|
||||||
--selection: hsl(240 3.7% 22%);
|
--selection: hsl(240 3.7% 22%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
/* Radius (for rounded-*) */
|
/* Radius (for rounded-*) */
|
||||||
--radius-sm: calc(var(--radius) - 4px);
|
--radius-sm: calc(var(--radius) - 4px);
|
||||||
--radius-md: calc(var(--radius) - 2px);
|
--radius-md: calc(var(--radius) - 2px);
|
||||||
--radius-lg: var(--radius);
|
--radius-lg: var(--radius);
|
||||||
--radius-xl: calc(var(--radius) + 4px);
|
--radius-xl: calc(var(--radius) + 4px);
|
||||||
|
|
||||||
|
/* Colors */
|
||||||
|
--color-background: var(--background);
|
||||||
|
--color-foreground: var(--foreground);
|
||||||
|
--color-muted: var(--muted);
|
||||||
|
--color-muted-foreground: var(--muted-foreground);
|
||||||
|
--color-popover: var(--popover);
|
||||||
|
--color-popover-foreground: var(--popover-foreground);
|
||||||
|
--color-card: var(--card);
|
||||||
|
--color-card-foreground: var(--card-foreground);
|
||||||
|
--color-border: var(--border);
|
||||||
|
--color-input: var(--input);
|
||||||
|
--color-primary: var(--primary);
|
||||||
|
--color-primary-foreground: var(--primary-foreground);
|
||||||
|
--color-secondary: var(--secondary);
|
||||||
|
--color-secondary-foreground: var(--secondary-foreground);
|
||||||
|
--color-accent: var(--accent);
|
||||||
|
--color-accent-foreground: var(--accent-foreground);
|
||||||
|
--color-destructive: var(--destructive);
|
||||||
|
--color-destructive-foreground: var(--destructive-foreground);
|
||||||
|
--color-ring: var(--ring);
|
||||||
|
--color-radius: var(--radius);
|
||||||
|
--color-sidebar: var(--sidebar);
|
||||||
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
|
--color-sidebar-primary: var(--sidebar-primary);
|
||||||
|
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||||
|
--color-sidebar-accent: var(--sidebar-accent);
|
||||||
|
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||||
|
--color-sidebar-border: var(--sidebar-border);
|
||||||
|
--color-sidebar-ring: var(--sidebar-ring);
|
||||||
|
--color-support: var(--support);
|
||||||
|
--color-link: var(--link);
|
||||||
|
|
||||||
/* Colors */
|
--breakpoint-xs: 540px;
|
||||||
--color-background: var(--background);
|
|
||||||
--color-foreground: var(--foreground);
|
|
||||||
--color-muted: var(--muted);
|
|
||||||
--color-muted-foreground: var(--muted-foreground);
|
|
||||||
--color-popover: var(--popover);
|
|
||||||
--color-popover-foreground: var(--popover-foreground);
|
|
||||||
--color-card: var(--card);
|
|
||||||
--color-card-foreground: var(--card-foreground);
|
|
||||||
--color-border: var(--border);
|
|
||||||
--color-input: var(--input);
|
|
||||||
--color-primary: var(--primary);
|
|
||||||
--color-primary-foreground: var(--primary-foreground);
|
|
||||||
--color-secondary: var(--secondary);
|
|
||||||
--color-secondary-foreground: var(--secondary-foreground);
|
|
||||||
--color-accent: var(--accent);
|
|
||||||
--color-accent-foreground: var(--accent-foreground);
|
|
||||||
--color-destructive: var(--destructive);
|
|
||||||
--color-destructive-foreground: var(--destructive-foreground);
|
|
||||||
--color-ring: var(--ring);
|
|
||||||
--color-radius: var(--radius);
|
|
||||||
--color-sidebar: var(--sidebar);
|
|
||||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
||||||
--color-sidebar-primary: var(--sidebar-primary);
|
|
||||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
||||||
--color-sidebar-accent: var(--sidebar-accent);
|
|
||||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
||||||
--color-sidebar-border: var(--sidebar-border);
|
|
||||||
--color-sidebar-ring: var(--sidebar-ring);
|
|
||||||
--color-support: var(--support);
|
|
||||||
--color-link: var(--link);
|
|
||||||
|
|
||||||
--breakpoint-xs: 540px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
SquareArrowUpLeft,
|
SquareArrowUpLeft,
|
||||||
SquareArrowOutDownRight,
|
SquareArrowOutDownRight,
|
||||||
} from '@lucide/svelte';
|
} from '@lucide/svelte';
|
||||||
import { brouterProfiles } from '$lib/components/toolbar/tools/routing/routing';
|
import { routingProfiles } from '$lib/components/toolbar/tools/routing/routing';
|
||||||
import { i18n } from '$lib/i18n.svelte';
|
import { i18n } from '$lib/i18n.svelte';
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
import {
|
import {
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
{i18n._(`toolbar.routing.activities.${$routingProfile}`)}
|
{i18n._(`toolbar.routing.activities.${$routingProfile}`)}
|
||||||
</Select.Trigger>
|
</Select.Trigger>
|
||||||
<Select.Content>
|
<Select.Content>
|
||||||
{#each Object.keys(brouterProfiles) as profile}
|
{#each Object.keys(routingProfiles) as profile}
|
||||||
<Select.Item value={profile}
|
<Select.Item value={profile}
|
||||||
>{i18n._(
|
>{i18n._(
|
||||||
`toolbar.routing.activities.${profile}`
|
`toolbar.routing.activities.${profile}`
|
||||||
|
|||||||
@@ -6,35 +6,141 @@ import { get } from 'svelte/store';
|
|||||||
|
|
||||||
const { routing, routingProfile, privateRoads } = settings;
|
const { routing, routingProfile, privateRoads } = settings;
|
||||||
|
|
||||||
export const brouterProfiles: { [key: string]: string } = {
|
export type RoutingProfile = {
|
||||||
bike: 'Trekking-dry',
|
engine: 'graphhopper' | 'brouter';
|
||||||
racing_bike: 'fastbike',
|
profile: string;
|
||||||
gravel_bike: 'gravel',
|
};
|
||||||
mountain_bike: 'MTB',
|
|
||||||
foot: 'Hiking-Alpine-SAC6',
|
export const routingProfiles: { [key: string]: RoutingProfile } = {
|
||||||
motorcycle: 'Car-FastEco',
|
bike: { engine: 'graphhopper', profile: 'bike' },
|
||||||
water: 'river',
|
racing_bike: { engine: 'graphhopper', profile: 'racingbike' },
|
||||||
railway: 'rail',
|
gravel_bike: { engine: 'brouter', profile: 'gravel' },
|
||||||
|
mountain_bike: { engine: 'graphhopper', profile: 'mtb' },
|
||||||
|
foot: { engine: 'graphhopper', profile: 'foot' },
|
||||||
|
motorcycle: { engine: 'graphhopper', profile: 'motorcycle' },
|
||||||
|
water: { engine: 'brouter', profile: 'river' },
|
||||||
|
railway: { engine: 'brouter', profile: 'rail' },
|
||||||
};
|
};
|
||||||
|
|
||||||
export function route(points: Coordinates[]): Promise<TrackPoint[]> {
|
export function route(points: Coordinates[]): Promise<TrackPoint[]> {
|
||||||
if (get(routing)) {
|
if (get(routing)) {
|
||||||
return getRoute(points, brouterProfiles[get(routingProfile)], get(privateRoads));
|
const profile = routingProfiles[get(routingProfile)];
|
||||||
|
if (profile.engine === 'graphhopper') {
|
||||||
|
return getGraphHopperRoute(points, profile.profile, get(privateRoads));
|
||||||
|
} else {
|
||||||
|
return getBRouterRoute(points, profile.profile);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return getIntermediatePoints(points);
|
return getIntermediatePoints(points);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getRoute(
|
const graphhopperDetails = ['road_class', 'surface', 'hike_rating', 'mtb_rating'];
|
||||||
|
const hikeRatingToSACScale: { [key: string]: string } = {
|
||||||
|
'1': 'hiking',
|
||||||
|
'2': 'mountain_hiking',
|
||||||
|
'3': 'demanding_mountain_hiking',
|
||||||
|
'4': 'alpine_hiking',
|
||||||
|
'5': 'demanding_alpine_hiking',
|
||||||
|
'6': 'difficult_alpine_hiking',
|
||||||
|
};
|
||||||
|
const mtbRatingToScale: { [key: string]: string } = {
|
||||||
|
'1': '0',
|
||||||
|
'2': '1',
|
||||||
|
'3': '2',
|
||||||
|
'4': '3',
|
||||||
|
'5': '4',
|
||||||
|
'6': '5',
|
||||||
|
'7': '6',
|
||||||
|
};
|
||||||
|
async function getGraphHopperRoute(
|
||||||
points: Coordinates[],
|
points: Coordinates[],
|
||||||
brouterProfile: string,
|
graphHopperProfile: string,
|
||||||
privateRoads: boolean
|
privateRoads: boolean
|
||||||
): Promise<TrackPoint[]> {
|
): Promise<TrackPoint[]> {
|
||||||
let url = `https://brouter.gpx.studio?lonlats=${points.map((point) => `${point.lon.toFixed(8)},${point.lat.toFixed(8)}`).join('|')}&profile=${brouterProfile + (privateRoads ? '-private' : '')}&format=geojson&alternativeidx=0`;
|
let response = await fetch('https://graphhopper-a.gpx.studio/route', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
points: points.map((point) => [point.lon, point.lat]),
|
||||||
|
profile: graphHopperProfile,
|
||||||
|
elevation: true,
|
||||||
|
points_encoded: false,
|
||||||
|
details: graphhopperDetails,
|
||||||
|
custom_model: privateRoads
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
priority: [
|
||||||
|
{
|
||||||
|
if: 'road_access == PRIVATE',
|
||||||
|
multiply_by: '0.0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`${await response.text()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let json = await response.json();
|
||||||
|
|
||||||
|
let route: TrackPoint[] = [];
|
||||||
|
let coordinates = json.paths[0].points.coordinates;
|
||||||
|
let details = json.paths[0].details;
|
||||||
|
|
||||||
|
for (let i = 0; i < coordinates.length; i++) {
|
||||||
|
route.push(
|
||||||
|
new TrackPoint({
|
||||||
|
attributes: {
|
||||||
|
lat: coordinates[i][1],
|
||||||
|
lon: coordinates[i][0],
|
||||||
|
},
|
||||||
|
ele: coordinates[i][2] ?? (i > 0 ? route[i - 1].ele : 0),
|
||||||
|
extensions: {},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let key of graphhopperDetails) {
|
||||||
|
let detail = details[key];
|
||||||
|
for (let i = 0; i < detail.length; i++) {
|
||||||
|
for (let j = detail[i][0]; j < detail[i][1] + (i == detail.length - 1); j++) {
|
||||||
|
if (detail[i][2] !== undefined && detail[i][2] !== 'missing') {
|
||||||
|
if (key === 'road_class') {
|
||||||
|
route[j].setExtension('highway', detail[i][2]);
|
||||||
|
} else if (key === 'hike_rating') {
|
||||||
|
const sacScale = hikeRatingToSACScale[detail[i][2]];
|
||||||
|
if (sacScale) {
|
||||||
|
route[j].setExtension('sac_scale', sacScale);
|
||||||
|
}
|
||||||
|
} else if (key === 'mtb_rating') {
|
||||||
|
const mtbScale = mtbRatingToScale[detail[i][2]];
|
||||||
|
if (mtbScale) {
|
||||||
|
route[j].setExtension('mtb_scale', mtbScale);
|
||||||
|
}
|
||||||
|
} else if (key === 'surface' && detail[i][2] !== 'other') {
|
||||||
|
route[j].setExtension('surface', detail[i][2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getBRouterRoute(
|
||||||
|
points: Coordinates[],
|
||||||
|
brouterProfile: string
|
||||||
|
): Promise<TrackPoint[]> {
|
||||||
|
let url = `https://brouter.de/brouter?lonlats=${points.map((point) => `${point.lon.toFixed(8)},${point.lat.toFixed(8)}`).join('|')}&profile=${brouterProfile}&format=geojson&alternativeidx=0`;
|
||||||
|
|
||||||
let response = await fetch(url);
|
let response = await fetch(url);
|
||||||
|
|
||||||
// Check if the response is ok
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`${await response.text()}`);
|
throw new Error(`${await response.text()}`);
|
||||||
}
|
}
|
||||||
@@ -52,14 +158,13 @@ async function getRoute(
|
|||||||
let tags = messageIdx < messages.length ? getTags(messages[messageIdx][tagIdx]) : {};
|
let tags = messageIdx < messages.length ? getTags(messages[messageIdx][tagIdx]) : {};
|
||||||
|
|
||||||
for (let i = 0; i < coordinates.length; i++) {
|
for (let i = 0; i < coordinates.length; i++) {
|
||||||
let coord = coordinates[i];
|
|
||||||
route.push(
|
route.push(
|
||||||
new TrackPoint({
|
new TrackPoint({
|
||||||
attributes: {
|
attributes: {
|
||||||
lat: coord[1],
|
lat: coordinates[i][1],
|
||||||
lon: coord[0],
|
lon: coordinates[i][0],
|
||||||
},
|
},
|
||||||
ele: coord[2] ?? (i > 0 ? route[i - 1].ele : 0),
|
ele: coordinates[i][2] ?? (i > 0 ? route[i - 1].ele : 0),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user