gps-plus-slam-app-framework 1.0.7 → 1.1.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 (167) hide show
  1. package/README.md +69 -15
  2. package/dist/{app-selectors-BeU0_ab8.d.ts → app-selectors-CR9OWodf.d.ts} +1 -1
  3. package/dist/ar/camera-blit-capture.d.ts +1 -1
  4. package/dist/ar/capability-checker.d.ts +2 -0
  5. package/dist/ar/capability-checker.js +25 -0
  6. package/dist/ar/capture-failure-tracker.d.ts +1 -1
  7. package/dist/ar/chromium-camera-access-workaround.d.ts +2 -2
  8. package/dist/ar/chromium-camera-access-workaround.js +197 -8
  9. package/dist/ar/depth-sampler.d.ts +2 -2
  10. package/dist/ar/enable-gps-ar.d.ts +2 -0
  11. package/dist/ar/enable-gps-ar.js +137 -0
  12. package/dist/ar/frame-loop.d.ts +1 -1
  13. package/dist/ar/frame-loop.js +24 -1
  14. package/dist/ar/image-capture.d.ts +1 -1
  15. package/dist/ar/index.d.ts +15 -11
  16. package/dist/ar/index.js +7 -3
  17. package/dist/ar/replay-scene.d.ts +1 -1
  18. package/dist/ar/scene-node-names.d.ts +1 -1
  19. package/dist/ar/webxr-session.d.ts +4 -4
  20. package/dist/ar/webxr-session.js +23 -38
  21. package/dist/ar/xr-error-handler.d.ts +1 -1
  22. package/dist/ar/xr-frame-loop.d.ts +2 -0
  23. package/dist/ar/xr-frame-loop.js +69 -0
  24. package/dist/ar-world-group-alignment-Dn4rQk_c.d.ts +43 -0
  25. package/dist/capability-checker-BTCmZRL4.d.ts +43 -0
  26. package/dist/chromium-camera-access-workaround-MifIwK9x.d.ts +137 -0
  27. package/dist/core/index.d.ts +1 -1
  28. package/dist/{create-slam-app-store-CNsZ3rcX.d.ts → create-slam-app-store-B76AGaI0.d.ts} +5 -5
  29. package/dist/{depth-sampler-xg8vna6c.d.ts → depth-sampler-CqrkRr2N.d.ts} +1 -1
  30. package/dist/enable-gps-ar-DNbO0zbg.d.ts +95 -0
  31. package/dist/{file-system-DTApEv_Q.d.ts → file-system-TIsDfamK.d.ts} +1 -1
  32. package/dist/frame-conversions-D2EYjeNa.d.ts +54 -0
  33. package/dist/{frame-loop-QJIxLin0.d.ts → frame-loop-BTeRpDm4.d.ts} +5 -0
  34. package/dist/{fused-path-CB4DwWOG.d.ts → fused-path-BdVHmDW9.d.ts} +1 -1
  35. package/dist/geo/h3-proximity.d.ts +1 -1
  36. package/dist/geo/index.d.ts +1 -1
  37. package/dist/{gps-anchor-CnWY61XK.d.ts → gps-anchor-CISLPQIb.d.ts} +12 -1
  38. package/dist/{gps-ar-pose-sampler-DsM1Kb2N.d.ts → gps-ar-pose-sampler-BypXZUqC.d.ts} +1 -1
  39. package/dist/{gps-event-coordinator-DBx9I1YX.d.ts → gps-event-coordinator-BKVZbS1M.d.ts} +3 -3
  40. package/dist/hit-test-reticle-BGXOxrUh.d.ts +45 -0
  41. package/dist/{image-capture-DZLxHDN9.d.ts → image-capture-BXZUmj7j.d.ts} +1 -1
  42. package/dist/index-22v8MXJX.d.ts +23 -0
  43. package/dist/index-BB2KEWbN2.d.ts +37 -0
  44. package/dist/index.d.ts +63 -57
  45. package/dist/index.js +14 -7
  46. package/dist/{leaflet-map-overlay-Cew7XAoO.d.ts → leaflet-map-overlay-jNt-kcUr.d.ts} +1 -1
  47. package/dist/{map-data-sih4g64v.d.ts → map-data-BGIBM5rv.d.ts} +1 -1
  48. package/dist/{map-overlay-draw-B3R1c9Xp.d.ts → map-overlay-draw-DcGs9UV3.d.ts} +1 -1
  49. package/dist/{null-storage-backend-BKOS7JpL.d.ts → null-storage-backend-BPQJSaMw.d.ts} +2 -2
  50. package/dist/{opfs-storage-backend-Cj_7PWoq.d.ts → opfs-storage-backend-u4QKvgvP.d.ts} +2 -2
  51. package/dist/{persistence-middleware-BkHIqvaA.d.ts → persistence-middleware-xB5sTllJ.d.ts} +1 -1
  52. package/dist/{recording-options-Dq6IsKAv.d.ts → recording-options-BSFpBSZH.d.ts} +10 -4
  53. package/dist/{recording-replayer-CmCIIZ02.d.ts → recording-replayer-CTL2cUE0.d.ts} +2 -2
  54. package/dist/{recording-slice-d6OtCrza.d.ts → recording-slice-Cb888P6d.d.ts} +2 -2
  55. package/dist/{replay-engine-BGBRQyXs.d.ts → replay-engine-B-5GIZtc.d.ts} +1 -1
  56. package/dist/{replay-scene-DpAGcAKY.d.ts → replay-scene-DkNfldPh.d.ts} +3 -3
  57. package/dist/sensors/gps-error-handler.d.ts +1 -1
  58. package/dist/sensors/gps.d.ts +1 -1
  59. package/dist/sensors/index.d.ts +3 -3
  60. package/dist/sensors/index.js +1 -1
  61. package/dist/sensors/permission-checker.d.ts +1 -1
  62. package/dist/session-disposers-M-oashRH.js +57 -0
  63. package/dist/state/app-selectors.d.ts +1 -1
  64. package/dist/state/combined-root-state.d.ts +1 -1
  65. package/dist/state/create-slam-app-store.d.ts +1 -1
  66. package/dist/state/gps-ar-pose-sampler.d.ts +3 -3
  67. package/dist/state/gps-event-coordinator.d.ts +1 -1
  68. package/dist/state/index.d.ts +17 -17
  69. package/dist/state/index.js +2 -2
  70. package/dist/state/persistence-middleware.d.ts +1 -1
  71. package/dist/state/persistence-middleware.js +9 -3
  72. package/dist/state/recording-options.d.ts +1 -1
  73. package/dist/state/recording-replayer.d.ts +2 -2
  74. package/dist/state/recording-slice.d.ts +1 -1
  75. package/dist/state/replay-engine.d.ts +1 -1
  76. package/dist/state/store-subscribers.d.ts +2 -2
  77. package/dist/state/subscribe-to-selector.d.ts +1 -1
  78. package/dist/state/tracking-quality.d.ts +1 -1
  79. package/dist/state/tracking-slice.d.ts +1 -1
  80. package/dist/state-BkIfpiyA.js +87 -0
  81. package/dist/storage/file-system-utils.d.ts +1 -1
  82. package/dist/storage/file-system.d.ts +1 -1
  83. package/dist/storage/index.d.ts +8 -8
  84. package/dist/storage/null-storage-backend.d.ts +1 -1
  85. package/dist/storage/opfs-storage-backend.d.ts +1 -1
  86. package/dist/storage/opfs-storage.d.ts +1 -1
  87. package/dist/storage/storage-backend.d.ts +1 -1
  88. package/dist/storage/zip-export.d.ts +1 -1
  89. package/dist/storage/zip-reader.d.ts +1 -1
  90. package/dist/{storage-backend-CT0Il_AB.d.ts → storage-backend-yDSKafAQ.d.ts} +1 -1
  91. package/dist/{store-subscribers-Dce_CoJF.d.ts → store-subscribers-swlbtg_z.d.ts} +2 -2
  92. package/dist/{subscribe-to-selector-DIHm3BRZ.d.ts → subscribe-to-selector--KQpgLXG.d.ts} +1 -1
  93. package/dist/test-utils/browser-mocks.d.ts +1 -1
  94. package/dist/test-utils/zip-round-trip-helpers.d.ts +1 -1
  95. package/dist/{tracking-slice-utCNND8t.d.ts → tracking-slice-CDREeoZ_.d.ts} +1 -1
  96. package/dist/types/ar-types.d.ts +1 -1
  97. package/dist/types/geo-types.d.ts +1 -1
  98. package/dist/types/index.d.ts +2 -2
  99. package/dist/utils/concurrency.d.ts +1 -1
  100. package/dist/utils/failure-tracker.d.ts +1 -1
  101. package/dist/utils/format-file-size.d.ts +1 -1
  102. package/dist/utils/fused-path.d.ts +1 -1
  103. package/dist/utils/index.d.ts +6 -6
  104. package/dist/utils/list-formatter.d.ts +1 -1
  105. package/dist/utils/logger.d.ts +1 -1
  106. package/dist/visualization/accuracy-circles.d.ts +1 -1
  107. package/dist/visualization/alignment-lerper.d.ts +1 -1
  108. package/dist/visualization/ar-world-group-alignment.d.ts +2 -0
  109. package/dist/visualization/ar-world-group-alignment.js +51 -0
  110. package/dist/visualization/camera-follower.d.ts +1 -1
  111. package/dist/visualization/css3d-renderer-manager.d.ts +1 -1
  112. package/dist/visualization/frame-conversions.d.ts +2 -0
  113. package/dist/visualization/frame-conversions.js +88 -0
  114. package/dist/visualization/frustum-visibility.d.ts +1 -1
  115. package/dist/visualization/gps-anchor.d.ts +1 -1
  116. package/dist/visualization/gps-anchor.js +216 -1
  117. package/dist/visualization/gps-compass-cubes.d.ts +1 -1
  118. package/dist/visualization/gps-event-markers.d.ts +1 -1
  119. package/dist/visualization/hit-test-reticle.d.ts +2 -0
  120. package/dist/visualization/hit-test-reticle.js +81 -0
  121. package/dist/visualization/index.d.ts +19 -17
  122. package/dist/visualization/index.js +5 -2
  123. package/dist/visualization/leaflet-map-overlay.d.ts +1 -1
  124. package/dist/visualization/lerp-utils.d.ts +1 -1
  125. package/dist/visualization/map-data.d.ts +1 -1
  126. package/dist/visualization/map-overlay-draw.d.ts +1 -1
  127. package/dist/visualization/map-overlay.d.ts +1 -1
  128. package/dist/visualization/three-dispose.d.ts +1 -1
  129. package/dist/visualization/vis-colors.d.ts +1 -1
  130. package/dist/webxr-nue-basis-BbdqhqY6.js +54 -0
  131. package/dist/{webxr-session-DB5cIZnN.d.ts → webxr-session-BnArFCew.d.ts} +29 -8
  132. package/dist/xr-frame-loop-BKckC7xC.d.ts +70 -0
  133. package/package.json +1 -1
  134. package/dist/chromium-camera-access-workaround-NvChXsi8.d.ts +0 -61
  135. package/dist/gps-anchor-DjC_3MoT.js +0 -257
  136. package/dist/index-pOjUCKEP.d.ts +0 -24
  137. /package/dist/{accuracy-circles-CsxE_7x1.d.ts → accuracy-circles-DEKr0Hoh.d.ts} +0 -0
  138. /package/dist/{alignment-lerper-L1RbWHQ4.d.ts → alignment-lerper-CCZJf-Xb.d.ts} +0 -0
  139. /package/dist/{ar-types-Ck8LEq8k.d.ts → ar-types-isPsQptb.d.ts} +0 -0
  140. /package/dist/{camera-blit-capture-C1V9I1Z6.d.ts → camera-blit-capture-75WWa9Xb.d.ts} +0 -0
  141. /package/dist/{camera-follower-1k8mnw5J.d.ts → camera-follower-B-nS1sr6.d.ts} +0 -0
  142. /package/dist/{capture-failure-tracker-JKb1ST8E.d.ts → capture-failure-tracker-D4HYJNOj.d.ts} +0 -0
  143. /package/dist/{concurrency-CMw8pSaG.d.ts → concurrency-Bsmv53qw.d.ts} +0 -0
  144. /package/dist/{css3d-renderer-manager-CkjCb2HW.d.ts → css3d-renderer-manager-EDED3nvg.d.ts} +0 -0
  145. /package/dist/{failure-tracker-DnHXOIRa.d.ts → failure-tracker-D7ELffm0.d.ts} +0 -0
  146. /package/dist/{file-system-utils-CtKiiw27.d.ts → file-system-utils-BH6uIs2i.d.ts} +0 -0
  147. /package/dist/{format-file-size-BTS5H62-.d.ts → format-file-size-B7gJb3Md.d.ts} +0 -0
  148. /package/dist/{frustum-visibility-BHnFrSKQ.d.ts → frustum-visibility-DGnJqls0.d.ts} +0 -0
  149. /package/dist/{geo-types-CTuF23gG.d.ts → geo-types-clgzl8b5.d.ts} +0 -0
  150. /package/dist/{gps-DXoQb9Kf.d.ts → gps-B7AlMPz5.d.ts} +0 -0
  151. /package/dist/{gps-compass-cubes-CsLtFv4B.d.ts → gps-compass-cubes-Ys6Hf1nc.d.ts} +0 -0
  152. /package/dist/{gps-error-handler-Dg3ziRVY.d.ts → gps-error-handler-BLDhUlw5.d.ts} +0 -0
  153. /package/dist/{gps-event-markers-BGr-iLvi.d.ts → gps-event-markers-BlHq3jYV.d.ts} +0 -0
  154. /package/dist/{h3-proximity-BhfgNbdW.d.ts → h3-proximity-DJnghtir.d.ts} +0 -0
  155. /package/dist/{index-gzWJMVpo.d.ts → index--ldLph4V.d.ts} +0 -0
  156. /package/dist/{lerp-utils-B8MM8zCR.d.ts → lerp-utils-DNcSmKVX.d.ts} +0 -0
  157. /package/dist/{list-formatter-CNqi-E2j.d.ts → list-formatter-CsqcU4v5.d.ts} +0 -0
  158. /package/dist/{logger-C9vugiQb.d.ts → logger-BZ44Dhd3.d.ts} +0 -0
  159. /package/dist/{map-overlay-DAmreyA3.d.ts → map-overlay-yrFsUtGv.d.ts} +0 -0
  160. /package/dist/{opfs-storage-DOPkzgeT.d.ts → opfs-storage-LsLY6VZV.d.ts} +0 -0
  161. /package/dist/{permission-checker-DPJl_RU6.d.ts → permission-checker-CfV7INCa.d.ts} +0 -0
  162. /package/dist/{scene-node-names-6LBjPmwz.d.ts → scene-node-names-IHW7HR4S.d.ts} +0 -0
  163. /package/dist/{three-dispose-C2drkp6f.d.ts → three-dispose-WTBAfaWU.d.ts} +0 -0
  164. /package/dist/{vis-colors-CHQhjal3.d.ts → vis-colors-Djnyg_UH.d.ts} +0 -0
  165. /package/dist/{xr-error-handler-CDY5QxGb.d.ts → xr-error-handler-DcUFshNF.d.ts} +0 -0
  166. /package/dist/{zip-export-QO4iLIi7.d.ts → zip-export-C0_ErAqT.d.ts} +0 -0
  167. /package/dist/{zip-reader-D1105idz.d.ts → zip-reader-B2lzN8F5.d.ts} +0 -0
@@ -1,2 +1,2 @@
1
- import { a as getCurrentScenarioHandle, c as resetForNewSession, d as startSession, f as verifyWriteAccess, h as writeSessionMetadata, i as ensureScenarioDirectory, l as resetStorageState, m as writeFrame, n as WriteAccessResult, o as initStorage, p as writeAction, r as clearRefPointsCacheForAllScenarios, s as listSessions, t as ClearRefPointsCacheResult, u as setCurrentScenario } from "../file-system-DTApEv_Q.js";
1
+ import { a as getCurrentScenarioHandle, c as resetForNewSession, d as startSession, f as verifyWriteAccess, h as writeSessionMetadata, i as ensureScenarioDirectory, l as resetStorageState, m as writeFrame, n as WriteAccessResult, o as initStorage, p as writeAction, r as clearRefPointsCacheForAllScenarios, s as listSessions, t as ClearRefPointsCacheResult, u as setCurrentScenario } from "../file-system-TIsDfamK.js";
2
2
  export { ClearRefPointsCacheResult, WriteAccessResult, clearRefPointsCacheForAllScenarios, ensureScenarioDirectory, getCurrentScenarioHandle, initStorage, listSessions, resetForNewSession, resetStorageState, setCurrentScenario, startSession, verifyWriteAccess, writeAction, writeFrame, writeSessionMetadata };
@@ -1,9 +1,9 @@
1
- import { a as getAppRootHandle, c as initOpfsStorage, d as resetSessionHandles, h as writeSessionMetadata$1, i as createSession, l as listSessions, n as SessionMetadata, o as getSessionHandle, r as checkStorageQuota, s as getSessionsRootHandle, u as resetOpfsStorage } from "../opfs-storage-DOPkzgeT.js";
2
- import { n as StorageBackend, t as CreateSessionResult } from "../storage-backend-CT0Il_AB.js";
3
- import { a as ZipActionEntry, c as loadEntriesFromSubdir, d as loadSessionMetadataFromBlob, f as readZipEntries, i as RecordedAction, l as loadGpsPathFromBlob, n as GpsPathCoord, o as ZipSubdirEntry, r as MAX_ACTION_FILE_SIZE, s as loadActionsFromZip, t as Entry, u as loadSessionMetadata } from "../zip-reader-D1105idz.js";
4
- import { t as NullStorageBackend } from "../null-storage-backend-BKOS7JpL.js";
5
- import { t as OpfsStorageBackend } from "../opfs-storage-backend-Cj_7PWoq.js";
6
- import { a as getCurrentScenarioHandle, c as resetForNewSession, d as startSession, f as verifyWriteAccess, h as writeSessionMetadata, i as ensureScenarioDirectory, l as resetStorageState, m as writeFrame, n as WriteAccessResult, o as initStorage, p as writeAction, s as listSessions$1, u as setCurrentScenario } from "../file-system-DTApEv_Q.js";
7
- import { n as formatFrameFilename, r as formatTimestamp, t as formatActionFilename } from "../file-system-utils-CtKiiw27.js";
8
- import { a as downloadZip, c as syncToExternalZip, i as ZipExportResult, n as ZipContributorAddFile, o as exportAndDownloadSession, r as ZipExportContributor, s as exportSessionAsZip, t as ExportSessionAsZipOptions } from "../zip-export-QO4iLIi7.js";
1
+ import { a as getAppRootHandle, c as initOpfsStorage, d as resetSessionHandles, h as writeSessionMetadata$1, i as createSession, l as listSessions, n as SessionMetadata, o as getSessionHandle, r as checkStorageQuota, s as getSessionsRootHandle, u as resetOpfsStorage } from "../opfs-storage-LsLY6VZV.js";
2
+ import { n as StorageBackend, t as CreateSessionResult } from "../storage-backend-yDSKafAQ.js";
3
+ import { a as ZipActionEntry, c as loadEntriesFromSubdir, d as loadSessionMetadataFromBlob, f as readZipEntries, i as RecordedAction, l as loadGpsPathFromBlob, n as GpsPathCoord, o as ZipSubdirEntry, r as MAX_ACTION_FILE_SIZE, s as loadActionsFromZip, t as Entry, u as loadSessionMetadata } from "../zip-reader-B2lzN8F5.js";
4
+ import { t as NullStorageBackend } from "../null-storage-backend-BPQJSaMw.js";
5
+ import { t as OpfsStorageBackend } from "../opfs-storage-backend-u4QKvgvP.js";
6
+ import { a as getCurrentScenarioHandle, c as resetForNewSession, d as startSession, f as verifyWriteAccess, h as writeSessionMetadata, i as ensureScenarioDirectory, l as resetStorageState, m as writeFrame, n as WriteAccessResult, o as initStorage, p as writeAction, s as listSessions$1, u as setCurrentScenario } from "../file-system-TIsDfamK.js";
7
+ import { n as formatFrameFilename, r as formatTimestamp, t as formatActionFilename } from "../file-system-utils-BH6uIs2i.js";
8
+ import { a as downloadZip, c as syncToExternalZip, i as ZipExportResult, n as ZipContributorAddFile, o as exportAndDownloadSession, r as ZipExportContributor, s as exportSessionAsZip, t as ExportSessionAsZipOptions } from "../zip-export-C0_ErAqT.js";
9
9
  export { type CreateSessionResult, type Entry, type ExportSessionAsZipOptions, type GpsPathCoord, MAX_ACTION_FILE_SIZE, NullStorageBackend, OpfsStorageBackend, type RecordedAction, type SessionMetadata, type StorageBackend, type WriteAccessResult, type ZipActionEntry, type ZipContributorAddFile, type ZipExportContributor, type ZipExportResult, type ZipSubdirEntry, checkStorageQuota, createSession, downloadZip, ensureScenarioDirectory, exportAndDownloadSession, exportSessionAsZip, formatActionFilename, formatFrameFilename, formatTimestamp, getAppRootHandle, getCurrentScenarioHandle, getSessionHandle, getSessionsRootHandle, initOpfsStorage, initStorage, listSessions, listSessions$1 as listSessionsFromFileSystem, loadActionsFromZip, loadEntriesFromSubdir, loadGpsPathFromBlob, loadSessionMetadataFromBlob, loadSessionMetadata as loadSessionMetadataFromZip, readZipEntries, resetForNewSession, resetOpfsStorage, resetSessionHandles, resetStorageState, setCurrentScenario, startSession as startStorageSession, syncToExternalZip, verifyWriteAccess, writeAction, writeFrame, writeSessionMetadata as writeSessionMeta, writeSessionMetadata$1 as writeSessionMetadata };
@@ -1,2 +1,2 @@
1
- import { t as NullStorageBackend } from "../null-storage-backend-BKOS7JpL.js";
1
+ import { t as NullStorageBackend } from "../null-storage-backend-BPQJSaMw.js";
2
2
  export { NullStorageBackend };
@@ -1,2 +1,2 @@
1
- import { t as OpfsStorageBackend } from "../opfs-storage-backend-Cj_7PWoq.js";
1
+ import { t as OpfsStorageBackend } from "../opfs-storage-backend-u4QKvgvP.js";
2
2
  export { OpfsStorageBackend };
@@ -1,2 +1,2 @@
1
- import { a as getAppRootHandle, c as initOpfsStorage, d as resetSessionHandles, f as setSessionHandles, h as writeSessionMetadata, i as createSession, l as listSessions, m as writeFrame, n as SessionMetadata, o as getSessionHandle, p as writeAction, r as checkStorageQuota, s as getSessionsRootHandle, t as CreateSessionResult, u as resetOpfsStorage } from "../opfs-storage-DOPkzgeT.js";
1
+ import { a as getAppRootHandle, c as initOpfsStorage, d as resetSessionHandles, f as setSessionHandles, h as writeSessionMetadata, i as createSession, l as listSessions, m as writeFrame, n as SessionMetadata, o as getSessionHandle, p as writeAction, r as checkStorageQuota, s as getSessionsRootHandle, t as CreateSessionResult, u as resetOpfsStorage } from "../opfs-storage-LsLY6VZV.js";
2
2
  export { CreateSessionResult, SessionMetadata, checkStorageQuota, createSession, getAppRootHandle, getSessionHandle, getSessionsRootHandle, initOpfsStorage, listSessions, resetOpfsStorage, resetSessionHandles, setSessionHandles, writeAction, writeFrame, writeSessionMetadata };
@@ -1,2 +1,2 @@
1
- import { n as StorageBackend, t as CreateSessionResult } from "../storage-backend-CT0Il_AB.js";
1
+ import { n as StorageBackend, t as CreateSessionResult } from "../storage-backend-yDSKafAQ.js";
2
2
  export { CreateSessionResult, StorageBackend };
@@ -1,2 +1,2 @@
1
- import { a as downloadZip, c as syncToExternalZip, i as ZipExportResult, n as ZipContributorAddFile, o as exportAndDownloadSession, r as ZipExportContributor, s as exportSessionAsZip, t as ExportSessionAsZipOptions } from "../zip-export-QO4iLIi7.js";
1
+ import { a as downloadZip, c as syncToExternalZip, i as ZipExportResult, n as ZipContributorAddFile, o as exportAndDownloadSession, r as ZipExportContributor, s as exportSessionAsZip, t as ExportSessionAsZipOptions } from "../zip-export-C0_ErAqT.js";
2
2
  export { ExportSessionAsZipOptions, ZipContributorAddFile, ZipExportContributor, ZipExportResult, downloadZip, exportAndDownloadSession, exportSessionAsZip, syncToExternalZip };
@@ -1,2 +1,2 @@
1
- import { a as ZipActionEntry, c as loadEntriesFromSubdir, d as loadSessionMetadataFromBlob, f as readZipEntries, i as RecordedAction, l as loadGpsPathFromBlob, n as GpsPathCoord, o as ZipSubdirEntry, r as MAX_ACTION_FILE_SIZE, s as loadActionsFromZip, t as Entry, u as loadSessionMetadata } from "../zip-reader-D1105idz.js";
1
+ import { a as ZipActionEntry, c as loadEntriesFromSubdir, d as loadSessionMetadataFromBlob, f as readZipEntries, i as RecordedAction, l as loadGpsPathFromBlob, n as GpsPathCoord, o as ZipSubdirEntry, r as MAX_ACTION_FILE_SIZE, s as loadActionsFromZip, t as Entry, u as loadSessionMetadata } from "../zip-reader-B2lzN8F5.js";
2
2
  export { Entry, GpsPathCoord, MAX_ACTION_FILE_SIZE, RecordedAction, ZipActionEntry, ZipSubdirEntry, loadActionsFromZip, loadEntriesFromSubdir, loadGpsPathFromBlob, loadSessionMetadata, loadSessionMetadataFromBlob, readZipEntries };
@@ -1,4 +1,4 @@
1
- import { n as SessionMetadata } from "./opfs-storage-DOPkzgeT.js";
1
+ import { n as SessionMetadata } from "./opfs-storage-LsLY6VZV.js";
2
2
 
3
3
  //#region ../src/storage/storage-backend.d.ts
4
4
  interface CreateSessionResult {
@@ -1,5 +1,5 @@
1
- import { t as MapData } from "./map-data-sih4g64v.js";
2
- import { t as SubscribableStore } from "./subscribe-to-selector-DIHm3BRZ.js";
1
+ import { t as MapData } from "./map-data-BGIBM5rv.js";
2
+ import { t as SubscribableStore } from "./subscribe-to-selector--KQpgLXG.js";
3
3
  import { LatLong, Matrix4, Quaternion, Vector3 } from "gps-plus-slam-js";
4
4
 
5
5
  //#region ../src/state/store-subscribers.d.ts
@@ -1,4 +1,4 @@
1
- import { L as CombinedRootState } from "./create-slam-app-store-CNsZ3rcX.js";
1
+ import { L as CombinedRootState } from "./create-slam-app-store-B76AGaI0.js";
2
2
 
3
3
  //#region ../src/state/subscribe-to-selector.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { a as WebXRQuaternion, o as WebXRVec3 } from "../ar-types-Ck8LEq8k.js";
1
+ import { a as WebXRQuaternion, o as WebXRVec3 } from "../ar-types-isPsQptb.js";
2
2
  import { Mock } from "vitest";
3
3
 
4
4
  //#region ../src/test-utils/browser-mocks.d.ts
@@ -1,4 +1,4 @@
1
- import { i as RecordedAction } from "../zip-reader-D1105idz.js";
1
+ import { i as RecordedAction } from "../zip-reader-B2lzN8F5.js";
2
2
  import { LatLong } from "gps-plus-slam-js";
3
3
 
4
4
  //#region ../src/test-utils/zip-round-trip-helpers.d.ts
@@ -1,4 +1,4 @@
1
- import { t as ARPose } from "./ar-types-Ck8LEq8k.js";
1
+ import { t as ARPose } from "./ar-types-isPsQptb.js";
2
2
  import { OdometryTrackingRestartedPayload, Quaternion, Vector3 } from "gps-plus-slam-js";
3
3
  import * as _$_reduxjs_toolkit0 from "@reduxjs/toolkit";
4
4
 
@@ -1,2 +1,2 @@
1
- import { a as WebXRQuaternion, i as DepthSample, n as ArPoseTuples, o as WebXRVec3, r as DepthPoint, t as ARPose } from "../ar-types-Ck8LEq8k.js";
1
+ import { a as WebXRQuaternion, i as DepthSample, n as ArPoseTuples, o as WebXRVec3, r as DepthPoint, t as ARPose } from "../ar-types-isPsQptb.js";
2
2
  export { ARPose, ArPoseTuples, DepthPoint, DepthSample, WebXRQuaternion, WebXRVec3 };
@@ -1,2 +1,2 @@
1
- import { n as RawGpsSample, r as RefPointMarker, t as GpsCoord } from "../geo-types-CTuF23gG.js";
1
+ import { n as RawGpsSample, r as RefPointMarker, t as GpsCoord } from "../geo-types-clgzl8b5.js";
2
2
  export { GpsCoord, RawGpsSample, RefPointMarker };
@@ -1,3 +1,3 @@
1
- import { a as WebXRQuaternion, i as DepthSample, n as ArPoseTuples, o as WebXRVec3, r as DepthPoint, t as ARPose } from "../ar-types-Ck8LEq8k.js";
2
- import { n as RawGpsSample, r as RefPointMarker, t as GpsCoord } from "../geo-types-CTuF23gG.js";
1
+ import { a as WebXRQuaternion, i as DepthSample, n as ArPoseTuples, o as WebXRVec3, r as DepthPoint, t as ARPose } from "../ar-types-isPsQptb.js";
2
+ import { n as RawGpsSample, r as RefPointMarker, t as GpsCoord } from "../geo-types-clgzl8b5.js";
3
3
  export { ARPose, ArPoseTuples, DepthPoint, DepthSample, GpsCoord, RawGpsSample, RefPointMarker, WebXRQuaternion, WebXRVec3 };
@@ -1,2 +1,2 @@
1
- import { t as mapWithConcurrencyLimit } from "../concurrency-CMw8pSaG.js";
1
+ import { t as mapWithConcurrencyLimit } from "../concurrency-Bsmv53qw.js";
2
2
  export { mapWithConcurrencyLimit };
@@ -1,2 +1,2 @@
1
- import { n as FailureTrackerConfig, r as createFailureTracker, t as FailureTracker } from "../failure-tracker-DnHXOIRa.js";
1
+ import { n as FailureTrackerConfig, r as createFailureTracker, t as FailureTracker } from "../failure-tracker-D7ELffm0.js";
2
2
  export { FailureTracker, FailureTrackerConfig, createFailureTracker };
@@ -1,2 +1,2 @@
1
- import { t as formatFileSize } from "../format-file-size-BTS5H62-.js";
1
+ import { t as formatFileSize } from "../format-file-size-B7gJb3Md.js";
2
2
  export { formatFileSize };
@@ -1,2 +1,2 @@
1
- import { n as computeFusedPath, r as fusedGpsFromOdom, t as FusedPathInput } from "../fused-path-CB4DwWOG.js";
1
+ import { n as computeFusedPath, r as fusedGpsFromOdom, t as FusedPathInput } from "../fused-path-BdVHmDW9.js";
2
2
  export { FusedPathInput, computeFusedPath, fusedGpsFromOdom };
@@ -1,7 +1,7 @@
1
- import { a as createLogger, c as setGlobalLogLevel, i as clearLogBuffer, l as subscribeToLogs, n as LogLevel, o as getGlobalLogLevel, r as Logger, s as getLogBuffer, t as LogEntry } from "../logger-C9vugiQb.js";
2
- import { n as computeFusedPath, r as fusedGpsFromOdom, t as FusedPathInput } from "../fused-path-CB4DwWOG.js";
3
- import { n as FailureTrackerConfig, r as createFailureTracker, t as FailureTracker } from "../failure-tracker-DnHXOIRa.js";
4
- import { t as mapWithConcurrencyLimit } from "../concurrency-CMw8pSaG.js";
5
- import { t as formatFileSize } from "../format-file-size-BTS5H62-.js";
6
- import { t as listFormatter } from "../list-formatter-CNqi-E2j.js";
1
+ import { a as createLogger, c as setGlobalLogLevel, i as clearLogBuffer, l as subscribeToLogs, n as LogLevel, o as getGlobalLogLevel, r as Logger, s as getLogBuffer, t as LogEntry } from "../logger-BZ44Dhd3.js";
2
+ import { n as computeFusedPath, r as fusedGpsFromOdom, t as FusedPathInput } from "../fused-path-BdVHmDW9.js";
3
+ import { n as FailureTrackerConfig, r as createFailureTracker, t as FailureTracker } from "../failure-tracker-D7ELffm0.js";
4
+ import { t as mapWithConcurrencyLimit } from "../concurrency-Bsmv53qw.js";
5
+ import { t as formatFileSize } from "../format-file-size-B7gJb3Md.js";
6
+ import { t as listFormatter } from "../list-formatter-CsqcU4v5.js";
7
7
  export { type FailureTracker, type FailureTrackerConfig, type FusedPathInput, type LogEntry, LogLevel, type Logger, clearLogBuffer, computeFusedPath, createFailureTracker, createLogger, formatFileSize, fusedGpsFromOdom, getGlobalLogLevel, getLogBuffer, listFormatter, mapWithConcurrencyLimit, setGlobalLogLevel, subscribeToLogs };
@@ -1,2 +1,2 @@
1
- import { t as listFormatter } from "../list-formatter-CNqi-E2j.js";
1
+ import { t as listFormatter } from "../list-formatter-CsqcU4v5.js";
2
2
  export { listFormatter };
@@ -1,2 +1,2 @@
1
- import { a as createLogger, c as setGlobalLogLevel, i as clearLogBuffer, l as subscribeToLogs, n as LogLevel, o as getGlobalLogLevel, r as Logger, s as getLogBuffer, t as LogEntry } from "../logger-C9vugiQb.js";
1
+ import { a as createLogger, c as setGlobalLogLevel, i as clearLogBuffer, l as subscribeToLogs, n as LogLevel, o as getGlobalLogLevel, r as Logger, s as getLogBuffer, t as LogEntry } from "../logger-BZ44Dhd3.js";
2
2
  export { LogEntry, LogLevel, Logger, clearLogBuffer, createLogger, getGlobalLogLevel, getLogBuffer, setGlobalLogLevel, subscribeToLogs };
@@ -1,2 +1,2 @@
1
- import { a as addAccuracyCircles, i as AccuracyCircleSample, n as ACCURACY_CIRCLE_STROKE_OPACITY, r as ACCURACY_CIRCLE_WEIGHT, t as ACCURACY_CIRCLE_FILL_OPACITY } from "../accuracy-circles-CsxE_7x1.js";
1
+ import { a as addAccuracyCircles, i as AccuracyCircleSample, n as ACCURACY_CIRCLE_STROKE_OPACITY, r as ACCURACY_CIRCLE_WEIGHT, t as ACCURACY_CIRCLE_FILL_OPACITY } from "../accuracy-circles-DEKr0Hoh.js";
2
2
  export { ACCURACY_CIRCLE_FILL_OPACITY, ACCURACY_CIRCLE_STROKE_OPACITY, ACCURACY_CIRCLE_WEIGHT, AccuracyCircleSample, addAccuracyCircles };
@@ -1,2 +1,2 @@
1
- import { n as createAlignmentLerper, t as AlignmentLerper } from "../alignment-lerper-L1RbWHQ4.js";
1
+ import { n as createAlignmentLerper, t as AlignmentLerper } from "../alignment-lerper-CCZJf-Xb.js";
2
2
  export { AlignmentLerper, createAlignmentLerper };
@@ -0,0 +1,2 @@
1
+ import { n as ArWorldGroupAlignmentOptions, r as enableArWorldGroupAlignment, t as ArWorldGroupAlignmentHandle } from "../ar-world-group-alignment-Dn4rQk_c.js";
2
+ export { ArWorldGroupAlignmentHandle, ArWorldGroupAlignmentOptions, enableArWorldGroupAlignment };
@@ -0,0 +1,51 @@
1
+ import { registerFrameUpdate } from "../ar/frame-loop.js";
2
+ import { t as registerSessionDisposer } from "../session-disposers-M-oashRH.js";
3
+ import { createAlignmentLerper } from "./alignment-lerper.js";
4
+ import { selectAlignmentMatrix } from "../state/app-selectors.js";
5
+ import { subscribeToSelector } from "../state/subscribe-to-selector.js";
6
+ //#region ../src/visualization/ar-world-group-alignment.ts
7
+ /**
8
+ * Begin applying the store's (lerped) alignment to `arWorldGroup`. Returns a
9
+ * handle whose `dispose()` removes both the store subscription and the
10
+ * per-frame update.
11
+ *
12
+ * Disposal is tied to the AR session lifecycle: the binding registers itself
13
+ * with the session-disposer registry that `resetWebXRState()` flushes on
14
+ * teardown, so a caller can `enableArWorldGroupAlignment(...)` once and never
15
+ * hold the handle — the binding cannot outlive the session (which is what two
16
+ * apps independently leaked: the store subscription survives a teardown because
17
+ * `clearFrameUpdates` only drops the per-frame tick). Because `initAR()` throws
18
+ * while a prior session is live, every restart passes through that flush. The
19
+ * handle is still returned for callers that want to stop alignment mid-session,
20
+ * and is idempotent + self-deregistering so a manual `dispose()` and the
21
+ * teardown flush never double-run. See
22
+ * gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-06-08-arworldgroup-alignment-session-scoped-disposal.md.
23
+ *
24
+ * Double-drive is still the caller's concern: the recorder owns its own lerper
25
+ * and must NOT also call this (it would double-lerp the same group). It does not
26
+ * call this helper, so flushing the registry on teardown never affects it.
27
+ */
28
+ function enableArWorldGroupAlignment(options) {
29
+ const lerper = createAlignmentLerper(options.arWorldGroup, options.lerpRate);
30
+ const current = selectAlignmentMatrix(options.store.getState());
31
+ if (current !== null && current !== void 0) lerper.setTarget(current);
32
+ const unsubscribe = subscribeToSelector(options.store, selectAlignmentMatrix, (matrix) => {
33
+ if (matrix !== null && matrix !== void 0) lerper.setTarget(matrix);
34
+ });
35
+ const unregister = registerFrameUpdate((dt) => {
36
+ lerper.update(dt);
37
+ });
38
+ let disposed = false;
39
+ const handle = { dispose() {
40
+ if (disposed) return;
41
+ disposed = true;
42
+ unsubscribe();
43
+ unregister();
44
+ lerper.dispose();
45
+ deregisterSessionDisposer();
46
+ } };
47
+ const deregisterSessionDisposer = registerSessionDisposer(() => handle.dispose());
48
+ return handle;
49
+ }
50
+ //#endregion
51
+ export { enableArWorldGroupAlignment };
@@ -1,2 +1,2 @@
1
- import { n as createCameraFollower, t as CameraFollower } from "../camera-follower-1k8mnw5J.js";
1
+ import { n as createCameraFollower, t as CameraFollower } from "../camera-follower-B-nS1sr6.js";
2
2
  export { CameraFollower, createCameraFollower };
@@ -1,2 +1,2 @@
1
- import { n as createCss3dRendererManager, t as Css3dRendererManager } from "../css3d-renderer-manager-CkjCb2HW.js";
1
+ import { n as createCss3dRendererManager, t as Css3dRendererManager } from "../css3d-renderer-manager-EDED3nvg.js";
2
2
  export { Css3dRendererManager, createCss3dRendererManager };
@@ -0,0 +1,2 @@
1
+ import { n as worldNueToGps, t as nueToArLocal } from "../frame-conversions-D2EYjeNa.js";
2
+ export { nueToArLocal, worldNueToGps };
@@ -0,0 +1,88 @@
1
+ import { calcGpsCoords } from "../core/index.js";
2
+ import * as THREE from "three";
3
+ //#region ../src/visualization/frame-conversions.ts
4
+ /**
5
+ * `frame-conversions` — small, pure coordinate-frame helpers for the AR scene
6
+ * graph. Currently a single function, `nueToArLocal`, that converts a
7
+ * GPS-world NUE point into the AR-odometry local frame of `arWorldGroup`.
8
+ *
9
+ * Background: the scene root is GPS-world NUE; `arWorldGroup.matrix` IS the
10
+ * alignment matrix, which maps **AR-odometry NUE → GPS-world NUE**. So a
11
+ * direct child of `arWorldGroup` whose WORLD position must equal a GPS-world
12
+ * point `nue` has to store `alignment⁻¹ · nue` as its LOCAL position —
13
+ * writing raw `nue` double-applies the alignment. Getting this wrong was the
14
+ * alignment-frame bug
15
+ * (gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-gps-anchor-alignment-frame-bug.md);
16
+ * this helper centralises the conversion behind one tested, well-named seam.
17
+ *
18
+ * Design (see the plan
19
+ * gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-nue-to-ar-local-helper-plan.md):
20
+ * - **Takes the explicit alignment matrix array**, NOT `Object3D.worldToLocal`.
21
+ * `worldToLocal` would read the live, mid-lerp `matrixWorld` and break
22
+ * replay determinism; the explicit target matrix keeps the result a pure
23
+ * function of its inputs. Full rationale in the review doc
24
+ * (gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-worldtolocal-frame-helper-review.md).
25
+ * - **Positions only.** No pose/quaternion variant exists until a caller
26
+ * needs one (YAGNI). No caller currently sets a GPS-world rotation.
27
+ */
28
+ const scratchMatrix = new THREE.Matrix4();
29
+ /**
30
+ * Convert a GPS-world NUE point into the AR-local position to write into a
31
+ * direct child of `arWorldGroup`, given the current alignment matrix.
32
+ *
33
+ * Computes `alignment⁻¹ · nue`. When the result is later composed back by the
34
+ * group's matrix (the same `alignment`), the child's WORLD position equals
35
+ * `nue` exactly.
36
+ *
37
+ * @param alignment - The alignment matrix as a 16-element **column-major**
38
+ * array (AR-odometry NUE → GPS-world NUE), e.g. from `getAlignmentMatrix()`
39
+ * or `THREE.Matrix4.toArray()`. Not mutated.
40
+ * @param nue - The GPS-world NUE point `[north, up, east]` in metres. Not
41
+ * mutated.
42
+ * @param out - Optional target vector to write into and return (pass a reused
43
+ * scratch to avoid allocation on hot paths). Defaults to a fresh
44
+ * `THREE.Vector3`.
45
+ * @returns `out`, set to the AR-local position.
46
+ */
47
+ function nueToArLocal(alignment, nue, out = new THREE.Vector3()) {
48
+ scratchMatrix.fromArray(alignment).invert();
49
+ return out.set(nue[0], nue[1], nue[2]).applyMatrix4(scratchMatrix);
50
+ }
51
+ /**
52
+ * Convert an object's **GPS-world NUE world position** back into a GPS
53
+ * coordinate, for the GPS-anchor bootstrap that medians where an object was
54
+ * actually placed (mirrors the C# `DetermineAndStoreGpsWorldPose`, which
55
+ * medians the object's world pose and converts via `zero.CalcGpsCoordsOf`).
56
+ *
57
+ * Precondition: `worldNue` must already be in GPS-world NUE — i.e. the object
58
+ * lives under an `arWorldGroup` whose `.matrix` carries the alignment (see
59
+ * `enableArWorldGroupAlignment`), so `object3D.getWorldPosition()` is the
60
+ * GPS-world position. Sampling a pure-VIO (identity-`arWorldGroup`) world
61
+ * position would yield a wrong GPS coordinate.
62
+ *
63
+ * Altitude round-trip: `calcGpsCoords` returns only `lat`/`lon` (it derives
64
+ * them from the North/East axes and ignores Up). The Up axis (`worldNue.y`,
65
+ * NUE index 1) is carried through verbatim as `altitude`, so a later
66
+ * `calcRelativeCoordsInMeters(zero, result, result.altitude, 0)` reproduces the
67
+ * same Up value — keeping the steady-state vertical target consistent with
68
+ * where the object was sampled.
69
+ *
70
+ * @param worldNue - The object's world position in GPS-world NUE metres
71
+ * (`x = North`, `y = Up`, `z = East`). A `THREE.Vector3` satisfies this.
72
+ * @param zero - The GPS zero reference (origin for the conversion).
73
+ * @returns The GPS coordinate of `worldNue`, with `altitude = worldNue.y`.
74
+ */
75
+ function worldNueToGps(worldNue, zero) {
76
+ const gps = calcGpsCoords(zero, [
77
+ worldNue.x,
78
+ worldNue.y,
79
+ worldNue.z
80
+ ]);
81
+ return {
82
+ lat: gps.lat,
83
+ lon: gps.lon,
84
+ altitude: worldNue.y
85
+ };
86
+ }
87
+ //#endregion
88
+ export { nueToArLocal, worldNueToGps };
@@ -1,2 +1,2 @@
1
- import { i as isSphereInCameraFrustum, n as isObjectInCameraFrustum, r as isPointInCameraFrustum, t as buildCameraFrustum } from "../frustum-visibility-BHnFrSKQ.js";
1
+ import { i as isSphereInCameraFrustum, n as isObjectInCameraFrustum, r as isPointInCameraFrustum, t as buildCameraFrustum } from "../frustum-visibility-DGnJqls0.js";
2
2
  export { buildCameraFrustum, isObjectInCameraFrustum, isPointInCameraFrustum, isSphereInCameraFrustum };
@@ -1,2 +1,2 @@
1
- import { a as GpsAnchorSamplePoint, i as GpsAnchorPhase, n as GpsAnchorMode, o as createGpsAnchor, r as GpsAnchorOptions, t as GpsAnchor } from "../gps-anchor-CnWY61XK.js";
1
+ import { a as GpsAnchorSamplePoint, i as GpsAnchorPhase, n as GpsAnchorMode, o as createGpsAnchor, r as GpsAnchorOptions, t as GpsAnchor } from "../gps-anchor-CISLPQIb.js";
2
2
  export { GpsAnchor, GpsAnchorMode, GpsAnchorOptions, GpsAnchorPhase, GpsAnchorSamplePoint, createGpsAnchor };
@@ -1,2 +1,217 @@
1
- import { t as createGpsAnchor } from "../gps-anchor-DjC_3MoT.js";
1
+ import { registerFrameUpdate } from "../ar/frame-loop.js";
2
+ import { isObjectInCameraFrustum } from "./frustum-visibility.js";
3
+ import { calcRelativeCoordsInMeters } from "../core/index.js";
4
+ import { nueToArLocal } from "./frame-conversions.js";
5
+ import * as THREE from "three";
6
+ //#region ../src/visualization/gps-anchor.ts
7
+ /**
8
+ * `createGpsAnchor` — GPS-anchored placement of a single `THREE.Object3D`.
9
+ *
10
+ * See the colocated sidecar (`gps-anchor.ts.md`) and the port plan at
11
+ * `gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-13-gps-anchor-port-plan.md`
12
+ * for the full design, state machine, and test matrix.
13
+ *
14
+ * This file implements sub-steps 2 (bootstrap phase), 3 (steady-state
15
+ * `'snap-every-tick'` + distance-scaled threshold gate), and 4
16
+ * (`'snap-when-offscreen'` mode gate, with a one-time initial-placement
17
+ * exemption for `skipBootstrap` anchors). Floor-Y correction is sub-step
18
+ * 6 and remains deferred.
19
+ */
20
+ /**
21
+ * Module-level registry of objects currently owned by a `GpsAnchor`.
22
+ * Used to detect nested anchors (parent + child both anchored) which
23
+ * we explicitly forbid; mirrors the C# invariant.
24
+ */
25
+ const anchoredObjects = /* @__PURE__ */ new WeakSet();
26
+ function isObjectInAnchoredChain(object) {
27
+ let cursor = object;
28
+ while (cursor) {
29
+ if (anchoredObjects.has(cursor)) return true;
30
+ cursor = cursor.parent;
31
+ }
32
+ return false;
33
+ }
34
+ /**
35
+ * Returns true iff `object` is `arWorldGroup` itself or a descendant of it.
36
+ * The anchor's `object3D` MUST satisfy this: only then does it ride the
37
+ * alignment applied to `arWorldGroup.matrix` (the node the camera also lives
38
+ * under) via scene-graph propagation. An anchor parented to the scene root
39
+ * instead never receives the alignment, so each steady-state re-registration
40
+ * snaps the full alignment delta and the object visibly slides as the user
41
+ * moves — the exact instability the anchor exists to prevent.
42
+ */
43
+ function isDescendantOf(object, arWorldGroup) {
44
+ let cursor = object;
45
+ while (cursor) {
46
+ if (cursor === arWorldGroup) return true;
47
+ cursor = cursor.parent;
48
+ }
49
+ return false;
50
+ }
51
+ function median(values) {
52
+ const sorted = [...values].sort((a, b) => a - b);
53
+ const mid = Math.floor(sorted.length / 2);
54
+ if (sorted.length % 2 === 0) return (sorted[mid - 1] + sorted[mid]) / 2;
55
+ return sorted[mid];
56
+ }
57
+ function medianPoint(samples) {
58
+ const lat = median(samples.map((s) => s.lat));
59
+ const lon = median(samples.map((s) => s.lon));
60
+ const alts = samples.map((s) => "altitude" in s ? s.altitude : void 0).filter((a) => typeof a === "number");
61
+ if (alts.length > 0) return {
62
+ lat,
63
+ lon,
64
+ altitude: median(alts)
65
+ };
66
+ return {
67
+ lat,
68
+ lon
69
+ };
70
+ }
71
+ function createGpsAnchor(options) {
72
+ if (isObjectInAnchoredChain(options.object3D)) throw new Error("createGpsAnchor: nested GpsAnchors are not supported — the supplied object3D is already inside an anchored parent chain.");
73
+ if (!isDescendantOf(options.object3D, options.arWorldGroup)) throw new Error("createGpsAnchor: object3D must be a descendant of arWorldGroup (the alignment-bearing node the camera lives under); parenting an anchor to the scene root defeats AR stability.");
74
+ anchoredObjects.add(options.object3D);
75
+ const sampleCount = options.secondsToAccumulateGpsPose ?? 7;
76
+ if (sampleCount < 1) {
77
+ anchoredObjects.delete(options.object3D);
78
+ throw new Error("createGpsAnchor: secondsToAccumulateGpsPose must be >= 1 — use skipBootstrap:true to bypass the accumulation phase.");
79
+ }
80
+ const settlingSeconds = options.settlingSeconds ?? 0;
81
+ const distanceThreshold = options.distanceThreshold ?? 2;
82
+ options.angleThresholdInDegrees;
83
+ const mode = options.mode ?? "snap-when-offscreen";
84
+ const scratchTarget = new THREE.Vector3();
85
+ const scratchCamWorld = new THREE.Vector3();
86
+ const scratchObjWorld = new THREE.Vector3();
87
+ let phase = options.skipBootstrap === true ? "anchored" : "bootstrap";
88
+ let isFullyAnchored = phase === "anchored";
89
+ let gpsPoint = options.gpsPoint;
90
+ let phaseEnteredAtElapsed = null;
91
+ let lastSampleAtElapsed = null;
92
+ const samples = [];
93
+ /**
94
+ * The one-time "initial placement" exemption from the `snap-when-offscreen`
95
+ * frustum gate. A `skipBootstrap` anchor is `anchored` from frame one but its
96
+ * `object3D` still sits at the AR origin (local 0,0,0 — "inside the user")
97
+ * until its first steady-state commit. That first commit MUST land even while
98
+ * the object is on-screen, otherwise the marker stays stuck at the origin
99
+ * until the user happens to look away. A fresh appearance is not a "jump", so
100
+ * it is exempt. Consumed (set false) by the first committed correction; never
101
+ * re-armed (a re-bootstrap moves an already-placed object, so its later
102
+ * corrections are normal gated snaps). Anchors that bootstrap are placed at
103
+ * their seed pose by the host, so they never need this exemption — hence it is
104
+ * armed only for `skipBootstrap`.
105
+ */
106
+ let firstCommitPending = options.skipBootstrap === true;
107
+ const enterBootstrap = () => {
108
+ phase = "bootstrap";
109
+ isFullyAnchored = false;
110
+ phaseEnteredAtElapsed = null;
111
+ lastSampleAtElapsed = null;
112
+ samples.length = 0;
113
+ };
114
+ const commitMedian = () => {
115
+ gpsPoint = medianPoint(samples);
116
+ phase = "anchored";
117
+ isFullyAnchored = true;
118
+ samples.length = 0;
119
+ options.onBootstrapComplete?.(gpsPoint);
120
+ };
121
+ /**
122
+ * Steady-state: compute the GPS-world NUE target from the stored
123
+ * `gpsPoint` and the current `zeroRef`, map it into `arWorldGroup`'s
124
+ * AR-local frame via the inverse alignment matrix, and commit it to
125
+ * `object3D.position` iff the (AR-local) position delta exceeds the
126
+ * distance-scaled threshold AND the mode gate allows it.
127
+ *
128
+ * Mode gate: in `'snap-when-offscreen'` a correction is suppressed while the
129
+ * object is inside the camera frustum — corrections only land when the user
130
+ * is not looking, so the anchor never visibly jumps. The whole AR frame
131
+ * (camera + every anchor) rides one lerped `arWorldGroup.matrix`
132
+ * (`enableArWorldGroupAlignment`), so an on-screen alignment change is
133
+ * absorbed smoothly for the entire view and never needs a per-anchor
134
+ * on-screen snap. The one exception is the first placement of a `skipBootstrap`
135
+ * anchor (see `firstCommitPending`), which must escape the origin even while
136
+ * on-screen. See
137
+ * `gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-06-06-anchor-starter-cachehit-jump-investigation.md`.
138
+ *
139
+ * Frame note: `arWorldGroup.matrix` IS the alignment matrix, which maps
140
+ * **AR-odometry NUE → GPS-world NUE**. `object3D.position` is a *local*
141
+ * transform in that AR-odometry frame. To make the object's *world*
142
+ * position equal the GPS-world `nue`, the local target must be
143
+ * `alignment⁻¹ · nue` — writing raw `nue` would double-apply the
144
+ * alignment (world = `alignment · nue`). See
145
+ * `gps-plus-slam/GpsPlusSlamJs_Docs/docs/2026-05-31-gps-anchor-alignment-frame-bug.md`.
146
+ *
147
+ * Returns silently on missing inputs (no `zeroRef`, or no alignment
148
+ * matrix yet — an AR-local object cannot be placed without knowing the
149
+ * AR↔NUE transform).
150
+ */
151
+ const maybeCommitSteadyState = () => {
152
+ const zero = options.getGpsZeroRef();
153
+ if (zero === null || zero === void 0) return;
154
+ const currentAlignment = options.getAlignmentMatrix();
155
+ if (currentAlignment === null || currentAlignment === void 0) return;
156
+ const targetAlt = "altitude" in gpsPoint && typeof gpsPoint.altitude === "number" ? gpsPoint.altitude : 0;
157
+ const nue = calcRelativeCoordsInMeters(zero, gpsPoint, targetAlt, 0);
158
+ nueToArLocal(currentAlignment, [
159
+ nue[0],
160
+ nue[1],
161
+ nue[2]
162
+ ], scratchTarget);
163
+ options.camera.getWorldPosition(scratchCamWorld);
164
+ options.object3D.getWorldPosition(scratchObjWorld);
165
+ const scale = 1 + 10 * scratchCamWorld.distanceTo(scratchObjWorld) / 100;
166
+ if (options.object3D.position.distanceTo(scratchTarget) >= distanceThreshold * scale) {
167
+ if (!(mode === "snap-when-offscreen" && !firstCommitPending && isObjectInCameraFrustum(options.camera, options.object3D))) {
168
+ options.object3D.position.copy(scratchTarget);
169
+ firstCommitPending = false;
170
+ }
171
+ }
172
+ };
173
+ const tick = (_dt, elapsed) => {
174
+ if (phase === "anchored") {
175
+ maybeCommitSteadyState();
176
+ return;
177
+ }
178
+ if (phaseEnteredAtElapsed === null) {
179
+ phaseEnteredAtElapsed = elapsed;
180
+ lastSampleAtElapsed = elapsed - 1;
181
+ }
182
+ if (elapsed - phaseEnteredAtElapsed < settlingSeconds) return;
183
+ if (lastSampleAtElapsed !== null && elapsed - lastSampleAtElapsed < 1) return;
184
+ const sample = options.getCurrentGpsPoint();
185
+ if (sample === null || sample === void 0) return;
186
+ samples.push(sample);
187
+ lastSampleAtElapsed = elapsed;
188
+ if (samples.length >= sampleCount) commitMedian();
189
+ };
190
+ const unregister = registerFrameUpdate(tick);
191
+ return {
192
+ get phase() {
193
+ return phase;
194
+ },
195
+ get isFullyAnchored() {
196
+ return isFullyAnchored;
197
+ },
198
+ get gpsPoint() {
199
+ return gpsPoint;
200
+ },
201
+ markMovedExternally() {
202
+ enterBootstrap();
203
+ },
204
+ setGpsPoint(point) {
205
+ gpsPoint = point;
206
+ },
207
+ dispose() {
208
+ unregister();
209
+ anchoredObjects.delete(options.object3D);
210
+ },
211
+ __tickForTests(dt, elapsed) {
212
+ tick(dt, elapsed);
213
+ }
214
+ };
215
+ }
216
+ //#endregion
2
217
  export { createGpsAnchor };
@@ -1,2 +1,2 @@
1
- import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-CsLtFv4B.js";
1
+ import { i as createGpsCompassCubes, n as COMPASS_CUBE_SIZE, r as GpsCompassCubes, t as COMPASS_CUBE_DISTANCE } from "../gps-compass-cubes-Ys6Hf1nc.js";
2
2
  export { COMPASS_CUBE_DISTANCE, COMPASS_CUBE_SIZE, GpsCompassCubes, createGpsCompassCubes };
@@ -1,2 +1,2 @@
1
- import { n as GpsEventVisualizer, r as gpsEventVisualizer, t as GpsEventAccuracy } from "../gps-event-markers-BGr-iLvi.js";
1
+ import { n as GpsEventVisualizer, r as gpsEventVisualizer, t as GpsEventAccuracy } from "../gps-event-markers-BlHq3jYV.js";
2
2
  export { GpsEventAccuracy, GpsEventVisualizer, gpsEventVisualizer };
@@ -0,0 +1,2 @@
1
+ import { n as createReticleMesh, r as updateReticle, t as HitMatrix } from "../hit-test-reticle-BGXOxrUh.js";
2
+ export { HitMatrix, createReticleMesh, updateReticle };