mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-08-30 23:30:04 +00:00
option to remove time gaps when merging
This commit is contained in:
@@ -890,7 +890,7 @@ export class TrackSegment extends GPXTreeLeaf {
|
||||
}
|
||||
|
||||
// Producers
|
||||
replaceTrackPoints(start: number, end: number, points: TrackPoint[], speed?: number, startTime?: Date) {
|
||||
replaceTrackPoints(start: number, end: number, points: TrackPoint[], speed?: number, startTime?: Date, removeGaps?: boolean) {
|
||||
let og = getOriginal(this); // Read as much as possible from the original object because it is faster
|
||||
let trkpt = og.trkpt.slice();
|
||||
|
||||
@@ -909,6 +909,21 @@ export class TrackSegment extends GPXTreeLeaf {
|
||||
} else if (last !== undefined && points[0].time < last.time) {
|
||||
// Adapt timestamps of the new points because they are too early
|
||||
points = withShiftedAndCompressedTimestamps(points, speed, 1, last);
|
||||
} else if (last !== undefined && removeGaps) {
|
||||
// Remove gaps between the new points and the previous point
|
||||
if (last.getLatitude() === points[0].getLatitude() && last.getLongitude() === points[0].getLongitude()) {
|
||||
// Same point, make the new points start at its timestamp and remove the first point
|
||||
if (points[0].time > last.time) {
|
||||
points = withShiftedAndCompressedTimestamps(points, speed, 1, last).slice(1);
|
||||
}
|
||||
} else {
|
||||
// Different points, make the new points start one second after the previous point
|
||||
if (points[0].time.getTime() - last.time.getTime() > 1000) {
|
||||
let artificialLast = points[0].clone();
|
||||
artificialLast.time = new Date(last.time.getTime() + 1000);
|
||||
points = withShiftedAndCompressedTimestamps(points, speed, 1, artificialLast);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (end < trkpt.length - 1) {
|
||||
|
@@ -11,15 +11,18 @@
|
||||
import { selection } from '$lib/components/file-list/Selection';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import { Label } from '$lib/components/ui/label/index.js';
|
||||
import { Checkbox } from '$lib/components/ui/checkbox';
|
||||
import * as RadioGroup from '$lib/components/ui/radio-group';
|
||||
import { _, locale } from 'svelte-i18n';
|
||||
import { dbUtils, getFile } from '$lib/db';
|
||||
import { Group } from 'lucide-svelte';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import Shortcut from '$lib/components/Shortcut.svelte';
|
||||
import { gpxStatistics } from '$lib/stores';
|
||||
|
||||
let canMergeTraces = false;
|
||||
let canMergeContents = false;
|
||||
let removeGaps = false;
|
||||
|
||||
$: if ($selection.size > 1) {
|
||||
canMergeTraces = true;
|
||||
@@ -56,22 +59,31 @@
|
||||
|
||||
<div class="flex flex-col gap-3 w-full max-w-80 {$$props.class ?? ''}">
|
||||
<RadioGroup.Root bind:value={mergeType}>
|
||||
<Label class="flex flex-row items-center gap-2 leading-5">
|
||||
<Label class="flex flex-row items-center gap-1.5 leading-5">
|
||||
<RadioGroup.Item value={MergeType.TRACES} />
|
||||
{$_('toolbar.merge.merge_traces')}
|
||||
</Label>
|
||||
<Label class="flex flex-row items-center gap-2 leading-5">
|
||||
<Label class="flex flex-row items-center gap-1.5 leading-5">
|
||||
<RadioGroup.Item value={MergeType.CONTENTS} />
|
||||
{$_('toolbar.merge.merge_contents')}
|
||||
</Label>
|
||||
</RadioGroup.Root>
|
||||
{#if mergeType === MergeType.TRACES && $gpxStatistics.global.time.total > 0}
|
||||
<div class="flex flex-row items-center gap-1.5">
|
||||
<Checkbox id="remove-gaps" bind:checked={removeGaps} />
|
||||
<Label for="remove-gaps">{$_('toolbar.merge.remove_gaps')}</Label>
|
||||
</div>
|
||||
{/if}
|
||||
<Button
|
||||
variant="outline"
|
||||
class="whitespace-normal h-fit"
|
||||
disabled={(mergeType === MergeType.TRACES && !canMergeTraces) ||
|
||||
(mergeType === MergeType.CONTENTS && !canMergeContents)}
|
||||
on:click={() => {
|
||||
dbUtils.mergeSelection(mergeType === MergeType.TRACES);
|
||||
dbUtils.mergeSelection(
|
||||
mergeType === MergeType.TRACES,
|
||||
mergeType === MergeType.TRACES && $gpxStatistics.global.time.total > 0 && removeGaps
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Group size="16" class="mr-1 shrink-0" />
|
||||
|
@@ -574,7 +574,7 @@ export const dbUtils = {
|
||||
});
|
||||
});
|
||||
},
|
||||
mergeSelection: (mergeTraces: boolean) => {
|
||||
mergeSelection: (mergeTraces: boolean, removeGaps: boolean) => {
|
||||
applyGlobal((draft) => {
|
||||
let first = true;
|
||||
let target: ListItem = new ListRootItem();
|
||||
@@ -649,7 +649,7 @@ export const dbUtils = {
|
||||
let s = new TrackSegment();
|
||||
toMerge.trk.map((track) => {
|
||||
track.trkseg.forEach((segment) => {
|
||||
s.replaceTrackPoints(s.trkpt.length, s.trkpt.length, segment.trkpt.slice(), speed, startTime);
|
||||
s.replaceTrackPoints(s.trkpt.length, s.trkpt.length, segment.trkpt.slice(), speed, startTime, removeGaps);
|
||||
});
|
||||
});
|
||||
toMerge.trk = [toMerge.trk[0]];
|
||||
@@ -658,7 +658,7 @@ export const dbUtils = {
|
||||
if (toMerge.trkseg.length > 0) {
|
||||
let s = new TrackSegment();
|
||||
toMerge.trkseg.forEach((segment) => {
|
||||
s.replaceTrackPoints(s.trkpt.length, s.trkpt.length, segment.trkpt.slice(), speed, startTime);
|
||||
s.replaceTrackPoints(s.trkpt.length, s.trkpt.length, segment.trkpt.slice(), speed, startTime, removeGaps);
|
||||
});
|
||||
toMerge.trkseg = [s];
|
||||
}
|
||||
|
@@ -173,6 +173,7 @@
|
||||
"merge_traces": "Connect the traces",
|
||||
"merge_contents": "Merge the contents and keep the traces disconnected",
|
||||
"merge_selection": "Merge selection",
|
||||
"remove_gaps": "Remove time gaps between traces",
|
||||
"tooltip": "Merge items together",
|
||||
"help_merge_traces": "Connecting the selected traces will create a single continuous trace.",
|
||||
"help_cannot_merge_traces": "Your selection must contain several traces to connect them.",
|
||||
|
Reference in New Issue
Block a user