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.
Files changed (238) hide show
  1. package/dist/{accuracy-circles-BtqOP_v1.d.ts → accuracy-circles-DkWBkF5g.d.ts} +16 -6
  2. package/dist/{app-selectors-ikTUQZpe.d.ts → app-selectors-BbAiCRUT.d.ts} +1 -1
  3. package/dist/ar/bresenham3d.d.ts +1 -1
  4. package/dist/ar/camera-blit-capture.d.ts +1 -1
  5. package/dist/ar/capability-checker.d.ts +1 -1
  6. package/dist/ar/capture-failure-tracker.d.ts +1 -1
  7. package/dist/ar/chromium-camera-access-workaround.d.ts +1 -1
  8. package/dist/ar/depth-grid-lookup.d.ts +1 -1
  9. package/dist/ar/depth-occluder.d.ts +127 -0
  10. package/dist/ar/depth-occluder.js +299 -0
  11. package/dist/ar/depth-sampler.d.ts +2 -2
  12. package/dist/ar/depth-sampler.js +24 -4
  13. package/dist/ar/depth-unprojection.d.ts +1 -1
  14. package/dist/ar/depth-unprojection.js +52 -21
  15. package/dist/ar/enable-gps-ar.d.ts +1 -1
  16. package/dist/ar/enable-gps-ar.js +1 -1
  17. package/dist/ar/frame-loop.d.ts +1 -1
  18. package/dist/ar/frame-loop.js +12 -2
  19. package/dist/ar/image-capture.d.ts +1 -1
  20. package/dist/ar/image-capture.js +1 -1
  21. package/dist/ar/image-quality.d.ts +1 -1
  22. package/dist/ar/image-quality.js +2 -1
  23. package/dist/ar/index.d.ts +32 -31
  24. package/dist/ar/index.js +5 -4
  25. package/dist/ar/occlusion-mesh-worker.d.ts +58 -0
  26. package/dist/ar/occlusion-mesh-worker.js +129 -0
  27. package/dist/ar/occupancy-grid.d.ts +2 -2
  28. package/dist/ar/occupancy-grid.js +287 -31
  29. package/dist/ar/occupancy-mesher.d.ts +2 -0
  30. package/dist/ar/occupancy-mesher.js +638 -0
  31. package/dist/ar/planar-pnp.d.ts +1 -1
  32. package/dist/ar/qr-debug-view.d.ts +1 -1
  33. package/dist/ar/qr-derived-pose.d.ts +1 -1
  34. package/dist/ar/qr-detection-controller.d.ts +1 -1
  35. package/dist/ar/qr-frontend.d.ts +1 -1
  36. package/dist/ar/qr-pose.d.ts +1 -1
  37. package/dist/ar/qr-size-depth-context.d.ts +2 -2
  38. package/dist/ar/qr-size-measurer.d.ts +1 -1
  39. package/dist/ar/replay-scene.d.ts +1 -1
  40. package/dist/ar/replay-scene.js +1 -1
  41. package/dist/ar/scene-node-names.d.ts +1 -1
  42. package/dist/ar/webxr-nue-basis.d.ts +1 -1
  43. package/dist/ar/webxr-session.d.ts +4 -4
  44. package/dist/ar/webxr-session.js +2 -2
  45. package/dist/ar/xr-camera-texture.d.ts +1 -1
  46. package/dist/ar/xr-error-handler.d.ts +1 -1
  47. package/dist/ar/xr-frame-loop.d.ts +1 -1
  48. package/dist/ar/xr-frame-loop.js +12 -2
  49. package/dist/{ar-MFpFlV7j.js → ar-BqCudtqE.js} +3 -2
  50. package/dist/{ar-world-group-alignment-69fgnB39.d.ts → ar-world-group-alignment-Cfg0trC3.d.ts} +1 -1
  51. package/dist/{capture-motion-gate-4EscNZCw.js → capture-motion-gate-_NdTSwKi.js} +17 -5
  52. package/dist/cell-key-DIB4rOTV.js +51 -0
  53. package/dist/core/index.d.ts +2 -2
  54. package/dist/core/index.js +2 -2
  55. package/dist/{create-slam-app-store-n_VF63D5.d.ts → create-slam-app-store-D1QSMuKu.d.ts} +8 -9
  56. package/dist/{create-slam-app-store-DkCHOpvb.js → create-slam-app-store-DXiAnJwR.js} +9 -2
  57. package/dist/{depth-grid-lookup-DQ-IYhO3.d.ts → depth-grid-lookup-D5atpNZ3.d.ts} +1 -1
  58. package/dist/{depth-sampler-asc8exHt.d.ts → depth-sampler-CwObAwEA.d.ts} +33 -1
  59. package/dist/{depth-unprojection-DjsbJW9L.d.ts → depth-unprojection-DRdBU90S.d.ts} +1 -1
  60. package/dist/{enable-gps-ar-DkNhFv4Y.d.ts → enable-gps-ar-BBtRO2FJ.d.ts} +4 -4
  61. package/dist/{frame-conversions-DObhj8Wf.d.ts → frame-conversions-DDcNHkTb.d.ts} +1 -1
  62. package/dist/{fused-path-v6eOmLl3.d.ts → fused-path-C5pp0PJU.d.ts} +1 -1
  63. package/dist/geo/h3-proximity.d.ts +1 -1
  64. package/dist/geo/index.d.ts +1 -1
  65. package/dist/{gps-anchor-BeFO2RYa.d.ts → gps-anchor-CEjGqEVD.d.ts} +1 -1
  66. package/dist/{gps-ar-pose-sampler-DHMZmYAc.d.ts → gps-ar-pose-sampler-DEGNk2CI.d.ts} +1 -1
  67. package/dist/{gps-event-coordinator-CjWW636x.d.ts → gps-event-coordinator-BWpgBrHq.d.ts} +4 -4
  68. package/dist/{image-capture-CNZDrQXG.d.ts → image-capture-Bp6Pd4Md.d.ts} +3 -3
  69. package/dist/{image-capture-B2-b6tKK.js → image-capture-DVcuqMtX.js} +1 -1
  70. package/dist/{index-BODDUTvD.d.ts → index-B6iBnO_K.d.ts} +1 -1
  71. package/dist/index-DXPVzOpP.d.ts +2 -0
  72. package/dist/{index-BneSj4_5.d.ts → index-cCQWuYqy.d.ts} +3 -3
  73. package/dist/index.d.ts +82 -80
  74. package/dist/index.js +10 -8
  75. package/dist/{leaflet-map-overlay-CmIyiE8n.d.ts → leaflet-map-overlay-C8GS4cUy.d.ts} +64 -10
  76. package/dist/leaflet-map-overlay-CBWPvaX9.js +452 -0
  77. package/dist/lerp-utils-Qs8OhumS.d.ts +42 -0
  78. package/dist/map-data-1tF5gcYV.js +124 -0
  79. package/dist/map-data-CUnTzRIC.d.ts +78 -0
  80. package/dist/{map-overlay-draw-ymz1s7fG.d.ts → map-overlay-draw-6WJeq0Kg.d.ts} +1 -1
  81. package/dist/{null-storage-backend-B9rtyDfG.d.ts → null-storage-backend-B1-jlpin.d.ts} +2 -2
  82. package/dist/occlusion-mesh-kXCQ2FM1.d.ts +194 -0
  83. package/dist/occupancy-grid-BV7RhB7I.d.ts +194 -0
  84. package/dist/occupancy-mesher-C2ecWhNp.d.ts +100 -0
  85. package/dist/{opfs-storage-3VZh-qH6.d.ts → opfs-storage-CTkxvxN4.d.ts} +5 -0
  86. package/dist/{opfs-storage-backend-JJiUJo-3.d.ts → opfs-storage-backend-D6Z03fML.d.ts} +2 -2
  87. package/dist/{persistence-middleware-DAPTTwB2.d.ts → persistence-middleware-CG-t08X4.d.ts} +1 -1
  88. package/dist/{planar-pnp-my9bqULS.d.ts → planar-pnp-D7bc_rLX.d.ts} +1 -1
  89. package/dist/{qr-debug-view-Brl73HGO.d.ts → qr-debug-view-BJooqbiP.d.ts} +1 -1
  90. package/dist/{qr-derived-pose-CmxTP2m4.d.ts → qr-derived-pose-BwNWn8oV.d.ts} +2 -2
  91. package/dist/{qr-detected-slice-VQssZmQJ.d.ts → qr-detected-slice-TzVb8bij.d.ts} +4 -4
  92. package/dist/{qr-detection-controller-CDurHv8E.d.ts → qr-detection-controller-Bo4XfQTP.d.ts} +3 -3
  93. package/dist/{qr-frontend--fFX25mV.d.ts → qr-frontend-BPURlh3S.d.ts} +1 -1
  94. package/dist/{qr-pose-aggregation-B7tWJq7j.d.ts → qr-pose-aggregation-CypnmjA-.d.ts} +1 -1
  95. package/dist/{qr-size-depth-context-CeAG53fy.d.ts → qr-size-depth-context-apAOmbrZ.d.ts} +2 -2
  96. package/dist/{qr-size-measurer-DQdAsid1.d.ts → qr-size-measurer-DxiMqRUw.d.ts} +3 -3
  97. package/dist/{recording-options-BPCpMHLK.d.ts → recording-options-DYKWVI93.d.ts} +203 -24
  98. package/dist/{recording-replayer-DQKpAGyQ.d.ts → recording-replayer-BJ8Lf0QY.d.ts} +2 -2
  99. package/dist/{recording-slice-DaxHZvNu.d.ts → recording-slice-BW8SiLo1.d.ts} +2 -2
  100. package/dist/{replay-engine-CmKh_4wf.d.ts → replay-engine-DmCAc7WM.d.ts} +1 -1
  101. package/dist/{replay-scene-DBlDrV_x.d.ts → replay-scene-zJ8SFDjE.d.ts} +3 -3
  102. package/dist/sensors/absolute-orientation.d.ts +1 -1
  103. package/dist/sensors/absolute-orientation.js +23 -6
  104. package/dist/sensors/gps-error-handler.d.ts +1 -1
  105. package/dist/sensors/gps.d.ts +1 -1
  106. package/dist/sensors/index.d.ts +4 -4
  107. package/dist/sensors/permission-checker.d.ts +1 -1
  108. package/dist/state/app-selectors.d.ts +1 -1
  109. package/dist/state/combined-root-state.d.ts +1 -1
  110. package/dist/state/create-slam-app-store.d.ts +1 -1
  111. package/dist/state/create-slam-app-store.js +1 -1
  112. package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
  113. package/dist/state/gps-event-coordinator.d.ts +1 -1
  114. package/dist/state/index.d.ts +19 -19
  115. package/dist/state/index.js +2 -2
  116. package/dist/state/persistence-middleware.d.ts +1 -1
  117. package/dist/state/qr-detected-slice.d.ts +3 -3
  118. package/dist/state/recording-options.d.ts +2 -2
  119. package/dist/state/recording-options.js +150 -19
  120. package/dist/state/recording-replayer.d.ts +2 -2
  121. package/dist/state/recording-replayer.js +1 -1
  122. package/dist/state/recording-slice.d.ts +1 -1
  123. package/dist/state/replay-engine.d.ts +1 -1
  124. package/dist/state/store-subscribers.d.ts +2 -2
  125. package/dist/state/store-subscribers.js +26 -12
  126. package/dist/state/subscribe-to-selector.d.ts +1 -1
  127. package/dist/state/tracking-quality.d.ts +1 -1
  128. package/dist/state/tracking-quality.js +14 -6
  129. package/dist/state/tracking-slice.d.ts +1 -1
  130. package/dist/{state-E51QT_-j.js → state-BeKvn4B-.js} +1 -1
  131. package/dist/storage/file-system-utils.d.ts +1 -1
  132. package/dist/storage/index.d.ts +8 -8
  133. package/dist/storage/null-storage-backend.d.ts +1 -1
  134. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  135. package/dist/storage/opfs-storage.d.ts +1 -1
  136. package/dist/storage/opfs-storage.js +30 -1
  137. package/dist/storage/storage-backend.d.ts +1 -1
  138. package/dist/storage/zip-coverage-embed.d.ts +1 -1
  139. package/dist/storage/zip-export.d.ts +1 -1
  140. package/dist/storage/zip-reader.d.ts +2 -2
  141. package/dist/storage/zip-reader.js +20 -7
  142. package/dist/{storage-backend-BdVLD0dU.d.ts → storage-backend-sEtmM4yW.d.ts} +1 -1
  143. package/dist/{store-subscribers-CA6AJH_8.d.ts → store-subscribers-DJUErW-o.d.ts} +6 -3
  144. package/dist/{subscribe-to-selector-B6EUmQ3I.d.ts → subscribe-to-selector-dQV8SpsO.d.ts} +1 -1
  145. package/dist/test-utils/browser-mocks.d.ts +1 -1
  146. package/dist/test-utils/browser-mocks.js +2 -0
  147. package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
  148. package/dist/{tracking-slice-BuAZxXZ5.d.ts → tracking-slice-DMkHlbny.d.ts} +1 -1
  149. package/dist/types/ar-types.d.ts +1 -1
  150. package/dist/types/geo-types.d.ts +1 -1
  151. package/dist/types/index.d.ts +2 -2
  152. package/dist/utils/concurrency.d.ts +1 -1
  153. package/dist/utils/failure-tracker.d.ts +1 -1
  154. package/dist/utils/format-file-size.d.ts +1 -1
  155. package/dist/utils/fused-path.d.ts +1 -1
  156. package/dist/utils/index.d.ts +7 -7
  157. package/dist/utils/list-formatter.d.ts +1 -1
  158. package/dist/utils/logger.d.ts +1 -1
  159. package/dist/visualization/accuracy-circles.d.ts +1 -1
  160. package/dist/visualization/accuracy-circles.js +17 -8
  161. package/dist/visualization/alignment-lerper.d.ts +1 -1
  162. package/dist/visualization/ar-world-group-alignment.d.ts +1 -1
  163. package/dist/visualization/ar-world-group-alignment.js +1 -1
  164. package/dist/visualization/camera-follower.d.ts +1 -1
  165. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  166. package/dist/visualization/frame-conversions.d.ts +1 -1
  167. package/dist/visualization/frustum-visibility.d.ts +1 -1
  168. package/dist/visualization/gps-anchor.d.ts +1 -1
  169. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  170. package/dist/visualization/gps-event-markers.d.ts +1 -1
  171. package/dist/visualization/gps-event-markers.js +1 -1
  172. package/dist/visualization/hit-test-reticle.d.ts +1 -1
  173. package/dist/visualization/index.d.ts +20 -19
  174. package/dist/visualization/index.js +4 -3
  175. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  176. package/dist/visualization/leaflet-map-overlay.js +1 -282
  177. package/dist/visualization/lerp-utils.d.ts +2 -2
  178. package/dist/visualization/lerp-utils.js +27 -3
  179. package/dist/visualization/map-data.d.ts +1 -1
  180. package/dist/visualization/map-data.js +1 -32
  181. package/dist/visualization/map-overlay-draw.d.ts +1 -1
  182. package/dist/visualization/map-overlay-draw.js +24 -2
  183. package/dist/visualization/map-overlay.d.ts +1 -1
  184. package/dist/visualization/occluder-mesh-driver.d.ts +130 -0
  185. package/dist/visualization/occluder-mesh-driver.js +219 -0
  186. package/dist/visualization/occlusion-mesh.d.ts +2 -0
  187. package/dist/visualization/occlusion-mesh.js +437 -0
  188. package/dist/visualization/three-dispose.d.ts +1 -1
  189. package/dist/visualization/vis-colors.d.ts +1 -1
  190. package/dist/{webxr-session-DG-eNfny.js → webxr-session-BCP2XK7k.js} +88 -13
  191. package/dist/{webxr-session-Do5L6G3B.d.ts → webxr-session-BWCpGd-2.d.ts} +73 -10
  192. package/dist/{zip-reader-D9iPQwdQ.d.ts → zip-reader-BzENzMH6.d.ts} +36 -10
  193. package/package.json +9 -5
  194. package/dist/index-_Rhgoqkh.d.ts +0 -2
  195. package/dist/lerp-utils-BLmHhkVe.d.ts +0 -20
  196. package/dist/map-data-B4oEehUh.d.ts +0 -49
  197. package/dist/occupancy-grid-DnOc-6PU.d.ts +0 -82
  198. /package/dist/{absolute-orientation-CAEh840t.d.ts → absolute-orientation-BAxc15J6.d.ts} +0 -0
  199. /package/dist/{alignment-lerper-Bil6vbVw.d.ts → alignment-lerper-gD70k7Fq.d.ts} +0 -0
  200. /package/dist/{ar-types-BFX2r1wk.d.ts → ar-types-Cc5yvBwn.d.ts} +0 -0
  201. /package/dist/{bresenham3d-CU1Gv2W4.d.ts → bresenham3d-DGc4nIb-.d.ts} +0 -0
  202. /package/dist/{camera-blit-capture-NKT9H5-e.d.ts → camera-blit-capture-BimSdyih.d.ts} +0 -0
  203. /package/dist/{camera-follower-CqJJ7zRj.d.ts → camera-follower-DfBm2J5i.d.ts} +0 -0
  204. /package/dist/{capability-checker-DUQLg6gq.d.ts → capability-checker-BTTpygvZ.d.ts} +0 -0
  205. /package/dist/{capture-failure-tracker-gsm8q7yi.d.ts → capture-failure-tracker-_BVfhpxv.d.ts} +0 -0
  206. /package/dist/{capture-motion-gate-0Yl2NpQG.d.ts → capture-motion-gate-BGoAMkmf.d.ts} +0 -0
  207. /package/dist/{chromium-camera-access-workaround-D4K2uwwQ.d.ts → chromium-camera-access-workaround-C6yJLXz9.d.ts} +0 -0
  208. /package/dist/{concurrency-By0oOTZt.d.ts → concurrency-DPeGBH0X.d.ts} +0 -0
  209. /package/dist/{css3d-renderer-manager-B3kGNtcn.d.ts → css3d-renderer-manager-CPpVtvgs.d.ts} +0 -0
  210. /package/dist/{failure-tracker-BO7M7jF_.d.ts → failure-tracker-CeKf5HIc.d.ts} +0 -0
  211. /package/dist/{file-system-utils-DOajnMm-.d.ts → file-system-utils-DueXHxo9.d.ts} +0 -0
  212. /package/dist/{format-file-size-Dc98ulzB.d.ts → format-file-size-DxN-EBLc.d.ts} +0 -0
  213. /package/dist/{frame-loop-CpVjQ1dH.d.ts → frame-loop-7GBMBu68.d.ts} +0 -0
  214. /package/dist/{frustum-visibility-CeoCZchO.d.ts → frustum-visibility-CokkgS_i.d.ts} +0 -0
  215. /package/dist/{geo-types-3Ip1NzVR.d.ts → geo-types-DrGVu8nS.d.ts} +0 -0
  216. /package/dist/{gps-BBO3hKfT.d.ts → gps-CDKDQokE.d.ts} +0 -0
  217. /package/dist/{gps-compass-cubes-DSN87L8p.d.ts → gps-compass-cubes-1mooS3BS.d.ts} +0 -0
  218. /package/dist/{gps-error-handler-BbPsfw-_.d.ts → gps-error-handler-C34GQuTu.d.ts} +0 -0
  219. /package/dist/{gps-event-markers-Cz9RMA2k.d.ts → gps-event-markers-Di2nBzx-.d.ts} +0 -0
  220. /package/dist/{h3-proximity-C-j0pw1j.d.ts → h3-proximity-D0GTHQmr.d.ts} +0 -0
  221. /package/dist/{hit-test-reticle-DV-2TpB9.d.ts → hit-test-reticle-CaQbrhbk.d.ts} +0 -0
  222. /package/dist/{image-quality-smCBoFj1.d.ts → image-quality-BMx2ko9-.d.ts} +0 -0
  223. /package/dist/{index-BAPokxMb.d.ts → index-D74JTX4I.d.ts} +0 -0
  224. /package/dist/{list-formatter-KNMS0ay2.d.ts → list-formatter-DLFDnS70.d.ts} +0 -0
  225. /package/dist/{logger-CLnPrHiD.d.ts → logger-CqTd5Kpk.d.ts} +0 -0
  226. /package/dist/{map-overlay-Dh2B97MP.d.ts → map-overlay-BCQgvIgU.d.ts} +0 -0
  227. /package/dist/{permission-checker-CDuI8BwC.d.ts → permission-checker-B-VtjnBA.d.ts} +0 -0
  228. /package/dist/{qr-pose-D2rfu5DA.d.ts → qr-pose-y3vaEd6x.d.ts} +0 -0
  229. /package/dist/{scene-node-names-BiShOQDB.d.ts → scene-node-names-CGb-ylBd.d.ts} +0 -0
  230. /package/dist/{session-disposers-zv9OGXPB.js → session-disposers-BPrMplIC.js} +0 -0
  231. /package/dist/{three-dispose-Bt1k7WKh.d.ts → three-dispose-BMOAmPhb.d.ts} +0 -0
  232. /package/dist/{vis-colors-Obw2pLqT.d.ts → vis-colors-C7HI0u9_.d.ts} +0 -0
  233. /package/dist/{webxr-nue-basis-3nfjDJJp.d.ts → webxr-nue-basis-CaCnYxuq.d.ts} +0 -0
  234. /package/dist/{xr-camera-texture-Cva1q3Qj.d.ts → xr-camera-texture-q0eIDSRg.d.ts} +0 -0
  235. /package/dist/{xr-error-handler-CtvHpjfm.d.ts → xr-error-handler-uVGDu9IX.d.ts} +0 -0
  236. /package/dist/{xr-frame-loop-DIYtRcUa.d.ts → xr-frame-loop-DX3JPpAU.d.ts} +0 -0
  237. /package/dist/{zip-coverage-embed-DCAREVmw.d.ts → zip-coverage-embed-ncVbaZAz.d.ts} +0 -0
  238. /package/dist/{zip-export-ol0S_Ofd.d.ts → zip-export-CtiUnAlJ.d.ts} +0 -0
@@ -1,283 +1,2 @@
1
- import { createLogger } from "../utils/logger.js";
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-BLmHhkVe.js";
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 1.0.
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-B4oEehUh.js";
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 { computeFusedPath } from "../utils/fused-path.js";
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-ymz1s7fG.js";
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: `<div style="background:${USER_POSITION_COLOR};width:14px;height:14px;border-radius:50%;border:2px solid white;"></div>`,
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-Dh2B97MP.js";
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 };