gps-plus-slam-js 1.0.4 → 1.0.5
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/README.md
CHANGED
|
@@ -144,3 +144,16 @@ The open-source companion packages provide a full AR+GPS application framework b
|
|
|
144
144
|
- **gps-plus-slam-recorder** — Reference AR recording application (Apache 2.0)
|
|
145
145
|
|
|
146
146
|
Source: [github.com/cs-util-com/location-based-webxr](https://github.com/cs-util-com/location-based-webxr)
|
|
147
|
+
|
|
148
|
+
## Releasing
|
|
149
|
+
|
|
150
|
+
To prepare a new release version for npm:
|
|
151
|
+
|
|
152
|
+
1. Bump the package version using `pnpm`:
|
|
153
|
+
```bash
|
|
154
|
+
pnpm version patch --no-git-tag-version
|
|
155
|
+
```
|
|
156
|
+
2. Commit the changes, open a PR, and merge it.
|
|
157
|
+
3. Create a new GitHub Release with the new version tag. The GitHub Actions release workflow will automatically re-sign the community license key to ensure a fresh 12-month lifetime and publish the package to npm.
|
|
158
|
+
|
|
159
|
+
_Note: See the internal `npm-publish-guide.md` (and `pnpm prep_new_releases` helper script) for detailed release instructions._
|
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,ee=180/Math.PI,w=`0123456789bcdefghjkmnpqrstuvwxyz`,T=[16,8,4,2,1],E=(e,t,n)=>Math.min(Math.max(e,t),n),te=e=>E(e,-180,180),D=e=>e*C,ne=e=>e*ee,re=e=>{if(!Number.isFinite(e))throw RangeError(`Coordinate values must be finite numbers`);return String(e)},ie=e=>({lat:re(e.lat),lon:re(e.lon)}),ae=(e,t=0)=>{let n=D(e.lat),r=D(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)},oe=f((e,t)=>{if(t<1||t>23)throw RangeError(`levelOfDetail must be between 1 and 23 (inclusive)`);let n=E(e.lat,-85.05112878,85.05112878),r=te(e.lon),i=Math.sin(D(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=E(Math.floor(o/256),0,c),u=E(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}),se=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:ne(Math.atan(Math.sinh(Math.PI*(1-2*c)))),lon:l}}),ce=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|=T[s],i=t):a=t}else{let t=(n+r)/2;e.lat>=t?(c|=T[s],n=t):r=t}l=!l,s<4?s+=1:(o+=w[c],s=0,c=0)}return o}),le=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=w.indexOf(o);if(e===-1)throw Error(`Invalid geohash character: ${o}`);for(let o of T){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}}),ue=f((e,t)=>{let n=D(e.lat),r=D(t.lat),i=r-n,a=D(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)))}),de=f((e,t)=>{let n=O(e,t);return Math.hypot(n[0],n[2])}),O=f((e,t,n=0,r=0)=>{let i=(t.lon-e.lon)*x*Math.cos(D(e.lat)),a=(t.lat-e.lat)*S,s=n-r;return o.fromValues(a,s,i)}),k=f((e,t)=>{let n=t[0],r=t[2];return{lat:n/S+e.lat,lon:r/(x*Math.cos(D(e.lat)))+e.lon}}),fe=f((e,t=0)=>ae(e,t)),A=e=>{let{lat:t,lon:n}=ie(e);return`${t}%2C${n}`},pe=f(e=>`https://www.google.com/maps/search/?api=1&query=${A(e)}`),me=f((e,t)=>`https://www.google.com/maps/dir/?api=1&origin=${A(t)}&destination=${A(e)}`),he=f((e,t=19)=>{let{lat:n,lon:r}=ie(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}=k(n,s);return{lat:c,lon:l,altitude:s[1]}}),_e=()=>({points:[]}),j=()=>({gpsMarkers:[],gpsLines:[],areas:[],heatMap:{},heatAreas:{}}),M=()=>({arPlanes:{},floorDetections:[],eventAreas:[],currentEventAreaId:null,currentEventAreaPoints:[]}),N=e=>o.fromValues(e[0],e[1],e[2]),P=e=>a.fromValues(e[0],e[1],e[2],e[3]),ve=e=>i.fromValues(...e),F=e=>[e[0],e[1],e[2]],I=e=>[e[0],e[1],e[2],e[3]],L=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]],R=e=>[e[0],e[1],e[2]],ye=e=>[e[0],e[1],e[2],e[3]],be=e=>[...e],z=Object.freeze([0,0,0,1]),B=Object.freeze([0,0,0]),V=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),H=e=>{let t=Se(e);if(t===0)return z;let n=1/t;return[e[0]*n,e[1]*n,e[2]*n,e[3]*n]},xe=e=>{for(let t=0;t<16;t++)if(e[t]!==V[t])return!1;return!0},Se=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]+e[3]*e[3]),Ce=e=>e[0]===0&&e[1]===0&&e[2]===0&&e[3]===1,we=(e,t)=>Math.abs(e[0])<t&&Math.abs(e[1])<t&&Math.abs(e[2])<t&&Math.abs(e[3]-1)<t,Te=(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},Ee=(e,t)=>{let n=a.create();return a.multiply(n,e,t),[n[0],n[1],n[2],n[3]]},De=e=>{let t=a.create();return a.invert(t,e),[t[0],t[1],t[2],t[3]]},U=e=>[-e[2],e[1],e[0]],Oe=e=>[e[2],e[1],-e[0]],W=e=>[-e[2],e[1],e[0],e[3]],ke=e=>[e[2],e[1],-e[0],e[3]],G=e=>[e[1],e[2],e[0],e[3]],Ae=e=>[e[2],e[0],e[1],e[3]],K=(e,t,n)=>{if(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(n))throw Error(`eulerToQuaternion: non-finite input (alpha=${e}, beta=${t}, gamma=${n})`);let r=e*Math.PI/180,i=t*Math.PI/180,o=n*Math.PI/180,s=a.create(),c=a.create(),l=a.create();a.setAxisAngle(s,[0,0,1],r),a.setAxisAngle(c,[1,0,0],i),a.setAxisAngle(l,[0,1,0],o);let u=a.create();return a.multiply(u,s,c),a.multiply(u,u,l),[u[0],u[1],u[2],u[3]]},je=t({name:`arElements`,initialState:M(),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(R(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=ve(r),l=s.arPoints.map(e=>{let t=N(e);return k(i,o.transformMat4(o.create(),t,c))});e.eventAreas[a]={...s,isInArSpace:!1,polygon:l,arPoints:void 0}},resetArElements:()=>M()}}),{recordPhoneHeight:Me,addOrUpdateArPlane:Ne,startEventArea:Pe,addCornerToEventArea:Fe,correctArDriftForEventArea:Ie,finishEventArea:Le,anchorEventAreaInWorldSpace:Re,resetArElements:ze}=je.actions,Be=p(Me),Ve=p(Ne),He=p(Pe),Ue=p(Fe),We=p(Ie),Ge=p(Le),Ke=p(Re),qe=p(ze),Je=m(je.reducer);function Ye(e,t,n,r){let{inCentroid:i,refCentroid:a,refVec:s,tmp:c}=r;o.set(i,0,0,0),o.set(a,0,0,0);let l=0;for(let n=0;n<e.length;n++){let r=t[n][3];o.scaleAndAdd(i,i,e[n],r),q(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),q(s,t[n]),o.subtract(c,s,a),f+=o.length(c);return{inCentroid:i,refCentroid:a,scaleRatio:d===0?1:f/d}}function Xe(e,t,n,r,a,s,c){let{negCentroid:l,scaleVec:u}=c;return i.fromRotationTranslation(e,r,n),s&&(o.set(u,a,a,a),i.scale(e,e,u)),o.negate(l,t),i.translate(e,e,l),e}function Ze(e,t,n={}){let r=e.length;if(r!==t.length)throw Error(`Length of the point lists was not equal: ${r} vs ${t.length}`);if(r===0)return i.create();let s=n.solveRotation??!0,c=n.solveScale??!1,l=n.ignoreYAxisForRotation??!1,u=n.rotationIterations??9,{inCentroid:d,refCentroid:f,scaleRatio:p}=Ye(e,t,c,{inCentroid:o.create(),refCentroid:o.create(),refVec:o.create(),tmp:o.create()}),m=a.create();s?new Qe(l).solve(e,t,d,f,m,u):a.identity(m);let h={negCentroid:o.create(),scaleVec:o.create()};return Xe(i.create(),d,f,m,p,c,h)}var Qe=class e{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]),q(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 q=(e,t)=>(e[0]=t[0],e[1]=t[1],e[2]=t[2],e);function $e(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 nt(s,et(s,t,n,r,i,a,o),i,a)}function et(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){it(e,n,o,c,l);let{inliers:r,outliers:u}=tt(e,l,i(c),a);if(s===null||n+r.length>=t){let e=[...c,...r],t=i(e),n=rt(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 tt(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 nt(e,t,n,r){let i=t??n(e);rt(i,`RANSAC failed to produce a model with totalModelError`);let{inliers:a,outliers:o}=tt(e,null,i,r);return a.length>0&&(i=n(a),rt(i,`createModel must assign totalModelError for final RANSAC model`)),i.inliers=a,i.outliers=o,i}function rt(e,t){let{totalModelError:n}=e;if(n==null)throw Error(t);return n}function it(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 at={useOnlyRecentData:!1,recentSeconds:180,includeTimeWeight:!0,weightByTimeFactor:1321,ignoreYAxisForRotation:!0,useRansac:!1,ransacInlierRatio:.95,ransacSampleRatio:.3,ransacMaxIterations:230,ransacErrorTolerance:1,geohashPrecision:8,geohashWindowSize:10,gpsAccuracyExponent:.5},ot=e=>e.map(e=>R(e)),st=e=>e.map(e=>H(e)),ct=e=>e.map(Q),lt=e=>e.map(e=>[e[0],e[1],e[2],e[3]]),J=e=>Array.isArray(e)?e:F(e),Y=e=>Array.isArray(e)?e:I(e),ut=(e,t,n,r)=>({odometryPosOffset:R(J(e)),odometryRotOffset:H(Y(t)),latestLoopClosureFixPointPos:n?R(J(n)):null,latestLoopClosureFixPointRot:r?H(Y(r)):null}),dt=(e,t,n,r)=>({odometryPositions:[],odometryRotations:[],gpsPositions:[],gpsPositionsVec4:[],alignmentMatrix:[...V],alignmentRotation:[...z],alignmentTranslation:[...B],alignmentRotationInDegree:[...B],...ut(e,t,n,r),gpsAccuracyMedian:null,gpsAccuracyMean:null,currentGpsPosGeoHash:null}),ft=()=>dt(B,z,null,null),pt=(e,t,n,r)=>{let i=e.map(e=>J(e)),a=t.map(e=>H(Y(e))),o=n.map(Q),s=r.gpsAccuracyExponent;for(let e of o)e.weight=ht(e.latLongAccuracy,s);let c=o.map(Ot),l=r.includeTimeWeight?wt(c,o,r.weightByTimeFactor):c,u=r.useOnlyRecentData?Ct(o,r.recentSeconds):0;return{allPositionTuples:i,allRotationTuples:a,allGpsPoints:o,allVec4Tuples:l,solverPositionsTyped:i.slice(u).map(N),solverGpsPoints:o.slice(u),solverWeightedVec4Tuples:l.slice(u)}},mt=e=>{let{odometryPositions:t,odometryRotations:n,gpsPoints:r,odometryPosOffset:i=B,odometryRotOffset:s=z,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={...at,...u??{}};if(t.length===0)return dt(i,s,c,l);let{allPositionTuples:p,allRotationTuples:m,allGpsPoints:h,allVec4Tuples:g,solverPositionsTyped:_,solverGpsPoints:v,solverWeightedVec4Tuples:y}=pt(t,n,r,f),b=yt(_,y,f,d??Math.random),x=a.create(),S=o.create(),C=o.create();_t(b.matrix,x,S,C);let{mean:ee,median:w}=Et(h),T=Tt(r,f.geohashPrecision,f.geohashWindowSize);return{odometryPositions:ot(p),odometryRotations:st(m),gpsPositions:ct(h),gpsPositionsVec4:lt(g),alignmentMatrix:L(b.matrix),alignmentRotation:I(x),alignmentTranslation:F(S),alignmentRotationInDegree:F(C),...ut(i,s,c,l),gpsAccuracyMedian:w,gpsAccuracyMean:ee,currentGpsPosGeoHash:T}},ht=(e,t)=>e!=null&&e>0?1/Math.max(e,1)**+t:1,gt=(e,t,n,r,i,s)=>{let c=e.odometryPositions,l=e.odometryRotations,u=e.gpsPositions,d=e.gpsPositionsVec4;c.push(J(t)),l.push(H(Y(n)));let f=Q(r);u.push(f);let p={...at,...i??{}};f.weight=ht(f.latLongAccuracy,p.gpsAccuracyExponent);let m=Ot(f);if(p.includeTimeWeight){d.push(m);let e=wt(d,u,p.weightByTimeFactor);for(let t=0;t<e.length;t++)d[t]=e[t]}else d.push(m);let h=0;p.useOnlyRecentData&&(h=Ct(u,p.recentSeconds));let g=yt(c.slice(h).map(N),d.slice(h),p,s??Math.random);e.alignmentMatrix=L(g.matrix);let _=a.create(),v=o.create(),y=o.create();_t(g.matrix,_,v,y),e.alignmentRotation=I(_),e.alignmentTranslation=F(v),e.alignmentRotationInDegree=F(y);let{mean:b,median:x}=Et(u);e.gpsAccuracyMean=b,e.gpsAccuracyMedian=x,e.currentGpsPosGeoHash=Tt(u,p.geohashPrecision,p.geohashWindowSize)},_t=(e,t,n,r)=>{i.getRotation(t,e),a.normalize(t,t),i.getTranslation(n,e),Dt(t,r)},X=o.create(),vt=o.create(),yt=(e,t,n,r)=>{if(e.length===0)return{matrix:i.create(),meanError:0};let a=e.length,o=[];for(let n=0;n<a;n+=1){let r=t[n];o.push({odom:e[n],ref:s.fromValues(r[0],r[1],r[2],r[3])})}if(n.useRansac&&o.length>=3){let e=o.length,t=Math.max(3,Math.min(e,Math.ceil(e*n.ransacSampleRatio))),i=$e(o,Math.max(t,Math.min(e,Math.ceil(e*n.ransacInlierRatio))),t,n.ransacMaxIterations,e=>bt(e,n.ignoreYAxisForRotation),(e,t)=>xt(e,t)<e.meanAlignmentError+n.ransacErrorTolerance,r);return{matrix:i.alignmentMatrix,meanError:i.meanAlignmentError}}let c=bt(o,n.ignoreYAxisForRotation);return{matrix:c.alignmentMatrix,meanError:c.meanAlignmentError}},bt=(e,t)=>{let n=Array.from(e),r=n.length,i=Array(r),a=Array(r);for(let e=0;e<r;e+=1)i[e]=n[e].odom,a[e]=n[e].ref;let s=Ze(i,a,{ignoreYAxisForRotation:t}),c=0;for(let e=0;e<r;e+=1)o.transformMat4(X,i[e],s),c+=St(X,n[e].ref);return{alignmentMatrix:s,meanAlignmentError:r===0?0:c/r,totalModelError:c}},xt=(e,t)=>(o.transformMat4(X,t.odom,e.alignmentMatrix),St(X,t.ref)),St=(e,t)=>(o.set(vt,t[0],t[1],t[2]),o.squaredDistance(e,vt)),Ct=(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},wt=(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,c=1/(1/(s>0&&Number.isFinite(s)?s:1)+o);return[e[0],e[1],e[2],c]})},Z=new Map,Tt=(e,t,n)=>{if(e.length===0)return null;let r=Math.max(0,e.length-n);Z.clear();for(let n=r;n<e.length;n+=1){let r=e[n],i=ce(kt(r),t),a=Z.get(i);a?(a.count+=1,a.index=n):Z.set(i,{count:1,index:n})}let i=null,a=-1,o=-1;for(let[e,{count:t,index:n}]of Z)(t>a||t===a&&n>o)&&(i=e,a=t,o=n);return i},Et=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]}},Dt=(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},Ot=e=>[e.coordinates[0],e.coordinates[1],e.coordinates[2],e.weight>0&&Number.isFinite(e.weight)?e.weight:1],kt=e=>({lat:e.latitude,lon:e.longitude}),Q=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?H(Y(e.deviceRotation)):void 0}),At=({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}`)},jt=o.fromValues(1,1,1),Mt=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],Nt=(e,t,n)=>{let r=O(t,{lat:e.latitude,lon:e.longitude},e.altitude??0,0),i=n?.alpha!=null&&n?.beta!=null&&n?.gamma!=null?G(K(n.alpha,n.beta,n.gamma)):void 0;return{...e,zeroRef:t,coordinates:F(r),weight:1,deviceRotation:i}},Pt=(e,t,n)=>{if(e)return K(e.alpha,e.beta,e.gamma);if(t)return t;throw Error(`Sensor rotation missing for ${n}: neither raw orientation nor legacy quaternion provided`)},Ft=e=>{let t=a.invert(a.create(),e);if(!t)throw Error(`Encountered non-invertible quaternion`);return t},It=e=>{let t=Ft(a.normalize(a.create(),P(e.lastSensorRot))),n=a.normalize(a.create(),P(e.lastValidOdomRot)),r=a.multiply(a.create(),t,n),i=a.normalize(a.create(),P(e.newSensorRot)),o=a.multiply(a.create(),i,r),s=a.normalize(a.create(),P(e.newOdomRot)),c=a.multiply(a.create(),o,s);return a.normalize(c,c),I(c)},Lt=(e,t)=>{let n=i.create();return i.fromRotationTranslationScale(n,a.normalize(a.create(),P(t)),N(e),jt),n},Rt=(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)},zt=(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=Rt(o,a,s<=0?1:t/s);return i.multiply(i.create(),n,e)})},Bt=(e,t,n)=>{for(let r=e.length-1;r>=0;--r)if(n(e[r],t))return r;return-1},Vt=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2],Ht=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]&&e[3]===t[3],Ut=t({name:`gpsData`,initialState:null,reducers:{setZeroPos:{reducer:(e,t)=>e===null?{zero:t.payload,gpsEvents:ft(),odometryPath:_e(),referencePoints:[]}:e,prepare:e=>(At(e),{payload:e})},recordGpsEvent:(e,t)=>{if(!e)return e;let{odomPosition:n,odomRotation:r,rawGpsPoint:i,rawDeviceOrientation:a}=t.payload,o=Nt(i,e.zero,a);gt(e.gpsEvents,U(n),W(r),o)},odometryTrackingRestarted:(e,t)=>{if(!e)return e;let n=Mt(e.gpsEvents.odometryPosOffset,U(t.payload.lastValidOdomPos)),r=Pt(t.payload.lastSensorOrientation,t.payload.lastSensorRot,`lastSensor`),i=Pt(t.payload.newSensorOrientation,t.payload.newSensorRot,`newSensor`);e.gpsEvents=c(mt({odometryPositions:[],odometryRotations:[],gpsPoints:[],odometryPosOffset:n,odometryRotOffset:It({...t.payload,lastValidOdomRot:W(t.payload.lastValidOdomRot),newOdomRot:W(t.payload.newOdomRot),lastSensorRot:G(r),newSensorRot:G(i)}),latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null}))},arLoopClosureDetected:(e,t)=>{if(!e)return e;let n=e.gpsEvents;if(n.odometryPositions.length===0)return e;let r=n.latestLoopClosureFixPointPos?Bt(n.odometryPositions,n.latestLoopClosureFixPointPos,Vt):0,s=n.latestLoopClosureFixPointRot?Bt(n.odometryRotations,n.latestLoopClosureFixPointRot,Ht):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=>R(e)),u=n.odometryRotations.slice(0,r).map(e=>H(e)),d=n.odometryPositions.slice(r).map(e=>R(e)),f=n.odometryRotations.slice(r).map(e=>H(e)),p=d.map((e,t)=>Lt(e,f[t])),m=Lt(U(t.payload.lastPos),H(W(t.payload.lastRot)));p.push(m);let h=zt(p,Lt(U(t.payload.newPos),H(W(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(F(n)),_.push(I(r))}e.gpsEvents=c(mt({odometryPositions:l.concat(g),odometryRotations:u.concat(_),gpsPoints:n.gpsPositions,odometryPosOffset:n.odometryPosOffset,odometryRotOffset:n.odometryRotOffset,latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null}))},add2dImage:(e,t)=>{if(!e)return e;e.odometryPath.points.push(c({imageFile:t.payload.imageFile,screenRotation:t.payload.screenRotation,position:U(t.payload.position),rotation:H(W(t.payload.rotation)),capturedAt:t.payload.capturedAt}))},markReferencePoint:(e,t)=>{if(!e)return e;let{id:n,position:r,rotation:i,rawGpsPoint:a,timestamp:o}=t.payload,s=Nt(a,e.zero);e.referencePoints.push(c({id:n,position:U(r),rotation:H(W(i)),gpsPoint:Q(s),timestamp:o??Date.now()}))}}}),{setZeroPos:Wt,recordGpsEvent:Gt,odometryTrackingRestarted:Kt,arLoopClosureDetected:qt,add2dImage:Jt,markReferencePoint:Yt}=Ut.actions,Xt=p(Wt),Zt=p(Gt),Qt=p(Kt),$t=p(qt),en=p(Jt),tn=p(Yt),nn=m(Ut.reducer),rn=t({name:`gpsElements`,initialState:j(),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:()=>j()}}),{addMarker:an,addLine:on,addArea:sn,addToHeatMaps:cn,addHeatMapArea:ln,resetGpsElements:un}=rn.actions,dn=p(an),fn=p(on),pn=p(sn),mn=p(cn),hn=p(ln),gn=p(un),_n=m(rn.reducer),vn=()=>({gpsData:null,gpsElements:j(),arElements:M()}),yn=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},bn=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 bn(e)?yn(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},xn=(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=vn(),s=n?{gpsData:n.gpsData??o.gpsData,gpsElements:n.gpsElements??o.gpsElements,arElements:n.arElements??o.arElements}:void 0;return e({reducer:{gpsData:nn,gpsElements:_n,arElements:Je},preloadedState:s,middleware:e=>e({serializableCheck:i,immutableCheck:i}),devTools:r?{actionSanitizer:$,stateSanitizer:$}:!0})},Sn=[],Cn=[],wn=[],Tn=[],En={median:null,mean:null},Dn=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentMatrix}),On=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentRotation}),kn=f(function(e){return e.gpsData?.gpsEvents?.odometryPositions??Sn}),An=f(function(e){return e.gpsData?.gpsEvents?.odometryRotations??Cn}),jn=f(function(e){return e.gpsData?.gpsEvents?.gpsPositions??wn}),Mn=f(function(e){return e.gpsData?.referencePoints??Tn}),Nn=f(function(e){return e.gpsData?.zero??null}),Pn=f(function(e){let t=e.gpsData?.gpsEvents?.gpsAccuracyMedian??null,n=e.gpsData?.gpsEvents?.gpsAccuracyMean??null;return t===null&&n===null?En:{median:t,mean:n}}),Fn=`1.0.0`;export{V as IDENTITY_MATRIX4,z as IDENTITY_QUATERNION,Fn as LIB_VERSION,B as ZERO_VECTOR3,en as add2dImage,pn as addArea,Ue as addCornerToEventArea,hn as addHeatMapArea,fn as addLine,dn as addMarker,Ve as addOrUpdateArPlane,mn as addToHeatMaps,Ke as anchorEventAreaInWorldSpace,Je as arElementsReducer,$t as arLoopClosureDetected,ce as calcGeoHash,k as calcGpsCoords,oe as calcQuadKey,O as calcRelativeCoordsInMeters,be as cloneMatrix4,ye as cloneQuaternion,R as cloneVector3,We as correctArDriftForEventArea,xn as createGpsSlamStore,ue as distanceInMeters,de as distanceInMetersRelative,G as enuQuaternionToNUE,K as eulerToQuaternion,Ge as finishEventArea,ve as fromMatrix4,P as fromQuaternion,N as fromVector3,ge as fusedGpsFromOdom,le as geoHashToLatLong,Dn as getAlignmentMatrix,On as getAlignmentRotation,me as getGoogleMapsDirectionsLink,pe as getGoogleMapsLink,Pn as getGpsAccuracyStats,jn as getGpsPositions,kn as getOdometryPositions,An as getOdometryRotations,he as getOpenStreetMapLink,Mn as getReferencePoints,Nn as getZeroReference,nn as gpsDataReducer,_n as gpsElementsReducer,De as invertQuaternion,xe as isIdentityMatrix4,Ce as isIdentityQuaternion,we as isNearIdentityQuaternion,tn as markReferencePoint,Ee as multiplyQuaternions,H as normalizeQuaternion,Ae as nueQuaternionToENU,ke as nueQuaternionToWebXR,Oe as nueToWebXR,Qt as odometryTrackingRestarted,se as quadKeyToLatLong,Se as quaternionMagnitude,Te as quaternionsEquivalent,Zt as recordGpsEvent,Be as recordPhoneHeight,qe as resetArElements,gn as resetGpsElements,$ as sanitizeForDevTools,Xt as setZeroPos,He as startEventArea,fe as toEarthCenteredCoordinates,L as toMatrix4,I as toQuaternion,F as toVector3,g as validateLicenseKey,W as webxrQuaternionToNUE,U 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,ee=180/Math.PI,w=`0123456789bcdefghjkmnpqrstuvwxyz`,T=[16,8,4,2,1],E=(e,t,n)=>Math.min(Math.max(e,t),n),te=e=>E(e,-180,180),D=e=>e*C,ne=e=>e*ee,re=e=>{if(!Number.isFinite(e))throw RangeError(`Coordinate values must be finite numbers`);return String(e)},ie=e=>({lat:re(e.lat),lon:re(e.lon)}),ae=(e,t=0)=>{let n=D(e.lat),r=D(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)},oe=f((e,t)=>{if(t<1||t>23)throw RangeError(`levelOfDetail must be between 1 and 23 (inclusive)`);let n=E(e.lat,-85.05112878,85.05112878),r=te(e.lon),i=Math.sin(D(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=E(Math.floor(o/256),0,c),u=E(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}),se=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:ne(Math.atan(Math.sinh(Math.PI*(1-2*c)))),lon:l}}),ce=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|=T[s],i=t):a=t}else{let t=(n+r)/2;e.lat>=t?(c|=T[s],n=t):r=t}l=!l,s<4?s+=1:(o+=w[c],s=0,c=0)}return o}),le=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=w.indexOf(o);if(e===-1)throw Error(`Invalid geohash character: ${o}`);for(let o of T){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}}),ue=f((e,t)=>{let n=D(e.lat),r=D(t.lat),i=r-n,a=D(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)))}),de=f((e,t)=>{let n=O(e,t);return Math.hypot(n[0],n[2])}),O=f((e,t,n=0,r=0)=>{let i=(t.lon-e.lon)*x*Math.cos(D(e.lat)),a=(t.lat-e.lat)*S,s=n-r;return o.fromValues(a,s,i)}),k=f((e,t)=>{let n=t[0],r=t[2];return{lat:n/S+e.lat,lon:r/(x*Math.cos(D(e.lat)))+e.lon}}),fe=f((e,t=0)=>ae(e,t)),A=e=>{let{lat:t,lon:n}=ie(e);return`${t}%2C${n}`},pe=f(e=>`https://www.google.com/maps/search/?api=1&query=${A(e)}`),me=f((e,t)=>`https://www.google.com/maps/dir/?api=1&origin=${A(t)}&destination=${A(e)}`),he=f((e,t=19)=>{let{lat:n,lon:r}=ie(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}=k(n,s);return{lat:c,lon:l,altitude:s[1]}}),_e=()=>({points:[]}),j=()=>({gpsMarkers:[],gpsLines:[],areas:[],heatMap:{},heatAreas:{}}),M=()=>({arPlanes:{},floorDetections:[],eventAreas:[],currentEventAreaId:null,currentEventAreaPoints:[]}),N=e=>o.fromValues(e[0],e[1],e[2]),P=e=>a.fromValues(e[0],e[1],e[2],e[3]),ve=e=>i.fromValues(...e),F=e=>[e[0],e[1],e[2]],I=e=>[e[0],e[1],e[2],e[3]],L=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]],R=e=>[e[0],e[1],e[2]],ye=e=>[e[0],e[1],e[2],e[3]],be=e=>[...e],z=Object.freeze([0,0,0,1]),B=Object.freeze([0,0,0]),V=Object.freeze([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),H=e=>{let t=Se(e);if(t===0)return z;let n=1/t;return[e[0]*n,e[1]*n,e[2]*n,e[3]*n]},xe=e=>{for(let t=0;t<16;t++)if(e[t]!==V[t])return!1;return!0},Se=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]+e[3]*e[3]),Ce=e=>e[0]===0&&e[1]===0&&e[2]===0&&e[3]===1,we=(e,t)=>Math.abs(e[0])<t&&Math.abs(e[1])<t&&Math.abs(e[2])<t&&Math.abs(e[3]-1)<t,Te=(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},Ee=(e,t)=>{let n=a.create();return a.multiply(n,e,t),[n[0],n[1],n[2],n[3]]},De=e=>{let t=a.create();return a.invert(t,e),[t[0],t[1],t[2],t[3]]},U=e=>[-e[2],e[1],e[0]],Oe=e=>[e[2],e[1],-e[0]],W=e=>[-e[2],e[1],e[0],e[3]],ke=e=>[e[2],e[1],-e[0],e[3]],G=e=>[e[1],e[2],e[0],e[3]],Ae=e=>[e[2],e[0],e[1],e[3]],K=(e,t,n)=>{if(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(n))throw Error(`eulerToQuaternion: non-finite input (alpha=${e}, beta=${t}, gamma=${n})`);let r=e*Math.PI/180,i=t*Math.PI/180,o=n*Math.PI/180,s=a.create(),c=a.create(),l=a.create();a.setAxisAngle(s,[0,0,1],r),a.setAxisAngle(c,[1,0,0],i),a.setAxisAngle(l,[0,1,0],o);let u=a.create();return a.multiply(u,s,c),a.multiply(u,u,l),[u[0],u[1],u[2],u[3]]},je=t({name:`arElements`,initialState:M(),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(R(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=ve(r),l=s.arPoints.map(e=>{let t=N(e);return k(i,o.transformMat4(o.create(),t,c))});e.eventAreas[a]={...s,isInArSpace:!1,polygon:l,arPoints:void 0}},resetArElements:()=>M()}}),{recordPhoneHeight:Me,addOrUpdateArPlane:Ne,startEventArea:Pe,addCornerToEventArea:Fe,correctArDriftForEventArea:Ie,finishEventArea:Le,anchorEventAreaInWorldSpace:Re,resetArElements:ze}=je.actions,Be=p(Me),Ve=p(Ne),He=p(Pe),Ue=p(Fe),We=p(Ie),Ge=p(Le),Ke=p(Re),qe=p(ze),Je=m(je.reducer);function Ye(e,t,n,r){let{inCentroid:i,refCentroid:a,refVec:s,tmp:c}=r;o.set(i,0,0,0),o.set(a,0,0,0);let l=0;for(let n=0;n<e.length;n++){let r=t[n][3];o.scaleAndAdd(i,i,e[n],r),q(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),q(s,t[n]),o.subtract(c,s,a),f+=o.length(c);return{inCentroid:i,refCentroid:a,scaleRatio:d===0?1:f/d}}function Xe(e,t,n,r,a,s,c){let{negCentroid:l,scaleVec:u}=c;return i.fromRotationTranslation(e,r,n),s&&(o.set(u,a,a,a),i.scale(e,e,u)),o.negate(l,t),i.translate(e,e,l),e}function Ze(e,t,n={}){let r=e.length;if(r!==t.length)throw Error(`Length of the point lists was not equal: ${r} vs ${t.length}`);if(r===0)return i.create();let s=n.solveRotation??!0,c=n.solveScale??!1,l=n.ignoreYAxisForRotation??!1,u=n.rotationIterations??9,{inCentroid:d,refCentroid:f,scaleRatio:p}=Ye(e,t,c,{inCentroid:o.create(),refCentroid:o.create(),refVec:o.create(),tmp:o.create()}),m=a.create();s?new Qe(l).solve(e,t,d,f,m,u):a.identity(m);let h={negCentroid:o.create(),scaleVec:o.create()};return Xe(i.create(),d,f,m,p,c,h)}var Qe=class e{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]),q(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 q=(e,t)=>(e[0]=t[0],e[1]=t[1],e[2]=t[2],e);function $e(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 nt(s,et(s,t,n,r,i,a,o),i,a)}function et(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){it(e,n,o,c,l);let{inliers:r,outliers:u}=tt(e,l,i(c),a);if(s===null||n+r.length>=t){let e=[...c,...r],t=i(e),n=rt(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 tt(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 nt(e,t,n,r){let i=t??n(e);rt(i,`RANSAC failed to produce a model with totalModelError`);let{inliers:a,outliers:o}=tt(e,null,i,r);return a.length>0&&(i=n(a),rt(i,`createModel must assign totalModelError for final RANSAC model`)),i.inliers=a,i.outliers=o,i}function rt(e,t){let{totalModelError:n}=e;if(n==null)throw Error(t);return n}function it(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 at={useOnlyRecentData:!1,recentSeconds:180,includeTimeWeight:!0,weightByTimeFactor:800,ignoreYAxisForRotation:!0,useRansac:!1,ransacInlierRatio:.95,ransacSampleRatio:.3,ransacMaxIterations:230,ransacErrorTolerance:1,geohashPrecision:8,geohashWindowSize:10,gpsAccuracyExponent:.1},ot=e=>e.map(e=>R(e)),st=e=>e.map(e=>H(e)),ct=e=>e.map(Q),lt=e=>e.map(e=>[e[0],e[1],e[2],e[3]]),J=e=>Array.isArray(e)?e:F(e),Y=e=>Array.isArray(e)?e:I(e),ut=(e,t,n,r)=>({odometryPosOffset:R(J(e)),odometryRotOffset:H(Y(t)),latestLoopClosureFixPointPos:n?R(J(n)):null,latestLoopClosureFixPointRot:r?H(Y(r)):null}),dt=(e,t,n,r)=>({odometryPositions:[],odometryRotations:[],gpsPositions:[],gpsPositionsVec4:[],alignmentMatrix:[...V],alignmentRotation:[...z],alignmentTranslation:[...B],alignmentRotationInDegree:[...B],...ut(e,t,n,r),gpsAccuracyMedian:null,gpsAccuracyMean:null,currentGpsPosGeoHash:null}),ft=()=>dt(B,z,null,null),pt=(e,t,n,r)=>{let i=e.map(e=>J(e)),a=t.map(e=>H(Y(e))),o=n.map(Q),s=r.gpsAccuracyExponent;for(let e of o)e.weight=ht(e.latLongAccuracy,s);let c=o.map(Ot),l=r.includeTimeWeight?wt(c,o,r.weightByTimeFactor):c,u=r.useOnlyRecentData?Ct(o,r.recentSeconds):0;return{allPositionTuples:i,allRotationTuples:a,allGpsPoints:o,allVec4Tuples:l,solverPositionsTyped:i.slice(u).map(N),solverGpsPoints:o.slice(u),solverWeightedVec4Tuples:l.slice(u)}},mt=e=>{let{odometryPositions:t,odometryRotations:n,gpsPoints:r,odometryPosOffset:i=B,odometryRotOffset:s=z,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={...at,...u??{}};if(t.length===0)return dt(i,s,c,l);let{allPositionTuples:p,allRotationTuples:m,allGpsPoints:h,allVec4Tuples:g,solverPositionsTyped:_,solverGpsPoints:v,solverWeightedVec4Tuples:y}=pt(t,n,r,f),b=yt(_,y,f,d??Math.random),x=a.create(),S=o.create(),C=o.create();_t(b.matrix,x,S,C);let{mean:ee,median:w}=Et(h),T=Tt(r,f.geohashPrecision,f.geohashWindowSize);return{odometryPositions:ot(p),odometryRotations:st(m),gpsPositions:ct(h),gpsPositionsVec4:lt(g),alignmentMatrix:L(b.matrix),alignmentRotation:I(x),alignmentTranslation:F(S),alignmentRotationInDegree:F(C),...ut(i,s,c,l),gpsAccuracyMedian:w,gpsAccuracyMean:ee,currentGpsPosGeoHash:T}},ht=(e,t)=>e!=null&&e>0?1/Math.max(e,1)**+t:1,gt=(e,t,n,r,i,s)=>{let c=e.odometryPositions,l=e.odometryRotations,u=e.gpsPositions,d=e.gpsPositionsVec4;c.push(J(t)),l.push(H(Y(n)));let f=Q(r);u.push(f);let p={...at,...i??{}};f.weight=ht(f.latLongAccuracy,p.gpsAccuracyExponent);let m=Ot(f);if(p.includeTimeWeight){d.push(m);let e=wt(d,u,p.weightByTimeFactor);for(let t=0;t<e.length;t++)d[t]=e[t]}else d.push(m);let h=0;p.useOnlyRecentData&&(h=Ct(u,p.recentSeconds));let g=yt(c.slice(h).map(N),d.slice(h),p,s??Math.random);e.alignmentMatrix=L(g.matrix);let _=a.create(),v=o.create(),y=o.create();_t(g.matrix,_,v,y),e.alignmentRotation=I(_),e.alignmentTranslation=F(v),e.alignmentRotationInDegree=F(y);let{mean:b,median:x}=Et(u);e.gpsAccuracyMean=b,e.gpsAccuracyMedian=x,e.currentGpsPosGeoHash=Tt(u,p.geohashPrecision,p.geohashWindowSize)},_t=(e,t,n,r)=>{i.getRotation(t,e),a.normalize(t,t),i.getTranslation(n,e),Dt(t,r)},X=o.create(),vt=o.create(),yt=(e,t,n,r)=>{if(e.length===0)return{matrix:i.create(),meanError:0};let a=e.length,o=[];for(let n=0;n<a;n+=1){let r=t[n];o.push({odom:e[n],ref:s.fromValues(r[0],r[1],r[2],r[3])})}if(n.useRansac&&o.length>=3){let e=o.length,t=Math.max(3,Math.min(e,Math.ceil(e*n.ransacSampleRatio))),i=$e(o,Math.max(t,Math.min(e,Math.ceil(e*n.ransacInlierRatio))),t,n.ransacMaxIterations,e=>bt(e,n.ignoreYAxisForRotation),(e,t)=>xt(e,t)<e.meanAlignmentError+n.ransacErrorTolerance,r);return{matrix:i.alignmentMatrix,meanError:i.meanAlignmentError}}let c=bt(o,n.ignoreYAxisForRotation);return{matrix:c.alignmentMatrix,meanError:c.meanAlignmentError}},bt=(e,t)=>{let n=Array.from(e),r=n.length,i=Array(r),a=Array(r);for(let e=0;e<r;e+=1)i[e]=n[e].odom,a[e]=n[e].ref;let s=Ze(i,a,{ignoreYAxisForRotation:t}),c=0;for(let e=0;e<r;e+=1)o.transformMat4(X,i[e],s),c+=St(X,n[e].ref);return{alignmentMatrix:s,meanAlignmentError:r===0?0:c/r,totalModelError:c}},xt=(e,t)=>(o.transformMat4(X,t.odom,e.alignmentMatrix),St(X,t.ref)),St=(e,t)=>(o.set(vt,t[0],t[1],t[2]),o.squaredDistance(e,vt)),Ct=(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},wt=(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,c=1/(1/(s>0&&Number.isFinite(s)?s:1)+o);return[e[0],e[1],e[2],c]})},Z=new Map,Tt=(e,t,n)=>{if(e.length===0)return null;let r=Math.max(0,e.length-n);Z.clear();for(let n=r;n<e.length;n+=1){let r=e[n],i=ce(kt(r),t),a=Z.get(i);a?(a.count+=1,a.index=n):Z.set(i,{count:1,index:n})}let i=null,a=-1,o=-1;for(let[e,{count:t,index:n}]of Z)(t>a||t===a&&n>o)&&(i=e,a=t,o=n);return i},Et=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]}},Dt=(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},Ot=e=>[e.coordinates[0],e.coordinates[1],e.coordinates[2],e.weight>0&&Number.isFinite(e.weight)?e.weight:1],kt=e=>({lat:e.latitude,lon:e.longitude}),Q=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?H(Y(e.deviceRotation)):void 0}),At=({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}`)},jt=o.fromValues(1,1,1),Mt=(e,t)=>[e[0]+t[0],e[1]+t[1],e[2]+t[2]],Nt=(e,t,n)=>{let r=O(t,{lat:e.latitude,lon:e.longitude},e.altitude??0,0),i=n?.alpha!=null&&n?.beta!=null&&n?.gamma!=null?G(K(n.alpha,n.beta,n.gamma)):void 0;return{...e,zeroRef:t,coordinates:F(r),weight:1,deviceRotation:i}},Pt=(e,t,n)=>{if(e)return K(e.alpha,e.beta,e.gamma);if(t)return t;throw Error(`Sensor rotation missing for ${n}: neither raw orientation nor legacy quaternion provided`)},Ft=e=>{let t=a.invert(a.create(),e);if(!t)throw Error(`Encountered non-invertible quaternion`);return t},It=e=>{let t=Ft(a.normalize(a.create(),P(e.lastSensorRot))),n=a.normalize(a.create(),P(e.lastValidOdomRot)),r=a.multiply(a.create(),t,n),i=a.normalize(a.create(),P(e.newSensorRot)),o=a.multiply(a.create(),i,r),s=a.normalize(a.create(),P(e.newOdomRot)),c=a.multiply(a.create(),o,s);return a.normalize(c,c),I(c)},Lt=(e,t)=>{let n=i.create();return i.fromRotationTranslationScale(n,a.normalize(a.create(),P(t)),N(e),jt),n},Rt=(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)},zt=(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=Rt(o,a,s<=0?1:t/s);return i.multiply(i.create(),n,e)})},Bt=(e,t,n)=>{for(let r=e.length-1;r>=0;--r)if(n(e[r],t))return r;return-1},Vt=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2],Ht=(e,t)=>e[0]===t[0]&&e[1]===t[1]&&e[2]===t[2]&&e[3]===t[3],Ut=t({name:`gpsData`,initialState:null,reducers:{setZeroPos:{reducer:(e,t)=>e===null?{zero:t.payload,gpsEvents:ft(),odometryPath:_e(),referencePoints:[]}:e,prepare:e=>(At(e),{payload:e})},recordGpsEvent:(e,t)=>{if(!e)return e;let{odomPosition:n,odomRotation:r,rawGpsPoint:i,rawDeviceOrientation:a}=t.payload,o=Nt(i,e.zero,a);gt(e.gpsEvents,U(n),W(r),o)},odometryTrackingRestarted:(e,t)=>{if(!e)return e;let n=Mt(e.gpsEvents.odometryPosOffset,U(t.payload.lastValidOdomPos)),r=Pt(t.payload.lastSensorOrientation,t.payload.lastSensorRot,`lastSensor`),i=Pt(t.payload.newSensorOrientation,t.payload.newSensorRot,`newSensor`);e.gpsEvents=c(mt({odometryPositions:[],odometryRotations:[],gpsPoints:[],odometryPosOffset:n,odometryRotOffset:It({...t.payload,lastValidOdomRot:W(t.payload.lastValidOdomRot),newOdomRot:W(t.payload.newOdomRot),lastSensorRot:G(r),newSensorRot:G(i)}),latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null}))},arLoopClosureDetected:(e,t)=>{if(!e)return e;let n=e.gpsEvents;if(n.odometryPositions.length===0)return e;let r=n.latestLoopClosureFixPointPos?Bt(n.odometryPositions,n.latestLoopClosureFixPointPos,Vt):0,s=n.latestLoopClosureFixPointRot?Bt(n.odometryRotations,n.latestLoopClosureFixPointRot,Ht):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=>R(e)),u=n.odometryRotations.slice(0,r).map(e=>H(e)),d=n.odometryPositions.slice(r).map(e=>R(e)),f=n.odometryRotations.slice(r).map(e=>H(e)),p=d.map((e,t)=>Lt(e,f[t])),m=Lt(U(t.payload.lastPos),H(W(t.payload.lastRot)));p.push(m);let h=zt(p,Lt(U(t.payload.newPos),H(W(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(F(n)),_.push(I(r))}e.gpsEvents=c(mt({odometryPositions:l.concat(g),odometryRotations:u.concat(_),gpsPoints:n.gpsPositions,odometryPosOffset:n.odometryPosOffset,odometryRotOffset:n.odometryRotOffset,latestLoopClosureFixPointPos:null,latestLoopClosureFixPointRot:null}))},add2dImage:(e,t)=>{if(!e)return e;e.odometryPath.points.push(c({imageFile:t.payload.imageFile,screenRotation:t.payload.screenRotation,position:U(t.payload.position),rotation:H(W(t.payload.rotation)),capturedAt:t.payload.capturedAt}))},markReferencePoint:(e,t)=>{if(!e)return e;let{id:n,position:r,rotation:i,rawGpsPoint:a,timestamp:o}=t.payload,s=Nt(a,e.zero);e.referencePoints.push(c({id:n,position:U(r),rotation:H(W(i)),gpsPoint:Q(s),timestamp:o??Date.now()}))}}}),{setZeroPos:Wt,recordGpsEvent:Gt,odometryTrackingRestarted:Kt,arLoopClosureDetected:qt,add2dImage:Jt,markReferencePoint:Yt}=Ut.actions,Xt=p(Wt),Zt=p(Gt),Qt=p(Kt),$t=p(qt),en=p(Jt),tn=p(Yt),nn=m(Ut.reducer),rn=t({name:`gpsElements`,initialState:j(),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:()=>j()}}),{addMarker:an,addLine:on,addArea:sn,addToHeatMaps:cn,addHeatMapArea:ln,resetGpsElements:un}=rn.actions,dn=p(an),fn=p(on),pn=p(sn),mn=p(cn),hn=p(ln),gn=p(un),_n=m(rn.reducer),vn=()=>({gpsData:null,gpsElements:j(),arElements:M()}),yn=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},bn=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 bn(e)?yn(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},xn=(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=vn(),s=n?{gpsData:n.gpsData??o.gpsData,gpsElements:n.gpsElements??o.gpsElements,arElements:n.arElements??o.arElements}:void 0;return e({reducer:{gpsData:nn,gpsElements:_n,arElements:Je},preloadedState:s,middleware:e=>e({serializableCheck:i,immutableCheck:i}),devTools:r?{actionSanitizer:$,stateSanitizer:$}:!0})},Sn=[],Cn=[],wn=[],Tn=[],En={median:null,mean:null},Dn=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentMatrix}),On=f(function(e){let t=e.gpsData?.gpsEvents;return!t||t.gpsPositions.length===0?null:t.alignmentRotation}),kn=f(function(e){return e.gpsData?.gpsEvents?.odometryPositions??Sn}),An=f(function(e){return e.gpsData?.gpsEvents?.odometryRotations??Cn}),jn=f(function(e){return e.gpsData?.gpsEvents?.gpsPositions??wn}),Mn=f(function(e){return e.gpsData?.referencePoints??Tn}),Nn=f(function(e){return e.gpsData?.zero??null}),Pn=f(function(e){let t=e.gpsData?.gpsEvents?.gpsAccuracyMedian??null,n=e.gpsData?.gpsEvents?.gpsAccuracyMean??null;return t===null&&n===null?En:{median:t,mean:n}}),Fn=`1.0.0`;export{V as IDENTITY_MATRIX4,z as IDENTITY_QUATERNION,Fn as LIB_VERSION,B as ZERO_VECTOR3,en as add2dImage,pn as addArea,Ue as addCornerToEventArea,hn as addHeatMapArea,fn as addLine,dn as addMarker,Ve as addOrUpdateArPlane,mn as addToHeatMaps,Ke as anchorEventAreaInWorldSpace,Je as arElementsReducer,$t as arLoopClosureDetected,ce as calcGeoHash,k as calcGpsCoords,oe as calcQuadKey,O as calcRelativeCoordsInMeters,be as cloneMatrix4,ye as cloneQuaternion,R as cloneVector3,We as correctArDriftForEventArea,xn as createGpsSlamStore,ue as distanceInMeters,de as distanceInMetersRelative,G as enuQuaternionToNUE,K as eulerToQuaternion,Ge as finishEventArea,ve as fromMatrix4,P as fromQuaternion,N as fromVector3,ge as fusedGpsFromOdom,le as geoHashToLatLong,Dn as getAlignmentMatrix,On as getAlignmentRotation,me as getGoogleMapsDirectionsLink,pe as getGoogleMapsLink,Pn as getGpsAccuracyStats,jn as getGpsPositions,kn as getOdometryPositions,An as getOdometryRotations,he as getOpenStreetMapLink,Mn as getReferencePoints,Nn as getZeroReference,nn as gpsDataReducer,_n as gpsElementsReducer,De as invertQuaternion,xe as isIdentityMatrix4,Ce as isIdentityQuaternion,we as isNearIdentityQuaternion,tn as markReferencePoint,Ee as multiplyQuaternions,H as normalizeQuaternion,Ae as nueQuaternionToENU,ke as nueQuaternionToWebXR,Oe as nueToWebXR,Qt as odometryTrackingRestarted,se as quadKeyToLatLong,Se as quaternionMagnitude,Te as quaternionsEquivalent,Zt as recordGpsEvent,Be as recordPhoneHeight,qe as resetArElements,gn as resetGpsElements,$ as sanitizeForDevTools,Xt as setZeroPos,He as startEventArea,fe as toEarthCenteredCoordinates,L as toMatrix4,I as toQuaternion,F as toVector3,g as validateLicenseKey,W as webxrQuaternionToNUE,U 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 = "
|
|
38
|
+
declare const COMMUNITY_LICENSE_KEY = "eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODA5NTA0ODYyfQ.y_V0DcaNmpj6SwBdHOyxrYwIDYwDBPNiM2uBZOlg87CvSA4KtaQl0GTjWi8vT0Sbu5hE_W63FEuoBMi36aJOBw";
|
|
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=`
|
|
2
|
+
const e=`eyJ0eXBlIjoiY29tbXVuaXR5IiwiZXhwIjoxODA5NTA0ODYyfQ.y_V0DcaNmpj6SwBdHOyxrYwIDYwDBPNiM2uBZOlg87CvSA4KtaQl0GTjWi8vT0Sbu5hE_W63FEuoBMi36aJOBw`;export{e as COMMUNITY_LICENSE_KEY};
|