gps-plus-slam-js 1.6.0 → 1.6.2

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
@@ -415,6 +415,24 @@ interface GpsModel {
415
415
  * GpsPlusSlamJs_Docs/docs/2026-06-26-absolute-orientation-sensor-phase4-stage0-followup.md.
416
416
  */
417
417
  coldStartOverrideEnabled?: boolean;
418
+ /**
419
+ * Runtime opt-in for the Phase-4 **Stage C** trust-gated compass rotation prior
420
+ * (closed/internal). Set via `setCompassRotationPriorEnabled` (after
421
+ * `setZeroPos`). When truthy the reducer threads
422
+ * `{ useCompassRotationPrior: true }` into the solve (it supersedes Stage 0,
423
+ * keeping a steady-state vote once observable+trusted). Absent/false ⇒
424
+ * byte-identical. Debug/experiment flag.
425
+ */
426
+ compassRotationPriorEnabled?: boolean;
427
+ /**
428
+ * Runtime opt-in for the GPS-free compass↔WebXR consistency gate
429
+ * (closed/internal). Set via `setCompassWebXRConsistencyEnabled` (after
430
+ * `setZeroPos`). When truthy the reducer threads
431
+ * `{ requireCompassWebXRConsistency: true }` into the solve, so the compass
432
+ * override (Stage 0 / Stage C) abstains unless the compass is rotating in
433
+ * lock-step with WebXR. Absent/false ⇒ byte-identical. Debug/experiment flag.
434
+ */
435
+ compassWebXRConsistencyEnabled?: boolean;
418
436
  }
419
437
  interface GpsSlamState {
420
438
  gpsData: GpsModel | null;
@@ -539,6 +557,8 @@ declare const odometryTrackingRestarted: _$_reduxjs_toolkit0.ActionCreatorWithPa
539
557
  declare const arLoopClosureDetected: _$_reduxjs_toolkit0.ActionCreatorWithPayload<ArLoopClosureDetectedPayload, "gpsData/arLoopClosureDetected">;
540
558
  declare const add2dImage: _$_reduxjs_toolkit0.ActionCreatorWithPayload<ArImageCapture, "gpsData/add2dImage">;
541
559
  declare const setColdStartOverrideEnabled: _$_reduxjs_toolkit0.ActionCreatorWithPayload<boolean, "gpsData/setColdStartOverrideEnabled">;
560
+ declare const setCompassRotationPriorEnabled: _$_reduxjs_toolkit0.ActionCreatorWithPayload<boolean, "gpsData/setCompassRotationPriorEnabled">;
561
+ declare const setCompassWebXRConsistencyEnabled: _$_reduxjs_toolkit0.ActionCreatorWithPayload<boolean, "gpsData/setCompassWebXRConsistencyEnabled">;
542
562
  declare const gpsDataReducer: (state: GpsModel | null | undefined, action: _$redux.UnknownAction) => GpsModel | null;
543
563
  //#endregion
544
564
  //#region ../src/state/gpsElementsSlice.d.ts
@@ -744,4 +764,4 @@ declare function validateLicenseKey(key: string): LicenseValidationResult;
744
764
  //#region ../src/index.d.ts
745
765
  declare const LIB_VERSION = "1.0.0";
746
766
  //#endregion
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 };
767
+ 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, setCompassRotationPriorEnabled, setCompassWebXRConsistencyEnabled, 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),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};
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,te=e=>e*w,k=e=>{if(!Number.isFinite(e))throw RangeError(`Coordinate values must be finite numbers`);return String(e)},A=e=>({lat:k(e.lat),lon:k(e.lon)}),ne=(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)},re=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}),ie=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:te(Math.atan(Math.sinh(Math.PI*(1-2*c)))),lon:l}}),ae=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}),oe=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}}),se=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)))}),ce=f((e,t)=>{let n=le(e,t);return Math.hypot(n[0],n[2])}),le=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)}),ue=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}}),de=f((e,t=0)=>ne(e,t)),fe=e=>{let{lat:t,lon:n}=A(e);return`${t}%2C${n}`},pe=f(e=>`https://www.google.com/maps/search/?api=1&query=${fe(e)}`),me=f((e,t)=>`https://www.google.com/maps/dir/?api=1&origin=${fe(t)}&destination=${fe(e)}`),he=f((e,t=19)=>{let{lat:n,lon:r}=A(e);return`https://www.openstreetmap.org/query?lat=${n}&lon=${r}#map=${t}/${n}/${r}`}),ge=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}=ue(n,s);return{lat:c,lon:l,altitude:s[1]}}),_e=()=>({points:[]}),ve=()=>({gpsMarkers:[],gpsLines:[],areas:[],heatMap:{},heatAreas:{}}),ye=()=>({arPlanes:{},floorDetections:[],eventAreas:[],currentEventAreaId:null,currentEventAreaPoints:[]}),j=e=>o.fromValues(e[0],e[1],e[2]),M=e=>a.fromValues(e[0],e[1],e[2],e[3]),be=e=>i.fromValues(...e),N=e=>[e[0],e[1],e[2]],P=e=>[e[0],e[1],e[2],e[3]],F=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]],I=e=>[e[0],e[1],e[2]],xe=e=>[e[0],e[1],e[2],e[3]],Se=e=>[...e],L=Object.freeze([0,0,0,1]),R=Object.freeze([0,0,0]),Ce=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),z=e=>{let t=Te(e);if(t===0)return L;let n=1/t;return[e[0]*n,e[1]*n,e[2]*n,e[3]*n]},we=e=>{for(let t=0;t<16;t++)if(e[t]!==Ce[t])return!1;return!0},Te=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]+e[3]*e[3]),Ee=e=>e[0]===0&&e[1]===0&&e[2]===0&&e[3]===1,De=(e,t)=>Math.abs(e[0])<t&&Math.abs(e[1])<t&&Math.abs(e[2])<t&&Math.abs(e[3]-1)<t,Oe=(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},ke=(e,t)=>{let n=a.create();return a.multiply(n,e,t),[n[0],n[1],n[2],n[3]]},Ae=e=>{let t=a.create();return a.invert(t,e),[t[0],t[1],t[2],t[3]]},B=e=>[-e[2],e[1],e[0]],je=e=>[e[2],e[1],-e[0]],V=e=>[-e[2],e[1],e[0],e[3]],Me=e=>[e[2],e[1],-e[0],e[3]],H=e=>[e[1],e[2],e[0],e[3]],Ne=e=>[e[2],e[0],e[1],e[3]],Pe=(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]]},Fe=t({name:`arElements`,initialState:ye(),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(I(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=be(r),l=s.arPoints.map(e=>{let t=j(e);return ue(i,o.transformMat4(o.create(),t,c))});e.eventAreas[a]={...s,isInArSpace:!1,polygon:l,arPoints:void 0}},resetArElements:()=>ye()}}),{recordPhoneHeight:Ie,addOrUpdateArPlane:Le,startEventArea:Re,addCornerToEventArea:ze,correctArDriftForEventArea:Be,finishEventArea:Ve,anchorEventAreaInWorldSpace:He,resetArElements:Ue}=Fe.actions,We=p(Ie),Ge=p(Le),Ke=p(Re),qe=p(ze),Je=p(Be),Ye=p(Ve),Xe=p(He),Ze=p(Ue),Qe=m(Fe.reducer);function $e(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),rt(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),rt(s,t[n]),o.subtract(c,s,a),f+=o.length(c);return{inCentroid:i,refCentroid:a,scaleRatio:d===0?1:f/d}}function et(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 tt(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}=$e(e,t,c,{inCentroid:o.create(),refCentroid:o.create(),refVec:o.create(),tmp:o.create()}),m=a.create();s?new nt(l).solve(e,t,d,f,m,u):a.identity(m);let h={negCentroid:o.create(),scaleVec:o.create()};return et(i.create(),d,f,m,p,c,h)}var nt=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]),rt(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 rt=(e,t)=>(e[0]=t[0],e[1]=t[1],e[2]=t[2],e);function it(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 st(s,at(s,t,n,r,i,a,o),i,a)}function at(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){lt(e,n,o,c,l);let{inliers:r,outliers:u}=ot(e,l,i(c),a);if(s===null||n+r.length>=t){let e=[...c,...r],t=i(e),n=ct(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 ot(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 st(e,t,n,r){let i=t??n(e);ct(i,`RANSAC failed to produce a model with totalModelError`);let{inliers:a,outliers:o}=ot(e,null,i,r);return a.length>0&&(i=n(a),ct(i,`createModel must assign totalModelError for final RANSAC model`)),i.inliers=a,i.outliers=o,i}function ct(e,t){let{totalModelError:n}=e;if(n==null)throw Error(t);return n}function lt(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 ut=.08,dt=180/Math.PI,ft=e=>(e%360+360)%360,pt=(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 mt(e){let[t,n,r,i]=e,a=-2*(t*r+i*n),o=-2*(n*r-i*t);return Math.hypot(a,o)<ut?null:ft(Math.atan2(a,o)*dt)}const ht=[0,0,-1];function gt(e,t){return ke(e,Ae(t))}function _t(e,t){let[n,r]=pt(gt(e,t),ht);return Math.hypot(n,r)<ut?null:ft(Math.atan2(n,r)*dt)}function U(e,t){let n=((e-t+180)%360+360)%360-180;return n===-180&&(n=180),n}const vt=Math.PI/180,yt=180/Math.PI,bt=2025,xt=2025,St=2030,Ct=6378137;Ct*(1-1/298.257223563);const wt=[[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 Tt(){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 wt)t.g[e][n]=r,t.h[e][n]=i,t.gdot[e][n]=a,t.hdot[e][n]=o;return t}const W=Tt();function Et(){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=W.g[e][t],r=W.h[e][t],s=W.gdot[e][t],c=W.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 Dt=Et();function Ot(e){return e%4==0&&e%100!=0||e%400==0?366:365}function kt(e){let t=e.getUTCFullYear(),n=Date.UTC(t,0,1);return t+Math.floor((e.getTime()-n)/864e5)/Ot(t)}let At=!1;function jt(e){return e===void 0?2027.5:typeof e==`number`?e>1e4?kt(new Date(e)):e:kt(e)}function Mt(e,t,n){let r=Ct/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 Nt(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 Pt(e,t,n,r){let i=r-bt;(r<2025||r>=2030)&&!At&&(At=!0,console.warn(`magneticDeclinationDeg: date ${r.toFixed(3)} is outside the WMM2025 validity window [${xt}, ${St}); using linear secular extrapolation (accuracy degrades).`));let{snorm:a,k:o,fn:s,fm:c,c:l,cd:u,idx:d}=Dt,f=t*vt,p=e*vt,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}=Mt(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,te=a.slice(),k=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){Nt(te,k,o,d,e,t,S,x);let n=l[d(t,e)]+i*u[d(t,e)],r=E*te[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*k[d(t,e)],ee+=c[t]*f*r,O+=s[e]*a*r}}let A;return A=S===0?0:ee/S,{x:-D*C-O*w,y:A,z:D*w-O*C}}function Ft(e){let t=e%360;return t<0?t+360:t}function It(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}=Pt(e,t,r,jt(n?.date));return Math.atan2(a,i)*yt}function Lt(e,t,n,r){return Ft(e+It(t,n,r))}const G=Math.PI/180,Rt=180/Math.PI,K=e=>(e%360+360)%360,q=e=>e<0?0:e>1?1:e,zt=e=>{let t=0,n=0;for(let r of e)t+=Math.sin(r*G),n+=Math.cos(r*G);return t===0&&n===0?0:K(Math.atan2(t,n)*Rt)},Bt=e=>{if(e.length===0)return 0;let t=zt(e),n=0;for(let r of e){let e=Math.abs(U(r,t));e>n&&(n=e)}return n},Vt=(e,t,n)=>n<=0?+(e<=t):q((t+n-e)/n),Ht=(e,t,n)=>n<=0?+(e>=t):q((e-(t-n))/n),Ut=(e,t,n)=>{if(e.length<n.minWindow)return 0;let r=Vt(Bt(e),n.collapseThresholdDeg,n.rampWidthDeg),i=Ht(t,n.baselineMinM,n.baselineRampM);return Math.min(r,i)},Wt=e=>q(1-e),Gt=(e,t,n)=>{let r=q(n),i=Math.cos(e*G),a=Math.sin(e*G),o=Math.cos(t*G),s=Math.sin(t*G),c=o+(i-o)*r,l=s+(a-s)*r;return K(Math.hypot(c,l)<1e-9?t:Math.atan2(l,c)*Rt)},Kt=(e,t,n)=>{if(e===null)return K(t);let r=q(n);return K(e+U(t,e)*r)},J=e=>K(Math.atan2(e[2],e[0])*Rt),qt=(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=U(n,J(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*G);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),F(f)},Jt=()=>({state:`dormant`,agreeStreak:0,disagreeStreak:0,recommendRecalibration:!1}),Yt=(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}},Xt=e=>e<0?0:e>1?1:e,Zt=e=>+(e===`trusted`),Qt=(e,t,n)=>{let r=Xt(e),i=Xt(t);return Xt(1-r+r*i*n.steadyStateMaxWeight)},$t=180/Math.PI,en=e=>(e%360+360)%360,tn=[0,0,-1],nn=[0,1,0],rn=(e,t)=>{let n=gt(e,t),[r,i]=pt(n,tn),a=Math.hypot(r,i),o=a<.08?null:en(Math.atan2(r,i)*$t),[s,c,l]=pt(n,nn);return{bearingDeg:o,horizontality:a,upDisagreementDeg:Math.atan2(Math.hypot(s,c),l)*$t}},an=(e,t)=>{let n=[],r=0;for(let i of e){let e=rn(i.qSensor,i.qWebxr);Number.isFinite(e.upDisagreementDeg)&&(r+=e.upDisagreementDeg),e.bearingDeg!==null&&e.horizontality>=t.minHorizontality&&n.push(e.bearingDeg)}return{yawSpreadDeg:n.length?Bt(n):NaN,meanUpDisagreementDeg:e.length?r/e.length:NaN,usableCount:n.length,totalCount:e.length}},on=(e,t)=>!(e.totalCount===0||e.usableCount===0||e.usableCount/e.totalCount<t.minUsableFraction||!Number.isFinite(e.yawSpreadDeg)||e.yawSpreadDeg>t.maxYawSpreadDeg||!Number.isFinite(e.meanUpDisagreementDeg)||e.meanUpDisagreementDeg>t.maxUpDisagreementDeg),sn={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,requireCompassWebXRConsistency:!1},cn=e=>e.map(e=>I(e)),ln=e=>e.map(e=>z(e)),un=e=>e.map(er),dn=e=>e.map(e=>[e[0],e[1],e[2],e[3]]),Y=e=>Array.isArray(e)?e:N(e),X=e=>Array.isArray(e)?e:P(e),fn=(e,t,n,r)=>({odometryPosOffset:I(Y(e)),odometryRotOffset:z(X(t)),latestLoopClosureFixPointPos:n?I(Y(n)):null,latestLoopClosureFixPointRot:r?z(X(r)):null}),pn=(e,t,n,r)=>({odometryPositions:[],odometryRotations:[],gpsPositions:[],gpsPositionsVec4:[],alignmentMatrix:[...Ce],alignmentRotation:[...L],alignmentTranslation:[...R],alignmentRotationInDegree:[...R],...fn(e,t,n,r),gpsAccuracyMedian:null,gpsAccuracyMean:null,currentGpsPosGeoHash:null,lastAdmittedOdomPos:null,lastAdmittedTs:null}),mn=()=>pn(R,L,null,null),hn=(e,t,n,r)=>{let i=e.map(e=>Y(e)),a=t.map(e=>z(X(e))),o=n.map(er),s=r.gpsAccuracyExponent;for(let e of o)e.weight=bn(e.latLongAccuracy,s);let c=o.map(Qn),l=r.includeTimeWeight?qn(c,o,r.weightByTimeFactor):c,u=r.useOnlyRecentData?Gn(o,r.recentSeconds):0,d=i.slice(u).map(j),f=o.slice(u);return{allPositionTuples:i,allRotationTuples:a,allGpsPoints:o,allVec4Tuples:l,solverPositionsTyped:d,solverGpsPoints:f,solverWeightedVec4Tuples:l.slice(u),solverVerticalWeights:Kn(f,r)}},gn=(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},_n=(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=Y(e[l]),d=n[l].timestamp;gn(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}},vn=(e,t)=>{let n=e.length-1;return n<0?{lastAdmittedOdomPos:null,lastAdmittedTs:null}:{lastAdmittedOdomPos:I(e[n]),lastAdmittedTs:t[n]?.timestamp??null}},yn=e=>{let{odometryPositions:t,odometryRotations:n,gpsPoints:r,odometryPosOffset:i=R,odometryRotOffset:s=L,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={...sn,...u??{}},p=d??Math.random;if(t.length===0)return pn(i,s,c,l);let m=_n(t,n,r,f),{allPositionTuples:h,allRotationTuples:g,allGpsPoints:_,allVec4Tuples:v,solverPositionsTyped:y,solverGpsPoints:b,solverWeightedVec4Tuples:x,solverVerticalWeights:S}=hn(m.odometryPositions,m.odometryRotations,m.gpsPoints,f),C=Bn(wn(y,x,S,f,p).matrix,y,x,S,_,g,f,p),w=C.matrix,T=a.create(),E=o.create(),D=o.create();Sn(w,T,E,D);let{mean:ee,median:O}=Xn(_),te=Yn(m.gpsPoints,f.geohashPrecision,f.geohashWindowSize),{lastAdmittedOdomPos:k,lastAdmittedTs:A}=vn(h,m.gpsPoints);return{odometryPositions:cn(h),odometryRotations:ln(g),gpsPositions:un(_),gpsPositionsVec4:dn(v),alignmentMatrix:F(w),alignmentRotation:P(T),alignmentTranslation:N(E),alignmentRotationInDegree:N(D),...fn(i,s,c,l),gpsAccuracyMedian:O,gpsAccuracyMean:ee,currentGpsPosGeoHash:te,lastAdmittedOdomPos:k,lastAdmittedTs:A,...C.fields}},bn=(e,t)=>e!=null&&e>0?1/Math.max(e,1)**+t:1,xn=(e,t,n,r,i,s)=>{let c={...sn,...i??{}},l=Y(t);if(c.useDistanceGating&&!gn(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(z(X(n)));let m=er(r);f.push(m),m.weight=bn(m.latLongAccuracy,c.gpsAccuracyExponent);let h=Qn(m);if(c.includeTimeWeight){p.push(h);let e=qn(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=Gn(f,c.recentSeconds));let _=u.slice(g).map(j),v=p.slice(g),y=zn(e,wn(_,v,Kn(f.slice(g),c),c,s??Math.random).matrix,_,v,f,d,c);e.alignmentMatrix=F(y);let b=a.create(),x=o.create(),S=o.create();Sn(y,b,x,S),e.alignmentRotation=P(b),e.alignmentTranslation=N(x),e.alignmentRotationInDegree=N(S);let{mean:C,median:w}=Xn(f);e.gpsAccuracyMean=C,e.gpsAccuracyMedian=w,e.currentGpsPosGeoHash=Yn(f,c.geohashPrecision,c.geohashWindowSize),e.lastAdmittedOdomPos=I(l),e.lastAdmittedTs=r.timestamp},Sn=(e,t,n,r)=>{i.getRotation(t,e),a.normalize(t,t),i.getTranslation(n,e),Zn(t,r)},Z=o.create(),Cn=o.create(),wn=(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=it(c,Math.max(t,Math.min(e,Math.ceil(e*r.ransacInlierRatio))),t,r.ransacMaxIterations,e=>Q(e,r.ignoreYAxisForRotation),(e,t)=>Vn(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}=Wn(c,r);l=e.alignmentMatrix,u=e.meanAlignmentError,d=t}else{let e=Q(c,r.ignoreYAxisForRotation);l=e.alignmentMatrix,u=e.meanAlignmentError}return r.altitudeAlignmentMode===`separate1D`&&Tn(l,c,d,r),{matrix:l,meanError:u}},Tn=(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`?Dn(a,o):En(a,o)},En=(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},Dn=(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]]},On=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},kn=(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},An=(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=_t(i.quaternion,a);if(o===null)continue;let s=((o+It(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:zt(n)},jn=e=>({collapseThresholdDeg:e.coldStartObservabilityCollapseDeg,rampWidthDeg:e.coldStartObservabilityRampDeg,minWindow:e.coldStartObservabilityWindow,baselineMinM:e.coldStartBaselineMinM,baselineRampM:e.coldStartBaselineRampM}),Mn=(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=wn(e.slice(0,c),t.slice(0,c),n.slice(0,c),r,i);s.push(J(a.matrix))}return s},Nn=.5,Pn={agreeToleranceDeg:8,minAgreeStreak:3,dropToleranceDeg:20,recalibrateAfterStreak:4},Fn={minHorizontality:.5,maxYawSpreadDeg:12,maxUpDisagreementDeg:15,minUsableFraction:.5},In=(e,t)=>{let n=[];for(let r=0;r<e.length;r+=1){let i=e[r].absoluteOrientation,a=t[r];i&&a&&n.push({qSensor:i.quaternion,qWebxr:a})}return n.length===0?!1:on(an(n,Fn),Fn)},Ln=(e,t,n,r,i,a,o,s,c)=>{let l=An(r,i);if(l===null)return{matrix:e,appliedBearingDeg:o,trust:s};let u=a.length>0?a[a.length-1]:J(e),d=Ut(a,On(r),jn(c));if(c.requireCompassWebXRConsistency&&d>=Nn&&!In(r,i))return{matrix:e,appliedBearingDeg:o,trust:s};let f,p=s;c.useCompassRotationPrior?(p=Yt(s??Jt(),{gpsYawObservable:d>=Nn,agreementDeltaDeg:U(l,u)},Pn),f=Qt(d,Zt(p.state),{steadyStateMaxWeight:c.compassSteadyStateMaxWeight})):f=Wt(d);let m=Kt(o,Gt(l,u,f),c.coldStartSnapAlpha);return{matrix:be(qt(e,kn(t,n),m)),appliedBearingDeg:m,trust:p}},Rn=e=>e.useCompassColdStartOverride||e.useCompassRotationPrior,zn=(e,t,n,r,i,a,o)=>{if(!Rn(o))return t;let s=e.coldStartYawWindowDeg?[...e.coldStartYawWindowDeg]:[];for(s.push(J(t));s.length>o.coldStartObservabilityWindow;)s.shift();let c=Ln(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},Bn=(e,t,n,r,i,a,o,s)=>{if(!Rn(o))return{matrix:e,fields:{}};let c=Mn(t,n,r,o,s),l=Ln(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}},Q=(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=tt(i,a,{ignoreYAxisForRotation:t}),c=0;for(let e=0;e<r;e+=1)o.transformMat4(Z,i[e],s),c+=Hn(Z,n[e].ref);return{alignmentMatrix:s,meanAlignmentError:r===0?0:c/r,totalModelError:c}},Vn=(e,t)=>(o.transformMat4(Z,t.odom,e.alignmentMatrix),Hn(Z,t.ref)),Hn=(e,t)=>(o.set(Cn,t[0],t[1],t[2]),o.squaredDistance(e,Cn)),Un=(e,t)=>{o.transformMat4(Z,t.odom,e.alignmentMatrix);let n=Z[0]-t.ref[0],r=Z[2]-t.ref[2];return n*n+r*r},Wn=(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=Q(a,t.ignoreYAxisForRotation);for(;a.length>r;){let e=-1,n=-1;for(let t=0;t<a.length;t+=1){let r=Un(o,a[t]);r>n&&(n=r,e=t)}if(n<=i||e<0)break;a=a.filter((t,n)=>n!==e),o=Q(a,t.ignoreYAxisForRotation)}return{model:o,inliers:a}},Gn=(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},Kn=(e,t)=>{let n=t.gpsVerticalAccuracyExponent,r=e.map(e=>{let t=e.altitudeAccuracy;return bn(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)})},qn=(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]})},Jn=new Map,Yn=(e,t,n)=>{if(e.length===0)return null;let r=Math.max(0,e.length-n);Jn.clear();for(let n=r;n<e.length;n+=1){let r=e[n],i=ae($n(r),t),a=Jn.get(i);a?(a.count+=1,a.index=n):Jn.set(i,{count:1,index:n})}let i=null,a=-1,o=-1;for(let[e,{count:t,index:n}]of Jn)(t>a||t===a&&n>o)&&(i=e,a=t,o=n);return i},Xn=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]}},Zn=(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},Qn=e=>[e.coordinates[0],e.coordinates[1],e.coordinates[2],e.weight>0&&Number.isFinite(e.weight)?e.weight:1],$n=e=>({lat:e.latitude,lon:e.longitude}),er=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?z(X(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}),tr=({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}`)},nr=o.fromValues(1,1,1),rr=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],ir=(e,t,n,r)=>{let i=le(t,{lat:e.latitude,lon:e.longitude},e.altitude??0,0),a=n?.alpha!=null&&n?.beta!=null&&n?.gamma!=null?H(Pe(n.alpha,n.beta,n.gamma)):void 0;return{...e,zeroRef:t,coordinates:N(i),weight:1,deviceRotation:a,absoluteOrientation:r}},ar=(e,t,n)=>{if(e)return Pe(e.alpha,e.beta,e.gamma);if(t)return t;throw Error(`Sensor rotation missing for ${n}: neither raw orientation nor legacy quaternion provided`)},or=e=>{let t=a.invert(a.create(),e);if(!t)throw Error(`Encountered non-invertible quaternion`);return t},sr=e=>{let t=or(a.normalize(a.create(),M(e.lastSensorRot))),n=a.normalize(a.create(),M(e.lastValidOdomRot)),r=a.multiply(a.create(),t,n),i=a.normalize(a.create(),M(e.newSensorRot)),o=a.multiply(a.create(),i,r),s=a.normalize(a.create(),M(e.newOdomRot)),c=a.multiply(a.create(),o,s);return a.normalize(c,c),P(c)},cr=(e,t)=>{let n=i.create();return i.fromRotationTranslationScale(n,a.normalize(a.create(),M(t)),j(e),nr),n},lr=(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)},ur=(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=lr(o,a,s<=0?1:t/s);return i.multiply(i.create(),n,e)})},dr=(e,t,n)=>{for(let r=e.length-1;r>=0;--r)if(n(e[r],t))return r;return-1},fr=e=>{let t={};return e.coldStartOverrideEnabled&&(t.useCompassColdStartOverride=!0),e.compassRotationPriorEnabled&&(t.useCompassRotationPrior=!0),e.compassWebXRConsistencyEnabled&&(t.requireCompassWebXRConsistency=!0),Object.keys(t).length>0?t:void 0},pr=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2],mr=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]&&e[3]===t[3],hr=t({name:`gpsData`,initialState:null,reducers:{setZeroPos:{reducer:(e,t)=>e===null?{zero:t.payload,gpsEvents:mn(),odometryPath:_e()}:e,prepare:e=>(tr(e),{payload:e})},recordGpsEvent:(e,t)=>{if(!e)return e;let{odomPosition:n,odomRotation:r,rawGpsPoint:i,rawDeviceOrientation:a,rawAbsoluteOrientation:o}=t.payload,s=ir(i,e.zero,a,o);xn(e.gpsEvents,B(n),V(r),s,fr(e))},setColdStartOverrideEnabled:(e,t)=>{if(!e)return e;e.coldStartOverrideEnabled=t.payload},setCompassRotationPriorEnabled:(e,t)=>{if(!e)return e;e.compassRotationPriorEnabled=t.payload},setCompassWebXRConsistencyEnabled:(e,t)=>{if(!e)return e;e.compassWebXRConsistencyEnabled=t.payload},odometryTrackingRestarted:(e,t)=>{if(!e)return e;let n=rr(e.gpsEvents.odometryPosOffset,B(t.payload.lastValidOdomPos)),r=ar(t.payload.lastSensorOrientation,t.payload.lastSensorRot,`lastSensor`),i=ar(t.payload.newSensorOrientation,t.payload.newSensorRot,`newSensor`);e.gpsEvents=c(yn({odometryPositions:[],odometryRotations:[],gpsPoints:[],odometryPosOffset:n,odometryRotOffset:sr({...t.payload,lastValidOdomRot:V(t.payload.lastValidOdomRot),newOdomRot:V(t.payload.newOdomRot),lastSensorRot:H(r),newSensorRot:H(i)}),latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null,alignmentConfig:fr(e)}))},arLoopClosureDetected:(e,t)=>{if(!e)return e;let n=e.gpsEvents;if(n.odometryPositions.length===0)return e;let r=n.latestLoopClosureFixPointPos?dr(n.odometryPositions,n.latestLoopClosureFixPointPos,pr):0,s=n.latestLoopClosureFixPointRot?dr(n.odometryRotations,n.latestLoopClosureFixPointRot,mr):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=>I(e)),u=n.odometryRotations.slice(0,r).map(e=>z(e)),d=n.odometryPositions.slice(r).map(e=>I(e)),f=n.odometryRotations.slice(r).map(e=>z(e)),p=d.map((e,t)=>cr(e,f[t])),m=cr(B(t.payload.lastPos),z(V(t.payload.lastRot)));p.push(m);let h=ur(p,cr(B(t.payload.newPos),z(V(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(N(n)),_.push(P(r))}e.gpsEvents=c(yn({odometryPositions:l.concat(g),odometryRotations:u.concat(_),gpsPoints:n.gpsPositions,odometryPosOffset:n.odometryPosOffset,odometryRotOffset:n.odometryRotOffset,latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null,alignmentConfig:fr(e)}))},add2dImage:(e,t)=>{if(!e)return e;e.odometryPath.points.push(c({imageFile:t.payload.imageFile,screenRotation:t.payload.screenRotation,position:B(t.payload.position),rotation:z(V(t.payload.rotation)),capturedAt:t.payload.capturedAt,width:t.payload.width,height:t.payload.height}))}}}),{setZeroPos:gr,recordGpsEvent:_r,odometryTrackingRestarted:vr,arLoopClosureDetected:yr,add2dImage:br,setColdStartOverrideEnabled:xr,setCompassRotationPriorEnabled:Sr,setCompassWebXRConsistencyEnabled:Cr}=hr.actions,wr=p(gr),Tr=p(_r),Er=p(vr),Dr=p(yr),Or=p(br),kr=p(xr),Ar=p(Sr),jr=p(Cr),Mr=m(hr.reducer),Nr=t({name:`gpsElements`,initialState:ve(),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:()=>ve()}}),{addMarker:Pr,addLine:Fr,addArea:Ir,addToHeatMaps:Lr,addHeatMapArea:Rr,resetGpsElements:zr}=Nr.actions,Br=p(Pr),Vr=p(Fr),Hr=p(Ir),Ur=p(Lr),Wr=p(Rr),Gr=p(zr),Kr=m(Nr.reducer),qr=()=>({gpsData:null,gpsElements:ve(),arElements:ye()}),Jr=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},Yr=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 Yr(e)?Jr(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},Xr=(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=qr(),s=n?{gpsData:n.gpsData??o.gpsData,gpsElements:n.gpsElements??o.gpsElements,arElements:n.arElements??o.arElements}:void 0;return e({reducer:{gpsData:Mr,gpsElements:Kr,arElements:Qe},preloadedState:s,middleware:e=>e({serializableCheck:i,immutableCheck:i}),devTools:r?{actionSanitizer:$,stateSanitizer:$}:!0})},Zr=[],Qr=[],$r=[],ei={median:null,mean:null},ti=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentMatrix}),ni=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentRotation}),ri=f(function(e){return e.gpsData?.gpsEvents?.odometryPositions??Zr}),ii=f(function(e){return e.gpsData?.gpsEvents?.odometryRotations??Qr}),ai=f(function(e){return e.gpsData?.gpsEvents?.gpsPositions??$r}),oi=f(function(e){return e.gpsData?.zero??null}),si=f(function(e){let t=e.gpsData?.gpsEvents?.gpsAccuracyMedian??null,n=e.gpsData?.gpsEvents?.gpsAccuracyMean??null;return t===null&&n===null?ei:{median:t,mean:n}}),ci=`1.0.0`;export{Ce as IDENTITY_MATRIX4,L as IDENTITY_QUATERNION,ci as LIB_VERSION,bt as WMM2025_EPOCH,xt as WMM2025_VALID_FROM,St as WMM2025_VALID_TO,R as ZERO_VECTOR3,Or as add2dImage,Hr as addArea,qe as addCornerToEventArea,Wr as addHeatMapArea,Vr as addLine,Br as addMarker,Ge as addOrUpdateArPlane,Ur as addToHeatMaps,Xe as anchorEventAreaInWorldSpace,Qe as arElementsReducer,Dr as arLoopClosureDetected,_t as arNorthBearingDeg,gt as arToEnuRotation,U as bearingDeltaDeg,ae as calcGeoHash,ue as calcGpsCoords,re as calcQuadKey,le as calcRelativeCoordsInMeters,Se as cloneMatrix4,xe as cloneQuaternion,I as cloneVector3,Je as correctArDriftForEventArea,Xr as createGpsSlamStore,se as distanceInMeters,ce as distanceInMetersRelative,H as enuQuaternionToNUE,Pe as eulerToQuaternion,Ye as finishEventArea,be as fromMatrix4,M as fromQuaternion,j as fromVector3,ge as fusedGpsFromOdom,oe as geoHashToLatLong,ti as getAlignmentMatrix,ni as getAlignmentRotation,me as getGoogleMapsDirectionsLink,pe as getGoogleMapsLink,si as getGpsAccuracyStats,ai as getGpsPositions,ri as getOdometryPositions,ii as getOdometryRotations,he as getOpenStreetMapLink,oi as getZeroReference,Mr as gpsDataReducer,Kr as gpsElementsReducer,Ae as invertQuaternion,we as isIdentityMatrix4,Ee as isIdentityQuaternion,De as isNearIdentityQuaternion,It as magneticDeclinationDeg,mt as magneticHeadingFromEnuQuat,Lt as magneticToTrueHeadingDeg,ke as multiplyQuaternions,z as normalizeQuaternion,Ne as nueQuaternionToENU,Me as nueQuaternionToWebXR,je as nueToWebXR,Er as odometryTrackingRestarted,ie as quadKeyToLatLong,Te as quaternionMagnitude,Oe as quaternionsEquivalent,Tr as recordGpsEvent,We as recordPhoneHeight,Ze as resetArElements,Gr as resetGpsElements,$ as sanitizeForDevTools,kr as setColdStartOverrideEnabled,Ar as setCompassRotationPriorEnabled,jr as setCompassWebXRConsistencyEnabled,wr as setZeroPos,Ke as startEventArea,de as toEarthCenteredCoordinates,F as toMatrix4,P as toQuaternion,N as toVector3,g as validateLicenseKey,V as webxrQuaternionToNUE,B 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 = "eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODE0MDQ4ODExfQ.93uD-XHsPVXAAVkr163KYmYcRxMXpi4qkdntamr9kUWsU9q5-zb67ptgISNOOfdLDJnejod4auPokrYlF1zqBQ";
38
+ declare const COMMUNITY_LICENSE_KEY = "eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODE0MDk4ODkzfQ.SvCD62PM1LLzQIh-OXH-EjiuU8luhnNzkbmuk7KzJNlBJaUvchV-0hXvxYviH-xCQ1QLy6HuMjq4Z8HSGZbGAA";
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=`eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODE0MDQ4ODExfQ.93uD-XHsPVXAAVkr163KYmYcRxMXpi4qkdntamr9kUWsU9q5-zb67ptgISNOOfdLDJnejod4auPokrYlF1zqBQ`;export{e as COMMUNITY_LICENSE_KEY};
2
+ const e=`eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODE0MDk4ODkzfQ.SvCD62PM1LLzQIh-OXH-EjiuU8luhnNzkbmuk7KzJNlBJaUvchV-0hXvxYviH-xCQ1QLy6HuMjq4Z8HSGZbGAA`;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.6.0",
3
+ "version": "1.6.2",
4
4
  "description": "TypeScript library for real-time GPS + AR odometry alignment.",
5
5
  "author": "cs-util-com",
6
6
  "keywords": [