mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-09-02 16:52:31 +00:00
create new file
This commit is contained in:
@@ -164,12 +164,19 @@ export class GPXFile extends GPXTreeNode<Track>{
|
|||||||
wpt: Waypoint[];
|
wpt: Waypoint[];
|
||||||
trk: Track[];
|
trk: Track[];
|
||||||
|
|
||||||
constructor(gpx: GPXFileType | GPXFile) {
|
constructor(gpx?: GPXFileType | GPXFile) {
|
||||||
super();
|
super();
|
||||||
this.attributes = cloneJSON(gpx.attributes);
|
if (gpx) {
|
||||||
this.metadata = cloneJSON(gpx.metadata);
|
this.attributes = cloneJSON(gpx.attributes);
|
||||||
this.wpt = gpx.wpt ? gpx.wpt.map((waypoint) => new Waypoint(waypoint)) : [];
|
this.metadata = cloneJSON(gpx.metadata);
|
||||||
this.trk = gpx.trk ? gpx.trk.map((track) => new Track(track)) : [];
|
this.wpt = gpx.wpt ? gpx.wpt.map((waypoint) => new Waypoint(waypoint)) : [];
|
||||||
|
this.trk = gpx.trk ? gpx.trk.map((track) => new Track(track)) : [];
|
||||||
|
} else {
|
||||||
|
this.attributes = {};
|
||||||
|
this.metadata = {};
|
||||||
|
this.wpt = [];
|
||||||
|
this.trk = [new Track()];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildren(): Track[] {
|
getChildren(): Track[] {
|
||||||
@@ -208,16 +215,20 @@ export class Track extends GPXTreeNode<TrackSegment> {
|
|||||||
trkseg: TrackSegment[];
|
trkseg: TrackSegment[];
|
||||||
extensions?: TrackExtensions;
|
extensions?: TrackExtensions;
|
||||||
|
|
||||||
constructor(track: TrackType | Track) {
|
constructor(track?: TrackType | Track) {
|
||||||
super();
|
super();
|
||||||
this.name = track.name;
|
if (track) {
|
||||||
this.cmt = track.cmt;
|
this.name = track.name;
|
||||||
this.desc = track.desc;
|
this.cmt = track.cmt;
|
||||||
this.src = track.src;
|
this.desc = track.desc;
|
||||||
this.link = cloneJSON(track.link);
|
this.src = track.src;
|
||||||
this.type = track.type;
|
this.link = cloneJSON(track.link);
|
||||||
this.trkseg = track.trkseg ? track.trkseg.map((seg) => new TrackSegment(seg)) : [];
|
this.type = track.type;
|
||||||
this.extensions = cloneJSON(track.extensions);
|
this.trkseg = track.trkseg ? track.trkseg.map((seg) => new TrackSegment(seg)) : [];
|
||||||
|
this.extensions = cloneJSON(track.extensions);
|
||||||
|
} else {
|
||||||
|
this.trkseg = [new TrackSegment()];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildren(): TrackSegment[] {
|
getChildren(): TrackSegment[] {
|
||||||
@@ -266,9 +277,14 @@ export class TrackSegment extends GPXTreeLeaf {
|
|||||||
trkptStatistics: TrackPointStatistics;
|
trkptStatistics: TrackPointStatistics;
|
||||||
statistics: GPXStatistics;
|
statistics: GPXStatistics;
|
||||||
|
|
||||||
constructor(segment: TrackSegmentType | TrackSegment) {
|
constructor(segment?: TrackSegmentType | TrackSegment) {
|
||||||
super();
|
super();
|
||||||
this.trkpt = segment.trkpt.map((point) => new TrackPoint(point));
|
if (segment) {
|
||||||
|
this.trkpt = segment.trkpt.map((point) => new TrackPoint(point));
|
||||||
|
} else {
|
||||||
|
this.trkpt = [];
|
||||||
|
}
|
||||||
|
|
||||||
this._computeStatistics();
|
this._computeStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ export type GPXFileType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type GPXFileAttributes = {
|
export type GPXFileAttributes = {
|
||||||
creator: string;
|
creator?: string;
|
||||||
[key: string]: string;
|
[key: string]: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -14,7 +14,8 @@
|
|||||||
removeSelectedFiles,
|
removeSelectedFiles,
|
||||||
triggerFileInput,
|
triggerFileInput,
|
||||||
selectFiles,
|
selectFiles,
|
||||||
settings
|
settings,
|
||||||
|
createFile
|
||||||
} from '$lib/stores';
|
} from '$lib/stores';
|
||||||
|
|
||||||
import { mode, resetMode, setMode } from 'mode-watcher';
|
import { mode, resetMode, setMode } from 'mode-watcher';
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
<Menubar.Menu>
|
<Menubar.Menu>
|
||||||
<Menubar.Trigger>{$_('menu.file')}</Menubar.Trigger>
|
<Menubar.Trigger>{$_('menu.file')}</Menubar.Trigger>
|
||||||
<Menubar.Content class="border-none">
|
<Menubar.Content class="border-none">
|
||||||
<Menubar.Item>
|
<Menubar.Item on:click={createFile}>
|
||||||
<Plus size="16" class="mr-1" />
|
<Plus size="16" class="mr-1" />
|
||||||
{$_('menu.new')}
|
{$_('menu.new')}
|
||||||
<Menubar.Shortcut>⌘N</Menubar.Shortcut>
|
<Menubar.Shortcut>⌘N</Menubar.Shortcut>
|
||||||
@@ -183,7 +184,10 @@
|
|||||||
<svelte:window
|
<svelte:window
|
||||||
on:keydown={(e) => {
|
on:keydown={(e) => {
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
if (e.key === 'o' && (e.metaKey || e.ctrlKey)) {
|
if (e.key === 'n' && (e.metaKey || e.ctrlKey)) {
|
||||||
|
createFile();
|
||||||
|
e.preventDefault();
|
||||||
|
} else if (e.key === 'o' && (e.metaKey || e.ctrlKey)) {
|
||||||
triggerFileInput();
|
triggerFileInput();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
} else if (e.key === 'd' && (e.metaKey || e.ctrlKey)) {
|
} else if (e.key === 'd' && (e.metaKey || e.ctrlKey)) {
|
||||||
|
@@ -339,6 +339,13 @@ export class RoutingControls {
|
|||||||
this.createMarker(newAnchor);
|
this.createMarker(newAnchor);
|
||||||
segment._data.anchors.push(newAnchor);
|
segment._data.anchors.push(newAnchor);
|
||||||
|
|
||||||
|
if (!lastAnchor) {
|
||||||
|
applyToFileElement(this.file, segment, (segment) => {
|
||||||
|
segment.replace(0, 0, [newPoint]);
|
||||||
|
}, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let success = await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchor.point.getCoordinates(), newAnchor.point.getCoordinates()]);
|
let success = await this.routeBetweenAnchors([lastAnchor, newAnchor], [lastAnchor.point.getCoordinates(), newAnchor.point.getCoordinates()]);
|
||||||
|
|
||||||
if (!success) { // Route failed, remove the anchor
|
if (!success) { // Route failed, remove the anchor
|
||||||
|
@@ -25,6 +25,14 @@ export function computeAnchorPoints(segment: TrackSegment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ramerDouglasPeucker(points: TrackPoint[], epsilon: number = 50, start: number = 0, end: number = points.length - 1): SimplifiedTrackPoint[] {
|
export function ramerDouglasPeucker(points: TrackPoint[], epsilon: number = 50, start: number = 0, end: number = points.length - 1): SimplifiedTrackPoint[] {
|
||||||
|
if (points.length == 0) {
|
||||||
|
return [];
|
||||||
|
} else if (points.length == 1) {
|
||||||
|
return [{
|
||||||
|
point: points[0]
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
let simplified = [{
|
let simplified = [{
|
||||||
point: points[start]
|
point: points[start]
|
||||||
}];
|
}];
|
||||||
|
@@ -2,6 +2,8 @@ import { writable, get, type Writable } from 'svelte/store';
|
|||||||
|
|
||||||
import mapboxgl from 'mapbox-gl';
|
import mapboxgl from 'mapbox-gl';
|
||||||
import { GPXFile, buildGPX, parseGPX, type AnyGPXTreeElement } from 'gpx';
|
import { GPXFile, buildGPX, parseGPX, type AnyGPXTreeElement } from 'gpx';
|
||||||
|
import { tick } from 'svelte';
|
||||||
|
import { _ } from 'svelte-i18n';
|
||||||
|
|
||||||
export const map = writable<mapboxgl.Map | null>(null);
|
export const map = writable<mapboxgl.Map | null>(null);
|
||||||
export const files = writable<Writable<GPXFile>[]>([]);
|
export const files = writable<Writable<GPXFile>[]>([]);
|
||||||
@@ -72,6 +74,15 @@ export function addFile(file: GPXFile): Writable<GPXFile> {
|
|||||||
return fileStore;
|
return fileStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createFile(): Writable<GPXFile> {
|
||||||
|
let file = new GPXFile();
|
||||||
|
file.metadata.name = get(_)("menu.new_filename");
|
||||||
|
let fileStore = addFile(file);
|
||||||
|
tick().then(() => get(selectFiles).select(file));
|
||||||
|
currentTool.set(Tool.ROUTING);
|
||||||
|
return fileStore;
|
||||||
|
}
|
||||||
|
|
||||||
export function triggerFileInput() {
|
export function triggerFileInput() {
|
||||||
const input = document.createElement('input');
|
const input = document.createElement('input');
|
||||||
input.type = 'file';
|
input.type = 'file';
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
"menu": {
|
"menu": {
|
||||||
"file": "File",
|
"file": "File",
|
||||||
"new": "New",
|
"new": "New",
|
||||||
|
"new_filename": "new",
|
||||||
"load_desktop": "Load from desktop...",
|
"load_desktop": "Load from desktop...",
|
||||||
"load_drive": "Load from Google Drive...",
|
"load_drive": "Load from Google Drive...",
|
||||||
"duplicate": "Duplicate",
|
"duplicate": "Duplicate",
|
||||||
|
Reference in New Issue
Block a user