gps-plus-slam-app-framework 1.7.0 → 1.9.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.
- package/dist/{accuracy-circles-BtqOP_v1.d.ts → accuracy-circles-DkWBkF5g.d.ts} +16 -6
- package/dist/{app-selectors-ikTUQZpe.d.ts → app-selectors-BbAiCRUT.d.ts} +1 -1
- package/dist/ar/bresenham3d.d.ts +1 -1
- package/dist/ar/camera-blit-capture.d.ts +1 -1
- package/dist/ar/capability-checker.d.ts +1 -1
- package/dist/ar/capture-failure-tracker.d.ts +1 -1
- package/dist/ar/chromium-camera-access-workaround.d.ts +1 -1
- package/dist/ar/depth-grid-lookup.d.ts +1 -1
- package/dist/ar/depth-occluder.d.ts +127 -0
- package/dist/ar/depth-occluder.js +299 -0
- package/dist/ar/depth-sampler.d.ts +2 -2
- package/dist/ar/depth-sampler.js +24 -4
- package/dist/ar/depth-unprojection.d.ts +1 -1
- package/dist/ar/depth-unprojection.js +52 -21
- package/dist/ar/enable-gps-ar.d.ts +1 -1
- package/dist/ar/enable-gps-ar.js +1 -1
- package/dist/ar/frame-loop.d.ts +1 -1
- package/dist/ar/frame-loop.js +12 -2
- package/dist/ar/image-capture.d.ts +1 -1
- package/dist/ar/image-capture.js +1 -1
- package/dist/ar/image-quality.d.ts +1 -1
- package/dist/ar/image-quality.js +2 -1
- package/dist/ar/index.d.ts +32 -31
- package/dist/ar/index.js +5 -4
- package/dist/ar/occlusion-mesh-worker.d.ts +58 -0
- package/dist/ar/occlusion-mesh-worker.js +129 -0
- package/dist/ar/occupancy-grid.d.ts +2 -2
- package/dist/ar/occupancy-grid.js +287 -31
- package/dist/ar/occupancy-mesher.d.ts +2 -0
- package/dist/ar/occupancy-mesher.js +638 -0
- package/dist/ar/planar-pnp.d.ts +1 -1
- package/dist/ar/qr-debug-view.d.ts +1 -1
- package/dist/ar/qr-derived-pose.d.ts +1 -1
- package/dist/ar/qr-detection-controller.d.ts +1 -1
- package/dist/ar/qr-frontend.d.ts +1 -1
- package/dist/ar/qr-pose.d.ts +1 -1
- package/dist/ar/qr-size-depth-context.d.ts +2 -2
- package/dist/ar/qr-size-measurer.d.ts +1 -1
- package/dist/ar/replay-scene.d.ts +1 -1
- package/dist/ar/replay-scene.js +1 -1
- package/dist/ar/scene-node-names.d.ts +1 -1
- package/dist/ar/webxr-nue-basis.d.ts +1 -1
- package/dist/ar/webxr-session.d.ts +4 -4
- package/dist/ar/webxr-session.js +2 -2
- package/dist/ar/xr-camera-texture.d.ts +1 -1
- package/dist/ar/xr-error-handler.d.ts +1 -1
- package/dist/ar/xr-frame-loop.d.ts +1 -1
- package/dist/ar/xr-frame-loop.js +12 -2
- package/dist/{ar-MFpFlV7j.js → ar-BqCudtqE.js} +3 -2
- package/dist/{ar-world-group-alignment-69fgnB39.d.ts → ar-world-group-alignment-Cfg0trC3.d.ts} +1 -1
- package/dist/{capture-motion-gate-4EscNZCw.js → capture-motion-gate-_NdTSwKi.js} +17 -5
- package/dist/cell-key-DIB4rOTV.js +51 -0
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +2 -2
- package/dist/{create-slam-app-store-n_VF63D5.d.ts → create-slam-app-store-D1QSMuKu.d.ts} +8 -9
- package/dist/{create-slam-app-store-DkCHOpvb.js → create-slam-app-store-DXiAnJwR.js} +9 -2
- package/dist/{depth-grid-lookup-DQ-IYhO3.d.ts → depth-grid-lookup-D5atpNZ3.d.ts} +1 -1
- package/dist/{depth-sampler-asc8exHt.d.ts → depth-sampler-CwObAwEA.d.ts} +33 -1
- package/dist/{depth-unprojection-DjsbJW9L.d.ts → depth-unprojection-DRdBU90S.d.ts} +1 -1
- package/dist/{enable-gps-ar-DkNhFv4Y.d.ts → enable-gps-ar-BBtRO2FJ.d.ts} +4 -4
- package/dist/{frame-conversions-DObhj8Wf.d.ts → frame-conversions-DDcNHkTb.d.ts} +1 -1
- package/dist/{fused-path-v6eOmLl3.d.ts → fused-path-C5pp0PJU.d.ts} +1 -1
- package/dist/geo/h3-proximity.d.ts +1 -1
- package/dist/geo/index.d.ts +1 -1
- package/dist/{gps-anchor-BeFO2RYa.d.ts → gps-anchor-CEjGqEVD.d.ts} +1 -1
- package/dist/{gps-ar-pose-sampler-DHMZmYAc.d.ts → gps-ar-pose-sampler-DEGNk2CI.d.ts} +1 -1
- package/dist/{gps-event-coordinator-CjWW636x.d.ts → gps-event-coordinator-BWpgBrHq.d.ts} +4 -4
- package/dist/{image-capture-CNZDrQXG.d.ts → image-capture-Bp6Pd4Md.d.ts} +3 -3
- package/dist/{image-capture-B2-b6tKK.js → image-capture-DVcuqMtX.js} +1 -1
- package/dist/{index-BODDUTvD.d.ts → index-B6iBnO_K.d.ts} +1 -1
- package/dist/index-DXPVzOpP.d.ts +2 -0
- package/dist/{index-BneSj4_5.d.ts → index-cCQWuYqy.d.ts} +3 -3
- package/dist/index.d.ts +82 -80
- package/dist/index.js +10 -8
- package/dist/{leaflet-map-overlay-CmIyiE8n.d.ts → leaflet-map-overlay-C8GS4cUy.d.ts} +64 -10
- package/dist/leaflet-map-overlay-CBWPvaX9.js +452 -0
- package/dist/lerp-utils-Qs8OhumS.d.ts +42 -0
- package/dist/map-data-1tF5gcYV.js +124 -0
- package/dist/map-data-CUnTzRIC.d.ts +78 -0
- package/dist/{map-overlay-draw-ymz1s7fG.d.ts → map-overlay-draw-6WJeq0Kg.d.ts} +1 -1
- package/dist/{null-storage-backend-B9rtyDfG.d.ts → null-storage-backend-B1-jlpin.d.ts} +2 -2
- package/dist/occlusion-mesh-kXCQ2FM1.d.ts +194 -0
- package/dist/occupancy-grid-BV7RhB7I.d.ts +194 -0
- package/dist/occupancy-mesher-C2ecWhNp.d.ts +100 -0
- package/dist/{opfs-storage-3VZh-qH6.d.ts → opfs-storage-CTkxvxN4.d.ts} +5 -0
- package/dist/{opfs-storage-backend-JJiUJo-3.d.ts → opfs-storage-backend-D6Z03fML.d.ts} +2 -2
- package/dist/{persistence-middleware-DAPTTwB2.d.ts → persistence-middleware-CG-t08X4.d.ts} +1 -1
- package/dist/{planar-pnp-my9bqULS.d.ts → planar-pnp-D7bc_rLX.d.ts} +1 -1
- package/dist/{qr-debug-view-Brl73HGO.d.ts → qr-debug-view-BJooqbiP.d.ts} +1 -1
- package/dist/{qr-derived-pose-CmxTP2m4.d.ts → qr-derived-pose-BwNWn8oV.d.ts} +2 -2
- package/dist/{qr-detected-slice-VQssZmQJ.d.ts → qr-detected-slice-TzVb8bij.d.ts} +4 -4
- package/dist/{qr-detection-controller-CDurHv8E.d.ts → qr-detection-controller-Bo4XfQTP.d.ts} +3 -3
- package/dist/{qr-frontend--fFX25mV.d.ts → qr-frontend-BPURlh3S.d.ts} +1 -1
- package/dist/{qr-pose-aggregation-B7tWJq7j.d.ts → qr-pose-aggregation-CypnmjA-.d.ts} +1 -1
- package/dist/{qr-size-depth-context-CeAG53fy.d.ts → qr-size-depth-context-apAOmbrZ.d.ts} +2 -2
- package/dist/{qr-size-measurer-DQdAsid1.d.ts → qr-size-measurer-DxiMqRUw.d.ts} +3 -3
- package/dist/{recording-options-BPCpMHLK.d.ts → recording-options-DYKWVI93.d.ts} +203 -24
- package/dist/{recording-replayer-DQKpAGyQ.d.ts → recording-replayer-BJ8Lf0QY.d.ts} +2 -2
- package/dist/{recording-slice-DaxHZvNu.d.ts → recording-slice-BW8SiLo1.d.ts} +2 -2
- package/dist/{replay-engine-CmKh_4wf.d.ts → replay-engine-DmCAc7WM.d.ts} +1 -1
- package/dist/{replay-scene-DBlDrV_x.d.ts → replay-scene-zJ8SFDjE.d.ts} +3 -3
- package/dist/sensors/absolute-orientation.d.ts +1 -1
- package/dist/sensors/absolute-orientation.js +23 -6
- package/dist/sensors/gps-error-handler.d.ts +1 -1
- package/dist/sensors/gps.d.ts +1 -1
- package/dist/sensors/index.d.ts +4 -4
- package/dist/sensors/permission-checker.d.ts +1 -1
- package/dist/state/app-selectors.d.ts +1 -1
- package/dist/state/combined-root-state.d.ts +1 -1
- package/dist/state/create-slam-app-store.d.ts +1 -1
- package/dist/state/create-slam-app-store.js +1 -1
- package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
- package/dist/state/gps-event-coordinator.d.ts +1 -1
- package/dist/state/index.d.ts +19 -19
- package/dist/state/index.js +2 -2
- package/dist/state/persistence-middleware.d.ts +1 -1
- package/dist/state/qr-detected-slice.d.ts +3 -3
- package/dist/state/recording-options.d.ts +2 -2
- package/dist/state/recording-options.js +150 -19
- package/dist/state/recording-replayer.d.ts +2 -2
- package/dist/state/recording-replayer.js +1 -1
- package/dist/state/recording-slice.d.ts +1 -1
- package/dist/state/replay-engine.d.ts +1 -1
- package/dist/state/store-subscribers.d.ts +2 -2
- package/dist/state/store-subscribers.js +26 -12
- package/dist/state/subscribe-to-selector.d.ts +1 -1
- package/dist/state/tracking-quality.d.ts +1 -1
- package/dist/state/tracking-quality.js +14 -6
- package/dist/state/tracking-slice.d.ts +1 -1
- package/dist/{state-E51QT_-j.js → state-BeKvn4B-.js} +1 -1
- package/dist/storage/file-system-utils.d.ts +1 -1
- package/dist/storage/index.d.ts +8 -8
- package/dist/storage/null-storage-backend.d.ts +1 -1
- package/dist/storage/opfs-storage-backend.d.ts +1 -1
- package/dist/storage/opfs-storage.d.ts +1 -1
- package/dist/storage/opfs-storage.js +30 -1
- package/dist/storage/storage-backend.d.ts +1 -1
- package/dist/storage/zip-coverage-embed.d.ts +1 -1
- package/dist/storage/zip-export.d.ts +1 -1
- package/dist/storage/zip-reader.d.ts +2 -2
- package/dist/storage/zip-reader.js +20 -7
- package/dist/{storage-backend-BdVLD0dU.d.ts → storage-backend-sEtmM4yW.d.ts} +1 -1
- package/dist/{store-subscribers-CA6AJH_8.d.ts → store-subscribers-DJUErW-o.d.ts} +6 -3
- package/dist/{subscribe-to-selector-B6EUmQ3I.d.ts → subscribe-to-selector-dQV8SpsO.d.ts} +1 -1
- package/dist/test-utils/browser-mocks.d.ts +1 -1
- package/dist/test-utils/browser-mocks.js +2 -0
- package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
- package/dist/{tracking-slice-BuAZxXZ5.d.ts → tracking-slice-DMkHlbny.d.ts} +1 -1
- package/dist/types/ar-types.d.ts +1 -1
- package/dist/types/geo-types.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/utils/concurrency.d.ts +1 -1
- package/dist/utils/failure-tracker.d.ts +1 -1
- package/dist/utils/format-file-size.d.ts +1 -1
- package/dist/utils/fused-path.d.ts +1 -1
- package/dist/utils/index.d.ts +7 -7
- package/dist/utils/list-formatter.d.ts +1 -1
- package/dist/utils/logger.d.ts +1 -1
- package/dist/visualization/accuracy-circles.d.ts +1 -1
- package/dist/visualization/accuracy-circles.js +17 -8
- package/dist/visualization/alignment-lerper.d.ts +1 -1
- package/dist/visualization/ar-world-group-alignment.d.ts +1 -1
- package/dist/visualization/ar-world-group-alignment.js +1 -1
- package/dist/visualization/camera-follower.d.ts +1 -1
- package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
- package/dist/visualization/frame-conversions.d.ts +1 -1
- package/dist/visualization/frustum-visibility.d.ts +1 -1
- package/dist/visualization/gps-anchor.d.ts +1 -1
- package/dist/visualization/gps-compass-cubes.d.ts +1 -1
- package/dist/visualization/gps-event-markers.d.ts +1 -1
- package/dist/visualization/gps-event-markers.js +1 -1
- package/dist/visualization/hit-test-reticle.d.ts +1 -1
- package/dist/visualization/index.d.ts +20 -19
- package/dist/visualization/index.js +4 -3
- package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
- package/dist/visualization/leaflet-map-overlay.js +1 -282
- package/dist/visualization/lerp-utils.d.ts +2 -2
- package/dist/visualization/lerp-utils.js +27 -3
- package/dist/visualization/map-data.d.ts +1 -1
- package/dist/visualization/map-data.js +1 -32
- package/dist/visualization/map-overlay-draw.d.ts +1 -1
- package/dist/visualization/map-overlay-draw.js +24 -2
- package/dist/visualization/map-overlay.d.ts +1 -1
- package/dist/visualization/occluder-mesh-driver.d.ts +130 -0
- package/dist/visualization/occluder-mesh-driver.js +219 -0
- package/dist/visualization/occlusion-mesh.d.ts +2 -0
- package/dist/visualization/occlusion-mesh.js +437 -0
- package/dist/visualization/three-dispose.d.ts +1 -1
- package/dist/visualization/vis-colors.d.ts +1 -1
- package/dist/{webxr-session-DG-eNfny.js → webxr-session-BCP2XK7k.js} +88 -13
- package/dist/{webxr-session-Do5L6G3B.d.ts → webxr-session-BWCpGd-2.d.ts} +73 -10
- package/dist/{zip-reader-D9iPQwdQ.d.ts → zip-reader-BzENzMH6.d.ts} +36 -10
- package/package.json +9 -5
- package/dist/index-_Rhgoqkh.d.ts +0 -2
- package/dist/lerp-utils-BLmHhkVe.d.ts +0 -20
- package/dist/map-data-B4oEehUh.d.ts +0 -49
- package/dist/occupancy-grid-DnOc-6PU.d.ts +0 -82
- /package/dist/{absolute-orientation-CAEh840t.d.ts → absolute-orientation-BAxc15J6.d.ts} +0 -0
- /package/dist/{alignment-lerper-Bil6vbVw.d.ts → alignment-lerper-gD70k7Fq.d.ts} +0 -0
- /package/dist/{ar-types-BFX2r1wk.d.ts → ar-types-Cc5yvBwn.d.ts} +0 -0
- /package/dist/{bresenham3d-CU1Gv2W4.d.ts → bresenham3d-DGc4nIb-.d.ts} +0 -0
- /package/dist/{camera-blit-capture-NKT9H5-e.d.ts → camera-blit-capture-BimSdyih.d.ts} +0 -0
- /package/dist/{camera-follower-CqJJ7zRj.d.ts → camera-follower-DfBm2J5i.d.ts} +0 -0
- /package/dist/{capability-checker-DUQLg6gq.d.ts → capability-checker-BTTpygvZ.d.ts} +0 -0
- /package/dist/{capture-failure-tracker-gsm8q7yi.d.ts → capture-failure-tracker-_BVfhpxv.d.ts} +0 -0
- /package/dist/{capture-motion-gate-0Yl2NpQG.d.ts → capture-motion-gate-BGoAMkmf.d.ts} +0 -0
- /package/dist/{chromium-camera-access-workaround-D4K2uwwQ.d.ts → chromium-camera-access-workaround-C6yJLXz9.d.ts} +0 -0
- /package/dist/{concurrency-By0oOTZt.d.ts → concurrency-DPeGBH0X.d.ts} +0 -0
- /package/dist/{css3d-renderer-manager-B3kGNtcn.d.ts → css3d-renderer-manager-CPpVtvgs.d.ts} +0 -0
- /package/dist/{failure-tracker-BO7M7jF_.d.ts → failure-tracker-CeKf5HIc.d.ts} +0 -0
- /package/dist/{file-system-utils-DOajnMm-.d.ts → file-system-utils-DueXHxo9.d.ts} +0 -0
- /package/dist/{format-file-size-Dc98ulzB.d.ts → format-file-size-DxN-EBLc.d.ts} +0 -0
- /package/dist/{frame-loop-CpVjQ1dH.d.ts → frame-loop-7GBMBu68.d.ts} +0 -0
- /package/dist/{frustum-visibility-CeoCZchO.d.ts → frustum-visibility-CokkgS_i.d.ts} +0 -0
- /package/dist/{geo-types-3Ip1NzVR.d.ts → geo-types-DrGVu8nS.d.ts} +0 -0
- /package/dist/{gps-BBO3hKfT.d.ts → gps-CDKDQokE.d.ts} +0 -0
- /package/dist/{gps-compass-cubes-DSN87L8p.d.ts → gps-compass-cubes-1mooS3BS.d.ts} +0 -0
- /package/dist/{gps-error-handler-BbPsfw-_.d.ts → gps-error-handler-C34GQuTu.d.ts} +0 -0
- /package/dist/{gps-event-markers-Cz9RMA2k.d.ts → gps-event-markers-Di2nBzx-.d.ts} +0 -0
- /package/dist/{h3-proximity-C-j0pw1j.d.ts → h3-proximity-D0GTHQmr.d.ts} +0 -0
- /package/dist/{hit-test-reticle-DV-2TpB9.d.ts → hit-test-reticle-CaQbrhbk.d.ts} +0 -0
- /package/dist/{image-quality-smCBoFj1.d.ts → image-quality-BMx2ko9-.d.ts} +0 -0
- /package/dist/{index-BAPokxMb.d.ts → index-D74JTX4I.d.ts} +0 -0
- /package/dist/{list-formatter-KNMS0ay2.d.ts → list-formatter-DLFDnS70.d.ts} +0 -0
- /package/dist/{logger-CLnPrHiD.d.ts → logger-CqTd5Kpk.d.ts} +0 -0
- /package/dist/{map-overlay-Dh2B97MP.d.ts → map-overlay-BCQgvIgU.d.ts} +0 -0
- /package/dist/{permission-checker-CDuI8BwC.d.ts → permission-checker-B-VtjnBA.d.ts} +0 -0
- /package/dist/{qr-pose-D2rfu5DA.d.ts → qr-pose-y3vaEd6x.d.ts} +0 -0
- /package/dist/{scene-node-names-BiShOQDB.d.ts → scene-node-names-CGb-ylBd.d.ts} +0 -0
- /package/dist/{session-disposers-zv9OGXPB.js → session-disposers-BPrMplIC.js} +0 -0
- /package/dist/{three-dispose-Bt1k7WKh.d.ts → three-dispose-BMOAmPhb.d.ts} +0 -0
- /package/dist/{vis-colors-Obw2pLqT.d.ts → vis-colors-C7HI0u9_.d.ts} +0 -0
- /package/dist/{webxr-nue-basis-3nfjDJJp.d.ts → webxr-nue-basis-CaCnYxuq.d.ts} +0 -0
- /package/dist/{xr-camera-texture-Cva1q3Qj.d.ts → xr-camera-texture-q0eIDSRg.d.ts} +0 -0
- /package/dist/{xr-error-handler-CtvHpjfm.d.ts → xr-error-handler-uVGDu9IX.d.ts} +0 -0
- /package/dist/{xr-frame-loop-DIYtRcUa.d.ts → xr-frame-loop-DX3JPpAU.d.ts} +0 -0
- /package/dist/{zip-coverage-embed-DCAREVmw.d.ts → zip-coverage-embed-ncVbaZAz.d.ts} +0 -0
- /package/dist/{zip-export-ol0S_Ofd.d.ts → zip-export-CtiUnAlJ.d.ts} +0 -0
|
@@ -1,283 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { VIS_COLORS } from "./vis-colors.js";
|
|
3
|
-
import { drawMapData } from "./map-overlay-draw.js";
|
|
4
|
-
import { CSS3DObject } from "three/addons/renderers/CSS3DRenderer.js";
|
|
5
|
-
import L from "leaflet";
|
|
6
|
-
//#region ../src/visualization/leaflet-map-overlay.ts
|
|
7
|
-
const log = createLogger("LeafletMapOverlay");
|
|
8
|
-
/** Default pixel size of the Leaflet map container */
|
|
9
|
-
const DEFAULT_LEAFLET_MAP_SIZE_PX = 600;
|
|
10
|
-
/**
|
|
11
|
-
* Diameter (px) of the ref-point markers on the in-AR minimap.
|
|
12
|
-
*
|
|
13
|
-
* Enlarged 12 → 20 px (F5-A, 2026-06-16 user feedback): the field tester
|
|
14
|
-
* reported the minimap "showed the user but not the marker". The markers WERE
|
|
15
|
-
* rendered — they were just too small to notice on the small CSS3D minimap. A
|
|
16
|
-
* bigger dot plus a thicker white halo and a drop shadow makes them the most
|
|
17
|
-
* prominent feature on the minimap (the user-position marker stays 14 px).
|
|
18
|
-
*/
|
|
19
|
-
const REF_POINT_MARKER_SIZE_PX = 20;
|
|
20
|
-
/** Default world-space size in meters (matches old MapOverlay) */
|
|
21
|
-
const DEFAULT_WORLD_SIZE = 10;
|
|
22
|
-
/** Default height offset below camera (negative = below) */
|
|
23
|
-
const DEFAULT_HEIGHT_OFFSET = -4;
|
|
24
|
-
/** Default forward offset from parent (negative = forward in parent-local Z) */
|
|
25
|
-
const DEFAULT_Z_OFFSET = -1;
|
|
26
|
-
/** Default zoom level for the Leaflet map */
|
|
27
|
-
const DEFAULT_ZOOM = 17;
|
|
28
|
-
/** Minimum allowed zoom level */
|
|
29
|
-
const MIN_ZOOM = 0;
|
|
30
|
-
/** Maximum allowed zoom level */
|
|
31
|
-
const MAX_ZOOM = 19;
|
|
32
|
-
var LeafletMapOverlay = class {
|
|
33
|
-
scene;
|
|
34
|
-
camera;
|
|
35
|
-
mapParent;
|
|
36
|
-
worldSize;
|
|
37
|
-
heightOffset;
|
|
38
|
-
mapSizePx;
|
|
39
|
-
tileServerUrl;
|
|
40
|
-
onTileError;
|
|
41
|
-
offscreenRoot;
|
|
42
|
-
zoomLevel;
|
|
43
|
-
gpsPosition = null;
|
|
44
|
-
visible = false;
|
|
45
|
-
mapContainer = null;
|
|
46
|
-
leafletMap = null;
|
|
47
|
-
tileLayer = null;
|
|
48
|
-
cssObject = null;
|
|
49
|
-
latestMapData = null;
|
|
50
|
-
trajectoryLayers = [];
|
|
51
|
-
namedMarkers = [];
|
|
52
|
-
constructor(scene, camera, options = {}) {
|
|
53
|
-
this.scene = scene;
|
|
54
|
-
this.camera = camera;
|
|
55
|
-
this.mapParent = options.mapParent ?? camera;
|
|
56
|
-
this.worldSize = options.worldSize ?? 10;
|
|
57
|
-
this.heightOffset = options.heightOffset ?? -4;
|
|
58
|
-
this.mapSizePx = options.mapSizePx ?? 600;
|
|
59
|
-
this.zoomLevel = options.zoomLevel ?? 17;
|
|
60
|
-
this.tileServerUrl = options.tileServerUrl ?? "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
|
|
61
|
-
this.onTileError = options.onTileError;
|
|
62
|
-
this.offscreenRoot = options.offscreenRoot ?? document.body;
|
|
63
|
-
}
|
|
64
|
-
setGpsPosition(lat, lon) {
|
|
65
|
-
this.gpsPosition = {
|
|
66
|
-
lat,
|
|
67
|
-
lon
|
|
68
|
-
};
|
|
69
|
-
if (this.leafletMap) this.leafletMap.setView([lat, lon], this.zoomLevel);
|
|
70
|
-
}
|
|
71
|
-
getGpsPosition() {
|
|
72
|
-
return this.gpsPosition;
|
|
73
|
-
}
|
|
74
|
-
show() {
|
|
75
|
-
if (!this.gpsPosition) {
|
|
76
|
-
log.warn("Cannot show map — no GPS position set");
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (this.visible) return;
|
|
80
|
-
this.createLeafletMap();
|
|
81
|
-
this.createCssObject();
|
|
82
|
-
this.applyBufferedOverlays();
|
|
83
|
-
this.visible = true;
|
|
84
|
-
log.info("Leaflet map overlay shown");
|
|
85
|
-
}
|
|
86
|
-
hide() {
|
|
87
|
-
if (!this.visible) return;
|
|
88
|
-
this.removeCssObject();
|
|
89
|
-
this.visible = false;
|
|
90
|
-
log.info("Leaflet map overlay hidden");
|
|
91
|
-
}
|
|
92
|
-
toggle() {
|
|
93
|
-
if (this.visible) this.hide();
|
|
94
|
-
else this.show();
|
|
95
|
-
}
|
|
96
|
-
isVisible() {
|
|
97
|
-
return this.visible;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Render a full trajectory snapshot.
|
|
101
|
-
*
|
|
102
|
-
* Replaces the previous incremental `addRawGpsPoint` / `addFusedPoint` /
|
|
103
|
-
* `addAlignmentSnapshot` API with a single full-snapshot path: the caller
|
|
104
|
-
* builds a {@link MapData} (via the shared `buildMapData`) from the latest
|
|
105
|
-
* store slices and hands it here. The trajectory layers are redrawn
|
|
106
|
-
* wholesale through the shared {@link drawMapData} routine, so the live map
|
|
107
|
-
* stays pixel-identical to the 2D session-summary map and the fused path
|
|
108
|
-
* recomputes (D2) as the alignment matrix improves.
|
|
109
|
-
*
|
|
110
|
-
* Buffered when the map is not yet shown; applied on `show()`.
|
|
111
|
-
*/
|
|
112
|
-
render(data) {
|
|
113
|
-
this.latestMapData = data;
|
|
114
|
-
if (this.leafletMap) this.drawTrajectory();
|
|
115
|
-
}
|
|
116
|
-
/** Add a "current" named marker (red). Buffered if map is not yet shown. */
|
|
117
|
-
addCurrentMarker(lat, lon, name) {
|
|
118
|
-
const marker = this.leafletMap ? this.createNamedMarker(lat, lon, name, false) : null;
|
|
119
|
-
this.namedMarkers.push({
|
|
120
|
-
lat,
|
|
121
|
-
lng: lon,
|
|
122
|
-
name,
|
|
123
|
-
isPrior: false,
|
|
124
|
-
marker
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
/** Add a "prior" named marker (green, decorated). Buffered if not shown. */
|
|
128
|
-
addPriorMarker(lat, lon, name) {
|
|
129
|
-
const marker = this.leafletMap ? this.createNamedMarker(lat, lon, name, true) : null;
|
|
130
|
-
this.namedMarkers.push({
|
|
131
|
-
lat,
|
|
132
|
-
lng: lon,
|
|
133
|
-
name,
|
|
134
|
-
isPrior: true,
|
|
135
|
-
marker
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
/** Bulk add prior markers. */
|
|
139
|
-
addPriorMarkers(markers) {
|
|
140
|
-
for (const m of markers) this.addPriorMarker(m.lat, m.lon, m.name);
|
|
141
|
-
}
|
|
142
|
-
/** Remove all prior markers; current markers are unaffected. */
|
|
143
|
-
clearPriorMarkers() {
|
|
144
|
-
this.namedMarkers = this.namedMarkers.filter((m) => {
|
|
145
|
-
if (m.isPrior) {
|
|
146
|
-
m.marker?.remove();
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
return true;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
setZoomLevel(zoom) {
|
|
153
|
-
this.zoomLevel = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoom));
|
|
154
|
-
if (this.leafletMap) this.leafletMap.setZoom(this.zoomLevel);
|
|
155
|
-
}
|
|
156
|
-
getZoomLevel() {
|
|
157
|
-
return this.zoomLevel;
|
|
158
|
-
}
|
|
159
|
-
/** Increment zoom level by 1 (clamped at MAX_ZOOM). */
|
|
160
|
-
zoomIn() {
|
|
161
|
-
this.setZoomLevel(this.zoomLevel + 1);
|
|
162
|
-
}
|
|
163
|
-
/** Decrement zoom level by 1 (clamped at MIN_ZOOM). */
|
|
164
|
-
zoomOut() {
|
|
165
|
-
this.setZoomLevel(this.zoomLevel - 1);
|
|
166
|
-
}
|
|
167
|
-
getWorldSize() {
|
|
168
|
-
return this.worldSize;
|
|
169
|
-
}
|
|
170
|
-
getHeightOffset() {
|
|
171
|
-
return this.heightOffset;
|
|
172
|
-
}
|
|
173
|
-
getMapSizePx() {
|
|
174
|
-
return this.mapSizePx;
|
|
175
|
-
}
|
|
176
|
-
/** Expose the Leaflet map instance for testing and advanced usage. */
|
|
177
|
-
getLeafletMap() {
|
|
178
|
-
return this.leafletMap;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* No-op — kept for backward compatibility with the frame-loop call
|
|
182
|
-
* in main.ts. The CSS3DObject is a child of the parent, so Three.js
|
|
183
|
-
* scene graph propagation handles positioning automatically.
|
|
184
|
-
*/
|
|
185
|
-
updatePosition() {}
|
|
186
|
-
dispose() {
|
|
187
|
-
this.hide();
|
|
188
|
-
this.destroyLeafletMap();
|
|
189
|
-
this.latestMapData = null;
|
|
190
|
-
this.trajectoryLayers = [];
|
|
191
|
-
this.namedMarkers = [];
|
|
192
|
-
this.cssObject = null;
|
|
193
|
-
log.info("Leaflet map overlay disposed");
|
|
194
|
-
}
|
|
195
|
-
createLeafletMap() {
|
|
196
|
-
if (this.leafletMap) return;
|
|
197
|
-
this.mapContainer = document.createElement("div");
|
|
198
|
-
this.mapContainer.style.width = `${this.mapSizePx}px`;
|
|
199
|
-
this.mapContainer.style.height = `${this.mapSizePx}px`;
|
|
200
|
-
this.mapContainer.style.background = "white";
|
|
201
|
-
this.mapContainer.style.position = "fixed";
|
|
202
|
-
this.mapContainer.style.left = "-9999px";
|
|
203
|
-
this.mapContainer.style.top = "-9999px";
|
|
204
|
-
this.mapContainer.style.pointerEvents = "none";
|
|
205
|
-
this.offscreenRoot.appendChild(this.mapContainer);
|
|
206
|
-
const pos = this.gpsPosition;
|
|
207
|
-
this.leafletMap = L.map(this.mapContainer, {
|
|
208
|
-
center: [pos.lat, pos.lon],
|
|
209
|
-
zoom: this.zoomLevel,
|
|
210
|
-
zoomControl: false,
|
|
211
|
-
attributionControl: false
|
|
212
|
-
});
|
|
213
|
-
this.tileLayer = L.tileLayer(this.tileServerUrl, { maxZoom: MAX_ZOOM });
|
|
214
|
-
this.tileLayer.on("tileerror", (e) => {
|
|
215
|
-
log.error("Failed to load map tile:", e.error);
|
|
216
|
-
this.onTileError?.(e.error);
|
|
217
|
-
});
|
|
218
|
-
this.tileLayer.addTo(this.leafletMap);
|
|
219
|
-
}
|
|
220
|
-
destroyLeafletMap() {
|
|
221
|
-
for (const layer of this.trajectoryLayers) layer.remove();
|
|
222
|
-
this.trajectoryLayers = [];
|
|
223
|
-
for (const m of this.namedMarkers) {
|
|
224
|
-
m.marker?.remove();
|
|
225
|
-
m.marker = null;
|
|
226
|
-
}
|
|
227
|
-
if (this.leafletMap) {
|
|
228
|
-
this.leafletMap.remove();
|
|
229
|
-
this.leafletMap = null;
|
|
230
|
-
}
|
|
231
|
-
if (this.mapContainer?.parentElement) this.mapContainer.parentElement.removeChild(this.mapContainer);
|
|
232
|
-
this.mapContainer = null;
|
|
233
|
-
this.tileLayer = null;
|
|
234
|
-
}
|
|
235
|
-
createCssObject() {
|
|
236
|
-
if (!this.mapContainer) return;
|
|
237
|
-
if (this.cssObject) {
|
|
238
|
-
this.mapParent.add(this.cssObject);
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
this.mapContainer.style.position = "";
|
|
242
|
-
this.mapContainer.style.left = "";
|
|
243
|
-
this.mapContainer.style.top = "";
|
|
244
|
-
this.cssObject = new CSS3DObject(this.mapContainer);
|
|
245
|
-
const scale = this.worldSize / this.mapSizePx;
|
|
246
|
-
this.cssObject.scale.set(scale, scale, scale);
|
|
247
|
-
this.cssObject.position.set(0, this.heightOffset, -1);
|
|
248
|
-
this.cssObject.rotation.x = -Math.PI / 2;
|
|
249
|
-
this.mapParent.add(this.cssObject);
|
|
250
|
-
}
|
|
251
|
-
removeCssObject() {
|
|
252
|
-
if (this.cssObject) this.mapParent.remove(this.cssObject);
|
|
253
|
-
}
|
|
254
|
-
applyBufferedOverlays() {
|
|
255
|
-
if (!this.leafletMap) return;
|
|
256
|
-
this.drawTrajectory();
|
|
257
|
-
for (const m of this.namedMarkers) if (!m.marker) m.marker = this.createNamedMarker(m.lat, m.lng, m.name, m.isPrior);
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Redraw the trajectory layers from {@link latestMapData} via the shared
|
|
261
|
-
* {@link drawMapData} routine, removing any layers from the previous draw.
|
|
262
|
-
*/
|
|
263
|
-
drawTrajectory() {
|
|
264
|
-
if (!this.leafletMap || !this.latestMapData) return;
|
|
265
|
-
for (const layer of this.trajectoryLayers) layer.remove();
|
|
266
|
-
this.trajectoryLayers = drawMapData(this.leafletMap, this.latestMapData, { showUserPosition: true }).layers;
|
|
267
|
-
}
|
|
268
|
-
createNamedMarker(lat, lon, name, isPrior) {
|
|
269
|
-
const color = isPrior ? VIS_COLORS.PRIOR_REF_POINT.css : VIS_COLORS.CURRENT_REF_POINT.css;
|
|
270
|
-
const opacity = isPrior ? "opacity:0.8;" : "";
|
|
271
|
-
const label = isPrior ? `📌 ${name} (prior)` : name;
|
|
272
|
-
const size = REF_POINT_MARKER_SIZE_PX;
|
|
273
|
-
const anchor = size / 2;
|
|
274
|
-
return L.marker([lat, lon], { icon: L.divIcon({
|
|
275
|
-
className: "",
|
|
276
|
-
html: `<div style="background:${color};width:${size}px;height:${size}px;border-radius:50%;border:3px solid white;box-shadow:0 0 4px rgba(0,0,0,0.7);${opacity}"></div>`,
|
|
277
|
-
iconSize: [size, size],
|
|
278
|
-
iconAnchor: [anchor, anchor]
|
|
279
|
-
}) }).bindPopup(label).addTo(this.leafletMap);
|
|
280
|
-
}
|
|
281
|
-
};
|
|
282
|
-
//#endregion
|
|
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, t as DEFAULT_HEIGHT_OFFSET } from "../leaflet-map-overlay-CBWPvaX9.js";
|
|
283
2
|
export { DEFAULT_HEIGHT_OFFSET, DEFAULT_LEAFLET_MAP_SIZE_PX, DEFAULT_WORLD_SIZE, DEFAULT_ZOOM, DEFAULT_Z_OFFSET, LeafletMapOverlay };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as clampedAlpha, t as DEFAULT_LERP_RATE } from "../lerp-utils-
|
|
2
|
-
export { DEFAULT_LERP_RATE, clampedAlpha };
|
|
1
|
+
import { n as clampedAlpha, r as lerpAngleDeg, t as DEFAULT_LERP_RATE } from "../lerp-utils-Qs8OhumS.js";
|
|
2
|
+
export { DEFAULT_LERP_RATE, clampedAlpha, lerpAngleDeg };
|
|
@@ -11,12 +11,36 @@ const DEFAULT_LERP_RATE = 8;
|
|
|
11
11
|
/**
|
|
12
12
|
* Compute a frame-rate-independent lerp/slerp factor clamped to [0, 1].
|
|
13
13
|
*
|
|
14
|
+
* Both bounds are clamped: the upper bound caps an overlong frame at a full
|
|
15
|
+
* (instant) step, and the lower bound rejects a negative `dt` (system clock
|
|
16
|
+
* adjustment, a frame loop whose timestamp runs backward, or a paused-then-
|
|
17
|
+
* resumed tab). Without the lower clamp a negative `dt` would yield a negative
|
|
18
|
+
* alpha and the angle/quaternion lerp would extrapolate BACKWARD, away from the
|
|
19
|
+
* target — a visible heading/alignment jump.
|
|
20
|
+
*
|
|
14
21
|
* @param lerpRate Speed multiplier (higher = faster convergence).
|
|
15
22
|
* @param dt Delta time in seconds since last frame.
|
|
16
|
-
* @returns The interpolation alpha, guaranteed
|
|
23
|
+
* @returns The interpolation alpha, guaranteed within [0, 1].
|
|
17
24
|
*/
|
|
18
25
|
function clampedAlpha(lerpRate, dt) {
|
|
19
|
-
return Math.min(lerpRate * dt, 1);
|
|
26
|
+
return Math.min(Math.max(lerpRate * dt, 0), 1);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Interpolate between two angles (degrees) along the SHORTEST arc.
|
|
30
|
+
*
|
|
31
|
+
* Used by the heading-up minimap to smooth the map's yaw toward a ~1 Hz target
|
|
32
|
+
* heading every frame without spinning the long way across the 0°/360° seam
|
|
33
|
+
* (e.g. 350° → 10° goes +20° through 0°, not −340° through 180°).
|
|
34
|
+
*
|
|
35
|
+
* @param current Current angle in degrees (any range; normalized internally).
|
|
36
|
+
* @param target Target angle in degrees (any range).
|
|
37
|
+
* @param alpha Interpolation factor — 0 returns `current`, 1 returns `target`.
|
|
38
|
+
* Values outside [0, 1] extrapolate; callers should clamp (see
|
|
39
|
+
* {@link clampedAlpha}).
|
|
40
|
+
* @returns The interpolated angle normalized to `[0, 360)`.
|
|
41
|
+
*/
|
|
42
|
+
function lerpAngleDeg(current, target, alpha) {
|
|
43
|
+
return ((current + (((target - current) % 360 + 540) % 360 - 180) * alpha) % 360 + 360) % 360;
|
|
20
44
|
}
|
|
21
45
|
//#endregion
|
|
22
|
-
export { DEFAULT_LERP_RATE, clampedAlpha };
|
|
46
|
+
export { DEFAULT_LERP_RATE, clampedAlpha, lerpAngleDeg };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as MapDataInput, r as buildMapData, t as MapData } from "../map-data-
|
|
1
|
+
import { n as MapDataInput, r as buildMapData, t as MapData } from "../map-data-CUnTzRIC.js";
|
|
2
2
|
export { MapData, MapDataInput, buildMapData };
|
|
@@ -1,33 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
//#region ../src/visualization/map-data.ts
|
|
3
|
-
/**
|
|
4
|
-
* Build a {@link MapData} snapshot from store-derived inputs.
|
|
5
|
-
*
|
|
6
|
-
* Pure and free of Leaflet/Three dependencies. The fused path is always
|
|
7
|
-
* derived via {@link computeFusedPath} (D2); when the matrix or zero reference
|
|
8
|
-
* is missing it is an empty array.
|
|
9
|
-
*
|
|
10
|
-
* @param input - Optional trajectory slices (see {@link MapDataInput}).
|
|
11
|
-
* @returns A fully-resolved {@link MapData} with all arrays defensively copied.
|
|
12
|
-
*/
|
|
13
|
-
function buildMapData(input) {
|
|
14
|
-
const rawGpsPath = input.rawGpsPath ? [...input.rawGpsPath] : [];
|
|
15
|
-
const alignmentSnapshots = input.alignmentSnapshots ? [...input.alignmentSnapshots] : [];
|
|
16
|
-
const fusedPath = computeFusedPath({
|
|
17
|
-
odometryPositions: input.odometryPositions ?? [],
|
|
18
|
-
alignmentMatrix: input.alignmentMatrix ?? null,
|
|
19
|
-
zeroRef: input.zeroRef ?? null
|
|
20
|
-
});
|
|
21
|
-
const lastRaw = rawGpsPath[rawGpsPath.length - 1];
|
|
22
|
-
return {
|
|
23
|
-
userPosition: input.userPosition !== void 0 ? input.userPosition : lastRaw ? {
|
|
24
|
-
lat: lastRaw.lat,
|
|
25
|
-
lng: lastRaw.lng
|
|
26
|
-
} : null,
|
|
27
|
-
rawGpsPath,
|
|
28
|
-
fusedPath,
|
|
29
|
-
alignmentSnapshots
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
//#endregion
|
|
1
|
+
import { t as buildMapData } from "../map-data-1tF5gcYV.js";
|
|
33
2
|
export { buildMapData };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as MAP_PATH_POLYLINE_OPACITY, c as USER_POSITION_COLOR, i as FUSED_PATH_COLOR, l as drawMapData, n as DrawMapDataOptions, o as MAP_PATH_POLYLINE_WEIGHT, r as DrawnMapData, s as RAW_GPS_COLOR, t as ALIGNMENT_SNAPSHOT_COLOR } from "../map-overlay-draw-
|
|
1
|
+
import { a as MAP_PATH_POLYLINE_OPACITY, c as USER_POSITION_COLOR, i as FUSED_PATH_COLOR, l as drawMapData, n as DrawMapDataOptions, o as MAP_PATH_POLYLINE_WEIGHT, r as DrawnMapData, s as RAW_GPS_COLOR, t as ALIGNMENT_SNAPSHOT_COLOR } from "../map-overlay-draw-6WJeq0Kg.js";
|
|
2
2
|
export { ALIGNMENT_SNAPSHOT_COLOR, DrawMapDataOptions, DrawnMapData, FUSED_PATH_COLOR, MAP_PATH_POLYLINE_OPACITY, MAP_PATH_POLYLINE_WEIGHT, RAW_GPS_COLOR, USER_POSITION_COLOR, drawMapData };
|
|
@@ -18,7 +18,8 @@ import L from "leaflet";
|
|
|
18
18
|
* polyline stays on top), then the raw GPS polyline;
|
|
19
19
|
* 2. the fused (SLAM+GPS) polyline;
|
|
20
20
|
* 3. the alignment-snapshot polyline;
|
|
21
|
-
* 4. (optional) a user-position marker
|
|
21
|
+
* 4. (optional) a user-position marker — a dot plus, when `userHeadingDeg`
|
|
22
|
+
* is set, a thin view-direction line rotated to that true-north bearing.
|
|
22
23
|
*
|
|
23
24
|
* SCOPE: this module draws only the genuinely-shared SLAM/GPS trajectory
|
|
24
25
|
* layers. Reference-point markers are a RECORDER concept and are drawn by the
|
|
@@ -45,6 +46,27 @@ const MAP_PATH_POLYLINE_WEIGHT = 3;
|
|
|
45
46
|
/** Polyline opacity — matches the recorder's `PATH_POLYLINE_OPACITY`. */
|
|
46
47
|
const MAP_PATH_POLYLINE_OPACITY = .8;
|
|
47
48
|
/**
|
|
49
|
+
* Length (px) of the user view-direction line. A FIXED pixel length (not a
|
|
50
|
+
* metric distance): the line is a direction-only indicator drawn inside the
|
|
51
|
+
* user-position divIcon, so it stays the same size at every zoom level.
|
|
52
|
+
* Module-private — internal styling detail, not part of the public surface.
|
|
53
|
+
*/
|
|
54
|
+
const USER_HEADING_LINE_LENGTH_PX = 28;
|
|
55
|
+
/**
|
|
56
|
+
* Build the inner HTML for the user-position divIcon: a centered dot, plus —
|
|
57
|
+
* when `headingDeg` is a finite bearing — a thin line rotated to that absolute
|
|
58
|
+
* (true-north) heading. The line lives in a zero-size wrapper centered on the
|
|
59
|
+
* dot and rotated by CSS, so North (0°) points up and the line keeps a fixed
|
|
60
|
+
* pixel length regardless of map zoom. A null/undefined/non-finite heading
|
|
61
|
+
* yields the dot alone (Finding 2: fallback when the camera is near-vertical or
|
|
62
|
+
* before the first alignment solve).
|
|
63
|
+
*/
|
|
64
|
+
function buildUserMarkerHtml(headingDeg) {
|
|
65
|
+
const dot = `<div style="position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background:${USER_POSITION_COLOR};width:14px;height:14px;border-radius:50%;border:2px solid white;"></div>`;
|
|
66
|
+
if (typeof headingDeg !== "number" || !Number.isFinite(headingDeg)) return dot;
|
|
67
|
+
return `${`<div style="position:absolute;left:50%;top:50%;transform:rotate(${headingDeg}deg);"><div class="map-overlay-user-heading" style="position:absolute;left:-1px;bottom:0;width:2px;height:${USER_HEADING_LINE_LENGTH_PX}px;background:${USER_POSITION_COLOR};"></div></div>`}${dot}`;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
48
70
|
* Draw a {@link MapData} snapshot onto an existing Leaflet map.
|
|
49
71
|
*
|
|
50
72
|
* @param map - Target map (already created with a tile layer by the caller).
|
|
@@ -90,7 +112,7 @@ function drawMapData(map, data, options = {}) {
|
|
|
90
112
|
if (options.showUserPosition && data.userPosition) {
|
|
91
113
|
const icon = L.divIcon({
|
|
92
114
|
className: "map-overlay-user-position",
|
|
93
|
-
html:
|
|
115
|
+
html: buildUserMarkerHtml(data.userHeadingDeg),
|
|
94
116
|
iconSize: [18, 18],
|
|
95
117
|
iconAnchor: [9, 9]
|
|
96
118
|
});
|
|
@@ -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-BCQgvIgU.js";
|
|
2
2
|
export { DEFAULT_HEIGHT_OFFSET, DEFAULT_MAP_SIZE, DEFAULT_ZOOM, MapOverlay, MapOverlayOptions, TextureLoaderInterface, latLonToTileXY, tileXYToLatLon };
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { t as GridCell } from "../bresenham3d-DGc4nIb-.js";
|
|
2
|
+
import { n as MeshMode } from "../occupancy-mesher-C2ecWhNp.js";
|
|
3
|
+
import { MeshWorkerRequest, MeshWorkerResponse } from "../ar/occlusion-mesh-worker.js";
|
|
4
|
+
import { Vector3 } from "gps-plus-slam-js";
|
|
5
|
+
|
|
6
|
+
//#region ../src/visualization/occluder-mesh-driver.d.ts
|
|
7
|
+
/** Called with the meshed geometry (typed arrays) when a job completes. */
|
|
8
|
+
type OnMesh = (positions: Float32Array, indices: Uint32Array) => void;
|
|
9
|
+
/**
|
|
10
|
+
* Timing/size stats for one completed mesh job — the freshness instrumentation
|
|
11
|
+
* for the Phase-2 gate (see the plan's §"Next step"): `durationMs` is the
|
|
12
|
+
* wall-clock time from posting the job (including packing already done by then)
|
|
13
|
+
* to receiving its geometry, i.e. the occluder's current refresh latency.
|
|
14
|
+
* Failed jobs report nothing (they surface via
|
|
15
|
+
* {@link OccluderMeshDriverOptions.onError}).
|
|
16
|
+
*/
|
|
17
|
+
interface OccluderMeshStats {
|
|
18
|
+
/** Wall-clock ms from post to delivered geometry (inline time on the sync path). */
|
|
19
|
+
readonly durationMs: number;
|
|
20
|
+
/** Number of occupied cells the mesh was built from. */
|
|
21
|
+
readonly cellCount: number;
|
|
22
|
+
readonly mode: MeshMode;
|
|
23
|
+
/** True when meshed inline on the main thread (fallback), false when off-thread. */
|
|
24
|
+
readonly synchronous: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The minimal `Worker`-like surface the driver needs. A consumer adapts a real
|
|
28
|
+
* `Worker`: forwards `worker.onmessage` → `poster.onmessage` and
|
|
29
|
+
* `worker.onerror` / `worker.onmessageerror` → `poster.onerror` (so the driver
|
|
30
|
+
* can recover from a worker that never replies).
|
|
31
|
+
*/
|
|
32
|
+
interface MeshWorkerPoster {
|
|
33
|
+
postMessage(message: MeshWorkerRequest, transfer: ArrayBufferLike[]): void;
|
|
34
|
+
onmessage: ((event: {
|
|
35
|
+
data: MeshWorkerResponse;
|
|
36
|
+
}) => void) | null;
|
|
37
|
+
/** Fired when the worker errors (uncaught throw or module load failure). */
|
|
38
|
+
onerror: ((error?: unknown) => void) | null;
|
|
39
|
+
}
|
|
40
|
+
/** Optional driver callbacks (logging + worker-teardown seams). */
|
|
41
|
+
interface OccluderMeshDriverOptions {
|
|
42
|
+
/**
|
|
43
|
+
* Called once when the driver gives up on the worker and switches to
|
|
44
|
+
* synchronous meshing (the worker errored before ever producing a mesh —
|
|
45
|
+
* almost always a module that failed to load). The consumer should terminate
|
|
46
|
+
* the now-dead worker.
|
|
47
|
+
*/
|
|
48
|
+
onWorkerUnusable?: () => void;
|
|
49
|
+
/**
|
|
50
|
+
* Called with any error that aborts a job — a worker error event, or a throw
|
|
51
|
+
* from synchronous meshing — so the consumer can log it. Optional; if absent
|
|
52
|
+
* the error is swallowed (the frame is dropped, the driver stays healthy).
|
|
53
|
+
*/
|
|
54
|
+
onError?: (error: unknown) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Called with {@link OccluderMeshStats} each time a job completes (fires just
|
|
57
|
+
* before the job's geometry callback). Optional logging seam so the consumer
|
|
58
|
+
* can surface mesh duration + input size per refresh.
|
|
59
|
+
*/
|
|
60
|
+
onMeshStats?: (stats: OccluderMeshStats) => void;
|
|
61
|
+
/**
|
|
62
|
+
* Injectable monotonic clock in ms for {@link OccluderMeshStats.durationMs}
|
|
63
|
+
* (tests); defaults to `performance.now()`.
|
|
64
|
+
*/
|
|
65
|
+
now?: () => number;
|
|
66
|
+
}
|
|
67
|
+
declare class OccluderMeshDriver {
|
|
68
|
+
private readonly poster;
|
|
69
|
+
private readonly onWorkerUnusable?;
|
|
70
|
+
private readonly onError?;
|
|
71
|
+
private readonly onMeshStats?;
|
|
72
|
+
private readonly now;
|
|
73
|
+
private nextId;
|
|
74
|
+
private inFlightId;
|
|
75
|
+
private inFlightCallback;
|
|
76
|
+
/** Timing/size context of the in-flight job; cleared on completion/failure. */
|
|
77
|
+
private inFlightStats;
|
|
78
|
+
private pending;
|
|
79
|
+
private disposed;
|
|
80
|
+
/** True ⇒ mesh inline (no worker, or the worker was declared unusable). */
|
|
81
|
+
private syncMode;
|
|
82
|
+
/** Set once the worker returns a mesh — distinguishes a transient error from a load failure. */
|
|
83
|
+
private hasSucceeded;
|
|
84
|
+
/**
|
|
85
|
+
* @param poster a worker adapter, or `null` for synchronous main-thread meshing.
|
|
86
|
+
* @param options optional {@link OccluderMeshDriverOptions.onWorkerUnusable} /
|
|
87
|
+
* {@link OccluderMeshDriverOptions.onError} callbacks.
|
|
88
|
+
*/
|
|
89
|
+
constructor(poster: MeshWorkerPoster | null, options?: OccluderMeshDriverOptions);
|
|
90
|
+
/** True while a mesh job is being computed (worker path only). */
|
|
91
|
+
get busy(): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Request a mesh of `cells` (tuple array, or a flat Int32Array snapshot —
|
|
94
|
+
* see `packMeshRequest`; a flat snapshot's buffer is transferred/detached,
|
|
95
|
+
* so pass a fresh array). If a job is already in flight, this becomes the
|
|
96
|
+
* (single) pending job — the newest request wins; intermediates are dropped.
|
|
97
|
+
* `getCellPoint` is invoked with a transient cell tuple that may be a reused
|
|
98
|
+
* scratch — it must not retain the tuple beyond the call (see
|
|
99
|
+
* `MeshOccupiedCellsOptions.getCellPoint`).
|
|
100
|
+
*/
|
|
101
|
+
request(cells: readonly GridCell[] | Int32Array, cellSizeM: number, mode: MeshMode, getCellPoint: ((cell: GridCell) => Vector3 | null) | undefined, onMesh: OnMesh): void;
|
|
102
|
+
private post;
|
|
103
|
+
private handleResponse;
|
|
104
|
+
/**
|
|
105
|
+
* A worker error event. If a job is in flight, recover it (only one ever is).
|
|
106
|
+
* If none is — the realistic ordering for a **module-load failure**, which
|
|
107
|
+
* errors within a few ms of construction, before the first (throttled)
|
|
108
|
+
* `request` posts anything — the worker is dead: posting to it would be
|
|
109
|
+
* silently dropped (no second error) and wedge the in-flight slot forever. So
|
|
110
|
+
* a pre-first-post error on a worker that has **never** succeeded is treated as
|
|
111
|
+
* a load failure right here — declare it unusable and switch to synchronous
|
|
112
|
+
* meshing so the first `request` never touches the dead worker. A stray/late
|
|
113
|
+
* error on a worker that has already meshed once is transient — kept, ignored.
|
|
114
|
+
*/
|
|
115
|
+
private handleWorkerError;
|
|
116
|
+
/**
|
|
117
|
+
* Clear a failed in-flight job so the driver never wedges. If the worker had
|
|
118
|
+
* never produced a mesh (almost always a module load failure) fall back to
|
|
119
|
+
* synchronous meshing — unless `workerAtFault` is false (a pack-time error in
|
|
120
|
+
* the caller's `getCellPoint`, which never reached the worker). Then re-post
|
|
121
|
+
* the pending snapshot if one is queued. We deliberately do NOT re-post the
|
|
122
|
+
* *failed* job: if it failed on deterministic bad data, re-posting would
|
|
123
|
+
* loop — the next refresh brings a fresh snapshot.
|
|
124
|
+
*/
|
|
125
|
+
private failInFlight;
|
|
126
|
+
/** Stop delivering results (detaches the worker handlers; drops any pending). */
|
|
127
|
+
dispose(): void;
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
export { MeshWorkerPoster, OccluderMeshDriver, OccluderMeshDriverOptions, OccluderMeshStats, OnMesh };
|