memoscan
← all memos

Memo 0xdf2326c7…d47818 on Ethereum

prevhedge=m,m.nexthedge=h;else{const e=d.hedgelist.indexOf(h);let t,n;0===e?(t=d.hedgelist[d.hedgelist.length-1],n=d.hedgelist[(e+1)%d.hedgelist.length]):(t=d.hedgelist[e-1],n=d.hedgelist[(e+1)%d.hedgelist.length]),h.prevhedge=t.twin,t.twin.nexthedge=h,m.nexthedge=n,n.prevhedge=m}if(r)m.prevhedge=h,h.nexthedge=m;else{const e=u.hedgelist.indexOf(m);let t,n;0===e?(t=u.hedgelist[u.hedgelist.length-1],n=u.hedgelist[(e+1)%u.hedgelist.length]):(t=u.hedgelist[e-1],n=u.hedgelist[(e+1)%u.hedgelist.length]),m.prevhedge=t.twin,t.twin.nexthedge=m,h.nexthedge=n,n.prevhedge=h}const p=h.nexthedge,g=m.nexthedge;if(p.face){const e=s.indexOf(p.face);e>-1&&s.splice(e,1),p.face.dispose(),p.face.area<=this.tolerance&&(c=!0)}if(g.face){const e=s.indexOf(g.face);e>-1&&s.splice(e,1),g.face.dispose(),g.face.area<=this.tolerance&&(c=!0)}const b=new Rn(this);b.wedge=p;let f=new Rn(this);if(f.wedge=g,b.equals(f)&&(f.dispose(),f=null),b){let e=b.wedge;for(e.face=b;e.nexthedge!==b.wedge;)e=e.nexthedge,e.face=b;b.area<=this.tolerance&&(c=!0),s.push(b)}if(f){let e=f.wedge;for(e.face=f;e.nexthedge!==f.wedge;)e=e.nexthedge,e.face=f;f.area<=this.tolerance&&(c=!0),s.push(f)}if(c)for(let e=0,t=s.length;e<t;e++)s[e]._holesDirty=!0}removeEdge(e,t,n,i){const{vertices:l,hedges:a,faces:s}=this,o=this.findHedge(e,t,n,i);if(!o)return;const r=o.twin,c=o.nexthedge,d=r.nexthedge;let u,h=!0,m=!0,p=!1;if(u=a.indexOf(o),a.splice(u,1),u=a.indexOf(r),a.splice(u,1),u=s.indexOf(o.face),u>-1&&s.splice(u,1),o.face.dispose(),o.face.area<=this.tolerance&&(p=!0),u=s.indexOf(r.face),u>-1&&s.splice(u,1),r.face.dispose(),r.face.area<=this.tolerance&&(p=!0),u=o.origin.hedgelist.indexOf(o),o.origin.hedgelist.splice(u,1),o.origin.hedgelist.length>0){let e,t;0===u?(e=o.origin.hedgelist[o.origin.hedgelist.length-1],t=o.origin.hedgelist[u]):(e=o.origin.hedgelist[u-1],t=o.origin.hedgelist[u%o.origin.hedgelist.length]),t.prevhedge=e.twin,e.twin.nexthedge=t}else this.deleteVertex(o.origin),m=!1;if(u=r.origin.hedgelist.indexOf(r),r.origin.hedgelist.splice(u,1),r.origin.hedgelist.length>0){let e,t;0===u?(e=r.origin.hedgelist[r.origin.hedgelist.length-1],t=r.origin.hedgelist[u]):(e=r.origin.hedgelist[u-1],t=r.origin.hedgelist[u%r.origin.hedgelist.length]),t.prevhedge=e.twin,e.twin.nexthedge=t}else this.deleteVertex(r.origin),h=!1;o.dispose(),r.dispose();const g=h?new Rn(this):null;g&&(g.wedge=c);let b=m?new Rn(this):null;if(b&&(b.wedge=d),g&&b)try{g.equals(b)&&(b.dispose(),b=null)}catch{b=null}if(g){let e=g.wedge;for(e.face=g;e.nexthedge!==g.wedge;){if(e=e.nexthedge,!e.face)return;e.face=g}g.area<=this.tolerance&&(p=!0),s.push(g)}if(b){let e=b.wedge;for(e.face=b;e.nexthedge!==b.wedge;)e=e.nexthedge,e.face=b;b.area<=this.tolerance&&(p=!0),s.push(b)}if(p)for(let e=0,t=s.length;e<t;e++)s[e]._holesDirty=!0}splitEdge(e,t,n,i,l,a){const{vertices:s,hedges:o}=this;let r=this.findVertex(l,a),c=this.findHedge(e,t,n,i);if(!c)return!1;if(r)return!0;const d=c.twin;let u;const h=this.addVertex(l,a),m=new Gn(h,c.origin),p=new Gn(d.origin,h);o.push(m),o.push(p);const g=new Gn(h,d.origin),b=new Gn(c.origin,h);return o.push(g),o.push(b),c.face.wedge===c&&(c.face.wedge=m),c.face._vertexlistDirty=!0,m.face=c.face,p.face=c.face,d.face.wedge===d&&(d.face.wedge=g),d.face._vertexlistDirty=!0,g.face=d.face,b.face=d.face,m.nexthedge=p,p.prevhedge=m,g.nexthedge=b,b.prevhedge=g,m.prevhedge=c.prevhedge!==d?c.prevhedge:b,m.prevhedge.nexthedge=m,p.nexthedge=c.nexthedge!==d?c.nexthedge:g,p.nexthedge.prevhedge=p,g.prevhedge=d.prevhedge!==c?d.prevhedge:p,g.prevhedge.nexthedge=g,b.nexthedge=d.nexthedge!==c?d.nexthedge:m,b.nexthedge.prevhedge=b,m.twin=b,p.twin=g,g.twin=p,b.twin=m,h.hedgelist.push(p,b),u=c.origin.hedgelist.indexOf(c),c.origin.hedgelist.splice(u,1,m),u=d.origin.hedgelist.indexOf(d),d.origin.hedgelist.splice(u,1,g),c.dispose(),d.dispose(),u=o.indexOf(c),o.splice(u,1),u=o.indexOf(d),o.splice(u,1),{h1:m,h2:p}}intersectFaceWithPolyLine(e,t,n=!1,i=!1){let l=[],a=i?t.length:t.length-1;for(let i=0;i<a;i++){let a=[t[i],t[(i+1)%t.length]];if(l.push(...e.intersectWithLineSeg(a.map((e=>(new zt).fromArray(e))))),n&&l.length>=2)break}return l}getFacesAtPoint(e){let t=[],n=new zt(...e);for(let e of this.faces)e.aabb.containsPoint(n)&&e.containsPoint(n)&&t.push(e);return t}getFacesIntersectingPoly(e){let t=e.map((e=>(new zt).fromArray(e))),n=new nn;n.expands(t);let i=[];for(let l of this.faces)if(!(l.area<=this.tolerance)&&n.intersects(l.aabb)){if(Mn(t,l.vertexlist)){i.push({face:l,intersections:[],isContained:!0});continue}let n=[];for(let i=0;i<e.length;i++){let a=[t[i],t[(i+1)%e.length]];n.push(...l.intersectWithLineSeg(a))}n.length>0&&i.push({face:l,intersections:n,isContained:!1})}return i}}class Ln extends vn{tolerance;constructor(e,t,n=Wn){super(e,t,n),this.tolerance=n}isPolyLineSegmentOnEdge(e,t){for(let n=0;n<t.length-1;n++){let i=[t[n],t[n+1]];if(this.isLineSegmentOnEdgeOfFace(e,i),this.tolerance)return!0}}isLineSegmentOnEdgeOfFace(e,t,n=b){for(let i=0;i<e.vertexlist.length;i++)if(Sn([e.vertexlist[i].toArray(),e.vertexlist[(i+1)%e.vertexlist.length].toArray()],t),n)return!0;return!1}getFacesIntersectingAABB(e){let t=[];for(let n of this.faces.filter((e=>e.area>0)))e.intersects(n.aabb,this.tolerance)&&t.push(n);return t}removeEdgesInsidePolygon(e,t=100){let n=new nn;n.expands(e.map((e=>(new zt).fromArray(e))));let i=e.map((e=>(new zt).fromArray(e))),l=this.getFacesIntersectingAABB(n),a=[];for(let t of l){let n=t.vertexlist;for(let t=0;t<n.length;t++){let l=n[t],s=n[(t+1)%n.length];if(!Tn(i,l,this.tolerance)||!Tn(i,s,this.tolerance))continue;let o=0;[l,s].forEach((t=>{Cn(t.toArray(),e,this.tolerance)&&o++})),o>1||a.push([l,s])}}for(let e of a)J.bool(t)&&this.removeEdge(e[0].x,e[0].y,e[1].x,e[1].y);this.cleanupTrailingEdges()}insertPolygon(e,t=!0){let n=[],i=new nn;i.expands(e.map((e=>(new zt).fromArray(e)))),i.expandByValue(this.tolerance);let l=this.getFacesIntersectingAABB(i),a=new Set;for(let e of l){let t=e.vertexlist;for(let e=0;e<t.length;e++){let n=t[e],i=t[(e+1)%t.length],l=this.findHedge(n.x,n.y,i.x,i.y);a.has(l.twin)||a.add(l)}}for(let t of e)n.push({type:"addVertex",data:{x:t[0],y:t[1]}});for(let i of a){let l=[];e:for(let a=0;a<(t?e.length:e.length-1);a++){let t=[new zt(...e[a]),new zt(...e[(a+1)%e.length])],s=i.intersectWithLineSegment(t);if(s.type==gn.intersecting){for(let e of l)if(e.isEqualTo(s.point))continue e;n.push({type:"addVertex",data:{x:s.point.x,y:s.point.y}})}}}for(let i=0;i<(t?e.length:e.length-1);i++){let t=[e[i],e[(i+1)%e.length]];n.push({type:"addEdge",data:{from:{x:t[0][0],y:t[0][1]},to:{x:t[1][0],y:t[1][1]}}})}this.executeAddOperations(n)}splitFaceByPolyLine(e,t,n=!1,i=!1,l=!1){const a=(e,t,n,i)=>{const l=[.5,.25,.75];for(let a of l){let l=e.lerp(t,a);if(n.containsPoint(l)&&!n.isPointOnBoundary(l,i))return!0}return!1},s=(e,t,n,i)=>{let l=[.25,.5,.75],a=0;for(let s of l){let l=e.lerp(t,s);if(n.isPointOnBoundary(l,i)&&(a++,a>=2))return!0}return a>=2};let o=[],r=[],c=!1,d=0;if(n){let n=t.findIndex((t=>!e.containsPoint(new zt(...t))||e.isPointOnBoundary(new zt(...t),this.tolerance)));if(!(n>=0))return!1;t=t.slice(n).concat(t.slice(0,n))}const u=n?t.length:t.length-1;for(let n=0;n<u;n++){let i=new zt(...t[n]),l=new zt(...t[(n+1)%t.length]),u=[i,l],h=e.intersectWithLineSeg(u);d+=h.length;let m=[i,...h.map((e=>e.point)),l];m=Xn(i,l,m,!0,this.tolerance);for(let t=0;t<m.length-1;t++){let n=m[t],i=m[t+1];a(n,i,e,this.tolerance)&&!s(n,i,e,this.tolerance)?(c||(r=[n],c=!0),r.push(i)):c&&(o.push(r),r=[],c=!1)}}if(!n&&c&&r.length>1&&o.push(r),i||(o=o.filter((t=>{let n=t[Math.floor(t.length/2)].lerp(t[Math.ceil(t.length/2)],.5);return e.containsPoint(n)}))),o.length>1&&l){let e=null;for(let t of o){let i=0;for(let e=0;e<(n?t.length:t.length-1);e++)i+=t[e].distanceTo(t[(e+1)%t.length]);(!e||i>e.length)&&(e={length:i,line:t})}if(!e)return!1;o=[e.line]}if(0===o.length)return!1;if(i)return{lines:o,intersectionCount:d};let h=[];for(let e of o)for(let t of e)h.push({type:"addVertex",data:{x:t.x,y:t.y}});for(let e of o)for(let t=0;t<e.length-1;t++)h.push({type:"addEdge",data:{from:{x:e[t].x,y:e[t].y},to:{x:e[t+1].x,y:e[t+1].y}}});return this.executeAddOperations(h),!0}executeAddOperations(e){const t=e.filter((e=>"addVertex"===e.type)),n=e.filter((e=>"addEdge"===e.type));let i=[];for(const e of n){let t=new nn,n=new zt(e.data.from.x,e.data.from.y),l=new zt(e.data.to.x,e.data.to.y);t.expands([n,l]),t.expandByValue(this.tolerance);let a=new Set;for(let e of this.hedges){let i=e.getAABB();if(i.expandByValue(this.tolerance),i.intersects(t)){let t=e.intersectWithLineSegment([n,l]);t.type==gn.intersecting&&(a.add(t.point),this.findVertex(t.point.x,t.point.y)||this.splitEdge(e.origin.x,e.origin.y,e.twin.origin.x,e.twin.origin.y,t.point.x,t.point.y))}}if(a.size>1){let e=Xn(n,l,[n,...a,l],!0,this.tolerance);for(let t=0;t<e.length-1;t++)i.push({type:"addEdge",data:{from:{x:e[t].x,y:e[t].y},to:{x:e[t+1].x,y:e[t+1].y}}})}else i.push(e)}for(const e of t){let{x:t,y:n}=e.data;if(!this.findVertex(t,n)){let e=!1;for(let i of this.hedges){let l=i.getAABB();l.expandByValue(this.tolerance),l.containsPoint(new zt(t,n))&&!this.findVertex(t,n)&&Vn([t,n],[i.origin.toArray(),i.twin.origin.toArray()])&&(e=!1!==this.splitEdge(i.origin.x,i.origin.y,i.twin.origin.x,i.twin.origin.y,t,n))}!e&&this.addVertex(t,n)}}for(const e of i.filter((e=>"addEdge"===e.type))){let{from:t,to:n}=e.data,i=this.findVertex(t.x,t.y),l=this.findVertex(n.x,n.y);if(i&&l){let e=new Set;e.add(i);let t=new nn;t.expands([i,l]),t.expandByValue(this.tolerance);for(let n of this.verticesInBB(t))Vn(n.toArray(),[i.toArray(),l.toArray()])&&e.add(n);e.add(l);let n=Xn(i,l,Array.from(e),!0);for(let e=0;e<n.length-1;e++)this.findHedge(n[e].x,n[e].y,n[e+1].x,n[e+1].y)||this.addEdge(n[e].x,n[e].y,n[e+1].x,n[e+1].y)}}}cleanupDegenerateHoles(){let e=new Set;this.faces.forEach((t=>{for(let n of this.faces)t!=n&&t.aabb.containsBB(n.aabb)&&t.vertexlist.every((e=>n.containsPoint(e)))&&n.hedges.forEach((t=>{t.face==n&&e.add(t)}))})),this.faces.filter((e=>e.area>0)).forEach((t=>{t.holes.forEach((n=>{n.hedges.forEach((n=>{n.face==t&&e.add(n)}))}))}));for(const t of e)t.origin&&t.twin.origin&&this.removeEdge(t.origin.x,t.origin.y,t.twin.origin.x,t.twin.origin.y)}cleanupTrailingEdges(){this.hedges.forEach((e=>{e.face==e.twin.face&&this.removeEdge(e.origin.x,e.origin.y,e.twin.origin.x,e.twin.origin.y)}))}}function Sn(e,t,n=b){let[i,l]=e,[a,o]=t;const r=l[0]-i[0],c=l[1]-i[1],u=o[0]-a[0],h=o[1]-a[1];if(s(r*h-c*u)>n)return!1;const m=s(r*(i[1]-a[1])-(i[0]-a[0])*c),p=d(r*r+c*c);return!(p<n)&&m/p<n}function Xn(e,t,n,i=!1,l=b){const a=t.x-e.x,s=t.y-e.y;let o=a*a+s*s;if(o<l)return n;const r=1/o,c=n.map((t=>{const n=((t.x-e.x)*a+(t.y-e.y)*s)*r;return{point:t,t:Math.max(0,Math.min(1,n))}}));c.sort(((t,n)=>{const i=t.t-n.t;return Math.abs(i)>l?i:(t.point.x-e.x)**2+(t.point.y-e.y)**2-((n.point.x-e.x)**2+(n.point.y-e.y)**2)}));let d=c.map((e=>e.point));return i&&(d=function(e,t){const n=[],i=new Map;for(const l of e){const e=`${Math.round(l.x/t)},${Math.round(l.y/t)}`;i.has(e)||(i.set(e,!0),n.push(l))}return n}(d,l)),d}function Cn(e,t,n=b){for(let i=0;i<t.length;i++){const l=t[i],a=t[(i+1)%t.length],s=o(l[0],a[0])-n,c=r(l[0],a[0])+n,d=o(l[1],a[1])+-n,u=r(l[1],a[1])+n;if(e[0]>=s&&e[0]<=c&&e[1]>=d&&e[1]<=u&&wn(e,l,a)<=n*n)return!0}return!1}function Vn(e,t,n=b){const[i,l]=t,a=(e[1]-i[1])*(l[0]-i[0])-(e[0]-i[0])*(l[1]-i[1]);if(Math.abs(a)>n)return!1;const s=(e[0]-i[0])*(l[0]-i[0])+(e[1]-i[1])*(l[1]-i[1]);return!(s<-n||s-((l[0]-i[0])*(l[0]-i[0])+(l[1]-i[1])*(l[1]-i[1]))>n)}function wn(e,t,n){const i=n[0]-t[0],l=n[1]-t[1],a=i*i+l*l;if(a<1e-14){const n=e[0]-t[0],i=e[1]-t[1];return n*n+i*i}let s=((e[0]-t[0])*i+(e[1]-t[1])*l)/a;s=Math.max(0,Math.min(1,s));const o=t[0]+s*i,r=t[1]+s*l,c=e[0]-o,d=e[1]-r;return c*c+d*d}let Kn=0;class Rn{_dcel;id=Kn++;changeIndex=0;wedge=null;_area=0;_areaDirty=!0;_vertexlist=[];_vertexlistDirty=!0;_centerDirty=!0;_hedges=[];_hedgesDirty=!0;_center=null;_hasInsertedIntoPQ=!1;_holes=[];_holesDirty=!0;_aabb=null;_aabbDirty=!0;constructor(e){this._dcel=e}get area(){return this._areaDirty&&(this._area=zn(this.vertexlist),this._areaDirty=!1),this._area}get areaExceptHoles(){const e=this.holes;let t=this.area;for(let n=0,i=e.length;n<i;n++)t+=e[n].area;return t}get internal(){return this.area>Wn}get external(){return this.area<=Wn}get hedges(){if(this._hedgesDirty){const e=[];let t=this.wedge,n=0;const i=1e6;for(e.push(t);t.nexthedge!==this.wedge&&n<i;)t=t.nexthedge,e.push(t),n++;if(n>=i)throw Error("Face vertex list is too long");this._hedges=e,this._hedgesDirty=!1}return this._hedges}get center(){if(this._centerDirty){const e=this.vertexlist;let t=0,n=0,i=0;for(let l=0;l<e.length;l++){const a=e[l].x,s=e[l].y,o=e[(l+1)%e.length].x,r=e[(l+1)%e.length].y,c=a*r-s*o;t+=c,n+=(a+o)*c,i+=(s+r)*c}t*=.5,n/=6*t,i/=6*t,this._center=new zt(n,i),this._centerDirty=!1}return this._center}get vertexlist(){return this._vertexlistDirty&&this.cleanVertexList(),this._vertexlist}cleanVertexList(){if(!this._vertexlistDirty)return;let e=this.wedge;const t=this._vertexlist;t.length=0;let n=0;const i=1e6;for(t.push(e.origin);e.nexthedge!==this.wedge&&n<i;)e=e.nexthedge,t.push(e.origin),n++;if(n>=i)throw Error("Face vertex list is too long");this._vertexlistDirty=!1}get holes(){if(this._holesDirty&&(this._holesDirty=!1,this._holes.length=0,this.internal)){const e=this._dcel.faces;for(let t=0,n=e.length;t<n;t++)this._tryAddHole(e[t])}return this._holes}get aabb(){return this._aabb||(this._aabb=new nn),this._aabbDirty&&(this._aabb.reset(),this._aabb.expands(this.vertexlist),this._aabbDirty=!1),this._aabb}equals(e){const t=this.vertexlist,n=e.vertexlist;if(t.length!==n.length)return!1;const i=t.length;for(let e=0;e<i;e++)for(let l=0;l<i&&t[l]===n[(e+l)%i];l++)if(l===i-1)return!0;return!1}findNearestEdge(e){return function(e,t){const n=Yn(e);let i=[e[0],e[1]],l=1e10,a=-1/0,s=null;for(let o=0;o<e.length;o++){const r=[e[o],e[(o+1)%e.length]],{distance:c,projection:d}=Pn(t,r[0],r[1]),u={x:r[1].x-r[0].x,y:r[1].y-r[0].y};let h={x:-u.y,y:u.x},m={x:(r[0].x+r[1].x)/2-n.x,y:(r[0].y+r[1].y)/2-n.y};h.x*m.x+h.y*m.y<0&&(h={x:u.y,y:-u.x});const p={x:t.x-(r[0].x+r[1].x)/2,y:t.y-(r[0].y+r[1].y)/2},g=h.x*p.x+h.y*p.y;(c<l||c===l&&g>a)&&g>0&&(l=c,i=r,a=g,s=d)}return{edge:i,distance:l,edgePoint:s}}(this.vertexlist,e)}containsPoint(e){return!(!this.aabb.containsPoint(e)||!Tn(this.vertexlist,e))}isPointOnBoundary(e,t=Wn){let n=this.vertexlist.map((e=>e.toArray()));return!!Cn(e.toArray(),n,t)}intersectWithPolyLine(e,t=!1){let n=[];const i=t?e.length:e.length-1;for(let l=0;l<i;l++){const i=t?(l+1)%e.length:l+1,a=[e[l],e[i]];n.push(...this.intersectWithLineSeg(a))}return n}intersectWithLineSeg(e){const t=[],n=this.hedges.filter((e=>e.face==this)),i=(new nn).expands(e);for(let l of n){if(!l.getAABB().intersects(i))continue;const n=l.intersectWithLineSegment(e);n.type===gn.intersecting&&t.push({point:n.point,edge:[l.origin,l.twin.origin]})}return t}dirty(){this._areaDirty=!0,this._hedgesDirty=!0,this._centerDirty=!0,this._vertexlistDirty=!0,this._holesDirty=!0,this._aabbDirty=!0,this.changeIndex++}dispose(){this.wedge=null,this._vertexlist.length=0,this._holes.length=0,this._aabb=null,this._dcel=null}_tryAddHole(e){this._holesDirty||e.external&&this.area-Math.abs(e.area)>Wn&&this.aabb.containsPoints(e.vertexlist)&&Mn(this.vertexlist,e.vertexlist,Wn)&&this._holes.push(e)}}function kn(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)}function Tn(e,t,n=Wn){if(Cn([t.x,t.y],e.map((e=>e.toArray())),n))return!0;let i=0;for(let n=0;n<e.length;n++){const l=e[n],a=e[(n+1)%e.length];l.y<=t.y?a.y>t.y&&kn(l,a,t)>0&&i++:a.y<=t.y&&kn(l,a,t)<0&&i--}return 0!==i}function Mn(e,t,n=Wn){for(let i=0,l=t.length;i<l;i++)if(!Tn(e,t[i],n))return!1;return!0}function zn(e){if(e.length<3)return 0;let t=0;for(let n=0;n<e.length;n++){const i=(n+1)%e.length;t+=e[n].x*e[i].y-e[n].y*e[i].x}return.5*t}function Yn(e){let t=0,n=0;for(let i=0;i<e.length;i++)t+=e[i].x,n+=e[i].y;return new zt(t/e.length,n/e.length)}function Pn(e,t,n,i=Wn){const l=(n.x-t.x)*(n.x-t.x)+(n.y-t.y)*(n.y-t.y);if(l<i)return{distance:e.distanceTo(t),projection:t};let a=((e.x-t.x)*(n.x-t.x)+(e.y-t.y)*(n.y-t.y))/l;a<-i?a=0:a>1+i&&(a=1);const s=new zt(t.x+a*(n.x-t.x),t.y+a*(n.y-t.y));return{distance:e.distanceTo(s),projection:s}}function In(e,t,n=b){const[{x:i,y:l},{x:a,y:s}]=e,[{x:o,y:r},{x:c,y:d}]=t,u=(i-a)*(r-d)-(l-s)*(o-c);if(Math.abs(u)<n)return null;const h=((i-o)*(r-d)-(l-r)*(o-c))/u,m=((a-i)*(l-r)-(s-l)*(i-o))/u;return h>=-n&&h<=1+n&&m>=-n&&m<=1+n?new zt(i+h*(a-i),l+h*(s-l)):null}function Hn(e,t){const n=[];for(let i=0;i<t.length;i++){const l=[t[i],t[(i+1)%t.length]],a=In(e,l);a&&n.push({point:a,edge:l})}return n}let Fn=0;function Nn(){return Fn++,Fn}function Un(e){let{boxCenter:t,perspectiveCenter:n,centerBoxMaskDimensions:i=[0,0],width:l,height:a,gThreshold:s=2.5,gMean:o=1,gStdDev:r=1.5}=e;n||(n=t);const[c,d]=t;let[u,h]=n;u=Pt(new zt(u,h)).x,h=Pt(new zt(u,h)).y;let m=[i[0]*ze.scale,i[1]*ze.scale];l=Rt(l,ze.scale),a=Rt(a,ze.scale);let p=[];const g=2*(l+a),b=g/ze.scale,f=g/b;let x=[[u-m[0],h-m[1]],[u+m[0],h-m[1]],[u+m[0],h+m[1]],[u-m[0],h+m[1]]],Z=0,y=0,G=0;for(let e=0;e<b;e++){if(G<l?(Z=c-l/2+G,y=d-a/2):G<l+a?(Z=c+l/2,y=d-a/2+(G-l)):G<2*l+a?(Z=c+l/2-(G-(l+a)),y=d+a/2):(Z=c-l/2,y=d+a/2-(G-(2*l+a))),J.gaussianBool(s,o,r)){let e=Hn([[u,h],[Z,y]].map((e=>new zt(...e))),x.map((e=>new zt(...e))));if(!e[0])continue;let t=[e[0].point.toArray(),[Z,y]];if(p.push(t),J.bool(0)){let e=J.int(1,3)*ze.scale;J.bool(50)&&(e*=-1);let n=[[t[0][0]+e,t[0][1]],[t[1][0]+e,t[1][1]]];p.push(n)}}G+=f}return p}function Dn({center:e,width:t,height:n,angle:a=0}){let[s,o]=e,r=t/2,c=n/2,d=[[s-r,o-c],[s+r,o-c],[s+r,o+c],[s-r,o+c]];return 0!==a&&(d=function(e,t,n){const a=n||function(e){const t=e.reduce(((e,t)=>[e[0]+t[0],e[1]+t[1]]),[0,0]);return[t[0]/e.length,t[1]/e.length]}(e),s=t*g/180;return e.map((e=>{const t=[e[0]-a[0],e[1]-a[1]],n=[t[0]*l(s)-t[1]*i(s),t[0]*i(s)+t[1]*l(s)];return[n[0]+a[0],n[1]+a[1]]}))}(d,a,e)),d}function On(e){let{center:n,radius:i,startAngle:l=0,endAngle:a=180}=e,s=[],[o,r]=n;l=me(l),a=me(a);let c=t(i*Math.abs(a-l)*.125);for(let e=0;e<=c;e++){let t=l+e/c*(a-l),n=o+i*Math.cos(t),d=r+i*Math.sin(t);s.push([n,d])}let d=function(e){let t=0,n=0;for(let i=0;i<e.length;i++)t+=e[i][0],n+=e[i][1];return[t/e.length,n/e.length]}(s),u=[o-d[0],r-d[1]];return s=s.map((e=>[e[0]+u[0],e[1]+u[1]])),s}class Bn{startX;startY;endX;endY;distances;constructor(e,t,n,i){this.startX=e,this.startY=t,this.endX=n,this.endY=i;const l=n-e+1,a=i-t+1;this.distances=Array(a).fill(null).map((()=>Array(l).fill(1/0)))}initializeWithEmptyCells(e,t){for(let e=0;e<this.distances.length;e++)for(let t=0;t<this.distances[0].length;t++)this.distances[e][t]=0;e.forEach((e=>{const[n,i]=t(e),l=n-this.startX,a=i-this.startY;l>=0&&a>=0&&l<this.distances[0].length&&a<this.distances.length&&(this.distances[a][l]=1/0)}));for(let e=0;e<this.distances.length;e++)this.distances[e][0]=0,this.distances[e][this.distances[0].length-1]=0;for(let e=0;e<this.distances[0].length;e++)this.distances[0][e]=0,this.distances[this.distances.length-1][e]=0;this.performJFA()}performJFA(){const e=this.distances.length,t=this.distances[0].length;let n=[];for(let i=0;i<e;i++)for(let e=0;e<t;e++)0===this.distances[i][e]&&n.push([e,i]);for(;n.length>0;){let e=n.length;for(let t=0;t<e;t++){const[e,t]=n.shift();this.checkAndUpdate(e,t,n)}}}checkAndUpdate(e,t,n){const i=[[-1,0],[1,0],[0,-1],[0,1],[-1,-1],[-1,1],[1,-1],[1,1]];for(const[l,a]of i){const i=e+l,s=t+a;i>=0&&i<this.distances[0].length&&s>=0&&s<this.distances.length&&this.distances[s][i]>this.distances[t][e]+1&&(this.distances[s][i]=this.distances[t][e]+1,n.push([i,s]))}}getDistance(e,t){const n=e-this.startX,i=t-this.startY;return n>=0&&i>=0&&n<this.distances[0].length&&i<this.distances.length?this.distances[i][n]:1/0}}var Qn;!function(e){e.intersecting="INTERSECTING",e.contained="CONTAINED"}(Qn||(Qn={}));class Jn{cells=new Map;lines=new Map;lineMeta=new Map;distanceCalculator;nextLineId=0;cellSize;faceCellIndicesCache=new Map;aabbLineIntersectionCache=new Map;constructor(e,t){this.cellSize=e,t&&this.addLines(t)}getCellBounds(){let e=0,t=0,n=0,i=0;return this.cells.forEach(((l,a)=>{const[s,o]=this.getCellXYfromIndex(a);e=Math.min(e,s),t=Math.min(t,o),n=Math.max(n,s),i=Math.max(i,o)})),{width:n-e,height:i-t,minX:e,minY:t,maxX:n,maxY:i}}getCellIndex(e,t){return`${f(e)},${f(t)}`}getCellXYfromIndex(e){return e.split(",").map(Number)}getCellVertexFromIndex(e){let[t,n]=this.getCellXYfromIndex(e);return new zt(t*this.cellSize,n*this.cellSize)}clear(){this.cells.clear(),this.lines.clear(),this.lineMeta.clear(),this.faceCellIndicesCache.clear(),this.aabbLineIntersectionCache.clear()}addLines(e){e.forEach((e=>this.addLine(e.line,e.meta)))}addLine(e,t){const n=this.nextLineId++;this.lines.set(n,e),this.lineMeta.set(n,t);let i=t.isClosed?e.length:e.length-1;for(let t=0;t<i;t++)this.addSegment(e[t],e[(t+1)%e.length],n);return this.aabbLineIntersectionCache.clear(),n}removeLineById(e){if(this.lines.get(e)){for(let t of this.cells.values())t.delete(e);this.lines.delete(e),this.lineMeta.delete(e),this.aabbLineIntersectionCache.clear()}}addSegment(e,t,n){let i,[l,a]=e,[o,r]=t,c=f(l/this.cellSize),d=f(a/this.cellSize),u=f(o/this.cellSize),h=f(r/this.cellSize),m=s(u-c),p=-s(h-d),g=c<u?1:-1,b=d<h?1:-1,x=m+p;for(;;){const e=this.getCellIndex(c,d);if(this.cells.has(e)||this.cells.set(e,new Set),this.cells.get(e).add(n),c===u&&d===h)break;i=2*x,i>=p&&(x+=p,c+=g),i<=m&&(x+=m,d+=b)}}getLinesIntersectingOrContainedWithinAABB(e){let t=new Set,n=f(e.minX/this.cellSize),i=f(e.maxX/this.cellSize),l=f(e.minY/this.cellSize),a=f(e.maxY/this.cellSize);for(let e=n;e<=i;e++)for(let n=l;n<=a;n++){const i=this.getCellIndex(e,n);this.cells.has(i)&&this.cells.get(i).forEach((e=>t.add(e)))}return Array.from(t).map((e=>({id:Nn(),line:this.lines.get(e),meta:this.lineMeta.get(e)})))}getAllLines(){return Array.from(this.lines).map((([e,t])=>({id:e,line:t,meta:this.lineMeta.get(e)})))}getCellsIntersectedByFace(e){const t=this.faceCellIndicesCache.get(e.id);if(t&&t.changeIndex===e.changeIndex)return t.cellIndices;const n=new Set,i=e.aabb,l=f(i.minX/this.cellSize),a=f(i.maxX/this.cellSize),s=f(i.minY/this.cellSize),o=f(i.maxY/this.cellSize);for(let t=l;t<=a;t++)for(let i=s;i<=o;i++){const l=new nn;l.expands([new zt(t*this.cellSize,i*this.cellSize),new zt((t+1)*this.cellSize,(i+1)*this.cellSize)]);for(let a of l.vertexList)if(e.containsPoint(a)){n.add(this.getCellIndex(t,i));break}}return this.faceCellIndicesCache.set(e.id,{changeIndex:e.changeInd