gps-plus-slam-js 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -166,6 +166,41 @@ interface RawAbsoluteOrientation {
166
166
  */
167
167
  declare const eulerToQuaternion: (alpha: number, beta: number, gamma: number) => Quaternion;
168
168
  //#endregion
169
+ //#region ../src/state/models/compass-trust.d.ts
170
+ /**
171
+ * Phase 4 Stage A — magnetometer consistency-trust state machine
172
+ * (CLOSED / INTERNAL ONLY).
173
+ *
174
+ * A pure, deterministic reducer that earns (or withholds) trust in the absolute
175
+ * compass by comparing it against the **GPS-only** alignment yaw over time. It
176
+ * exists to feed the *steady-state* Stage B/C use of the compass (detection /
177
+ * soft-prior correction) — it is built in the same iteration as Stage 0 but is
178
+ * **deliberately orthogonal to the Stage-0 cold-start handover**, which stays
179
+ * GPS-intrinsic and never consults trust (plan §7b "the circularity trap").
180
+ *
181
+ * The cardinal property (plan §4c item 9, §10): a **consistently-biased**
182
+ * magnetometer must NEVER reach "trusted" once GPS yaw is observable — its
183
+ * disagreement keeps it out of the trusted state, and a sustained disagreement
184
+ * raises the figure-8 recalibration recommendation instead.
185
+ *
186
+ * Trust ordering (plan §7b Stage A):
187
+ * - Before GPS yaw is observable there is nothing trustworthy to validate
188
+ * against ⇒ the machine is `dormant` (Stage 0's unconditional override holds).
189
+ * - Once observable, agreement within tolerance for a sustained streak ⇒
190
+ * `trusted`; a later large disagreement drops it back to `untrusted`.
191
+ *
192
+ * See the colocated `.md` sidecar for the API, invariants and test strategy.
193
+ */
194
+ type TrustState = 'dormant' | 'untrusted' | 'trusted';
195
+ /** Serializable trust memory (survives Redux round-trips). */
196
+ interface TrustMemory {
197
+ readonly state: TrustState;
198
+ readonly agreeStreak: number;
199
+ readonly disagreeStreak: number;
200
+ /** Derived per-step: surface the figure-8 prompt (observable + sustained disagreement). */
201
+ readonly recommendRecalibration: boolean;
202
+ }
203
+ //#endregion
169
204
  //#region ../src/state/models/gpsEvents.d.ts
170
205
  /**
171
206
  * Plain object representing GPS events state.
@@ -200,6 +235,23 @@ interface GpsEventsState {
200
235
  */
201
236
  lastAdmittedOdomPos: Vector3 | null;
202
237
  lastAdmittedTs: number | null;
238
+ /**
239
+ * Phase-4 Stage 0 (only present when `useCompassColdStartOverride` is on):
240
+ * ring buffer of the last N GPS-only solved yaw bearings (deg) feeding the
241
+ * intrinsic observability gate, and the last applied override bearing driving
242
+ * the snap-correction across incremental calls. **Absent** when the override is
243
+ * off ⇒ byte-identical state shape for every existing consumer. Reset on
244
+ * origin-jump rebuilds (the batch path rebuilds the window from prefixes).
245
+ */
246
+ coldStartYawWindowDeg?: number[];
247
+ coldStartAppliedBearingDeg?: number | null;
248
+ /**
249
+ * Phase-4 Stage C (only present when `useCompassRotationPrior` is on): the
250
+ * compass consistency-trust memory, updated each observation from the windowed
251
+ * compass-vs-GPS-only-yaw agreement (gated on observability). Absent otherwise
252
+ * ⇒ byte-identical state shape. Reset to dormant on origin-jump rebuilds.
253
+ */
254
+ compassTrust?: TrustMemory;
203
255
  }
204
256
  //#endregion
205
257
  //#region ../src/state/types.d.ts
@@ -353,6 +405,16 @@ interface GpsModel {
353
405
  zero: LatLong;
354
406
  gpsEvents: GpsEventsType;
355
407
  odometryPath: OdometryPath;
408
+ /**
409
+ * Runtime opt-in for the Phase-4 Stage-0 cold-start compass yaw override
410
+ * (closed/internal alignment feature). Set via `setColdStartOverrideEnabled`
411
+ * — must be dispatched **after** `setZeroPos` (state is null before it). When
412
+ * truthy the reducer threads `{ useCompassColdStartOverride: true }` into the
413
+ * solve; absent/false ⇒ byte-identical to today. A debug/experiment flag —
414
+ * keep OFF until the §6a field matrix re-tunes the thresholds. See
415
+ * GpsPlusSlamJs_Docs/docs/2026-06-26-absolute-orientation-sensor-phase4-stage0-followup.md.
416
+ */
417
+ coldStartOverrideEnabled?: boolean;
356
418
  }
357
419
  interface GpsSlamState {
358
420
  gpsData: GpsModel | null;
@@ -476,6 +538,7 @@ declare const recordGpsEvent: _$_reduxjs_toolkit0.ActionCreatorWithPayload<Recor
476
538
  declare const odometryTrackingRestarted: _$_reduxjs_toolkit0.ActionCreatorWithPayload<OdometryTrackingRestartedPayload, "gpsData/odometryTrackingRestarted">;
477
539
  declare const arLoopClosureDetected: _$_reduxjs_toolkit0.ActionCreatorWithPayload<ArLoopClosureDetectedPayload, "gpsData/arLoopClosureDetected">;
478
540
  declare const add2dImage: _$_reduxjs_toolkit0.ActionCreatorWithPayload<ArImageCapture, "gpsData/add2dImage">;
541
+ declare const setColdStartOverrideEnabled: _$_reduxjs_toolkit0.ActionCreatorWithPayload<boolean, "gpsData/setColdStartOverrideEnabled">;
479
542
  declare const gpsDataReducer: (state: GpsModel | null | undefined, action: _$redux.UnknownAction) => GpsModel | null;
480
543
  //#endregion
481
544
  //#region ../src/state/gpsElementsSlice.d.ts
@@ -681,4 +744,4 @@ declare function validateLicenseKey(key: string): LicenseValidationResult;
681
744
  //#region ../src/index.d.ts
682
745
  declare const LIB_VERSION = "1.0.0";
683
746
  //#endregion
684
- export { type Add2dImagePayload, type ArElementsState, type ArImageCapture, type ArLoopClosureDetectedPayload, type AreaPolygon, type CreateGpsSlamStoreOptions, type DetectedArPlane, type EventArea, type FloorDetection, type GpsElementsState, type GpsLine, type GpsMarker, type GpsModel, type GpsPoint, type GpsSlamDispatch, type GpsSlamState, type GpsSlamStore, type HeatArea, type HeatMapTile, IDENTITY_MATRIX4, IDENTITY_QUATERNION, LIB_VERSION, type LatLong, type LatLongAlt, type LicenseValidationResult, type Matrix4, type OdometryPath, type OdometryTrackingRestartedPayload, type Quaternion, type RawAbsoluteOrientation, type RawDeviceOrientation, type RawGpsPoint, type RecordGpsEventPayload, type RootState, type Vector3, type Vector4, WMM2025_EPOCH, WMM2025_VALID_FROM, WMM2025_VALID_TO, ZERO_VECTOR3, add2dImage, addArea, addCornerToEventArea, addHeatMapArea, addLine, addMarker, addOrUpdateArPlane, addToHeatMaps, anchorEventAreaInWorldSpace, arElementsReducer, arLoopClosureDetected, arNorthBearingDeg, arToEnuRotation, bearingDeltaDeg, calcGeoHash, calcGpsCoords, calcQuadKey, calcRelativeCoordsInMeters, cloneMatrix4, cloneQuaternion, cloneVector3, correctArDriftForEventArea, createGpsSlamStore, distanceInMeters, distanceInMetersRelative, enuQuaternionToNUE, eulerToQuaternion, finishEventArea, fromMatrix4, fromQuaternion, fromVector3, fusedGpsFromOdom, geoHashToLatLong, getAlignmentMatrix, getAlignmentRotation, getGoogleMapsDirectionsLink, getGoogleMapsLink, getGpsAccuracyStats, getGpsPositions, getOdometryPositions, getOdometryRotations, getOpenStreetMapLink, getZeroReference, gpsDataReducer, gpsElementsReducer, invertQuaternion, isIdentityMatrix4, isIdentityQuaternion, isNearIdentityQuaternion, magneticDeclinationDeg, magneticHeadingFromEnuQuat, magneticToTrueHeadingDeg, multiplyQuaternions, normalizeQuaternion, nueQuaternionToENU, nueQuaternionToWebXR, nueToWebXR, odometryTrackingRestarted, quadKeyToLatLong, quaternionMagnitude, quaternionsEquivalent, recordGpsEvent, recordPhoneHeight, resetArElements, resetGpsElements, sanitizeForDevTools, setZeroPos, startEventArea, toEarthCenteredCoordinates, toMatrix4, toQuaternion, toVector3, validateLicenseKey, webxrQuaternionToNUE, webxrToNUE };
747
+ export { type Add2dImagePayload, type ArElementsState, type ArImageCapture, type ArLoopClosureDetectedPayload, type AreaPolygon, type CreateGpsSlamStoreOptions, type DetectedArPlane, type EventArea, type FloorDetection, type GpsElementsState, type GpsLine, type GpsMarker, type GpsModel, type GpsPoint, type GpsSlamDispatch, type GpsSlamState, type GpsSlamStore, type HeatArea, type HeatMapTile, IDENTITY_MATRIX4, IDENTITY_QUATERNION, LIB_VERSION, type LatLong, type LatLongAlt, type LicenseValidationResult, type Matrix4, type OdometryPath, type OdometryTrackingRestartedPayload, type Quaternion, type RawAbsoluteOrientation, type RawDeviceOrientation, type RawGpsPoint, type RecordGpsEventPayload, type RootState, type Vector3, type Vector4, WMM2025_EPOCH, WMM2025_VALID_FROM, WMM2025_VALID_TO, ZERO_VECTOR3, add2dImage, addArea, addCornerToEventArea, addHeatMapArea, addLine, addMarker, addOrUpdateArPlane, addToHeatMaps, anchorEventAreaInWorldSpace, arElementsReducer, arLoopClosureDetected, arNorthBearingDeg, arToEnuRotation, bearingDeltaDeg, calcGeoHash, calcGpsCoords, calcQuadKey, calcRelativeCoordsInMeters, cloneMatrix4, cloneQuaternion, cloneVector3, correctArDriftForEventArea, createGpsSlamStore, distanceInMeters, distanceInMetersRelative, enuQuaternionToNUE, eulerToQuaternion, finishEventArea, fromMatrix4, fromQuaternion, fromVector3, fusedGpsFromOdom, geoHashToLatLong, getAlignmentMatrix, getAlignmentRotation, getGoogleMapsDirectionsLink, getGoogleMapsLink, getGpsAccuracyStats, getGpsPositions, getOdometryPositions, getOdometryRotations, getOpenStreetMapLink, getZeroReference, gpsDataReducer, gpsElementsReducer, invertQuaternion, isIdentityMatrix4, isIdentityQuaternion, isNearIdentityQuaternion, magneticDeclinationDeg, magneticHeadingFromEnuQuat, magneticToTrueHeadingDeg, multiplyQuaternions, normalizeQuaternion, nueQuaternionToENU, nueQuaternionToWebXR, nueToWebXR, odometryTrackingRestarted, quadKeyToLatLong, quaternionMagnitude, quaternionsEquivalent, recordGpsEvent, recordPhoneHeight, resetArElements, resetGpsElements, sanitizeForDevTools, setColdStartOverrideEnabled, setZeroPos, startEventArea, toEarthCenteredCoordinates, toMatrix4, toQuaternion, toVector3, validateLicenseKey, webxrQuaternionToNUE, webxrToNUE };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! gps-plus-slam-js | (c) 2026 cs-util-com | UNLICENSED — see EULA.md */
2
- import{configureStore as e,createSlice as t}from"@reduxjs/toolkit";import{ed25519 as n}from"@noble/curves/ed25519.js";import{hexToBytes as r}from"@noble/curves/utils.js";import{mat4 as i,quat as a,vec3 as o,vec4 as s}from"gl-matrix";import{castDraft as c}from"immer";let l=!1;function u(){l=!0}function d(){if(!l)throw Error(`gps-plus-slam-js: license not activated. Construct your store via createRecorderStore() from gps-plus-slam-app-framework, or pass a valid licenseKey to createGpsSlamStore(). See EULA §3.`)}function f(e){return((...t)=>(d(),e(...t)))}function p(e){let t=((...t)=>(d(),e(...t)));return Object.assign(t,e),t.toString=()=>e.type,t}function m(e){return(t,n)=>(d(),e(t,n))}function h(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`),n=`=`.repeat((4-t.length%4)%4),r=atob(t+n);return Uint8Array.from(r,e=>e.charCodeAt(0))}function g(e){let t=new Date,i=e.indexOf(`.`);if(i<=0||i>=e.length-1)throw Error(`Invalid license key format: expected "payload.signature" with base64url-encoded parts.`);let a,o;try{a=h(e.substring(0,i)),o=h(e.substring(i+1))}catch{throw Error(`Invalid license key format: base64url decoding failed.`)}let s=r(`dfe5c62120b7a0ce962b17907a15b27cf1b056e6619bf6ce55e6e094b322a470`);if(!n.verify(o,a,s))throw Error(`Invalid license key: signature verification failed.`);let c=JSON.parse(new TextDecoder().decode(a));if(typeof c!=`object`||!c)throw Error(`Invalid license key: payload must be a JSON object.`);let{type:l,exp:d}=c;if(l!==`community`)throw Error(`Invalid license key: "type" must be "community".`);if(typeof d!=`number`||!Number.isFinite(d))throw Error(`Invalid license key: "exp" must be a finite number (Unix timestamp in seconds).`);if(d<Math.floor(t.getTime()/1e3)){let e=new Date(d*1e3);throw Error(`License key expired on ${e.toISOString()}. Update to the latest version for a renewed community key.`)}return u(),{type:l,expiresAt:new Date(d*1e3)}}const _=180/Math.PI,v=e=>{let t=e[0],n=e[1],r=e[2],i=e[3],a=2*(i*t+n*r),o=1-2*(t*t+n*n),s=Math.atan2(a,o)*_,c=2*(i*n-r*t),l=Math.abs(c)>=1?Math.sign(c)*90:Math.asin(c)*_,u=2*(i*r+t*n),d=1-2*(n*n+r*r);return{pitch:l,yaw:Math.atan2(u,d)*_,roll:s}},y=1/298.257223563,b=y*(2-y),x=40075016.6856/360,S=39940652.7422/360,C=Math.PI/180,w=180/Math.PI,T=`0123456789bcdefghjkmnpqrstuvwxyz`,E=[16,8,4,2,1],D=(e,t,n)=>Math.min(Math.max(e,t),n),O=e=>D(e,-180,180),k=e=>e*C,A=e=>e*w,j=e=>{if(!Number.isFinite(e))throw RangeError(`Coordinate values must be finite numbers`);return String(e)},M=e=>({lat:j(e.lat),lon:j(e.lon)}),ee=(e,t=0)=>{let n=k(e.lat),r=k(e.lon),i=Math.sin(n),a=Math.cos(n),s=Math.sin(r),c=Math.cos(r),l=6378137/Math.sqrt(1-b*i*i),u=(l+t)*a*c,d=(l+t)*a*s,f=(l*(1-b)+t)*i;return o.fromValues(u,d,f)},te=f((e,t)=>{if(t<1||t>23)throw RangeError(`levelOfDetail must be between 1 and 23 (inclusive)`);let n=D(e.lat,-85.05112878,85.05112878),r=O(e.lon),i=Math.sin(k(n)),a=256*2**t,o=(r+180)/360*a,s=(.5-Math.log((1+i)/(1-i))/(4*Math.PI))*a,c=2**t-1,l=D(Math.floor(o/256),0,c),u=D(Math.floor(s/256),0,c),d=``;for(let e=t;e>0;--e){let t=0,n=1<<e-1;(l&n)!==0&&(t+=1),(u&n)!==0&&(t+=2),d+=t.toString()}return d}),ne=f(e=>{if(!/^[0-3]+$/.test(e))throw Error(`QuadKey must consist of digits 0-3`);let t=e.length;if(t===0)throw Error(`QuadKey must not be empty`);let n=0,r=0;for(let i=0;i<t;i+=1){let a=Number.parseInt(e[i],10),o=1<<t-i-1;a&1&&(n+=o),a&2&&(r+=o)}let i=256*2**t,a=(n+.5)*256,o=(r+.5)*256,s=a/i,c=o/i,l=s*360-180;return{lat:A(Math.atan(Math.sinh(Math.PI*(1-2*c)))),lon:l}}),re=f((e,t)=>{if(t<=0)throw RangeError(`precision must be greater than 0`);let n=-90,r=90,i=-180,a=180,o=``,s=0,c=0,l=!0;for(;o.length<t;){if(l){let t=(i+a)/2;e.lon>=t?(c|=E[s],i=t):a=t}else{let t=(n+r)/2;e.lat>=t?(c|=E[s],n=t):r=t}l=!l,s<4?s+=1:(o+=T[c],s=0,c=0)}return o}),ie=f(e=>{if(e.length===0)throw Error(`geoHash must not be empty`);let t=-90,n=90,r=-180,i=180,a=!0;for(let o of e){let e=T.indexOf(o);if(e===-1)throw Error(`Invalid geohash character: ${o}`);for(let o of E){if(a){let t=(r+i)/2;(e&o)===0?i=t:r=t}else{let r=(t+n)/2;(e&o)===0?n=r:t=r}a=!a}}return{lat:(t+n)/2,lon:(r+i)/2}}),ae=f((e,t)=>{let n=k(e.lat),r=k(t.lat),i=r-n,a=k(t.lon-e.lon),o=Math.sin(i/2),s=Math.sin(a/2),c=o*o+Math.cos(n)*Math.cos(r)*s*s,l=Math.min(1,Math.max(0,c));return 6371008.8*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}),oe=f((e,t)=>{let n=N(e,t);return Math.hypot(n[0],n[2])}),N=f((e,t,n=0,r=0)=>{let i=(t.lon-e.lon)*x*Math.cos(k(e.lat)),a=(t.lat-e.lat)*S,s=n-r;return o.fromValues(a,s,i)}),P=f((e,t)=>{let n=t[0],r=t[2];return{lat:n/S+e.lat,lon:r/(x*Math.cos(k(e.lat)))+e.lon}}),se=f((e,t=0)=>ee(e,t)),F=e=>{let{lat:t,lon:n}=M(e);return`${t}%2C${n}`},ce=f(e=>`https://www.google.com/maps/search/?api=1&query=${F(e)}`),le=f((e,t)=>`https://www.google.com/maps/dir/?api=1&origin=${F(t)}&destination=${F(e)}`),ue=f((e,t=19)=>{let{lat:n,lon:r}=M(e);return`https://www.openstreetmap.org/query?lat=${n}&lon=${r}#map=${t}/${n}/${r}`}),de=f((e,t,n)=>{let r=i.fromValues(...e),a=o.fromValues(t[0],t[1],t[2]),s=o.create();o.transformMat4(s,a,r);let{lat:c,lon:l}=P(n,s);return{lat:c,lon:l,altitude:s[1]}}),fe=()=>({points:[]}),pe=()=>({gpsMarkers:[],gpsLines:[],areas:[],heatMap:{},heatAreas:{}}),me=()=>({arPlanes:{},floorDetections:[],eventAreas:[],currentEventAreaId:null,currentEventAreaPoints:[]}),I=e=>o.fromValues(e[0],e[1],e[2]),L=e=>a.fromValues(e[0],e[1],e[2],e[3]),he=e=>i.fromValues(...e),R=e=>[e[0],e[1],e[2]],z=e=>[e[0],e[1],e[2],e[3]],ge=e=>[e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9],e[10],e[11],e[12],e[13],e[14],e[15]],B=e=>[e[0],e[1],e[2]],_e=e=>[e[0],e[1],e[2],e[3]],ve=e=>[...e],V=Object.freeze([0,0,0,1]),H=Object.freeze([0,0,0]),ye=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),U=e=>{let t=xe(e);if(t===0)return V;let n=1/t;return[e[0]*n,e[1]*n,e[2]*n,e[3]*n]},be=e=>{for(let t=0;t<16;t++)if(e[t]!==ye[t])return!1;return!0},xe=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]+e[3]*e[3]),Se=e=>e[0]===0&&e[1]===0&&e[2]===0&&e[3]===1,Ce=(e,t)=>Math.abs(e[0])<t&&Math.abs(e[1])<t&&Math.abs(e[2])<t&&Math.abs(e[3]-1)<t,we=(e,t,n=1e-10)=>{let r=Math.abs(e[0]-t[0])<n&&Math.abs(e[1]-t[1])<n&&Math.abs(e[2]-t[2])<n&&Math.abs(e[3]-t[3])<n,i=Math.abs(e[0]+t[0])<n&&Math.abs(e[1]+t[1])<n&&Math.abs(e[2]+t[2])<n&&Math.abs(e[3]+t[3])<n;return r||i},Te=(e,t)=>{let n=a.create();return a.multiply(n,e,t),[n[0],n[1],n[2],n[3]]},Ee=e=>{let t=a.create();return a.invert(t,e),[t[0],t[1],t[2],t[3]]},W=e=>[-e[2],e[1],e[0]],De=e=>[e[2],e[1],-e[0]],G=e=>[-e[2],e[1],e[0],e[3]],Oe=e=>[e[2],e[1],-e[0],e[3]],K=e=>[e[1],e[2],e[0],e[3]],ke=e=>[e[2],e[0],e[1],e[3]],Ae=(e,t,n)=>{if(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(n))throw Error(`eulerToQuaternion: non-finite input (alpha=${e}, beta=${t}, gamma=${n})`);let r=e*Math.PI/180,i=t*Math.PI/180,o=n*Math.PI/180,s=a.create(),c=a.create(),l=a.create();a.setAxisAngle(s,[0,0,1],r),a.setAxisAngle(c,[1,0,0],i),a.setAxisAngle(l,[0,1,0],o);let u=a.create();return a.multiply(u,s,c),a.multiply(u,u,l),[u[0],u[1],u[2],u[3]]},je=t({name:`arElements`,initialState:me(),reducers:{recordPhoneHeight:(e,t)=>{e.floorDetections.push(t.payload)},addOrUpdateArPlane:(e,t)=>{let n=t.payload;if(n.parentPlaneId){delete e.arPlanes[n.planeId];return}e.arPlanes[n.planeId]=c(n)},startEventArea:(e,t)=>{e.currentEventAreaId=t.payload.id,e.currentEventAreaPoints=[]},addCornerToEventArea:(e,t)=>{e.currentEventAreaId&&e.currentEventAreaPoints.push(c(B(t.payload.position)))},correctArDriftForEventArea:(e,t)=>{let n=t.payload.drift;for(let t of e.currentEventAreaPoints)t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]},finishEventArea:(e,t)=>{e.currentEventAreaId&&(e.eventAreas.push({id:e.currentEventAreaId,label:t.payload.label,polygon:[],isInArSpace:!0,arPoints:e.currentEventAreaPoints}),e.currentEventAreaId=null,e.currentEventAreaPoints=[])},anchorEventAreaInWorldSpace:(e,t)=>{let{areaId:n,alignmentMatrix:r,zeroRef:i}=t.payload,a=e.eventAreas.findIndex(e=>e.id===n);if(a===-1)return;let s=e.eventAreas[a];if(!s.isInArSpace||!s.arPoints)throw Error(`The area ${s.id} is already anchored in world space`);let c=he(r),l=s.arPoints.map(e=>{let t=I(e);return P(i,o.transformMat4(o.create(),t,c))});e.eventAreas[a]={...s,isInArSpace:!1,polygon:l,arPoints:void 0}},resetArElements:()=>me()}}),{recordPhoneHeight:Me,addOrUpdateArPlane:Ne,startEventArea:Pe,addCornerToEventArea:Fe,correctArDriftForEventArea:Ie,finishEventArea:Le,anchorEventAreaInWorldSpace:Re,resetArElements:ze}=je.actions,Be=p(Me),Ve=p(Ne),He=p(Pe),Ue=p(Fe),We=p(Ie),Ge=p(Le),Ke=p(Re),qe=p(ze),Je=m(je.reducer);function Ye(e,t,n,r){let{inCentroid:i,refCentroid:a,refVec:s,tmp:c}=r;o.set(i,0,0,0),o.set(a,0,0,0);let l=0;for(let n=0;n<e.length;n++){let r=t[n][3];o.scaleAndAdd(i,i,e[n],r),$e(s,t[n]),o.scaleAndAdd(a,a,s,r),l+=r}if(l===0)throw Error(`Weights must not sum to zero when solving Kabsch`);let u=1/l;if(o.scale(i,i,u),o.scale(a,a,u),!n)return{inCentroid:i,refCentroid:a,scaleRatio:1};let d=0,f=0;for(let n=0;n<e.length;n++)o.subtract(c,e[n],i),d+=o.length(c),$e(s,t[n]),o.subtract(c,s,a),f+=o.length(c);return{inCentroid:i,refCentroid:a,scaleRatio:d===0?1:f/d}}function Xe(e,t,n,r,a,s,c){let{negCentroid:l,scaleVec:u}=c;return i.fromRotationTranslation(e,r,n),s&&(o.set(u,a,a,a),i.scale(e,e,u)),o.negate(l,t),i.translate(e,e,l),e}function Ze(e,t,n={}){let r=e.length;if(r!==t.length)throw Error(`Length of the point lists was not equal: ${r} vs ${t.length}`);if(r===0)return i.create();let s=n.solveRotation??!0,c=n.solveScale??!1,l=n.ignoreYAxisForRotation??!1,u=n.rotationIterations??9,{inCentroid:d,refCentroid:f,scaleRatio:p}=Ye(e,t,c,{inCentroid:o.create(),refCentroid:o.create(),refVec:o.create(),tmp:o.create()}),m=a.create();s?new Qe(l).solve(e,t,d,f,m,u):a.identity(m);let h={negCentroid:o.create(),scaleVec:o.create()};return Xe(i.create(),d,f,m,p,c,h)}var Qe=class e{ignoreYAxis;static twoPi=Math.PI*2;static basisX=o.fromValues(1,0,0);static basisY=o.fromValues(0,1,0);static basisZ=o.fromValues(0,0,1);constructor(e){this.ignoreYAxis=e}solve(t,n,r,i,o,s){let c=this.transposeMultSubtract(t,n,r,i);if(this.ignoreYAxis){let t=c[0][0],n=c[0][2],r=c[2][0],i=c[2][2],s=Math.atan2(r-n,t+i);a.setAxisAngle(o,e.basisY,s)}else this.extractRotation(c,o,s)}transposeMultSubtract(e,t,n,r){let i=[o.create(),o.create(),o.create()],a=o.clone(n),s=o.clone(r);this.ignoreYAxis&&(a[1]=0,s[1]=0);let c=o.create(),l=o.create(),u=o.create();for(let n=0;n<e.length;n++){o.copy(c,e[n]),$e(u,t[n]),this.ignoreYAxis&&(c[1]=0,u[1]=0);let r=t[n][3];o.subtract(c,c,a),o.scale(c,c,r),o.subtract(l,u,s),i[0][0]+=c[0]*l[0],i[1][0]+=c[1]*l[0],i[2][0]+=c[2]*l[0],i[0][1]+=c[0]*l[1],i[1][1]+=c[1]*l[1],i[2][1]+=c[2]*l[1],i[0][2]+=c[0]*l[2],i[1][2]+=c[1]*l[2],i[2][2]+=c[2]*l[2]}return i}extractRotation(t,n,r){let i=[o.create(),o.create(),o.create()],s=o.create(),c=o.create(),l=o.create();for(let u=0;u<r;u++){this.fillMatrixFromQuaternion(n,i),o.cross(s,i[0],t[0]),o.cross(l,i[1],t[1]),o.add(s,s,l),o.cross(l,i[2],t[2]),o.add(s,s,l);let r=o.dot(i[0],t[0])+o.dot(i[1],t[1])+o.dot(i[2],t[2])+1e-9;r=Math.abs(r),o.scale(s,s,1/r);let u=o.length(s);if(u<1e-9)break;o.scale(c,s,1/u);let d=u%e.twoPi,f=a.create();a.setAxisAngle(f,c,d),a.multiply(n,f,n),a.normalize(n,n)}}fillMatrixFromQuaternion(t,n){o.transformQuat(n[0],e.basisX,t),o.transformQuat(n[1],e.basisY,t),o.transformQuat(n[2],e.basisZ,t)}};const $e=(e,t)=>(e[0]=t[0],e[1]=t[1],e[2]=t[2],e);function et(e,t,n,r,i,a,o=Math.random){let s=Array.from(e);if(n>s.length)throw RangeError(`minSampleSize must be smaller than the number of elements: minSampleSize=${n}, elements=${s.length}`);return rt(s,tt(s,t,n,r,i,a,o),i,a)}function tt(e,t,n,r,i,a,o){let s=null,c=Array(n),l=new Uint8Array(e.length);for(let u=0;u<r;u+=1){at(e,n,o,c,l);let{inliers:r,outliers:u}=nt(e,l,i(c),a);if(s===null||n+r.length>=t){let e=[...c,...r],t=i(e),n=it(t,`createModel must assign totalModelError for comparison during RANSAC`);(s===null||n<s.error)&&(t.inliers=e,t.outliers=u,s={model:t,error:n})}}return s?.model??null}function nt(e,t,n,r){let i=[],a=[];for(let o=0;o<e.length;o+=1){if(t?.[o])continue;let s=e[o];(r(n,s)?i:a).push(s)}return{inliers:i,outliers:a}}function rt(e,t,n,r){let i=t??n(e);it(i,`RANSAC failed to produce a model with totalModelError`);let{inliers:a,outliers:o}=nt(e,null,i,r);return a.length>0&&(i=n(a),it(i,`createModel must assign totalModelError for final RANSAC model`)),i.inliers=a,i.outliers=o,i}function it(e,t){let{totalModelError:n}=e;if(n==null)throw Error(t);return n}function at(e,t,n,r,i){i.fill(0);let a=0;for(;a<t;){let t=Math.floor(n()*e.length);i[t]||(i[t]=1,r[a]=e[t],a+=1)}}const ot={useOnlyRecentData:!1,recentSeconds:180,includeTimeWeight:!0,weightByTimeFactor:2500,ignoreYAxisForRotation:!0,useRansac:!1,ransacInlierRatio:.95,ransacSampleRatio:.3,ransacMaxIterations:230,ransacErrorTolerance:1,geohashPrecision:8,geohashWindowSize:10,gpsAccuracyExponent:.1,altitudeAlignmentMode:`separate1D`,altitudeAggregator:`mean`,altitudeSampleSet:`all`,gpsVerticalAccuracyExponent:5,useOutlierRejection:!1,outlierThresholdMeters:10,outlierRetainRatio:.6,useDistanceGating:!1,minSampleDistanceMeters:1,maxSampleIntervalMs:3e3},st=e=>e.map(e=>B(e)),ct=e=>e.map(e=>U(e)),lt=e=>e.map(Rt),ut=e=>e.map(e=>[e[0],e[1],e[2],e[3]]),q=e=>Array.isArray(e)?e:R(e),J=e=>Array.isArray(e)?e:z(e),dt=(e,t,n,r)=>({odometryPosOffset:B(q(e)),odometryRotOffset:U(J(t)),latestLoopClosureFixPointPos:n?B(q(n)):null,latestLoopClosureFixPointRot:r?U(J(r)):null}),ft=(e,t,n,r)=>({odometryPositions:[],odometryRotations:[],gpsPositions:[],gpsPositionsVec4:[],alignmentMatrix:[...ye],alignmentRotation:[...V],alignmentTranslation:[...H],alignmentRotationInDegree:[...H],...dt(e,t,n,r),gpsAccuracyMedian:null,gpsAccuracyMean:null,currentGpsPosGeoHash:null,lastAdmittedOdomPos:null,lastAdmittedTs:null}),pt=()=>ft(H,V,null,null),mt=(e,t,n,r)=>{let i=e.map(e=>q(e)),a=t.map(e=>U(J(e))),o=n.map(Rt),s=r.gpsAccuracyExponent;for(let e of o)e.weight=vt(e.latLongAccuracy,s);let c=o.map(It),l=r.includeTimeWeight?Mt(c,o,r.weightByTimeFactor):c,u=r.useOnlyRecentData?At(o,r.recentSeconds):0,d=i.slice(u).map(I),f=o.slice(u);return{allPositionTuples:i,allRotationTuples:a,allGpsPoints:o,allVec4Tuples:l,solverPositionsTyped:d,solverGpsPoints:f,solverWeightedVec4Tuples:l.slice(u),solverVerticalWeights:jt(f,r)}},ht=(e,t,n,r,i)=>{if(e==null||t==null)return!0;let a=n[0]-e[0],o=n[2]-e[2],s=i.minSampleDistanceMeters*i.minSampleDistanceMeters;return a*a+o*o>=s||r-t>=i.maxSampleIntervalMs},gt=(e,t,n,r)=>{if(!r.useDistanceGating)return{odometryPositions:e,odometryRotations:t,gpsPoints:n};let i=[],a=[],o=[],s=null,c=null;for(let l=0;l<n.length;l+=1){let u=q(e[l]),d=n[l].timestamp;ht(s,c,u,d,r)&&(i.push(e[l]),a.push(t[l]),o.push(n[l]),s=u,c=d)}return{odometryPositions:i,odometryRotations:a,gpsPoints:o}},_t=e=>{let{odometryPositions:t,odometryRotations:n,gpsPoints:r,odometryPosOffset:i=H,odometryRotOffset:s=V,latestLoopClosureFixPointPos:c=null,latestLoopClosureFixPointRot:l=null,alignmentConfig:u,random:d}=e;if(t.length!==n.length||t.length!==r.length)throw Error(`GpsEvents requires odometry positions, rotations, and gps points to have identical lengths`);let f={...ot,...u??{}};if(t.length===0)return ft(i,s,c,l);let p=gt(t,n,r,f),{allPositionTuples:m,allRotationTuples:h,allGpsPoints:g,allVec4Tuples:_,solverPositionsTyped:v,solverGpsPoints:y,solverWeightedVec4Tuples:b,solverVerticalWeights:x}=mt(p.odometryPositions,p.odometryRotations,p.gpsPoints,f),S=St(v,b,x,f,d??Math.random),C=a.create(),w=o.create(),T=o.create();bt(S.matrix,C,w,T);let{mean:E,median:D}=Pt(g),O=Nt(p.gpsPoints,f.geohashPrecision,f.geohashWindowSize),k=m.length-1,A=k>=0?B(m[k]):null,j=k>=0?p.gpsPoints[k]?.timestamp??null:null;return{odometryPositions:st(m),odometryRotations:ct(h),gpsPositions:lt(g),gpsPositionsVec4:ut(_),alignmentMatrix:ge(S.matrix),alignmentRotation:z(C),alignmentTranslation:R(w),alignmentRotationInDegree:R(T),...dt(i,s,c,l),gpsAccuracyMedian:D,gpsAccuracyMean:E,currentGpsPosGeoHash:O,lastAdmittedOdomPos:A,lastAdmittedTs:j}},vt=(e,t)=>e!=null&&e>0?1/Math.max(e,1)**+t:1,yt=(e,t,n,r,i,s)=>{let c={...ot,...i??{}},l=q(t);if(c.useDistanceGating&&!ht(e.lastAdmittedOdomPos,e.lastAdmittedTs,l,r.timestamp,c))return;let u=e.odometryPositions,d=e.odometryRotations,f=e.gpsPositions,p=e.gpsPositionsVec4;u.push(l),d.push(U(J(n)));let m=Rt(r);f.push(m),m.weight=vt(m.latLongAccuracy,c.gpsAccuracyExponent);let h=It(m);if(c.includeTimeWeight){p.push(h);let e=Mt(p,f,c.weightByTimeFactor);for(let t=0;t<e.length;t++)p[t]=e[t]}else p.push(h);let g=0;c.useOnlyRecentData&&(g=At(f,c.recentSeconds));let _=St(u.slice(g).map(I),p.slice(g),jt(f.slice(g),c),c,s??Math.random);e.alignmentMatrix=ge(_.matrix);let v=a.create(),y=o.create(),b=o.create();bt(_.matrix,v,y,b),e.alignmentRotation=z(v),e.alignmentTranslation=R(y),e.alignmentRotationInDegree=R(b);let{mean:x,median:S}=Pt(f);e.gpsAccuracyMean=x,e.gpsAccuracyMedian=S,e.currentGpsPosGeoHash=Nt(f,c.geohashPrecision,c.geohashWindowSize),e.lastAdmittedOdomPos=B(l),e.lastAdmittedTs=r.timestamp},bt=(e,t,n,r)=>{i.getRotation(t,e),a.normalize(t,t),i.getTranslation(n,e),Ft(t,r)},Y=o.create(),xt=o.create(),St=(e,t,n,r,a)=>{if(e.length===0)return{matrix:i.create(),meanError:0};let o=e.length,c=[];for(let r=0;r<o;r+=1){let i=t[r];c.push({odom:e[r],ref:s.fromValues(i[0],i[1],i[2],i[3]),verticalWeight:n[r]??1})}let l,u,d;if(r.useRansac&&c.length>=3){let e=c.length,t=Math.max(3,Math.min(e,Math.ceil(e*r.ransacSampleRatio))),n=et(c,Math.max(t,Math.min(e,Math.ceil(e*r.ransacInlierRatio))),t,r.ransacMaxIterations,e=>X(e,r.ignoreYAxisForRotation),(e,t)=>Et(e,t)<e.meanAlignmentError+r.ransacErrorTolerance,a);l=n.alignmentMatrix,u=n.meanAlignmentError,n.inliers!==void 0&&(d=Array.from(n.inliers))}else if(r.useOutlierRejection&&c.length>=4){let{model:e,inliers:t}=kt(c,r);l=e.alignmentMatrix,u=e.meanAlignmentError,d=t}else{let e=X(c,r.ignoreYAxisForRotation);l=e.alignmentMatrix,u=e.meanAlignmentError}return r.altitudeAlignmentMode===`separate1D`&&Ct(l,c,d,r),{matrix:l,meanError:u}},Ct=(e,t,n,r)=>{let i=r.altitudeSampleSet===`horizontalInliers`&&n!==void 0&&n.length>0?n:t;if(i.length===0)return;let a=Array(i.length),o=Array(i.length);for(let e=0;e<i.length;e+=1){let t=i[e];a[e]=t.ref[1]-t.odom[1];let n=t.verticalWeight;o[e]=n>0&&Number.isFinite(n)?n:0}e[13]=r.altitudeAggregator===`median`?Tt(a,o):wt(a,o)},wt=(e,t)=>{let n=0,r=0;for(let i=0;i<e.length;i+=1)n+=e[i]*t[i],r+=t[i];if(r>0&&Number.isFinite(r))return n/r;let i=0;for(let t=0;t<e.length;t+=1)i+=e[t];return e.length===0?0:i/e.length},Tt=(e,t)=>{if(e.length===0)return 0;if(e.length===1)return e[0];let n=e.map((e,t)=>t);n.sort((t,n)=>e[t]-e[n]);let r=0;for(let e=0;e<t.length;e+=1)r+=t[e];if(!(r>0)||!Number.isFinite(r)){let t=n.map(t=>e[t]);return t[Math.floor((t.length-1)/2)]}let i=r/2,a=0;for(let r=0;r<n.length;r+=1)if(a+=t[n[r]],a>=i)return e[n[r]];return e[n[n.length-1]]},X=(e,t)=>{let n=Array.from(e),r=n.length,i=Array(r),a=Array(r);for(let e=0;e<r;e+=1)i[e]=n[e].odom,a[e]=n[e].ref;let s=Ze(i,a,{ignoreYAxisForRotation:t}),c=0;for(let e=0;e<r;e+=1)o.transformMat4(Y,i[e],s),c+=Dt(Y,n[e].ref);return{alignmentMatrix:s,meanAlignmentError:r===0?0:c/r,totalModelError:c}},Et=(e,t)=>(o.transformMat4(Y,t.odom,e.alignmentMatrix),Dt(Y,t.ref)),Dt=(e,t)=>(o.set(xt,t[0],t[1],t[2]),o.squaredDistance(e,xt)),Ot=(e,t)=>{o.transformMat4(Y,t.odom,e.alignmentMatrix);let n=Y[0]-t.ref[0],r=Y[2]-t.ref[2];return n*n+r*r},kt=(e,t)=>{let n=e.length,r=Math.max(3,Math.ceil(t.outlierRetainRatio*n)),i=t.outlierThresholdMeters*t.outlierThresholdMeters,a=Array.from(e),o=X(a,t.ignoreYAxisForRotation);for(;a.length>r;){let e=-1,n=-1;for(let t=0;t<a.length;t+=1){let r=Ot(o,a[t]);r>n&&(n=r,e=t)}if(n<=i||e<0)break;a=a.filter((t,n)=>n!==e),o=X(a,t.ignoreYAxisForRotation)}return{model:o,inliers:a}},At=(e,t)=>{if(e.length===0||t<=0)return 0;let n=e[e.length-1].timestamp-t*1e3;for(let t=0;t<e.length;t+=1)if(e[t].timestamp>=n)return t;return 0},jt=(e,t)=>{let n=t.gpsVerticalAccuracyExponent,r=e.map(e=>{let t=e.altitudeAccuracy;return vt(t!=null&&Number.isFinite(t)&&t>0?t:e.latLongAccuracy,n)});if(!t.includeTimeWeight||e.length<2)return r;let i=e[e.length-1].timestamp,a=e[0].timestamp,o=Math.max(1,i-a),s=t.weightByTimeFactor;return r.map((t,n)=>{if(!(t>0&&Number.isFinite(t)))return 0;let r=s*((i-e[n].timestamp)/o)+1;return 1/(1/t+r)})},Mt=(e,t,n)=>{if(e.length<2)return e.map(e=>[e[0],e[1],e[2],e[3]]);let r=t[t.length-1].timestamp,i=t[0].timestamp,a=Math.max(1,r-i);return e.map((e,i)=>{let o=n*((r-t[i].timestamp)/a)+1,s=t[i].weight;if(!(s>0&&Number.isFinite(s)))return[e[0],e[1],e[2],0];let c=1/(1/s+o);return[e[0],e[1],e[2],c]})},Z=new Map,Nt=(e,t,n)=>{if(e.length===0)return null;let r=Math.max(0,e.length-n);Z.clear();for(let n=r;n<e.length;n+=1){let r=e[n],i=re(Lt(r),t),a=Z.get(i);a?(a.count+=1,a.index=n):Z.set(i,{count:1,index:n})}let i=null,a=-1,o=-1;for(let[e,{count:t,index:n}]of Z)(t>a||t===a&&n>o)&&(i=e,a=t,o=n);return i},Pt=e=>{let t=e.map(e=>e.latLongAccuracy).filter(e=>typeof e==`number`&&Number.isFinite(e));if(t.length===0)return{mean:null,median:null};let n=t.reduce((e,t)=>e+t,0)/t.length,r=t.slice().sort((e,t)=>e-t),i=Math.floor(r.length/2);return{mean:n,median:r.length%2==0?(r[i-1]+r[i])/2:r[i]}},Ft=(e,t)=>{let n=e[0],r=e[1],i=e[2],a=e[3],s=2*(a*n+r*i),c=1-2*(n*n+r*r),l=Math.atan2(s,c),u=2*(a*r-i*n),d;d=Math.abs(u)>=1?Math.PI/2*Math.sign(u):Math.asin(u);let f=2*(a*i+n*r),p=1-2*(r*r+i*i),m=Math.atan2(f,p),h=180/Math.PI,g=t??o.create();return g[0]=l*h,g[1]=d*h,g[2]=m*h,g},It=e=>[e.coordinates[0],e.coordinates[1],e.coordinates[2],e.weight>0&&Number.isFinite(e.weight)?e.weight:1],Lt=e=>({lat:e.latitude,lon:e.longitude}),Rt=e=>({...e,zeroRef:{lat:e.zeroRef.lat,lon:e.zeroRef.lon},coordinates:[e.coordinates[0],e.coordinates[1],e.coordinates[2]],timestamp:e.timestamp,deviceRotation:e.deviceRotation?U(J(e.deviceRotation)):void 0,absoluteOrientation:e.absoluteOrientation?{...e.absoluteOrientation,quaternion:[e.absoluteOrientation.quaternion[0],e.absoluteOrientation.quaternion[1],e.absoluteOrientation.quaternion[2],e.absoluteOrientation.quaternion[3]]}:void 0}),zt=({lat:e,lon:t})=>{if(!Number.isFinite(e))throw Error(`Invalid latitude value: ${e}`);if(!Number.isFinite(t))throw Error(`Invalid longitude value: ${t}`);if(e<-90||e>90)throw Error(`Invalid latitude range: ${e}`);if(t<-180||t>180)throw Error(`Invalid longitude range: ${t}`)},Bt=o.fromValues(1,1,1),Vt=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],Ht=(e,t,n,r)=>{let i=N(t,{lat:e.latitude,lon:e.longitude},e.altitude??0,0),a=n?.alpha!=null&&n?.beta!=null&&n?.gamma!=null?K(Ae(n.alpha,n.beta,n.gamma)):void 0;return{...e,zeroRef:t,coordinates:R(i),weight:1,deviceRotation:a,absoluteOrientation:r}},Ut=(e,t,n)=>{if(e)return Ae(e.alpha,e.beta,e.gamma);if(t)return t;throw Error(`Sensor rotation missing for ${n}: neither raw orientation nor legacy quaternion provided`)},Wt=e=>{let t=a.invert(a.create(),e);if(!t)throw Error(`Encountered non-invertible quaternion`);return t},Gt=e=>{let t=Wt(a.normalize(a.create(),L(e.lastSensorRot))),n=a.normalize(a.create(),L(e.lastValidOdomRot)),r=a.multiply(a.create(),t,n),i=a.normalize(a.create(),L(e.newSensorRot)),o=a.multiply(a.create(),i,r),s=a.normalize(a.create(),L(e.newOdomRot)),c=a.multiply(a.create(),o,s);return a.normalize(c,c),z(c)},Kt=(e,t)=>{let n=i.create();return i.fromRotationTranslationScale(n,a.normalize(a.create(),L(t)),I(e),Bt),n},qt=(e,t,n)=>{let r=o.create(),s=o.create(),c=a.create(),l=a.create();i.getTranslation(r,e),i.getTranslation(s,t),i.getRotation(c,e),i.getRotation(l,t);let u=o.create();o.lerp(u,r,s,n);let d=a.create();return a.slerp(d,c,l,n),i.fromRotationTranslation(i.create(),d,u)},Jt=(e,t)=>{if(e.length===0)return[];let n=e[e.length-1],r=i.invert(i.create(),n);if(!r)throw Error(`End pose matrix is not invertible`);let a=i.multiply(i.create(),t,r),o=i.create(),s=e.length-1;return e.map((e,t)=>{let n=qt(o,a,s<=0?1:t/s);return i.multiply(i.create(),n,e)})},Yt=(e,t,n)=>{for(let r=e.length-1;r>=0;--r)if(n(e[r],t))return r;return-1},Xt=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2],Zt=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]&&e[3]===t[3],Qt=t({name:`gpsData`,initialState:null,reducers:{setZeroPos:{reducer:(e,t)=>e===null?{zero:t.payload,gpsEvents:pt(),odometryPath:fe()}:e,prepare:e=>(zt(e),{payload:e})},recordGpsEvent:(e,t)=>{if(!e)return e;let{odomPosition:n,odomRotation:r,rawGpsPoint:i,rawDeviceOrientation:a,rawAbsoluteOrientation:o}=t.payload,s=Ht(i,e.zero,a,o);yt(e.gpsEvents,W(n),G(r),s)},odometryTrackingRestarted:(e,t)=>{if(!e)return e;let n=Vt(e.gpsEvents.odometryPosOffset,W(t.payload.lastValidOdomPos)),r=Ut(t.payload.lastSensorOrientation,t.payload.lastSensorRot,`lastSensor`),i=Ut(t.payload.newSensorOrientation,t.payload.newSensorRot,`newSensor`);e.gpsEvents=c(_t({odometryPositions:[],odometryRotations:[],gpsPoints:[],odometryPosOffset:n,odometryRotOffset:Gt({...t.payload,lastValidOdomRot:G(t.payload.lastValidOdomRot),newOdomRot:G(t.payload.newOdomRot),lastSensorRot:K(r),newSensorRot:K(i)}),latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null}))},arLoopClosureDetected:(e,t)=>{if(!e)return e;let n=e.gpsEvents;if(n.odometryPositions.length===0)return e;let r=n.latestLoopClosureFixPointPos?Yt(n.odometryPositions,n.latestLoopClosureFixPointPos,Xt):0,s=n.latestLoopClosureFixPointRot?Yt(n.odometryRotations,n.latestLoopClosureFixPointRot,Zt):0;if(r<0||s<0)throw Error(`Loop closure fix point could not be located in history`);if(r!==s)throw Error(`Loop closure fix point indices for position and rotation diverged`);let l=n.odometryPositions.slice(0,r).map(e=>B(e)),u=n.odometryRotations.slice(0,r).map(e=>U(e)),d=n.odometryPositions.slice(r).map(e=>B(e)),f=n.odometryRotations.slice(r).map(e=>U(e)),p=d.map((e,t)=>Kt(e,f[t])),m=Kt(W(t.payload.lastPos),U(G(t.payload.lastRot)));p.push(m);let h=Jt(p,Kt(W(t.payload.newPos),U(G(t.payload.newRot)))),g=[],_=[],v=o.create();for(let e=0;e<h.length-1;e+=1){let t=h[e],n=o.create();i.getTranslation(n,t);let r=a.create();if(i.getRotation(r,t),a.normalize(r,r),i.getScaling(v,t),Math.hypot(v[0]-1,v[1]-1,v[2]-1)>.05)throw Error(`Unexpected scale drift encountered during loop closure correction`);g.push(R(n)),_.push(z(r))}e.gpsEvents=c(_t({odometryPositions:l.concat(g),odometryRotations:u.concat(_),gpsPoints:n.gpsPositions,odometryPosOffset:n.odometryPosOffset,odometryRotOffset:n.odometryRotOffset,latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null}))},add2dImage:(e,t)=>{if(!e)return e;e.odometryPath.points.push(c({imageFile:t.payload.imageFile,screenRotation:t.payload.screenRotation,position:W(t.payload.position),rotation:U(G(t.payload.rotation)),capturedAt:t.payload.capturedAt,width:t.payload.width,height:t.payload.height}))}}}),{setZeroPos:$t,recordGpsEvent:en,odometryTrackingRestarted:tn,arLoopClosureDetected:nn,add2dImage:rn}=Qt.actions,an=p($t),on=p(en),sn=p(tn),cn=p(nn),ln=p(rn),un=m(Qt.reducer),dn=t({name:`gpsElements`,initialState:pe(),reducers:{addMarker:(e,t)=>{e.gpsMarkers.push(t.payload)},addLine:(e,t)=>{e.gpsLines.push(t.payload)},addArea:(e,t)=>{e.areas.push(t.payload)},addToHeatMaps:(e,t)=>{let{category:n,tiles:r}=t.payload,i=e.heatMap[n]??{};e.heatMap[n]={...i,...r}},addHeatMapArea:(e,t)=>{let n=t.payload,r=n.category;if(e.heatAreas[r]||(e.heatAreas[r]={}),e.heatAreas[r][n.geoHash])throw Error(`HeatArea collision detected for GeoHash: ${n.geoHash}`);e.heatAreas[r][n.geoHash]=n},resetGpsElements:()=>pe()}}),{addMarker:fn,addLine:pn,addArea:mn,addToHeatMaps:hn,addHeatMapArea:gn,resetGpsElements:_n}=dn.actions,vn=p(fn),yn=p(pn),bn=p(mn),xn=p(hn),Sn=p(gn),Cn=p(_n),wn=m(dn.reducer),Tn=()=>({gpsData:null,gpsElements:pe(),arElements:me()}),En=e=>{let t=Array.from({length:Math.min(e.length,4)},(t,n)=>e[n].toFixed(2));e.length>4&&t.push(`…`);let n=`[${t.join(`, `)}]`;if(e.length===4){let{pitch:t,yaw:r,roll:i}=v(e);return`${n} (pitch=${t.toFixed(0)}°, yaw=${r.toFixed(0)}°, roll=${i.toFixed(0)}°)`}return n},Dn=e=>(e.length===3||e.length===4||e.length===16)&&e.every(e=>typeof e==`number`),Q=(e,t=0)=>{if(t>10||e==null)return e;if(Array.isArray(e))return Dn(e)?En(e):e.map(e=>Q(e,t+1));if(typeof e==`object`){let n={};for(let[r,i]of Object.entries(e))n[r]=Q(i,t+1);return n}return e},On=(t={})=>{let{preloadedState:n,enableDevToolsSanitizers:r=!0,enableDevChecks:i=!0,licenseKey:a}=t;if(a==null)throw Error(`License key required. Pass options.licenseKey or use createRecorderStore() from gps-plus-slam-app-framework. See EULA §3.`);g(a);let o=Tn(),s=n?{gpsData:n.gpsData??o.gpsData,gpsElements:n.gpsElements??o.gpsElements,arElements:n.arElements??o.arElements}:void 0;return e({reducer:{gpsData:un,gpsElements:wn,arElements:Je},preloadedState:s,middleware:e=>e({serializableCheck:i,immutableCheck:i}),devTools:r?{actionSanitizer:Q,stateSanitizer:Q}:!0})},kn=Math.PI/180,An=180/Math.PI,jn=2025,Mn=2025,Nn=2030,Pn=6378137;Pn*(1-1/298.257223563);const Fn=[[1,0,-29351.8,0,12,0],[1,1,-1410.8,4545.4,9.7,-21.5],[2,0,-2556.6,0,-11.6,0],[2,1,2951.1,-3133.6,-5.2,-27.7],[2,2,1649.3,-815.1,-8,-12.1],[3,0,1361,0,-1.3,0],[3,1,-2404.1,-56.6,-4.2,4],[3,2,1243.8,237.5,.4,-.3],[3,3,453.6,-549.5,-15.6,-4.1],[4,0,895,0,-1.6,0],[4,1,799.5,278.6,-2.4,-1.1],[4,2,55.7,-133.9,-6,4.1],[4,3,-281.1,212,5.6,1.6],[4,4,12.1,-375.6,-7,-4.4],[5,0,-233.2,0,.6,0],[5,1,368.9,45.4,1.4,-.5],[5,2,187.2,220.2,0,2.2],[5,3,-138.7,-122.9,.6,.4],[5,4,-142,43,2.2,1.7],[5,5,20.9,106.1,.9,1.9],[6,0,64.4,0,-.2,0],[6,1,63.8,-18.4,-.4,.3],[6,2,76.9,16.8,.9,-1.6],[6,3,-115.7,48.8,1.2,-.4],[6,4,-40.9,-59.8,-.9,.9],[6,5,14.9,10.9,.3,.7],[6,6,-60.7,72.7,.9,.9],[7,0,79.5,0,-0,0],[7,1,-77,-48.9,-.1,.6],[7,2,-8.8,-14.4,-.1,.5],[7,3,59.3,-1,.5,-.8],[7,4,15.8,23.4,-.1,0],[7,5,2.5,-7.4,-.8,-1],[7,6,-11.1,-25.1,-.8,.6],[7,7,14.2,-2.3,.8,-.2],[8,0,23.2,0,-.1,0],[8,1,10.8,7.1,.2,-.2],[8,2,-17.5,-12.6,0,.5],[8,3,2,11.4,.5,-.4],[8,4,-21.7,-9.7,-.1,.4],[8,5,16.9,12.7,.3,-.5],[8,6,15,.7,.2,-.6],[8,7,-16.8,-5.2,-0,.3],[8,8,.9,3.9,.2,.2],[9,0,4.6,0,-0,0],[9,1,7.8,-24.8,-.1,-.3],[9,2,3,12.2,.1,.3],[9,3,-.2,8.3,.3,-.3],[9,4,-2.5,-3.3,-.3,.3],[9,5,-13.1,-5.2,0,.2],[9,6,2.4,7.2,.3,-.1],[9,7,8.6,-.6,-.1,-.2],[9,8,-8.7,.8,.1,.4],[9,9,-12.9,10,-.1,.1],[10,0,-1.3,0,.1,0],[10,1,-6.4,3.3,0,0],[10,2,.2,0,.1,-0],[10,3,2,2.4,.1,-.2],[10,4,-1,5.3,-0,.1],[10,5,-.6,-9.1,-.3,-.1],[10,6,-.9,.4,0,.1],[10,7,1.5,-4.2,-.1,0],[10,8,.9,-3.8,-.1,-.1],[10,9,-2.7,.9,-0,.2],[10,10,-3.9,-9.1,-0,-0],[11,0,2.9,0,0,0],[11,1,-1.5,0,-0,-0],[11,2,-2.5,2.9,0,.1],[11,3,2.4,-.6,0,-0],[11,4,-.6,.2,0,.1],[11,5,-.1,.5,-.1,-0],[11,6,-.6,-.3,0,-0],[11,7,-.1,-1.2,-0,.1],[11,8,1.1,-1.7,-.1,-0],[11,9,-1,-2.9,-.1,0],[11,10,-.2,-1.8,-.1,0],[11,11,2.6,-2.3,-.1,0],[12,0,-2,0,0,0],[12,1,-.2,-1.3,0,-0],[12,2,.3,.7,-0,0],[12,3,1.2,1,-0,-.1],[12,4,-1.3,-1.4,-0,.1],[12,5,.6,-0,-0,-0],[12,6,.6,.6,.1,-0],[12,7,.5,-.1,-0,-0],[12,8,-.1,.8,0,0],[12,9,-.4,.1,0,-0],[12,10,-.2,-1,-.1,-0],[12,11,-1.3,.1,-0,0],[12,12,-.7,.2,-.1,-.1]];function In(){let e=()=>Array.from({length:13},()=>Array(13).fill(0)),t={g:e(),h:e(),gdot:e(),hdot:e()};for(let[e,n,r,i,a,o]of Fn)t.g[e][n]=r,t.h[e][n]=i,t.gdot[e][n]=a,t.hdot[e][n]=o;return t}const $=In();function Ln(){let e=Array(169).fill(0),t=Array(169).fill(0),n=Array(13).fill(0),r=Array(13).fill(0),i=Array(169).fill(0),a=Array(169).fill(0),o=(e,t)=>e*13+t;for(let e=1;e<=12;e++)for(let t=0;t<=e;t++){let n=$.g[e][t],r=$.h[e][t],s=$.gdot[e][t],c=$.hdot[e][t];i[o(t,e)]=n,a[o(t,e)]=s,t!==0&&(i[o(e,t-1)]=r,a[o(e,t-1)]=c)}e[o(0,0)]=1;for(let s=1;s<=12;s++){e[o(0,s)]=e[o(0,s-1)]*(2*s-1)/s;let c=2;for(let n=0,r=(s-n+1)/1;r>0;r--,n+=1){if(t[o(n,s)]=((s-1)*(s-1)-n*n)/((2*s-1)*(2*s-3)),n>0){let t=(s-n+1)*c/(s+n);e[o(n,s)]=e[o(n-1,s)]*Math.sqrt(t),c=1,i[o(s,n-1)]=e[o(n,s)]*i[o(s,n-1)],a[o(s,n-1)]=e[o(n,s)]*a[o(s,n-1)]}i[o(n,s)]=e[o(n,s)]*i[o(n,s)],a[o(n,s)]=e[o(n,s)]*a[o(n,s)]}n[s]=s+1,r[s]=s}return t[o(1,1)]=0,r[0]=0,{snorm:e,k:t,fn:n,fm:r,c:i,cd:a,idx:o}}const Rn=Ln();function zn(e){return e%4==0&&e%100!=0||e%400==0?366:365}function Bn(e){let t=e.getUTCFullYear(),n=Date.UTC(t,0,1);return t+Math.floor((e.getTime()-n)/864e5)/zn(t)}let Vn=!1;function Hn(e){return e===void 0?2027.5:typeof e==`number`?e>1e4?Bn(new Date(e)):e:Bn(e)}function Un(e,t,n){let r=Pn/1e3,i=6356752.314245179/1e3,a=r*r,o=i*i,s=a-o,c=a*a;c-o*o;let l=t*t,u=n*n,d=Math.sqrt(a-s*l),f=e*d,p=(f+a)/(f+o)*((f+a)/(f+o)),m=t/Math.sqrt(p*u+l),h=Math.sqrt(1-m*m),g=Math.sqrt(e*e+2*f+(c-22083078973482.75*l)/(d*d)),_=Math.sqrt(a*u+o*l);return{r:g,ct:m,st:h,ca:(e+_)/g,sa:s/_*t*n/g}}function Wn(e,t,n,r,i,a,o,s){if(i===a){e[r(a,i)]=o*e[r(a-1,i-1)],t[r(a,i)]=o*t[r(a-1,i-1)]+s*e[r(a-1,i-1)];return}if(i===1&&a===0){e[r(a,i)]=s*e[r(a,i-1)],t[r(a,i)]=s*t[r(a,i-1)]-o*e[r(a,i-1)];return}a>i-2&&(e[r(a,i-2)]=0,t[r(a,i-2)]=0),e[r(a,i)]=s*e[r(a,i-1)]-n[r(a,i)]*e[r(a,i-2)],t[r(a,i)]=s*t[r(a,i-1)]-o*e[r(a,i-1)]-n[r(a,i)]*t[r(a,i-2)]}function Gn(e,t,n,r){let i=r-jn;(r<2025||r>=2030)&&!Vn&&(Vn=!0,console.warn(`magneticDeclinationDeg: date ${r.toFixed(3)} is outside the WMM2025 validity window [${Mn}, ${Nn}); using linear secular extrapolation (accuracy degrades).`));let{snorm:a,k:o,fn:s,fm:c,c:l,cd:u,idx:d}=Rn,f=t*kn,p=e*kn,m=Math.sin(f),h=Math.sin(p),g=Math.cos(f),_=Math.cos(p),v=Array(13).fill(0),y=Array(13).fill(0);v[0]=0,y[0]=1,v[1]=m,y[1]=g;let{r:b,ct:x,st:S,ca:C,sa:w}=Un(n,h,_);for(let e=2;e<=12;e++)v[e]=m*y[e-1]+g*v[e-1],y[e]=g*y[e-1]-m*v[e-1];let T=6371.2/b,E=T*T,D=0,O=0,k=0,A=a.slice(),j=Array(169).fill(0);for(let e=1;e<=12;e++){E*=T;for(let t=0,n=(e+t+1)/1;n>0;n--,t+=1){Wn(A,j,o,d,e,t,S,x);let n=l[d(t,e)]+i*u[d(t,e)],r=E*A[d(t,e)],a,f;if(t===0)a=n*y[t],f=n*v[t];else{let r=l[d(e,t-1)]+i*u[d(e,t-1)];a=n*y[t]+r*v[t],f=n*v[t]-r*y[t]}D-=E*a*j[d(t,e)],O+=c[t]*f*r,k+=s[e]*a*r}}let M;return M=S===0?0:O/S,{x:-D*C-k*w,y:M,z:D*w-k*C}}function Kn(e){let t=e%360;return t<0?t+360:t}function qn(e,t,n){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;let r=n?.altitudeKm??0;if(!Number.isFinite(r))return NaN;let{x:i,y:a}=Gn(e,t,r,Hn(n?.date));return Math.atan2(a,i)*An}function Jn(e,t,n,r){return Kn(e+qn(t,n,r))}const Yn=.08,Xn=180/Math.PI,Zn=e=>(e%360+360)%360,Qn=(e,t)=>{let[n,r,i,a]=e,[o,s,c]=t,l=2*(r*c-i*s),u=2*(i*o-n*c),d=2*(n*s-r*o);return[o+a*l+(r*d-i*u),s+a*u+(i*l-n*d),c+a*d+(n*u-r*l)]};function $n(e){let[t,n,r,i]=e,a=-2*(t*r+i*n),o=-2*(n*r-i*t);return Math.hypot(a,o)<Yn?null:Zn(Math.atan2(a,o)*Xn)}const er=[0,0,-1];function tr(e,t){return Te(e,Ee(t))}function nr(e,t){let[n,r]=Qn(tr(e,t),er);return Math.hypot(n,r)<Yn?null:Zn(Math.atan2(n,r)*Xn)}function rr(e,t){let n=((e-t+180)%360+360)%360-180;return n===-180&&(n=180),n}const ir=[],ar=[],or=[],sr={median:null,mean:null},cr=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentMatrix}),lr=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentRotation}),ur=f(function(e){return e.gpsData?.gpsEvents?.odometryPositions??ir}),dr=f(function(e){return e.gpsData?.gpsEvents?.odometryRotations??ar}),fr=f(function(e){return e.gpsData?.gpsEvents?.gpsPositions??or}),pr=f(function(e){return e.gpsData?.zero??null}),mr=f(function(e){let t=e.gpsData?.gpsEvents?.gpsAccuracyMedian??null,n=e.gpsData?.gpsEvents?.gpsAccuracyMean??null;return t===null&&n===null?sr:{median:t,mean:n}}),hr=`1.0.0`;export{ye as IDENTITY_MATRIX4,V as IDENTITY_QUATERNION,hr as LIB_VERSION,jn as WMM2025_EPOCH,Mn as WMM2025_VALID_FROM,Nn as WMM2025_VALID_TO,H as ZERO_VECTOR3,ln as add2dImage,bn as addArea,Ue as addCornerToEventArea,Sn as addHeatMapArea,yn as addLine,vn as addMarker,Ve as addOrUpdateArPlane,xn as addToHeatMaps,Ke as anchorEventAreaInWorldSpace,Je as arElementsReducer,cn as arLoopClosureDetected,nr as arNorthBearingDeg,tr as arToEnuRotation,rr as bearingDeltaDeg,re as calcGeoHash,P as calcGpsCoords,te as calcQuadKey,N as calcRelativeCoordsInMeters,ve as cloneMatrix4,_e as cloneQuaternion,B as cloneVector3,We as correctArDriftForEventArea,On as createGpsSlamStore,ae as distanceInMeters,oe as distanceInMetersRelative,K as enuQuaternionToNUE,Ae as eulerToQuaternion,Ge as finishEventArea,he as fromMatrix4,L as fromQuaternion,I as fromVector3,de as fusedGpsFromOdom,ie as geoHashToLatLong,cr as getAlignmentMatrix,lr as getAlignmentRotation,le as getGoogleMapsDirectionsLink,ce as getGoogleMapsLink,mr as getGpsAccuracyStats,fr as getGpsPositions,ur as getOdometryPositions,dr as getOdometryRotations,ue as getOpenStreetMapLink,pr as getZeroReference,un as gpsDataReducer,wn as gpsElementsReducer,Ee as invertQuaternion,be as isIdentityMatrix4,Se as isIdentityQuaternion,Ce as isNearIdentityQuaternion,qn as magneticDeclinationDeg,$n as magneticHeadingFromEnuQuat,Jn as magneticToTrueHeadingDeg,Te as multiplyQuaternions,U as normalizeQuaternion,ke as nueQuaternionToENU,Oe as nueQuaternionToWebXR,De as nueToWebXR,sn as odometryTrackingRestarted,ne as quadKeyToLatLong,xe as quaternionMagnitude,we as quaternionsEquivalent,on as recordGpsEvent,Be as recordPhoneHeight,qe as resetArElements,Cn as resetGpsElements,Q as sanitizeForDevTools,an as setZeroPos,He as startEventArea,se as toEarthCenteredCoordinates,ge as toMatrix4,z as toQuaternion,R as toVector3,g as validateLicenseKey,G as webxrQuaternionToNUE,W as webxrToNUE};
2
+ import{configureStore as e,createSlice as t}from"@reduxjs/toolkit";import{ed25519 as n}from"@noble/curves/ed25519.js";import{hexToBytes as r}from"@noble/curves/utils.js";import{mat4 as i,quat as a,vec3 as o,vec4 as s}from"gl-matrix";import{castDraft as c}from"immer";let l=!1;function u(){l=!0}function d(){if(!l)throw Error(`gps-plus-slam-js: license not activated. Construct your store via createRecorderStore() from gps-plus-slam-app-framework, or pass a valid licenseKey to createGpsSlamStore(). See EULA §3.`)}function f(e){return((...t)=>(d(),e(...t)))}function p(e){let t=((...t)=>(d(),e(...t)));return Object.assign(t,e),t.toString=()=>e.type,t}function m(e){return(t,n)=>(d(),e(t,n))}function h(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`),n=`=`.repeat((4-t.length%4)%4),r=atob(t+n);return Uint8Array.from(r,e=>e.charCodeAt(0))}function g(e){let t=new Date,i=e.indexOf(`.`);if(i<=0||i>=e.length-1)throw Error(`Invalid license key format: expected "payload.signature" with base64url-encoded parts.`);let a,o;try{a=h(e.substring(0,i)),o=h(e.substring(i+1))}catch{throw Error(`Invalid license key format: base64url decoding failed.`)}let s=r(`dfe5c62120b7a0ce962b17907a15b27cf1b056e6619bf6ce55e6e094b322a470`);if(!n.verify(o,a,s))throw Error(`Invalid license key: signature verification failed.`);let c=JSON.parse(new TextDecoder().decode(a));if(typeof c!=`object`||!c)throw Error(`Invalid license key: payload must be a JSON object.`);let{type:l,exp:d}=c;if(l!==`community`)throw Error(`Invalid license key: "type" must be "community".`);if(typeof d!=`number`||!Number.isFinite(d))throw Error(`Invalid license key: "exp" must be a finite number (Unix timestamp in seconds).`);if(d<Math.floor(t.getTime()/1e3)){let e=new Date(d*1e3);throw Error(`License key expired on ${e.toISOString()}. Update to the latest version for a renewed community key.`)}return u(),{type:l,expiresAt:new Date(d*1e3)}}const _=180/Math.PI,v=e=>{let t=e[0],n=e[1],r=e[2],i=e[3],a=2*(i*t+n*r),o=1-2*(t*t+n*n),s=Math.atan2(a,o)*_,c=2*(i*n-r*t),l=Math.abs(c)>=1?Math.sign(c)*90:Math.asin(c)*_,u=2*(i*r+t*n),d=1-2*(n*n+r*r);return{pitch:l,yaw:Math.atan2(u,d)*_,roll:s}},y=1/298.257223563,b=y*(2-y),x=40075016.6856/360,S=39940652.7422/360,C=Math.PI/180,w=180/Math.PI,T=`0123456789bcdefghjkmnpqrstuvwxyz`,E=[16,8,4,2,1],D=(e,t,n)=>Math.min(Math.max(e,t),n),ee=e=>D(e,-180,180),O=e=>e*C,k=e=>e*w,A=e=>{if(!Number.isFinite(e))throw RangeError(`Coordinate values must be finite numbers`);return String(e)},j=e=>({lat:A(e.lat),lon:A(e.lon)}),te=(e,t=0)=>{let n=O(e.lat),r=O(e.lon),i=Math.sin(n),a=Math.cos(n),s=Math.sin(r),c=Math.cos(r),l=6378137/Math.sqrt(1-b*i*i),u=(l+t)*a*c,d=(l+t)*a*s,f=(l*(1-b)+t)*i;return o.fromValues(u,d,f)},ne=f((e,t)=>{if(t<1||t>23)throw RangeError(`levelOfDetail must be between 1 and 23 (inclusive)`);let n=D(e.lat,-85.05112878,85.05112878),r=ee(e.lon),i=Math.sin(O(n)),a=256*2**t,o=(r+180)/360*a,s=(.5-Math.log((1+i)/(1-i))/(4*Math.PI))*a,c=2**t-1,l=D(Math.floor(o/256),0,c),u=D(Math.floor(s/256),0,c),d=``;for(let e=t;e>0;--e){let t=0,n=1<<e-1;(l&n)!==0&&(t+=1),(u&n)!==0&&(t+=2),d+=t.toString()}return d}),re=f(e=>{if(!/^[0-3]+$/.test(e))throw Error(`QuadKey must consist of digits 0-3`);let t=e.length;if(t===0)throw Error(`QuadKey must not be empty`);let n=0,r=0;for(let i=0;i<t;i+=1){let a=Number.parseInt(e[i],10),o=1<<t-i-1;a&1&&(n+=o),a&2&&(r+=o)}let i=256*2**t,a=(n+.5)*256,o=(r+.5)*256,s=a/i,c=o/i,l=s*360-180;return{lat:k(Math.atan(Math.sinh(Math.PI*(1-2*c)))),lon:l}}),ie=f((e,t)=>{if(t<=0)throw RangeError(`precision must be greater than 0`);let n=-90,r=90,i=-180,a=180,o=``,s=0,c=0,l=!0;for(;o.length<t;){if(l){let t=(i+a)/2;e.lon>=t?(c|=E[s],i=t):a=t}else{let t=(n+r)/2;e.lat>=t?(c|=E[s],n=t):r=t}l=!l,s<4?s+=1:(o+=T[c],s=0,c=0)}return o}),ae=f(e=>{if(e.length===0)throw Error(`geoHash must not be empty`);let t=-90,n=90,r=-180,i=180,a=!0;for(let o of e){let e=T.indexOf(o);if(e===-1)throw Error(`Invalid geohash character: ${o}`);for(let o of E){if(a){let t=(r+i)/2;(e&o)===0?i=t:r=t}else{let r=(t+n)/2;(e&o)===0?n=r:t=r}a=!a}}return{lat:(t+n)/2,lon:(r+i)/2}}),oe=f((e,t)=>{let n=O(e.lat),r=O(t.lat),i=r-n,a=O(t.lon-e.lon),o=Math.sin(i/2),s=Math.sin(a/2),c=o*o+Math.cos(n)*Math.cos(r)*s*s,l=Math.min(1,Math.max(0,c));return 6371008.8*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}),se=f((e,t)=>{let n=ce(e,t);return Math.hypot(n[0],n[2])}),ce=f((e,t,n=0,r=0)=>{let i=(t.lon-e.lon)*x*Math.cos(O(e.lat)),a=(t.lat-e.lat)*S,s=n-r;return o.fromValues(a,s,i)}),le=f((e,t)=>{let n=t[0],r=t[2];return{lat:n/S+e.lat,lon:r/(x*Math.cos(O(e.lat)))+e.lon}}),ue=f((e,t=0)=>te(e,t)),de=e=>{let{lat:t,lon:n}=j(e);return`${t}%2C${n}`},fe=f(e=>`https://www.google.com/maps/search/?api=1&query=${de(e)}`),pe=f((e,t)=>`https://www.google.com/maps/dir/?api=1&origin=${de(t)}&destination=${de(e)}`),me=f((e,t=19)=>{let{lat:n,lon:r}=j(e);return`https://www.openstreetmap.org/query?lat=${n}&lon=${r}#map=${t}/${n}/${r}`}),he=f((e,t,n)=>{let r=i.fromValues(...e),a=o.fromValues(t[0],t[1],t[2]),s=o.create();o.transformMat4(s,a,r);let{lat:c,lon:l}=le(n,s);return{lat:c,lon:l,altitude:s[1]}}),ge=()=>({points:[]}),_e=()=>({gpsMarkers:[],gpsLines:[],areas:[],heatMap:{},heatAreas:{}}),ve=()=>({arPlanes:{},floorDetections:[],eventAreas:[],currentEventAreaId:null,currentEventAreaPoints:[]}),M=e=>o.fromValues(e[0],e[1],e[2]),N=e=>a.fromValues(e[0],e[1],e[2],e[3]),ye=e=>i.fromValues(...e),P=e=>[e[0],e[1],e[2]],F=e=>[e[0],e[1],e[2],e[3]],I=e=>[e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9],e[10],e[11],e[12],e[13],e[14],e[15]],L=e=>[e[0],e[1],e[2]],be=e=>[e[0],e[1],e[2],e[3]],xe=e=>[...e],R=Object.freeze([0,0,0,1]),z=Object.freeze([0,0,0]),Se=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),B=e=>{let t=we(e);if(t===0)return R;let n=1/t;return[e[0]*n,e[1]*n,e[2]*n,e[3]*n]},Ce=e=>{for(let t=0;t<16;t++)if(e[t]!==Se[t])return!1;return!0},we=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]+e[3]*e[3]),Te=e=>e[0]===0&&e[1]===0&&e[2]===0&&e[3]===1,Ee=(e,t)=>Math.abs(e[0])<t&&Math.abs(e[1])<t&&Math.abs(e[2])<t&&Math.abs(e[3]-1)<t,De=(e,t,n=1e-10)=>{let r=Math.abs(e[0]-t[0])<n&&Math.abs(e[1]-t[1])<n&&Math.abs(e[2]-t[2])<n&&Math.abs(e[3]-t[3])<n,i=Math.abs(e[0]+t[0])<n&&Math.abs(e[1]+t[1])<n&&Math.abs(e[2]+t[2])<n&&Math.abs(e[3]+t[3])<n;return r||i},Oe=(e,t)=>{let n=a.create();return a.multiply(n,e,t),[n[0],n[1],n[2],n[3]]},ke=e=>{let t=a.create();return a.invert(t,e),[t[0],t[1],t[2],t[3]]},V=e=>[-e[2],e[1],e[0]],Ae=e=>[e[2],e[1],-e[0]],H=e=>[-e[2],e[1],e[0],e[3]],je=e=>[e[2],e[1],-e[0],e[3]],U=e=>[e[1],e[2],e[0],e[3]],Me=e=>[e[2],e[0],e[1],e[3]],Ne=(e,t,n)=>{if(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(n))throw Error(`eulerToQuaternion: non-finite input (alpha=${e}, beta=${t}, gamma=${n})`);let r=e*Math.PI/180,i=t*Math.PI/180,o=n*Math.PI/180,s=a.create(),c=a.create(),l=a.create();a.setAxisAngle(s,[0,0,1],r),a.setAxisAngle(c,[1,0,0],i),a.setAxisAngle(l,[0,1,0],o);let u=a.create();return a.multiply(u,s,c),a.multiply(u,u,l),[u[0],u[1],u[2],u[3]]},Pe=t({name:`arElements`,initialState:ve(),reducers:{recordPhoneHeight:(e,t)=>{e.floorDetections.push(t.payload)},addOrUpdateArPlane:(e,t)=>{let n=t.payload;if(n.parentPlaneId){delete e.arPlanes[n.planeId];return}e.arPlanes[n.planeId]=c(n)},startEventArea:(e,t)=>{e.currentEventAreaId=t.payload.id,e.currentEventAreaPoints=[]},addCornerToEventArea:(e,t)=>{e.currentEventAreaId&&e.currentEventAreaPoints.push(c(L(t.payload.position)))},correctArDriftForEventArea:(e,t)=>{let n=t.payload.drift;for(let t of e.currentEventAreaPoints)t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]},finishEventArea:(e,t)=>{e.currentEventAreaId&&(e.eventAreas.push({id:e.currentEventAreaId,label:t.payload.label,polygon:[],isInArSpace:!0,arPoints:e.currentEventAreaPoints}),e.currentEventAreaId=null,e.currentEventAreaPoints=[])},anchorEventAreaInWorldSpace:(e,t)=>{let{areaId:n,alignmentMatrix:r,zeroRef:i}=t.payload,a=e.eventAreas.findIndex(e=>e.id===n);if(a===-1)return;let s=e.eventAreas[a];if(!s.isInArSpace||!s.arPoints)throw Error(`The area ${s.id} is already anchored in world space`);let c=ye(r),l=s.arPoints.map(e=>{let t=M(e);return le(i,o.transformMat4(o.create(),t,c))});e.eventAreas[a]={...s,isInArSpace:!1,polygon:l,arPoints:void 0}},resetArElements:()=>ve()}}),{recordPhoneHeight:Fe,addOrUpdateArPlane:Ie,startEventArea:Le,addCornerToEventArea:Re,correctArDriftForEventArea:ze,finishEventArea:Be,anchorEventAreaInWorldSpace:Ve,resetArElements:He}=Pe.actions,Ue=p(Fe),We=p(Ie),Ge=p(Le),Ke=p(Re),qe=p(ze),Je=p(Be),Ye=p(Ve),Xe=p(He),Ze=m(Pe.reducer);function Qe(e,t,n,r){let{inCentroid:i,refCentroid:a,refVec:s,tmp:c}=r;o.set(i,0,0,0),o.set(a,0,0,0);let l=0;for(let n=0;n<e.length;n++){let r=t[n][3];o.scaleAndAdd(i,i,e[n],r),nt(s,t[n]),o.scaleAndAdd(a,a,s,r),l+=r}if(l===0)throw Error(`Weights must not sum to zero when solving Kabsch`);let u=1/l;if(o.scale(i,i,u),o.scale(a,a,u),!n)return{inCentroid:i,refCentroid:a,scaleRatio:1};let d=0,f=0;for(let n=0;n<e.length;n++)o.subtract(c,e[n],i),d+=o.length(c),nt(s,t[n]),o.subtract(c,s,a),f+=o.length(c);return{inCentroid:i,refCentroid:a,scaleRatio:d===0?1:f/d}}function $e(e,t,n,r,a,s,c){let{negCentroid:l,scaleVec:u}=c;return i.fromRotationTranslation(e,r,n),s&&(o.set(u,a,a,a),i.scale(e,e,u)),o.negate(l,t),i.translate(e,e,l),e}function et(e,t,n={}){let r=e.length;if(r!==t.length)throw Error(`Length of the point lists was not equal: ${r} vs ${t.length}`);if(r===0)return i.create();let s=n.solveRotation??!0,c=n.solveScale??!1,l=n.ignoreYAxisForRotation??!1,u=n.rotationIterations??9,{inCentroid:d,refCentroid:f,scaleRatio:p}=Qe(e,t,c,{inCentroid:o.create(),refCentroid:o.create(),refVec:o.create(),tmp:o.create()}),m=a.create();s?new tt(l).solve(e,t,d,f,m,u):a.identity(m);let h={negCentroid:o.create(),scaleVec:o.create()};return $e(i.create(),d,f,m,p,c,h)}var tt=class e{ignoreYAxis;static twoPi=Math.PI*2;static basisX=o.fromValues(1,0,0);static basisY=o.fromValues(0,1,0);static basisZ=o.fromValues(0,0,1);constructor(e){this.ignoreYAxis=e}solve(t,n,r,i,o,s){let c=this.transposeMultSubtract(t,n,r,i);if(this.ignoreYAxis){let t=c[0][0],n=c[0][2],r=c[2][0],i=c[2][2],s=Math.atan2(r-n,t+i);a.setAxisAngle(o,e.basisY,s)}else this.extractRotation(c,o,s)}transposeMultSubtract(e,t,n,r){let i=[o.create(),o.create(),o.create()],a=o.clone(n),s=o.clone(r);this.ignoreYAxis&&(a[1]=0,s[1]=0);let c=o.create(),l=o.create(),u=o.create();for(let n=0;n<e.length;n++){o.copy(c,e[n]),nt(u,t[n]),this.ignoreYAxis&&(c[1]=0,u[1]=0);let r=t[n][3];o.subtract(c,c,a),o.scale(c,c,r),o.subtract(l,u,s),i[0][0]+=c[0]*l[0],i[1][0]+=c[1]*l[0],i[2][0]+=c[2]*l[0],i[0][1]+=c[0]*l[1],i[1][1]+=c[1]*l[1],i[2][1]+=c[2]*l[1],i[0][2]+=c[0]*l[2],i[1][2]+=c[1]*l[2],i[2][2]+=c[2]*l[2]}return i}extractRotation(t,n,r){let i=[o.create(),o.create(),o.create()],s=o.create(),c=o.create(),l=o.create();for(let u=0;u<r;u++){this.fillMatrixFromQuaternion(n,i),o.cross(s,i[0],t[0]),o.cross(l,i[1],t[1]),o.add(s,s,l),o.cross(l,i[2],t[2]),o.add(s,s,l);let r=o.dot(i[0],t[0])+o.dot(i[1],t[1])+o.dot(i[2],t[2])+1e-9;r=Math.abs(r),o.scale(s,s,1/r);let u=o.length(s);if(u<1e-9)break;o.scale(c,s,1/u);let d=u%e.twoPi,f=a.create();a.setAxisAngle(f,c,d),a.multiply(n,f,n),a.normalize(n,n)}}fillMatrixFromQuaternion(t,n){o.transformQuat(n[0],e.basisX,t),o.transformQuat(n[1],e.basisY,t),o.transformQuat(n[2],e.basisZ,t)}};const nt=(e,t)=>(e[0]=t[0],e[1]=t[1],e[2]=t[2],e);function rt(e,t,n,r,i,a,o=Math.random){let s=Array.from(e);if(n>s.length)throw RangeError(`minSampleSize must be smaller than the number of elements: minSampleSize=${n}, elements=${s.length}`);return ot(s,it(s,t,n,r,i,a,o),i,a)}function it(e,t,n,r,i,a,o){let s=null,c=Array(n),l=new Uint8Array(e.length);for(let u=0;u<r;u+=1){ct(e,n,o,c,l);let{inliers:r,outliers:u}=at(e,l,i(c),a);if(s===null||n+r.length>=t){let e=[...c,...r],t=i(e),n=st(t,`createModel must assign totalModelError for comparison during RANSAC`);(s===null||n<s.error)&&(t.inliers=e,t.outliers=u,s={model:t,error:n})}}return s?.model??null}function at(e,t,n,r){let i=[],a=[];for(let o=0;o<e.length;o+=1){if(t?.[o])continue;let s=e[o];(r(n,s)?i:a).push(s)}return{inliers:i,outliers:a}}function ot(e,t,n,r){let i=t??n(e);st(i,`RANSAC failed to produce a model with totalModelError`);let{inliers:a,outliers:o}=at(e,null,i,r);return a.length>0&&(i=n(a),st(i,`createModel must assign totalModelError for final RANSAC model`)),i.inliers=a,i.outliers=o,i}function st(e,t){let{totalModelError:n}=e;if(n==null)throw Error(t);return n}function ct(e,t,n,r,i){i.fill(0);let a=0;for(;a<t;){let t=Math.floor(n()*e.length);i[t]||(i[t]=1,r[a]=e[t],a+=1)}}const lt=.08,ut=180/Math.PI,dt=e=>(e%360+360)%360,ft=(e,t)=>{let[n,r,i,a]=e,[o,s,c]=t,l=2*(r*c-i*s),u=2*(i*o-n*c),d=2*(n*s-r*o);return[o+a*l+(r*d-i*u),s+a*u+(i*l-n*d),c+a*d+(n*u-r*l)]};function pt(e){let[t,n,r,i]=e,a=-2*(t*r+i*n),o=-2*(n*r-i*t);return Math.hypot(a,o)<lt?null:dt(Math.atan2(a,o)*ut)}const mt=[0,0,-1];function ht(e,t){return Oe(e,ke(t))}function gt(e,t){let[n,r]=ft(ht(e,t),mt);return Math.hypot(n,r)<lt?null:dt(Math.atan2(n,r)*ut)}function W(e,t){let n=((e-t+180)%360+360)%360-180;return n===-180&&(n=180),n}const _t=Math.PI/180,vt=180/Math.PI,yt=2025,bt=2025,xt=2030,St=6378137;St*(1-1/298.257223563);const Ct=[[1,0,-29351.8,0,12,0],[1,1,-1410.8,4545.4,9.7,-21.5],[2,0,-2556.6,0,-11.6,0],[2,1,2951.1,-3133.6,-5.2,-27.7],[2,2,1649.3,-815.1,-8,-12.1],[3,0,1361,0,-1.3,0],[3,1,-2404.1,-56.6,-4.2,4],[3,2,1243.8,237.5,.4,-.3],[3,3,453.6,-549.5,-15.6,-4.1],[4,0,895,0,-1.6,0],[4,1,799.5,278.6,-2.4,-1.1],[4,2,55.7,-133.9,-6,4.1],[4,3,-281.1,212,5.6,1.6],[4,4,12.1,-375.6,-7,-4.4],[5,0,-233.2,0,.6,0],[5,1,368.9,45.4,1.4,-.5],[5,2,187.2,220.2,0,2.2],[5,3,-138.7,-122.9,.6,.4],[5,4,-142,43,2.2,1.7],[5,5,20.9,106.1,.9,1.9],[6,0,64.4,0,-.2,0],[6,1,63.8,-18.4,-.4,.3],[6,2,76.9,16.8,.9,-1.6],[6,3,-115.7,48.8,1.2,-.4],[6,4,-40.9,-59.8,-.9,.9],[6,5,14.9,10.9,.3,.7],[6,6,-60.7,72.7,.9,.9],[7,0,79.5,0,-0,0],[7,1,-77,-48.9,-.1,.6],[7,2,-8.8,-14.4,-.1,.5],[7,3,59.3,-1,.5,-.8],[7,4,15.8,23.4,-.1,0],[7,5,2.5,-7.4,-.8,-1],[7,6,-11.1,-25.1,-.8,.6],[7,7,14.2,-2.3,.8,-.2],[8,0,23.2,0,-.1,0],[8,1,10.8,7.1,.2,-.2],[8,2,-17.5,-12.6,0,.5],[8,3,2,11.4,.5,-.4],[8,4,-21.7,-9.7,-.1,.4],[8,5,16.9,12.7,.3,-.5],[8,6,15,.7,.2,-.6],[8,7,-16.8,-5.2,-0,.3],[8,8,.9,3.9,.2,.2],[9,0,4.6,0,-0,0],[9,1,7.8,-24.8,-.1,-.3],[9,2,3,12.2,.1,.3],[9,3,-.2,8.3,.3,-.3],[9,4,-2.5,-3.3,-.3,.3],[9,5,-13.1,-5.2,0,.2],[9,6,2.4,7.2,.3,-.1],[9,7,8.6,-.6,-.1,-.2],[9,8,-8.7,.8,.1,.4],[9,9,-12.9,10,-.1,.1],[10,0,-1.3,0,.1,0],[10,1,-6.4,3.3,0,0],[10,2,.2,0,.1,-0],[10,3,2,2.4,.1,-.2],[10,4,-1,5.3,-0,.1],[10,5,-.6,-9.1,-.3,-.1],[10,6,-.9,.4,0,.1],[10,7,1.5,-4.2,-.1,0],[10,8,.9,-3.8,-.1,-.1],[10,9,-2.7,.9,-0,.2],[10,10,-3.9,-9.1,-0,-0],[11,0,2.9,0,0,0],[11,1,-1.5,0,-0,-0],[11,2,-2.5,2.9,0,.1],[11,3,2.4,-.6,0,-0],[11,4,-.6,.2,0,.1],[11,5,-.1,.5,-.1,-0],[11,6,-.6,-.3,0,-0],[11,7,-.1,-1.2,-0,.1],[11,8,1.1,-1.7,-.1,-0],[11,9,-1,-2.9,-.1,0],[11,10,-.2,-1.8,-.1,0],[11,11,2.6,-2.3,-.1,0],[12,0,-2,0,0,0],[12,1,-.2,-1.3,0,-0],[12,2,.3,.7,-0,0],[12,3,1.2,1,-0,-.1],[12,4,-1.3,-1.4,-0,.1],[12,5,.6,-0,-0,-0],[12,6,.6,.6,.1,-0],[12,7,.5,-.1,-0,-0],[12,8,-.1,.8,0,0],[12,9,-.4,.1,0,-0],[12,10,-.2,-1,-.1,-0],[12,11,-1.3,.1,-0,0],[12,12,-.7,.2,-.1,-.1]];function wt(){let e=()=>Array.from({length:13},()=>Array(13).fill(0)),t={g:e(),h:e(),gdot:e(),hdot:e()};for(let[e,n,r,i,a,o]of Ct)t.g[e][n]=r,t.h[e][n]=i,t.gdot[e][n]=a,t.hdot[e][n]=o;return t}const G=wt();function Tt(){let e=Array(169).fill(0),t=Array(169).fill(0),n=Array(13).fill(0),r=Array(13).fill(0),i=Array(169).fill(0),a=Array(169).fill(0),o=(e,t)=>e*13+t;for(let e=1;e<=12;e++)for(let t=0;t<=e;t++){let n=G.g[e][t],r=G.h[e][t],s=G.gdot[e][t],c=G.hdot[e][t];i[o(t,e)]=n,a[o(t,e)]=s,t!==0&&(i[o(e,t-1)]=r,a[o(e,t-1)]=c)}e[o(0,0)]=1;for(let s=1;s<=12;s++){e[o(0,s)]=e[o(0,s-1)]*(2*s-1)/s;let c=2;for(let n=0,r=(s-n+1)/1;r>0;r--,n+=1){if(t[o(n,s)]=((s-1)*(s-1)-n*n)/((2*s-1)*(2*s-3)),n>0){let t=(s-n+1)*c/(s+n);e[o(n,s)]=e[o(n-1,s)]*Math.sqrt(t),c=1,i[o(s,n-1)]=e[o(n,s)]*i[o(s,n-1)],a[o(s,n-1)]=e[o(n,s)]*a[o(s,n-1)]}i[o(n,s)]=e[o(n,s)]*i[o(n,s)],a[o(n,s)]=e[o(n,s)]*a[o(n,s)]}n[s]=s+1,r[s]=s}return t[o(1,1)]=0,r[0]=0,{snorm:e,k:t,fn:n,fm:r,c:i,cd:a,idx:o}}const Et=Tt();function Dt(e){return e%4==0&&e%100!=0||e%400==0?366:365}function Ot(e){let t=e.getUTCFullYear(),n=Date.UTC(t,0,1);return t+Math.floor((e.getTime()-n)/864e5)/Dt(t)}let kt=!1;function At(e){return e===void 0?2027.5:typeof e==`number`?e>1e4?Ot(new Date(e)):e:Ot(e)}function jt(e,t,n){let r=St/1e3,i=6356752.314245179/1e3,a=r*r,o=i*i,s=a-o,c=a*a;c-o*o;let l=t*t,u=n*n,d=Math.sqrt(a-s*l),f=e*d,p=(f+a)/(f+o)*((f+a)/(f+o)),m=t/Math.sqrt(p*u+l),h=Math.sqrt(1-m*m),g=Math.sqrt(e*e+2*f+(c-22083078973482.75*l)/(d*d)),_=Math.sqrt(a*u+o*l);return{r:g,ct:m,st:h,ca:(e+_)/g,sa:s/_*t*n/g}}function Mt(e,t,n,r,i,a,o,s){if(i===a){e[r(a,i)]=o*e[r(a-1,i-1)],t[r(a,i)]=o*t[r(a-1,i-1)]+s*e[r(a-1,i-1)];return}if(i===1&&a===0){e[r(a,i)]=s*e[r(a,i-1)],t[r(a,i)]=s*t[r(a,i-1)]-o*e[r(a,i-1)];return}a>i-2&&(e[r(a,i-2)]=0,t[r(a,i-2)]=0),e[r(a,i)]=s*e[r(a,i-1)]-n[r(a,i)]*e[r(a,i-2)],t[r(a,i)]=s*t[r(a,i-1)]-o*e[r(a,i-1)]-n[r(a,i)]*t[r(a,i-2)]}function Nt(e,t,n,r){let i=r-yt;(r<2025||r>=2030)&&!kt&&(kt=!0,console.warn(`magneticDeclinationDeg: date ${r.toFixed(3)} is outside the WMM2025 validity window [${bt}, ${xt}); using linear secular extrapolation (accuracy degrades).`));let{snorm:a,k:o,fn:s,fm:c,c:l,cd:u,idx:d}=Et,f=t*_t,p=e*_t,m=Math.sin(f),h=Math.sin(p),g=Math.cos(f),_=Math.cos(p),v=Array(13).fill(0),y=Array(13).fill(0);v[0]=0,y[0]=1,v[1]=m,y[1]=g;let{r:b,ct:x,st:S,ca:C,sa:w}=jt(n,h,_);for(let e=2;e<=12;e++)v[e]=m*y[e-1]+g*v[e-1],y[e]=g*y[e-1]-m*v[e-1];let T=6371.2/b,E=T*T,D=0,ee=0,O=0,k=a.slice(),A=Array(169).fill(0);for(let e=1;e<=12;e++){E*=T;for(let t=0,n=(e+t+1)/1;n>0;n--,t+=1){Mt(k,A,o,d,e,t,S,x);let n=l[d(t,e)]+i*u[d(t,e)],r=E*k[d(t,e)],a,f;if(t===0)a=n*y[t],f=n*v[t];else{let r=l[d(e,t-1)]+i*u[d(e,t-1)];a=n*y[t]+r*v[t],f=n*v[t]-r*y[t]}D-=E*a*A[d(t,e)],ee+=c[t]*f*r,O+=s[e]*a*r}}let j;return j=S===0?0:ee/S,{x:-D*C-O*w,y:j,z:D*w-O*C}}function Pt(e){let t=e%360;return t<0?t+360:t}function Ft(e,t,n){if(!Number.isFinite(e)||!Number.isFinite(t))return NaN;let r=n?.altitudeKm??0;if(!Number.isFinite(r))return NaN;let{x:i,y:a}=Nt(e,t,r,At(n?.date));return Math.atan2(a,i)*vt}function It(e,t,n,r){return Pt(e+Ft(t,n,r))}const K=Math.PI/180,Lt=180/Math.PI,q=e=>(e%360+360)%360,J=e=>e<0?0:e>1?1:e,Rt=e=>{let t=0,n=0;for(let r of e)t+=Math.sin(r*K),n+=Math.cos(r*K);return t===0&&n===0?0:q(Math.atan2(t,n)*Lt)},zt=e=>{if(e.length===0)return 0;let t=Rt(e),n=0;for(let r of e){let e=Math.abs(W(r,t));e>n&&(n=e)}return n},Bt=(e,t,n)=>n<=0?+(e<=t):J((t+n-e)/n),Vt=(e,t,n)=>n<=0?+(e>=t):J((e-(t-n))/n),Ht=(e,t,n)=>{if(e.length<n.minWindow)return 0;let r=Bt(zt(e),n.collapseThresholdDeg,n.rampWidthDeg),i=Vt(t,n.baselineMinM,n.baselineRampM);return Math.min(r,i)},Ut=e=>J(1-e),Wt=(e,t,n)=>{let r=J(n),i=Math.cos(e*K),a=Math.sin(e*K),o=Math.cos(t*K),s=Math.sin(t*K),c=o+(i-o)*r,l=s+(a-s)*r;return q(Math.hypot(c,l)<1e-9?t:Math.atan2(l,c)*Lt)},Gt=(e,t,n)=>{if(e===null)return q(t);let r=J(n);return q(e+W(t,e)*r)},Y=e=>q(Math.atan2(e[2],e[0])*Lt),Kt=(e,t,n)=>{let r=i.fromValues(e[0],e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9],e[10],e[11],e[12],e[13],e[14],e[15]),a=W(n,Y(e)),s=o.fromValues(t[0],t[1],t[2]),c=o.create();o.transformMat4(c,s,r);let l=i.create();i.fromYRotation(l,-a*K);let u=i.create();i.fromTranslation(u,c),i.multiply(u,u,l);let d=o.fromValues(-c[0],-c[1],-c[2]);i.translate(u,u,d);let f=i.create();return i.multiply(f,u,r),I(f)},qt=()=>({state:`dormant`,agreeStreak:0,disagreeStreak:0,recommendRecalibration:!1}),Jt=(e,t,n)=>{if(!t.gpsYawObservable)return{state:`dormant`,agreeStreak:0,disagreeStreak:0,recommendRecalibration:!1};let r=Math.abs(t.agreementDeltaDeg);if(r<=n.agreeToleranceDeg){let t=e.agreeStreak+1;return{state:t>=n.minAgreeStreak?`trusted`:`untrusted`,agreeStreak:t,disagreeStreak:0,recommendRecalibration:!1}}let i=e.disagreeStreak+1;return{state:e.state===`trusted`&&r>n.dropToleranceDeg?`untrusted`:e.state===`trusted`?`trusted`:`untrusted`,agreeStreak:0,disagreeStreak:i,recommendRecalibration:i>=n.recalibrateAfterStreak}},Yt=e=>e<0?0:e>1?1:e,Xt=e=>+(e===`trusted`),Zt=(e,t,n)=>{let r=Yt(e),i=Yt(t);return Yt(1-r+r*i*n.steadyStateMaxWeight)},Qt={useOnlyRecentData:!1,recentSeconds:180,includeTimeWeight:!0,weightByTimeFactor:2500,ignoreYAxisForRotation:!0,useRansac:!1,ransacInlierRatio:.95,ransacSampleRatio:.3,ransacMaxIterations:230,ransacErrorTolerance:1,geohashPrecision:8,geohashWindowSize:10,gpsAccuracyExponent:.1,altitudeAlignmentMode:`separate1D`,altitudeAggregator:`mean`,altitudeSampleSet:`all`,gpsVerticalAccuracyExponent:5,useOutlierRejection:!1,outlierThresholdMeters:10,outlierRetainRatio:.6,useDistanceGating:!1,minSampleDistanceMeters:1,maxSampleIntervalMs:3e3,useCompassColdStartOverride:!1,coldStartObservabilityCollapseDeg:12,coldStartObservabilityRampDeg:8,coldStartObservabilityWindow:5,coldStartBaselineMinM:15,coldStartBaselineRampM:10,coldStartSnapAlpha:.5,useCompassRotationPrior:!1,compassSteadyStateMaxWeight:.3},$t=e=>e.map(e=>L(e)),en=e=>e.map(e=>B(e)),tn=e=>e.map(Un),nn=e=>e.map(e=>[e[0],e[1],e[2],e[3]]),X=e=>Array.isArray(e)?e:P(e),Z=e=>Array.isArray(e)?e:F(e),rn=(e,t,n,r)=>({odometryPosOffset:L(X(e)),odometryRotOffset:B(Z(t)),latestLoopClosureFixPointPos:n?L(X(n)):null,latestLoopClosureFixPointRot:r?B(Z(r)):null}),an=(e,t,n,r)=>({odometryPositions:[],odometryRotations:[],gpsPositions:[],gpsPositionsVec4:[],alignmentMatrix:[...Se],alignmentRotation:[...R],alignmentTranslation:[...z],alignmentRotationInDegree:[...z],...rn(e,t,n,r),gpsAccuracyMedian:null,gpsAccuracyMean:null,currentGpsPosGeoHash:null,lastAdmittedOdomPos:null,lastAdmittedTs:null}),on=()=>an(z,R,null,null),sn=(e,t,n,r)=>{let i=e.map(e=>X(e)),a=t.map(e=>B(Z(e))),o=n.map(Un),s=r.gpsAccuracyExponent;for(let e of o)e.weight=dn(e.latLongAccuracy,s);let c=o.map(Vn),l=r.includeTimeWeight?In(c,o,r.weightByTimeFactor):c,u=r.useOnlyRecentData?Pn(o,r.recentSeconds):0,d=i.slice(u).map(M),f=o.slice(u);return{allPositionTuples:i,allRotationTuples:a,allGpsPoints:o,allVec4Tuples:l,solverPositionsTyped:d,solverGpsPoints:f,solverWeightedVec4Tuples:l.slice(u),solverVerticalWeights:Fn(f,r)}},cn=(e,t,n,r,i)=>{if(e==null||t==null)return!0;let a=n[0]-e[0],o=n[2]-e[2],s=i.minSampleDistanceMeters*i.minSampleDistanceMeters;return a*a+o*o>=s||r-t>=i.maxSampleIntervalMs},ln=(e,t,n,r)=>{if(!r.useDistanceGating)return{odometryPositions:e,odometryRotations:t,gpsPoints:n};let i=[],a=[],o=[],s=null,c=null;for(let l=0;l<n.length;l+=1){let u=X(e[l]),d=n[l].timestamp;cn(s,c,u,d,r)&&(i.push(e[l]),a.push(t[l]),o.push(n[l]),s=u,c=d)}return{odometryPositions:i,odometryRotations:a,gpsPoints:o}},un=e=>{let{odometryPositions:t,odometryRotations:n,gpsPoints:r,odometryPosOffset:i=z,odometryRotOffset:s=R,latestLoopClosureFixPointPos:c=null,latestLoopClosureFixPointRot:l=null,alignmentConfig:u,random:d}=e;if(t.length!==n.length||t.length!==r.length)throw Error(`GpsEvents requires odometry positions, rotations, and gps points to have identical lengths`);let f={...Qt,...u??{}};if(t.length===0)return an(i,s,c,l);let p=ln(t,n,r,f),{allPositionTuples:m,allRotationTuples:h,allGpsPoints:g,allVec4Tuples:_,solverPositionsTyped:v,solverGpsPoints:y,solverWeightedVec4Tuples:b,solverVerticalWeights:x}=sn(p.odometryPositions,p.odometryRotations,p.gpsPoints,f),S=On(hn(v,b,x,f,d??Math.random).matrix,v,b,x,g,h,f,d??Math.random),C=S.matrix,w=a.create(),T=o.create(),E=o.create();pn(C,w,T,E);let{mean:D,median:ee}=zn(g),O=Rn(p.gpsPoints,f.geohashPrecision,f.geohashWindowSize),k=m.length-1,A=k>=0?L(m[k]):null,j=k>=0?p.gpsPoints[k]?.timestamp??null:null;return{odometryPositions:$t(m),odometryRotations:en(h),gpsPositions:tn(g),gpsPositionsVec4:nn(_),alignmentMatrix:I(C),alignmentRotation:F(w),alignmentTranslation:P(T),alignmentRotationInDegree:P(E),...rn(i,s,c,l),gpsAccuracyMedian:ee,gpsAccuracyMean:D,currentGpsPosGeoHash:O,lastAdmittedOdomPos:A,lastAdmittedTs:j,...S.fields}},dn=(e,t)=>e!=null&&e>0?1/Math.max(e,1)**+t:1,fn=(e,t,n,r,i,s)=>{let c={...Qt,...i??{}},l=X(t);if(c.useDistanceGating&&!cn(e.lastAdmittedOdomPos,e.lastAdmittedTs,l,r.timestamp,c))return;let u=e.odometryPositions,d=e.odometryRotations,f=e.gpsPositions,p=e.gpsPositionsVec4;u.push(l),d.push(B(Z(n)));let m=Un(r);f.push(m),m.weight=dn(m.latLongAccuracy,c.gpsAccuracyExponent);let h=Vn(m);if(c.includeTimeWeight){p.push(h);let e=In(p,f,c.weightByTimeFactor);for(let t=0;t<e.length;t++)p[t]=e[t]}else p.push(h);let g=0;c.useOnlyRecentData&&(g=Pn(f,c.recentSeconds));let _=u.slice(g).map(M),v=p.slice(g),y=Dn(e,hn(_,v,Fn(f.slice(g),c),c,s??Math.random).matrix,_,v,f,d,c);e.alignmentMatrix=I(y);let b=a.create(),x=o.create(),S=o.create();pn(y,b,x,S),e.alignmentRotation=F(b),e.alignmentTranslation=P(x),e.alignmentRotationInDegree=P(S);let{mean:C,median:w}=zn(f);e.gpsAccuracyMean=C,e.gpsAccuracyMedian=w,e.currentGpsPosGeoHash=Rn(f,c.geohashPrecision,c.geohashWindowSize),e.lastAdmittedOdomPos=L(l),e.lastAdmittedTs=r.timestamp},pn=(e,t,n,r)=>{i.getRotation(t,e),a.normalize(t,t),i.getTranslation(n,e),Bn(t,r)},Q=o.create(),mn=o.create(),hn=(e,t,n,r,a)=>{if(e.length===0)return{matrix:i.create(),meanError:0};let o=e.length,c=[];for(let r=0;r<o;r+=1){let i=t[r];c.push({odom:e[r],ref:s.fromValues(i[0],i[1],i[2],i[3]),verticalWeight:n[r]??1})}let l,u,d;if(r.useRansac&&c.length>=3){let e=c.length,t=Math.max(3,Math.min(e,Math.ceil(e*r.ransacSampleRatio))),n=rt(c,Math.max(t,Math.min(e,Math.ceil(e*r.ransacInlierRatio))),t,r.ransacMaxIterations,e=>kn(e,r.ignoreYAxisForRotation),(e,t)=>An(e,t)<e.meanAlignmentError+r.ransacErrorTolerance,a);l=n.alignmentMatrix,u=n.meanAlignmentError,n.inliers!==void 0&&(d=Array.from(n.inliers))}else if(r.useOutlierRejection&&c.length>=4){let{model:e,inliers:t}=Nn(c,r);l=e.alignmentMatrix,u=e.meanAlignmentError,d=t}else{let e=kn(c,r.ignoreYAxisForRotation);l=e.alignmentMatrix,u=e.meanAlignmentError}return r.altitudeAlignmentMode===`separate1D`&&gn(l,c,d,r),{matrix:l,meanError:u}},gn=(e,t,n,r)=>{let i=r.altitudeSampleSet===`horizontalInliers`&&n!==void 0&&n.length>0?n:t;if(i.length===0)return;let a=Array(i.length),o=Array(i.length);for(let e=0;e<i.length;e+=1){let t=i[e];a[e]=t.ref[1]-t.odom[1];let n=t.verticalWeight;o[e]=n>0&&Number.isFinite(n)?n:0}e[13]=r.altitudeAggregator===`median`?vn(a,o):_n(a,o)},_n=(e,t)=>{let n=0,r=0;for(let i=0;i<e.length;i+=1)n+=e[i]*t[i],r+=t[i];if(r>0&&Number.isFinite(r))return n/r;let i=0;for(let t=0;t<e.length;t+=1)i+=e[t];return e.length===0?0:i/e.length},vn=(e,t)=>{if(e.length===0)return 0;if(e.length===1)return e[0];let n=e.map((e,t)=>t);n.sort((t,n)=>e[t]-e[n]);let r=0;for(let e=0;e<t.length;e+=1)r+=t[e];if(!(r>0)||!Number.isFinite(r)){let t=n.map(t=>e[t]);return t[Math.floor((t.length-1)/2)]}let i=r/2,a=0;for(let r=0;r<n.length;r+=1)if(a+=t[n[r]],a>=i)return e[n[r]];return e[n[n.length-1]]},yn=e=>{let t=0;for(let n=1;n<e.length;n+=1){let r=e[n].coordinates,i=e[n-1].coordinates;t+=Math.hypot(r[0]-i[0],r[2]-i[2])}return t},bn=(e,t)=>{let n=o.create(),r=0;for(let i=0;i<e.length;i+=1){let a=t[i][3];o.scaleAndAdd(n,n,e[i],a),r+=a}return r>0&&o.scale(n,n,1/r),n},xn=(e,t)=>{let n=[];for(let r=0;r<e.length;r+=1){let i=e[r].absoluteOrientation,a=t[r];if(!i||!a)continue;let o=gt(i.quaternion,a);if(o===null)continue;let s=((o+Ft(e[r].latitude,e[r].longitude,{date:e[r].timestamp||void 0}))%360+360)%360;Number.isFinite(s)&&n.push(s)}return n.length===0?null:Rt(n)},Sn=e=>({collapseThresholdDeg:e.coldStartObservabilityCollapseDeg,rampWidthDeg:e.coldStartObservabilityRampDeg,minWindow:e.coldStartObservabilityWindow,baselineMinM:e.coldStartBaselineMinM,baselineRampM:e.coldStartBaselineRampM}),Cn=(e,t,n,r,i)=>{let a=e.length,o=Math.max(1,a-r.coldStartObservabilityWindow+1),s=[];for(let c=o;c<=a;c+=1){let a=hn(e.slice(0,c),t.slice(0,c),n.slice(0,c),r,i);s.push(Y(a.matrix))}return s},wn={agreeToleranceDeg:8,minAgreeStreak:3,dropToleranceDeg:20,recalibrateAfterStreak:4},Tn=(e,t,n,r,i,a,o,s,c)=>{let l=xn(r,i);if(l===null)return{matrix:e,appliedBearingDeg:o,trust:s};let u=a.length>0?a[a.length-1]:Y(e),d=Ht(a,yn(r),Sn(c)),f,p=s;c.useCompassRotationPrior?(p=Jt(s??qt(),{gpsYawObservable:d>=.5,agreementDeltaDeg:W(l,u)},wn),f=Zt(d,Xt(p.state),{steadyStateMaxWeight:c.compassSteadyStateMaxWeight})):f=Ut(d);let m=Gt(o,Wt(l,u,f),c.coldStartSnapAlpha);return{matrix:ye(Kt(e,bn(t,n),m)),appliedBearingDeg:m,trust:p}},En=e=>e.useCompassColdStartOverride||e.useCompassRotationPrior,Dn=(e,t,n,r,i,a,o)=>{if(!En(o))return t;let s=e.coldStartYawWindowDeg?[...e.coldStartYawWindowDeg]:[];for(s.push(Y(t));s.length>o.coldStartObservabilityWindow;)s.shift();let c=Tn(t,n,r,i,a,s,e.coldStartAppliedBearingDeg??null,e.compassTrust,o);return e.coldStartYawWindowDeg=s,e.coldStartAppliedBearingDeg=c.appliedBearingDeg,c.trust!==void 0&&(e.compassTrust=c.trust),c.matrix},On=(e,t,n,r,i,a,o,s)=>{if(!En(o))return{matrix:e,fields:{}};let c=Cn(t,n,r,o,s),l=Tn(e,t,n,i,a,c,null,void 0,o),u={coldStartYawWindowDeg:c,coldStartAppliedBearingDeg:l.appliedBearingDeg};return l.trust!==void 0&&(u.compassTrust=l.trust),{matrix:l.matrix,fields:u}},kn=(e,t)=>{let n=Array.from(e),r=n.length,i=Array(r),a=Array(r);for(let e=0;e<r;e+=1)i[e]=n[e].odom,a[e]=n[e].ref;let s=et(i,a,{ignoreYAxisForRotation:t}),c=0;for(let e=0;e<r;e+=1)o.transformMat4(Q,i[e],s),c+=jn(Q,n[e].ref);return{alignmentMatrix:s,meanAlignmentError:r===0?0:c/r,totalModelError:c}},An=(e,t)=>(o.transformMat4(Q,t.odom,e.alignmentMatrix),jn(Q,t.ref)),jn=(e,t)=>(o.set(mn,t[0],t[1],t[2]),o.squaredDistance(e,mn)),Mn=(e,t)=>{o.transformMat4(Q,t.odom,e.alignmentMatrix);let n=Q[0]-t.ref[0],r=Q[2]-t.ref[2];return n*n+r*r},Nn=(e,t)=>{let n=e.length,r=Math.max(3,Math.ceil(t.outlierRetainRatio*n)),i=t.outlierThresholdMeters*t.outlierThresholdMeters,a=Array.from(e),o=kn(a,t.ignoreYAxisForRotation);for(;a.length>r;){let e=-1,n=-1;for(let t=0;t<a.length;t+=1){let r=Mn(o,a[t]);r>n&&(n=r,e=t)}if(n<=i||e<0)break;a=a.filter((t,n)=>n!==e),o=kn(a,t.ignoreYAxisForRotation)}return{model:o,inliers:a}},Pn=(e,t)=>{if(e.length===0||t<=0)return 0;let n=e[e.length-1].timestamp-t*1e3;for(let t=0;t<e.length;t+=1)if(e[t].timestamp>=n)return t;return 0},Fn=(e,t)=>{let n=t.gpsVerticalAccuracyExponent,r=e.map(e=>{let t=e.altitudeAccuracy;return dn(t!=null&&Number.isFinite(t)&&t>0?t:e.latLongAccuracy,n)});if(!t.includeTimeWeight||e.length<2)return r;let i=e[e.length-1].timestamp,a=e[0].timestamp,o=Math.max(1,i-a),s=t.weightByTimeFactor;return r.map((t,n)=>{if(!(t>0&&Number.isFinite(t)))return 0;let r=s*((i-e[n].timestamp)/o)+1;return 1/(1/t+r)})},In=(e,t,n)=>{if(e.length<2)return e.map(e=>[e[0],e[1],e[2],e[3]]);let r=t[t.length-1].timestamp,i=t[0].timestamp,a=Math.max(1,r-i);return e.map((e,i)=>{let o=n*((r-t[i].timestamp)/a)+1,s=t[i].weight;if(!(s>0&&Number.isFinite(s)))return[e[0],e[1],e[2],0];let c=1/(1/s+o);return[e[0],e[1],e[2],c]})},Ln=new Map,Rn=(e,t,n)=>{if(e.length===0)return null;let r=Math.max(0,e.length-n);Ln.clear();for(let n=r;n<e.length;n+=1){let r=e[n],i=ie(Hn(r),t),a=Ln.get(i);a?(a.count+=1,a.index=n):Ln.set(i,{count:1,index:n})}let i=null,a=-1,o=-1;for(let[e,{count:t,index:n}]of Ln)(t>a||t===a&&n>o)&&(i=e,a=t,o=n);return i},zn=e=>{let t=e.map(e=>e.latLongAccuracy).filter(e=>typeof e==`number`&&Number.isFinite(e));if(t.length===0)return{mean:null,median:null};let n=t.reduce((e,t)=>e+t,0)/t.length,r=t.slice().sort((e,t)=>e-t),i=Math.floor(r.length/2);return{mean:n,median:r.length%2==0?(r[i-1]+r[i])/2:r[i]}},Bn=(e,t)=>{let n=e[0],r=e[1],i=e[2],a=e[3],s=2*(a*n+r*i),c=1-2*(n*n+r*r),l=Math.atan2(s,c),u=2*(a*r-i*n),d;d=Math.abs(u)>=1?Math.PI/2*Math.sign(u):Math.asin(u);let f=2*(a*i+n*r),p=1-2*(r*r+i*i),m=Math.atan2(f,p),h=180/Math.PI,g=t??o.create();return g[0]=l*h,g[1]=d*h,g[2]=m*h,g},Vn=e=>[e.coordinates[0],e.coordinates[1],e.coordinates[2],e.weight>0&&Number.isFinite(e.weight)?e.weight:1],Hn=e=>({lat:e.latitude,lon:e.longitude}),Un=e=>({...e,zeroRef:{lat:e.zeroRef.lat,lon:e.zeroRef.lon},coordinates:[e.coordinates[0],e.coordinates[1],e.coordinates[2]],timestamp:e.timestamp,deviceRotation:e.deviceRotation?B(Z(e.deviceRotation)):void 0,absoluteOrientation:e.absoluteOrientation?{...e.absoluteOrientation,quaternion:[e.absoluteOrientation.quaternion[0],e.absoluteOrientation.quaternion[1],e.absoluteOrientation.quaternion[2],e.absoluteOrientation.quaternion[3]]}:void 0}),Wn=({lat:e,lon:t})=>{if(!Number.isFinite(e))throw Error(`Invalid latitude value: ${e}`);if(!Number.isFinite(t))throw Error(`Invalid longitude value: ${t}`);if(e<-90||e>90)throw Error(`Invalid latitude range: ${e}`);if(t<-180||t>180)throw Error(`Invalid longitude range: ${t}`)},Gn=o.fromValues(1,1,1),Kn=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],qn=(e,t,n,r)=>{let i=ce(t,{lat:e.latitude,lon:e.longitude},e.altitude??0,0),a=n?.alpha!=null&&n?.beta!=null&&n?.gamma!=null?U(Ne(n.alpha,n.beta,n.gamma)):void 0;return{...e,zeroRef:t,coordinates:P(i),weight:1,deviceRotation:a,absoluteOrientation:r}},Jn=(e,t,n)=>{if(e)return Ne(e.alpha,e.beta,e.gamma);if(t)return t;throw Error(`Sensor rotation missing for ${n}: neither raw orientation nor legacy quaternion provided`)},Yn=e=>{let t=a.invert(a.create(),e);if(!t)throw Error(`Encountered non-invertible quaternion`);return t},Xn=e=>{let t=Yn(a.normalize(a.create(),N(e.lastSensorRot))),n=a.normalize(a.create(),N(e.lastValidOdomRot)),r=a.multiply(a.create(),t,n),i=a.normalize(a.create(),N(e.newSensorRot)),o=a.multiply(a.create(),i,r),s=a.normalize(a.create(),N(e.newOdomRot)),c=a.multiply(a.create(),o,s);return a.normalize(c,c),F(c)},Zn=(e,t)=>{let n=i.create();return i.fromRotationTranslationScale(n,a.normalize(a.create(),N(t)),M(e),Gn),n},Qn=(e,t,n)=>{let r=o.create(),s=o.create(),c=a.create(),l=a.create();i.getTranslation(r,e),i.getTranslation(s,t),i.getRotation(c,e),i.getRotation(l,t);let u=o.create();o.lerp(u,r,s,n);let d=a.create();return a.slerp(d,c,l,n),i.fromRotationTranslation(i.create(),d,u)},$n=(e,t)=>{if(e.length===0)return[];let n=e[e.length-1],r=i.invert(i.create(),n);if(!r)throw Error(`End pose matrix is not invertible`);let a=i.multiply(i.create(),t,r),o=i.create(),s=e.length-1;return e.map((e,t)=>{let n=Qn(o,a,s<=0?1:t/s);return i.multiply(i.create(),n,e)})},er=(e,t,n)=>{for(let r=e.length-1;r>=0;--r)if(n(e[r],t))return r;return-1},tr=e=>e.coldStartOverrideEnabled?{useCompassColdStartOverride:!0}:void 0,nr=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2],rr=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]&&e[3]===t[3],ir=t({name:`gpsData`,initialState:null,reducers:{setZeroPos:{reducer:(e,t)=>e===null?{zero:t.payload,gpsEvents:on(),odometryPath:ge()}:e,prepare:e=>(Wn(e),{payload:e})},recordGpsEvent:(e,t)=>{if(!e)return e;let{odomPosition:n,odomRotation:r,rawGpsPoint:i,rawDeviceOrientation:a,rawAbsoluteOrientation:o}=t.payload,s=qn(i,e.zero,a,o);fn(e.gpsEvents,V(n),H(r),s,tr(e))},setColdStartOverrideEnabled:(e,t)=>{if(!e)return e;e.coldStartOverrideEnabled=t.payload},odometryTrackingRestarted:(e,t)=>{if(!e)return e;let n=Kn(e.gpsEvents.odometryPosOffset,V(t.payload.lastValidOdomPos)),r=Jn(t.payload.lastSensorOrientation,t.payload.lastSensorRot,`lastSensor`),i=Jn(t.payload.newSensorOrientation,t.payload.newSensorRot,`newSensor`);e.gpsEvents=c(un({odometryPositions:[],odometryRotations:[],gpsPoints:[],odometryPosOffset:n,odometryRotOffset:Xn({...t.payload,lastValidOdomRot:H(t.payload.lastValidOdomRot),newOdomRot:H(t.payload.newOdomRot),lastSensorRot:U(r),newSensorRot:U(i)}),latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null,alignmentConfig:tr(e)}))},arLoopClosureDetected:(e,t)=>{if(!e)return e;let n=e.gpsEvents;if(n.odometryPositions.length===0)return e;let r=n.latestLoopClosureFixPointPos?er(n.odometryPositions,n.latestLoopClosureFixPointPos,nr):0,s=n.latestLoopClosureFixPointRot?er(n.odometryRotations,n.latestLoopClosureFixPointRot,rr):0;if(r<0||s<0)throw Error(`Loop closure fix point could not be located in history`);if(r!==s)throw Error(`Loop closure fix point indices for position and rotation diverged`);let l=n.odometryPositions.slice(0,r).map(e=>L(e)),u=n.odometryRotations.slice(0,r).map(e=>B(e)),d=n.odometryPositions.slice(r).map(e=>L(e)),f=n.odometryRotations.slice(r).map(e=>B(e)),p=d.map((e,t)=>Zn(e,f[t])),m=Zn(V(t.payload.lastPos),B(H(t.payload.lastRot)));p.push(m);let h=$n(p,Zn(V(t.payload.newPos),B(H(t.payload.newRot)))),g=[],_=[],v=o.create();for(let e=0;e<h.length-1;e+=1){let t=h[e],n=o.create();i.getTranslation(n,t);let r=a.create();if(i.getRotation(r,t),a.normalize(r,r),i.getScaling(v,t),Math.hypot(v[0]-1,v[1]-1,v[2]-1)>.05)throw Error(`Unexpected scale drift encountered during loop closure correction`);g.push(P(n)),_.push(F(r))}e.gpsEvents=c(un({odometryPositions:l.concat(g),odometryRotations:u.concat(_),gpsPoints:n.gpsPositions,odometryPosOffset:n.odometryPosOffset,odometryRotOffset:n.odometryRotOffset,latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null,alignmentConfig:tr(e)}))},add2dImage:(e,t)=>{if(!e)return e;e.odometryPath.points.push(c({imageFile:t.payload.imageFile,screenRotation:t.payload.screenRotation,position:V(t.payload.position),rotation:B(H(t.payload.rotation)),capturedAt:t.payload.capturedAt,width:t.payload.width,height:t.payload.height}))}}}),{setZeroPos:ar,recordGpsEvent:or,odometryTrackingRestarted:sr,arLoopClosureDetected:cr,add2dImage:lr,setColdStartOverrideEnabled:ur}=ir.actions,dr=p(ar),fr=p(or),pr=p(sr),mr=p(cr),hr=p(lr),gr=p(ur),_r=m(ir.reducer),vr=t({name:`gpsElements`,initialState:_e(),reducers:{addMarker:(e,t)=>{e.gpsMarkers.push(t.payload)},addLine:(e,t)=>{e.gpsLines.push(t.payload)},addArea:(e,t)=>{e.areas.push(t.payload)},addToHeatMaps:(e,t)=>{let{category:n,tiles:r}=t.payload,i=e.heatMap[n]??{};e.heatMap[n]={...i,...r}},addHeatMapArea:(e,t)=>{let n=t.payload,r=n.category;if(e.heatAreas[r]||(e.heatAreas[r]={}),e.heatAreas[r][n.geoHash])throw Error(`HeatArea collision detected for GeoHash: ${n.geoHash}`);e.heatAreas[r][n.geoHash]=n},resetGpsElements:()=>_e()}}),{addMarker:yr,addLine:br,addArea:xr,addToHeatMaps:Sr,addHeatMapArea:Cr,resetGpsElements:wr}=vr.actions,Tr=p(yr),Er=p(br),Dr=p(xr),Or=p(Sr),kr=p(Cr),Ar=p(wr),jr=m(vr.reducer),Mr=()=>({gpsData:null,gpsElements:_e(),arElements:ve()}),Nr=e=>{let t=Array.from({length:Math.min(e.length,4)},(t,n)=>e[n].toFixed(2));e.length>4&&t.push(`…`);let n=`[${t.join(`, `)}]`;if(e.length===4){let{pitch:t,yaw:r,roll:i}=v(e);return`${n} (pitch=${t.toFixed(0)}°, yaw=${r.toFixed(0)}°, roll=${i.toFixed(0)}°)`}return n},Pr=e=>(e.length===3||e.length===4||e.length===16)&&e.every(e=>typeof e==`number`),$=(e,t=0)=>{if(t>10||e==null)return e;if(Array.isArray(e))return Pr(e)?Nr(e):e.map(e=>$(e,t+1));if(typeof e==`object`){let n={};for(let[r,i]of Object.entries(e))n[r]=$(i,t+1);return n}return e},Fr=(t={})=>{let{preloadedState:n,enableDevToolsSanitizers:r=!0,enableDevChecks:i=!0,licenseKey:a}=t;if(a==null)throw Error(`License key required. Pass options.licenseKey or use createRecorderStore() from gps-plus-slam-app-framework. See EULA §3.`);g(a);let o=Mr(),s=n?{gpsData:n.gpsData??o.gpsData,gpsElements:n.gpsElements??o.gpsElements,arElements:n.arElements??o.arElements}:void 0;return e({reducer:{gpsData:_r,gpsElements:jr,arElements:Ze},preloadedState:s,middleware:e=>e({serializableCheck:i,immutableCheck:i}),devTools:r?{actionSanitizer:$,stateSanitizer:$}:!0})},Ir=[],Lr=[],Rr=[],zr={median:null,mean:null},Br=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentMatrix}),Vr=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentRotation}),Hr=f(function(e){return e.gpsData?.gpsEvents?.odometryPositions??Ir}),Ur=f(function(e){return e.gpsData?.gpsEvents?.odometryRotations??Lr}),Wr=f(function(e){return e.gpsData?.gpsEvents?.gpsPositions??Rr}),Gr=f(function(e){return e.gpsData?.zero??null}),Kr=f(function(e){let t=e.gpsData?.gpsEvents?.gpsAccuracyMedian??null,n=e.gpsData?.gpsEvents?.gpsAccuracyMean??null;return t===null&&n===null?zr:{median:t,mean:n}}),qr=`1.0.0`;export{Se as IDENTITY_MATRIX4,R as IDENTITY_QUATERNION,qr as LIB_VERSION,yt as WMM2025_EPOCH,bt as WMM2025_VALID_FROM,xt as WMM2025_VALID_TO,z as ZERO_VECTOR3,hr as add2dImage,Dr as addArea,Ke as addCornerToEventArea,kr as addHeatMapArea,Er as addLine,Tr as addMarker,We as addOrUpdateArPlane,Or as addToHeatMaps,Ye as anchorEventAreaInWorldSpace,Ze as arElementsReducer,mr as arLoopClosureDetected,gt as arNorthBearingDeg,ht as arToEnuRotation,W as bearingDeltaDeg,ie as calcGeoHash,le as calcGpsCoords,ne as calcQuadKey,ce as calcRelativeCoordsInMeters,xe as cloneMatrix4,be as cloneQuaternion,L as cloneVector3,qe as correctArDriftForEventArea,Fr as createGpsSlamStore,oe as distanceInMeters,se as distanceInMetersRelative,U as enuQuaternionToNUE,Ne as eulerToQuaternion,Je as finishEventArea,ye as fromMatrix4,N as fromQuaternion,M as fromVector3,he as fusedGpsFromOdom,ae as geoHashToLatLong,Br as getAlignmentMatrix,Vr as getAlignmentRotation,pe as getGoogleMapsDirectionsLink,fe as getGoogleMapsLink,Kr as getGpsAccuracyStats,Wr as getGpsPositions,Hr as getOdometryPositions,Ur as getOdometryRotations,me as getOpenStreetMapLink,Gr as getZeroReference,_r as gpsDataReducer,jr as gpsElementsReducer,ke as invertQuaternion,Ce as isIdentityMatrix4,Te as isIdentityQuaternion,Ee as isNearIdentityQuaternion,Ft as magneticDeclinationDeg,pt as magneticHeadingFromEnuQuat,It as magneticToTrueHeadingDeg,Oe as multiplyQuaternions,B as normalizeQuaternion,Me as nueQuaternionToENU,je as nueQuaternionToWebXR,Ae as nueToWebXR,pr as odometryTrackingRestarted,re as quadKeyToLatLong,we as quaternionMagnitude,De as quaternionsEquivalent,fr as recordGpsEvent,Ue as recordPhoneHeight,Xe as resetArElements,Ar as resetGpsElements,$ as sanitizeForDevTools,gr as setColdStartOverrideEnabled,dr as setZeroPos,Ge as startEventArea,ue as toEarthCenteredCoordinates,I as toMatrix4,F as toQuaternion,P as toVector3,g as validateLicenseKey,H as webxrQuaternionToNUE,V as webxrToNUE};
@@ -35,6 +35,6 @@
35
35
  * @see docs/2026-04-25-private-key-security-plan.md — secret-backed renewal
36
36
  * @see ../../GpsPlusSlamJs_Docs/docs/2026-05-01-community-key-resign-cross-repo-issue.md
37
37
  */
38
- declare const COMMUNITY_LICENSE_KEY = "eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODEzOTA4MDgzfQ.zzBeiFZSpkdY22kZKTL5WuexQ_MZOe0o7KTmuv7p873-66tZYWIjYUPkRXt4LI_XAJFpmeCPxlEpvpw1pqCgBw";
38
+ declare const COMMUNITY_LICENSE_KEY = "eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODE0MDQ4ODExfQ.93uD-XHsPVXAAVkr163KYmYcRxMXpi4qkdntamr9kUWsU9q5-zb67ptgISNOOfdLDJnejod4auPokrYlF1zqBQ";
39
39
  //#endregion
40
40
  export { COMMUNITY_LICENSE_KEY };
@@ -1,2 +1,2 @@
1
1
  /*! gps-plus-slam-js | (c) 2026 cs-util-com | UNLICENSED — see EULA.md */
2
- const e=`eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODEzOTA4MDgzfQ.zzBeiFZSpkdY22kZKTL5WuexQ_MZOe0o7KTmuv7p873-66tZYWIjYUPkRXt4LI_XAJFpmeCPxlEpvpw1pqCgBw`;export{e as COMMUNITY_LICENSE_KEY};
2
+ const e=`eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODE0MDQ4ODExfQ.93uD-XHsPVXAAVkr163KYmYcRxMXpi4qkdntamr9kUWsU9q5-zb67ptgISNOOfdLDJnejod4auPokrYlF1zqBQ`;export{e as COMMUNITY_LICENSE_KEY};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gps-plus-slam-js",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "TypeScript library for real-time GPS + AR odometry alignment.",
5
5
  "author": "cs-util-com",
6
6
  "keywords": [