@wemap/geo 14.6.0 → 14.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@wemap/maths")):typeof define==`function`&&define.amd?define([`exports`,`@wemap/maths`],t):(e=typeof globalThis<`u`?globalThis:e||self,t((e.Wemap=e.Wemap||{},e.Wemap.Geo={}),e.Wemap.Maths))})(this,function(e,t){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var n=Object.defineProperty,r=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},i=r({CIRCUMFERENCE:()=>_,EARTH_GRAVITY:()=>s,ECCENTRICITY:()=>d,ECCENTRICITY_2:()=>f,ELLIPSOID_FLATNESS:()=>u,EPS_DEG_MM:()=>c,EPS_MM:()=>l,R_MAJOR:()=>a,R_MAJOR_2:()=>p,R_MAJOR_4:()=>m,R_MINOR:()=>o,R_MINOR_2:()=>h,R_MINOR_4:()=>g,SECOND_ECCENTRICITY_2:()=>v}),a=6378137,o=6356752.314245179,s=9.80665,c=1e-8,l=.001,u=1/298.257223563,d=Math.sqrt(u*(2-u)),f=d*d,p=a*a,m=p*p,h=o*o,g=h*h,_=a*2*Math.PI,v=(p-h)/h,y=class e{static VERIFY_TYPING=!1;static checkType(e){if(e!==null&&!(typeof e==`number`&&!isNaN(e))){if(Array.isArray(e)&&e.length===2){let[t,n]=e;if(typeof t==`number`&&!isNaN(t)&&typeof n==`number`&&!isNaN(n)){if(t>n||t===n)throw Error(`Invalid level range: [${t}, ${n}]`);return}}throw Error(`Unknown level format: ${e}`)}}static isRange(t){return e.VERIFY_TYPING&&e.checkType(t),Array.isArray(t)}static clone(t){return e.VERIFY_TYPING&&e.checkType(t),t===null?null:typeof t==`number`?t:[t[0],t[1]]}static fromString(t){if(t===null)return null;if(typeof t!=`string`||!t.length)throw Error(`argument must be a non empty string, got ${typeof t}`);if(!isNaN(Number(t)))return parseFloat(t);let n=e=>{let n=e.map(e=>Number(e));if(n.some(e=>Number.isNaN(e))||e.some(e=>!e.length))throw Error(`Cannot parse following level: ${t}`);return n},r=t.split(`;`);if(r.length>1){let t=n(r),i=Math.min(...t),a=Math.max(...t);return e.checkType([i,a]),[i,a]}else{let r=t.substring(1).indexOf(`-`)+1;if(r>0){let[i,a]=n([t.substring(0,r),t.substring(r+1)]);return e.checkType([i,a]),[i,a]}}throw Error(`Cannot parse following level: ${t}`)}static parse(t){if(t==null)return null;if(typeof t==`number`){if(Number.isNaN(t))throw Error(`level number must not be NaN`);return t}if(Array.isArray(t)){if(t.length!==2)throw Error(`level range must have exactly 2 elements, got ${t.length}`);let n=[t[0],t[1]];return e.checkType(n),e.clone(n)}if(typeof t==`string`)return e.fromString(t);throw Error(`Cannot parse level from ${typeof t}`)}static contains(t,n){return e.VERIFY_TYPING&&(e.checkType(t),e.checkType(n)),t===n?!0:Array.isArray(t)?Array.isArray(n)?t[0]<=n[0]&&t[1]>=n[1]:n!==null&&t[0]<=n&&t[1]>=n:t===null||n===null?!1:t<=n[0]&&t>=n[1]}static intersection(t,n){if(e.VERIFY_TYPING&&(e.checkType(t),e.checkType(n)),t===null||n===null)return null;if(e.equals(t,n))return e.clone(t);if(typeof t==`number`&&typeof n==`number`)return t===n?t:null;if(Array.isArray(t)&&!Array.isArray(n))return e.contains(t,n)?n:null;if(!Array.isArray(t)&&Array.isArray(n))return e.contains(n,t)?t:null;let r=Math.max(t[0],n[0]),i=Math.min(t[1],n[1]);return i===r?i:i<r?null:[r,i]}static intersect(t,n){return e.VERIFY_TYPING&&(e.checkType(t),e.checkType(n)),t===null&&n===null||e.intersection(t,n)!==null}static union(t,n){if(e.VERIFY_TYPING&&(e.checkType(t),e.checkType(n)),t===n)return e.clone(t);if(n===null||t===null)return null;let r,i;return!Array.isArray(t)&&!Array.isArray(n)?(r=Math.min(t,n),i=Math.max(t,n)):Array.isArray(t)&&!Array.isArray(n)?(r=Math.min(t[0],n),i=Math.max(t[1],n)):!Array.isArray(t)&&Array.isArray(n)?(r=Math.min(n[0],t),i=Math.max(n[1],t)):(r=Math.min(t[0],n[0]),i=Math.max(t[1],n[1])),r===i?r:[r,i]}static multiplyBy(t,n){return e.VERIFY_TYPING&&e.checkType(t),t===null?null:Array.isArray(t)?[t[0]*n,t[1]*n]:t*n}static toString(t){return e.VERIFY_TYPING&&e.checkType(t),t===null?null:Array.isArray(t)?t[0]+`;`+t[1]:String(t)}static equals(t,n){return e.VERIFY_TYPING&&(e.checkType(t),e.checkType(n)),t===n?!0:Array.isArray(t)&&Array.isArray(n)?t[0]===n[0]&&t[1]===n[1]:!1}static diff(t,n){return e.VERIFY_TYPING&&(e.checkType(t),e.checkType(n)),t===null||n===null?null:!Array.isArray(t)&&!Array.isArray(n)?n-t:Array.isArray(t)&&!Array.isArray(n)?t[0]===n?n-t[1]:t[1]===n?n-t[0]:null:Array.isArray(n)&&!Array.isArray(t)?t===n[0]?n[1]-t:t===n[1]?n[0]-t:null:e.equals(t,n)?0:null}};function b(e,n){let r=(0,t.deg2rad)(e),i=(0,t.deg2rad)(n);return{sinLat:Math.sin(r),cosLat:Math.cos(r),sinLng:Math.sin(i),cosLng:Math.cos(i)}}function x(e){return a/Math.sqrt(1-f*e**2)}function S(e){return o/(1-f*e**2)}function C(e,t,n){let{sinLat:r,cosLat:i,sinLng:a,cosLng:o}=b(e,t),s=x(r),c=(s+n)*i;return[c*o,c*a,(s*(1-f)+n)*r]}function w(e){let[n,r,i]=e,s=Math.hypot(n,r),c=Math.atan2(a*i,o*s),l=Math.atan2(i+o*v*Math.sin(c)**3,s-a*f*Math.cos(c)**3),u=Math.sin(l),d=s*Math.cos(l)+i*u-a*Math.sqrt(1-f*u**2);return[(0,t.rad2deg)(l),(0,t.rad2deg)(Math.atan2(r,n)),d]}function T(e,n){let r=(0,t.deg2rad)(e),i=(0,t.deg2rad)(n),a=Math.cos(r);return[a*Math.cos(i),a*Math.sin(i),Math.sin(r)]}function E(e){return[(0,t.rad2deg)(Math.atan2(e[2],Math.hypot(e[0],e[1]))),(0,t.rad2deg)(Math.atan2(e[1],e[0]))]}function D(e,t){return 2*Math.asin(Math.hypot(e[0]-t[0],e[1]-t[1],e[2]-t[2])/2)}var O=class e{_lat;_lng;_alt=null;_level=null;_heightFromFloor=null;_heightFromGround=null;_ecef;_groundEcef=null;autoWrap=!0;constructor(e,t,n=null,r=null){this.lat=e,this.lng=t,this.alt=n,this.level=r,this._ecef=null}get lat(){return this._lat}set lat(e){if(Math.abs(e)<=90)this._lat=e;else throw Error(`lat argument is not in [-90; 90], value is ${e}`);this._ecef=null,this._groundEcef=null}get latitude(){return this._lat}set latitude(e){throw Error(`Please use Coordinates#lat setter instead of Coordinate#latitude`)}get lng(){return this._lng}set lng(e){this._lng=e,this.autoWrap&&this.wrap(),this._ecef=null,this._groundEcef=null}get longitude(){return this._lng}set longitude(e){throw Error(`Please use Coordinates#lng setter instead of Coordinate#longitude`)}get alt(){return this._alt}set alt(e){this._alt=e,this._ecef=null}get level(){return this._level}set level(e){y.checkType(e),this._level=e}get heightFromFloor(){return this._heightFromFloor}set heightFromFloor(e){this._heightFromFloor=e}get heightFromGround(){return this._heightFromGround}set heightFromGround(e){this._heightFromGround=e}clone(){let t=new e(this.lat,this.lng,this.alt);return this.level!==null&&(t.level=y.clone(this.level)),t}wrap(){(this._lng<=-180||this._lng>180)&&(this._lng=(0,t.wrap)(this._lng,-180,180))}static equals(e,t,n=c,r=l){return this.equalsWithoutLevel(e,t,n,r)?e===null||t===null||y.equals(e.level,t.level):!1}equals(t){return e.equals(this,t)}static equalsWithoutLevel(t,n,r=c,i=l){return t===null&&t===n?!0:!(t instanceof e)||!(n instanceof e)?!1:Math.abs(n.lat-t.lat)<r&&Math.abs(n.lng-t.lng)<r&&(t.alt===n.alt||t.alt!==null&&n.alt!==null&&Math.abs(n.alt-t.alt)<i)}equalsWithoutLevel(t,n=c,r=l){return e.equalsWithoutLevel(this,t,n,r)}destinationPoint(e,t,n=null){let r=this.clone();return r.move(e,t,n),r}move(e,t,n=null){let{sinLat:r,cosLat:i,sinLng:a,cosLng:o}=b(this.lat,this.lng),s=S(r),c=e/(2*s),l=2*s*Math.sin(c),u=l*Math.cos(c),d=u*Math.sin(t),p=u*Math.cos(t),m=-l*Math.sin(c),h=x(r),g=h*i,[_,v]=w([g*o-a*d-r*o*p+i*o*m,g*a+o*d-r*a*p+i*a*m,h*(1-f)*r+i*p+r*m]);if(this.lat=_,this.lng=v,n!==null){if(this.alt===null)throw Error(`Point altitude is not defined`);this.alt+=n}return this}distanceTo(e){let[n,r,i]=this.groundEcef,[a,o,s]=e.groundEcef,c=Math.hypot(a-n,o-r,s-i),l=S(Math.sin((0,t.deg2rad)((this.lat+e.lat)/2)));return 2*l*Math.asin(Math.min(1,c/(2*l)))}static distanceBetween(e,t){return e.distanceTo(t)}bearingTo(e){let t=this.groundEcef,n=e.groundEcef,r=n[0]-t[0],i=n[1]-t[1],a=n[2]-t[2],{sinLat:o,cosLat:s,sinLng:c,cosLng:l}=b(this.lat,this.lng),u=-c*r+l*i,d=-o*l*r-o*c*i+s*a;return Math.atan2(u,d)}static bearingTo(e,t){return e.bearingTo(t)}get enuToEcefRotation(){let e=t.Quaternion.fromAxisAngle([0,0,1],Math.PI/2+(0,t.deg2rad)(this.lng)),n=t.Quaternion.fromAxisAngle([1,0,0],Math.PI/2-(0,t.deg2rad)(this.lat));return t.Quaternion.multiply(e,n)}get ecefToEnuRotation(){let e=t.Quaternion.fromAxisAngle([1,0,0],(0,t.deg2rad)(this.lat)-Math.PI/2),n=t.Quaternion.fromAxisAngle([0,0,1],-(0,t.deg2rad)(this.lng)-Math.PI/2);return t.Quaternion.multiply(e,n)}get ecef(){return this._ecef||=C(this.lat,this.lng,this.alt||0),this._ecef}get groundEcef(){return this.alt?(this._groundEcef||=C(this.lat,this.lng,0),this._groundEcef):this.ecef}static fromECEF(n){if(t.Vector3.norm(n)===0)throw Error(`ECEF vector cannot be the earth center`);let[r,i,a]=w(n),o=new e(r,i,a);return o._ecef=n,o}getSegmentProjection(n,r){let i=T(n.lat,n.lng),a=T(r.lat,r.lng),o=T(this.lat,this.lng),s=t.Vector3.cross(i,a);if(t.Vector3.norm(s)===0)return null;let c=t.Vector3.cross(o,s),l=t.Vector3.normalize(t.Vector3.cross(s,c));if(Math.abs(D(i,a)-D(i,l)-D(a,l))>.001/6378137)return null;let[u,d]=E(l),f;return n.alt!==null&&r.alt!==null&&(f=(n.alt+r.alt)/2),new e(u,d,f,y.union(n.level,r.level))}toString(){let e=`[`+this._lat.toFixed(7)+`, `+this._lng.toFixed(7);return this._alt!==null&&(e+=`, `+this._alt.toFixed(2)),this._level!==null&&(e+=`, [`+y.toString(this._level)+`]`),e+=`]`,e}toJson(){return{lat:Number(this.lat.toFixed(8)),lng:Number(this.lng.toFixed(8)),...this.alt!==null&&{alt:Number(this.alt.toFixed(3))},...this.level!==null&&{level:this.level}}}static fromJson(t){return new e(t.lat,t.lng,t.alt,t.level)}toCompressedJson(){return this.level===null?[Number(this.lat.toFixed(8)),Number(this.lng.toFixed(8))]:[Number(this.lat.toFixed(8)),Number(this.lng.toFixed(8)),this.level]}static fromCompressedJson(t){let n=new e(t[0],t[1]);return t.length>2&&(n.level=t[2]),n}},k=class e extends O{_time=null;_accuracy=null;_bearing=null;constructor(e,t,n=null,r=null,i=null,a=null,o=null){super(e,t,n,r),this.time=i,this.accuracy=a,this.bearing=o}get time(){return this._time}set time(e){this._time=e}get accuracy(){return this._accuracy}set accuracy(e){if(e!==null&&e<0)throw Error(`accuracy argument is not a positive number`);this._accuracy=e}get bearing(){return this._bearing}set bearing(e){this._bearing=e===null?null:e%(2*Math.PI)}move(e,t,n=null){return super.move(e,t,n),this}destinationPoint(e,t,n=null){let r=this.clone();return r.move(e,t,n),r}static fromCoordinates(t){return new e(t.lat,t.lng,t.alt,t.level)}clone(){let t=e.fromCoordinates(super.clone());return t.time=this.time,t.accuracy=this.accuracy,t.bearing=this.bearing,t}static equals(t,n,r=c,i=l){return t===null&&t===n?!0:!(t instanceof e)||!(n instanceof e)||!super.equals(t,n,r,i)?!1:t.time===n.time&&t.accuracy===n.accuracy&&t.bearing===n.bearing}equals(t,n=c,r=l){return e.equals(this,t,n,r)}toJson(){return{...super.toJson(),...this.time!==null&&{time:this.time},...this.accuracy!==null&&{accuracy:this.accuracy},...this.bearing!==null&&{bearing:this.bearing}}}static fromJson(t){let n=e.fromCoordinates(O.fromJson(t));return t.time!==void 0&&(n.time=t.time),t.accuracy!==void 0&&(n.accuracy=t.accuracy),t.bearing!==void 0&&(n.bearing=t.bearing),n}},A=r({calcDistance:()=>F,createSegmentsAtLevel:()=>ee,geolocationPositionToUserPosition:()=>P,sampleRoute:()=>j,segmentIntersection:()=>te,simplifyRoute:()=>N,trimRoute:()=>M});function j(e,t=.7,n=0,r=Number.MAX_VALUE){let i=n+r,a=[],o,s=0,c=0,l=!1;for(let r=0;r<e.length-1;r++){let u=e[r],d=e[r+1],f=u.distanceTo(d),p=u.bearingTo(d),m=0;if(!l)if(n<s+f)l=!0,c=n-s;else{s+=f;continue}for(o=Object.assign(u.clone(),{bearing:p});m+c<f&&s+c<=i;){let e=o.destinationPoint(c,p);e.bearing=p,a.push(e),o=e,m+=c,s+=c,c=t}if(s+c>i)break;let h=f-m;s+=h,c-=h}return a}function M(e,t=e[0],n=Number.MAX_VALUE){let r=[],i=null,a,o=0;if(e.length<=1)throw Error(`Route must have at least 2 points`);for(a=1;a<e.length;a++){let n=e[a-1],o=e[a];if(O.equals(t,n)){r.push(n),i=n;break}let s=t.getSegmentProjection(n,o);if(s&&O.equals(t,s)&&!s.equals(o)){r.push(s),i=s;break}}if(!r.length)throw Error(`startPosition is not on the route`);for(;i&&a<e.length;){let t=e[a],s=i.distanceTo(t);if(o+s>=n||Math.abs(o+s-n)<=.001){let e=i.bearingTo(t),a=n-o,s=i.destinationPoint(a,e);r.push(s);break}r.push(t),i=t,o+=s,a++}return r}function N(e,n=(0,t.deg2rad)(5)){let r=e[0].equals(e[e.length-1]),i=e.slice(0,e.length-+!!r),a=i.length;for(let o=+!r;o<a;o++){let r=e[(0,t.positiveMod)(o-1,a)],s=e[o],c=e[(0,t.positiveMod)(o+1,a)],l=r.bearingTo(s),u=s.bearingTo(c);Math.abs(u-l)<n&&(i=i.filter(e=>e!==s))}return r&&i.push(i[0]),i}function P(e){if(e===null)return null;let{latitude:n,longitude:r,accuracy:i,heading:a}=e.coords,o=new k(n,r);return o.time=e.timestamp,o.accuracy=i,o.bearing=a?(0,t.deg2rad)(a):null,o}function F(e){return e.reduce((e,t,n,r)=>e+(n?r[n-1].distanceTo(t):0),0)}function ee(e,t,n=!0){let r=e.length,i=!1,a=[],o=[];for(let s=0;s<r;s++){let r=e[s],c=y.intersect(t,r.level);n&&!c&&i?o.push(r):c&&(i||(o=[],a.push(o),n&&s!==0&&o.push(e[s-1])),o.push(r)),i=c}return a}function te(e,t,n,r){let i=e=>e*Math.PI/180,o=(e.lat+t.lat+n.lat+r.lat)/4,s=a*180/Math.PI,c=a*180/Math.PI*Math.cos(i(o)),l=e=>({x:e.lng*c,y:e.lat*s}),u=l(e),d=l(t),f=l(n),p=l(r),m=d.x-u.x,h=d.y-u.y,g=p.x-f.x,_=p.y-f.y,v=m*_-h*g;if(Math.abs(v)<1e-10)return null;let y=f.x-u.x,b=f.y-u.y,x=(y*_-b*g)/v,S=(y*h-b*m)/v;return x<0||x>1||S<0||S>1?null:new O((u.y+x*h)/s,(u.x+x*m)/c)}var I=class e{northEast;southWest;constructor(e,t){if(this.northEast=e,this.southWest=t,this.northEast&&this.southWest&&this.getNorth()<this.getSouth())throw Error(`Incorrect bounding box`)}get center(){return new O((this.southWest.lat+this.northEast.lat)/2,(this.northEast.lng+this.southWest.lng)/2)}contains(e){return e.lat<=this.northEast.lat&&e.lat>=this.southWest.lat&&e.lng<=this.northEast.lng&&e.lng>=this.southWest.lng}extend(t){let n=this.southWest,r=this.northEast,i,a;if(t instanceof O)i=t,a=t;else if(t instanceof e)i=t.southWest,a=t.northEast;else throw Error(`Unknown parameter`);return this.southWest=new O(Math.min(i.lat,n.lat),Math.min(i.lng,n.lng)),this.northEast=new O(Math.max(a.lat,r.lat),Math.max(a.lng,r.lng)),this}extendsWithMeasure(e){if(typeof e!=`number`)throw Error(`measure is not a number`);return this.northEast=this.northEast.destinationPoint(e,0).move(e,Math.PI/2),this.southWest=this.southWest.clone().destinationPoint(e,-Math.PI/2).destinationPoint(e,Math.PI),this}pad(e){let t=this.southWest,n=this.northEast,r=Math.abs(t.lat-n.lat)*e,i=Math.abs(t.lng-n.lng)*e;return this.southWest=new O(t.lat-r,t.lng-i),this.northEast=new O(n.lat+r,n.lng+i),this}getSouthWest(){return this.southWest}getNorthEast(){return this.northEast}getNorthWest(){return new O(this.getNorth(),this.getWest())}getSouthEast(){return new O(this.getSouth(),this.getEast())}getWest(){return this.southWest.lng}getSouth(){return this.southWest.lat}getEast(){return this.northEast.lng}getNorth(){return this.northEast.lat}static equals(e,t){return O.equals(e.northEast,t.northEast)&&O.equals(e.southWest,t.southWest)}equals(t){return e.equals(this,t)}static fromArray(t){return new e(new O(t[3],t[2]),new O(t[1],t[0]))}static fromCoordinates(t){return t.length===0?null:t.reduce((e,t)=>e.extend(t),new e(t[0],t[0]))}toArray(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()]}},L=class e{x;y;z;time=null;_accuracy=null;_bearing=null;constructor(e,t,n,r=null,i=null,a=null){this.x=e,this.y=t,this.z=n,this.time=r,this.accuracy=i,this.bearing=a}get accuracy(){return this._accuracy}set accuracy(e){if(e!==null&&e<0)throw Error(`accuracy argument is not a positive number`);this._accuracy=e}get bearing(){return this._bearing}set bearing(e){this._bearing=e===null?null:e%(2*Math.PI)}clone(){return new e(this.x,this.y,this.z,this.time,this.accuracy,this.bearing)}static equals(t,n,r=l){return t===null&&t===n?!0:!(t instanceof e)||!(n instanceof e)?!1:Math.abs(n.x-t.x)<r&&Math.abs(n.y-t.y)<r&&Math.abs(n.z-t.z)<r&&t.time===n.time&&t.accuracy===n.accuracy&&t.bearing===n.bearing}equals(t){return e.equals(this,t)}toJson(){return{x:this.x,y:this.y,z:this.z,...this.time!==null&&{time:this.time},...this.accuracy!==null&&{accuracy:this.accuracy},...this.bearing!==null&&{bearing:this.bearing}}}static fromJson(t){return new e(t.x,t.y,t.z,t.time,t.accuracy,t.bearing)}},R=class extends L{},z=11102230246251565e-32,B=134217729,V=3.000000000000001*z;function H(e,t,n,r,i){let a,o,s,c,l=t[0],u=r[0],d=0,f=0;u>l==u>-l?(a=l,l=t[++d]):(a=u,u=r[++f]);let p=0;if(d<e&&f<n)for(u>l==u>-l?(o=l+a,s=a-(o-l),l=t[++d]):(o=u+a,s=a-(o-u),u=r[++f]),a=o,s!==0&&(i[p++]=s);d<e&&f<n;)u>l==u>-l?(o=a+l,c=o-a,s=a-(o-c)+(l-c),l=t[++d]):(o=a+u,c=o-a,s=a-(o-c)+(u-c),u=r[++f]),a=o,s!==0&&(i[p++]=s);for(;d<e;)o=a+l,c=o-a,s=a-(o-c)+(l-c),l=t[++d],a=o,s!==0&&(i[p++]=s);for(;f<n;)o=a+u,c=o-a,s=a-(o-c)+(u-c),u=r[++f],a=o,s!==0&&(i[p++]=s);return(a!==0||p===0)&&(i[p++]=a),p}function U(e,t){let n=t[0];for(let r=1;r<e;r++)n+=t[r];return n}function W(e){return new Float64Array(e)}var G=(3+16*z)*z,K=(2+12*z)*z,q=(9+64*z)*z*z,J=W(4),Y=W(8),X=W(12),Z=W(16),Q=W(4);function ne(e,t,n,r,i,a,o){let s,c,l,u,d,f,p,m,h,g,_,v,y,b,x,S,C,w,T=e-i,E=n-i,D=t-a,O=r-a;b=T*O,f=B*T,p=f-(f-T),m=T-p,f=B*O,h=f-(f-O),g=O-h,x=m*g-(b-p*h-m*h-p*g),S=D*E,f=B*D,p=f-(f-D),m=D-p,f=B*E,h=f-(f-E),g=E-h,C=m*g-(S-p*h-m*h-p*g),_=x-C,d=x-_,J[0]=x-(_+d)+(d-C),v=b+_,d=v-b,y=b-(v-d)+(_-d),_=y-S,d=y-_,J[1]=y-(_+d)+(d-S),w=v+_,d=w-v,J[2]=v-(w-d)+(_-d),J[3]=w;let k=U(4,J),A=K*o;if(k>=A||-k>=A||(d=e-T,s=e-(T+d)+(d-i),d=n-E,l=n-(E+d)+(d-i),d=t-D,c=t-(D+d)+(d-a),d=r-O,u=r-(O+d)+(d-a),s===0&&c===0&&l===0&&u===0)||(A=q*o+V*Math.abs(k),k+=T*u+O*s-(D*l+E*c),k>=A||-k>=A))return k;b=s*O,f=B*s,p=f-(f-s),m=s-p,f=B*O,h=f-(f-O),g=O-h,x=m*g-(b-p*h-m*h-p*g),S=c*E,f=B*c,p=f-(f-c),m=c-p,f=B*E,h=f-(f-E),g=E-h,C=m*g-(S-p*h-m*h-p*g),_=x-C,d=x-_,Q[0]=x-(_+d)+(d-C),v=b+_,d=v-b,y=b-(v-d)+(_-d),_=y-S,d=y-_,Q[1]=y-(_+d)+(d-S),w=v+_,d=w-v,Q[2]=v-(w-d)+(_-d),Q[3]=w;let j=H(4,J,4,Q,Y);b=T*u,f=B*T,p=f-(f-T),m=T-p,f=B*u,h=f-(f-u),g=u-h,x=m*g-(b-p*h-m*h-p*g),S=D*l,f=B*D,p=f-(f-D),m=D-p,f=B*l,h=f-(f-l),g=l-h,C=m*g-(S-p*h-m*h-p*g),_=x-C,d=x-_,Q[0]=x-(_+d)+(d-C),v=b+_,d=v-b,y=b-(v-d)+(_-d),_=y-S,d=y-_,Q[1]=y-(_+d)+(d-S),w=v+_,d=w-v,Q[2]=v-(w-d)+(_-d),Q[3]=w;let M=H(j,Y,4,Q,X);return b=s*u,f=B*s,p=f-(f-s),m=s-p,f=B*u,h=f-(f-u),g=u-h,x=m*g-(b-p*h-m*h-p*g),S=c*l,f=B*c,p=f-(f-c),m=c-p,f=B*l,h=f-(f-l),g=l-h,C=m*g-(S-p*h-m*h-p*g),_=x-C,d=x-_,Q[0]=x-(_+d)+(d-C),v=b+_,d=v-b,y=b-(v-d)+(_-d),_=y-S,d=y-_,Q[1]=y-(_+d)+(d-S),w=v+_,d=w-v,Q[2]=v-(w-d)+(_-d),Q[3]=w,Z[H(M,X,4,Q,Z)-1]}function re(e,t,n,r,i,a){let o=(t-a)*(n-i),s=(e-i)*(r-a),c=o-s,l=Math.abs(o+s);return Math.abs(c)>=G*l?c:-ne(e,t,n,r,i,a,l)}(7+56*z)*z,(3+28*z)*z,(26+288*z)*z*z,W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(8),W(8),W(8),W(4),W(8),W(8),W(16),W(12),W(192),W(192),(10+96*z)*z,(4+48*z)*z,(44+576*z)*z*z,W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(8),W(8),W(8),W(8),W(8),W(8),W(8),W(8),W(8),W(4),W(4),W(4),W(8),W(16),W(16),W(16),W(32),W(32),W(48),W(64),W(1152),W(1152),(16+224*z)*z,(5+72*z)*z,(71+1408*z)*z*z,W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(4),W(24),W(24),W(24),W(24),W(24),W(24),W(24),W(24),W(24),W(24),W(1152),W(1152),W(1152),W(1152),W(1152),W(2304),W(2304),W(3456),W(5760),W(8),W(8),W(8),W(16),W(24),W(48),W(48),W(96),W(192),W(384),W(384),W(384),W(768),W(96),W(96),W(96),W(1152);function ie(e,t){var n,r,i=0,a,o,s,c,l,u,d,f=e[0],p=e[1],m=t.length;for(n=0;n<m;n++){r=0;var h=t[n],g=h.length-1;if(u=h[0],u[0]!==h[g][0]&&u[1]!==h[g][1])throw Error(`First and last coordinates in a ring must be the same`);for(o=u[0]-f,s=u[1]-p;r<g;r++){if(d=h[r+1],c=d[0]-f,l=d[1]-p,s===0&&l===0){if(c<=0&&o>=0||o<=0&&c>=0)return 0}else if(l>=0&&s<=0||l<=0&&s>=0){if(a=re(o,c,s,l,0,0),a===0)return 0;(a>0&&l>0&&s<=0||a<0&&l<=0&&s>0)&&i++}u=d,s=l,o=c}}return i%2!=0}function ae(e){if(!e)throw Error(`coord is required`);if(!Array.isArray(e)){if(e.type===`Feature`&&e.geometry!==null&&e.geometry.type===`Point`)return[...e.geometry.coordinates];if(e.type===`Point`)return[...e.coordinates]}if(Array.isArray(e)&&e.length>=2&&!Array.isArray(e[0])&&!Array.isArray(e[1]))return[...e];throw Error(`coord must be GeoJSON Point or an Array of numbers`)}function oe(e){return e.type===`Feature`?e.geometry:e}function se(e,t,n={}){if(!e)throw Error(`point is required`);if(!t)throw Error(`polygon is required`);let r=ae(e),i=oe(t),a=i.type,o=t.bbox,s=i.coordinates;if(o&&ce(r,o)===!1)return!1;a===`Polygon`&&(s=[s]);let c=!1;for(var l=0;l<s.length;++l){let e=ie(r,s[l]);if(e===0)return!n.ignoreBoundary;e&&(c=!0)}return c}function ce(e,t){return t[0]<=e[0]&&t[1]<=e[1]&&t[2]>=e[0]&&t[3]>=e[1]}var le=se,ue=class e{scale=1;heading=0;origin;buildingLevels;constructor(e,t=[]){this.origin=e,this.buildingLevels=t}localToWorld(e){let n=t.Vector3.multiplyScalar(e,this.scale),r=t.Quaternion.fromAxisAngle([0,0,1],-this.heading),i=t.Quaternion.multiply(this.origin.enuToEcefRotation,r),a=t.Quaternion.rotate(i,n),o=t.Vector3.sum(this.origin.ecef,a),s=O.fromECEF(o),c=s.alt;s.heightFromGround=s.alt-this.origin.alt;let l=e=>{s.level=e.id,s.heightFromFloor=c-e.floorAltitude};if(!this.buildingLevels.length)return s;let u=this.buildingLevels.filter(e=>c>=e.floorAltitude&&c<=e.ceilingAltitude);if(!u.length)return s;let d=u[0],f=[s.lng,s.lat],p=u.filter(e=>e.geometries.length);if(!p.length)return l(d),s;let m=p.filter(e=>e.geometries.some(e=>le(f,e)))[0];return m&&l(m),s}worldToLocal(e){let n=t.Quaternion.fromAxisAngle([0,0,1],this.heading),r=t.Quaternion.multiply(n,this.origin.ecefToEnuRotation),i=t.Vector3.subtract(e.ecef,this.origin.ecef),a=t.Vector3.multiplyScalar(i,1/this.scale);return t.Quaternion.rotate(r,a)}toJson(){return{origin:this.origin.toJson(),...this.scale!==1&&{scale:this.scale},...this.heading!==0&&{heading:this.heading}}}static fromJson(t){let n=new e(O.fromJson(t.origin));return n.scale=t.scale===void 0?1:t.scale,n.heading=t.heading===void 0?0:t.heading,n}},$=class e{_quaternion=[1,0,0,0];_heading=null;_eulerAngles=null;_time=null;_accuracy=null;constructor(e,t=null,n=null){this.quaternion=e,this.time=t,this.accuracy=n}static unitary(){return new e([1,0,0,0])}get quaternion(){return this._quaternion}set quaternion(e){if(Math.abs(1-t.Quaternion.norm(e))>1e-4)throw Error(`quaternion is not a unit quaternion`);this._quaternion=e,this._heading=null,this._eulerAngles=null}get time(){return this._time}set time(e){this._time=e}get accuracy(){return this._accuracy}set accuracy(e){if(e!==null&&(e<0||e>Math.PI))throw Error(`accuracy argument (`+e+`) is not in range [0; PI]`);this._accuracy=e}get eulerAngles(){return this._eulerAngles===null&&(this._eulerAngles=t.Rotations.quaternionToEulerZXY(this.quaternion)),this._eulerAngles}get eulerAnglesDegrees(){return this.eulerAngles.map(e=>(0,t.rad2deg)(e))}get heading(){if(this._heading===null){let e=0;typeof window<`u`&&window&&window.orientation&&(e=(0,t.deg2rad)(window.orientation)),this._heading=t.Rotations.getHeadingFromQuaternion(this.quaternion)+e}return this._heading}get headingDegrees(){return(0,t.rad2deg)(this.heading)}static equals(n,r){return n===null&&n===r?!0:!(n instanceof e)||!(r instanceof e)?!1:n===r||t.Quaternion.equals(n.quaternion,r.quaternion)}equals(t){return e.equals(this,t)}toJson(){return this.time===null&&this.accuracy===null?this.quaternion:{q:this.quaternion,...this.time!==null&&{time:this.time},...this.accuracy!==null&&{accuracy:this.accuracy}}}static fromJson(t){return Array.isArray(t)?new e(t,null,null):new e(t.q,t.time,t.accuracy)}clone(){return new e(this.quaternion.slice(0),this.time,this.accuracy)}static diff(n,r){let i=t.Quaternion.multiply(t.Quaternion.inverse(n.quaternion),r.quaternion),a=null;r.time!==null&&n.time!==null&&(a=r.time-n.time);let o=null;return n.accuracy!==null&&r.accuracy!==null&&(o=Math.max(r.accuracy-n.accuracy)),new e(i,a,o)}};e.AbsoluteHeading=class e{heading;time=null;_accuracy=null;constructor(e,t=null,n=null){this.heading=e,this.time=t,this.accuracy=n}get accuracy(){return this._accuracy}set accuracy(e){if(e!==null&&(e<0||e>Math.PI))throw Error(`accuracy argument (`+e+`) is not in range [0; PI]`);this._accuracy=e}toAttitude(){return new $(t.Quaternion.fromAxisAngle([0,0,1],-this.heading),this.time,this.accuracy)}static equals(t,n){return t===null&&t===n?!0:!(t instanceof e)||!(n instanceof e)?!1:Math.abs(t.heading-n.heading)<1e-8}equals(t){return e.equals(this,t)}toJson(){return{heading:this.heading,...this.time!==null&&{time:this.time},...this.accuracy!==null&&{accuracy:this.accuracy}}}static fromJson(t){return new e(t.heading,t.time,t.accuracy)}clone(){return new e(this.heading,this.time,this.accuracy)}},e.Attitude=$,e.BoundingBox=I,Object.defineProperty(e,"Constants",{enumerable:!0,get:function(){return i}}),e.Coordinates=O,e.GeoRef=ue,e.GeoRelativePosition=R,e.Level=y,e.RelativePosition=L,e.UserPosition=k,Object.defineProperty(e,"Utils",{enumerable:!0,get:function(){return A}})});
package/dist/index.js CHANGED
@@ -21,8 +21,9 @@ var c = Object.defineProperty, l = (e, t) => {
21
21
  R_MAJOR_4: () => b,
22
22
  R_MINOR: () => f,
23
23
  R_MINOR_2: () => x,
24
- R_MINOR_4: () => S
25
- }), d = 6378137, f = 6356752.3142, p = 9.80665, m = 1e-8, h = .001, g = (d - f) / d, _ = Math.sqrt(g * (2 - g)), v = _ * _, y = d * d, b = y * y, x = f * f, S = x * x, C = d * 2 * Math.PI, w = class e {
24
+ R_MINOR_4: () => S,
25
+ SECOND_ECCENTRICITY_2: () => w
26
+ }), d = 6378137, f = 6356752.314245179, p = 9.80665, m = 1e-8, h = .001, g = 1 / 298.257223563, _ = Math.sqrt(g * (2 - g)), v = _ * _, y = d * d, b = y * y, x = f * f, S = x * x, C = d * 2 * Math.PI, w = (y - x) / x, T = class e {
26
27
  static VERIFY_TYPING = !1;
27
28
  static checkType(e) {
28
29
  if (e !== null && !(typeof e == "number" && !isNaN(e))) {
@@ -110,7 +111,55 @@ var c = Object.defineProperty, l = (e, t) => {
110
111
  static diff(t, n) {
111
112
  return e.VERIFY_TYPING && (e.checkType(t), e.checkType(n)), t === null || n === null ? null : !Array.isArray(t) && !Array.isArray(n) ? n - t : Array.isArray(t) && !Array.isArray(n) ? t[0] === n ? n - t[1] : t[1] === n ? n - t[0] : null : Array.isArray(n) && !Array.isArray(t) ? t === n[0] ? n[1] - t : t === n[1] ? n[0] - t : null : e.equals(t, n) ? 0 : null;
112
113
  }
113
- }, T = class t {
114
+ };
115
+ //#endregion
116
+ //#region src/coordinates/Coordinates.ts
117
+ function E(e, t) {
118
+ let n = r(e), i = r(t);
119
+ return {
120
+ sinLat: Math.sin(n),
121
+ cosLat: Math.cos(n),
122
+ sinLng: Math.sin(i),
123
+ cosLng: Math.cos(i)
124
+ };
125
+ }
126
+ function D(e) {
127
+ return d / Math.sqrt(1 - v * e ** 2);
128
+ }
129
+ function O(e) {
130
+ return f / (1 - v * e ** 2);
131
+ }
132
+ function k(e, t, n) {
133
+ let { sinLat: r, cosLat: i, sinLng: a, cosLng: o } = E(e, t), s = D(r), c = (s + n) * i;
134
+ return [
135
+ c * o,
136
+ c * a,
137
+ (s * (1 - v) + n) * r
138
+ ];
139
+ }
140
+ function A(e) {
141
+ let [t, n, r] = e, i = Math.hypot(t, n), o = Math.atan2(d * r, f * i), s = Math.atan2(r + f * w * Math.sin(o) ** 3, i - d * v * Math.cos(o) ** 3), c = Math.sin(s), l = i * Math.cos(s) + r * c - d * Math.sqrt(1 - v * c ** 2);
142
+ return [
143
+ a(s),
144
+ a(Math.atan2(n, t)),
145
+ l
146
+ ];
147
+ }
148
+ function j(e, t) {
149
+ let n = r(e), i = r(t), a = Math.cos(n);
150
+ return [
151
+ a * Math.cos(i),
152
+ a * Math.sin(i),
153
+ Math.sin(n)
154
+ ];
155
+ }
156
+ function M(e) {
157
+ return [a(Math.atan2(e[2], Math.hypot(e[0], e[1]))), a(Math.atan2(e[1], e[0]))];
158
+ }
159
+ function N(e, t) {
160
+ return 2 * Math.asin(Math.hypot(e[0] - t[0], e[1] - t[1], e[2] - t[2]) / 2);
161
+ }
162
+ var P = class t {
114
163
  _lat;
115
164
  _lng;
116
165
  _alt = null;
@@ -118,6 +167,7 @@ var c = Object.defineProperty, l = (e, t) => {
118
167
  _heightFromFloor = null;
119
168
  _heightFromGround = null;
120
169
  _ecef;
170
+ _groundEcef = null;
121
171
  autoWrap = !0;
122
172
  constructor(e, t, n = null, r = null) {
123
173
  this.lat = e, this.lng = t, this.alt = n, this.level = r, this._ecef = null;
@@ -128,7 +178,7 @@ var c = Object.defineProperty, l = (e, t) => {
128
178
  set lat(e) {
129
179
  if (Math.abs(e) <= 90) this._lat = e;
130
180
  else throw Error(`lat argument is not in [-90; 90], value is ${e}`);
131
- this._ecef = null;
181
+ this._ecef = null, this._groundEcef = null;
132
182
  }
133
183
  get latitude() {
134
184
  return this._lat;
@@ -140,7 +190,7 @@ var c = Object.defineProperty, l = (e, t) => {
140
190
  return this._lng;
141
191
  }
142
192
  set lng(e) {
143
- this._lng = e, this.autoWrap && this.wrap(), this._ecef = null;
193
+ this._lng = e, this.autoWrap && this.wrap(), this._ecef = null, this._groundEcef = null;
144
194
  }
145
195
  get longitude() {
146
196
  return this._lng;
@@ -158,7 +208,7 @@ var c = Object.defineProperty, l = (e, t) => {
158
208
  return this._level;
159
209
  }
160
210
  set level(e) {
161
- w.checkType(e), this._level = e;
211
+ T.checkType(e), this._level = e;
162
212
  }
163
213
  get heightFromFloor() {
164
214
  return this._heightFromFloor;
@@ -174,13 +224,13 @@ var c = Object.defineProperty, l = (e, t) => {
174
224
  }
175
225
  clone() {
176
226
  let e = new t(this.lat, this.lng, this.alt);
177
- return this.level !== null && (e.level = w.clone(this.level)), e;
227
+ return this.level !== null && (e.level = T.clone(this.level)), e;
178
228
  }
179
229
  wrap() {
180
230
  (this._lng <= -180 || this._lng > 180) && (this._lng = o(this._lng, -180, 180));
181
231
  }
182
232
  static equals(e, t, n = m, r = h) {
183
- return this.equalsWithoutLevel(e, t, n, r) ? e === null || t === null || w.equals(e.level, t.level) : !1;
233
+ return this.equalsWithoutLevel(e, t, n, r) ? e === null || t === null || T.equals(e.level, t.level) : !1;
184
234
  }
185
235
  equals(e) {
186
236
  return t.equals(this, e);
@@ -196,23 +246,27 @@ var c = Object.defineProperty, l = (e, t) => {
196
246
  return r.move(e, t, n), r;
197
247
  }
198
248
  move(e, t, n = null) {
199
- let i = e / d, o = Math.cos(i), s = Math.sin(i), c = r(this.lat), l = r(this.lng), u = Math.asin(Math.sin(c) * o + Math.cos(c) * s * Math.cos(t)), f = l + Math.atan2(Math.sin(t) * s * Math.cos(c), o - Math.sin(c) * Math.sin(u));
200
- if (this.lat = a(u), this.lng = a(f), n !== null) {
249
+ let { sinLat: r, cosLat: i, sinLng: a, cosLng: o } = E(this.lat, this.lng), s = O(r), c = e / (2 * s), l = 2 * s * Math.sin(c), u = l * Math.cos(c), d = u * Math.sin(t), f = u * Math.cos(t), p = -l * Math.sin(c), m = D(r), h = m * i, [g, _] = A([
250
+ h * o - a * d - r * o * f + i * o * p,
251
+ h * a + o * d - r * a * f + i * a * p,
252
+ m * (1 - v) * r + i * f + r * p
253
+ ]);
254
+ if (this.lat = g, this.lng = _, n !== null) {
201
255
  if (this.alt === null) throw Error("Point altitude is not defined");
202
256
  this.alt += n;
203
257
  }
204
258
  return this;
205
259
  }
206
260
  distanceTo(e) {
207
- let t = this.lat, n = this.lng, i = e.lat, a = e.lng, o = r(i - t), s = r(a - n), c = Math.sin(s / 2), l = Math.sin(o / 2), u = r(t), f = Math.cos(u), p = r(i), m = Math.cos(p), h = l * l + f * m * c * c, g = Math.sqrt(h), _ = Math.sqrt(1 - h);
208
- return 2 * Math.atan2(g, _) * d;
261
+ let [t, n, i] = this.groundEcef, [a, o, s] = e.groundEcef, c = Math.hypot(a - t, o - n, s - i), l = O(Math.sin(r((this.lat + e.lat) / 2)));
262
+ return 2 * l * Math.asin(Math.min(1, c / (2 * l)));
209
263
  }
210
264
  static distanceBetween(e, t) {
211
265
  return e.distanceTo(t);
212
266
  }
213
267
  bearingTo(e) {
214
- let t = r(this.lat), n = r(e.lat), i = r(e.lng - this.lng);
215
- return Math.atan2(Math.sin(i) * Math.cos(n), Math.cos(t) * Math.sin(n) - Math.sin(t) * Math.cos(n) * Math.cos(i));
268
+ let t = this.groundEcef, n = e.groundEcef, r = n[0] - t[0], i = n[1] - t[1], a = n[2] - t[2], { sinLat: o, cosLat: s, sinLng: c, cosLng: l } = E(this.lat, this.lng), u = -c * r + l * i, d = -o * l * r - o * c * i + s * a;
269
+ return Math.atan2(u, d);
216
270
  }
217
271
  static bearingTo(e, t) {
218
272
  return e.bearingTo(t);
@@ -242,33 +296,27 @@ var c = Object.defineProperty, l = (e, t) => {
242
296
  return e.multiply(t, n);
243
297
  }
244
298
  get ecef() {
245
- if (!this._ecef) {
246
- let e = r(this.lat), t = r(this.lng), n = this.alt || 0, i = (d + n) * Math.cos(e) * Math.cos(t), a = (d + n) * Math.cos(e) * Math.sin(t), o = (d + n) * Math.sin(e);
247
- this._ecef = [
248
- i,
249
- a,
250
- o
251
- ];
252
- }
253
- return this._ecef;
299
+ return this._ecef ||= k(this.lat, this.lng, this.alt || 0), this._ecef;
300
+ }
301
+ get groundEcef() {
302
+ return this.alt ? (this._groundEcef ||= k(this.lat, this.lng, 0), this._groundEcef) : this.ecef;
254
303
  }
255
304
  static fromECEF(e) {
256
- let n = e[0], r = e[1], i = e[2], o = Math.sqrt(n ** 2 + r ** 2), s = Math.atan2(r, n), c = Math.atan2(i, o), l = o / Math.cos(c) - d;
257
- s %= 2 * Math.PI;
258
- let u = new t(a(c), a(s), l);
259
- return u._ecef = e, u;
305
+ if (n.norm(e) === 0) throw Error("ECEF vector cannot be the earth center");
306
+ let [r, i, a] = A(e), o = new t(r, i, a);
307
+ return o._ecef = e, o;
260
308
  }
261
309
  getSegmentProjection(e, r) {
262
- let i = n.normalize(e.ecef), a = n.normalize(r.ecef), o = n.normalize(this.ecef), s = n.cross(i, a);
310
+ let i = j(e.lat, e.lng), a = j(r.lat, r.lng), o = j(this.lat, this.lng), s = n.cross(i, a);
263
311
  if (n.norm(s) === 0) return null;
264
- let c = n.cross(o, s), l = n.normalize(n.cross(s, c)), u = n.multiplyScalar(l, d), f = t.fromECEF(u), p;
265
- e.alt !== null && r.alt !== null && (p = (e.alt + r.alt) / 2);
266
- let m = new t(f.lat, f.lng, p, w.union(e.level, r.level));
267
- return Math.abs(e.distanceTo(r) - e.distanceTo(m) - r.distanceTo(m)) > .001 ? null : m;
312
+ let c = n.cross(o, s), l = n.normalize(n.cross(s, c));
313
+ if (Math.abs(N(i, a) - N(i, l) - N(a, l)) > .001 / 6378137) return null;
314
+ let [u, d] = M(l), f;
315
+ return e.alt !== null && r.alt !== null && (f = (e.alt + r.alt) / 2), new t(u, d, f, T.union(e.level, r.level));
268
316
  }
269
317
  toString() {
270
318
  let e = "[" + this._lat.toFixed(7) + ", " + this._lng.toFixed(7);
271
- return this._alt !== null && (e += ", " + this._alt.toFixed(2)), this._level !== null && (e += ", [" + w.toString(this._level) + "]"), e += "]", e;
319
+ return this._alt !== null && (e += ", " + this._alt.toFixed(2)), this._level !== null && (e += ", [" + T.toString(this._level) + "]"), e += "]", e;
272
320
  }
273
321
  toJson() {
274
322
  return {
@@ -292,7 +340,7 @@ var c = Object.defineProperty, l = (e, t) => {
292
340
  let n = new t(e[0], e[1]);
293
341
  return e.length > 2 && (n.level = e[2]), n;
294
342
  }
295
- }, E = class e extends T {
343
+ }, F = class e extends P {
296
344
  _time = null;
297
345
  _accuracy = null;
298
346
  _bearing = null;
@@ -347,19 +395,19 @@ var c = Object.defineProperty, l = (e, t) => {
347
395
  };
348
396
  }
349
397
  static fromJson(t) {
350
- let n = e.fromCoordinates(T.fromJson(t));
398
+ let n = e.fromCoordinates(P.fromJson(t));
351
399
  return t.time !== void 0 && (n.time = t.time), t.accuracy !== void 0 && (n.accuracy = t.accuracy), t.bearing !== void 0 && (n.bearing = t.bearing), n;
352
400
  }
353
- }, D = /* @__PURE__ */ l({
354
- calcDistance: () => M,
355
- createSegmentsAtLevel: () => N,
356
- geolocationPositionToUserPosition: () => j,
357
- sampleRoute: () => O,
358
- segmentIntersection: () => P,
359
- simplifyRoute: () => A,
360
- trimRoute: () => k
401
+ }, I = /* @__PURE__ */ l({
402
+ calcDistance: () => V,
403
+ createSegmentsAtLevel: () => H,
404
+ geolocationPositionToUserPosition: () => B,
405
+ sampleRoute: () => L,
406
+ segmentIntersection: () => U,
407
+ simplifyRoute: () => z,
408
+ trimRoute: () => R
361
409
  });
362
- function O(e, t = .7, n = 0, r = Number.MAX_VALUE) {
410
+ function L(e, t = .7, n = 0, r = Number.MAX_VALUE) {
363
411
  let i = n + r, a = [], o, s = 0, c = 0, l = !1;
364
412
  for (let r = 0; r < e.length - 1; r++) {
365
413
  let u = e[r], d = e[r + 1], f = u.distanceTo(d), p = u.bearingTo(d), m = 0;
@@ -378,17 +426,17 @@ function O(e, t = .7, n = 0, r = Number.MAX_VALUE) {
378
426
  }
379
427
  return a;
380
428
  }
381
- function k(e, t = e[0], n = Number.MAX_VALUE) {
429
+ function R(e, t = e[0], n = Number.MAX_VALUE) {
382
430
  let r = [], i = null, a, o = 0;
383
431
  if (e.length <= 1) throw Error("Route must have at least 2 points");
384
432
  for (a = 1; a < e.length; a++) {
385
433
  let n = e[a - 1], o = e[a];
386
- if (T.equals(t, n)) {
434
+ if (P.equals(t, n)) {
387
435
  r.push(n), i = n;
388
436
  break;
389
437
  }
390
438
  let s = t.getSegmentProjection(n, o);
391
- if (s && T.equals(t, s) && !s.equals(o)) {
439
+ if (s && P.equals(t, s) && !s.equals(o)) {
392
440
  r.push(s), i = s;
393
441
  break;
394
442
  }
@@ -405,7 +453,7 @@ function k(e, t = e[0], n = Number.MAX_VALUE) {
405
453
  }
406
454
  return r;
407
455
  }
408
- function A(e, t = r(5)) {
456
+ function z(e, t = r(5)) {
409
457
  let n = e[0].equals(e[e.length - 1]), a = e.slice(0, e.length - +!!n), o = a.length;
410
458
  for (let r = +!n; r < o; r++) {
411
459
  let n = e[i(r - 1, o)], s = e[r], c = e[i(r + 1, o)], l = n.bearingTo(s), u = s.bearingTo(c);
@@ -413,51 +461,51 @@ function A(e, t = r(5)) {
413
461
  }
414
462
  return n && a.push(a[0]), a;
415
463
  }
416
- function j(e) {
464
+ function B(e) {
417
465
  if (e === null) return null;
418
- let { latitude: t, longitude: n, accuracy: i, heading: a } = e.coords, o = new E(t, n);
466
+ let { latitude: t, longitude: n, accuracy: i, heading: a } = e.coords, o = new F(t, n);
419
467
  return o.time = e.timestamp, o.accuracy = i, o.bearing = a ? r(a) : null, o;
420
468
  }
421
- function M(e) {
469
+ function V(e) {
422
470
  return e.reduce((e, t, n, r) => e + (n ? r[n - 1].distanceTo(t) : 0), 0);
423
471
  }
424
- function N(e, t, n = !0) {
472
+ function H(e, t, n = !0) {
425
473
  let r = e.length, i = !1, a = [], o = [];
426
474
  for (let s = 0; s < r; s++) {
427
- let r = e[s], c = w.intersect(t, r.level);
475
+ let r = e[s], c = T.intersect(t, r.level);
428
476
  n && !c && i ? o.push(r) : c && (i || (o = [], a.push(o), n && s !== 0 && o.push(e[s - 1])), o.push(r)), i = c;
429
477
  }
430
478
  return a;
431
479
  }
432
- function P(e, t, n, r) {
480
+ function U(e, t, n, r) {
433
481
  let i = (e) => e * Math.PI / 180, a = (e.lat + t.lat + n.lat + r.lat) / 4, o = d * 180 / Math.PI, s = d * 180 / Math.PI * Math.cos(i(a)), c = (e) => ({
434
482
  x: e.lng * s,
435
483
  y: e.lat * o
436
484
  }), l = c(e), u = c(t), f = c(n), p = c(r), m = u.x - l.x, h = u.y - l.y, g = p.x - f.x, _ = p.y - f.y, v = m * _ - h * g;
437
485
  if (Math.abs(v) < 1e-10) return null;
438
486
  let y = f.x - l.x, b = f.y - l.y, x = (y * _ - b * g) / v, S = (y * h - b * m) / v;
439
- return x < 0 || x > 1 || S < 0 || S > 1 ? null : new T((l.y + x * h) / o, (l.x + x * m) / s);
487
+ return x < 0 || x > 1 || S < 0 || S > 1 ? null : new P((l.y + x * h) / o, (l.x + x * m) / s);
440
488
  }
441
489
  //#endregion
442
490
  //#region src/coordinates/BoundingBox.ts
443
- var F = class e {
491
+ var W = class e {
444
492
  northEast;
445
493
  southWest;
446
494
  constructor(e, t) {
447
495
  if (this.northEast = e, this.southWest = t, this.northEast && this.southWest && this.getNorth() < this.getSouth()) throw Error("Incorrect bounding box");
448
496
  }
449
497
  get center() {
450
- return new T((this.southWest.lat + this.northEast.lat) / 2, (this.northEast.lng + this.southWest.lng) / 2);
498
+ return new P((this.southWest.lat + this.northEast.lat) / 2, (this.northEast.lng + this.southWest.lng) / 2);
451
499
  }
452
500
  contains(e) {
453
501
  return e.lat <= this.northEast.lat && e.lat >= this.southWest.lat && e.lng <= this.northEast.lng && e.lng >= this.southWest.lng;
454
502
  }
455
503
  extend(t) {
456
504
  let n = this.southWest, r = this.northEast, i, a;
457
- if (t instanceof T) i = t, a = t;
505
+ if (t instanceof P) i = t, a = t;
458
506
  else if (t instanceof e) i = t.southWest, a = t.northEast;
459
507
  else throw Error("Unknown parameter");
460
- return this.southWest = new T(Math.min(i.lat, n.lat), Math.min(i.lng, n.lng)), this.northEast = new T(Math.max(a.lat, r.lat), Math.max(a.lng, r.lng)), this;
508
+ return this.southWest = new P(Math.min(i.lat, n.lat), Math.min(i.lng, n.lng)), this.northEast = new P(Math.max(a.lat, r.lat), Math.max(a.lng, r.lng)), this;
461
509
  }
462
510
  extendsWithMeasure(e) {
463
511
  if (typeof e != "number") throw Error("measure is not a number");
@@ -465,7 +513,7 @@ var F = class e {
465
513
  }
466
514
  pad(e) {
467
515
  let t = this.southWest, n = this.northEast, r = Math.abs(t.lat - n.lat) * e, i = Math.abs(t.lng - n.lng) * e;
468
- return this.southWest = new T(t.lat - r, t.lng - i), this.northEast = new T(n.lat + r, n.lng + i), this;
516
+ return this.southWest = new P(t.lat - r, t.lng - i), this.northEast = new P(n.lat + r, n.lng + i), this;
469
517
  }
470
518
  getSouthWest() {
471
519
  return this.southWest;
@@ -474,10 +522,10 @@ var F = class e {
474
522
  return this.northEast;
475
523
  }
476
524
  getNorthWest() {
477
- return new T(this.getNorth(), this.getWest());
525
+ return new P(this.getNorth(), this.getWest());
478
526
  }
479
527
  getSouthEast() {
480
- return new T(this.getSouth(), this.getEast());
528
+ return new P(this.getSouth(), this.getEast());
481
529
  }
482
530
  getWest() {
483
531
  return this.southWest.lng;
@@ -492,13 +540,13 @@ var F = class e {
492
540
  return this.northEast.lat;
493
541
  }
494
542
  static equals(e, t) {
495
- return T.equals(e.northEast, t.northEast) && T.equals(e.southWest, t.southWest);
543
+ return P.equals(e.northEast, t.northEast) && P.equals(e.southWest, t.southWest);
496
544
  }
497
545
  equals(t) {
498
546
  return e.equals(this, t);
499
547
  }
500
548
  static fromArray(t) {
501
- return new e(new T(t[3], t[2]), new T(t[1], t[0]));
549
+ return new e(new P(t[3], t[2]), new P(t[1], t[0]));
502
550
  }
503
551
  static fromCoordinates(t) {
504
552
  return t.length === 0 ? null : t.reduce((e, t) => e.extend(t), new e(t[0], t[0]));
@@ -511,7 +559,7 @@ var F = class e {
511
559
  this.getNorth()
512
560
  ];
513
561
  }
514
- }, I = class e {
562
+ }, G = class e {
515
563
  x;
516
564
  y;
517
565
  z;
@@ -556,7 +604,7 @@ var F = class e {
556
604
  static fromJson(t) {
557
605
  return new e(t.x, t.y, t.z, t.time, t.accuracy, t.bearing);
558
606
  }
559
- }, L = class extends I {}, R = class t {
607
+ }, K = class extends G {}, q = class t {
560
608
  scale = 1;
561
609
  heading = 0;
562
610
  origin;
@@ -569,7 +617,7 @@ var F = class e {
569
617
  0,
570
618
  0,
571
619
  1
572
- ], this.heading), a = e.multiply(i, this.origin.enuToEcefRotation), o = e.rotate(a, r), c = n.sum(this.origin.ecef, o), l = T.fromECEF(c), u = l.alt;
620
+ ], -this.heading), a = e.multiply(this.origin.enuToEcefRotation, i), o = e.rotate(a, r), c = n.sum(this.origin.ecef, o), l = P.fromECEF(c), u = l.alt;
573
621
  l.heightFromGround = l.alt - this.origin.alt;
574
622
  let d = (e) => {
575
623
  l.level = e.id, l.heightFromFloor = u - e.floorAltitude;
@@ -587,7 +635,7 @@ var F = class e {
587
635
  0,
588
636
  0,
589
637
  1
590
- ], -this.heading), i = e.multiply(this.origin.ecefToEnuRotation, r), a = n.subtract(t.ecef, this.origin.ecef), o = n.multiplyScalar(a, 1 / this.scale);
638
+ ], this.heading), i = e.multiply(r, this.origin.ecefToEnuRotation), a = n.subtract(t.ecef, this.origin.ecef), o = n.multiplyScalar(a, 1 / this.scale);
591
639
  return e.rotate(i, o);
592
640
  }
593
641
  toJson() {
@@ -598,10 +646,10 @@ var F = class e {
598
646
  };
599
647
  }
600
648
  static fromJson(e) {
601
- let n = new t(T.fromJson(e.origin));
649
+ let n = new t(P.fromJson(e.origin));
602
650
  return n.scale = e.scale === void 0 ? 1 : e.scale, n.heading = e.heading === void 0 ? 0 : e.heading, n;
603
651
  }
604
- }, z = class n {
652
+ }, J = class n {
605
653
  _quaternion = [
606
654
  1,
607
655
  0,
@@ -684,7 +732,7 @@ var F = class e {
684
732
  let o = null;
685
733
  return t.accuracy !== null && r.accuracy !== null && (o = Math.max(r.accuracy - t.accuracy)), new n(i, a, o);
686
734
  }
687
- }, B = class t {
735
+ }, Y = class t {
688
736
  heading;
689
737
  time = null;
690
738
  _accuracy = null;
@@ -699,7 +747,7 @@ var F = class e {
699
747
  this._accuracy = e;
700
748
  }
701
749
  toAttitude() {
702
- return new z(e.fromAxisAngle([
750
+ return new J(e.fromAxisAngle([
703
751
  0,
704
752
  0,
705
753
  1
@@ -726,4 +774,4 @@ var F = class e {
726
774
  }
727
775
  };
728
776
  //#endregion
729
- export { B as AbsoluteHeading, z as Attitude, F as BoundingBox, u as Constants, T as Coordinates, R as GeoRef, L as GeoRelativePosition, w as Level, I as RelativePosition, E as UserPosition, D as Utils };
777
+ export { Y as AbsoluteHeading, J as Attitude, W as BoundingBox, u as Constants, P as Coordinates, q as GeoRef, K as GeoRelativePosition, T as Level, G as RelativePosition, F as UserPosition, I as Utils };
@@ -1,5 +1,9 @@
1
1
  export declare const R_MAJOR = 6378137;
2
- export declare const R_MINOR = 6356752.3142;
2
+ /**
3
+ * R_MAJOR * (1 - ELLIPSOID_FLATNESS), to the last bit. Kept as a literal so it stays a
4
+ * literal type for consumers, but the flattening below is the primitive one.
5
+ */
6
+ export declare const R_MINOR = 6356752.314245179;
3
7
  export declare const EARTH_GRAVITY = 9.80665;
4
8
  /**
5
9
  * latitude and longitude epsilon in degrees
@@ -10,6 +14,7 @@ export declare const EPS_DEG_MM = 1e-8;
10
14
  * epsilon in meters which corresponds to 1 millimeter
11
15
  */
12
16
  export declare const EPS_MM = 0.001;
17
+ /** WGS84 defines the flattening, and derives the semi-minor axis from it. */
13
18
  export declare const ELLIPSOID_FLATNESS: number;
14
19
  export declare const ECCENTRICITY: number;
15
20
  export declare const ECCENTRICITY_2: number;
@@ -18,4 +23,9 @@ export declare const R_MAJOR_4: number;
18
23
  export declare const R_MINOR_2: number;
19
24
  export declare const R_MINOR_4: number;
20
25
  export declare const CIRCUMFERENCE: number;
26
+ /**
27
+ * Second (polar) eccentricity squared, e'^2 = (a^2 - b^2) / b^2.
28
+ * Used by the geodetic <-> ECEF conversion.
29
+ */
30
+ export declare const SECOND_ECCENTRICITY_2: number;
21
31
  //# sourceMappingURL=Constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../../src/Constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAY,CAAC;AACjC,eAAO,MAAM,OAAO,eAAe,CAAC;AACpC,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC;;;GAGG;AACH,eAAO,MAAM,UAAU,OAAO,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,MAAM,QAAO,CAAC;AAG3B,eAAO,MAAM,kBAAkB,QAAgC,CAAC;AAEhE,eAAO,MAAM,YAAY,QAA2D,CAAC;AACrF,eAAO,MAAM,cAAc,QAA8B,CAAC;AAE1D,eAAO,MAAM,SAAS,QAAoB,CAAC;AAC3C,eAAO,MAAM,SAAS,QAAwB,CAAC;AAC/C,eAAO,MAAM,SAAS,QAAoB,CAAC;AAC3C,eAAO,MAAM,SAAS,QAAwB,CAAC;AAC/C,eAAO,MAAM,aAAa,QAAwB,CAAC"}
1
+ {"version":3,"file":"Constants.d.ts","sourceRoot":"","sources":["../../src/Constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAY,CAAC;AACjC;;;GAGG;AACH,eAAO,MAAM,OAAO,oBAAoB,CAAC;AACzC,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC;;;GAGG;AACH,eAAO,MAAM,UAAU,OAAO,CAAC;AAE/B;;GAEG;AACH,eAAO,MAAM,MAAM,QAAO,CAAC;AAG3B,6EAA6E;AAC7E,eAAO,MAAM,kBAAkB,QAAoB,CAAC;AAEpD,eAAO,MAAM,YAAY,QAA2D,CAAC;AACrF,eAAO,MAAM,cAAc,QAA8B,CAAC;AAE1D,eAAO,MAAM,SAAS,QAAoB,CAAC;AAC3C,eAAO,MAAM,SAAS,QAAwB,CAAC;AAC/C,eAAO,MAAM,SAAS,QAAoB,CAAC;AAC3C,eAAO,MAAM,SAAS,QAAwB,CAAC;AAC/C,eAAO,MAAM,aAAa,QAAwB,CAAC;AAEnD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAsC,CAAC"}
@@ -24,9 +24,19 @@ export declare function calcDistance(coords: Coordinates[]): number;
24
24
  export declare function createSegmentsAtLevel(itineraryCoords: Coordinates[], segmentsLevel: Level_t, useMultiLevelSegments?: boolean): Coordinates[][];
25
25
  /**
26
26
  * Computes the intersection point of two WGS84 segments.
27
- * Uses a local planar projection in meters (valid approximation for short-to-medium distances).
28
27
  * Returns null if segments are parallel or do not intersect.
29
28
  * Note: it does not use level information.
29
+ *
30
+ * The projection below is linear, so it maps lines to lines: the intersection point comes out
31
+ * the same for any kLat / kLng, spherical or ellipsoidal, because the factors cancel on the
32
+ * way out. They are kept because they make the code read as metres, and because the parallel
33
+ * test is not scale invariant: denom is in projected units, so its 1e-10 threshold means
34
+ * square metres. Make that epsilon relative before changing the factors.
35
+ *
36
+ * What the result does approximate is treating the segments as straight in lat/lng rather than
37
+ * as geodesics, which is off by 0.6mm on 100m segments and grows with the square of their
38
+ * length (5.6cm at 1km, 5.6m at 10km). Only Edge.intersection uses it, on graph edges, so
39
+ * that is well inside the noise.
30
40
  */
31
41
  export declare function segmentIntersection(a1: Coordinates, a2: Coordinates, b1: Coordinates, b2: Coordinates): Coordinates | null;
32
42
  //# sourceMappingURL=Utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../src/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,YAAY,MAAM,4BAA4B,CAAC;AAEtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D;;;;;GAKG;AACH,wBAAgB,WAAW,CACvB,KAAK,EAAE,WAAW,EAAE,EACpB,QAAQ,SAAM,EACd,aAAa,SAAI,EACjB,MAAM,SAAmB,iBAwD5B;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,aAAa,cAAW,EAAE,MAAM,SAAmB,iBAqDlG;AAGD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,cAAc,SAAa,iBA0B/E;AAED,wBAAgB,iCAAiC,CAAC,mBAAmB,EAAE,mBAAmB,uBAYzF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,UAGjD;AAGD,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,qBAAqB,UAAO,mBA2BzH;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAChC,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,GAC7B,WAAW,GAAG,IAAI,CAmCxB"}
1
+ {"version":3,"file":"Utils.d.ts","sourceRoot":"","sources":["../../src/Utils.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,2BAA2B,CAAC;AACpD,OAAO,YAAY,MAAM,4BAA4B,CAAC;AAEtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D;;;;;GAKG;AACH,wBAAgB,WAAW,CACvB,KAAK,EAAE,WAAW,EAAE,EACpB,QAAQ,SAAM,EACd,aAAa,SAAI,EACjB,MAAM,SAAmB,iBAwD5B;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,aAAa,cAAW,EAAE,MAAM,SAAmB,iBAqDlG;AAGD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,EAAE,cAAc,SAAa,iBA0B/E;AAED,wBAAgB,iCAAiC,CAAC,mBAAmB,EAAE,mBAAmB,uBAYzF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,UAGjD;AAGD,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,WAAW,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,qBAAqB,UAAO,mBA2BzH;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAC/B,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAChC,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,GAC7B,WAAW,GAAG,IAAI,CAmCxB"}
@@ -7,9 +7,20 @@ import { CoordinatesCompressedJson, CoordinatesJson, Level_t } from '../types';
7
7
  * Basic geo methods are directly accessibles from here:
8
8
  * distanceTo, bearingTo, toEcef...
9
9
  *
10
- * /!\ This class has been adapted to use earth as a sphere and not as an ellipsoid
11
- * /!\ So, this class does not stricly represent WGS84 coordinates anymore
12
- * /!\ This modifications have been made for computational improvements.
10
+ * Coordinates are WGS84 and every transformation here uses the ellipsoid, so the local up
11
+ * axis is the ellipsoid normal and the ECEF / ENU geometry reads `alt` as a height above the
12
+ * ellipsoid.
13
+ *
14
+ * What `alt` actually carries is not settled across the SDK, and that predates this class:
15
+ * the position providers put a height above the ground in it (Constants.DEFAULT_ALTITUDE is
16
+ * 1.6m, a phone in a hand), while GeoRef.localToWorld compares it against the absolute
17
+ * floorAltitude / ceilingAltitude of a building level. Both cannot be right. Only differences
18
+ * matter to the geometry here, which is why the ambiguity has never surfaced as a bug, but
19
+ * level detection does depend on the answer.
20
+ *
21
+ * (Until 2026-08 this class modelled the earth as a sphere of radius R_MAJOR for speed. That
22
+ * cost ~0.35% of anisotropic scale error at mid-latitude and tilted the local vertical by
23
+ * 11.5', i.e. ~33cm of altitude error per 100m of horizontal travel.)
13
24
  */
14
25
  declare class Coordinates {
15
26
  private _lat;
@@ -19,6 +30,7 @@ declare class Coordinates {
19
30
  private _heightFromFloor;
20
31
  private _heightFromGround;
21
32
  private _ecef;
33
+ private _groundEcef;
22
34
  autoWrap: boolean;
23
35
  constructor(lat: number, lng: number, alt?: number | null, level?: Level_t | null);
24
36
  get lat(): number;
@@ -32,6 +44,7 @@ declare class Coordinates {
32
44
  /**
33
45
  * alt does not denote the altitude of a point but its height from
34
46
  * the "level" field (if defined) or from the ground
47
+ * /!\ This is the providers' convention, not GeoRef's: see the class header.
35
48
  */
36
49
  get alt(): number | null;
37
50
  set alt(alt: number | null);
@@ -55,33 +68,62 @@ declare class Coordinates {
55
68
  */
56
69
  destinationPoint(distance: number, bearing: number, elevation?: number | null): Coordinates;
57
70
  /**
58
- * Source: http://www.movable-type.co.uk/scripts/latlong.html#destPoint
71
+ * Moves the point by a ground distance (in meters) along a bearing, on the WGS84 ellipsoid.
72
+ * The displacement is built in the local ENU frame as the chord of the arc travelled, then
73
+ * converted back through ECEF.
74
+ * ponytail: micrometer-accurate at working range (7um at 10km), then degrades as
75
+ * distance^3 / radius^2 (7mm at 100km, ~20m at 1200km). Use Karney's geodesics if
76
+ * continental distances ever matter.
59
77
  * @throws {Error} if elevation is defined and point altitude is not defined
60
78
  */
61
79
  move(distance: number, bearing: number, elevation?: number | null): this;
62
80
  /**
63
- * Returns a distance between two points in meters
81
+ * Returns the ground distance between two points in meters, on the WGS84 ellipsoid.
82
+ * Altitudes are ignored, as many callers compare positions across levels.
83
+ *
84
+ * The chord between the two ECEF points is exact; converting it back to an arc length on
85
+ * the locally fitting sphere is what costs accuracy, and it costs very little: 3nm at
86
+ * 340m, 3um at 14km, 1.2m at 557km.
87
+ *
88
+ * The one case where this is worse than the old haversine is a path along the equator,
89
+ * where the arc radius is R_MAJOR but the Gaussian radius is R_MINOR: 264m over 3340km,
90
+ * 9.3km over 10000km, against an exact haversine there. Everywhere else, and at every
91
+ * distance this SDK works at, it is orders of magnitude better.
64
92
  */
65
93
  distanceTo(location2: Coordinates): number;
66
94
  static distanceBetween(point1: Coordinates, point2: Coordinates): number;
95
+ /**
96
+ * Azimuth to another point, in radians, clockwise from north.
97
+ * Taken in the local ENU frame, so it matches the true geodesic azimuth within 0.02" even
98
+ * at 100km.
99
+ */
67
100
  bearingTo(location2: Coordinates): number;
68
101
  static bearingTo(point1: Coordinates, point2: Coordinates): number;
69
102
  /**
70
- * ECEF Transformations
71
- * Here we used a light version of ECEF considering earth
72
- * as a sphere instead of an ellipse
103
+ * ECEF Transformations (WGS84 ellipsoid)
73
104
  */
74
105
  get enuToEcefRotation(): Quaternion_t;
75
106
  get ecefToEnuRotation(): Quaternion_t;
76
107
  /**
77
108
  * https://gist.github.com/klucar/1536194
78
- * Adapted for spherical formula
79
109
  */
80
110
  get ecef(): Vector3_t;
111
+ /**
112
+ * ECEF at altitude 0, for the ground-level geometry of distanceTo, move and bearingTo.
113
+ * The cached ecef already is that vector whenever alt is null or 0, which is both the
114
+ * common case and the hot one: the routing graph measures the same vertices thousands of
115
+ * times, and OsrmRemoteRouter walks hundreds of millions of pairs on a long route.
116
+ */
117
+ private get groundEcef();
81
118
  static fromECEF(ecef: Vector3_t): Coordinates;
82
119
  /**
83
120
  * https://stackoverflow.com/questions/1299567/how-to-calculate-distance-from-a-point-to-a-line-segment-on-a-sphere
84
- * Adapted to ECEF
121
+ *
122
+ * Great-circle geometry, so it stays on the sphere: normalizing an ellipsoidal ECEF
123
+ * vector would yield a geocentric direction and shift the projection by tens of meters.
124
+ * The closure test that rejects a point off the segment measures angles between the same
125
+ * unit vectors, for the same reason: mixing in the geodesic distanceTo would compare a
126
+ * great circle with a geodesic and reject valid projections on long segments.
85
127
  */
86
128
  getSegmentProjection(p1: Coordinates, p2: Coordinates): Coordinates | null;
87
129
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Coordinates.d.ts","sourceRoot":"","sources":["../../../src/coordinates/Coordinates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Coordinates.d.ts","sourceRoot":"","sources":["../../../src/coordinates/Coordinates.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,12 @@ import { BuildingLevel, GeoRefJson } from '../types';
3
3
  import { default as Coordinates } from './Coordinates';
4
4
  declare class GeoRef {
5
5
  scale: number;
6
+ /**
7
+ * Orientation of the local frame, in radians, clockwise from north, around the local
8
+ * vertical. Clockwise because that is the convention everything user-facing uses here
9
+ * (Coordinates#bearingTo, AbsoluteHeading, Rotations.getHeadingFromQuaternion), which is
10
+ * why the rotations below negate it to work in the counter-clockwise ENU frame.
11
+ */
6
12
  heading: number;
7
13
  origin: Coordinates;
8
14
  buildingLevels: BuildingLevel[];
@@ -1 +1 @@
1
- {"version":3,"file":"GeoRef.d.ts","sourceRoot":"","sources":["../../../src/coordinates/GeoRef.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,cAAM,MAAM;IAER,KAAK,SAAK;IACV,OAAO,SAAK;IACZ,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc,EAAE,aAAa,EAAE,CAAC;gBAEpB,MAAM,EAAE,WAAW,EAAE,cAAc,GAAE,aAAa,EAAO;IAKrE;;OAEG;IACH,YAAY,CAAC,aAAa,EAAE,SAAS;IAyFrC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,WAAW;IAQhC,MAAM,IAAI,UAAU;IAQpB,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU;CAMnC;AAED,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"GeoRef.d.ts","sourceRoot":"","sources":["../../../src/coordinates/GeoRef.ts"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE1D,OAAO,WAAW,MAAM,eAAe,CAAC;AAExC,cAAM,MAAM;IAER,KAAK,SAAK;IAEV;;;;;OAKG;IACH,OAAO,SAAK;IAEZ,MAAM,EAAE,WAAW,CAAC;IACpB,cAAc,EAAE,aAAa,EAAE,CAAC;gBAEpB,MAAM,EAAE,WAAW,EAAE,cAAc,GAAE,aAAa,EAAO;IAKrE;;OAEG;IACH,YAAY,CAAC,aAAa,EAAE,SAAS;IA8FrC;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,WAAW;IAQhC,MAAM,IAAI,UAAU;IAQpB,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,UAAU;CAMnC;AAED,eAAe,MAAM,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import('vite').UserConfig;
2
+ export default _default;
3
+ //# sourceMappingURL=vite.config.cdn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.config.cdn.d.ts","sourceRoot":"","sources":["../vite.config.cdn.ts"],"names":[],"mappings":";AAMA,wBAAuE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wemap/geo",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "description": "Geospatial primitives (coordinates, levels, bounding boxes) for the Wemap SDK.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "Wemap SAS",
@@ -38,8 +38,8 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@turf/boolean-point-in-polygon": "^7.3.4",
41
- "@wemap/maths": "14.6.0",
42
- "@wemap/utils": "14.6.0"
41
+ "@wemap/maths": "14.7.0",
42
+ "@wemap/utils": "14.7.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/geojson": "^7946.0.14",