mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-01 08:12:32 +00:00
fix freezed files bug
This commit is contained in:
@@ -412,10 +412,10 @@ export class TrackSegment extends GPXTreeLeaf {
|
|||||||
// Producers
|
// Producers
|
||||||
replace(segment: number, start: number, end: number, points: TrackPoint[]) {
|
replace(segment: number, start: number, end: number, points: TrackPoint[]) {
|
||||||
return produce(this, (draft) => {
|
return produce(this, (draft) => {
|
||||||
let og = getOriginal(draft);
|
let og = getOriginal(draft); // Read as much as possible from the original object because it is faster
|
||||||
let trkpt = og.trkpt.slice();
|
let trkpt = og.trkpt.slice();
|
||||||
trkpt.splice(start, end - start + 1, ...points);
|
trkpt.splice(start, end - start + 1, ...points);
|
||||||
draft.trkpt = freeze(trkpt);
|
draft.trkpt = freeze(trkpt); // Pre-freeze the array, faster as well
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -432,17 +432,18 @@ export class RoutingControls {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = anchors[0].point._data.index + 1;
|
|
||||||
let end = anchors[anchors.length - 1].point._data.index - 1;
|
|
||||||
|
|
||||||
if (anchors[0].point._data.index === 0) { // First anchor is the first point of the segment
|
if (anchors[0].point._data.index === 0) { // First anchor is the first point of the segment
|
||||||
anchors[0].point = response[0]; // Update the first anchor in case it was not on a road
|
anchors[0].point = response[0]; // Update the first anchor
|
||||||
start--; // Remove the original first point
|
anchors[0].point._data.index = 0;
|
||||||
|
} else {
|
||||||
|
response.splice(0, 0, anchors[0].point); // Keep the original start point
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anchors[anchors.length - 1].point._data.index === segment.trkpt.length - 1) { // Last anchor is the last point of the segment
|
if (anchors[anchors.length - 1].point._data.index === segment.trkpt.length - 1) { // Last anchor is the last point of the segment
|
||||||
anchors[anchors.length - 1].point = response[response.length - 1]; // Update the last anchor in case it was not on a road
|
anchors[anchors.length - 1].point = response[response.length - 1]; // Update the last anchor
|
||||||
end++; // Remove the original last point
|
anchors[anchors.length - 1].point._data.index = segment.trkpt.length - 1;
|
||||||
|
} else {
|
||||||
|
response.push(anchors[anchors.length - 1].point); // Keep the original end point
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 1; i < anchors.length - 1; i++) {
|
for (let i = 1; i < anchors.length - 1; i++) {
|
||||||
@@ -465,7 +466,7 @@ export class RoutingControls {
|
|||||||
anchor.point._data.zoom = 0; // Make these anchors permanent
|
anchor.point._data.zoom = 0; // Make these anchors permanent
|
||||||
});
|
});
|
||||||
|
|
||||||
dbUtils.applyToFile(this.fileId, (file) => file.replace(anchors[0].segmentIndex, start, end, response));
|
dbUtils.applyToFile(this.fileId, (file) => file.replace(anchors[0].segmentIndex, anchors[0].point._data.index, anchors[anchors.length - 1].point._data.index, response));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -26,7 +26,7 @@ export function computeAnchorPoints(segment: TrackSegment) {
|
|||||||
segment._data.anchors = true;
|
segment._data.anchors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ramerDouglasPeucker(points: TrackPoint[], epsilon: number = 50, start: number = 0, end: number = points.length - 1): SimplifiedTrackPoint[] {
|
export function ramerDouglasPeucker(points: readonly TrackPoint[], epsilon: number = 50, start: number = 0, end: number = points.length - 1): SimplifiedTrackPoint[] {
|
||||||
if (points.length == 0) {
|
if (points.length == 0) {
|
||||||
return [];
|
return [];
|
||||||
} else if (points.length == 1) {
|
} else if (points.length == 1) {
|
||||||
@@ -45,7 +45,7 @@ export function ramerDouglasPeucker(points: TrackPoint[], epsilon: number = 50,
|
|||||||
return simplified;
|
return simplified;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ramerDouglasPeuckerRecursive(points: TrackPoint[], epsilon: number, start: number, end: number, simplified: SimplifiedTrackPoint[]) {
|
function ramerDouglasPeuckerRecursive(points: readonly TrackPoint[], epsilon: number, start: number, end: number, simplified: SimplifiedTrackPoint[]) {
|
||||||
let largest = {
|
let largest = {
|
||||||
index: 0,
|
index: 0,
|
||||||
distance: 0
|
distance: 0
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import Dexie, { liveQuery } from 'dexie';
|
import Dexie, { liveQuery } from 'dexie';
|
||||||
import { GPXFile, GPXStatistics } from 'gpx';
|
import { GPXFile, GPXStatistics } from 'gpx';
|
||||||
import { enableMapSet, enablePatches, produceWithPatches, applyPatches, type Patch, type WritableDraft, castDraft } from 'immer';
|
import { enableMapSet, enablePatches, applyPatches, type Patch, type WritableDraft, castDraft, Immer } from 'immer';
|
||||||
import { writable, get, derived, type Readable, type Writable } from 'svelte/store';
|
import { writable, get, derived, type Readable, type Writable } from 'svelte/store';
|
||||||
import { fileOrder, initTargetMapBounds, selectedFiles, updateTargetMapBounds } from './stores';
|
import { fileOrder, initTargetMapBounds, selectedFiles, updateTargetMapBounds } from './stores';
|
||||||
import { mode } from 'mode-watcher';
|
import { mode } from 'mode-watcher';
|
||||||
@@ -9,6 +9,8 @@ import { defaultBasemap, defaultBasemapTree, defaultOverlayTree, defaultOverlays
|
|||||||
enableMapSet();
|
enableMapSet();
|
||||||
enablePatches();
|
enablePatches();
|
||||||
|
|
||||||
|
const noFreezeImmer = new Immer({ autoFreeze: false }); // Do not freeze files that are not concerned by an update, otherwise cannot assign anchors for them
|
||||||
|
|
||||||
class Database extends Dexie {
|
class Database extends Dexie {
|
||||||
|
|
||||||
fileids!: Dexie.Table<string, string>;
|
fileids!: Dexie.Table<string, string>;
|
||||||
@@ -210,7 +212,7 @@ export const canRedo: Readable<boolean> = derived([patchIndex, patchMinMaxIndex]
|
|||||||
|
|
||||||
// Helper function to apply a callback to the global file state
|
// Helper function to apply a callback to the global file state
|
||||||
function applyGlobal(callback: (files: Map<string, GPXFile>) => void) {
|
function applyGlobal(callback: (files: Map<string, GPXFile>) => void) {
|
||||||
const [newFileState, patch, inversePatch] = produceWithPatches(fileState, callback);
|
const [newFileState, patch, inversePatch] = noFreezeImmer.produceWithPatches(fileState, callback);
|
||||||
|
|
||||||
storePatches(patch, inversePatch);
|
storePatches(patch, inversePatch);
|
||||||
|
|
||||||
@@ -219,7 +221,7 @@ function applyGlobal(callback: (files: Map<string, GPXFile>) => void) {
|
|||||||
|
|
||||||
// Helper function to apply a callback to multiple files
|
// Helper function to apply a callback to multiple files
|
||||||
function applyToFiles(fileIds: string[], callback: (file: WritableDraft<GPXFile>) => GPXFile) {
|
function applyToFiles(fileIds: string[], callback: (file: WritableDraft<GPXFile>) => GPXFile) {
|
||||||
const [newFileState, patch, inversePatch] = produceWithPatches(fileState, (draft) => {
|
const [newFileState, patch, inversePatch] = noFreezeImmer.produceWithPatches(fileState, (draft) => {
|
||||||
fileIds.forEach((fileId) => {
|
fileIds.forEach((fileId) => {
|
||||||
let file = draft.get(fileId);
|
let file = draft.get(fileId);
|
||||||
if (file) {
|
if (file) {
|
||||||
|
Reference in New Issue
Block a user