improves gpx elevation calculation
This commit is contained in:
@@ -101,7 +101,7 @@
|
||||
"empty-activities": "{username} has no activity yet",
|
||||
"empty-bio": "{username} has not added a bio yet",
|
||||
"empty-lists": "{username} has no public lists",
|
||||
"enable-auto-routing": "",
|
||||
"enable-auto-routing": "Enable auto-routing",
|
||||
"english": "English",
|
||||
"entry": "Entry",
|
||||
"error-creating-user": "Error creating user",
|
||||
|
||||
@@ -7,6 +7,9 @@ import Waypoint from './waypoint';
|
||||
import GpxMetricsComputation from './gpx-metrics-computation';
|
||||
//@ts-ignore
|
||||
import geohash from "ngeohash"
|
||||
import { encodePolyline } from '$lib/util/polyline_util';
|
||||
import { APIError } from '$lib/util/api_util';
|
||||
import type { ValhallaHeightResponse } from '../valhalla';
|
||||
|
||||
const defaultAttributes = {
|
||||
version: '1.1',
|
||||
@@ -97,7 +100,7 @@ export default class GPX {
|
||||
let totalLat = 0
|
||||
let totalLon = 0
|
||||
|
||||
const metrics = new GpxMetricsComputation(5, 10);
|
||||
const metrics = new GpxMetricsComputation(5, 5);
|
||||
|
||||
let minLat = Infinity, maxLat = -Infinity, minLon = Infinity, maxLon = -Infinity;
|
||||
|
||||
@@ -155,19 +158,40 @@ export default class GPX {
|
||||
return hashes.sort().join('').slice(0, 10);
|
||||
}
|
||||
|
||||
isSimilar(other: GPX, distanceThreshold = 50): boolean {
|
||||
const f1 = this.features;
|
||||
const f2 = other.features;
|
||||
const centroidDistance = haversineDistance(f1.centroid.lat, f1.centroid.lon, f2.centroid.lat, f2.centroid.lon);
|
||||
const boundingBoxOverlap =
|
||||
f1.boundingBox.minLat <= f2.boundingBox.maxLat && f1.boundingBox.maxLat >= f2.boundingBox.minLat &&
|
||||
f1.boundingBox.minLon <= f2.boundingBox.maxLon && f1.boundingBox.maxLon >= f2.boundingBox.minLon;
|
||||
async correctElevation(f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
||||
let coordinates: number[][] = []
|
||||
for (const track of this.trk ?? []) {
|
||||
for (const segment of track.trkseg ?? []) {
|
||||
if (!segment.trkpt) {
|
||||
continue
|
||||
}
|
||||
coordinates = coordinates.concat(segment.trkpt.map(pt => [pt.$.lat ?? 0, pt.$.lon ?? 0]))
|
||||
}
|
||||
}
|
||||
|
||||
const lengthDifference = Math.abs(f1.distance - f2.distance);
|
||||
const hashSimilarity = f1.hash === f2.hash;
|
||||
const shape = encodePolyline(coordinates);
|
||||
const r2 = await f("/api/v1/valhalla/height", { method: "POST", body: JSON.stringify({ encoded_polyline: shape }) })
|
||||
|
||||
return centroidDistance < distanceThreshold || boundingBoxOverlap || (lengthDifference < 100 && hashSimilarity);
|
||||
if (!r2.ok) {
|
||||
const response = await r2.json();
|
||||
throw new APIError(r2.status, response.message, response.detail)
|
||||
}
|
||||
|
||||
const heightResponse: ValhallaHeightResponse = await r2.json()
|
||||
|
||||
let heightIndex = 0;
|
||||
for (const track of this.trk ?? []) {
|
||||
for (const segment of track.trkseg ?? []) {
|
||||
if (!segment.trkpt) {
|
||||
continue
|
||||
}
|
||||
segment.trkpt.forEach((pt) => {
|
||||
pt.ele = heightResponse.height[heightIndex]
|
||||
heightIndex++;
|
||||
})
|
||||
}
|
||||
}
|
||||
this.features = this.getTotals()
|
||||
}
|
||||
|
||||
static parse(gpxString: string): Promise<GPX | Error> {
|
||||
@@ -182,7 +206,7 @@ export default class GPX {
|
||||
return str;
|
||||
}
|
||||
]
|
||||
}, (err, xml) => {
|
||||
}, async (err, xml) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import GPX from "$lib/models/gpx/gpx";
|
||||
import { Trail } from "$lib/models/trail";
|
||||
import { Waypoint } from "$lib/models/waypoint";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { gpx, kml, tcx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||
import cryptoRandomString from "crypto-random-string";
|
||||
import { get } from "svelte/store";
|
||||
//@ts-ignore
|
||||
import { browser } from "$app/environment";
|
||||
import Track from "$lib/models/gpx/track";
|
||||
@@ -12,19 +10,20 @@ import TrackSegment from "$lib/models/gpx/track-segment";
|
||||
import GPXWaypoint from "$lib/models/gpx/waypoint";
|
||||
import EasyFit from "$lib/vendor/easy-fit/easy-fit";
|
||||
import type { Feature, FeatureCollection, GeoJSON, GeoJsonProperties, Position } from 'geojson';
|
||||
import * as xmldom from 'xmldom';
|
||||
import { bbox, splitMultiLineStringToLineStrings } from "./geojson_util";
|
||||
import JSZip from "jszip";
|
||||
import type { AuthRecord } from "pocketbase";
|
||||
import * as xmldom from 'xmldom';
|
||||
import { bbox, splitMultiLineStringToLineStrings } from "./geojson_util";
|
||||
|
||||
|
||||
export async function gpx2trail(gpxString: string, fallbackName?: string) {
|
||||
export async function gpx2trail(gpxString: string, fallbackName?: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
||||
|
||||
const gpx = await GPX.parse(gpxString);
|
||||
|
||||
if (gpx instanceof Error) {
|
||||
throw gpx;
|
||||
}
|
||||
await gpx.correctElevation(f)
|
||||
|
||||
const trail = new Trail("");
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function PUT(event: RequestEvent) {
|
||||
}
|
||||
let parseResult: { trail: Trail, gpx: GPX };
|
||||
try {
|
||||
parseResult = (await gpx2trail(gpxData, data.get("name") as string | undefined));
|
||||
parseResult = (await gpx2trail(gpxData, data.get("name") as string | undefined, event.fetch));
|
||||
} catch (e: any) {
|
||||
console.error(e)
|
||||
throw new ClientResponseError({ status: 400, response: { message: "Invalid file" } })
|
||||
|
||||
Reference in New Issue
Block a user