gps-plus-slam-app-framework 1.0.0

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.
Files changed (200) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +222 -0
  3. package/dist/alignment-lerper-D9BeDwZX.d.ts +29 -0
  4. package/dist/app-selectors-DyMzxCEC.d.ts +140 -0
  5. package/dist/ar/camera-blit-capture.d.ts +2 -0
  6. package/dist/ar/camera-blit-capture.js +253 -0
  7. package/dist/ar/capture-failure-tracker.d.ts +2 -0
  8. package/dist/ar/capture-failure-tracker.js +45 -0
  9. package/dist/ar/chromium-camera-access-workaround.d.ts +2 -0
  10. package/dist/ar/chromium-camera-access-workaround.js +32 -0
  11. package/dist/ar/depth-sampler.d.ts +3 -0
  12. package/dist/ar/depth-sampler.js +147 -0
  13. package/dist/ar/image-capture.d.ts +2 -0
  14. package/dist/ar/image-capture.js +152 -0
  15. package/dist/ar/index.d.ts +12 -0
  16. package/dist/ar/index.js +12 -0
  17. package/dist/ar/replay-scene.d.ts +2 -0
  18. package/dist/ar/replay-scene.js +325 -0
  19. package/dist/ar/scene-node-names.d.ts +2 -0
  20. package/dist/ar/scene-node-names.js +16 -0
  21. package/dist/ar/tracking-state.d.ts +2 -0
  22. package/dist/ar/tracking-state.js +164 -0
  23. package/dist/ar/webxr-session.d.ts +4 -0
  24. package/dist/ar/webxr-session.js +890 -0
  25. package/dist/ar/xr-camera-texture.d.ts +2 -0
  26. package/dist/ar/xr-camera-texture.js +39 -0
  27. package/dist/ar/xr-error-handler.d.ts +2 -0
  28. package/dist/ar/xr-error-handler.js +37 -0
  29. package/dist/ar-types-B-ORgk6Z.d.ts +82 -0
  30. package/dist/camera-blit-capture-DHuyrrxr.d.ts +108 -0
  31. package/dist/camera-follower-BMqPddxx.d.ts +29 -0
  32. package/dist/capture-failure-tracker-2Q6oI2uQ.d.ts +52 -0
  33. package/dist/chromium-camera-access-workaround-CU5zSKNr.d.ts +61 -0
  34. package/dist/community-license-key-ChZLCJyO.d.ts +21 -0
  35. package/dist/concurrency-p6gB30fT.d.ts +24 -0
  36. package/dist/css3d-renderer-manager-rgLMVAvd.d.ts +23 -0
  37. package/dist/depth-sampler-BNCtnEoP.d.ts +108 -0
  38. package/dist/failure-tracker-1sQ_Cgyw.d.ts +49 -0
  39. package/dist/file-system-BsQgYCU3.d.ts +128 -0
  40. package/dist/file-system-utils-5cWO8Xyv.d.ts +24 -0
  41. package/dist/format-file-size-onGq0k1Q.d.ts +24 -0
  42. package/dist/fused-path-DtqCSqJh.d.ts +25 -0
  43. package/dist/geo-types-Xx-LVcnw.d.ts +29 -0
  44. package/dist/gps-Ddzr2KlX.d.ts +54 -0
  45. package/dist/gps-compass-cubes-C-6JEnpR.d.ts +22 -0
  46. package/dist/gps-error-handler-VPuNOuf8.d.ts +40 -0
  47. package/dist/gps-event-markers-DpEy2qRd.d.ts +67 -0
  48. package/dist/h3-ref-point-CFhayNSZ.d.ts +59 -0
  49. package/dist/image-capture-2pKjYUS6.d.ts +130 -0
  50. package/dist/index.d.ts +56 -0
  51. package/dist/index.js +61 -0
  52. package/dist/leaflet-map-overlay-CvfQXTye.d.ts +114 -0
  53. package/dist/lerp-utils-87NWjUOD.d.ts +20 -0
  54. package/dist/licensing/community-license-key.d.ts +2 -0
  55. package/dist/licensing/community-license-key.js +21 -0
  56. package/dist/licensing/index.d.ts +2 -0
  57. package/dist/licensing/index.js +2 -0
  58. package/dist/list-formatter-DKQQVLcl.d.ts +14 -0
  59. package/dist/logger-B81iwxx0.d.ts +74 -0
  60. package/dist/map-overlay-DuiZuCTx.d.ts +153 -0
  61. package/dist/null-storage-backend-CsWvQwN8.d.ts +11 -0
  62. package/dist/opfs-storage-ChOzF_Wp.d.ts +181 -0
  63. package/dist/opfs-storage-backend-CVcmfJHN.d.ts +11 -0
  64. package/dist/permission-checker-jO2ziCWC.d.ts +146 -0
  65. package/dist/persistence-middleware-DrptY02i.d.ts +31 -0
  66. package/dist/recorder-slice-fcwAXrsh.d.ts +35 -0
  67. package/dist/recording-coordinator-DzflP07_.d.ts +81 -0
  68. package/dist/recording-options-BYUFX8iU.d.ts +166 -0
  69. package/dist/recording-replayer-oOzPITrd.d.ts +32 -0
  70. package/dist/ref-point-importer-B_wn5ABk.d.ts +62 -0
  71. package/dist/ref-point-loader-Pt1smgHS.d.ts +117 -0
  72. package/dist/ref-points/h3-ref-point.d.ts +2 -0
  73. package/dist/ref-points/h3-ref-point.js +74 -0
  74. package/dist/ref-points/index.d.ts +2 -0
  75. package/dist/ref-points/index.js +2 -0
  76. package/dist/ref-points-slice-tC-Wd6XJ.d.ts +48 -0
  77. package/dist/reference-points-CFWy8_wj.d.ts +68 -0
  78. package/dist/replay-engine-DuX316ae.d.ts +103 -0
  79. package/dist/replay-scene-DtUm6bsr.d.ts +109 -0
  80. package/dist/routing-slice-BlHTM8eh.d.ts +23 -0
  81. package/dist/scene-node-names-DPsaE2z3.d.ts +14 -0
  82. package/dist/sensors/gps-error-handler.d.ts +2 -0
  83. package/dist/sensors/gps-error-handler.js +53 -0
  84. package/dist/sensors/gps.d.ts +2 -0
  85. package/dist/sensors/gps.js +93 -0
  86. package/dist/sensors/index.d.ts +4 -0
  87. package/dist/sensors/index.js +4 -0
  88. package/dist/sensors/permission-checker.d.ts +2 -0
  89. package/dist/sensors/permission-checker.js +397 -0
  90. package/dist/state/app-selectors.d.ts +2 -0
  91. package/dist/state/app-selectors.js +35 -0
  92. package/dist/state/index.d.ts +17 -0
  93. package/dist/state/index.js +13 -0
  94. package/dist/state/persistence-middleware.d.ts +2 -0
  95. package/dist/state/persistence-middleware.js +71 -0
  96. package/dist/state/recorder-slice.d.ts +2 -0
  97. package/dist/state/recorder-slice.js +47 -0
  98. package/dist/state/recording-coordinator.d.ts +2 -0
  99. package/dist/state/recording-coordinator.js +150 -0
  100. package/dist/state/recording-options.d.ts +2 -0
  101. package/dist/state/recording-options.js +192 -0
  102. package/dist/state/recording-replayer.d.ts +2 -0
  103. package/dist/state/recording-replayer.js +39 -0
  104. package/dist/state/ref-points-slice.d.ts +2 -0
  105. package/dist/state/ref-points-slice.js +44 -0
  106. package/dist/state/replay-engine.d.ts +2 -0
  107. package/dist/state/replay-engine.js +230 -0
  108. package/dist/state/routing-slice.d.ts +2 -0
  109. package/dist/state/routing-slice.js +13 -0
  110. package/dist/state/store-subscribers.d.ts +3 -0
  111. package/dist/state/store-subscribers.js +97 -0
  112. package/dist/state/store.d.ts +9 -0
  113. package/dist/state/store.js +71 -0
  114. package/dist/state/subscribe-to-selector.d.ts +2 -0
  115. package/dist/state/subscribe-to-selector.js +26 -0
  116. package/dist/storage/file-system-utils.d.ts +2 -0
  117. package/dist/storage/file-system-utils.js +31 -0
  118. package/dist/storage/file-system.d.ts +2 -0
  119. package/dist/storage/file-system.js +229 -0
  120. package/dist/storage/index.d.ts +11 -0
  121. package/dist/storage/index.js +10 -0
  122. package/dist/storage/null-storage-backend.d.ts +2 -0
  123. package/dist/storage/null-storage-backend.js +8 -0
  124. package/dist/storage/opfs-storage-backend.d.ts +2 -0
  125. package/dist/storage/opfs-storage-backend.js +15 -0
  126. package/dist/storage/opfs-storage.d.ts +2 -0
  127. package/dist/storage/opfs-storage.js +242 -0
  128. package/dist/storage/ref-point-importer.d.ts +2 -0
  129. package/dist/storage/ref-point-importer.js +163 -0
  130. package/dist/storage/ref-point-loader.d.ts +2 -0
  131. package/dist/storage/ref-point-loader.js +248 -0
  132. package/dist/storage/ref-point-recovery.d.ts +28 -0
  133. package/dist/storage/ref-point-recovery.js +159 -0
  134. package/dist/storage/storage-backend.d.ts +2 -0
  135. package/dist/storage/storage-backend.js +1 -0
  136. package/dist/storage/zip-export.d.ts +2 -0
  137. package/dist/storage/zip-export.js +214 -0
  138. package/dist/storage/zip-reader.d.ts +2 -0
  139. package/dist/storage/zip-reader.js +190 -0
  140. package/dist/storage-backend-BcEItnFr.d.ts +20 -0
  141. package/dist/store-C7PKOj8S.d.ts +96 -0
  142. package/dist/store-subscribers-CuoIzB5T.d.ts +77 -0
  143. package/dist/subscribe-to-selector-UTZ0KkAc.d.ts +26 -0
  144. package/dist/test-utils/browser-mocks.d.ts +294 -0
  145. package/dist/test-utils/browser-mocks.js +568 -0
  146. package/dist/test-utils/zip-round-trip-helpers.d.ts +60 -0
  147. package/dist/test-utils/zip-round-trip-helpers.js +207 -0
  148. package/dist/three-dispose-CCBHjE_a.d.ts +30 -0
  149. package/dist/tracking-state-B9QfuZCg.d.ts +101 -0
  150. package/dist/types/ar-types.d.ts +2 -0
  151. package/dist/types/ar-types.js +1 -0
  152. package/dist/types/geo-types.d.ts +2 -0
  153. package/dist/types/geo-types.js +1 -0
  154. package/dist/types/index.d.ts +3 -0
  155. package/dist/types/index.js +1 -0
  156. package/dist/utils/concurrency.d.ts +2 -0
  157. package/dist/utils/concurrency.js +40 -0
  158. package/dist/utils/failure-tracker.d.ts +2 -0
  159. package/dist/utils/failure-tracker.js +48 -0
  160. package/dist/utils/format-file-size.d.ts +2 -0
  161. package/dist/utils/format-file-size.js +41 -0
  162. package/dist/utils/fused-path.d.ts +2 -0
  163. package/dist/utils/fused-path.js +44 -0
  164. package/dist/utils/index.d.ts +7 -0
  165. package/dist/utils/index.js +7 -0
  166. package/dist/utils/list-formatter.d.ts +2 -0
  167. package/dist/utils/list-formatter.js +17 -0
  168. package/dist/utils/logger.d.ts +2 -0
  169. package/dist/utils/logger.js +226 -0
  170. package/dist/vis-colors-Qi2vlRGt.d.ts +63 -0
  171. package/dist/visualization/alignment-lerper.d.ts +2 -0
  172. package/dist/visualization/alignment-lerper.js +68 -0
  173. package/dist/visualization/camera-follower.d.ts +2 -0
  174. package/dist/visualization/camera-follower.js +51 -0
  175. package/dist/visualization/css3d-renderer-manager.d.ts +2 -0
  176. package/dist/visualization/css3d-renderer-manager.js +41 -0
  177. package/dist/visualization/gps-compass-cubes.d.ts +2 -0
  178. package/dist/visualization/gps-compass-cubes.js +129 -0
  179. package/dist/visualization/gps-event-markers.d.ts +2 -0
  180. package/dist/visualization/gps-event-markers.js +159 -0
  181. package/dist/visualization/index.d.ts +12 -0
  182. package/dist/visualization/index.js +12 -0
  183. package/dist/visualization/leaflet-map-overlay.d.ts +2 -0
  184. package/dist/visualization/leaflet-map-overlay.js +313 -0
  185. package/dist/visualization/lerp-utils.d.ts +2 -0
  186. package/dist/visualization/lerp-utils.js +22 -0
  187. package/dist/visualization/map-overlay.d.ts +2 -0
  188. package/dist/visualization/map-overlay.js +241 -0
  189. package/dist/visualization/reference-points.d.ts +2 -0
  190. package/dist/visualization/reference-points.js +160 -0
  191. package/dist/visualization/three-dispose.d.ts +2 -0
  192. package/dist/visualization/three-dispose.js +55 -0
  193. package/dist/visualization/vis-colors.d.ts +2 -0
  194. package/dist/visualization/vis-colors.js +74 -0
  195. package/dist/webxr-session-COlSrXdL.d.ts +316 -0
  196. package/dist/xr-camera-texture-BbukNE79.d.ts +53 -0
  197. package/dist/xr-error-handler-DTHfmvrl.d.ts +24 -0
  198. package/dist/zip-export-Rtpi75JJ.d.ts +87 -0
  199. package/dist/zip-reader-D7pkpX8K.d.ts +97 -0
  200. package/package.json +104 -0
@@ -0,0 +1,241 @@
1
+ import { createLogger } from "../utils/logger.js";
2
+ import { disposeObject3D } from "./three-dispose.js";
3
+ import * as THREE from "three";
4
+ //#region ../src/visualization/map-overlay.ts
5
+ /**
6
+ * Map Overlay Module
7
+ *
8
+ * Creates and manages a 3D map overlay that displays OSM tiles
9
+ * floating below the user in the AR scene. The map is attached
10
+ * as a child of the camera so it automatically follows the user
11
+ * and is always visible at a fixed position in the camera's
12
+ * local coordinate space (below and slightly in front).
13
+ *
14
+ * ARCHITECTURE NOTE:
15
+ * - Map mesh is a child of the camera (camera-local space)
16
+ * - Position is fixed relative to camera: below + slightly in front
17
+ * - No per-frame position update needed — Three.js handles it
18
+ * - OSM tiles are loaded as textures on a PlaneGeometry
19
+ */
20
+ const log = createLogger("MapOverlay");
21
+ /** Default zoom level for OSM tiles (higher = more detail, smaller area) */
22
+ const DEFAULT_ZOOM = 17;
23
+ /** Default map size in meters */
24
+ const DEFAULT_MAP_SIZE = 10;
25
+ /** Default height offset below camera (negative = below) */
26
+ const DEFAULT_HEIGHT_OFFSET = -4;
27
+ /**
28
+ * Convert latitude/longitude to tile X/Y coordinates.
29
+ * Uses Web Mercator projection (EPSG:3857).
30
+ *
31
+ * @param lat - Latitude in degrees
32
+ * @param lon - Longitude in degrees
33
+ * @param zoom - Zoom level (0-19)
34
+ * @returns [tileX, tileY] as integers
35
+ */
36
+ function latLonToTileXY(lat, lon, zoom) {
37
+ const n = Math.pow(2, zoom);
38
+ const latRad = lat * Math.PI / 180;
39
+ const x = Math.floor((lon + 180) / 360 * n);
40
+ const y = Math.floor((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * n);
41
+ return [Math.max(0, Math.min(n - 1, x)), Math.max(0, Math.min(n - 1, y))];
42
+ }
43
+ /**
44
+ * Convert tile X/Y coordinates back to latitude/longitude.
45
+ * Returns the top-left corner of the tile.
46
+ *
47
+ * @param x - Tile X coordinate
48
+ * @param y - Tile Y coordinate
49
+ * @param zoom - Zoom level
50
+ * @returns [lat, lon] in degrees
51
+ */
52
+ function tileXYToLatLon(x, y, zoom) {
53
+ const n = Math.pow(2, zoom);
54
+ const lon = x / n * 360 - 180;
55
+ return [Math.atan(Math.sinh(Math.PI * (1 - 2 * y / n))) * 180 / Math.PI, lon];
56
+ }
57
+ /**
58
+ * Interactive 3D map overlay that displays OSM tiles in the AR scene.
59
+ * The map floats below the user and follows their horizontal movement.
60
+ */
61
+ var MapOverlay = class {
62
+ scene;
63
+ camera;
64
+ options;
65
+ onTileError;
66
+ mapParent;
67
+ mesh = null;
68
+ material = null;
69
+ geometry = null;
70
+ textureLoader;
71
+ gpsPosition = null;
72
+ currentTile = null;
73
+ visible = false;
74
+ /**
75
+ * Create a new map overlay.
76
+ *
77
+ * @param scene - The Three.js scene to add the map to
78
+ * @param camera - The camera to follow (for positioning)
79
+ * @param options - Configuration options
80
+ */
81
+ constructor(scene, camera, options = {}) {
82
+ this.scene = scene;
83
+ this.camera = camera;
84
+ this.options = {
85
+ mapSize: options.mapSize ?? 10,
86
+ heightOffset: options.heightOffset ?? -4,
87
+ zoomLevel: options.zoomLevel ?? 17,
88
+ tileServerUrl: options.tileServerUrl ?? "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
89
+ };
90
+ this.textureLoader = options.textureLoader ?? new THREE.TextureLoader();
91
+ this.onTileError = options.onTileError;
92
+ this.mapParent = options.mapParent ?? camera;
93
+ }
94
+ /**
95
+ * Set the current GPS position for tile loading.
96
+ *
97
+ * @param lat - Latitude in degrees
98
+ * @param lon - Longitude in degrees
99
+ */
100
+ setGpsPosition(lat, lon) {
101
+ this.gpsPosition = {
102
+ lat,
103
+ lon
104
+ };
105
+ if (this.visible) this.updateTile();
106
+ }
107
+ /**
108
+ * Get the current GPS position.
109
+ */
110
+ getGpsPosition() {
111
+ return this.gpsPosition;
112
+ }
113
+ /**
114
+ * Show the map overlay.
115
+ * Requires GPS position to be set first.
116
+ */
117
+ show() {
118
+ if (!this.gpsPosition) {
119
+ log.warn("Cannot show map - no GPS position set");
120
+ return;
121
+ }
122
+ if (this.visible) return;
123
+ this.createMesh();
124
+ this.updateTile();
125
+ this.visible = true;
126
+ log.info("Map overlay shown");
127
+ }
128
+ /**
129
+ * Hide the map overlay.
130
+ */
131
+ hide() {
132
+ if (!this.visible) return;
133
+ this.removeMesh();
134
+ this.visible = false;
135
+ log.info("Map overlay hidden");
136
+ }
137
+ /**
138
+ * Toggle map visibility.
139
+ */
140
+ toggle() {
141
+ if (this.visible) this.hide();
142
+ else this.show();
143
+ }
144
+ /**
145
+ * Check if the map is currently visible.
146
+ */
147
+ isVisible() {
148
+ return this.visible;
149
+ }
150
+ /**
151
+ * Get the map size in meters.
152
+ */
153
+ getMapSize() {
154
+ return this.options.mapSize;
155
+ }
156
+ /**
157
+ * Get the height offset below camera.
158
+ */
159
+ getHeightOffset() {
160
+ return this.options.heightOffset;
161
+ }
162
+ /**
163
+ * Get the mesh (for testing).
164
+ */
165
+ getMesh() {
166
+ return this.mesh;
167
+ }
168
+ /**
169
+ * Update the map position to follow the camera.
170
+ *
171
+ * Since the mesh is now a child of the camera, Three.js handles
172
+ * world-space transforms automatically. This method is kept for
173
+ * backward compatibility but is a no-op (position is set once in
174
+ * createMesh and doesn't need per-frame updates).
175
+ */
176
+ updatePosition() {}
177
+ /**
178
+ * Clean up resources.
179
+ */
180
+ dispose() {
181
+ this.hide();
182
+ if (this.mesh) disposeObject3D(this.mesh);
183
+ this.geometry = null;
184
+ this.material = null;
185
+ this.mesh = null;
186
+ this.currentTile = null;
187
+ }
188
+ /**
189
+ * Create the map mesh (plane facing up).
190
+ */
191
+ createMesh() {
192
+ if (this.mesh) {
193
+ this.mapParent.add(this.mesh);
194
+ return;
195
+ }
196
+ this.geometry = new THREE.PlaneGeometry(this.options.mapSize, this.options.mapSize);
197
+ this.material = new THREE.MeshBasicMaterial({
198
+ color: 16777215,
199
+ side: THREE.DoubleSide,
200
+ transparent: true,
201
+ opacity: .9
202
+ });
203
+ this.mesh = new THREE.Mesh(this.geometry, this.material);
204
+ this.mesh.name = "map-overlay";
205
+ this.mesh.rotation.x = -Math.PI / 2;
206
+ this.mesh.position.set(0, this.options.heightOffset, -.5);
207
+ this.mapParent.add(this.mesh);
208
+ }
209
+ /**
210
+ * Remove the mesh from the camera.
211
+ */
212
+ removeMesh() {
213
+ if (this.mesh) this.mapParent.remove(this.mesh);
214
+ }
215
+ /**
216
+ * Update the tile texture based on current GPS position.
217
+ */
218
+ updateTile() {
219
+ if (!this.gpsPosition || !this.material) return;
220
+ const [x, y] = latLonToTileXY(this.gpsPosition.lat, this.gpsPosition.lon, this.options.zoomLevel);
221
+ if (this.currentTile?.x === x && this.currentTile?.y === y) return;
222
+ this.currentTile = {
223
+ x,
224
+ y
225
+ };
226
+ const url = this.options.tileServerUrl.replace("{z}", String(this.options.zoomLevel)).replace("{x}", String(x)).replace("{y}", String(y));
227
+ log.info(`Loading tile: z=${this.options.zoomLevel}, x=${x}, y=${y}`);
228
+ this.textureLoader.load(url, (texture) => {
229
+ if (this.material) {
230
+ if (this.material.map) this.material.map.dispose();
231
+ this.material.map = texture;
232
+ this.material.needsUpdate = true;
233
+ }
234
+ }, void 0, (error) => {
235
+ log.error("Failed to load map tile:", error);
236
+ this.onTileError?.(error);
237
+ });
238
+ }
239
+ };
240
+ //#endregion
241
+ export { DEFAULT_HEIGHT_OFFSET, DEFAULT_MAP_SIZE, DEFAULT_ZOOM, MapOverlay, latLonToTileXY, tileXYToLatLon };
@@ -0,0 +1,2 @@
1
+ import { n as refPointVisualizer, t as RefPointVisualizer } from "../reference-points-CFWy8_wj.js";
2
+ export { RefPointVisualizer, refPointVisualizer };
@@ -0,0 +1,160 @@
1
+ import { createLogger } from "../utils/logger.js";
2
+ import { disposeMeshArray } from "./three-dispose.js";
3
+ import { getScene } from "../ar/webxr-session.js";
4
+ import { VIS_COLORS } from "./vis-colors.js";
5
+ import * as THREE from "three";
6
+ import { calcRelativeCoordsInMeters } from "gps-plus-slam-js";
7
+ //#region ../src/visualization/reference-points.ts
8
+ /**
9
+ * Reference Point Visualizer
10
+ *
11
+ * Creates and manages Three.js meshes for visualizing reference points
12
+ * in GPS-aligned 3D space.
13
+ *
14
+ * ARCHITECTURE NOTE:
15
+ * - Prior reference points (green) are added to scene root (GPS world space)
16
+ * - Current session points (red) are also in GPS world space
17
+ * - Spheres stay in GPS coordinates, independent of alignment matrix
18
+ */
19
+ const log = createLogger("RefPointVisualizer");
20
+ /** Sphere radius in meters (10cm) */
21
+ const REF_POINT_RADIUS = .1;
22
+ /**
23
+ * Manager for reference point visualization
24
+ */
25
+ var RefPointVisualizer = class {
26
+ priorRefMeshes = [];
27
+ currentRefMeshes = [];
28
+ zeroRef = null;
29
+ /** Shared geometry for prior-session ref point meshes (lazy-created) */
30
+ priorRefGeometry = null;
31
+ /** Shared material for prior-session ref point meshes (lazy-created) */
32
+ priorRefMaterial = null;
33
+ /** Shared geometry for current-session ref point meshes (lazy-created) */
34
+ currentRefGeometry = null;
35
+ /**
36
+ * Set the GPS zero reference (origin for coordinate conversion).
37
+ * Must be called before displaying reference points.
38
+ *
39
+ * @param zero - GPS coordinates of the origin
40
+ */
41
+ setZeroRef(zero) {
42
+ this.zeroRef = zero;
43
+ }
44
+ /**
45
+ * Get the current zero reference
46
+ */
47
+ getZeroRef() {
48
+ return this.zeroRef;
49
+ }
50
+ /**
51
+ * Display reference points from prior sessions.
52
+ * Clears any existing prior ref points first.
53
+ *
54
+ * @param refPoints - Array of reference point marks to visualize
55
+ */
56
+ displayPriorRefPoints(refPoints) {
57
+ if (!this.zeroRef) {
58
+ log.warn("No zero reference set");
59
+ return;
60
+ }
61
+ const scene = getScene();
62
+ if (!scene) {
63
+ log.warn("Scene not available");
64
+ return;
65
+ }
66
+ this.clearPriorRefPoints();
67
+ const geometry = this.priorRefGeometry ??= new THREE.SphereGeometry(REF_POINT_RADIUS, 16, 16);
68
+ const material = this.priorRefMaterial ??= new THREE.MeshBasicMaterial({ color: VIS_COLORS.PRIOR_REF_POINT.hex });
69
+ let visibleCount = 0;
70
+ for (const refPoint of refPoints) {
71
+ if (!refPoint.gpsPosition) continue;
72
+ const coords = calcRelativeCoordsInMeters(this.zeroRef, {
73
+ lat: refPoint.gpsPosition.lat,
74
+ lon: refPoint.gpsPosition.lon
75
+ }, refPoint.gpsPosition.altitude ?? 0, 0);
76
+ const mesh = new THREE.Mesh(geometry, material);
77
+ mesh.position.set(coords[0], coords[1], coords[2]);
78
+ mesh.name = `prior-ref-${refPoint.id}`;
79
+ scene.add(mesh);
80
+ this.priorRefMeshes.push(mesh);
81
+ visibleCount++;
82
+ }
83
+ log.info(`Displayed ${visibleCount}/${refPoints.length} prior reference points`);
84
+ }
85
+ /**
86
+ * Add a reference point from the current session.
87
+ *
88
+ * @param refPoint - Reference point mark to visualize
89
+ */
90
+ addCurrentRefPoint(refPoint) {
91
+ if (!this.zeroRef || !refPoint.gpsPosition) {
92
+ log.warn("Cannot add current ref point - missing zero ref or GPS position");
93
+ return;
94
+ }
95
+ const scene = getScene();
96
+ if (!scene) {
97
+ log.warn("Scene not available");
98
+ return;
99
+ }
100
+ const coords = calcRelativeCoordsInMeters(this.zeroRef, {
101
+ lat: refPoint.gpsPosition.lat,
102
+ lon: refPoint.gpsPosition.lon
103
+ }, refPoint.gpsPosition.altitude ?? 0, 0);
104
+ const geometry = this.currentRefGeometry ??= new THREE.SphereGeometry(REF_POINT_RADIUS, 16, 16);
105
+ const material = new THREE.MeshBasicMaterial({ color: VIS_COLORS.CURRENT_REF_POINT.hex });
106
+ const mesh = new THREE.Mesh(geometry, material);
107
+ mesh.position.set(coords[0], coords[1], coords[2]);
108
+ mesh.name = `current-ref-${refPoint.id}`;
109
+ scene.add(mesh);
110
+ this.currentRefMeshes.push(mesh);
111
+ log.info(`Added current ref point: ${refPoint.id}`);
112
+ }
113
+ /**
114
+ * Clear all prior reference point meshes from the scene.
115
+ */
116
+ clearPriorRefPoints() {
117
+ const scene = getScene();
118
+ disposeMeshArray(this.priorRefMeshes, scene, {
119
+ skipGeometry: true,
120
+ skipMaterial: true
121
+ });
122
+ this.priorRefGeometry?.dispose();
123
+ this.priorRefGeometry = null;
124
+ this.priorRefMaterial?.dispose();
125
+ this.priorRefMaterial = null;
126
+ }
127
+ /**
128
+ * Clear current session reference point meshes from the scene.
129
+ */
130
+ clearCurrentRefPoints() {
131
+ const scene = getScene();
132
+ disposeMeshArray(this.currentRefMeshes, scene, { skipGeometry: true });
133
+ this.currentRefGeometry?.dispose();
134
+ this.currentRefGeometry = null;
135
+ }
136
+ /**
137
+ * Clear all visualizations and reset state.
138
+ */
139
+ clearAll() {
140
+ this.clearPriorRefPoints();
141
+ this.clearCurrentRefPoints();
142
+ this.zeroRef = null;
143
+ }
144
+ /**
145
+ * Get count of visible reference points.
146
+ */
147
+ getCounts() {
148
+ return {
149
+ prior: this.priorRefMeshes.length,
150
+ current: this.currentRefMeshes.length
151
+ };
152
+ }
153
+ };
154
+ /**
155
+ * Singleton instance for global use.
156
+ * Import this to visualize reference points.
157
+ */
158
+ const refPointVisualizer = new RefPointVisualizer();
159
+ //#endregion
160
+ export { RefPointVisualizer, refPointVisualizer };
@@ -0,0 +1,2 @@
1
+ import { n as disposeMeshArray, r as disposeObject3D, t as DisposeOptions } from "../three-dispose-CCBHjE_a.js";
2
+ export { DisposeOptions, disposeMeshArray, disposeObject3D };
@@ -0,0 +1,55 @@
1
+ //#region ../src/visualization/three-dispose.ts
2
+ /**
3
+ * Traverse an Object3D and all its descendants, disposing GPU resources:
4
+ * geometries (Mesh), materials (Mesh + Sprite), and material textures.
5
+ *
6
+ * Does NOT remove root from its parent — callers handle that.
7
+ *
8
+ * @param root The Object3D tree root to clean up.
9
+ * @param opts Optional flags (e.g. skipGeometry for shared geometries).
10
+ */
11
+ function disposeObject3D(root, opts) {
12
+ const disposed = /* @__PURE__ */ new Set();
13
+ root.traverse((object) => {
14
+ if ("geometry" in object && object.geometry) {
15
+ const geo = object.geometry;
16
+ if (!opts?.skipGeometry && !disposed.has(geo)) {
17
+ disposed.add(geo);
18
+ geo.dispose();
19
+ }
20
+ }
21
+ if (!opts?.skipMaterial && "material" in object) {
22
+ const raw = object.material;
23
+ const materials = Array.isArray(raw) ? raw : [raw];
24
+ for (const mat of materials) {
25
+ if (!mat || disposed.has(mat)) continue;
26
+ disposed.add(mat);
27
+ if ("map" in mat && mat.map) {
28
+ const tex = mat.map;
29
+ if (!disposed.has(tex)) {
30
+ disposed.add(tex);
31
+ tex.dispose();
32
+ }
33
+ }
34
+ mat.dispose();
35
+ }
36
+ }
37
+ });
38
+ }
39
+ /**
40
+ * Remove meshes from a parent, dispose their GPU resources, and clear
41
+ * the array in-place.
42
+ *
43
+ * @param meshes Array of meshes (mutated — emptied after disposal).
44
+ * @param parent The Object3D to remove meshes from. Pass null/undefined to skip removal.
45
+ * @param opts Optional flags (e.g. skipGeometry for shared geometries).
46
+ */
47
+ function disposeMeshArray(meshes, parent, opts) {
48
+ for (const mesh of meshes) {
49
+ if (parent) parent.remove(mesh);
50
+ disposeObject3D(mesh, opts);
51
+ }
52
+ meshes.length = 0;
53
+ }
54
+ //#endregion
55
+ export { disposeMeshArray, disposeObject3D };
@@ -0,0 +1,2 @@
1
+ import { t as VIS_COLORS } from "../vis-colors-Qi2vlRGt.js";
2
+ export { VIS_COLORS };
@@ -0,0 +1,74 @@
1
+ //#region ../src/visualization/vis-colors.ts
2
+ /**
3
+ * Centralized Visualization Color Palette
4
+ *
5
+ * Single source of truth for all semantic colors used across the app's
6
+ * visualization layers (Three.js 3D scene and Leaflet 2D summary map).
7
+ *
8
+ * Each entry provides both hex (number, for Three.js) and css (string,
9
+ * for Leaflet/CSS) formats. Some entries intentionally use different 3D/2D
10
+ * shades — see inline comments.
11
+ *
12
+ * Tailwind classes in index.html (e.g., bg-yellow-400) cannot be dynamically
13
+ * generated and must be kept in sync manually — search for "vis-colors" in
14
+ * the HTML legend to find them.
15
+ */
16
+ const VIS_COLORS = {
17
+ /** Raw GPS marker — yellow */
18
+ RAW_GPS: {
19
+ hex: 16776960,
20
+ css: "#ffff00"
21
+ },
22
+ /** Fused VIO marker — cyan */
23
+ FUSED_VIO: {
24
+ hex: 65535,
25
+ css: "#00ffff"
26
+ },
27
+ /** Alignment snapshot marker — red */
28
+ ALIGNMENT_SNAPSHOT: {
29
+ hex: 16711680,
30
+ css: "#ff0000"
31
+ },
32
+ /** Prior reference point — green */
33
+ PRIOR_REF_POINT: {
34
+ hex: 65280,
35
+ css: "#00ff00"
36
+ },
37
+ /** Current reference point — bright red in 3D, lighter red (#ff6b6b) in 2D for map visibility */
38
+ CURRENT_REF_POINT: {
39
+ hex: 16711680,
40
+ css: "#ff6b6b"
41
+ },
42
+ /** Compass north indicator — red */
43
+ COMPASS_NORTH: {
44
+ hex: 16711680,
45
+ css: "#ff0000"
46
+ },
47
+ /** Compass east indicator — blue */
48
+ COMPASS_EAST: {
49
+ hex: 255,
50
+ css: "#0000ff"
51
+ },
52
+ /** Compass south indicator — dark red */
53
+ COMPASS_SOUTH: {
54
+ hex: 8930372,
55
+ css: "#884444"
56
+ },
57
+ /** Compass west indicator — dark blue */
58
+ COMPASS_WEST: {
59
+ hex: 4473992,
60
+ css: "#444488"
61
+ },
62
+ /** Compass up indicator — green */
63
+ COMPASS_UP: {
64
+ hex: 65280,
65
+ css: "#00ff00"
66
+ },
67
+ /** User GPS position marker — blue */
68
+ USER_POSITION: {
69
+ hex: 3900150,
70
+ css: "#3b82f6"
71
+ }
72
+ };
73
+ //#endregion
74
+ export { VIS_COLORS };