diff --git a/gpx/src/gpx.ts b/gpx/src/gpx.ts index 54612f18..2d06ae6e 100644 --- a/gpx/src/gpx.ts +++ b/gpx/src/gpx.ts @@ -784,7 +784,7 @@ export class TrackSegment extends GPXTreeLeaf { let start = simplified[i].point._data.index; let end = simplified[i + 1].point._data.index; let dist = statistics.local.distance.total[end] - statistics.local.distance.total[start]; - let ele = simplified[i + 1].point.ele - simplified[i].point.ele; + let ele = (simplified[i + 1].point.ele ?? 0) - (simplified[i].point.ele ?? 0); for (let j = start; j < end + (i + 1 === simplified.length - 1 ? 1 : 0); j++) { slope.push(0.1 * ele / dist); @@ -1326,6 +1326,17 @@ export class GPXStatistics { } slice(start: number, end: number): GPXStatistics { + if (start < 0) { + start = 0; + } else if (start >= this.local.points.length) { + return new GPXStatistics(); + } + if (end < start) { + return new GPXStatistics(); + } else if (end >= this.local.points.length) { + end = this.local.points.length - 1; + } + let statistics = new GPXStatistics(); statistics.local.points = this.local.points.slice(start, end + 1); @@ -1360,7 +1371,13 @@ export class GPXStatistics { } const earthRadius = 6371008.8; -export function distance(coord1: Coordinates, coord2: Coordinates): number { +export function distance(coord1: TrackPoint | Coordinates, coord2: TrackPoint | Coordinates): number { + if (coord1 instanceof TrackPoint) { + coord1 = coord1.getCoordinates(); + } + if (coord2 instanceof TrackPoint) { + coord2 = coord2.getCoordinates(); + } const rad = Math.PI / 180; const lat1 = coord1.lat * rad; const lat2 = coord2.lat * rad; @@ -1412,9 +1429,15 @@ function withTimestamps(points: TrackPoint[], speed: number, lastPoint: TrackPoi function withShiftedAndCompressedTimestamps(points: TrackPoint[], speed: number, ratio: number, lastPoint: TrackPoint): TrackPoint[] { let start = getTimestamp(lastPoint, points[0], speed); + let last = points[0]; return points.map((point) => { let pt = point.clone(); - pt.time = new Date(start.getTime() + ratio * (point.time.getTime() - points[0].time.getTime())); + if (point.time === undefined) { + pt.time = getTimestamp(last, point, speed); + } else { + pt.time = new Date(start.getTime() + ratio * (point.time.getTime() - points[0].time.getTime())); + } + last = pt; return pt; }); } diff --git a/website/src/lib/components/Menu.svelte b/website/src/lib/components/Menu.svelte index add8a904..ca67c0a3 100644 --- a/website/src/lib/components/Menu.svelte +++ b/website/src/lib/components/Menu.svelte @@ -500,12 +500,14 @@ dbUtils.undo(); } } else if ((e.key === 'Backspace' || e.key === 'Delete') && (e.metaKey || e.ctrlKey)) { - if (e.shiftKey) { - dbUtils.deleteAllFiles(); - } else { - dbUtils.deleteSelection(); + if (!targetInput) { + if (e.shiftKey) { + dbUtils.deleteAllFiles(); + } else { + dbUtils.deleteSelection(); + } + e.preventDefault(); } - e.preventDefault(); } else if (e.key === 'a' && (e.metaKey || e.ctrlKey)) { if (!targetInput) { selectAll(); diff --git a/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts b/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts index ec118d16..08b21755 100644 --- a/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts +++ b/website/src/lib/components/toolbar/tools/routing/RoutingControls.ts @@ -334,14 +334,14 @@ export class RoutingControls { let file = get(this.file)?.file; // Find the point closest to the temporary anchor - let minDistance = Number.MAX_VALUE; + let minDetails: any = { distance: Number.MAX_VALUE }; let minAnchor = this.temporaryAnchor as Anchor; file?.forEachSegment((segment, trackIndex, segmentIndex) => { if (get(selection).hasAnyParent(new ListTrackSegmentItem(this.fileId, trackIndex, segmentIndex))) { let details: any = {}; let closest = getClosestLinePoint(segment.trkpt, this.temporaryAnchor.point, details); - if (details.distance < minDistance) { - minDistance = details.distance; + if (details.distance < minDetails.distance) { + minDetails = details; minAnchor = { point: closest, segment, @@ -352,6 +352,15 @@ export class RoutingControls { } }); + if (minAnchor.point._data.anchor) { + minAnchor.point = minAnchor.point.clone(); + if (minDetails.before) { + minAnchor.point._data.index = minAnchor.point._data.index + 0.5; + } else { + minAnchor.point._data.index = minAnchor.point._data.index - 0.5; + } + } + return minAnchor; } diff --git a/website/src/lib/components/toolbar/tools/scissors/Scissors.svelte b/website/src/lib/components/toolbar/tools/scissors/Scissors.svelte index 9c51406b..05ff6143 100644 --- a/website/src/lib/components/toolbar/tools/scissors/Scissors.svelte +++ b/website/src/lib/components/toolbar/tools/scissors/Scissors.svelte @@ -37,8 +37,8 @@ $selection.hasAnyChildren(new ListRootItem(), true, ['waypoints']) && $gpxStatistics.local.points.length > 0; - let maxSliderValue = 100; - let sliderValues = [0, 100]; + let maxSliderValue = 1; + let sliderValues = [0, 1]; function updateCanCrop() { canCrop = sliderValues[0] != 0 || sliderValues[1] != maxSliderValue; @@ -66,7 +66,7 @@ if (validSelection && $gpxStatistics.local.points.length > 0) { maxSliderValue = $gpxStatistics.local.points.length - 1; } else { - maxSliderValue = 100; + maxSliderValue = 1; } await tick(); sliderValues = [0, maxSliderValue]; diff --git a/website/src/lib/utils.ts b/website/src/lib/utils.ts index 3542aae4..1e0d6e40 100644 --- a/website/src/lib/utils.ts +++ b/website/src/lib/utils.ts @@ -5,11 +5,10 @@ import type { TransitionConfig } from "svelte/transition"; import { get } from "svelte/store"; import { map } from "./stores"; import { base } from "$app/paths"; -import { browser } from "$app/environment"; import { languages } from "$lib/languages"; -import { locale } from "svelte-i18n"; +import { locale, t } from "svelte-i18n"; import type mapboxgl from "mapbox-gl"; -import { type TrackPoint, type Coordinates, crossarcDistance } from "gpx"; +import { type TrackPoint, type Coordinates, crossarcDistance, distance } from "gpx"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); @@ -75,8 +74,14 @@ export function getClosestLinePoint(points: TrackPoint[], point: TrackPoint | Co for (let i = 0; i < points.length - 1; i++) { let dist = crossarcDistance(points[i], points[i + 1], point); if (dist < closestDist) { - closest = points[i]; closestDist = dist; + if (distance(points[i], point) <= distance(points[i + 1], point)) { + closest = points[i]; + details['before'] = true; + } else { + closest = points[i + 1]; + details['before'] = false; + } } } details['distance'] = closestDist;