gps-plus-slam-app-framework 1.9.0 → 1.10.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 (244) hide show
  1. package/dist/{alignment-lerper-gD70k7Fq.d.ts → alignment-lerper-B4COh_0p.d.ts} +0 -6
  2. package/dist/{app-selectors-BbAiCRUT.d.ts → app-selectors-CV7ggGoo.d.ts} +23 -13
  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 +1 -1
  10. package/dist/ar/depth-sampler.d.ts +2 -2
  11. package/dist/ar/depth-sampler.js +16 -5
  12. package/dist/ar/depth-unprojection.d.ts +1 -1
  13. package/dist/ar/enable-gps-ar.d.ts +1 -1
  14. package/dist/ar/enable-gps-ar.js +1 -1
  15. package/dist/ar/frame-loop.d.ts +1 -1
  16. package/dist/ar/image-capture.d.ts +1 -1
  17. package/dist/ar/image-capture.js +1 -1
  18. package/dist/ar/image-quality.d.ts +1 -1
  19. package/dist/ar/image-quality.js +28 -9
  20. package/dist/ar/index.d.ts +32 -32
  21. package/dist/ar/index.js +7 -7
  22. package/dist/ar/occlusion-mesh-worker.d.ts +2 -2
  23. package/dist/ar/occlusion-mesh-worker.js +1 -1
  24. package/dist/ar/occupancy-grid.d.ts +1 -1
  25. package/dist/ar/occupancy-grid.js +1 -1
  26. package/dist/ar/occupancy-mesher.d.ts +1 -1
  27. package/dist/ar/occupancy-mesher.js +3 -4
  28. package/dist/ar/planar-pnp.d.ts +1 -1
  29. package/dist/ar/qr-debug-view.d.ts +1 -1
  30. package/dist/ar/qr-derived-pose.d.ts +1 -1
  31. package/dist/ar/qr-derived-pose.js +1 -1
  32. package/dist/ar/qr-detection-controller.d.ts +1 -1
  33. package/dist/ar/qr-detection-controller.js +1 -1
  34. package/dist/ar/qr-frontend.d.ts +1 -1
  35. package/dist/ar/qr-pose.d.ts +1 -1
  36. package/dist/ar/qr-size-depth-context.d.ts +2 -2
  37. package/dist/ar/qr-size-measurer.d.ts +1 -1
  38. package/dist/ar/qr-size-measurer.js +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 +3 -3
  44. package/dist/ar/webxr-session.js +1 -1
  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-BqCudtqE.js → ar-D-03Kso-.js} +18 -14
  49. package/dist/{ar-types-Cc5yvBwn.d.ts → ar-types-CBafnxhE.d.ts} +16 -1
  50. package/dist/{ar-world-group-alignment-Cfg0trC3.d.ts → ar-world-group-alignment-B6XiA1cT.d.ts} +1 -1
  51. package/dist/core/index.d.ts +1 -1
  52. package/dist/{create-slam-app-store-D1QSMuKu.d.ts → create-slam-app-store-CH31erpP.d.ts} +4 -4
  53. package/dist/{create-slam-app-store-DXiAnJwR.js → create-slam-app-store-DLv5ZwqU.js} +2 -2
  54. package/dist/{depth-grid-lookup-D5atpNZ3.d.ts → depth-grid-lookup-DY6zYTLx.d.ts} +1 -1
  55. package/dist/{depth-sampler-CwObAwEA.d.ts → depth-sampler-txG8evgQ.d.ts} +14 -4
  56. package/dist/{depth-unprojection-DRdBU90S.d.ts → depth-unprojection-JKkeqJrV.d.ts} +1 -1
  57. package/dist/device-orientation-cache-BjEaEAmh.js +20 -0
  58. package/dist/{enable-gps-ar-BBtRO2FJ.d.ts → enable-gps-ar-BbNWyqp5.d.ts} +4 -4
  59. package/dist/{frame-conversions-DDcNHkTb.d.ts → frame-conversions-CH7E2Iv_.d.ts} +1 -1
  60. package/dist/{fused-path-C5pp0PJU.d.ts → fused-path-DOKzVMiO.d.ts} +1 -1
  61. package/dist/geo/h3-proximity.d.ts +1 -1
  62. package/dist/geo/index.d.ts +1 -1
  63. package/dist/{gps-CDKDQokE.d.ts → gps-CX5b9g3s.d.ts} +8 -1
  64. package/dist/{gps-anchor-CEjGqEVD.d.ts → gps-anchor-BaqyRsPC.d.ts} +14 -4
  65. package/dist/{gps-ar-pose-sampler-DEGNk2CI.d.ts → gps-ar-pose-sampler-BOOV0jJk.d.ts} +1 -1
  66. package/dist/{gps-event-coordinator-BWpgBrHq.d.ts → gps-event-coordinator-03rVh_us.d.ts} +16 -29
  67. package/dist/{image-capture-DVcuqMtX.js → image-capture-BUqqsOi3.js} +11 -9
  68. package/dist/{image-capture-Bp6Pd4Md.d.ts → image-capture-Cr_rljeV.d.ts} +3 -3
  69. package/dist/{index-cCQWuYqy.d.ts → index-C2Bo0buN.d.ts} +4 -6
  70. package/dist/{index-B6iBnO_K.d.ts → index-CuHaGY0F.d.ts} +1 -1
  71. package/dist/index.d.ts +82 -82
  72. package/dist/index.js +16 -14
  73. package/dist/{leaflet-map-overlay-C8GS4cUy.d.ts → leaflet-map-overlay-QhF199BW.d.ts} +1 -1
  74. package/dist/{map-data-CUnTzRIC.d.ts → map-data-D8sSxpOr.d.ts} +1 -1
  75. package/dist/{map-overlay-draw-6WJeq0Kg.d.ts → map-overlay-draw-1E61FLKs.d.ts} +1 -1
  76. package/dist/median-Bla_W50f.js +44 -0
  77. package/dist/{null-storage-backend-B1-jlpin.d.ts → null-storage-backend-DXXuwG8T.d.ts} +2 -2
  78. package/dist/{occlusion-mesh-kXCQ2FM1.d.ts → occlusion-mesh-CZ4i_SW2.d.ts} +3 -11
  79. package/dist/{occupancy-grid-BV7RhB7I.d.ts → occupancy-grid-f0I07UxI.d.ts} +2 -2
  80. package/dist/{occupancy-mesher-C2ecWhNp.d.ts → occupancy-mesher-BqnRd10x.d.ts} +4 -9
  81. package/dist/{opfs-storage-backend-D6Z03fML.d.ts → opfs-storage-backend-D1ZpeNEL.d.ts} +2 -2
  82. package/dist/{persistence-middleware-CG-t08X4.d.ts → persistence-middleware-CI4Cetnl.d.ts} +1 -1
  83. package/dist/{planar-pnp-D7bc_rLX.d.ts → planar-pnp-CPLhg5MX.d.ts} +1 -1
  84. package/dist/{qr-debug-view-BJooqbiP.d.ts → qr-debug-view-BmbWo06j.d.ts} +1 -1
  85. package/dist/{qr-derived-pose-BwNWn8oV.d.ts → qr-derived-pose-DEYT85ul.d.ts} +2 -2
  86. package/dist/{qr-detected-slice-TzVb8bij.d.ts → qr-detected-slice-CPEkGbxh.d.ts} +4 -4
  87. package/dist/{qr-detection-controller-Bo4XfQTP.d.ts → qr-detection-controller-IcMRpTjV.d.ts} +3 -3
  88. package/dist/{qr-frontend-BPURlh3S.d.ts → qr-frontend-61SKPSyU.d.ts} +1 -1
  89. package/dist/{qr-pose-aggregation-CypnmjA-.d.ts → qr-pose-aggregation-BL6gfl0s.d.ts} +1 -1
  90. package/dist/{qr-pose-aggregation-DBiaLW0O.js → qr-pose-aggregation-H-O_Jjz9.js} +5 -10
  91. package/dist/{qr-size-depth-context-apAOmbrZ.d.ts → qr-size-depth-context-DJsYqbqY.d.ts} +2 -2
  92. package/dist/{qr-size-measurer-DLb33geH.js → qr-size-measurer-BVOIg-He.js} +6 -12
  93. package/dist/{qr-size-measurer-DxiMqRUw.d.ts → qr-size-measurer-Bl_i-umk.d.ts} +3 -3
  94. package/dist/{recording-options-DYKWVI93.d.ts → recording-options-Cai9D14V.d.ts} +16 -9
  95. package/dist/{recording-replayer-BJ8Lf0QY.d.ts → recording-replayer-DyIN13nG.d.ts} +2 -2
  96. package/dist/{recording-slice-BW8SiLo1.d.ts → recording-slice-DziOl7P5.d.ts} +2 -2
  97. package/dist/{replay-engine-DmCAc7WM.d.ts → replay-engine-DAymjsd1.d.ts} +1 -1
  98. package/dist/{replay-scene-zJ8SFDjE.d.ts → replay-scene-CZdWgcpc.d.ts} +3 -3
  99. package/dist/sensors/absolute-orientation.d.ts +1 -1
  100. package/dist/sensors/gps-error-handler.d.ts +1 -1
  101. package/dist/sensors/gps.d.ts +1 -1
  102. package/dist/sensors/gps.js +10 -8
  103. package/dist/sensors/index.d.ts +4 -4
  104. package/dist/sensors/index.js +1 -1
  105. package/dist/sensors/permission-checker.d.ts +1 -1
  106. package/dist/sensors/permission-checker.js +71 -40
  107. package/dist/state/app-selectors.d.ts +1 -1
  108. package/dist/state/combined-root-state.d.ts +1 -1
  109. package/dist/state/create-slam-app-store.d.ts +1 -1
  110. package/dist/state/create-slam-app-store.js +1 -1
  111. package/dist/state/gps-ar-pose-sampler.d.ts +2 -3
  112. package/dist/state/gps-ar-pose-sampler.js +1 -1
  113. package/dist/state/gps-event-coordinator.d.ts +2 -1
  114. package/dist/state/gps-event-coordinator.js +4 -46
  115. package/dist/state/index.d.ts +19 -19
  116. package/dist/state/index.js +5 -3
  117. package/dist/state/persistence-middleware.d.ts +1 -1
  118. package/dist/state/qr-detected-slice.d.ts +3 -3
  119. package/dist/state/qr-detected-slice.js +5 -9
  120. package/dist/state/recording-options.d.ts +1 -1
  121. package/dist/state/recording-options.js +74 -45
  122. package/dist/state/recording-replayer.d.ts +2 -2
  123. package/dist/state/recording-replayer.js +1 -1
  124. package/dist/state/recording-slice.d.ts +1 -1
  125. package/dist/state/replay-engine.d.ts +1 -1
  126. package/dist/state/store-subscribers.d.ts +2 -2
  127. package/dist/state/store-subscribers.js +23 -6
  128. package/dist/state/subscribe-to-selector.d.ts +1 -1
  129. package/dist/state/tracking-quality.d.ts +1 -1
  130. package/dist/state/tracking-quality.js +14 -11
  131. package/dist/state/tracking-slice.d.ts +1 -1
  132. package/dist/{state-BeKvn4B-.js → state-U45ioVyB.js} +2 -3
  133. package/dist/storage/file-system-utils.d.ts +1 -1
  134. package/dist/storage/index.d.ts +8 -8
  135. package/dist/storage/null-storage-backend.d.ts +1 -1
  136. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  137. package/dist/storage/opfs-storage.d.ts +1 -1
  138. package/dist/storage/storage-backend.d.ts +1 -1
  139. package/dist/storage/zip-coverage-embed.d.ts +1 -1
  140. package/dist/storage/zip-export.d.ts +1 -1
  141. package/dist/storage/zip-export.js +10 -4
  142. package/dist/storage/zip-reader.d.ts +1 -1
  143. package/dist/{storage-backend-sEtmM4yW.d.ts → storage-backend-BX7egQKi.d.ts} +1 -1
  144. package/dist/{store-subscribers-DJUErW-o.d.ts → store-subscribers-DtwakLrQ.d.ts} +2 -2
  145. package/dist/{subscribe-to-selector-dQV8SpsO.d.ts → subscribe-to-selector-Cgo9JTfS.d.ts} +1 -1
  146. package/dist/test-utils/browser-mocks.d.ts +1 -1
  147. package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
  148. package/dist/{tracking-slice-DMkHlbny.d.ts → tracking-slice-Bt2OEQhA.d.ts} +1 -1
  149. package/dist/types/ar-types.d.ts +2 -2
  150. package/dist/types/ar-types.js +31 -1
  151. package/dist/types/geo-types.d.ts +1 -1
  152. package/dist/types/index.d.ts +3 -3
  153. package/dist/types/index.js +2 -1
  154. package/dist/utils/concurrency.d.ts +1 -1
  155. package/dist/utils/failure-tracker.d.ts +1 -1
  156. package/dist/utils/format-file-size.d.ts +1 -1
  157. package/dist/utils/fused-path.d.ts +1 -1
  158. package/dist/utils/fused-path.js +1 -1
  159. package/dist/utils/index.d.ts +7 -7
  160. package/dist/utils/index.js +1 -1
  161. package/dist/utils/list-formatter.d.ts +1 -1
  162. package/dist/utils/logger.d.ts +1 -1
  163. package/dist/utils/logger.js +30 -20
  164. package/dist/visualization/accuracy-circles.d.ts +1 -1
  165. package/dist/visualization/alignment-lerper.d.ts +1 -1
  166. package/dist/visualization/alignment-lerper.js +20 -5
  167. package/dist/visualization/ar-world-group-alignment.d.ts +1 -1
  168. package/dist/visualization/ar-world-group-alignment.js +1 -1
  169. package/dist/visualization/camera-follower.d.ts +1 -1
  170. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  171. package/dist/visualization/frame-conversions.d.ts +1 -1
  172. package/dist/visualization/frustum-visibility.d.ts +1 -1
  173. package/dist/visualization/gps-anchor.d.ts +1 -1
  174. package/dist/visualization/gps-anchor.js +43 -18
  175. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  176. package/dist/visualization/gps-event-markers.d.ts +1 -1
  177. package/dist/visualization/gps-event-markers.js +1 -1
  178. package/dist/visualization/hit-test-reticle.d.ts +1 -1
  179. package/dist/visualization/index.d.ts +19 -19
  180. package/dist/visualization/index.js +2 -2
  181. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  182. package/dist/visualization/leaflet-map-overlay.js +1 -1
  183. package/dist/visualization/lerp-utils.d.ts +1 -1
  184. package/dist/visualization/map-data.d.ts +1 -1
  185. package/dist/visualization/map-data.js +1 -1
  186. package/dist/visualization/map-overlay-draw.d.ts +1 -1
  187. package/dist/visualization/map-overlay.d.ts +1 -1
  188. package/dist/visualization/occluder-mesh-driver.d.ts +2 -2
  189. package/dist/visualization/occlusion-mesh.d.ts +1 -1
  190. package/dist/visualization/occlusion-mesh.js +1 -11
  191. package/dist/visualization/three-dispose.d.ts +1 -1
  192. package/dist/visualization/vis-colors.d.ts +1 -1
  193. package/dist/{webxr-session-BWCpGd-2.d.ts → webxr-session-CGFZ429B.d.ts} +8 -8
  194. package/dist/{webxr-session-BCP2XK7k.js → webxr-session-DWKUsCN9.js} +7 -7
  195. package/package.json +4 -4
  196. /package/dist/{absolute-orientation-BAxc15J6.d.ts → absolute-orientation-C_IxDR_j.d.ts} +0 -0
  197. /package/dist/{accuracy-circles-DkWBkF5g.d.ts → accuracy-circles-BE7tbvYV.d.ts} +0 -0
  198. /package/dist/{bresenham3d-DGc4nIb-.d.ts → bresenham3d-D-t9i_b5.d.ts} +0 -0
  199. /package/dist/{camera-blit-capture-BimSdyih.d.ts → camera-blit-capture-BlC-arRb.d.ts} +0 -0
  200. /package/dist/{camera-follower-DfBm2J5i.d.ts → camera-follower-B6zA3dy9.d.ts} +0 -0
  201. /package/dist/{capability-checker-BTTpygvZ.d.ts → capability-checker-DEo-ktWI.d.ts} +0 -0
  202. /package/dist/{capture-failure-tracker-_BVfhpxv.d.ts → capture-failure-tracker-BAUKjtXU.d.ts} +0 -0
  203. /package/dist/{capture-motion-gate-BGoAMkmf.d.ts → capture-motion-gate-BmjiWUJv.d.ts} +0 -0
  204. /package/dist/{capture-motion-gate-_NdTSwKi.js → capture-motion-gate-D1eyGC_o.js} +0 -0
  205. /package/dist/{cell-key-DIB4rOTV.js → cell-key-Bj-eYTLA.js} +0 -0
  206. /package/dist/{chromium-camera-access-workaround-C6yJLXz9.d.ts → chromium-camera-access-workaround-DCd8SP2N.d.ts} +0 -0
  207. /package/dist/{concurrency-DPeGBH0X.d.ts → concurrency-DW0jQo3G.d.ts} +0 -0
  208. /package/dist/{css3d-renderer-manager-CPpVtvgs.d.ts → css3d-renderer-manager-DbrSY7Mh.d.ts} +0 -0
  209. /package/dist/{failure-tracker-CeKf5HIc.d.ts → failure-tracker-B7fzPfZo.d.ts} +0 -0
  210. /package/dist/{file-system-utils-DueXHxo9.d.ts → file-system-utils-CfLTj5Ra.d.ts} +0 -0
  211. /package/dist/{format-file-size-DxN-EBLc.d.ts → format-file-size-Da8rZgfs.d.ts} +0 -0
  212. /package/dist/{frame-loop-7GBMBu68.d.ts → frame-loop-7HigCj7m.d.ts} +0 -0
  213. /package/dist/{frustum-visibility-CokkgS_i.d.ts → frustum-visibility-COPfzruF.d.ts} +0 -0
  214. /package/dist/{geo-types-DrGVu8nS.d.ts → geo-types-BfDK8kJu.d.ts} +0 -0
  215. /package/dist/{geodesic-angle-BTldfFgs.js → geodesic-angle-HXBWiXiI.js} +0 -0
  216. /package/dist/{gps-compass-cubes-1mooS3BS.d.ts → gps-compass-cubes-CT3TWctJ.d.ts} +0 -0
  217. /package/dist/{gps-error-handler-C34GQuTu.d.ts → gps-error-handler-DjVuLXve.d.ts} +0 -0
  218. /package/dist/{gps-event-markers-Di2nBzx-.d.ts → gps-event-markers-BsC2Ynlh.d.ts} +0 -0
  219. /package/dist/{h3-proximity-D0GTHQmr.d.ts → h3-proximity-pFluGfwL.d.ts} +0 -0
  220. /package/dist/{hit-test-reticle-CaQbrhbk.d.ts → hit-test-reticle-DhnCMOsc.d.ts} +0 -0
  221. /package/dist/{image-quality-BMx2ko9-.d.ts → image-quality-BjBLoTec.d.ts} +0 -0
  222. /package/dist/{index-DXPVzOpP.d.ts → index-CjxbDm8W.d.ts} +0 -0
  223. /package/dist/{index-D74JTX4I.d.ts → index-Nr3qg4IH.d.ts} +0 -0
  224. /package/dist/{leaflet-map-overlay-CBWPvaX9.js → leaflet-map-overlay-BRkUhZMD.js} +0 -0
  225. /package/dist/{lerp-utils-Qs8OhumS.d.ts → lerp-utils-bwMwVCpU.d.ts} +0 -0
  226. /package/dist/{list-formatter-DLFDnS70.d.ts → list-formatter-1ttG18MQ.d.ts} +0 -0
  227. /package/dist/{logger-CqTd5Kpk.d.ts → logger-B4StJUDb.d.ts} +0 -0
  228. /package/dist/{map-data-1tF5gcYV.js → map-data-D3oE8AQP.js} +0 -0
  229. /package/dist/{map-overlay-BCQgvIgU.d.ts → map-overlay-0yJOcEVO.d.ts} +0 -0
  230. /package/dist/{opfs-storage-CTkxvxN4.d.ts → opfs-storage-S_odkCk1.d.ts} +0 -0
  231. /package/dist/{permission-checker-B-VtjnBA.d.ts → permission-checker-D1C5zvo-.d.ts} +0 -0
  232. /package/dist/{qr-detection-controller-B-tLVd-S.js → qr-detection-controller-bRTJXC6G.js} +0 -0
  233. /package/dist/{qr-pose-y3vaEd6x.d.ts → qr-pose-CCTF1PP0.d.ts} +0 -0
  234. /package/dist/{scene-node-names-CGb-ylBd.d.ts → scene-node-names-DWzhE7Ro.d.ts} +0 -0
  235. /package/dist/{session-disposers-BPrMplIC.js → session-disposers-BZS-hi8u.js} +0 -0
  236. /package/dist/{three-dispose-BMOAmPhb.d.ts → three-dispose-C9mdpSRX.d.ts} +0 -0
  237. /package/dist/{vis-colors-C7HI0u9_.d.ts → vis-colors-DjStl_tD.d.ts} +0 -0
  238. /package/dist/{webxr-nue-basis-CaCnYxuq.d.ts → webxr-nue-basis-C3vTqkE2.d.ts} +0 -0
  239. /package/dist/{xr-camera-texture-q0eIDSRg.d.ts → xr-camera-texture-C6Z4d7RR.d.ts} +0 -0
  240. /package/dist/{xr-error-handler-uVGDu9IX.d.ts → xr-error-handler-D9y5r8ok.d.ts} +0 -0
  241. /package/dist/{xr-frame-loop-DX3JPpAU.d.ts → xr-frame-loop-25gM4B0K.d.ts} +0 -0
  242. /package/dist/{zip-coverage-embed-ncVbaZAz.d.ts → zip-coverage-embed-BrodRLq0.d.ts} +0 -0
  243. /package/dist/{zip-export-CtiUnAlJ.d.ts → zip-export-CuBimX1J.d.ts} +0 -0
  244. /package/dist/{zip-reader-BzENzMH6.d.ts → zip-reader-BHc_b_iA.d.ts} +0 -0
@@ -1,4 +1,5 @@
1
- import { t as geodesicAngleRad } from "./geodesic-angle-BTldfFgs.js";
1
+ import { n as lowerMedian } from "./median-Bla_W50f.js";
2
+ import { t as geodesicAngleRad } from "./geodesic-angle-HXBWiXiI.js";
2
3
  import { quat } from "gl-matrix";
3
4
  //#region ../src/ar/qr-pose-aggregation.ts
4
5
  /**
@@ -118,17 +119,11 @@ function averageRotation(quats, options = {}) {
118
119
  maxAngleDeg: refined.maxAngleRad * RAD2DEG
119
120
  };
120
121
  }
121
- /** Per-axis median of a numeric list (lower-middle for even n, matching
122
- * `medianQrPosition` in the slice so the two agree on the same data). */
123
- function medianOf(values) {
124
- const sorted = [...values].sort((a, b) => a - b);
125
- return sorted[Math.floor((sorted.length - 1) / 2)];
126
- }
127
122
  function medianPosition(positions) {
128
123
  return [
129
- medianOf(positions.map((p) => p[0])),
130
- medianOf(positions.map((p) => p[1])),
131
- medianOf(positions.map((p) => p[2]))
124
+ lowerMedian(positions.map((p) => p[0])),
125
+ lowerMedian(positions.map((p) => p[1])),
126
+ lowerMedian(positions.map((p) => p[2]))
132
127
  ];
133
128
  }
134
129
  /** Max absolute per-axis deviation from `center` across all positions. */
@@ -1,5 +1,5 @@
1
- import { i as DepthSample } from "./ar-types-Cc5yvBwn.js";
2
- import { n as QrSizeDepthContext } from "./qr-size-measurer-DxiMqRUw.js";
1
+ import { i as DepthSample } from "./ar-types-CBafnxhE.js";
2
+ import { n as QrSizeDepthContext } from "./qr-size-measurer-Bl_i-umk.js";
3
3
 
4
4
  //#region ../src/ar/qr-size-depth-context.d.ts
5
5
  /**
@@ -1,3 +1,4 @@
1
+ import { t as interpolatingMedian } from "./median-Bla_W50f.js";
1
2
  import { vec3 } from "gl-matrix";
2
3
  //#region ../src/ar/qr-size-from-depth.ts
3
4
  /**
@@ -40,13 +41,6 @@ const PLANE_INLIER_FLOOR_M = .005;
40
41
  function dist(a, b) {
41
42
  return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
42
43
  }
43
- /** Median of a numeric list (mean of the middle two for even n). */
44
- function median(values) {
45
- const sorted = [...values].sort((a, b) => a - b);
46
- const n = sorted.length;
47
- const mid = n >> 1;
48
- return n % 2 === 1 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
49
- }
50
44
  /**
51
45
  * Estimate a QR's physical side length from one detection's depth samples.
52
46
  *
@@ -109,7 +103,7 @@ function estimateQrSizeFromDepth(corners, interiorSamples, unprojector) {
109
103
  const planeErr = maxPlaneOffset / meanEdge;
110
104
  const quality = Math.max(0, Math.min(1, 1 - Math.max(edgeErr, diagErr, planeErr)));
111
105
  return {
112
- sizeM: median(edges),
106
+ sizeM: interpolatingMedian(edges),
113
107
  quality
114
108
  };
115
109
  }
@@ -250,7 +244,7 @@ function fitPlaneRobust(points) {
250
244
  nx /= len;
251
245
  ny /= len;
252
246
  nz /= len;
253
- const medSq = median(points.map((p) => {
247
+ const medSq = interpolatingMedian(points.map((p) => {
254
248
  const d = nx * (p[0] - a[0]) + ny * (p[1] - a[1]) + nz * (p[2] - a[2]);
255
249
  return d * d;
256
250
  }));
@@ -353,7 +347,7 @@ function estimateQrSizeFromDepthDense(cornerScreens, samples, unprojector) {
353
347
  const planeErr = plane.rms / meanEdge;
354
348
  const quality = Math.max(0, Math.min(1, 1 - Math.max(edgeErr, diagErr, planeErr)));
355
349
  return {
356
- sizeM: median(edges),
350
+ sizeM: interpolatingMedian(edges),
357
351
  quality
358
352
  };
359
353
  }
@@ -369,8 +363,8 @@ function createQrSizeAccumulator(options = {}) {
369
363
  let everConverged = false;
370
364
  function estimate() {
371
365
  if (sizes.length === 0) return { ...UNKNOWN };
372
- const med = median(sizes);
373
- const spreadM = 1.4826 * median(sizes.map((s) => Math.abs(s - med))) / Math.sqrt(sizes.length);
366
+ const med = interpolatingMedian(sizes);
367
+ const spreadM = 1.4826 * interpolatingMedian(sizes.map((s) => Math.abs(s - med))) / Math.sqrt(sizes.length);
374
368
  if (sizes.length >= minSamples && spreadM <= maxSpreadM) everConverged = true;
375
369
  return {
376
370
  status: everConverged ? "estimated" : "measuring",
@@ -1,6 +1,6 @@
1
- import { r as DepthPoint } from "./ar-types-Cc5yvBwn.js";
2
- import { t as DepthUnprojector } from "./depth-unprojection-DRdBU90S.js";
3
- import { r as Point2 } from "./qr-pose-y3vaEd6x.js";
1
+ import { r as DepthPoint } from "./ar-types-CBafnxhE.js";
2
+ import { t as DepthUnprojector } from "./depth-unprojection-JKkeqJrV.js";
3
+ import { r as Point2 } from "./qr-pose-CCTF1PP0.js";
4
4
  import { Vector3 } from "gps-plus-slam-js";
5
5
 
6
6
  //#region ../src/ar/qr-size-from-depth.d.ts
@@ -1,5 +1,5 @@
1
- import { t as MotionFilterConfig } from "./capture-motion-gate-BGoAMkmf.js";
2
- import { a as QualityFilterConfig } from "./image-quality-BMx2ko9-.js";
1
+ import { t as MotionFilterConfig } from "./capture-motion-gate-BmjiWUJv.js";
2
+ import { a as QualityFilterConfig } from "./image-quality-BjBLoTec.js";
3
3
 
4
4
  //#region ../src/state/recording-options.d.ts
5
5
  /**
@@ -440,12 +440,23 @@ declare const DEPTH_CONSTRAINTS: {
440
440
  readonly step: 1;
441
441
  };
442
442
  };
443
- /** Validation constraints for image options */
443
+ /**
444
+ * Validation constraints for image options.
445
+ *
446
+ * `intervalMs` min/step lowered 1000/500 → 250/250 (2026-07-10) so
447
+ * splat-style object scans can capture up to 4 Hz — at the old 1 Hz floor a
448
+ * slow orbit yields ~1 frame/m, too sparse for Gaussian-splat reconstruction
449
+ * (50–150+ frames/object). An interval faster than the readback+encode path
450
+ * cannot overlap captures: `captureInProgress` serialises them and the
451
+ * interval is measured from the actual capture time, so the pipeline
452
+ * self-limits. See
453
+ * GpsPlusSlamJs_Docs/docs/2026-07-10-splat-orbit-capture-rate-finding.md.
454
+ */
444
455
  declare const IMAGE_CONSTRAINTS: {
445
456
  readonly intervalMs: {
446
- readonly min: 1000;
457
+ readonly min: 250;
447
458
  readonly max: 10000;
448
- readonly step: 500;
459
+ readonly step: 250;
449
460
  };
450
461
  readonly quality: {
451
462
  readonly min: 0.3;
@@ -589,10 +600,6 @@ declare const QR_CONSTRAINTS: {
589
600
  readonly step: 128;
590
601
  };
591
602
  };
592
- /**
593
- * Validate and normalize AR crash isolation flags.
594
- * Missing or invalid values fall back to defaults.
595
- */
596
603
  declare function validateArCrashIsolationOptions(options: Partial<ArCrashIsolationOptions>): ArCrashIsolationOptions;
597
604
  /**
598
605
  * Validate and normalize the compass alignment debug toggles. Boolean-or-default
@@ -1,5 +1,5 @@
1
- import { N as CombinedRootState } from "./create-slam-app-store-D1QSMuKu.js";
2
- import { i as RecordedAction } from "./zip-reader-BzENzMH6.js";
1
+ import { N as CombinedRootState } from "./create-slam-app-store-CH31erpP.js";
2
+ import { i as RecordedAction } from "./zip-reader-BHc_b_iA.js";
3
3
 
4
4
  //#region ../src/state/recording-replayer.d.ts
5
5
  /**
@@ -1,5 +1,5 @@
1
- import { i as DepthSample } from "./ar-types-Cc5yvBwn.js";
2
- import { y as RecordingOptions } from "./recording-options-DYKWVI93.js";
1
+ import { i as DepthSample } from "./ar-types-CBafnxhE.js";
2
+ import { y as RecordingOptions } from "./recording-options-Cai9D14V.js";
3
3
  import * as _$_reduxjs_toolkit0 from "@reduxjs/toolkit";
4
4
 
5
5
  //#region ../src/state/recording-slice.d.ts
@@ -1,4 +1,4 @@
1
- import { i as SlamAppStore } from "./create-slam-app-store-D1QSMuKu.js";
1
+ import { i as SlamAppStore } from "./create-slam-app-store-CH31erpP.js";
2
2
  import { ReducersMapObject } from "@reduxjs/toolkit";
3
3
 
4
4
  //#region ../src/state/replay-engine.d.ts
@@ -1,6 +1,6 @@
1
- import { t as Css3dRendererManager } from "./css3d-renderer-manager-CPpVtvgs.js";
2
- import { t as CameraFollower } from "./camera-follower-DfBm2J5i.js";
3
- import { t as AlignmentLerper } from "./alignment-lerper-gD70k7Fq.js";
1
+ import { t as Css3dRendererManager } from "./css3d-renderer-manager-DbrSY7Mh.js";
2
+ import { t as CameraFollower } from "./camera-follower-B6zA3dy9.js";
3
+ import { t as AlignmentLerper } from "./alignment-lerper-B4COh_0p.js";
4
4
  import * as THREE from "three";
5
5
  import { OrbitControls } from "three/addons/controls/OrbitControls.js";
6
6
 
@@ -1,2 +1,2 @@
1
- import { a as startAbsoluteOrientationWatch, i as isAbsoluteOrientationAvailable, n as AbsoluteOrientationStatus, o as stopAbsoluteOrientationWatch, r as getLatestAbsoluteOrientation, t as AbsoluteOrientationReading } from "../absolute-orientation-BAxc15J6.js";
1
+ import { a as startAbsoluteOrientationWatch, i as isAbsoluteOrientationAvailable, n as AbsoluteOrientationStatus, o as stopAbsoluteOrientationWatch, r as getLatestAbsoluteOrientation, t as AbsoluteOrientationReading } from "../absolute-orientation-C_IxDR_j.js";
2
2
  export { AbsoluteOrientationReading, AbsoluteOrientationStatus, getLatestAbsoluteOrientation, isAbsoluteOrientationAvailable, startAbsoluteOrientationWatch, stopAbsoluteOrientationWatch };
@@ -1,2 +1,2 @@
1
- import { a as getGpsErrorMessage, i as createGpsErrorHandler, n as GPS_ERROR_MESSAGES, r as GPS_ERROR_MESSAGE_UNKNOWN, t as GPS_ERROR_CODES } from "../gps-error-handler-C34GQuTu.js";
1
+ import { a as getGpsErrorMessage, i as createGpsErrorHandler, n as GPS_ERROR_MESSAGES, r as GPS_ERROR_MESSAGE_UNKNOWN, t as GPS_ERROR_CODES } from "../gps-error-handler-DjVuLXve.js";
2
2
  export { GPS_ERROR_CODES, GPS_ERROR_MESSAGES, GPS_ERROR_MESSAGE_UNKNOWN, createGpsErrorHandler, getGpsErrorMessage };
@@ -1,2 +1,2 @@
1
- import { a as startOrientationWatch, i as startGpsWatch, n as RawDeviceOrientation, o as stopGpsWatch, r as requestOrientationPermission, s as stopOrientationWatch, t as GpsPosition } from "../gps-CDKDQokE.js";
1
+ import { a as startOrientationWatch, i as startGpsWatch, n as RawDeviceOrientation, o as stopGpsWatch, r as requestOrientationPermission, s as stopOrientationWatch, t as GpsPosition } from "../gps-CX5b9g3s.js";
2
2
  export { GpsPosition, RawDeviceOrientation, requestOrientationPermission, startGpsWatch, startOrientationWatch, stopGpsWatch, stopOrientationWatch };
@@ -1,4 +1,5 @@
1
1
  import { createLogger } from "../utils/logger.js";
2
+ import { requestOrientationPermission as requestOrientationPermission$1 } from "./permission-checker.js";
2
3
  //#region ../src/sensors/gps.ts
3
4
  /**
4
5
  * GPS Module
@@ -78,16 +79,17 @@ function stopOrientationWatch() {
78
79
  }
79
80
  }
80
81
  /**
81
- * Request permission for device orientation (required on iOS 13+)
82
+ * Request permission for device orientation (required on iOS 13+).
83
+ *
84
+ * Boolean-contract wrapper around the permission-checker's
85
+ * `requestOrientationPermission` superset (quality-review A-4 — the two
86
+ * public implementations had already drifted once; this one lacked the
87
+ * missing-API guard and threw a ReferenceError where `DeviceOrientationEvent`
88
+ * does not exist). `true` only for an explicit grant (or the non-iOS
89
+ * no-permission-needed case); denied, failed, or unsupported → `false`.
82
90
  */
83
91
  async function requestOrientationPermission() {
84
- const DeviceOrientationEventWithPermission = DeviceOrientationEvent;
85
- if (typeof DeviceOrientationEventWithPermission.requestPermission === "function") try {
86
- return await DeviceOrientationEventWithPermission.requestPermission() === "granted";
87
- } catch {
88
- return false;
89
- }
90
- return true;
92
+ return (await requestOrientationPermission$1()).granted === true;
91
93
  }
92
94
  //#endregion
93
95
  export { requestOrientationPermission, startGpsWatch, startOrientationWatch, stopGpsWatch, stopOrientationWatch };
@@ -1,5 +1,5 @@
1
- import { a as startOrientationWatch, i as startGpsWatch, n as RawDeviceOrientation, o as stopGpsWatch, r as requestOrientationPermission, s as stopOrientationWatch, t as GpsPosition } from "../gps-CDKDQokE.js";
2
- import { a as checkCameraPermission, c as checkOrientationPermission, d as requestCameraPermission, f as requestGeolocationPermission, g as setFileSystemState, h as resetFileSystemState, i as checkAllPermissions, l as checkWebXRSupport, m as requestWebXRWithDepthPermission, n as PermissionStatus, o as checkFileSystemPermission, p as requestOrientationPermission$1, s as checkGeolocationPermission, t as PermissionCheckResult, u as requestAllPermissions } from "../permission-checker-B-VtjnBA.js";
3
- import { a as startAbsoluteOrientationWatch, i as isAbsoluteOrientationAvailable, n as AbsoluteOrientationStatus, o as stopAbsoluteOrientationWatch, r as getLatestAbsoluteOrientation, t as AbsoluteOrientationReading } from "../absolute-orientation-BAxc15J6.js";
4
- import { a as getGpsErrorMessage, i as createGpsErrorHandler, n as GPS_ERROR_MESSAGES, r as GPS_ERROR_MESSAGE_UNKNOWN, t as GPS_ERROR_CODES } from "../gps-error-handler-C34GQuTu.js";
1
+ import { a as startOrientationWatch, i as startGpsWatch, n as RawDeviceOrientation, o as stopGpsWatch, r as requestOrientationPermission, s as stopOrientationWatch, t as GpsPosition } from "../gps-CX5b9g3s.js";
2
+ import { a as checkCameraPermission, c as checkOrientationPermission, d as requestCameraPermission, f as requestGeolocationPermission, g as setFileSystemState, h as resetFileSystemState, i as checkAllPermissions, l as checkWebXRSupport, m as requestWebXRWithDepthPermission, n as PermissionStatus, o as checkFileSystemPermission, p as requestOrientationPermission$1, s as checkGeolocationPermission, t as PermissionCheckResult, u as requestAllPermissions } from "../permission-checker-D1C5zvo-.js";
3
+ import { a as startAbsoluteOrientationWatch, i as isAbsoluteOrientationAvailable, n as AbsoluteOrientationStatus, o as stopAbsoluteOrientationWatch, r as getLatestAbsoluteOrientation, t as AbsoluteOrientationReading } from "../absolute-orientation-C_IxDR_j.js";
4
+ import { a as getGpsErrorMessage, i as createGpsErrorHandler, n as GPS_ERROR_MESSAGES, r as GPS_ERROR_MESSAGE_UNKNOWN, t as GPS_ERROR_CODES } from "../gps-error-handler-DjVuLXve.js";
5
5
  export { type AbsoluteOrientationReading, type AbsoluteOrientationStatus, GPS_ERROR_CODES, GPS_ERROR_MESSAGES, GPS_ERROR_MESSAGE_UNKNOWN, type GpsPosition, type PermissionCheckResult, type PermissionStatus, type RawDeviceOrientation, checkAllPermissions, checkCameraPermission, checkFileSystemPermission, checkGeolocationPermission, checkOrientationPermission, checkWebXRSupport, createGpsErrorHandler, getGpsErrorMessage, getLatestAbsoluteOrientation, isAbsoluteOrientationAvailable, requestAllPermissions, requestCameraPermission, requestOrientationPermission as requestDeviceOrientationPermission, requestGeolocationPermission, requestOrientationPermission$1 as requestOrientationPermission, requestWebXRWithDepthPermission, resetFileSystemState, setFileSystemState, startAbsoluteOrientationWatch, startGpsWatch, startOrientationWatch, stopAbsoluteOrientationWatch, stopGpsWatch, stopOrientationWatch };
@@ -1,5 +1,5 @@
1
- import { getLatestAbsoluteOrientation, isAbsoluteOrientationAvailable, startAbsoluteOrientationWatch, stopAbsoluteOrientationWatch } from "./absolute-orientation.js";
2
1
  import { checkAllPermissions, checkCameraPermission, checkFileSystemPermission, checkGeolocationPermission, checkOrientationPermission, checkWebXRSupport, requestAllPermissions, requestCameraPermission, requestGeolocationPermission, requestOrientationPermission as requestOrientationPermission$1, requestWebXRWithDepthPermission, resetFileSystemState, setFileSystemState } from "./permission-checker.js";
3
2
  import { requestOrientationPermission, startGpsWatch, startOrientationWatch, stopGpsWatch, stopOrientationWatch } from "./gps.js";
3
+ import { getLatestAbsoluteOrientation, isAbsoluteOrientationAvailable, startAbsoluteOrientationWatch, stopAbsoluteOrientationWatch } from "./absolute-orientation.js";
4
4
  import { GPS_ERROR_CODES, GPS_ERROR_MESSAGES, GPS_ERROR_MESSAGE_UNKNOWN, createGpsErrorHandler, getGpsErrorMessage } from "./gps-error-handler.js";
5
5
  export { GPS_ERROR_CODES, GPS_ERROR_MESSAGES, GPS_ERROR_MESSAGE_UNKNOWN, checkAllPermissions, checkCameraPermission, checkFileSystemPermission, checkGeolocationPermission, checkOrientationPermission, checkWebXRSupport, createGpsErrorHandler, getGpsErrorMessage, getLatestAbsoluteOrientation, isAbsoluteOrientationAvailable, requestAllPermissions, requestCameraPermission, requestOrientationPermission as requestDeviceOrientationPermission, requestGeolocationPermission, requestOrientationPermission$1 as requestOrientationPermission, requestWebXRWithDepthPermission, resetFileSystemState, setFileSystemState, startAbsoluteOrientationWatch, startGpsWatch, startOrientationWatch, stopAbsoluteOrientationWatch, stopGpsWatch, stopOrientationWatch };
@@ -1,2 +1,2 @@
1
- import { _ as subscribePermissionChanges, a as checkCameraPermission, c as checkOrientationPermission, d as requestCameraPermission, f as requestGeolocationPermission, g as setFileSystemState, h as resetFileSystemState, i as checkAllPermissions, l as checkWebXRSupport, m as requestWebXRWithDepthPermission, n as PermissionStatus, o as checkFileSystemPermission, p as requestOrientationPermission, r as PermissionSubscription, s as checkGeolocationPermission, t as PermissionCheckResult, u as requestAllPermissions } from "../permission-checker-B-VtjnBA.js";
1
+ import { _ as subscribePermissionChanges, a as checkCameraPermission, c as checkOrientationPermission, d as requestCameraPermission, f as requestGeolocationPermission, g as setFileSystemState, h as resetFileSystemState, i as checkAllPermissions, l as checkWebXRSupport, m as requestWebXRWithDepthPermission, n as PermissionStatus, o as checkFileSystemPermission, p as requestOrientationPermission, r as PermissionSubscription, s as checkGeolocationPermission, t as PermissionCheckResult, u as requestAllPermissions } from "../permission-checker-D1C5zvo-.js";
2
2
  export { PermissionCheckResult, PermissionStatus, PermissionSubscription, checkAllPermissions, checkCameraPermission, checkFileSystemPermission, checkGeolocationPermission, checkOrientationPermission, checkWebXRSupport, requestAllPermissions, requestCameraPermission, requestGeolocationPermission, requestOrientationPermission, requestWebXRWithDepthPermission, resetFileSystemState, setFileSystemState, subscribePermissionChanges };
@@ -100,17 +100,19 @@ async function checkWebXRSupport() {
100
100
  }
101
101
  }
102
102
  /**
103
- * Check geolocation permission status without triggering a prompt.
104
- * Uses the Permissions API if available, otherwise returns unknown state.
103
+ * Shared Permissions-API status checker (quality-review C-2): probe-free
104
+ * query with the standard supported/granted/denied/prompt mapping. The two
105
+ * former copies (geolocation/camera) differed only in the API guard and the
106
+ * user-facing strings.
105
107
  */
106
- async function checkGeolocationPermission() {
107
- if (!navigator.geolocation) return {
108
+ async function checkPermissionViaQuery(options) {
109
+ if (!options.apiAvailable) return {
108
110
  supported: false,
109
111
  granted: null,
110
- error: "Geolocation API not available in this browser."
112
+ error: options.unsupportedError
111
113
  };
112
114
  if (navigator.permissions) try {
113
- const result = await navigator.permissions.query({ name: "geolocation" });
115
+ const result = await navigator.permissions.query({ name: options.name });
114
116
  if (result.state === "granted") return {
115
117
  supported: true,
116
118
  granted: true
@@ -118,7 +120,7 @@ async function checkGeolocationPermission() {
118
120
  else if (result.state === "denied") return {
119
121
  supported: true,
120
122
  granted: false,
121
- error: "Location access denied. Please enable in browser settings."
123
+ error: options.deniedError
122
124
  };
123
125
  return {
124
126
  supported: true,
@@ -131,6 +133,18 @@ async function checkGeolocationPermission() {
131
133
  };
132
134
  }
133
135
  /**
136
+ * Check geolocation permission status without triggering a prompt.
137
+ * Uses the Permissions API if available, otherwise returns unknown state.
138
+ */
139
+ async function checkGeolocationPermission() {
140
+ return checkPermissionViaQuery({
141
+ name: "geolocation",
142
+ apiAvailable: !!navigator.geolocation,
143
+ unsupportedError: "Geolocation API not available in this browser.",
144
+ deniedError: "Location access denied. Please enable in browser settings."
145
+ });
146
+ }
147
+ /**
134
148
  * Request geolocation permission by triggering a position request.
135
149
  * This will show the browser's permission prompt if not already granted.
136
150
  *
@@ -179,31 +193,12 @@ async function requestGeolocationPermission(timeoutMs = 1e4) {
179
193
  * Uses the Permissions API if available.
180
194
  */
181
195
  async function checkCameraPermission() {
182
- if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) return {
183
- supported: false,
184
- granted: null,
185
- error: "Camera API not available. Use HTTPS and a modern browser."
186
- };
187
- if (navigator.permissions) try {
188
- const result = await navigator.permissions.query({ name: "camera" });
189
- if (result.state === "granted") return {
190
- supported: true,
191
- granted: true
192
- };
193
- else if (result.state === "denied") return {
194
- supported: true,
195
- granted: false,
196
- error: "Camera access denied. Please enable in browser settings."
197
- };
198
- return {
199
- supported: true,
200
- granted: null
201
- };
202
- } catch {}
203
- return {
204
- supported: true,
205
- granted: null
206
- };
196
+ return checkPermissionViaQuery({
197
+ name: "camera",
198
+ apiAvailable: !!navigator.mediaDevices?.getUserMedia,
199
+ unsupportedError: "Camera API not available. Use HTTPS and a modern browser.",
200
+ deniedError: "Camera access denied. Please enable in browser settings."
201
+ });
207
202
  }
208
203
  /**
209
204
  * Request camera permission by triggering getUserMedia.
@@ -246,16 +241,33 @@ async function requestCameraPermission() {
246
241
  }
247
242
  }
248
243
  /**
244
+ * DeviceOrientationEvent availability + iOS 13+ permission-API probe
245
+ * (quality-review C-2 — this preamble used to be duplicated between the
246
+ * check and request paths). `available: false` ⇒ no orientation support at
247
+ * all; `requestPermission: null` ⇒ orientation works without a permission.
248
+ * The returned function is bound to `DeviceOrientationEvent` (it is a static
249
+ * method — an unbound call would lose `this`).
250
+ */
251
+ function getIosOrientationPermissionApi() {
252
+ if (typeof DeviceOrientationEvent === "undefined") return { available: false };
253
+ const withPermission = DeviceOrientationEvent;
254
+ return {
255
+ available: true,
256
+ requestPermission: typeof withPermission.requestPermission === "function" ? withPermission.requestPermission.bind(DeviceOrientationEvent) : null
257
+ };
258
+ }
259
+ /**
249
260
  * Check device orientation permission status.
250
261
  * On iOS 13+, this requires explicit permission request.
251
262
  */
252
263
  function checkOrientationPermission() {
253
- if (typeof DeviceOrientationEvent === "undefined") return Promise.resolve({
264
+ const api = getIosOrientationPermissionApi();
265
+ if (!api.available) return Promise.resolve({
254
266
  supported: false,
255
267
  granted: null,
256
268
  error: "Device orientation not supported."
257
269
  });
258
- if (typeof DeviceOrientationEvent.requestPermission === "function") return Promise.resolve({
270
+ if (api.requestPermission) return Promise.resolve({
259
271
  supported: true,
260
272
  granted: null
261
273
  });
@@ -269,14 +281,14 @@ function checkOrientationPermission() {
269
281
  * On other platforms, this is a no-op that returns granted.
270
282
  */
271
283
  async function requestOrientationPermission() {
272
- if (typeof DeviceOrientationEvent === "undefined") return {
284
+ const api = getIosOrientationPermissionApi();
285
+ if (!api.available) return {
273
286
  supported: false,
274
287
  granted: null,
275
288
  error: "Device orientation not supported."
276
289
  };
277
- const DeviceOrientationEventWithPermission = DeviceOrientationEvent;
278
- if (typeof DeviceOrientationEventWithPermission.requestPermission === "function") try {
279
- if (await DeviceOrientationEventWithPermission.requestPermission() === "granted") {
290
+ if (api.requestPermission) try {
291
+ if (await api.requestPermission() === "granted") {
280
292
  log.info("Orientation permission granted");
281
293
  return {
282
294
  supported: true,
@@ -317,10 +329,29 @@ async function checkAllPermissions() {
317
329
  camera,
318
330
  orientation,
319
331
  fileSystem,
320
- allMandatoryReady: webxr.supported && webxr.granted === true && geolocation.supported && geolocation.granted === true && camera.supported && camera.granted === true && fileSystem.supported && fileSystem.granted === true
332
+ allMandatoryReady: computeAllMandatoryReady({
333
+ webxr,
334
+ geolocation,
335
+ camera,
336
+ fileSystem
337
+ })
321
338
  };
322
339
  }
323
340
  /**
341
+ * The mandatory-set gate, written once (quality-review C-2 — the 8-clause
342
+ * boolean used to be spelled out twice and could drift): WebXR, Geolocation,
343
+ * Camera and FileSystem must all be supported AND granted. Orientation is
344
+ * deliberately not part of the mandatory set.
345
+ */
346
+ function computeAllMandatoryReady(result) {
347
+ return [
348
+ result.webxr,
349
+ result.geolocation,
350
+ result.camera,
351
+ result.fileSystem
352
+ ].every((p) => p.supported && p.granted === true);
353
+ }
354
+ /**
324
355
  * Subscribe to out-of-band permission changes.
325
356
  *
326
357
  * Today the recorder app only re-runs `checkAllPermissions()` at startup
@@ -414,7 +445,7 @@ async function requestAllPermissions() {
414
445
  if (result.orientation.supported && result.orientation.granted !== true) result.orientation = await requestOrientationPermission();
415
446
  if (result.geolocation.supported && result.geolocation.granted !== true) result.geolocation = await requestGeolocationPermission();
416
447
  result.fileSystem = checkFileSystemPermission();
417
- result.allMandatoryReady = result.webxr.supported && result.webxr.granted === true && result.geolocation.supported && result.geolocation.granted === true && result.camera.supported && result.camera.granted === true && result.fileSystem.supported && result.fileSystem.granted === true;
448
+ result.allMandatoryReady = computeAllMandatoryReady(result);
418
449
  return result;
419
450
  }
420
451
  /**
@@ -1,2 +1,2 @@
1
- import { a as selectOdometryRotations, i as selectOdometryPositions, n as selectFrameTilesInWebXR, o as selectZeroReference, r as selectGpsPositions, t as selectAlignmentMatrix } from "../app-selectors-BbAiCRUT.js";
1
+ import { a as selectOdometryRotations, i as selectOdometryPositions, n as selectFrameTilesInWebXR, o as selectZeroReference, r as selectGpsPositions, t as selectAlignmentMatrix } from "../app-selectors-CV7ggGoo.js";
2
2
  export { selectAlignmentMatrix, selectFrameTilesInWebXR, selectGpsPositions, selectOdometryPositions, selectOdometryRotations, selectZeroReference };
@@ -1,2 +1,2 @@
1
- import { N as CombinedRootState } from "../create-slam-app-store-D1QSMuKu.js";
1
+ import { N as CombinedRootState } from "../create-slam-app-store-CH31erpP.js";
2
2
  export { CombinedRootState };
@@ -1,2 +1,2 @@
1
- import { a as SlamAppStoreOptions, i as SlamAppStore, n as SlamAppMiddleware, o as createSlamAppStore, r as SlamAppRootState, t as SlamAppCombinedState } from "../create-slam-app-store-D1QSMuKu.js";
1
+ import { a as SlamAppStoreOptions, i as SlamAppStore, n as SlamAppMiddleware, o as createSlamAppStore, r as SlamAppRootState, t as SlamAppCombinedState } from "../create-slam-app-store-CH31erpP.js";
2
2
  export { SlamAppCombinedState, SlamAppMiddleware, SlamAppRootState, SlamAppStore, SlamAppStoreOptions, createSlamAppStore };
@@ -1,2 +1,2 @@
1
- import { t as createSlamAppStore } from "../create-slam-app-store-DXiAnJwR.js";
1
+ import { t as createSlamAppStore } from "../create-slam-app-store-DLv5ZwqU.js";
2
2
  export { createSlamAppStore };
@@ -1,4 +1,3 @@
1
- import { t as ARPose } from "../ar-types-Cc5yvBwn.js";
2
- import { o as extractOdomPosition, s as extractOdomRotation } from "../gps-event-coordinator-BWpgBrHq.js";
3
- import { i as captureGpsAnchorSample, n as GpsAnchorSample, r as GpsAnchorSampleGpsPoint, t as CaptureGpsAnchorSampleOptions } from "../gps-ar-pose-sampler-DEGNk2CI.js";
1
+ import { c as extractOdomPosition, l as extractOdomRotation, t as ARPose } from "../ar-types-CBafnxhE.js";
2
+ import { i as captureGpsAnchorSample, n as GpsAnchorSample, r as GpsAnchorSampleGpsPoint, t as CaptureGpsAnchorSampleOptions } from "../gps-ar-pose-sampler-BOOV0jJk.js";
4
3
  export { ARPose, CaptureGpsAnchorSampleOptions, GpsAnchorSample, GpsAnchorSampleGpsPoint, captureGpsAnchorSample, extractOdomPosition, extractOdomRotation };
@@ -1,4 +1,4 @@
1
- import { extractOdomPosition, extractOdomRotation } from "./gps-event-coordinator.js";
1
+ import { extractOdomPosition, extractOdomRotation } from "../types/ar-types.js";
2
2
  //#region ../src/state/gps-ar-pose-sampler.ts
3
3
  /**
4
4
  * Capture a GPS-AR pose snapshot. Extracts `odomPosition`/`odomRotation`
@@ -1,2 +1,3 @@
1
- import { a as eulerToQuaternion, c as getLastDeviceOrientation, d as updateDeviceOrientation, i as createGpsPositionHandler, l as resetCoordinatorState, n as buildRawGpsPoint, o as extractOdomPosition, r as buildRecordGpsEventPayload, s as extractOdomRotation, t as RecordingCoordinatorConfig, u as toRawAbsoluteOrientation } from "../gps-event-coordinator-BWpgBrHq.js";
1
+ import { c as extractOdomPosition, l as extractOdomRotation } from "../ar-types-CBafnxhE.js";
2
+ import { a as eulerToQuaternion, c as getLastDeviceOrientation, i as createGpsPositionHandler, l as updateDeviceOrientation, n as buildRawGpsPoint, o as resetCoordinatorState, r as buildRecordGpsEventPayload, s as toRawAbsoluteOrientation, t as RecordingCoordinatorConfig } from "../gps-event-coordinator-03rVh_us.js";
2
3
  export { RecordingCoordinatorConfig, buildRawGpsPoint, buildRecordGpsEventPayload, createGpsPositionHandler, eulerToQuaternion, extractOdomPosition, extractOdomRotation, getLastDeviceOrientation, resetCoordinatorState, toRawAbsoluteOrientation, updateDeviceOrientation };
@@ -1,4 +1,6 @@
1
1
  import { createLogger } from "../utils/logger.js";
2
+ import { extractOdomPosition, extractOdomRotation } from "../types/ar-types.js";
3
+ import { n as resetDeviceOrientationCache, r as updateDeviceOrientation, t as getLastDeviceOrientation } from "../device-orientation-cache-BjEaEAmh.js";
2
4
  import { getLatestAbsoluteOrientation } from "../sensors/absolute-orientation.js";
3
5
  import { eulerToQuaternion, getOdometryPositions, getZeroReference, recordGpsEvent, setZeroPos } from "gps-plus-slam-js";
4
6
  //#region ../src/state/gps-event-coordinator.ts
@@ -6,57 +8,13 @@ const log = createLogger("RecordingCoordinator");
6
8
  /** Counter for generating unique GPS point IDs */
7
9
  let gpsEventCounter = 0;
8
10
  /**
9
- * State for device orientation (captured separately from GPS)
10
- */
11
- let lastDeviceOrientation = null;
12
- /**
13
- * Update the cached device orientation.
14
- * Called by orientation watch, used when GPS event arrives.
15
- */
16
- function updateDeviceOrientation(orientation) {
17
- lastDeviceOrientation = orientation;
18
- }
19
- /**
20
- * Get the current cached device orientation.
21
- */
22
- function getLastDeviceOrientation() {
23
- return lastDeviceOrientation;
24
- }
25
- /**
26
11
  * Clear cached state (for testing or session reset)
27
12
  */
28
13
  function resetCoordinatorState() {
29
- lastDeviceOrientation = null;
14
+ resetDeviceOrientationCache();
30
15
  gpsEventCounter = 0;
31
16
  }
32
17
  /**
33
- * Extract raw odometry position tuple from ARPose.
34
- *
35
- * Returns the raw WebXR position without coordinate conversion.
36
- * The reducer applies the WebXR→NUE transform when storing into state
37
- * (raw-storage pattern, see docs/2026-04-09-raw-storage-convert-on-read.md).
38
- *
39
- * WebXR local-floor frame: X=East, Y=Up, Z=South (toward viewer / backward).
40
- */
41
- function extractOdomPosition(arPose) {
42
- return [
43
- arPose.position.x,
44
- arPose.position.y,
45
- arPose.position.z
46
- ];
47
- }
48
- /**
49
- * Extract odometry rotation tuple from ARPose.
50
- */
51
- function extractOdomRotation(arPose) {
52
- return [
53
- arPose.orientation.x,
54
- arPose.orientation.y,
55
- arPose.orientation.z,
56
- arPose.orientation.w
57
- ];
58
- }
59
- /**
60
18
  * Build a RawGpsPoint from GPS position data.
61
19
  * Returns only raw sensor fields — no derived fields (coordinates, weight,
62
20
  * zeroRef). Derived fields are computed by the library reducer when the
@@ -149,7 +107,7 @@ function createGpsPositionHandler(config) {
149
107
  log.error("Failed to get zero reference");
150
108
  return;
151
109
  }
152
- const payload = buildRecordGpsEventPayload(position, arPose, lastDeviceOrientation, getLatestAbsoluteOrientation());
110
+ const payload = buildRecordGpsEventPayload(position, arPose, getLastDeviceOrientation(), getLatestAbsoluteOrientation());
153
111
  store.dispatch(recordGpsEvent(payload));
154
112
  const eventCount = getOdometryPositions(store.getState()).length;
155
113
  log.info(`Recorded GPS event #${eventCount}`);