gps-plus-slam-app-framework 1.0.0 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{app-selectors-DyMzxCEC.d.ts → app-selectors-CHt7DLuq.d.ts} +9 -8
- package/dist/ar/depth-sampler.js +1 -1
- package/dist/ar/tracking-state.js +1 -1
- package/dist/ar/webxr-session.js +1 -1
- package/dist/combined-root-state-B3SvPNjU.d.ts +6 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/create-slam-app-store-DBm7g2Zd.d.ts +85 -0
- package/dist/file-system-DD5TczSO.d.ts +84 -0
- package/dist/geo/h3-proximity.d.ts +2 -0
- package/dist/{ref-points/h3-ref-point.js → geo/h3-proximity.js} +16 -12
- package/dist/geo/index.d.ts +2 -0
- package/dist/geo/index.js +2 -0
- package/dist/gps-anchored-mesh-manager-CovAFK4g.d.ts +56 -0
- package/dist/gps-ar-pose-sampler-D_Zso40V.d.ts +43 -0
- package/dist/{recording-coordinator-DzflP07_.d.ts → gps-event-coordinator-fwvmVfku.d.ts} +6 -5
- package/dist/{h3-ref-point-CFhayNSZ.d.ts → h3-proximity-GwesPTFT.d.ts} +16 -12
- package/dist/index.d.ts +31 -34
- package/dist/index.js +14 -19
- package/dist/{leaflet-map-overlay-CvfQXTye.d.ts → leaflet-map-overlay-CQZcnxbc.d.ts} +10 -6
- package/dist/licensing/index.d.ts +1 -1
- package/dist/licensing/index.js +1 -1
- package/dist/{null-storage-backend-CsWvQwN8.d.ts → null-storage-backend-C0TiwwzQ.d.ts} +4 -2
- package/dist/{opfs-storage-ChOzF_Wp.d.ts → opfs-storage-Dlq1I_Gb.d.ts} +54 -51
- package/dist/opfs-storage-backend-Gt3rd76D.d.ts +13 -0
- package/dist/{persistence-middleware-DrptY02i.d.ts → persistence-middleware-z-75iisb.d.ts} +4 -4
- package/dist/{recording-replayer-oOzPITrd.d.ts → recording-replayer-BFhFs7Mc.d.ts} +2 -2
- package/dist/recording-slice-BiktUIWF.d.ts +28 -0
- package/dist/{replay-engine-DuX316ae.d.ts → replay-engine-B88Va62x.d.ts} +4 -1
- package/dist/sensors/gps-error-handler.d.ts +1 -1
- package/dist/sensors/gps.d.ts +1 -1
- package/dist/sensors/index.d.ts +3 -3
- package/dist/sensors/index.js +1 -1
- package/dist/sensors/permission-checker.d.ts +1 -1
- package/dist/state/app-selectors.d.ts +1 -1
- package/dist/state/create-slam-app-store.d.ts +2 -0
- package/dist/state/create-slam-app-store.js +61 -0
- package/dist/state/gps-ar-pose-sampler.d.ts +4 -0
- package/dist/state/gps-ar-pose-sampler.js +19 -0
- package/dist/state/{recording-coordinator.d.ts → gps-event-coordinator.d.ts} +1 -1
- package/dist/state/{recording-coordinator.js → gps-event-coordinator.js} +3 -4
- package/dist/state/index.d.ts +15 -16
- package/dist/state/index.js +7 -7
- package/dist/state/persistence-middleware.d.ts +1 -1
- package/dist/state/persistence-middleware.js +8 -8
- package/dist/state/recording-replayer.d.ts +3 -2
- package/dist/state/recording-replayer.js +2 -2
- package/dist/state/recording-slice.d.ts +2 -0
- package/dist/state/{recorder-slice.js → recording-slice.js} +7 -15
- package/dist/state/replay-engine.d.ts +1 -1
- package/dist/state/replay-engine.js +3 -3
- package/dist/state/store-subscribers.d.ts +2 -2
- package/dist/state/store-subscribers.js +1 -9
- package/dist/state/subscribe-to-selector.d.ts +1 -1
- package/dist/storage/file-system-utils.d.ts +1 -1
- package/dist/storage/file-system.d.ts +2 -2
- package/dist/storage/file-system.js +103 -94
- package/dist/storage/index.d.ts +9 -11
- package/dist/storage/index.js +5 -7
- package/dist/storage/null-storage-backend.d.ts +1 -1
- package/dist/storage/null-storage-backend.js +7 -0
- package/dist/storage/opfs-storage-backend.d.ts +1 -1
- package/dist/storage/opfs-storage-backend.js +7 -1
- package/dist/storage/opfs-storage.d.ts +2 -2
- package/dist/storage/opfs-storage.js +69 -85
- package/dist/storage/storage-backend.d.ts +2 -2
- package/dist/storage/zip-export.d.ts +2 -2
- package/dist/storage/zip-export.js +55 -62
- package/dist/storage/zip-reader.d.ts +2 -2
- package/dist/storage/zip-reader.js +24 -1
- package/dist/storage-backend-yVnuWGTr.d.ts +28 -0
- package/dist/{store-subscribers-CuoIzB5T.d.ts → store-subscribers-DKKHld49.d.ts} +1 -2
- package/dist/{subscribe-to-selector-UTZ0KkAc.d.ts → subscribe-to-selector-ghDKYtap.d.ts} +1 -1
- package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
- package/dist/test-utils/zip-round-trip-helpers.js +4 -4
- package/dist/visualization/gps-anchored-mesh-manager.d.ts +2 -0
- package/dist/visualization/gps-anchored-mesh-manager.js +128 -0
- package/dist/visualization/gps-compass-cubes.d.ts +1 -1
- package/dist/visualization/gps-event-markers.d.ts +1 -1
- package/dist/visualization/index.d.ts +9 -9
- package/dist/visualization/index.js +2 -2
- package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
- package/dist/visualization/leaflet-map-overlay.js +23 -19
- package/dist/visualization/lerp-utils.d.ts +1 -1
- package/dist/visualization/map-overlay.d.ts +1 -1
- package/dist/visualization/three-dispose.d.ts +1 -1
- package/dist/visualization/vis-colors.d.ts +1 -1
- package/dist/{zip-export-Rtpi75JJ.d.ts → zip-export-BjrQPv0X.d.ts} +58 -7
- package/dist/{zip-reader-D7pkpX8K.d.ts → zip-reader-KgJEXbca.d.ts} +33 -1
- package/package.json +15 -4
- package/dist/community-license-key-ChZLCJyO.d.ts +0 -21
- package/dist/file-system-BsQgYCU3.d.ts +0 -128
- package/dist/licensing/community-license-key.d.ts +0 -2
- package/dist/licensing/community-license-key.js +0 -21
- package/dist/opfs-storage-backend-CVcmfJHN.d.ts +0 -11
- package/dist/recorder-slice-fcwAXrsh.d.ts +0 -35
- package/dist/ref-point-importer-B_wn5ABk.d.ts +0 -62
- package/dist/ref-point-loader-Pt1smgHS.d.ts +0 -117
- package/dist/ref-points/h3-ref-point.d.ts +0 -2
- package/dist/ref-points/index.d.ts +0 -2
- package/dist/ref-points/index.js +0 -2
- package/dist/ref-points-slice-tC-Wd6XJ.d.ts +0 -48
- package/dist/reference-points-CFWy8_wj.d.ts +0 -68
- package/dist/routing-slice-BlHTM8eh.d.ts +0 -23
- package/dist/state/recorder-slice.d.ts +0 -2
- package/dist/state/ref-points-slice.d.ts +0 -2
- package/dist/state/ref-points-slice.js +0 -44
- package/dist/state/routing-slice.d.ts +0 -2
- package/dist/state/routing-slice.js +0 -13
- package/dist/state/store.d.ts +0 -9
- package/dist/state/store.js +0 -71
- package/dist/storage/ref-point-importer.d.ts +0 -2
- package/dist/storage/ref-point-importer.js +0 -163
- package/dist/storage/ref-point-loader.d.ts +0 -2
- package/dist/storage/ref-point-loader.js +0 -248
- package/dist/storage/ref-point-recovery.d.ts +0 -28
- package/dist/storage/ref-point-recovery.js +0 -159
- package/dist/storage-backend-BcEItnFr.d.ts +0 -20
- package/dist/store-C7PKOj8S.d.ts +0 -96
- package/dist/visualization/reference-points.d.ts +0 -2
- package/dist/visualization/reference-points.js +0 -160
- /package/dist/{file-system-utils-5cWO8Xyv.d.ts → file-system-utils-BH8FdyIu.d.ts} +0 -0
- /package/dist/{gps-Ddzr2KlX.d.ts → gps-GKc6_Cly.d.ts} +0 -0
- /package/dist/{gps-compass-cubes-C-6JEnpR.d.ts → gps-compass-cubes-jRIJMOuh.d.ts} +0 -0
- /package/dist/{gps-error-handler-VPuNOuf8.d.ts → gps-error-handler-CH1S528z.d.ts} +0 -0
- /package/dist/{gps-event-markers-DpEy2qRd.d.ts → gps-event-markers-sVyO9utS.d.ts} +0 -0
- /package/dist/{lerp-utils-87NWjUOD.d.ts → lerp-utils-CZgQlrmu.d.ts} +0 -0
- /package/dist/{map-overlay-DuiZuCTx.d.ts → map-overlay-C9ifl_4-.d.ts} +0 -0
- /package/dist/{permission-checker-jO2ziCWC.d.ts → permission-checker-Cu3nbH1S.d.ts} +0 -0
- /package/dist/{three-dispose-CCBHjE_a.d.ts → three-dispose-qt_r5wR1.d.ts} +0 -0
- /package/dist/{vis-colors-Qi2vlRGt.d.ts → vis-colors-BKkdTIKb.d.ts} +0 -0
|
@@ -22,9 +22,16 @@ const log = createLogger("ZipExport");
|
|
|
22
22
|
/**
|
|
23
23
|
* Get the OPFS scenarios directory handle.
|
|
24
24
|
* Re-acquires from navigator.storage to avoid holding stale references.
|
|
25
|
+
* Creates on demand so it works even when initOpfsStorage only creates sessions/.
|
|
25
26
|
*/
|
|
26
27
|
async function getScenariosHandle() {
|
|
27
|
-
return (await (await navigator.storage.getDirectory()).getDirectoryHandle("gps-
|
|
28
|
+
return (await (await navigator.storage.getDirectory()).getDirectoryHandle("gps-plus-slam")).getDirectoryHandle("scenarios", { create: true });
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get the OPFS sessions directory handle (flat layout).
|
|
32
|
+
*/
|
|
33
|
+
async function getSessionsHandle() {
|
|
34
|
+
return (await (await navigator.storage.getDirectory()).getDirectoryHandle("gps-plus-slam")).getDirectoryHandle("sessions");
|
|
28
35
|
}
|
|
29
36
|
/**
|
|
30
37
|
* Stream all files from a directory recursively into a ZipWriter.
|
|
@@ -49,80 +56,66 @@ async function streamDirectoryToZip(dirHandle, zipWriter, basePath = "") {
|
|
|
49
56
|
return count;
|
|
50
57
|
}
|
|
51
58
|
/**
|
|
52
|
-
* Filter and stream per-session ref point observations into a ZipWriter.
|
|
53
|
-
*
|
|
54
|
-
* Reads each ref point JSON from the scenario-level refPoints/ directory,
|
|
55
|
-
* keeps only observations where `sessionId` matches `sessionName`, and writes
|
|
56
|
-
* the filtered definition into the ZIP under `refPoints/{h3}.json`.
|
|
57
|
-
*
|
|
58
|
-
* Ref points with no observations for the current session are skipped entirely.
|
|
59
|
-
* If the refPoints/ directory doesn't exist yet (new scenario), returns 0.
|
|
60
|
-
*
|
|
61
|
-
* @returns Number of ref point files added
|
|
62
|
-
*/
|
|
63
|
-
async function streamSessionRefPointsToZip(scenarioHandle, sessionName, zipWriter) {
|
|
64
|
-
let count = 0;
|
|
65
|
-
let refPointsHandle;
|
|
66
|
-
try {
|
|
67
|
-
refPointsHandle = await scenarioHandle.getDirectoryHandle("refPoints");
|
|
68
|
-
} catch {
|
|
69
|
-
return 0;
|
|
70
|
-
}
|
|
71
|
-
for await (const [name, handle] of refPointsHandle.entries()) {
|
|
72
|
-
if (handle.kind !== "file" || !name.endsWith(".json")) continue;
|
|
73
|
-
try {
|
|
74
|
-
const text = await (await handle.getFile()).text();
|
|
75
|
-
const def = JSON.parse(text);
|
|
76
|
-
if (!Array.isArray(def.observations)) continue;
|
|
77
|
-
const sessionObs = def.observations.filter((o) => o.sessionId === sessionName);
|
|
78
|
-
if (sessionObs.length === 0) continue;
|
|
79
|
-
const filtered = {
|
|
80
|
-
...def,
|
|
81
|
-
observations: sessionObs
|
|
82
|
-
};
|
|
83
|
-
const blob = new Blob([JSON.stringify(filtered, null, 2)], { type: "application/json" });
|
|
84
|
-
await zipWriter.add(`refPoints/${name}`, new BlobReader(blob));
|
|
85
|
-
count++;
|
|
86
|
-
} catch (err) {
|
|
87
|
-
log.warn(`Failed to process ref point ${name}:`, err);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return count;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
59
|
* Export a session from OPFS as a ZIP blob.
|
|
94
60
|
*
|
|
95
61
|
* The ZIP structure mirrors the OPFS session structure:
|
|
96
62
|
* - session.json (at root)
|
|
97
63
|
* - actions/000001.json, actions/000002.json, ...
|
|
98
64
|
* - frames/frame-000001.jpg, frames/frame-000002.jpg, ...
|
|
99
|
-
* - refPoints/{h3}.json (only observations from this session)
|
|
65
|
+
* - refPoints/{h3}.json (only observations from this session, scenario layout only)
|
|
100
66
|
*
|
|
101
67
|
* Uses "store" mode (compression level 0) for fast packaging.
|
|
102
68
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
69
|
+
* Supports both flat and scenario-based layouts:
|
|
70
|
+
* - `exportSessionAsZip(sessionName)` — flat layout (sessions/)
|
|
71
|
+
* - `exportSessionAsZip(scenarioName, sessionName)` — scenario layout (scenarios/{name}/)
|
|
72
|
+
*
|
|
105
73
|
* @returns ZIP export result with blob and file count
|
|
106
|
-
* @throws Error if
|
|
74
|
+
* @throws Error if session not found
|
|
107
75
|
*/
|
|
108
|
-
async function exportSessionAsZip(
|
|
109
|
-
log.info(`Exporting session: ${scenarioName}/${sessionName}`);
|
|
110
|
-
const scenariosDir = await getScenariosHandle();
|
|
111
|
-
let scenarioHandle;
|
|
112
|
-
try {
|
|
113
|
-
scenarioHandle = await scenariosDir.getDirectoryHandle(scenarioName);
|
|
114
|
-
} catch {
|
|
115
|
-
throw new Error(`Scenario "${scenarioName}" not found in OPFS storage`);
|
|
116
|
-
}
|
|
76
|
+
async function exportSessionAsZip(scenarioNameOrSessionName, sessionName, options) {
|
|
117
77
|
let sessionHandle;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
78
|
+
if (sessionName) {
|
|
79
|
+
const scenarioName = scenarioNameOrSessionName;
|
|
80
|
+
log.info(`Exporting session: ${scenarioName}/${sessionName}`);
|
|
81
|
+
const scenariosDir = await getScenariosHandle();
|
|
82
|
+
let scenarioHandle;
|
|
83
|
+
try {
|
|
84
|
+
scenarioHandle = await scenariosDir.getDirectoryHandle(scenarioName);
|
|
85
|
+
} catch {
|
|
86
|
+
throw new Error(`Scenario "${scenarioName}" not found in OPFS storage`);
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
sessionHandle = await scenarioHandle.getDirectoryHandle(sessionName);
|
|
90
|
+
} catch {
|
|
91
|
+
throw new Error(`Session "${sessionName}" not found in scenario "${scenarioName}"`);
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
log.info(`Exporting session: ${scenarioNameOrSessionName}`);
|
|
95
|
+
const sessionsDir = await getSessionsHandle();
|
|
96
|
+
try {
|
|
97
|
+
sessionHandle = await sessionsDir.getDirectoryHandle(scenarioNameOrSessionName);
|
|
98
|
+
} catch {
|
|
99
|
+
throw new Error(`Session "${scenarioNameOrSessionName}" not found in OPFS storage`);
|
|
100
|
+
}
|
|
122
101
|
}
|
|
123
102
|
const zipWriter = new ZipWriter(new BlobWriter("application/zip"), { level: 0 });
|
|
124
103
|
let fileCount = await streamDirectoryToZip(sessionHandle, zipWriter);
|
|
125
|
-
|
|
104
|
+
const contributors = options?.contributors ?? [];
|
|
105
|
+
const seenSubdirs = /* @__PURE__ */ new Set();
|
|
106
|
+
for (const contributor of contributors) {
|
|
107
|
+
const subdir = contributor.subdir;
|
|
108
|
+
if (!subdir || subdir.includes("/") || subdir.startsWith(".")) throw new Error(`ZipExportContributor.subdir must be a non-empty single path segment, got: ${JSON.stringify(subdir)}`);
|
|
109
|
+
if (seenSubdirs.has(subdir)) throw new Error(`Duplicate ZipExportContributor.subdir registered: ${subdir}`);
|
|
110
|
+
seenSubdirs.add(subdir);
|
|
111
|
+
const addFile = async (relativePath, blob) => {
|
|
112
|
+
if (relativePath.startsWith("/")) throw new Error(`ZipExportContributor relative path must not start with '/' (got ${relativePath})`);
|
|
113
|
+
if (relativePath.includes("\\")) throw new Error(`ZipExportContributor relative path must not contain '\\' (got ${relativePath})`);
|
|
114
|
+
if (relativePath.split("/").some((s) => s === ".." || s === ".")) throw new Error(`ZipExportContributor relative path must not contain '.' or '..' segments (got ${relativePath})`);
|
|
115
|
+
await zipWriter.add(`${subdir}/${relativePath}`, new BlobReader(blob));
|
|
116
|
+
};
|
|
117
|
+
fileCount += await contributor.contribute(addFile);
|
|
118
|
+
}
|
|
126
119
|
const blob = await zipWriter.close();
|
|
127
120
|
log.info(`ZIP created: ${blob.size} bytes, ${fileCount} files`);
|
|
128
121
|
return {
|
|
@@ -148,9 +141,9 @@ async function exportSessionAsZip(scenarioName, sessionName) {
|
|
|
148
141
|
* @returns ZIP export result with blob and file count
|
|
149
142
|
* @throws Error if scenario or session not found
|
|
150
143
|
*/
|
|
151
|
-
async function syncToExternalZip(fileHandle, scenarioName, sessionName) {
|
|
144
|
+
async function syncToExternalZip(fileHandle, scenarioName, sessionName, options) {
|
|
152
145
|
log.info(`Syncing to external ZIP: ${scenarioName}/${sessionName}`);
|
|
153
|
-
const result = await exportSessionAsZip(scenarioName, sessionName);
|
|
146
|
+
const result = await exportSessionAsZip(scenarioName, sessionName, options);
|
|
154
147
|
const writable = await fileHandle.createWritable();
|
|
155
148
|
await writable.write(result.blob);
|
|
156
149
|
await writable.close();
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as ZipActionEntry, c as
|
|
2
|
-
export { Entry, GpsPathCoord, MAX_ACTION_FILE_SIZE, RecordedAction, ZipActionEntry, loadActionsFromZip, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
|
|
1
|
+
import { a as ZipActionEntry, c as loadEntriesFromSubdir, d as loadSessionMetadataFromBlob, f as readZipEntries, i as RecordedAction, l as loadGpsPathFromBlob, n as GpsPathCoord, o as ZipSubdirEntry, r as MAX_ACTION_FILE_SIZE, s as loadActionsFromZip, t as Entry, u as loadSessionMetadata } from "../zip-reader-KgJEXbca.js";
|
|
2
|
+
export { Entry, GpsPathCoord, MAX_ACTION_FILE_SIZE, RecordedAction, ZipActionEntry, ZipSubdirEntry, loadActionsFromZip, loadEntriesFromSubdir, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
|
|
@@ -186,5 +186,28 @@ async function loadGpsPathFromBlob(blob, maxFileSize = MAX_ACTION_FILE_SIZE) {
|
|
|
186
186
|
} catch {}
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Enumerate every file under a single top-level subdirectory of a recording
|
|
191
|
+
* zip. Mirrors the writer-side {@link ZipExportContributor} seam so consumers
|
|
192
|
+
* (typically the recorder) can read back what they wrote without
|
|
193
|
+
* re-implementing zip enumeration.
|
|
194
|
+
*
|
|
195
|
+
* Skips directory entries and files outside `subdir`. Sorts entries by
|
|
196
|
+
* `relativePath` for deterministic iteration. Returns an empty array when
|
|
197
|
+
* the subdir is absent (graceful degradation for older zips).
|
|
198
|
+
*
|
|
199
|
+
* @param data - The zip file content as a Uint8Array
|
|
200
|
+
* @param subdir - Top-level subdir to scan (no leading or trailing `/`)
|
|
201
|
+
*/
|
|
202
|
+
async function loadEntriesFromSubdir(data, subdir) {
|
|
203
|
+
if (!subdir || subdir.includes("/") || subdir.startsWith(".")) throw new Error(`subdir must be a non-empty single path segment, got: ${JSON.stringify(subdir)}`);
|
|
204
|
+
const prefix = `${subdir}/`;
|
|
205
|
+
return (await readZipEntries(data)).filter((e) => !e.directory && e.filename.startsWith(prefix) && e.filename !== prefix).sort((a, b) => a.filename.localeCompare(b.filename)).map((entry) => ({
|
|
206
|
+
relativePath: entry.filename.slice(prefix.length),
|
|
207
|
+
fullPath: entry.filename,
|
|
208
|
+
uncompressedSize: entry.uncompressedSize,
|
|
209
|
+
getText: () => entry.getData(new TextWriter())
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
189
212
|
//#endregion
|
|
190
|
-
export { MAX_ACTION_FILE_SIZE, loadActionsFromZip, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
|
|
213
|
+
export { MAX_ACTION_FILE_SIZE, loadActionsFromZip, loadEntriesFromSubdir, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { n as SessionMetadata } from "./opfs-storage-Dlq1I_Gb.js";
|
|
2
|
+
|
|
3
|
+
//#region ../src/storage/storage-backend.d.ts
|
|
4
|
+
interface CreateSessionResult {
|
|
5
|
+
sessionName: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Contract for session lifecycle and recording persistence.
|
|
9
|
+
*
|
|
10
|
+
* Implementations:
|
|
11
|
+
* - OpfsStorageBackend: production — flat sessions under OPFS
|
|
12
|
+
* - NullStorageBackend: tests/replay — silent no-ops
|
|
13
|
+
* - ScenarioWrappingStorageBackend (recorder): layers scenario hierarchy on top
|
|
14
|
+
*/
|
|
15
|
+
interface StorageBackend {
|
|
16
|
+
/** Create a new recording session. Returns the session name for reference. */
|
|
17
|
+
createSession(timestamp: Date, contextTag?: string): Promise<CreateSessionResult>;
|
|
18
|
+
/** List all session names managed by this backend. */
|
|
19
|
+
listSessions(): Promise<string[]>;
|
|
20
|
+
/** Persist a Redux action as a numbered JSON file. */
|
|
21
|
+
writeAction(action: unknown, index: number): Promise<void>;
|
|
22
|
+
/** Persist a captured camera frame as a numbered JPEG. */
|
|
23
|
+
writeFrame(blob: Blob, index: number): Promise<void>;
|
|
24
|
+
/** Persist session metadata (session.json). */
|
|
25
|
+
writeSessionMetadata(metadata: SessionMetadata): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { StorageBackend as n, CreateSessionResult as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as SubscribableStore } from "./subscribe-to-selector-
|
|
1
|
+
import { t as SubscribableStore } from "./subscribe-to-selector-ghDKYtap.js";
|
|
2
2
|
import { LatLong, Matrix4, Quaternion, Vector3 } from "gps-plus-slam-js";
|
|
3
3
|
|
|
4
4
|
//#region ../src/state/store-subscribers.d.ts
|
|
@@ -22,7 +22,6 @@ interface StoreSubscriberDeps {
|
|
|
22
22
|
addRawGpsPoint?: (lat: number, lon: number) => void;
|
|
23
23
|
addFusedPoint?: (lat: number, lon: number) => void;
|
|
24
24
|
addAlignmentSnapshot?: (lat: number, lon: number) => void;
|
|
25
|
-
addRefPoint?: (lat: number, lon: number, name: string) => void;
|
|
26
25
|
} | null;
|
|
27
26
|
/**
|
|
28
27
|
* Optional callback invoked with the GPS world-space coordinates of each
|
|
@@ -65,7 +65,7 @@ async function produceTestZip(opts) {
|
|
|
65
65
|
const { cleanup } = installOPFSMocks();
|
|
66
66
|
try {
|
|
67
67
|
await initOpfsStorage();
|
|
68
|
-
const {
|
|
68
|
+
const { sessionName } = await createSession(options.sessionTimestamp, options.scenarioName);
|
|
69
69
|
const allActions = [];
|
|
70
70
|
let actionIndex = 0;
|
|
71
71
|
/** Increment index, persist to OPFS, and record for later assertions. */
|
|
@@ -75,7 +75,7 @@ async function produceTestZip(opts) {
|
|
|
75
75
|
allActions.push(action);
|
|
76
76
|
};
|
|
77
77
|
await writeAndRecordAction({
|
|
78
|
-
type: "
|
|
78
|
+
type: "recording/startSession",
|
|
79
79
|
payload: {
|
|
80
80
|
scenarioName: options.scenarioName,
|
|
81
81
|
sessionName,
|
|
@@ -174,12 +174,12 @@ async function produceTestZip(opts) {
|
|
|
174
174
|
version: 1,
|
|
175
175
|
startedAt: options.sessionTimestamp.toISOString(),
|
|
176
176
|
endedAt: new Date(options.sessionTimestamp.getTime() + actionIndex * 1e3 + 5e3).toISOString(),
|
|
177
|
-
|
|
177
|
+
contextTag: options.scenarioName,
|
|
178
178
|
actionCount: actionIndex,
|
|
179
179
|
frameCount: options.frameCount,
|
|
180
180
|
userAgent: options.deviceInfo
|
|
181
181
|
});
|
|
182
|
-
const { blob } = await exportSessionAsZip(
|
|
182
|
+
const { blob } = await exportSessionAsZip(sessionName);
|
|
183
183
|
return {
|
|
184
184
|
zipData: new Uint8Array(await blob.arrayBuffer()),
|
|
185
185
|
totalActionCount: actionIndex,
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { createLogger } from "../utils/logger.js";
|
|
2
|
+
import { disposeMeshArray } from "./three-dispose.js";
|
|
3
|
+
import { getScene } from "../ar/webxr-session.js";
|
|
4
|
+
import * as THREE from "three";
|
|
5
|
+
import { calcRelativeCoordsInMeters } from "gps-plus-slam-js";
|
|
6
|
+
//#region ../src/visualization/gps-anchored-mesh-manager.ts
|
|
7
|
+
/**
|
|
8
|
+
* GPS-Anchored Mesh Manager
|
|
9
|
+
*
|
|
10
|
+
* Generic mechanism for placing Three.js meshes at GPS coordinates relative
|
|
11
|
+
* to a configured GPS zero reference. This is the recorder-agnostic core
|
|
12
|
+
* that was extracted in Iter 4 from the recorder-flavoured
|
|
13
|
+
* `RefPointVisualizer` (which now lives in the RecorderApp and composes two
|
|
14
|
+
* instances of this manager — prior=green, current=red).
|
|
15
|
+
*
|
|
16
|
+
* The manager is intentionally narrow: it knows how to convert
|
|
17
|
+
* `{ lat, lon, altitude? }` into local meters via the framework's GPS zero
|
|
18
|
+
* reference, allocate a single shared geometry + material per instance, and
|
|
19
|
+
* keep the resulting mesh group in sync with caller-provided items. It does
|
|
20
|
+
* not know anything about ref points, sessions, or recorder semantics.
|
|
21
|
+
*/
|
|
22
|
+
const DEFAULT_RADIUS = .1;
|
|
23
|
+
/**
|
|
24
|
+
* Manages a single colored mesh group anchored to GPS coordinates.
|
|
25
|
+
* One instance == one color/group.
|
|
26
|
+
*/
|
|
27
|
+
var GpsAnchoredMeshManager = class {
|
|
28
|
+
color;
|
|
29
|
+
radius;
|
|
30
|
+
namePrefix;
|
|
31
|
+
log;
|
|
32
|
+
meshes = [];
|
|
33
|
+
zeroRef = null;
|
|
34
|
+
geometry = null;
|
|
35
|
+
material = null;
|
|
36
|
+
constructor(options) {
|
|
37
|
+
this.color = options.color;
|
|
38
|
+
this.radius = options.radius ?? DEFAULT_RADIUS;
|
|
39
|
+
this.namePrefix = options.namePrefix;
|
|
40
|
+
this.log = createLogger(options.loggerLabel ?? "GpsAnchoredMeshManager");
|
|
41
|
+
}
|
|
42
|
+
/** Set the GPS origin used to project items into local meters. */
|
|
43
|
+
setZeroRef(zero) {
|
|
44
|
+
this.zeroRef = zero;
|
|
45
|
+
}
|
|
46
|
+
getZeroRef() {
|
|
47
|
+
return this.zeroRef;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Replace the entire mesh group with one mesh per provided item.
|
|
51
|
+
* Items without GPS or before `setZeroRef` are skipped.
|
|
52
|
+
*/
|
|
53
|
+
setItems(items) {
|
|
54
|
+
if (!this.zeroRef) {
|
|
55
|
+
this.log.warn("No zero reference set");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const scene = getScene();
|
|
59
|
+
if (!scene) {
|
|
60
|
+
this.log.warn("Scene not available");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
this.clear();
|
|
64
|
+
const geometry = this.geometry ??= new THREE.SphereGeometry(this.radius, 16, 16);
|
|
65
|
+
const material = this.material ??= new THREE.MeshBasicMaterial({ color: this.color });
|
|
66
|
+
let visibleCount = 0;
|
|
67
|
+
for (const item of items) {
|
|
68
|
+
const coords = calcRelativeCoordsInMeters(this.zeroRef, {
|
|
69
|
+
lat: item.lat,
|
|
70
|
+
lon: item.lon
|
|
71
|
+
}, item.altitude ?? 0, 0);
|
|
72
|
+
const mesh = new THREE.Mesh(geometry, material);
|
|
73
|
+
mesh.position.set(coords[0], coords[1], coords[2]);
|
|
74
|
+
mesh.name = `${this.namePrefix}-${item.id}`;
|
|
75
|
+
scene.add(mesh);
|
|
76
|
+
this.meshes.push(mesh);
|
|
77
|
+
visibleCount++;
|
|
78
|
+
}
|
|
79
|
+
this.log.info(`Displayed ${visibleCount}/${items.length} anchored meshes`);
|
|
80
|
+
}
|
|
81
|
+
/** Append a single item to the existing mesh group. */
|
|
82
|
+
addItem(item) {
|
|
83
|
+
if (!this.zeroRef) {
|
|
84
|
+
this.log.warn("Cannot add item — no zero reference");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const scene = getScene();
|
|
88
|
+
if (!scene) {
|
|
89
|
+
this.log.warn("Scene not available");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const geometry = this.geometry ??= new THREE.SphereGeometry(this.radius, 16, 16);
|
|
93
|
+
const material = this.material ??= new THREE.MeshBasicMaterial({ color: this.color });
|
|
94
|
+
const coords = calcRelativeCoordsInMeters(this.zeroRef, {
|
|
95
|
+
lat: item.lat,
|
|
96
|
+
lon: item.lon
|
|
97
|
+
}, item.altitude ?? 0, 0);
|
|
98
|
+
const mesh = new THREE.Mesh(geometry, material);
|
|
99
|
+
mesh.position.set(coords[0], coords[1], coords[2]);
|
|
100
|
+
mesh.name = `${this.namePrefix}-${item.id}`;
|
|
101
|
+
scene.add(mesh);
|
|
102
|
+
this.meshes.push(mesh);
|
|
103
|
+
this.log.info(`Added anchored mesh: ${item.id}`);
|
|
104
|
+
}
|
|
105
|
+
/** Remove all meshes and dispose the shared geometry/material. */
|
|
106
|
+
clear() {
|
|
107
|
+
const scene = getScene();
|
|
108
|
+
disposeMeshArray(this.meshes, scene, {
|
|
109
|
+
skipGeometry: true,
|
|
110
|
+
skipMaterial: true
|
|
111
|
+
});
|
|
112
|
+
this.geometry?.dispose();
|
|
113
|
+
this.geometry = null;
|
|
114
|
+
this.material?.dispose();
|
|
115
|
+
this.material = null;
|
|
116
|
+
}
|
|
117
|
+
/** Number of meshes currently rendered. */
|
|
118
|
+
getCount() {
|
|
119
|
+
return this.meshes.length;
|
|
120
|
+
}
|
|
121
|
+
/** Convenience: clear and forget the zero reference. */
|
|
122
|
+
dispose() {
|
|
123
|
+
this.clear();
|
|
124
|
+
this.zeroRef = null;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
//#endregion
|
|
128
|
+
export { GpsAnchoredMeshManager };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-
|
|
1
|
+
import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-jRIJMOuh.js";
|
|
2
2
|
export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, GpsCompassCubes, createGpsCompassCubes };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-
|
|
1
|
+
import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-sVyO9utS.js";
|
|
2
2
|
export { GpsEventVisualizer, gpsEventVisualizer };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as createCameraFollower, t as CameraFollower } from "../camera-follower-BMqPddxx.js";
|
|
2
2
|
import { n as createAlignmentLerper, t as AlignmentLerper } from "../alignment-lerper-D9BeDwZX.js";
|
|
3
3
|
import { n as createCss3dRendererManager, t as Css3dRendererManager } from "../css3d-renderer-manager-rgLMVAvd.js";
|
|
4
|
-
import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-
|
|
5
|
-
import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-
|
|
6
|
-
import { a as DEFAULT_Z_OFFSET, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions } from "../leaflet-map-overlay-
|
|
7
|
-
import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-
|
|
8
|
-
import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-
|
|
9
|
-
import { n as
|
|
10
|
-
import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-
|
|
11
|
-
import { t as VIS_COLORS } from "../vis-colors-
|
|
12
|
-
export { type AlignmentLerper, COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, type CameraFollower, type Css3dRendererManager, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, type DisposeOptions, type GpsCompassCubes, GpsEventVisualizer, LeafletMapOverlay, type LeafletMapOverlayOptions, MapOverlay, type MapOverlayOptions,
|
|
4
|
+
import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-jRIJMOuh.js";
|
|
5
|
+
import { n as gpsEventVisualizer, t as GpsEventVisualizer } from "../gps-event-markers-sVyO9utS.js";
|
|
6
|
+
import { a as DEFAULT_Z_OFFSET, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions } from "../leaflet-map-overlay-CQZcnxbc.js";
|
|
7
|
+
import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-CZgQlrmu.js";
|
|
8
|
+
import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-C9ifl_4-.js";
|
|
9
|
+
import { n as GpsAnchoredMeshManager, r as GpsAnchoredMeshManagerOptions, t as GpsAnchoredItem } from "../gps-anchored-mesh-manager-CovAFK4g.js";
|
|
10
|
+
import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-qt_r5wR1.js";
|
|
11
|
+
import { t as VIS_COLORS } from "../vis-colors-BKkdTIKb.js";
|
|
12
|
+
export { type AlignmentLerper, COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, type CameraFollower, type Css3dRendererManager, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, type DisposeOptions, type GpsAnchoredItem, GpsAnchoredMeshManager, type GpsAnchoredMeshManagerOptions, type GpsCompassCubes, GpsEventVisualizer, LeafletMapOverlay, type LeafletMapOverlayOptions, MapOverlay, type MapOverlayOptions, type TextureLoaderInterface, VIS_COLORS, clampedAlpha, createAlignmentLerper, createCameraFollower, createCss3dRendererManager, createGpsCompassCubes, disposeMeshArray, disposeObject3D, gpsEventVisualizer, latLonToTileXY, tileXYToLatLon };
|
|
@@ -8,5 +8,5 @@ import { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, createGpsCompassCubes } from
|
|
|
8
8
|
import { GpsEventVisualizer, gpsEventVisualizer } from "./gps-event-markers.js";
|
|
9
9
|
import { DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_WORLD_SIZE, DEFAULT_Z_OFFSET, LeafletMapOverlay } from "./leaflet-map-overlay.js";
|
|
10
10
|
import { DEFAULT_HEIGHT_OFFSET, DEFAULT_MAP_SIZE, DEFAULT_ZOOM, MapOverlay, latLonToTileXY, tileXYToLatLon } from "./map-overlay.js";
|
|
11
|
-
import {
|
|
12
|
-
export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, GpsEventVisualizer, LeafletMapOverlay, MapOverlay,
|
|
11
|
+
import { GpsAnchoredMeshManager } from "./gps-anchored-mesh-manager.js";
|
|
12
|
+
export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_LERP_RATE, DEFAULT_MAP_SIZE, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, GpsAnchoredMeshManager, GpsEventVisualizer, LeafletMapOverlay, MapOverlay, VIS_COLORS, clampedAlpha, createAlignmentLerper, createCameraFollower, createCss3dRendererManager, createGpsCompassCubes, disposeMeshArray, disposeObject3D, gpsEventVisualizer, latLonToTileXY, tileXYToLatLon };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as DEFAULT_Z_OFFSET, i as DEFAULT_ZOOM, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions, t as DEFAULT_HEIGHT_OFFSET } from "../leaflet-map-overlay-
|
|
1
|
+
import { a as DEFAULT_Z_OFFSET, i as DEFAULT_ZOOM, n as DEFAULT_LEAFLET_MAP_SIZE_PX, o as LeafletMapOverlay, r as DEFAULT_WORLD_SIZE, s as LeafletMapOverlayOptions, t as DEFAULT_HEIGHT_OFFSET } from "../leaflet-map-overlay-CQZcnxbc.js";
|
|
2
2
|
export { DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, LeafletMapOverlay, LeafletMapOverlayOptions };
|
|
@@ -38,7 +38,7 @@ var LeafletMapOverlay = class {
|
|
|
38
38
|
rawGpsPoints = [];
|
|
39
39
|
fusedPoints = [];
|
|
40
40
|
snapshotPoints = [];
|
|
41
|
-
|
|
41
|
+
namedMarkers = [];
|
|
42
42
|
userMarker = null;
|
|
43
43
|
rawGpsPolyline = null;
|
|
44
44
|
fusedPolyline = null;
|
|
@@ -126,9 +126,10 @@ var LeafletMapOverlay = class {
|
|
|
126
126
|
this.snapshotPolyline.addLatLng([lat, lon]);
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.
|
|
129
|
+
/** Add a "current" named marker (red). Buffered if map is not yet shown. */
|
|
130
|
+
addCurrentMarker(lat, lon, name) {
|
|
131
|
+
const marker = this.leafletMap ? this.createNamedMarker(lat, lon, name, false) : null;
|
|
132
|
+
this.namedMarkers.push({
|
|
132
133
|
lat,
|
|
133
134
|
lng: lon,
|
|
134
135
|
name,
|
|
@@ -136,9 +137,10 @@ var LeafletMapOverlay = class {
|
|
|
136
137
|
marker
|
|
137
138
|
});
|
|
138
139
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
this.
|
|
140
|
+
/** Add a "prior" named marker (green, decorated). Buffered if not shown. */
|
|
141
|
+
addPriorMarker(lat, lon, name) {
|
|
142
|
+
const marker = this.leafletMap ? this.createNamedMarker(lat, lon, name, true) : null;
|
|
143
|
+
this.namedMarkers.push({
|
|
142
144
|
lat,
|
|
143
145
|
lng: lon,
|
|
144
146
|
name,
|
|
@@ -146,13 +148,15 @@ var LeafletMapOverlay = class {
|
|
|
146
148
|
marker
|
|
147
149
|
});
|
|
148
150
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
/** Bulk add prior markers. */
|
|
152
|
+
addPriorMarkers(markers) {
|
|
153
|
+
for (const m of markers) this.addPriorMarker(m.lat, m.lon, m.name);
|
|
151
154
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
/** Remove all prior markers; current markers are unaffected. */
|
|
156
|
+
clearPriorMarkers() {
|
|
157
|
+
this.namedMarkers = this.namedMarkers.filter((m) => {
|
|
158
|
+
if (m.isPrior) {
|
|
159
|
+
m.marker?.remove();
|
|
156
160
|
return false;
|
|
157
161
|
}
|
|
158
162
|
return true;
|
|
@@ -198,7 +202,7 @@ var LeafletMapOverlay = class {
|
|
|
198
202
|
this.rawGpsPoints = [];
|
|
199
203
|
this.fusedPoints = [];
|
|
200
204
|
this.snapshotPoints = [];
|
|
201
|
-
this.
|
|
205
|
+
this.namedMarkers = [];
|
|
202
206
|
this.cssObject = null;
|
|
203
207
|
log.info("Leaflet map overlay disposed");
|
|
204
208
|
}
|
|
@@ -236,9 +240,9 @@ var LeafletMapOverlay = class {
|
|
|
236
240
|
this.fusedPolyline = null;
|
|
237
241
|
this.snapshotPolyline?.remove();
|
|
238
242
|
this.snapshotPolyline = null;
|
|
239
|
-
for (const
|
|
240
|
-
|
|
241
|
-
|
|
243
|
+
for (const m of this.namedMarkers) {
|
|
244
|
+
m.marker?.remove();
|
|
245
|
+
m.marker = null;
|
|
242
246
|
}
|
|
243
247
|
if (this.leafletMap) {
|
|
244
248
|
this.leafletMap.remove();
|
|
@@ -285,7 +289,7 @@ var LeafletMapOverlay = class {
|
|
|
285
289
|
weight: 3,
|
|
286
290
|
opacity: .8
|
|
287
291
|
}).addTo(this.leafletMap);
|
|
288
|
-
for (const
|
|
292
|
+
for (const m of this.namedMarkers) if (!m.marker) m.marker = this.createNamedMarker(m.lat, m.lng, m.name, m.isPrior);
|
|
289
293
|
}
|
|
290
294
|
updateUserMarker() {
|
|
291
295
|
if (!this.gpsPosition || !this.leafletMap) return;
|
|
@@ -297,7 +301,7 @@ var LeafletMapOverlay = class {
|
|
|
297
301
|
iconAnchor: [7, 7]
|
|
298
302
|
}) }).addTo(this.leafletMap);
|
|
299
303
|
}
|
|
300
|
-
|
|
304
|
+
createNamedMarker(lat, lon, name, isPrior) {
|
|
301
305
|
const color = isPrior ? VIS_COLORS.PRIOR_REF_POINT.css : VIS_COLORS.CURRENT_REF_POINT.css;
|
|
302
306
|
const opacity = isPrior ? "opacity:0.8;" : "";
|
|
303
307
|
const label = isPrior ? `📌 ${name} (prior)` : name;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-
|
|
1
|
+
import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-CZgQlrmu.js";
|
|
2
2
|
export { DEFAULT_LERP_RATE, clampedAlpha };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-
|
|
1
|
+
import { a as MapOverlayOptions, c as tileXYToLatLon, i as MapOverlay, n as DEFAULT_MAP_SIZE, o as TextureLoaderInterface, r as DEFAULT_ZOOM, s as latLonToTileXY, t as DEFAULT_HEIGHT_OFFSET } from "../map-overlay-C9ifl_4-.js";
|
|
2
2
|
export { DEFAULT_HEIGHT_OFFSET, DEFAULT_MAP_SIZE, DEFAULT_ZOOM, MapOverlay, MapOverlayOptions, TextureLoaderInterface, latLonToTileXY, tileXYToLatLon };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-
|
|
1
|
+
import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-qt_r5wR1.js";
|
|
2
2
|
export { DisposeOptions, disposeMeshArray, disposeObject3D };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as VIS_COLORS } from "../vis-colors-
|
|
1
|
+
import { t as VIS_COLORS } from "../vis-colors-BKkdTIKb.js";
|
|
2
2
|
export { VIS_COLORS };
|