UNPKG

@expofp/floorplan

Version:

Interactive floor plan library for expos and events

2 lines (1 loc) 3.48 kB
import{MercatorCoordinate as F}from"maplibre-gl";const S=1e-12,g=3.28084,y=6371e3,O=1,k=.02;export function calculateTransformMatrix(t,i){let r,a;try{r=q(t),a="perpendicular"}catch(h){if(!t.p1)throw h;r=t.p1,a="explicit-fallback"}const o=G(t);a==="perpendicular"&&o?.inconsistent&&console.warn("Maplibre geo: ignoring inconsistent anchor p1; placing venue from the p0->p2 diagonal.",{angleErrorDeg:o.angleErrorDeg,sideRatioError:o.ratioError});const n=[t.p0,r,t.p2],s=[],c=[],e=[];for(const h of n){B(h),c.push([h.x,h.y]);const p=F.fromLngLat([h.lng,h.lat],0),d=p.meterInMercatorCoordinateUnits();M(p.x),M(p.y),M(d),s.push(d),e.push([p.x,p.y])}const l=[],E=[];for(let h=0;h<3;h++){const[p,d]=c[h],[A,L]=e[h];l.push([p,d,1,0,0,0]),E.push(A),l.push([0,0,0,p,d,1]),E.push(L)}const P=V(l,E),[R,w,D,T,I,N]=P,_=i?.toLowerCase?.().trim()==="ft"?1/g:1,v=s.reduce((h,p)=>h+p,0)/s.length*_,f=[R,T,0,0,w,I,0,0,0,0,v,0,D,N,0,1];if(!f.every(Number.isFinite))throw new Error("Cannot calculate Maplibre transform: geo anchor points produced a non-finite matrix.");return f}function G(t){const i=t.p1;if(!i)return null;const r=Z(t.p0.x,t.p0.y,i.x,i.y,t.p2.x,t.p2.y),a=j(t.p0,i,t.p2),o=Math.abs(r.angleDeg-a.angleDeg),n=Number.isFinite(a.axisRatio)&&a.axisRatio>0?Math.abs(r.axisRatio/a.axisRatio-1):1/0;return{angleErrorDeg:o,ratioError:n,inconsistent:o>O||n>k}}function Z(t,i,r,a,o,n){const s=Math.hypot(r-t,a-i),c=Math.hypot(o-t,n-i),e=(r-t)*(o-t)+(a-i)*(n-i),l=s>0&&c>0?e/(s*c):NaN;return{axisRatio:s>0?c/s:1/0,angleDeg:m(Math.acos(Math.max(-1,Math.min(1,l))))}}function j(t,i,r){const a=x(t.lat,t.lng,i.lat,i.lng),o=x(t.lat,t.lng,r.lat,r.lng),n=b(t.lat,t.lng,i.lat,i.lng),s=b(t.lat,t.lng,r.lat,r.lng);let c=Math.abs(s-n)%360;return c>180&&(c=360-c),{axisRatio:a>0?o/a:1/0,angleDeg:c}}function q(t){const i=t.p2.x-t.p0.x,r=t.p2.y-t.p0.y;if(i===0&&r===0)throw new Error("Cannot calculate Maplibre transform: p0 and p2 have identical SVG coordinates.");const a=t.p0.x-r,o=t.p0.y+i,n=x(t.p0.lat,t.p0.lng,t.p2.lat,t.p2.lng),s=b(t.p0.lat,t.p0.lng,t.p2.lat,t.p2.lng),[c,e]=U(t.p0.lat,t.p0.lng,n,s+90);return{x:a,y:o,lat:e,lng:c}}function B(t){M(t.x),M(t.y),M(t.lat),M(t.lng)}function M(t){if(!Number.isFinite(t))throw new Error("Cannot calculate Maplibre transform: geo anchor points contain invalid coordinates.")}function u(t){return t*Math.PI/180}function m(t){return t*180/Math.PI}function x(t,i,r,a){const o=u(t),n=u(r),s=u(r-t),c=u(a-i),e=Math.sin(s/2)*Math.sin(s/2)+Math.cos(o)*Math.cos(n)*Math.sin(c/2)*Math.sin(c/2),l=2*Math.atan2(Math.sqrt(e),Math.sqrt(1-e));return y*l}function b(t,i,r,a){const o=u(t),n=u(r),s=u(a-i),c=Math.sin(s)*Math.cos(n),e=Math.cos(o)*Math.sin(n)-Math.sin(o)*Math.cos(n)*Math.cos(s);return(m(Math.atan2(c,e))+360)%360}function U(t,i,r,a){const o=r/y,n=u(a),s=u(t),c=u(i),e=Math.asin(Math.sin(s)*Math.cos(o)+Math.cos(s)*Math.sin(o)*Math.cos(n)),l=c+Math.atan2(Math.sin(n)*Math.sin(o)*Math.cos(s),Math.cos(o)-Math.sin(s)*Math.sin(e));return[m(l),m(e)]}function V(t,i){const r=t.length,a=t.map((n,s)=>[...n,i[s]]);for(let n=0;n<r;n++){let s=n;for(let c=n+1;c<r;c++)Math.abs(a[c][n])>Math.abs(a[s][n])&&(s=c);if([a[n],a[s]]=[a[s],a[n]],Math.abs(a[n][n])<S)throw new Error("Cannot calculate Maplibre transform: geo anchor points are collinear or invalid.");for(let c=n+1;c<r;c++){const e=a[c][n]/a[n][n];for(let l=n;l<=r;l++)a[c][l]-=e*a[n][l]}}const o=new Array(r);for(let n=r-1;n>=0;n--){o[n]=a[n][r];for(let s=n+1;s<r;s++)o[n]-=a[n][s]*o[s];o[n]/=a[n][n]}return o}