gps-plus-slam-app-framework 1.3.0 → 1.7.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 (247) hide show
  1. package/dist/absolute-orientation-CAEh840t.d.ts +54 -0
  2. package/dist/{app-selectors-B8VQoMDY.d.ts → app-selectors-ikTUQZpe.d.ts} +1 -1
  3. package/dist/ar/bresenham3d.d.ts +1 -1
  4. package/dist/ar/camera-blit-capture.d.ts +2 -2
  5. package/dist/ar/camera-blit-capture.js +74 -9
  6. package/dist/ar/capability-checker.d.ts +1 -1
  7. package/dist/ar/capture-failure-tracker.d.ts +1 -1
  8. package/dist/ar/chromium-camera-access-workaround.d.ts +1 -1
  9. package/dist/ar/depth-grid-lookup.d.ts +2 -0
  10. package/dist/ar/depth-grid-lookup.js +43 -0
  11. package/dist/ar/depth-sampler.d.ts +2 -2
  12. package/dist/ar/depth-sampler.js +2 -4
  13. package/dist/ar/depth-unprojection.d.ts +1 -1
  14. package/dist/ar/enable-gps-ar.d.ts +1 -1
  15. package/dist/ar/enable-gps-ar.js +26 -1
  16. package/dist/ar/frame-loop.d.ts +1 -1
  17. package/dist/ar/image-capture.d.ts +2 -2
  18. package/dist/ar/image-capture.js +1 -154
  19. package/dist/ar/image-quality.d.ts +2 -0
  20. package/dist/ar/image-quality.js +168 -0
  21. package/dist/ar/index.d.ts +31 -19
  22. package/dist/ar/index.js +17 -5
  23. package/dist/ar/occupancy-grid.d.ts +1 -1
  24. package/dist/ar/occupancy-grid.js +29 -2
  25. package/dist/ar/planar-pnp.d.ts +2 -0
  26. package/dist/ar/planar-pnp.js +425 -0
  27. package/dist/ar/qr-debug-view.d.ts +2 -0
  28. package/dist/ar/qr-debug-view.js +89 -0
  29. package/dist/ar/qr-derived-pose.d.ts +2 -0
  30. package/dist/ar/qr-derived-pose.js +114 -0
  31. package/dist/ar/qr-detection-controller.d.ts +2 -0
  32. package/dist/ar/qr-detection-controller.js +2 -0
  33. package/dist/ar/qr-frontend.d.ts +2 -0
  34. package/dist/ar/qr-frontend.js +60 -0
  35. package/dist/ar/qr-pose.d.ts +2 -0
  36. package/dist/ar/qr-pose.js +267 -0
  37. package/dist/ar/qr-size-depth-context.d.ts +3 -0
  38. package/dist/ar/qr-size-depth-context.js +42 -0
  39. package/dist/ar/qr-size-measurer.d.ts +2 -0
  40. package/dist/ar/qr-size-measurer.js +2 -0
  41. package/dist/ar/replay-scene.d.ts +1 -1
  42. package/dist/ar/replay-scene.js +1 -1
  43. package/dist/ar/scene-node-names.d.ts +1 -1
  44. package/dist/ar/webxr-nue-basis.d.ts +1 -1
  45. package/dist/ar/webxr-session.d.ts +4 -4
  46. package/dist/ar/webxr-session.js +2 -2
  47. package/dist/ar/xr-camera-texture.d.ts +1 -1
  48. package/dist/ar/xr-error-handler.d.ts +1 -1
  49. package/dist/ar/xr-frame-loop.d.ts +1 -1
  50. package/dist/ar-MFpFlV7j.js +382 -0
  51. package/dist/{ar-world-group-alignment-C9lwwIyI.d.ts → ar-world-group-alignment-69fgnB39.d.ts} +1 -1
  52. package/dist/{camera-blit-capture-CnxUDbKx.d.ts → camera-blit-capture-NKT9H5-e.d.ts} +57 -4
  53. package/dist/capture-motion-gate-0Yl2NpQG.d.ts +24 -0
  54. package/dist/capture-motion-gate-4EscNZCw.js +94 -0
  55. package/dist/concurrency-By0oOTZt.d.ts +50 -0
  56. package/dist/core/index.d.ts +2 -2
  57. package/dist/core/index.js +2 -2
  58. package/dist/create-slam-app-store-DkCHOpvb.js +149 -0
  59. package/dist/{create-slam-app-store-BljusOua.d.ts → create-slam-app-store-n_VF63D5.d.ts} +50 -40
  60. package/dist/depth-grid-lookup-DQ-IYhO3.d.ts +21 -0
  61. package/dist/{depth-sampler-Bhanfwla.d.ts → depth-sampler-asc8exHt.d.ts} +1 -1
  62. package/dist/{depth-unprojection-Y6i_mJuT.d.ts → depth-unprojection-DjsbJW9L.d.ts} +1 -1
  63. package/dist/{enable-gps-ar-BfUJOgpW.d.ts → enable-gps-ar-DkNhFv4Y.d.ts} +4 -4
  64. package/dist/{frame-conversions-BfsafGWR.d.ts → frame-conversions-DObhj8Wf.d.ts} +1 -1
  65. package/dist/{fused-path-DJoVu98b.d.ts → fused-path-v6eOmLl3.d.ts} +1 -1
  66. package/dist/geo/h3-proximity.d.ts +2 -2
  67. package/dist/geo/h3-proximity.js +61 -2
  68. package/dist/geo/index.d.ts +2 -2
  69. package/dist/geo/index.js +2 -2
  70. package/dist/geodesic-angle-BTldfFgs.js +39 -0
  71. package/dist/{gps-anchor-dYeCvvp5.d.ts → gps-anchor-BeFO2RYa.d.ts} +1 -1
  72. package/dist/{gps-ar-pose-sampler-DVb96iOy.d.ts → gps-ar-pose-sampler-DHMZmYAc.d.ts} +1 -1
  73. package/dist/{gps-event-coordinator-CWIDOk4U.d.ts → gps-event-coordinator-CjWW636x.d.ts} +21 -11
  74. package/dist/{gps-event-markers-Dc9FT-q1.d.ts → gps-event-markers-Cz9RMA2k.d.ts} +18 -0
  75. package/dist/{h3-proximity-I1msGPgE.d.ts → h3-proximity-C-j0pw1j.d.ts} +39 -1
  76. package/dist/image-capture-B2-b6tKK.js +374 -0
  77. package/dist/{image-capture-qAZ5Fh5X.d.ts → image-capture-CNZDrQXG.d.ts} +103 -3
  78. package/dist/image-quality-smCBoFj1.d.ts +158 -0
  79. package/dist/index-BAPokxMb.d.ts +22 -0
  80. package/dist/{index-BYYUdf9v.d.ts → index-BODDUTvD.d.ts} +1 -1
  81. package/dist/index-BneSj4_5.d.ts +399 -0
  82. package/dist/index-_Rhgoqkh.d.ts +2 -0
  83. package/dist/index.d.ts +80 -67
  84. package/dist/index.js +24 -12
  85. package/dist/{leaflet-map-overlay-6CJC-E1l.d.ts → leaflet-map-overlay-CmIyiE8n.d.ts} +1 -1
  86. package/dist/{map-data-CkloBxIl.d.ts → map-data-B4oEehUh.d.ts} +1 -1
  87. package/dist/{map-overlay-draw-krOKwDAq.d.ts → map-overlay-draw-ymz1s7fG.d.ts} +1 -1
  88. package/dist/{null-storage-backend-uKQE8tl7.d.ts → null-storage-backend-B9rtyDfG.d.ts} +2 -2
  89. package/dist/{occupancy-grid-BRNRaPyT.d.ts → occupancy-grid-DnOc-6PU.d.ts} +12 -2
  90. package/dist/{opfs-storage-D5zAn_lx.d.ts → opfs-storage-3VZh-qH6.d.ts} +23 -4
  91. package/dist/{opfs-storage-backend-6aYMUZlJ.d.ts → opfs-storage-backend-JJiUJo-3.d.ts} +3 -3
  92. package/dist/{persistence-middleware-B9ei4Nhx.d.ts → persistence-middleware-DAPTTwB2.d.ts} +1 -1
  93. package/dist/planar-pnp-my9bqULS.d.ts +67 -0
  94. package/dist/qr-debug-view-Brl73HGO.d.ts +29 -0
  95. package/dist/qr-derived-pose-CmxTP2m4.d.ts +122 -0
  96. package/dist/qr-detected-slice-VQssZmQJ.d.ts +166 -0
  97. package/dist/qr-detection-controller-B-tLVd-S.js +119 -0
  98. package/dist/qr-detection-controller-CDurHv8E.d.ts +48 -0
  99. package/dist/qr-frontend--fFX25mV.d.ts +58 -0
  100. package/dist/qr-pose-D2rfu5DA.d.ts +138 -0
  101. package/dist/qr-pose-aggregation-B7tWJq7j.d.ts +90 -0
  102. package/dist/qr-pose-aggregation-DBiaLW0O.js +191 -0
  103. package/dist/qr-size-depth-context-CeAG53fy.d.ts +13 -0
  104. package/dist/qr-size-measurer-DLb33geH.js +596 -0
  105. package/dist/qr-size-measurer-DQdAsid1.d.ts +165 -0
  106. package/dist/recording-options-BPCpMHLK.d.ts +514 -0
  107. package/dist/{recording-replayer-r0DZ9ALp.d.ts → recording-replayer-DQKpAGyQ.d.ts} +2 -2
  108. package/dist/recording-slice-DaxHZvNu.d.ts +55 -0
  109. package/dist/{replay-engine-XpDa0dy1.d.ts → replay-engine-CmKh_4wf.d.ts} +7 -4
  110. package/dist/{replay-scene-Bw58VL6p.d.ts → replay-scene-DBlDrV_x.d.ts} +3 -3
  111. package/dist/sensors/absolute-orientation.d.ts +2 -0
  112. package/dist/sensors/absolute-orientation.js +145 -0
  113. package/dist/sensors/gps-error-handler.d.ts +1 -1
  114. package/dist/sensors/gps.d.ts +1 -1
  115. package/dist/sensors/index.d.ts +5 -4
  116. package/dist/sensors/index.js +2 -1
  117. package/dist/sensors/permission-checker.d.ts +1 -1
  118. package/dist/sensors/permission-checker.js +1 -1
  119. package/dist/state/app-selectors.d.ts +1 -1
  120. package/dist/state/combined-root-state.d.ts +1 -1
  121. package/dist/state/create-slam-app-store.d.ts +1 -1
  122. package/dist/state/create-slam-app-store.js +1 -74
  123. package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
  124. package/dist/state/gps-event-coordinator.d.ts +2 -2
  125. package/dist/state/gps-event-coordinator.js +27 -17
  126. package/dist/state/index.d.ts +20 -17
  127. package/dist/state/index.js +5 -4
  128. package/dist/state/persistence-middleware.d.ts +1 -1
  129. package/dist/state/persistence-middleware.js +30 -19
  130. package/dist/state/qr-detected-slice.d.ts +4 -0
  131. package/dist/state/qr-detected-slice.js +311 -0
  132. package/dist/state/recording-options.d.ts +2 -2
  133. package/dist/state/recording-options.js +273 -7
  134. package/dist/state/recording-replayer.d.ts +2 -2
  135. package/dist/state/recording-replayer.js +1 -1
  136. package/dist/state/recording-slice.d.ts +1 -1
  137. package/dist/state/recording-slice.js +5 -1
  138. package/dist/state/replay-engine.d.ts +1 -1
  139. package/dist/state/replay-engine.js +7 -3
  140. package/dist/state/store-subscribers.d.ts +2 -2
  141. package/dist/state/subscribe-to-selector.d.ts +1 -1
  142. package/dist/state/tracking-quality.d.ts +2 -2
  143. package/dist/state/tracking-quality.js +40 -128
  144. package/dist/state/tracking-slice.d.ts +1 -1
  145. package/dist/{state-BkIfpiyA.js → state-E51QT_-j.js} +2 -1
  146. package/dist/storage/file-system-utils.d.ts +1 -1
  147. package/dist/storage/index.d.ts +9 -9
  148. package/dist/storage/index.js +4 -4
  149. package/dist/storage/null-storage-backend.d.ts +1 -1
  150. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  151. package/dist/storage/opfs-storage-backend.js +3 -3
  152. package/dist/storage/opfs-storage.d.ts +1 -1
  153. package/dist/storage/opfs-storage.js +5 -4
  154. package/dist/storage/storage-backend.d.ts +1 -1
  155. package/dist/storage/zip-coverage-embed.d.ts +2 -0
  156. package/dist/storage/zip-coverage-embed.js +88 -0
  157. package/dist/storage/zip-export.d.ts +2 -2
  158. package/dist/storage/zip-export.js +37 -59
  159. package/dist/storage/zip-reader.d.ts +1 -1
  160. package/dist/{storage-backend-Do6YDpNo.d.ts → storage-backend-BdVLD0dU.d.ts} +1 -1
  161. package/dist/{store-subscribers-0YWyOLvV.d.ts → store-subscribers-CA6AJH_8.d.ts} +2 -2
  162. package/dist/{subscribe-to-selector-CZ6k1NFP.d.ts → subscribe-to-selector-B6EUmQ3I.d.ts} +1 -1
  163. package/dist/test-utils/browser-mocks.d.ts +7 -1
  164. package/dist/test-utils/browser-mocks.js +6 -0
  165. package/dist/test-utils/zip-round-trip-helpers.d.ts +9 -1
  166. package/dist/test-utils/zip-round-trip-helpers.js +5 -1
  167. package/dist/{tracking-slice-CdK8c-8P.d.ts → tracking-slice-BuAZxXZ5.d.ts} +1 -1
  168. package/dist/types/ar-types.d.ts +1 -1
  169. package/dist/types/geo-types.d.ts +1 -1
  170. package/dist/types/index.d.ts +2 -2
  171. package/dist/utils/concurrency.d.ts +2 -2
  172. package/dist/utils/concurrency.js +66 -2
  173. package/dist/utils/failure-tracker.d.ts +1 -1
  174. package/dist/utils/format-file-size.d.ts +1 -1
  175. package/dist/utils/fused-path.d.ts +1 -1
  176. package/dist/utils/index.d.ts +8 -7
  177. package/dist/utils/index.js +2 -1
  178. package/dist/utils/list-formatter.d.ts +1 -1
  179. package/dist/utils/logger.d.ts +1 -1
  180. package/dist/visualization/accuracy-circles.d.ts +1 -1
  181. package/dist/visualization/alignment-lerper.d.ts +1 -1
  182. package/dist/visualization/ar-world-group-alignment.d.ts +1 -1
  183. package/dist/visualization/ar-world-group-alignment.js +1 -1
  184. package/dist/visualization/camera-follower.d.ts +1 -1
  185. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  186. package/dist/visualization/frame-conversions.d.ts +1 -1
  187. package/dist/visualization/frustum-visibility.d.ts +1 -1
  188. package/dist/visualization/gps-anchor.d.ts +1 -1
  189. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  190. package/dist/visualization/gps-event-markers.d.ts +1 -1
  191. package/dist/visualization/gps-event-markers.js +40 -5
  192. package/dist/visualization/hit-test-reticle.d.ts +1 -1
  193. package/dist/visualization/hit-test-reticle.js +1 -0
  194. package/dist/visualization/index.d.ts +18 -18
  195. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  196. package/dist/visualization/leaflet-map-overlay.js +15 -3
  197. package/dist/visualization/lerp-utils.d.ts +1 -1
  198. package/dist/visualization/map-data.d.ts +1 -1
  199. package/dist/visualization/map-overlay-draw.d.ts +1 -1
  200. package/dist/visualization/map-overlay.d.ts +1 -1
  201. package/dist/visualization/three-dispose.d.ts +1 -1
  202. package/dist/visualization/vis-colors.d.ts +1 -1
  203. package/dist/{webxr-session-TIaD883f.js → webxr-session-DG-eNfny.js} +244 -11
  204. package/dist/{webxr-session-GjZ2BIpS.d.ts → webxr-session-Do5L6G3B.d.ts} +86 -8
  205. package/dist/zip-coverage-embed-DCAREVmw.d.ts +41 -0
  206. package/dist/{zip-export-G14hkSPG.d.ts → zip-export-ol0S_Ofd.d.ts} +27 -23
  207. package/package.json +2 -2
  208. package/dist/concurrency-CO1FQvs3.d.ts +0 -24
  209. package/dist/file-system-CwXTNHmB.d.ts +0 -114
  210. package/dist/index-CF05QV2m.d.ts +0 -2
  211. package/dist/recording-options-DJBXuMxV.d.ts +0 -182
  212. package/dist/recording-slice-89O07ebs.d.ts +0 -36
  213. package/dist/storage/file-system.d.ts +0 -2
  214. package/dist/storage/file-system.js +0 -289
  215. /package/dist/{accuracy-circles-BpwWAs8G.d.ts → accuracy-circles-BtqOP_v1.d.ts} +0 -0
  216. /package/dist/{alignment-lerper-Dm9G7JJO.d.ts → alignment-lerper-Bil6vbVw.d.ts} +0 -0
  217. /package/dist/{ar-types-Dan1MVTi.d.ts → ar-types-BFX2r1wk.d.ts} +0 -0
  218. /package/dist/{bresenham3d-CFfd7n6B.d.ts → bresenham3d-CU1Gv2W4.d.ts} +0 -0
  219. /package/dist/{camera-follower-C2mwEn7c.d.ts → camera-follower-CqJJ7zRj.d.ts} +0 -0
  220. /package/dist/{capability-checker-CQXJHxXg.d.ts → capability-checker-DUQLg6gq.d.ts} +0 -0
  221. /package/dist/{capture-failure-tracker-CUeU3L_M.d.ts → capture-failure-tracker-gsm8q7yi.d.ts} +0 -0
  222. /package/dist/{chromium-camera-access-workaround-Jqbn0apH.d.ts → chromium-camera-access-workaround-D4K2uwwQ.d.ts} +0 -0
  223. /package/dist/{css3d-renderer-manager-ptu_t3B3.d.ts → css3d-renderer-manager-B3kGNtcn.d.ts} +0 -0
  224. /package/dist/{failure-tracker-Cn8Fo9D4.d.ts → failure-tracker-BO7M7jF_.d.ts} +0 -0
  225. /package/dist/{file-system-utils-CXIoL-DM.d.ts → file-system-utils-DOajnMm-.d.ts} +0 -0
  226. /package/dist/{format-file-size-CLCZz3lC.d.ts → format-file-size-Dc98ulzB.d.ts} +0 -0
  227. /package/dist/{frame-loop-CMewS8cY.d.ts → frame-loop-CpVjQ1dH.d.ts} +0 -0
  228. /package/dist/{frustum-visibility-CmI96ESS.d.ts → frustum-visibility-CeoCZchO.d.ts} +0 -0
  229. /package/dist/{geo-types-SaPnIEUM.d.ts → geo-types-3Ip1NzVR.d.ts} +0 -0
  230. /package/dist/{gps-VuezJWK3.d.ts → gps-BBO3hKfT.d.ts} +0 -0
  231. /package/dist/{gps-compass-cubes-BM1uGiYV.d.ts → gps-compass-cubes-DSN87L8p.d.ts} +0 -0
  232. /package/dist/{gps-error-handler-CJl_2MVm.d.ts → gps-error-handler-BbPsfw-_.d.ts} +0 -0
  233. /package/dist/{hit-test-reticle-BEzEybxZ.d.ts → hit-test-reticle-DV-2TpB9.d.ts} +0 -0
  234. /package/dist/{lerp-utils-BpV-0Dtk.d.ts → lerp-utils-BLmHhkVe.d.ts} +0 -0
  235. /package/dist/{list-formatter-RRcBe8Vg.d.ts → list-formatter-KNMS0ay2.d.ts} +0 -0
  236. /package/dist/{logger-BEHXsnnq.d.ts → logger-CLnPrHiD.d.ts} +0 -0
  237. /package/dist/{map-overlay-bcogY5fK.d.ts → map-overlay-Dh2B97MP.d.ts} +0 -0
  238. /package/dist/{permission-checker-GpAiSCwd.d.ts → permission-checker-CDuI8BwC.d.ts} +0 -0
  239. /package/dist/{scene-node-names-Bu0S66H1.d.ts → scene-node-names-BiShOQDB.d.ts} +0 -0
  240. /package/dist/{session-disposers-M-oashRH.js → session-disposers-zv9OGXPB.js} +0 -0
  241. /package/dist/{three-dispose-D950t71B.d.ts → three-dispose-Bt1k7WKh.d.ts} +0 -0
  242. /package/dist/{vis-colors-D6omC64K.d.ts → vis-colors-Obw2pLqT.d.ts} +0 -0
  243. /package/dist/{webxr-nue-basis-CqKQmZzT.d.ts → webxr-nue-basis-3nfjDJJp.d.ts} +0 -0
  244. /package/dist/{xr-camera-texture-DBwCaKTd.d.ts → xr-camera-texture-Cva1q3Qj.d.ts} +0 -0
  245. /package/dist/{xr-error-handler-C0AQRmxs.d.ts → xr-error-handler-CtvHpjfm.d.ts} +0 -0
  246. /package/dist/{xr-frame-loop-BtYytZJg.d.ts → xr-frame-loop-DIYtRcUa.d.ts} +0 -0
  247. /package/dist/{zip-reader-DSEXt7K6.d.ts → zip-reader-D9iPQwdQ.d.ts} +0 -0
@@ -0,0 +1,165 @@
1
+ import { r as DepthPoint } from "./ar-types-BFX2r1wk.js";
2
+ import { t as DepthUnprojector } from "./depth-unprojection-DjsbJW9L.js";
3
+ import { r as Point2 } from "./qr-pose-D2rfu5DA.js";
4
+ import { Vector3 } from "gps-plus-slam-js";
5
+
6
+ //#region ../src/ar/qr-size-from-depth.d.ts
7
+ /** Where the size lifecycle currently sits for one marker (Note 3 / Note 4). */
8
+ type QrSizeStatus = /** No size authored and none measured yet — size-dependent features blocked. */'unknown' /** Measurements are accumulating but the estimate has not converged. */ | 'measuring' /** A reliably-estimated (or authored) size — size-dependent features unlock. */ | 'estimated';
9
+ /** Per-marker physical-size estimate (drives the Note 3 size lifecycle). */
10
+ interface QrSizeEstimate {
11
+ status: QrSizeStatus;
12
+ /** Running median side length, meters, or `null` while unknown. */
13
+ estimateM: number | null;
14
+ /** How many accepted samples back the estimate. */
15
+ sampleCount: number;
16
+ /**
17
+ * Robust confidence half-width of the estimate, meters (`1.4826·MAD/√N`), so
18
+ * it TIGHTENS as samples accumulate (WS-B) — not the raw max−min. 0 when <2
19
+ * samples. The HUD renders this as the shrinking `±mm`.
20
+ */
21
+ spreadM: number;
22
+ }
23
+ /** One per-observation size read from a single detection's depth samples. */
24
+ interface QrSizeObservation {
25
+ /** Median of the 4 unprojected edge lengths, meters. */
26
+ sizeM: number;
27
+ /** Consistency score in [0,1]; 1 = a perfect planar square facing the camera. */
28
+ quality: number;
29
+ }
30
+ /**
31
+ * Estimate a QR's physical side length from one detection's depth samples.
32
+ *
33
+ * @param corners - the 4 corner depth samples, ordered TL, TR, BR, BL (matching
34
+ * `buildObjectPoints` / the detector corner-order normalization).
35
+ * @param interiorSamples - a few interior depth samples (may be empty); used
36
+ * only to strengthen the planarity check against corner edge depth-bleed.
37
+ * @param unprojector - built once per depth sample via `createDepthUnprojector`.
38
+ * @returns `{ sizeM, quality }`, or `null` when a corner cannot be unprojected
39
+ * or the quad is degenerate (collinear / zero-area).
40
+ */
41
+ declare function estimateQrSizeFromDepth(corners: readonly [DepthPoint, DepthPoint, DepthPoint, DepthPoint], interiorSamples: readonly DepthPoint[], unprojector: DepthUnprojector): QrSizeObservation | null;
42
+ interface QrSizeAccumulatorOptions {
43
+ /** Minimum observation quality to ACCEPT a sample. Default 0.8. */
44
+ qualityThreshold?: number;
45
+ /** Accepted samples required before the estimate can be `estimated`. Default 8. */
46
+ minSamples?: number;
47
+ /**
48
+ * Max confidence half-width (`spreadM`, m) allowed for the `estimated` status.
49
+ * Default 0.01. `spreadM` is a robust standard-error (`1.4826·MAD/√N`) that
50
+ * TIGHTENS as samples accumulate — not the raw max−min — so it converges
51
+ * instead of being pinned by one early stray.
52
+ */
53
+ maxSpreadM?: number;
54
+ /**
55
+ * Optional cap on retained accepted sizes. **Default: unbounded** (lifelong
56
+ * refinement — WS-B). The QR's physical size never changes, so keeping the
57
+ * full session history lets the robust median tighten the longer the QR is
58
+ * seen. Set a finite cap only if memory/perf demands a bounded window; the
59
+ * estimate then becomes a sliding-window median again.
60
+ */
61
+ maxSamples?: number;
62
+ }
63
+ interface QrSizeAccumulator {
64
+ /**
65
+ * Offer one observation (or `null` for a failed read). Low-quality / null
66
+ * observations are ignored. Returns the updated {@link QrSizeEstimate}.
67
+ */
68
+ add(observation: QrSizeObservation | null): QrSizeEstimate;
69
+ /** The current estimate without adding a sample. */
70
+ current(): QrSizeEstimate;
71
+ /** Drop all samples back to `unknown`. */
72
+ reset(): void;
73
+ }
74
+ declare function createQrSizeAccumulator(options?: QrSizeAccumulatorOptions): QrSizeAccumulator;
75
+ //#endregion
76
+ //#region ../src/ar/qr-size-measurer.d.ts
77
+ /**
78
+ * Robustness knobs for the depth-at-corners stage (on top of the accumulator
79
+ * options). QR corners sit on a high-contrast print boundary where the coarse
80
+ * WebXR depth grid often has no near reading; these let a measurement still
81
+ * succeed instead of returning `null` every frame.
82
+ */
83
+ interface QrSizeMeasurerOptions extends QrSizeAccumulatorOptions {
84
+ /**
85
+ * Points-per-side of the interior depth lattice sampled across the QR quad for
86
+ * the PRIMARY dense plane-fit estimate (WS-A). `latticeSize × latticeSize`
87
+ * points are sampled strictly inside the quad; reads with no depth are
88
+ * skipped. Default `7` (≤49 reads). Set to a small value (or rely on the
89
+ * corner fallback) to disable dense sampling. See {@link estimateQrSizeFromDepthDense}.
90
+ */
91
+ latticeSize?: number;
92
+ /**
93
+ * When a corner pixel has no depth, retry at points inset toward the centroid
94
+ * by these fractions (in order) and borrow the first valid depth — keeping the
95
+ * TRUE corner screen position so the measured size is not shrunk. Default
96
+ * `[0.12, 0.25]`. Set to `[]` to disable inset fallback. Used by the corner-
97
+ * based FALLBACK estimate (when the interior lattice is too sparse for a fit).
98
+ */
99
+ cornerInsetFractions?: number[];
100
+ /**
101
+ * Max corners whose depth may be reconstructed by a planar fit through the
102
+ * other three when still missing after the inset fallback. Default `1`
103
+ * (tolerate one un-sampleable corner); `0` disables reconstruction. Used by
104
+ * the corner-based FALLBACK estimate.
105
+ */
106
+ maxReconstructedCorners?: number;
107
+ }
108
+ /** The per-frame depth access the measurer needs (a subset of the demo's `DepthContext`). */
109
+ interface QrSizeDepthContext {
110
+ /** Depth (m) at a normalized screen point, or `null` if unavailable there. */
111
+ depthAt: (screenX: number, screenY: number) => number | null;
112
+ /** Unprojector for the current depth sample (`createDepthUnprojector`). */
113
+ unprojector: DepthUnprojector;
114
+ }
115
+ /** Minimal frame dimensions needed to normalize pixel corners to screen coords. */
116
+ interface ImageSize {
117
+ width: number;
118
+ height: number;
119
+ }
120
+ /** One measurement: the accumulated estimate plus the raw depth samples used. */
121
+ interface QrSizeMeasurement {
122
+ /** The per-marker running estimate AFTER folding in this observation. */
123
+ estimate: QrSizeEstimate;
124
+ /**
125
+ * The 4 corner depth samples (detector order, normalized screen coords),
126
+ * best-effort. `null` when corner depth could not be sampled (e.g. a small QR
127
+ * whose corners fall between depth nodes) but the dense interior fit still
128
+ * produced an estimate — the dense path does not need corner depths.
129
+ */
130
+ cornerSamples: [DepthPoint, DepthPoint, DepthPoint, DepthPoint] | null;
131
+ /**
132
+ * The interior depth reads used for the estimate: the dense lattice on the
133
+ * primary path, or the single centroid sample on the corner-based fallback
134
+ * (may be empty).
135
+ */
136
+ interiorSamples: DepthPoint[];
137
+ }
138
+ interface QrSizeMeasurer {
139
+ /**
140
+ * Measure one detection's size from depth and fold it into the per-`text`
141
+ * accumulator. The PRIMARY path is the dense plane fit (WS-A): sample an
142
+ * interior lattice, fit the QR plane, recover the corners by ray-plane
143
+ * intersection. When the lattice is too sparse for a fit it FALLS BACK to the
144
+ * corner-based estimate (corner depths + inset/reconstruct robustness).
145
+ *
146
+ * Returns `null` only when neither path can run — `corners.length !== 4`, or
147
+ * the interior lattice yields too few reads AND the corner depths cannot be
148
+ * sampled (≥2 corners missing). A degenerate quad does not throw: the (null)
149
+ * observation is simply not accumulated and the prior estimate stands.
150
+ */
151
+ measure(text: string, corners: readonly Point2[], image: ImageSize, ctx: QrSizeDepthContext): QrSizeMeasurement | null;
152
+ /** Current estimate for a marker without adding a sample. */
153
+ current(text: string): QrSizeEstimate;
154
+ /** Drop one marker's samples (`text` given) or all of them. */
155
+ reset(text?: string): void;
156
+ }
157
+ /**
158
+ * Create a size measurer. Accumulator `options` (quality threshold, min samples,
159
+ * spread, cap) are forwarded to every per-marker {@link createQrSizeAccumulator};
160
+ * the depth-at-corners knobs ({@link QrSizeMeasurerOptions.cornerInsetFractions},
161
+ * {@link QrSizeMeasurerOptions.maxReconstructedCorners}) tune corner sampling.
162
+ */
163
+ declare function createQrSizeMeasurer(options?: QrSizeMeasurerOptions): QrSizeMeasurer;
164
+ //#endregion
165
+ export { QrSizeMeasurerOptions as a, QrSizeAccumulatorOptions as c, QrSizeStatus as d, createQrSizeAccumulator as f, QrSizeMeasurer as i, QrSizeEstimate as l, QrSizeDepthContext as n, createQrSizeMeasurer as o, estimateQrSizeFromDepth as p, QrSizeMeasurement as r, QrSizeAccumulator as s, ImageSize as t, QrSizeObservation as u };
@@ -0,0 +1,514 @@
1
+ import { t as MotionFilterConfig } from "./capture-motion-gate-0Yl2NpQG.js";
2
+ import { a as QualityFilterConfig } from "./image-quality-smCBoFj1.js";
3
+
4
+ //#region ../src/state/recording-options.d.ts
5
+ /**
6
+ * Input type for validateRecordingOptions allowing partial nested objects.
7
+ * This allows passing incomplete objects that will be merged with defaults.
8
+ */
9
+ interface RecordingOptionsInput {
10
+ depth?: Partial<DepthCaptureOptions>;
11
+ images?: Partial<ImageCaptureOptions>;
12
+ arCrashIsolation?: Partial<ArCrashIsolationOptions>;
13
+ occupancy?: Partial<OccupancyOptions>;
14
+ frameTileDisplay?: Partial<FrameTileDisplayOptions>;
15
+ visualization?: Partial<VisualizationOptions>;
16
+ qr?: Partial<QrCaptureOptions>;
17
+ compassDebug?: Partial<CompassDebugOptions>;
18
+ }
19
+ /**
20
+ * Toggles for the library's Phase-4 compass alignment features (closed/internal
21
+ * `AlignmentConfig` flags exposed via narrow boolean actions). They change how
22
+ * the LIVE alignment is computed, so they sit with the other capture groups.
23
+ * **Stage 0 (`coldStartOverride`) defaults ON** (a field-validated production
24
+ * feature); Stage C + the WebXR-consistency gate stay experimental (default
25
+ * OFF) until the §6a field-data matrix is in.
26
+ *
27
+ * On-device caveat: the resulting `gpsData` actions persist into the recording,
28
+ * so a replay re-enables them. Record §6a field-calibration sets with
29
+ * `coldStartOverride` OFF so the captured compass behaviour is unmodified.
30
+ */
31
+ interface CompassDebugOptions {
32
+ /** Stage 0 — cold-start compass yaw override (`setColdStartOverrideEnabled`). Default ON. */
33
+ coldStartOverride: boolean;
34
+ /** Stage C — trust-gated compass rotation prior (`setCompassRotationPriorEnabled`). */
35
+ rotationPrior: boolean;
36
+ /** GPS-free compass↔WebXR consistency gate (`setCompassWebXRConsistencyEnabled`). */
37
+ webXRConsistency: boolean;
38
+ }
39
+ /**
40
+ * Diagnostic flags for isolating pre-recording AR startup crashes.
41
+ * These gates affect XR session negotiation and frame-loop behavior,
42
+ * independently of recording-time image/depth capture.
43
+ */
44
+ interface ArCrashIsolationOptions {
45
+ enableDomOverlay: boolean;
46
+ enableCameraAccess: boolean;
47
+ enableDepthSensingFeature: boolean;
48
+ enableCss3dRenderer: boolean;
49
+ enableCameraTextureAcquisition: boolean;
50
+ /**
51
+ * Apply the Chromium WebXR camera-access tab-crash workaround at app
52
+ * bootstrap. The workaround always deletes
53
+ * `XRWebGLBinding.prototype.createProjectionLayer` /
54
+ * `XRRenderState.prototype.layers` (forcing `XRWebGLLayer`) — required on
55
+ * every affected Chrome build observed on-device, including Chrome 150 — and
56
+ * additionally persists the `baseLayer` across
57
+ * `XRSession.prototype.updateRenderState` only for Chrome builds inside the
58
+ * affected window (148.0.7778.12 up to 149.0.7821).
59
+ *
60
+ * Default `true`. Opt-out is offered because forcing `XRWebGLLayer` may break
61
+ * WebXR on unaffected (e.g. Quest) devices.
62
+ *
63
+ * @see GpsPlusSlamJs_AppFramework/src/ar/chromium-camera-access-workaround.ts
64
+ * @see https://github.com/mrdoob/three.js/issues/33404
65
+ */
66
+ applyChromiumProjectionLayerWorkaround: boolean;
67
+ }
68
+ /**
69
+ * Configuration for depth sampling during recording.
70
+ */
71
+ interface DepthCaptureOptions {
72
+ /** Whether to capture depth samples. Default: true */
73
+ enabled: boolean;
74
+ /** Interval between samples in milliseconds. Default: 1000 */
75
+ intervalMs: number;
76
+ /**
77
+ * Grid size (N×N points per sample). Default: 16 — dense enough to
78
+ * populate the AR-space occupancy grid (2026-06-11 port plan §1).
79
+ */
80
+ gridSize: number;
81
+ /**
82
+ * Whether to enrich each depth point with the camera color at its view
83
+ * coordinates (RGB voxel coloring, occupancy-grid port plan Iter 8).
84
+ * Costs one small GPU blit+readback per sample (~1 Hz); when off, the
85
+ * occupancy cubes keep the height-based coloring. Default: true.
86
+ */
87
+ rgb: boolean;
88
+ }
89
+ /**
90
+ * Configuration for image capture during recording.
91
+ */
92
+ interface ImageCaptureOptions {
93
+ /** Whether to capture images. Default: true */
94
+ enabled: boolean;
95
+ /** Interval between captures in milliseconds. Default: 2000 */
96
+ intervalMs: number;
97
+ /** JPEG quality (0.0 - 1.0). Default: 0.7 */
98
+ quality: number;
99
+ /** Resolution divisor: 1 = full native resolution, 2 = half, 4 = quarter. Default: 1 */
100
+ resolutionDivisor: number;
101
+ /**
102
+ * Motion gate — skip motion-blurred frames by deferring a due capture until
103
+ * device motion settles. Mirrors `ImageCaptureConfig.motionFilter` (the type
104
+ * the capture manager consumes); the recorder destructures `images` and flows
105
+ * the rest, including this group, through the capture seam. Default: enabled.
106
+ * See `ar/capture-motion-gate.ts` and
107
+ * `GpsPlusSlamJs_Docs/docs/2026-06-23-blurry-frame-motion-gating-plan.md`.
108
+ */
109
+ motionFilter: MotionFilterConfig;
110
+ /**
111
+ * Image-quality gate — drop a blurry/black frame (judged off-thread) and retry
112
+ * the next acceptable frame. Mirrors `ImageCaptureConfig.qualityFilter`; flows
113
+ * through the same capture seam as `motionFilter`. **Default: disabled**
114
+ * pending field tuning of the relative blur threshold (a mis-tuned gate
115
+ * silently dropping good frames is worse than the motion gate's default-on).
116
+ * See `ar/image-quality.ts` and
117
+ * `GpsPlusSlamJs_Docs/docs/2026-06-24-image-quality-gate-plan.md`.
118
+ */
119
+ qualityFilter: QualityFilterConfig;
120
+ }
121
+ /**
122
+ * Configuration for the derived AR-space occupancy grid (the voxelization of
123
+ * the depth samples, port plan 2026-06-11). These settings do NOT change what
124
+ * is recorded — they govern the grid derived from the recorded depth points,
125
+ * so they also apply when replaying an existing recording, letting the same
126
+ * session be re-quantized at a different resolution.
127
+ */
128
+ interface OccupancyOptions {
129
+ /**
130
+ * Voxel edge length in metres. Drives the occupancy-grid quantization, the
131
+ * debug cubes, and the COLMAP `points3D` density. Default 0.15 (15 cm, Unity
132
+ * parity). Smaller = finer detail but cell count scales as 1/cellSize³, so the
133
+ * range is deliberately clamped (see `OCCUPANCY_CONSTRAINTS`). Read once when
134
+ * the grid is constructed (Enter-AR / replay load), so a change takes effect
135
+ * on the next session rather than mid-session.
136
+ */
137
+ cellSizeM: number;
138
+ /**
139
+ * Minimum observation count for a voxel to be trusted as occupied (the
140
+ * grid's `getOccupiedCells(minObservations)` floor, promoted to a user
141
+ * setting). A cell is marked occupied the instant one noisy depth point
142
+ * lands in it; raising this filters single-frame depth noise — in
143
+ * particular the **behind-surface** phantoms (e.g. below the floor) that
144
+ * free-space carving can never clear because no ray passes through occluded
145
+ * space. Default 3 (1 = unfiltered/legacy). Higher = less noise but
146
+ * briefly-glimpsed real surfaces may be dropped, so it is exposed for
147
+ * on-device tuning. Read once when the visualizer is constructed (Enter-AR
148
+ * / replay load). See
149
+ * `GpsPlusSlamJs_Docs/docs/2026-06-22-occupancy-grid-behind-surface-noise-plan.md`.
150
+ */
151
+ minConfidence: number;
152
+ }
153
+ /**
154
+ * Configuration for how captured frame tiles are DISPLAYED in AR (D7-resolution,
155
+ * 2026-06-16 RecorderApp user feedback / Q3). This is **distinct from** the
156
+ * capture setting `images.resolutionDivisor`: capture quality (the JPEG written
157
+ * to the recording) is unchanged — this only downscales the in-AR/replay display
158
+ * texture built from each captured frame, cutting per-tile GPU texture memory.
159
+ *
160
+ * Like {@link OccupancyOptions} it does NOT change what is recorded, so it
161
+ * applies to **both live and replay** (the tile texture is decoded in both). A
162
+ * partial memory mitigation for the OOM/crash track (the tile *count* still
163
+ * grows unbounded — capping/recycling is the separate Track-S fix).
164
+ */
165
+ interface FrameTileDisplayOptions {
166
+ /**
167
+ * Display-texture resolution divisor: 1 = full captured resolution, 2 = half
168
+ * (each dimension), 4 = quarter, 8 = eighth. Default 2 (half). Higher = less
169
+ * GPU memory per tile but a blurrier in-AR preview. Independent of the capture
170
+ * `images.resolutionDivisor`.
171
+ */
172
+ divisor: number;
173
+ }
174
+ /**
175
+ * Visibility toggles for the live AR debug overlays (Finding B / DB-2 of
176
+ * 2026-06-14-followup-frame-tile-legacy-aspect-and-live-toggle.md).
177
+ *
178
+ * These gate **only what is drawn live during recording** — they never change
179
+ * what is captured (frame blobs, depth samples, occupancy data, GPS events all
180
+ * continue regardless) and they never affect replay (where reviewing the
181
+ * captured overlays is the whole point). Read once at Enter-AR: toggling
182
+ * mid-session applies on the next Enter-AR, not retroactively.
183
+ *
184
+ * All four default ON, so adding this group is purely additive — every overlay
185
+ * still renders until the operator opts out.
186
+ */
187
+ interface VisualizationOptions {
188
+ /** Live frame-tile planes (`FrameTileVisualizer`). Default: true */
189
+ frameTiles: boolean;
190
+ /** Voxel depth cubes (`OccupancyCubesVisualizer`). Default: true */
191
+ occupancyCubes: boolean;
192
+ /** Raw/fused/snapshot GPS+VIO alignment spheres (`GpsEventVisualizer`). Default: true */
193
+ gpsAlignmentMarkers: boolean;
194
+ /** N/E/S/W compass orientation cubes (`createGpsCompassCubes`). Default: true */
195
+ compassCubes: boolean;
196
+ }
197
+ /**
198
+ * Configuration for live QR detection + RAW recording (decision §0 of the
199
+ * recorder live-QR follow-up,
200
+ * `2026-06-17-followup-recorder-live-qr-next-steps.md`).
201
+ *
202
+ * OPT-IN (`enabled` defaults to `false`): turning it on adds per-frame RGBA
203
+ * capture + a `BarcodeDetector` decode to the session, so it is operator-gated
204
+ * exactly like the heavy `depth`/`images` streams — an existing recording pays
205
+ * nothing. When on, the producer dispatches one RAW `qrDetected/recordQrDetection`
206
+ * action per accepted decode (size + pose are DERIVED on read, never recorded).
207
+ */
208
+ interface QrCaptureOptions {
209
+ /** Whether live QR detection + recording runs. Default: false (opt-in). */
210
+ enabled: boolean;
211
+ /**
212
+ * Capture / detection cadence in ms — the SINGLE cadence owner (the producer
213
+ * runs `minIntervalMs: 0`; this throttles the camera-frame source). Default
214
+ * 125 (~8 Hz), matching the QR demo's `DETECT_INTERVAL_MS`.
215
+ */
216
+ intervalMs: number;
217
+ /**
218
+ * RGBA capture long-edge in px. Larger = more decode range on a small/distant
219
+ * QR but a costlier blit + detect. Default 1024 (the on-device sweep settled
220
+ * here; 512 only decoded small QRs at very close range).
221
+ */
222
+ captureSize: number;
223
+ }
224
+ /**
225
+ * User-configurable recording options.
226
+ * Persisted to localStorage for cross-session consistency.
227
+ */
228
+ interface RecordingOptions {
229
+ /** Depth sampling configuration */
230
+ depth: DepthCaptureOptions;
231
+ /** Image capture configuration */
232
+ images: ImageCaptureOptions;
233
+ /** Diagnostic flags for pre-recording AR crash isolation */
234
+ arCrashIsolation: ArCrashIsolationOptions;
235
+ /** Derived occupancy-grid configuration (voxel size) */
236
+ occupancy: OccupancyOptions;
237
+ /** Frame-tile display-texture resolution (live + replay; capture unchanged) */
238
+ frameTileDisplay: FrameTileDisplayOptions;
239
+ /** Live AR debug-overlay visibility toggles (live-only; replay unaffected) */
240
+ visualization: VisualizationOptions;
241
+ /** Live QR detection + RAW recording configuration (opt-in) */
242
+ qr: QrCaptureOptions;
243
+ /** Compass alignment debug toggles (Stage 0 / Stage C / consistency gate) */
244
+ compassDebug: CompassDebugOptions;
245
+ }
246
+ /**
247
+ * localStorage key for persisted options.
248
+ *
249
+ * **Multi-tab caveat:** All tabs/instances sharing the same origin will
250
+ * read and write this key. In multi-tab or embedded scenarios, concurrent
251
+ * saves can silently overwrite each other. Use a custom `storageKey`
252
+ * parameter in `loadRecordingOptions` / `saveRecordingOptions` to isolate
253
+ * instances when needed.
254
+ */
255
+ declare const STORAGE_KEY = "gps-plus-slam-recorder-options";
256
+ /** Default recording options (all streams enabled) */
257
+ declare const DEFAULT_RECORDING_OPTIONS: RecordingOptions;
258
+ /** Validation constraints for depth options */
259
+ declare const DEPTH_CONSTRAINTS: {
260
+ readonly intervalMs: {
261
+ readonly min: 500;
262
+ readonly max: 5000;
263
+ readonly step: 100;
264
+ };
265
+ readonly gridSize: {
266
+ readonly min: 2;
267
+ readonly max: 32;
268
+ readonly step: 1;
269
+ };
270
+ };
271
+ /** Validation constraints for image options */
272
+ declare const IMAGE_CONSTRAINTS: {
273
+ readonly intervalMs: {
274
+ readonly min: 1000;
275
+ readonly max: 10000;
276
+ readonly step: 500;
277
+ };
278
+ readonly quality: {
279
+ readonly min: 0.3;
280
+ readonly max: 1;
281
+ readonly step: 0.1;
282
+ };
283
+ readonly resolutionDivisor: {
284
+ readonly min: 1;
285
+ readonly max: 8;
286
+ readonly step: 1;
287
+ };
288
+ };
289
+ /**
290
+ * Validation constraints for the motion-filter (blurry-frame gate) thresholds.
291
+ *
292
+ * The velocity ranges (0.05–5) bracket the plausible scanning regime: below
293
+ * ~0.05 the gate would reject almost everything; above ~5 rad/s ≈ 286°/s (or
294
+ * 5 m/s) it would never reject, so the gate would be inert. `maxWaitMs` is
295
+ * clamped to 0.5–20 s — the never-calm fallback must always be able to fire.
296
+ * All three back a (currently advanced/hidden) settings slider, so a corrupt
297
+ * stored value can never disable capture. The default thresholds themselves are
298
+ * placeholders pending on-device field tuning (plan §7).
299
+ */
300
+ declare const MOTION_FILTER_CONSTRAINTS: {
301
+ readonly maxAngularVelocity: {
302
+ readonly min: 0.05;
303
+ readonly max: 5;
304
+ readonly step: 0.05;
305
+ };
306
+ readonly maxLinearVelocity: {
307
+ readonly min: 0.05;
308
+ readonly max: 5;
309
+ readonly step: 0.05;
310
+ };
311
+ readonly maxWaitMs: {
312
+ readonly min: 500;
313
+ readonly max: 20000;
314
+ readonly step: 500;
315
+ };
316
+ };
317
+ /**
318
+ * Validation constraints for the image-quality (blur/blackness) gate thresholds.
319
+ *
320
+ * `blurRelativeThreshold` (`k` in `sharpness < k·median`) is clamped to
321
+ * 0.05–0.95: it is a fraction of the recent sharpness median, so values must sit
322
+ * strictly inside (0, 1) — at ~0 the blur check never rejects, near 1 it rejects
323
+ * almost everything. `minMeanLuminance` (the absolute black cutoff on a 0–255
324
+ * luma scale) is clamped to 0–128: 0 disables the black check, and a cutoff
325
+ * above mid-grey would reject normally-lit frames. `maxWaitMs` mirrors the motion
326
+ * gate's range (0.5–20 s) so the never-good fallback can always fire. All back a
327
+ * (currently advanced/hidden) settings slider, so a corrupt stored value can
328
+ * never disable capture. The default thresholds are placeholders pending
329
+ * on-device field tuning (plan §5, §10).
330
+ */
331
+ declare const QUALITY_FILTER_CONSTRAINTS: {
332
+ readonly blurRelativeThreshold: {
333
+ readonly min: 0.05;
334
+ readonly max: 0.95;
335
+ readonly step: 0.05;
336
+ };
337
+ readonly minMeanLuminance: {
338
+ readonly min: 0;
339
+ readonly max: 128;
340
+ readonly step: 1;
341
+ };
342
+ readonly maxWaitMs: {
343
+ readonly min: 500;
344
+ readonly max: 20000;
345
+ readonly step: 500;
346
+ };
347
+ };
348
+ /**
349
+ * Validation constraints for occupancy options.
350
+ *
351
+ * `cellSizeM` is clamped to 1–20 cm. The floor exists because cell count (and
352
+ * therefore the cube `InstancedMesh`, the grid `Map`, and the COLMAP
353
+ * `points3D` row count) scales as 1/cellSize³ — sub-centimetre voxels are both
354
+ * a memory/perf cliff on a phone and below the depth sensor's noise floor.
355
+ * Step is 1 cm (the settings slider operates in cm).
356
+ *
357
+ * `minConfidence` is clamped to 1–10 (integer). 1 disables the filter (legacy
358
+ * behaviour: a single observation counts as occupied); the ceiling exists
359
+ * because real surfaces accumulate only a handful of observations per second
360
+ * of dwell, so a floor above ~10 would start hiding genuine geometry.
361
+ */
362
+ declare const OCCUPANCY_CONSTRAINTS: {
363
+ readonly cellSizeM: {
364
+ readonly min: 0.01;
365
+ readonly max: 0.2;
366
+ readonly step: 0.01;
367
+ };
368
+ readonly minConfidence: {
369
+ readonly min: 1;
370
+ readonly max: 10;
371
+ readonly step: 1;
372
+ };
373
+ };
374
+ /**
375
+ * Validation constraints for the frame-tile display-resolution divisor.
376
+ *
377
+ * Clamped to 1–8 (full down to one-eighth per dimension), mirroring the capture
378
+ * `IMAGE_CONSTRAINTS.resolutionDivisor` range so the settings slider behaves the
379
+ * same. The intended stops are 1, 2, 4, 8 (full / half / quarter / eighth); the
380
+ * divisor is rounded to an integer so the resize target dimensions stay clean.
381
+ */
382
+ declare const FRAME_TILE_DISPLAY_CONSTRAINTS: {
383
+ readonly divisor: {
384
+ readonly min: 1;
385
+ readonly max: 8;
386
+ readonly step: 1;
387
+ };
388
+ };
389
+ /**
390
+ * Validation constraints for QR-capture options.
391
+ *
392
+ * `intervalMs` is clamped to 50–1000 ms (20 Hz down to 1 Hz): below ~50 ms the
393
+ * detector cannot keep up and frames just queue; above 1 s tracking feels dead.
394
+ * `captureSize` is clamped to 256–2048 px: under 256 even a near QR loses its
395
+ * modules; over 2048 the blit + decode cost is not worth it on a phone. Both
396
+ * back a settings slider so a corrupt stored value can never break capture.
397
+ */
398
+ declare const QR_CONSTRAINTS: {
399
+ readonly intervalMs: {
400
+ readonly min: 50;
401
+ readonly max: 1000;
402
+ readonly step: 25;
403
+ };
404
+ readonly captureSize: {
405
+ readonly min: 256;
406
+ readonly max: 2048;
407
+ readonly step: 128;
408
+ };
409
+ };
410
+ /**
411
+ * Validate and normalize AR crash isolation flags.
412
+ * Missing or invalid values fall back to defaults.
413
+ */
414
+ declare function validateArCrashIsolationOptions(options: Partial<ArCrashIsolationOptions>): ArCrashIsolationOptions;
415
+ /**
416
+ * Validate and normalize the compass alignment debug toggles. Boolean-or-default
417
+ * per field; a missing/corrupted/pre-feature value falls back to the OFF default
418
+ * so a bad persisted value can never silently turn an alignment override ON.
419
+ */
420
+ declare function validateCompassDebugOptions(options: Partial<CompassDebugOptions>): CompassDebugOptions;
421
+ /**
422
+ * Validate and normalize the live debug-overlay visibility toggles.
423
+ * Each field is boolean-or-default (same policy as the AR-crash-isolation
424
+ * flags): a missing, corrupted, or pre-feature persisted value falls back to
425
+ * the ON default so an overlay is never silently disabled by bad input.
426
+ */
427
+ declare function validateVisualizationOptions(options: Partial<VisualizationOptions>): VisualizationOptions;
428
+ /**
429
+ * Validate and normalize QR-capture options. `enabled` is boolean-or-default
430
+ * (a corrupt/pre-feature value falls back to the OFF default so QR never
431
+ * silently turns ON); `intervalMs`/`captureSize` are clamped to
432
+ * {@link QR_CONSTRAINTS}, with a `Number.isFinite` guard so a stored `NaN`
433
+ * (which is `typeof 'number'` and survives `clamp`) falls back to the default
434
+ * rather than breaking the camera-frame source.
435
+ */
436
+ declare function validateQrOptions(options: Partial<QrCaptureOptions>): QrCaptureOptions;
437
+ /**
438
+ * Validate and normalize depth options.
439
+ * Invalid values are clamped to valid ranges.
440
+ */
441
+ declare function validateDepthOptions(options: Partial<DepthCaptureOptions>): DepthCaptureOptions;
442
+ /**
443
+ * Validate and normalize the motion-filter (blurry-frame gate) options.
444
+ * `enabled` is boolean-or-default; the three numeric thresholds are clamped to
445
+ * {@link MOTION_FILTER_CONSTRAINTS} with a `Number.isFinite` guard (a stored
446
+ * `NaN` is `typeof 'number'` and would survive `clamp`). A missing group
447
+ * default-fills entirely — a pre-feature persisted options object that lacks
448
+ * `motionFilter` therefore loads with the gate enabled rather than crashing.
449
+ */
450
+ declare function validateMotionFilterOptions(options: Partial<MotionFilterConfig>): MotionFilterConfig;
451
+ /**
452
+ * Validate and normalize the image-quality (blur/blackness gate) options. Same
453
+ * policy as {@link validateMotionFilterOptions}: `enabled` is boolean-or-default;
454
+ * the three numeric thresholds are clamped to {@link QUALITY_FILTER_CONSTRAINTS}
455
+ * with a `Number.isFinite` guard (a stored `NaN` is `typeof 'number'` and would
456
+ * survive `clamp`). A missing group default-fills entirely — a pre-feature
457
+ * persisted options object that lacks `qualityFilter` loads with the gate
458
+ * disabled (the safe default) rather than crashing.
459
+ */
460
+ declare function validateQualityFilterOptions(options: Partial<QualityFilterConfig>): QualityFilterConfig;
461
+ /**
462
+ * Validate and normalize image options.
463
+ * Invalid values are clamped to valid ranges.
464
+ */
465
+ declare function validateImageOptions(options: Partial<ImageCaptureOptions>): ImageCaptureOptions;
466
+ /**
467
+ * Validate and normalize occupancy options.
468
+ * Invalid values are clamped to valid ranges.
469
+ *
470
+ * Note the explicit `Number.isFinite` guard: `OccupancyGrid` throws a
471
+ * `RangeError` on a non-finite cell size, and `clamp(NaN, …)` would otherwise
472
+ * pass `NaN` straight through (it is `typeof 'number'`). Falling back to the
473
+ * default keeps a corrupted stored value from crashing grid construction.
474
+ */
475
+ declare function validateOccupancyOptions(options: Partial<OccupancyOptions>): OccupancyOptions;
476
+ /**
477
+ * Validate and normalize frame-tile display options. `divisor` is clamped to
478
+ * {@link FRAME_TILE_DISPLAY_CONSTRAINTS} and rounded to an integer, with a
479
+ * `Number.isFinite` guard so a stored `NaN` (which is `typeof 'number'` and
480
+ * survives `clamp`) falls back to the default rather than producing a broken
481
+ * resize target.
482
+ */
483
+ declare function validateFrameTileDisplayOptions(options: Partial<FrameTileDisplayOptions>): FrameTileDisplayOptions;
484
+ /**
485
+ * Validate and normalize a full RecordingOptions object.
486
+ * Merges with defaults and clamps invalid values.
487
+ */
488
+ declare function validateRecordingOptions(options: RecordingOptionsInput): RecordingOptions;
489
+ /**
490
+ * Load recording options from localStorage.
491
+ * Returns defaults if no saved options exist or parsing fails.
492
+ * Validates and merges with defaults to handle schema evolution.
493
+ * @param storageKey - Optional custom localStorage key (defaults to STORAGE_KEY).
494
+ */
495
+ declare function loadRecordingOptions(storageKey?: string): RecordingOptions;
496
+ /**
497
+ * Save recording options to localStorage.
498
+ * Options are validated before saving.
499
+ * @param storageKey - Optional custom localStorage key (defaults to STORAGE_KEY).
500
+ */
501
+ declare function saveRecordingOptions(options: RecordingOptions, storageKey?: string): void;
502
+ /**
503
+ * Reset recording options to defaults.
504
+ * Clears localStorage and returns default options.
505
+ * @param storageKey - Optional custom localStorage key (defaults to STORAGE_KEY).
506
+ */
507
+ declare function resetRecordingOptions(storageKey?: string): RecordingOptions;
508
+ /**
509
+ * Create a deep copy of recording options.
510
+ * Useful for creating mutable copies of the frozen defaults.
511
+ */
512
+ declare function cloneRecordingOptions(options: RecordingOptions): RecordingOptions;
513
+ //#endregion
514
+ export { validateOccupancyOptions as A, saveRecordingOptions as C, validateFrameTileDisplayOptions as D, validateDepthOptions as E, validateQualityFilterOptions as M, validateRecordingOptions as N, validateImageOptions as O, validateVisualizationOptions as P, resetRecordingOptions as S, validateCompassDebugOptions as T, RecordingOptionsInput as _, DepthCaptureOptions as a, cloneRecordingOptions as b, IMAGE_CONSTRAINTS as c, OCCUPANCY_CONSTRAINTS as d, OccupancyOptions as f, RecordingOptions as g, QrCaptureOptions as h, DEPTH_CONSTRAINTS as i, validateQrOptions as j, validateMotionFilterOptions as k, ImageCaptureOptions as l, QUALITY_FILTER_CONSTRAINTS as m, CompassDebugOptions as n, FRAME_TILE_DISPLAY_CONSTRAINTS as o, QR_CONSTRAINTS as p, DEFAULT_RECORDING_OPTIONS as r, FrameTileDisplayOptions as s, ArCrashIsolationOptions as t, MOTION_FILTER_CONSTRAINTS as u, STORAGE_KEY as v, validateArCrashIsolationOptions as w, loadRecordingOptions as x, VisualizationOptions as y };
@@ -1,5 +1,5 @@
1
- import { L as CombinedRootState } from "./create-slam-app-store-BljusOua.js";
2
- import { i as RecordedAction } from "./zip-reader-DSEXt7K6.js";
1
+ import { N as CombinedRootState } from "./create-slam-app-store-n_VF63D5.js";
2
+ import { i as RecordedAction } from "./zip-reader-D9iPQwdQ.js";
3
3
 
4
4
  //#region ../src/state/recording-replayer.d.ts
5
5
  /**