@expofp/floorplan
Version:
Interactive floor plan library for expos and events
2 lines (1 loc) • 1.65 kB
JavaScript
import{pointInPolygon as E}from"../geometry/pointInPolygon";import{projectPointOnSegment as O}from"../geometry/projectPointOnSegment";function D(o,a){let y=0;for(const n of o){const t=Math.hypot(n.p1.x-n.p0.x,n.p1.y-n.p0.y);if(t!==0){if(y+t>=a){const r=(a-y)/t,h=n.p0.x+(n.p1.x-n.p0.x)*r,s=n.p0.y+(n.p1.y-n.p0.y)*r;return{point:{layer:n.p0.layer,x:h,y:s},line:n}}y+=t}}const i=o[o.length-1];return{point:{layer:i.p0.layer,x:i.p1.x,y:i.p1.y},line:i}}export{SNAP_THRESHOLD_METERS}from"./gpsThreshold";export function snapToRoute(o,a,y){const i=a.length;if(!i)return{snapped:!1};const{snapThreshold:n,to:t,from:r,minRemainingUnits:h=.5}=y,s=o.layer||null;let P=1/0,u=null,m=0,F=s==null;for(let e=0;e<i;e++){const f=a[e],{p0:l,p1:c}=f,S=Math.hypot(c.x-l.x,c.y-l.y);if(S===0)continue;if(s!=null&&String(l.layer)!==s){m+=S;continue}F=!0;const g=O({x:o.x,y:o.y},l,c);g.distance<P&&(P=g.distance,u={segmentIndex:e,t:g.t,distanceFromPolylineStart:m+S*g.t}),m+=S}if(s!=null&&!F)return{snapped:!1};const p=m,b=a[0].p0,M=a[i-1].p1,A=Math.hypot(t.x-b.x,t.y-b.y),I=Math.hypot(t.x-M.x,t.y-M.y),x=A<=I,T=Math.min(h,p);if(r?.bounds&&(s==null||!r.layer||r.layer===s)&&E({x:o.x,y:o.y},r.bounds)){const e=p,f=x?e:p-e,l=D(a,f);return{snapped:!0,snappedPoint:l.point,snappedLine:l.line,distance:e}}if(t.bounds&&(s==null||!t.layer||t.layer===s)&&E({x:o.x,y:o.y},t.bounds)){const e=T,f=p-e,c=D(a,x?e:f);return{snapped:!0,snappedPoint:c.point,snappedLine:c.line,distance:e}}if(!u||P>n)return{snapped:!1};let d=x?u.distanceFromPolylineStart:p-u.distanceFromPolylineStart;d<T&&(d=T);const L=p-d,R=D(a,x?d:L);return{snapped:!0,snappedPoint:R.point,snappedLine:R.line,distance:d}}