@jscad/stl-deserializer 3.0.1-alpha.0 → 3.0.2-alpha.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.
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * STL Deserializer for JSCAD
3
3
  * @module @jscad/stl-deserializer
4
- * @version 3.0.1-alpha.0
4
+ * @version 3.0.2-alpha.0
5
5
  * @license MIT
6
6
  */
7
7
  var global,factory;global=this,factory=function(exports){
8
8
  /**
9
9
  * Constructive Solid Geometry (CSG) Library for JSCAD
10
10
  * @module @jscad/modeling
11
- * @version 3.0.1-alpha.0
11
+ * @version 3.0.2-alpha.0
12
12
  * @license MIT
13
13
  */
14
- const clone$a=matrix=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},copy$5=(out,matrix)=>(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out),EPS=1e-5,TAU=2*Math.PI,rezero=n=>Math.abs(n)<1e-13?0:n,sin=radians=>rezero(Math.sin(radians)),cos=radians=>rezero(Math.cos(radians)),identity=out=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromRotation=(out,rad,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return identity(out);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(rad),c=cos(rad),t=1-c;return out[0]=x*x*t+c,out[1]=y*x*t+z*s,out[2]=z*x*t-y*s,out[3]=0,out[4]=x*y*t-z*s,out[5]=y*y*t+c,out[6]=z*y*t+x*s,out[7]=0,out[8]=x*z*t+y*s,out[9]=y*z*t-x*s,out[10]=z*z*t+c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},abs$1=(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out[2]=Math.abs(vector[2]),out),add$1=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out),dot$2=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2],clone$9=vector=>{const out=[0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out},copy$4=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out),cross$1=(out,a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];return out[0]=ay*bz-az*by,out[1]=az*bx-ax*bz,out[2]=ax*by-ay*bx,out},distance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return Math.sqrt(x*x+y*y+z*z)},equals$7=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2],fromScalar$2=(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out),fromValues$3=(x,y,z)=>{const out=[0,0,0];return out[0]=x,out[1]=y,out[2]=z,out},fromVec2=(out,vector,z=0)=>(out[0]=vector[0],out[1]=vector[1],out[2]=z,out),length$2=vector=>{const x=vector[0],y=vector[1],z=vector[2];return Math.sqrt(x*x+y*y+z*z)},max$2=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out[2]=Math.max(a[2],b[2]),out),min$2=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out[2]=Math.min(a[2],b[2]),out),multiply$2=(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out[2]=a[2]*b[2],out),negate$1=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out[2]=-vector[2],out),normalize$1=(out,vector)=>{const x=vector[0],y=vector[1],z=vector[2];let len=x*x+y*y+z*z;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out[2]=z*len,out},orthogonal=(out,vector)=>{const bV=abs$1([0,0,0],vector),b0=0+(bV[0]<bV[1]&&bV[0]<bV[2]),b1=0+(bV[1]<=bV[0]&&bV[1]<bV[2]),b2=0+(bV[2]<=bV[0]&&bV[2]<=bV[1]);return cross$1(out,vector,[b0,b1,b2])},scale$3=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out[2]=vector[2]*amount,out),squaredDistance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return x*x+y*y+z*z},squaredLength$1=vector=>{const x=vector[0],y=vector[1],z=vector[2];return x*x+y*y+z*z},subtract$3=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out),toString$b=vec=>`[${vec[0].toFixed(7)}, ${vec[1].toFixed(7)}, ${vec[2].toFixed(7)}]`,transform$c=(out,vector,matrix)=>{const x=vector[0],y=vector[1],z=vector[2];let w=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15];return w=w||1,out[0]=(matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12])/w,out[1]=(matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13])/w,out[2]=(matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14])/w,out};var index$d=Object.freeze({__proto__:null,abs:abs$1,add:add$1,angle:(a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2],mag=Math.sqrt(ax*ax+ay*ay+az*az)*Math.sqrt(bx*bx+by*by+bz*bz),cosine=mag&&dot$2(a,b)/mag;return Math.acos(Math.min(Math.max(cosine,-1),1))},clone:clone$9,copy:copy$4,create:()=>[0,0,0],cross:cross$1,distance:distance$1,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out[2]=a[2]/b[2],out),dot:dot$2,equals:equals$7,fromScalar:fromScalar$2,fromValues:fromValues$3,fromVec2:fromVec2,length:length$2,lerp:(out,a,b,t)=>(out[0]=a[0]+t*(b[0]-a[0]),out[1]=a[1]+t*(b[1]-a[1]),out[2]=a[2]+t*(b[2]-a[2]),out),max:max$2,min:min$2,multiply:multiply$2,negate:negate$1,normalize:normalize$1,orthogonal:orthogonal,rotateX:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[0],r[1]=p[1]*Math.cos(radians)-p[2]*Math.sin(radians),r[2]=p[1]*Math.sin(radians)+p[2]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateY:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[2]*Math.sin(radians)+p[0]*Math.cos(radians),r[1]=p[1],r[2]=p[2]*Math.cos(radians)-p[0]*Math.sin(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateZ:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],r[0]=p[0]*Math.cos(radians)-p[1]*Math.sin(radians),r[1]=p[0]*Math.sin(radians)+p[1]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=vector[2],out},scale:scale$3,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out[2]=Math.round(vector[2]/epsilon)*epsilon+0,out),squaredDistance:squaredDistance$1,squaredLength:squaredLength$1,subtract:subtract$3,toString:toString$b,transform:transform$c});const isIdentity=matrix=>1===matrix[0]&&0===matrix[1]&&0===matrix[2]&&0===matrix[3]&&0===matrix[4]&&1===matrix[5]&&0===matrix[6]&&0===matrix[7]&&0===matrix[8]&&0===matrix[9]&&1===matrix[10]&&0===matrix[11]&&0===matrix[12]&&0===matrix[13]&&0===matrix[14]&&1===matrix[15],isMirroring=matrix=>{const x=matrix[4]*matrix[9]-matrix[8]*matrix[5],y=matrix[8]*matrix[1]-matrix[0]*matrix[9],z=matrix[0]*matrix[5]-matrix[4]*matrix[1];return x*matrix[2]+y*matrix[6]+z*matrix[10]<0},isZero=num=>Math.abs(num)<Number.EPSILON,multiply$1=(out,a,b)=>{const a00=a[0],a01=a[1],a02=a[2],a03=a[3],a10=a[4],a11=a[5],a12=a[6],a13=a[7],a20=a[8],a21=a[9],a22=a[10],a23=a[11],a30=a[12],a31=a[13],a32=a[14],a33=a[15];let b0=b[0],b1=b[1],b2=b[2],b3=b[3];return out[0]=b0*a00+b1*a10+b2*a20+b3*a30,out[1]=b0*a01+b1*a11+b2*a21+b3*a31,out[2]=b0*a02+b1*a12+b2*a22+b3*a32,out[3]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[4],b1=b[5],b2=b[6],b3=b[7],out[4]=b0*a00+b1*a10+b2*a20+b3*a30,out[5]=b0*a01+b1*a11+b2*a21+b3*a31,out[6]=b0*a02+b1*a12+b2*a22+b3*a32,out[7]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[8],b1=b[9],b2=b[10],b3=b[11],out[8]=b0*a00+b1*a10+b2*a20+b3*a30,out[9]=b0*a01+b1*a11+b2*a21+b3*a31,out[10]=b0*a02+b1*a12+b2*a22+b3*a32,out[11]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[12],b1=b[13],b2=b[14],b3=b[15],out[12]=b0*a00+b1*a10+b2*a20+b3*a30,out[13]=b0*a01+b1*a11+b2*a21+b3*a31,out[14]=b0*a02+b1*a12+b2*a22+b3*a32,out[15]=b0*a03+b1*a13+b2*a23+b3*a33,out};Object.freeze({__proto__:null,add:(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out[3]=a[3]+b[3],out[4]=a[4]+b[4],out[5]=a[5]+b[5],out[6]=a[6]+b[6],out[7]=a[7]+b[7],out[8]=a[8]+b[8],out[9]=a[9]+b[9],out[10]=a[10]+b[10],out[11]=a[11]+b[11],out[12]=a[12]+b[12],out[13]=a[13]+b[13],out[14]=a[14]+b[14],out[15]=a[15]+b[15],out),clone:clone$a,copy:copy$5,create:()=>[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],equals:(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15],fromRotation:fromRotation,fromScaling:(out,vector)=>(out[0]=vector[0],out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=vector[1],out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=vector[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromTaitBryanRotation:(out,yaw,pitch,roll)=>{const sy=sin(yaw),cy=cos(yaw),sp=sin(pitch),cp=cos(pitch),sr=sin(roll),cr=cos(roll);return out[0]=cp*cy,out[1]=cp*sy,out[2]=-sp,out[3]=0,out[4]=sr*sp*cy-cr*sy,out[5]=cr*cy+sr*sp*sy,out[6]=sr*cp,out[7]=0,out[8]=sr*sy+cr*sp*cy,out[9]=cr*sp*sy-sr*cy,out[10]=cr*cp,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromTranslation:(out,vector)=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=vector[0],out[13]=vector[1],out[14]=vector[2],out[15]=1,out),fromValues:(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33)=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=m00,out[1]=m01,out[2]=m02,out[3]=m03,out[4]=m10,out[5]=m11,out[6]=m12,out[7]=m13,out[8]=m20,out[9]=m21,out[10]=m22,out[11]=m23,out[12]=m30,out[13]=m31,out[14]=m32,out[15]=m33,out},fromVectorRotation:(out,source,target)=>{const sourceNormal=normalize$1([0,0,0],source),targetNormal=normalize$1([0,0,0],target),axis=cross$1([0,0,0],targetNormal,sourceNormal),cosA=dot$2(targetNormal,sourceNormal);if(-1===cosA)return fromRotation(out,Math.PI,orthogonal(axis,sourceNormal));const k=1/(1+cosA);return out[0]=axis[0]*axis[0]*k+cosA,out[1]=axis[1]*axis[0]*k-axis[2],out[2]=axis[2]*axis[0]*k+axis[1],out[3]=0,out[4]=axis[0]*axis[1]*k+axis[2],out[5]=axis[1]*axis[1]*k+cosA,out[6]=axis[2]*axis[1]*k-axis[0],out[7]=0,out[8]=axis[0]*axis[2]*k-axis[1],out[9]=axis[1]*axis[2]*k+axis[0],out[10]=axis[2]*axis[2]*k+cosA,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromXRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=c,out[6]=s,out[7]=0,out[8]=0,out[9]=-s,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromYRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=0,out[2]=-s,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=s,out[9]=0,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=s,out[2]=0,out[3]=0,out[4]=-s,out[5]=c,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},identity:identity,invert:(out,matrix)=>{const a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],a30=matrix[12],a31=matrix[13],a32=matrix[14],a33=matrix[15],b00=a00*a11-a01*a10,b01=a00*a12-a02*a10,b02=a00*a13-a03*a10,b03=a01*a12-a02*a11,b04=a01*a13-a03*a11,b05=a02*a13-a03*a12,b06=a20*a31-a21*a30,b07=a20*a32-a22*a30,b08=a20*a33-a23*a30,b09=a21*a32-a22*a31,b10=a21*a33-a23*a31,b11=a22*a33-a23*a32;let det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;return det?(det=1/det,out[0]=(a11*b11-a12*b10+a13*b09)*det,out[1]=(a02*b10-a01*b11-a03*b09)*det,out[2]=(a31*b05-a32*b04+a33*b03)*det,out[3]=(a22*b04-a21*b05-a23*b03)*det,out[4]=(a12*b08-a10*b11-a13*b07)*det,out[5]=(a00*b11-a02*b08+a03*b07)*det,out[6]=(a32*b02-a30*b05-a33*b01)*det,out[7]=(a20*b05-a22*b02+a23*b01)*det,out[8]=(a10*b10-a11*b08+a13*b06)*det,out[9]=(a01*b08-a00*b10-a03*b06)*det,out[10]=(a30*b04-a31*b02+a33*b00)*det,out[11]=(a21*b02-a20*b04-a23*b00)*det,out[12]=(a11*b07-a10*b09-a12*b06)*det,out[13]=(a00*b09-a01*b07+a02*b06)*det,out[14]=(a31*b01-a30*b03-a32*b00)*det,out[15]=(a20*b03-a21*b01+a22*b00)*det,out):null},isIdentity:isIdentity,isMirroring:isMirroring,isOnlyTransformScale:matrix=>isZero(matrix[1])&&isZero(matrix[2])&&isZero(matrix[3])&&isZero(matrix[4])&&isZero(matrix[6])&&isZero(matrix[7])&&isZero(matrix[8])&&isZero(matrix[9])&&isZero(matrix[11])&&1===matrix[15],mirrorByPlane:(out,plane)=>{const[nx,ny,nz,w]=plane;return out[0]=1-2*nx*nx,out[1]=-2*ny*nx,out[2]=-2*nz*nx,out[3]=0,out[4]=-2*nx*ny,out[5]=1-2*ny*ny,out[6]=-2*nz*ny,out[7]=0,out[8]=-2*nx*nz,out[9]=-2*ny*nz,out[10]=1-2*nz*nz,out[11]=0,out[12]=2*nx*w,out[13]=2*ny*w,out[14]=2*nz*w,out[15]=1,out},multiply:multiply$1,rotate:(out,matrix,radians,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return copy$5(out,matrix);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(radians),c=cos(radians),t=1-c,a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],b00=x*x*t+c,b01=y*x*t+z*s,b02=z*x*t-y*s,b10=x*y*t-z*s,b11=y*y*t+c,b12=z*y*t+x*s,b20=x*z*t+y*s,b21=y*z*t-x*s,b22=z*z*t+c;return out[0]=a00*b00+a10*b01+a20*b02,out[1]=a01*b00+a11*b01+a21*b02,out[2]=a02*b00+a12*b01+a22*b02,out[3]=a03*b00+a13*b01+a23*b02,out[4]=a00*b10+a10*b11+a20*b12,out[5]=a01*b10+a11*b11+a21*b12,out[6]=a02*b10+a12*b11+a22*b12,out[7]=a03*b10+a13*b11+a23*b12,out[8]=a00*b20+a10*b21+a20*b22,out[9]=a01*b20+a11*b21+a21*b22,out[10]=a02*b20+a12*b21+a22*b22,out[11]=a03*b20+a13*b21+a23*b22,matrix!==out&&(out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out},rotateX:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[4]=a10*c+a20*s,out[5]=a11*c+a21*s,out[6]=a12*c+a22*s,out[7]=a13*c+a23*s,out[8]=a20*c-a10*s,out[9]=a21*c-a11*s,out[10]=a22*c-a12*s,out[11]=a23*c-a13*s,out},rotateY:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c-a20*s,out[1]=a01*c-a21*s,out[2]=a02*c-a22*s,out[3]=a03*c-a23*s,out[8]=a00*s+a20*c,out[9]=a01*s+a21*c,out[10]=a02*s+a22*c,out[11]=a03*s+a23*c,out},rotateZ:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7];return matrix!==out&&(out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c+a10*s,out[1]=a01*c+a11*s,out[2]=a02*c+a12*s,out[3]=a03*c+a13*s,out[4]=a10*c-a00*s,out[5]=a11*c-a01*s,out[6]=a12*c-a02*s,out[7]=a13*c-a03*s,out},scale:(out,matrix,dimensions)=>{const x=dimensions[0],y=dimensions[1],z=dimensions[2];return out[0]=matrix[0]*x,out[1]=matrix[1]*x,out[2]=matrix[2]*x,out[3]=matrix[3]*x,out[4]=matrix[4]*y,out[5]=matrix[5]*y,out[6]=matrix[6]*y,out[7]=matrix[7]*y,out[8]=matrix[8]*z,out[9]=matrix[9]*z,out[10]=matrix[10]*z,out[11]=matrix[11]*z,out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},subtract:(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out[3]=a[3]-b[3],out[4]=a[4]-b[4],out[5]=a[5]-b[5],out[6]=a[6]-b[6],out[7]=a[7]-b[7],out[8]=a[8]-b[8],out[9]=a[9]-b[9],out[10]=a[10]-b[10],out[11]=a[11]-b[11],out[12]=a[12]-b[12],out[13]=a[13]-b[13],out[14]=a[14]-b[14],out[15]=a[15]-b[15],out),toString:mat=>mat.map((n=>n.toFixed(7))).toString(),translate:(out,matrix,offsets)=>{const x=offsets[0],y=offsets[1],z=offsets[2];let a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23;return matrix===out?(out[12]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12],out[13]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13],out[14]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14],out[15]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]):(a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],out[0]=a00,out[1]=a01,out[2]=a02,out[3]=a03,out[4]=a10,out[5]=a11,out[6]=a12,out[7]=a13,out[8]=a20,out[9]=a21,out[10]=a22,out[11]=a23,out[12]=a00*x+a10*y+a20*z+matrix[12],out[13]=a01*x+a11*y+a21*z+matrix[13],out[14]=a02*x+a12*y+a22*z+matrix[14],out[15]=a03*x+a13*y+a23*z+matrix[15]),out}});const create$a=(outlines=[])=>({outlines:outlines,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),add=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out),angleRadians=vector=>Math.atan2(vector[1],vector[0]),angleDegrees=vector=>57.29577951308232*angleRadians(vector),clone$8=vector=>{const out=[0,0];return out[0]=vector[0],out[1]=vector[1],out},cross=(out,a,b)=>(out[0]=0,out[1]=0,out[2]=a[0]*b[1]-a[1]*b[0],out),distance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)},dot$1=(a,b)=>a[0]*b[0]+a[1]*b[1],equals$6=(a,b)=>a[0]===b[0]&&a[1]===b[1],fromAngleRadians=(out,radians)=>(out[0]=cos(radians),out[1]=sin(radians),out),fromValues$2=(x,y)=>{const out=[0,0];return out[0]=x,out[1]=y,out},max$1=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out),min$1=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out),negate=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out),rotate$1=(out,vector,origin,radians)=>{const x=vector[0]-origin[0],y=vector[1]-origin[1],c=Math.cos(radians),s=Math.sin(radians);return out[0]=x*c-y*s+origin[0],out[1]=x*s+y*c+origin[1],out},normal=(out,vector)=>rotate$1(out,vector,[0,0],TAU/4),normalize=(out,vector)=>{const x=vector[0],y=vector[1];let len=x*x+y*y;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out},scale$1=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out),subtract$1=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out),toString$9=vector=>`[${vector[0].toFixed(7)}, ${vector[1].toFixed(7)}]`,transform$b=(out,vector,matrix)=>{const x=vector[0],y=vector[1];return out[0]=matrix[0]*x+matrix[4]*y+matrix[12],out[1]=matrix[1]*x+matrix[5]*y+matrix[13],out};Object.freeze({__proto__:null,abs:(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out),add:add,angle:angleRadians,angleDegrees:angleDegrees,angleRadians:angleRadians,clone:clone$8,copy:(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out),create:()=>[0,0],cross:cross,distance:distance,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out),dot:dot$1,equals:equals$6,fromAngleDegrees:(out,degrees)=>fromAngleRadians(out,.017453292519943295*degrees),fromAngleRadians:fromAngleRadians,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out),fromValues:fromValues$2,length:vector=>Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]),lerp:(out,a,b,t)=>{const ax=a[0],ay=a[1];return out[0]=ax+t*(b[0]-ax),out[1]=ay+t*(b[1]-ay),out},max:max$1,min:min$1,multiply:(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out),negate:negate,normal:normal,normalize:normalize,rotate:rotate$1,scale:scale$1,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out),squaredDistance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y},squaredLength:vector=>{const x=vector[0],y=vector[1];return x*x+y*y},subtract:subtract$1,toString:toString$9,transform:transform$b});const popNextSide=(startSide,nextSides)=>{if(1===nextSides.length)return nextSides.pop();const v0=[0,0],startAngle=angleDegrees(subtract$1(v0,startSide[1],startSide[0]));let bestAngle,bestIndex;nextSides.forEach(((nextSide,index)=>{let angle=angleDegrees(subtract$1(v0,nextSide[1],nextSide[0]))-startAngle;angle<-180&&(angle+=360),angle>=180&&(angle-=360),(void 0===bestIndex||angle>bestAngle)&&(bestIndex=index,bestAngle=angle)}));const nextSide=nextSides[bestIndex];return nextSides.splice(bestIndex,1),nextSide},isA$5=object=>!!(object&&"object"==typeof object&&"outlines"in object&&"transforms"in object&&Array.isArray(object.outlines)&&"length"in object.transforms),toOutlines=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.outlines=geometry.outlines.map((outline=>outline.map((point=>transform$b([0,0],point,geometry.transforms))))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).outlines,reverse$5=geometry=>{const outlines=toOutlines(geometry).map((outline=>outline.slice().reverse())),reversed=create$a(outlines);return geometry.color&&(reversed.color=geometry.color),reversed},intersect$1=(p1,p2,p3,p4,endpointTouch=!0)=>{if(p1[0]===p2[0]&&p1[1]===p2[1]||p3[0]===p4[0]&&p3[1]===p4[1])return;const denominator=(p4[1]-p3[1])*(p2[0]-p1[0])-(p4[0]-p3[0])*(p2[1]-p1[1]);if(Math.abs(denominator)<Number.MIN_VALUE)return;const ua=((p4[0]-p3[0])*(p1[1]-p3[1])-(p4[1]-p3[1])*(p1[0]-p3[0]))/denominator,ub=((p2[0]-p1[0])*(p1[1]-p3[1])-(p2[1]-p1[1])*(p1[0]-p3[0]))/denominator;return ua<0||ua>1||ub<0||ub>1||!(endpointTouch||0!==ua&&1!==ua&&0!==ub&&1!==ub)?void 0:[p1[0]+ua*(p2[0]-p1[0]),p1[1]+ua*(p2[1]-p1[1])]};Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$a,fromSides:sides=>{const pointMap=(sides=>{const pointMap=new Map,edges=(sides=>{const unique=new Map,getUniquePoint=point=>{const key=point.toString();return unique.has(key)?unique.get(key):(unique.set(key,point),point)};return sides.map((side=>side.map(getUniquePoint)))})(sides);return edges.forEach((edge=>{pointMap.has(edge[0])?pointMap.get(edge[0]).push(edge):pointMap.set(edge[0],[edge])})),pointMap})(sides),outlines=[];for(;;){let startSide;for(const[point,edges]of pointMap){if(startSide=edges.shift(),startSide)break;pointMap.delete(point)}if(void 0===startSide)break;const connectedPoints=[],startPoint=startSide[0];for(;;){connectedPoints.push(startSide[0]);const nextPoint=startSide[1];if(nextPoint===startPoint)break;const nextPossibleSides=pointMap.get(nextPoint);if(!nextPossibleSides)throw new Error(`geometry is not closed at point ${nextPoint}`);const nextSide=popNextSide(startSide,nextPossibleSides);0===nextPossibleSides.length&&pointMap.delete(nextPoint),startSide=nextSide}connectedPoints.length>0&&connectedPoints.push(connectedPoints.shift()),outlines.push(connectedPoints)}return pointMap.clear(),create$a(outlines)},fromCompactBinary:data=>{if(0!==data[0])throw new Error("invalid compact binary data");const created=create$a();created.transforms=clone$a(data.slice(1,17));for(let i=21;i<data.length;){const length=data[i++];if(length<0||i+2*length>data.length)throw new Error("invalid compact binary data");const outline=[];for(let j=0;j<length;j++){const x=data[i+2*j],y=data[i+2*j+1];outline.push(fromValues$2(x,y))}created.outlines.push(outline),i+=2*length}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},isA:isA$5,reverse:reverse$5,toOutlines:toOutlines,toPoints:geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},toSides:geometry=>{const sides=[];return toOutlines(geometry).forEach((outline=>{outline.forEach(((point,i)=>{const j=(i+1)%outline.length;sides.push([point,outline[j]])}))})),sides},toString:geometry=>{const outlines=toOutlines(geometry);let result="geom2 ("+outlines.length+" outlines):\n[\n";return outlines.forEach((outline=>{result+=" ["+outline.map(toString$9).join()+"]\n"})),result+="]\n",result},toCompactBinary:geometry=>{const transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);let size=21;geometry.outlines.forEach((outline=>{size+=2*outline.length+1}));const compacted=new Float32Array(size);compacted[0]=0,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3];let index=21;return geometry.outlines.forEach((outline=>{compacted[index++]=outline.length,outline.forEach((point=>{compacted[index++]=point[0],compacted[index++]=point[1]}))})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms),transformed=Object.assign({},geometry,{transforms:transforms});return matrix[0]*matrix[5]-matrix[4]*matrix[1]<0?reverse$5(transformed):transformed},validate:object=>{if(!isA$5(object))throw new Error("invalid geom2 structure");if(object.outlines.forEach(((outline,i)=>{if(outline.length<3)throw new Error(`geom2 outline ${i} must contain at least 3 points`);for(let i=0;i<outline.length;i++){const j=(i+1)%outline.length;if(equals$6(outline[i],outline[j]))throw new Error(`geom2 outline ${i} has duplicate point ${outline[i]}`)}})),toOutlines(object).forEach(((outline,i)=>{for(let a1=0;a1<outline.length;a1++){const a2=(a1+1)%outline.length;for(let b1=0;b1<outline.length;b1++){const b2=(b1+1)%outline.length;if(a1!==b1){const int=intersect$1(outline[a1],outline[a2],outline[b1],outline[b2],!1);if(int)throw new Error(`geom2 outline ${i} self intersection at ${int}`)}}}})),!object.transforms.every(Number.isFinite))throw new Error(`geom2 invalid transforms ${object.transforms}`)}});const create$8=polygons=>(void 0===polygons&&(polygons=[]),{polygons:polygons,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),create$7=vertices=>((void 0===vertices||vertices.length<3)&&(vertices=[]),{vertices:vertices}),fromVerticesAndPlane=(vertices,plane)=>{const poly=create$7(vertices);return poly.plane=plane,poly},create$6=()=>[0,0,0,0],clone$5=vector=>{const out=[0,0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out},copy$2=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out),equals$5=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3],flip=(out,plane)=>(out[0]=-plane[0],out[1]=-plane[1],out[2]=-plane[2],out[3]=-plane[3],out),fromValues$1=(x,y,z,w)=>{const out=[0,0,0,0];return out[0]=x,out[1]=y,out[2]=z,out[3]=w,out},fromPoints$4=(out,...vertices)=>{const len=vertices.length,ba=[0,0,0],ca=[0,0,0],vertexNormal=index=>{const a=vertices[index],b=vertices[(index+1)%len],c=vertices[(index+2)%len];return subtract$3(ba,b,a),subtract$3(ca,c,a),cross$1(ba,ba,ca),normalize$1(ba,ba),ba};return out[0]=0,out[1]=0,out[2]=0,3===len?copy$4(out,vertexNormal(0)):(vertices.forEach(((v,i)=>{add$1(out,out,vertexNormal(i))})),normalize$1(out,out)),out[3]=dot$2(out,vertices[0]),out},signedDistanceToPoint=(plane,point)=>dot$2(plane,point)-plane[3],toString$7=vec=>`(${vec[0].toFixed(9)}, ${vec[1].toFixed(9)}, ${vec[2].toFixed(9)}, ${vec[3].toFixed(9)})`;Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,equals:equals$5,flip:flip,fromNormalAndPoint:(out,normal,point)=>{const u=normalize$1([0,0,0],normal),w=dot$2(point,u);return out[0]=u[0],out[1]=u[1],out[2]=u[2],out[3]=w,out},fromValues:fromValues$1,fromPoints:fromPoints$4,fromPointsRandom:(out,a,b,c)=>{let ba=subtract$3([0,0,0],b,a),ca=subtract$3([0,0,0],c,a);length$2(ba)<EPS&&(ba=orthogonal(ba,ca)),length$2(ca)<EPS&&(ca=orthogonal(ca,ba));let normal=cross$1([0,0,0],ba,ca);length$2(normal)<EPS&&(ca=orthogonal(ca,ba),normal=cross$1(normal,ba,ca)),normal=normalize$1(normal,normal);const w=dot$2(normal,a);return out[0]=normal[0],out[1]=normal[1],out[2]=normal[2],out[3]=w,out},projectionOfPoint:(plane,point)=>{const a=point[0]*plane[0]+point[1]*plane[1]+point[2]*plane[2]-plane[3],x=point[0]-a*plane[0],y=point[1]-a*plane[1],z=point[2]-a*plane[2];return fromValues$3(x,y,z)},signedDistanceToPoint:signedDistanceToPoint,toString:toString$7,transform:(out,plane,matrix)=>{const isMirror=isMirroring(matrix),r=orthogonal([0,0,0],plane),u=cross$1(r,plane,r),v=cross$1([0,0,0],plane,u);let point1=fromScalar$2([0,0,0],plane[3]);multiply$2(point1,point1,plane);let point2=add$1([0,0,0],point1,u),point3=add$1([0,0,0],point1,v);return point1=transform$c(point1,point1,matrix),point2=transform$c(point2,point2,matrix),point3=transform$c(point3,point3,matrix),fromPoints$4(out,point1,point2,point3),isMirror&&flip(out,out),out}});const invert$1=polygon=>{const vertices=polygon.vertices.slice().reverse(),inverted=create$7(vertices);return polygon.plane&&(inverted.plane=flip([0,0,0,0],polygon.plane)),inverted},isA$4=object=>!!(object&&"object"==typeof object&&"vertices"in object&&Array.isArray(object.vertices)),isConvex$1=polygon=>areVerticesConvex(polygon.vertices),areVerticesConvex=vertices=>{const numVertices=vertices.length;if(numVertices>2){const normal=fromPoints$4([0,0,0,0],...vertices);let prevPrevPos=vertices[numVertices-2],prevPos=vertices[numVertices-1];for(let i=0;i<numVertices;i++){const pos=vertices[i];if(!isConvexVertex(prevPrevPos,prevPos,pos,normal))return!1;prevPrevPos=prevPos,prevPos=pos}}return!0},isConvexVertex=(prevVertex,vertex,nextVertex,normal)=>{const crossProduct=cross$1([0,0,0],subtract$3([0,0,0],vertex,prevVertex),subtract$3([0,0,0],nextVertex,vertex));return dot$2(crossProduct,normal)>=0},plane=polygon=>(polygon.plane||(polygon.plane=fromPoints$4([0,0,0,0],...polygon.vertices)),polygon.plane),measureArea$2=polygon=>{const n=polygon.vertices.length;if(n<3)return 0;const vertices=polygon.vertices,normal=plane(polygon),ax=Math.abs(normal[0]),ay=Math.abs(normal[1]),az=Math.abs(normal[2]);if(ax+ay+az===0)return 0;let coord=3;ax>ay&&ax>az?coord=1:ay>az&&(coord=2);let area=0,h=0,i=1,j=2;switch(coord){case 1:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][1]*(vertices[j][2]-vertices[h][2]);area+=vertices[0][1]*(vertices[1][2]-vertices[n-1][2]),area/=2*normal[0];break;case 2:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][2]*(vertices[j][0]-vertices[h][0]);area+=vertices[0][2]*(vertices[1][0]-vertices[n-1][0]),area/=2*normal[1];break;default:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][0]*(vertices[j][1]-vertices[h][1]);area+=vertices[0][0]*(vertices[1][1]-vertices[n-1][1]),area/=2*normal[2]}return area};Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,dot:(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],equals:equals$5,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out[3]=scalar,out),fromValues:fromValues$1,toString:toString$7,transform:(out,vector,matrix)=>{const[x,y,z,w]=vector;return out[0]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12]*w,out[1]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13]*w,out[2]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14]*w,out[3]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]*w,out}});const cache$4=new WeakMap,toVertices$1=polygon=>polygon.vertices,toString$6=polygon=>`poly3: [${polygon.vertices.map(toString$b).join(", ")}]`,transform$7=(matrix,polygon)=>{const vertices=polygon.vertices.map((vertex=>transform$c([0,0,0],vertex,matrix)));return isMirroring(matrix)&&vertices.reverse(),create$7(vertices)},validate$4=object=>{if(!isA$4(object))throw new Error("invalid poly3 structure");if(object.vertices.length<3)throw new Error(`poly3 not enough vertices ${object.vertices.length}`);if(measureArea$2(object)<=0)throw new Error("poly3 area must be greater than zero");for(let i=0;i<object.vertices.length;i++)if(equals$7(object.vertices[i],object.vertices[(i+1)%object.vertices.length]))throw new Error(`poly3 has duplicate vertex ${object.vertices[i]}`);if(!isConvex$1(object))throw new Error("poly3 must be convex");if(object.vertices.forEach((vertex=>{if(!vertex.every(Number.isFinite))throw new Error(`poly3 invalid vertex ${vertex}`)})),object.vertices.length>3){const normal=plane(object);object.vertices.forEach((vertex=>{const dist=Math.abs(signedDistanceToPoint(normal,vertex));if(dist>1e-13)throw new Error(`poly3 must be coplanar: vertex ${vertex} distance ${dist}`)}))}};Object.freeze({__proto__:null,clone:(...params)=>{let out,poly3;return 1===params.length?(out=create$7(),poly3=params[0]):(out=params[0],poly3=params[1]),out.vertices=poly3.vertices.map((vec=>clone$9(vec))),out},create:create$7,fromVerticesAndPlane:fromVerticesAndPlane,invert:invert$1,isA:isA$4,isConvex:isConvex$1,measureArea:measureArea$2,measureBoundingBox:polygon=>{const vertices=polygon.vertices,numVertices=vertices.length,min=0===numVertices?[0,0,0]:clone$9(vertices[0]),max=clone$9(min);for(let i=1;i<numVertices;i++)min$2(min,min,vertices[i]),max$2(max,max,vertices[i]);return[min,max]},measureBoundingSphere:polygon=>{const boundingSphere=cache$4.get(polygon);if(boundingSphere)return boundingSphere;const vertices=polygon.vertices,out=[0,0,0,0];if(0===vertices.length)return out[0]=0,out[1]=0,out[2]=0,out[3]=0,out;let minx=vertices[0],miny=minx,minz=minx,maxx=minx,maxy=minx,maxz=minx;vertices.forEach((v=>{minx[0]>v[0]&&(minx=v),miny[1]>v[1]&&(miny=v),minz[2]>v[2]&&(minz=v),maxx[0]<v[0]&&(maxx=v),maxy[1]<v[1]&&(maxy=v),maxz[2]<v[2]&&(maxz=v)})),out[0]=.5*(minx[0]+maxx[0]),out[1]=.5*(miny[1]+maxy[1]),out[2]=.5*(minz[2]+maxz[2]);const x=out[0]-maxx[0],y=out[1]-maxy[1],z=out[2]-maxz[2];return out[3]=Math.sqrt(x*x+y*y+z*z),cache$4.set(polygon,out),out},measureSignedVolume:polygon=>{let signedVolume=0;const vertices=polygon.vertices,cross=[0,0,0];for(let i=0;i<vertices.length-2;i++)cross$1(cross,vertices[i+1],vertices[i+2]),signedVolume+=dot$2(vertices[0],cross);return signedVolume/=6,signedVolume},plane:plane,toVertices:toVertices$1,toString:toString$6,transform:transform$7,validate:validate$4});class VertexList{constructor(){this.head=null,this.tail=null}clear(){this.head=this.tail=null}insertBefore(target,node){node.prev=target.prev,node.next=target,node.prev?node.prev.next=node:this.head=node,target.prev=node}insertAfter(target,node){node.prev=target,node.next=target.next,node.next?node.next.prev=node:this.tail=node,target.next=node}add(node){this.head?this.tail.next=node:this.head=node,node.prev=this.tail,node.next=null,this.tail=node}addAll(node){for(this.head?this.tail.next=node:this.head=node,node.prev=this.tail;node.next;)node=node.next;this.tail=node}remove(node){node.prev?node.prev.next=node.next:this.head=node.next,node.next?node.next.prev=node.prev:this.tail=node.prev}removeChain(a,b){a.prev?a.prev.next=b.next:this.head=b.next,b.next?b.next.prev=a.prev:this.tail=a.prev}first(){return this.head}isEmpty(){return!this.head}}class Vertex{constructor(point,index){this.point=point,this.index=index,this.next=null,this.prev=null,this.face=null}}class HalfEdge{constructor(vertex,face){this.vertex=vertex,this.face=face,this.next=null,this.prev=null,this.opposite=null}head(){return this.vertex}tail(){return this.prev?this.prev.vertex:null}length(){return this.tail()?distance$1(this.tail().point,this.head().point):-1}lengthSquared(){return this.tail()?squaredDistance$1(this.tail().point,this.head().point):-1}setOpposite(edge){this.opposite=edge,edge.opposite=this}}class Face{constructor(){this.normal=[],this.centroid=[],this.offset=0,this.outside=null,this.mark=0,this.edge=null,this.nVertices=0}getEdge(i){if("number"!=typeof i)throw Error("requires a number");let it=this.edge;for(;i>0;)it=it.next,i-=1;for(;i<0;)it=it.prev,i+=1;return it}computeNormal(){const e0=this.edge,e1=e0.next;let e2=e1.next;const v2=subtract$3([],e1.head().point,e0.head().point),t=[],v1=[];for(this.nVertices=2,this.normal=[0,0,0];e2!==e0;)copy$4(v1,v2),subtract$3(v2,e2.head().point,e0.head().point),add$1(this.normal,this.normal,cross$1(t,v1,v2)),e2=e2.next,this.nVertices+=1;this.area=length$2(this.normal),this.normal=scale$3(this.normal,this.normal,1/this.area)}computeNormalMinArea(minArea){if(this.computeNormal(),this.area<minArea){let maxEdge,maxSquaredLength=0,edge=this.edge;do{const lengthSquared=edge.lengthSquared();lengthSquared>maxSquaredLength&&(maxEdge=edge,maxSquaredLength=lengthSquared),edge=edge.next}while(edge!==this.edge);const p1=maxEdge.tail().point,p2=maxEdge.head().point,maxVector=subtract$3([],p2,p1),maxLength=Math.sqrt(maxSquaredLength);scale$3(maxVector,maxVector,1/maxLength);const maxProjection=dot$2(this.normal,maxVector);scale$3(maxVector,maxVector,-maxProjection),add$1(this.normal,this.normal,maxVector),normalize$1(this.normal,this.normal)}}computeCentroid(){this.centroid=[0,0,0];let edge=this.edge;do{add$1(this.centroid,this.centroid,edge.head().point),edge=edge.next}while(edge!==this.edge);scale$3(this.centroid,this.centroid,1/this.nVertices)}computeNormalAndCentroid(minArea){void 0!==minArea?this.computeNormalMinArea(minArea):this.computeNormal(),this.computeCentroid(),this.offset=dot$2(this.normal,this.centroid)}distanceToPlane(point){return dot$2(this.normal,point)-this.offset}connectHalfEdges(prev,next){let discardedFace;if(prev.opposite.face===next.opposite.face){const oppositeFace=next.opposite.face;let oppositeEdge;prev===this.edge&&(this.edge=next),3===oppositeFace.nVertices?(oppositeEdge=next.opposite.prev.opposite,oppositeFace.mark=2,discardedFace=oppositeFace):(oppositeEdge=next.opposite.next,oppositeFace.edge===oppositeEdge.prev&&(oppositeFace.edge=oppositeEdge),oppositeEdge.prev=oppositeEdge.prev.prev,oppositeEdge.prev.next=oppositeEdge),next.prev=prev.prev,next.prev.next=next,next.setOpposite(oppositeEdge),oppositeFace.computeNormalAndCentroid()}else prev.next=next,next.prev=prev;return discardedFace}mergeAdjacentFaces(adjacentEdge,discardedFaces){const oppositeEdge=adjacentEdge.opposite,oppositeFace=oppositeEdge.face;discardedFaces.push(oppositeFace),oppositeFace.mark=2;let edge,discardedFace,adjacentEdgePrev=adjacentEdge.prev,adjacentEdgeNext=adjacentEdge.next,oppositeEdgePrev=oppositeEdge.prev,oppositeEdgeNext=oppositeEdge.next;for(;adjacentEdgePrev.opposite.face===oppositeFace;)adjacentEdgePrev=adjacentEdgePrev.prev,oppositeEdgeNext=oppositeEdgeNext.next;for(;adjacentEdgeNext.opposite.face===oppositeFace;)adjacentEdgeNext=adjacentEdgeNext.next,oppositeEdgePrev=oppositeEdgePrev.prev;for(edge=oppositeEdgeNext;edge!==oppositeEdgePrev.next;edge=edge.next)edge.face=this;return this.edge=adjacentEdgeNext,discardedFace=this.connectHalfEdges(oppositeEdgePrev,adjacentEdgeNext),discardedFace&&discardedFaces.push(discardedFace),discardedFace=this.connectHalfEdges(adjacentEdgePrev,oppositeEdgeNext),discardedFace&&discardedFaces.push(discardedFace),this.computeNormalAndCentroid(),discardedFaces}collectIndices(){const indices=[];let edge=this.edge;do{indices.push(edge.head().index),edge=edge.next}while(edge!==this.edge);return indices}static createTriangle(v0,v1,v2,minArea=0){const face=new Face,e0=new HalfEdge(v0,face),e1=new HalfEdge(v1,face),e2=new HalfEdge(v2,face);return e0.next=e2.prev=e1,e1.next=e0.prev=e2,e2.next=e1.prev=e0,face.edge=e0,face.computeNormalAndCentroid(minArea),face}}class QuickHull{constructor(points){if(!Array.isArray(points))throw TypeError("input is not a valid array");if(points.length<4)throw Error("cannot build a simplex out of <4 points");this.tolerance=-1,this.nFaces=0,this.nPoints=points.length,this.faces=[],this.newFaces=[],this.claimed=new VertexList,this.unclaimed=new VertexList,this.vertices=[];for(let i=0;i<points.length;i+=1)this.vertices.push(new Vertex(points[i],i));this.discardedFaces=[],this.vertexPointIndices=[]}addVertexToFace(vertex,face){vertex.face=face,face.outside?this.claimed.insertBefore(face.outside,vertex):this.claimed.add(vertex),face.outside=vertex}removeVertexFromFace(vertex,face){vertex===face.outside&&(vertex.next&&vertex.next.face===face?face.outside=vertex.next:face.outside=null),this.claimed.remove(vertex)}removeAllVerticesFromFace(face){if(face.outside){let end=face.outside;for(;end.next&&end.next.face===face;)end=end.next;return this.claimed.removeChain(face.outside,end),end.next=null,face.outside}}deleteFaceVertices(face,absorbingFace){const faceVertices=this.removeAllVerticesFromFace(face);if(faceVertices)if(absorbingFace){let nextVertex;for(let vertex=faceVertices;vertex;vertex=nextVertex)nextVertex=vertex.next,absorbingFace.distanceToPlane(vertex.point)>this.tolerance?this.addVertexToFace(vertex,absorbingFace):this.unclaimed.add(vertex)}else this.unclaimed.addAll(faceVertices)}resolveUnclaimedPoints(newFaces){let vertexNext=this.unclaimed.first();for(let vertex=vertexNext;vertex;vertex=vertexNext){vertexNext=vertex.next;let maxFace,maxDistance=this.tolerance;for(let i=0;i<newFaces.length;i+=1){const face=newFaces[i];if(0===face.mark){const dist=face.distanceToPlane(vertex.point);if(dist>maxDistance&&(maxDistance=dist,maxFace=face),maxDistance>1e3*this.tolerance)break}}maxFace&&this.addVertexToFace(vertex,maxFace)}}computeExtremes(){const min=[],max=[],minVertices=[],maxVertices=[];let i,j;for(i=0;i<3;i+=1)minVertices[i]=maxVertices[i]=this.vertices[0];for(i=0;i<3;i+=1)min[i]=max[i]=this.vertices[0].point[i];for(i=1;i<this.vertices.length;i+=1){const vertex=this.vertices[i],point=vertex.point;for(j=0;j<3;j+=1)point[j]<min[j]&&(min[j]=point[j],minVertices[j]=vertex);for(j=0;j<3;j+=1)point[j]>max[j]&&(max[j]=point[j],maxVertices[j]=vertex)}return this.tolerance=3*Number.EPSILON*(Math.max(Math.abs(min[0]),Math.abs(max[0]))+Math.max(Math.abs(min[1]),Math.abs(max[1]))+Math.max(Math.abs(min[2]),Math.abs(max[2]))),[minVertices,maxVertices]}createInitialSimplex(){const vertices=this.vertices,[min,max]=this.computeExtremes();let v2,v3,i,j,maxDistance=0,indexMax=0;for(i=0;i<3;i+=1){const distance=max[i].point[i]-min[i].point[i];distance>maxDistance&&(maxDistance=distance,indexMax=i)}const v0=min[indexMax],v1=max[indexMax];for(maxDistance=0,i=0;i<this.vertices.length;i+=1){const vertex=this.vertices[i];if(vertex!==v0&&vertex!==v1){const distance=(point=vertex.point,a=v0.point,b=v1.point,Math.sqrt(((p,a,b)=>{const ab=[],ap=[];subtract$3(ab,b,a),subtract$3(ap,p,a);const area=squaredLength$1(cross$1([],ap,ab)),s=squaredLength$1(ab);if(0===s)throw Error("a and b are the same point");return area/s})(point,a,b)));distance>maxDistance&&(maxDistance=distance,v2=vertex)}}var point,a,b;const normal=fromPoints$4([],v0.point,v1.point,v2.point),distPO=dot$2(v0.point,normal);for(maxDistance=-1,i=0;i<this.vertices.length;i+=1){const vertex=this.vertices[i];if(vertex!==v0&&vertex!==v1&&vertex!==v2){const distance=Math.abs(dot$2(normal,vertex.point)-distPO);distance>maxDistance&&(maxDistance=distance,v3=vertex)}}const faces=[];if(dot$2(v3.point,normal)-distPO<0)for(faces.push(Face.createTriangle(v0,v1,v2),Face.createTriangle(v3,v1,v0),Face.createTriangle(v3,v2,v1),Face.createTriangle(v3,v0,v2)),i=0;i<3;i+=1){const j=(i+1)%3;faces[i+1].getEdge(2).setOpposite(faces[0].getEdge(j)),faces[i+1].getEdge(1).setOpposite(faces[j+1].getEdge(0))}else for(faces.push(Face.createTriangle(v0,v2,v1),Face.createTriangle(v3,v0,v1),Face.createTriangle(v3,v1,v2),Face.createTriangle(v3,v2,v0)),i=0;i<3;i+=1){const j=(i+1)%3;faces[i+1].getEdge(2).setOpposite(faces[0].getEdge((3-i)%3)),faces[i+1].getEdge(0).setOpposite(faces[j+1].getEdge(1))}for(i=0;i<4;i+=1)this.faces.push(faces[i]);for(i=0;i<vertices.length;i+=1){const vertex=vertices[i];if(vertex!==v0&&vertex!==v1&&vertex!==v2&&vertex!==v3){let maxFace;for(maxDistance=this.tolerance,j=0;j<4;j+=1){const distance=faces[j].distanceToPlane(vertex.point);distance>maxDistance&&(maxDistance=distance,maxFace=faces[j])}maxFace&&this.addVertexToFace(vertex,maxFace)}}}reindexFaceAndVertices(){const activeFaces=[];for(let i=0;i<this.faces.length;i+=1){const face=this.faces[i];0===face.mark&&activeFaces.push(face)}this.faces=activeFaces}collectFaces(skipTriangulation){const faceIndices=[];for(let i=0;i<this.faces.length;i+=1){if(0!==this.faces[i].mark)throw Error("attempt to include a destroyed face in the hull");const indices=this.faces[i].collectIndices();if(skipTriangulation)faceIndices.push(indices);else for(let j=0;j<indices.length-2;j+=1)faceIndices.push([indices[0],indices[j+1],indices[j+2]])}return faceIndices}nextVertexToAdd(){if(!this.claimed.isEmpty()){let eyeVertex,vertex,maxDistance=0;const eyeFace=this.claimed.first().face;for(vertex=eyeFace.outside;vertex&&vertex.face===eyeFace;vertex=vertex.next){const distance=eyeFace.distanceToPlane(vertex.point);distance>maxDistance&&(maxDistance=distance,eyeVertex=vertex)}return eyeVertex}}computeHorizon(eyePoint,crossEdge,face,horizon){let edge;this.deleteFaceVertices(face),face.mark=2,edge=crossEdge?crossEdge.next:crossEdge=face.getEdge(0);do{const oppositeEdge=edge.opposite,oppositeFace=oppositeEdge.face;0===oppositeFace.mark&&(oppositeFace.distanceToPlane(eyePoint)>this.tolerance?this.computeHorizon(eyePoint,oppositeEdge,oppositeFace,horizon):horizon.push(edge)),edge=edge.next}while(edge!==crossEdge)}addAdjoiningFace(eyeVertex,horizonEdge){const face=Face.createTriangle(eyeVertex,horizonEdge.tail(),horizonEdge.head());return this.faces.push(face),face.getEdge(-1).setOpposite(horizonEdge.opposite),face.getEdge(0)}addNewFaces(eyeVertex,horizon){let firstSideEdge,previousSideEdge;this.newFaces=[];for(let i=0;i<horizon.length;i+=1){const horizonEdge=horizon[i],sideEdge=this.addAdjoiningFace(eyeVertex,horizonEdge);firstSideEdge?sideEdge.next.setOpposite(previousSideEdge):firstSideEdge=sideEdge,this.newFaces.push(sideEdge.face),previousSideEdge=sideEdge}firstSideEdge.next.setOpposite(previousSideEdge)}oppositeFaceDistance(edge){return edge.face.distanceToPlane(edge.opposite.face.centroid)}doAdjacentMerge(face,mergeType){let edge=face.edge,convex=!0,it=0;do{if(it>=face.nVertices)throw Error("merge recursion limit exceeded");const oppositeFace=edge.opposite.face;let merge=!1;if(2===mergeType?(this.oppositeFaceDistance(edge)>-this.tolerance||this.oppositeFaceDistance(edge.opposite)>-this.tolerance)&&(merge=!0):face.area>oppositeFace.area?this.oppositeFaceDistance(edge)>-this.tolerance?merge=!0:this.oppositeFaceDistance(edge.opposite)>-this.tolerance&&(convex=!1):this.oppositeFaceDistance(edge.opposite)>-this.tolerance?merge=!0:this.oppositeFaceDistance(edge)>-this.tolerance&&(convex=!1),merge){const discardedFaces=face.mergeAdjacentFaces(edge,[]);for(let i=0;i<discardedFaces.length;i+=1)this.deleteFaceVertices(discardedFaces[i],face);return!0}edge=edge.next,it+=1}while(edge!==face.edge);return convex||(face.mark=1),!1}addVertexToHull(eyeVertex){const horizon=[];this.unclaimed.clear(),this.removeVertexFromFace(eyeVertex,eyeVertex.face),this.computeHorizon(eyeVertex.point,null,eyeVertex.face,horizon),this.addNewFaces(eyeVertex,horizon);for(let i=0;i<this.newFaces.length;i+=1){const face=this.newFaces[i];if(0===face.mark)for(;this.doAdjacentMerge(face,1););}for(let i=0;i<this.newFaces.length;i+=1){const face=this.newFaces[i];if(1===face.mark)for(face.mark=0;this.doAdjacentMerge(face,2););}this.resolveUnclaimedPoints(this.newFaces)}build(){let eyeVertex;for(this.createInitialSimplex();eyeVertex=this.nextVertexToAdd();)this.addVertexToHull(eyeVertex);this.reindexFaceAndVertices()}}const toPolygons$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.polygons=geometry.polygons.map((polygon=>transform$7(geometry.transforms,polygon))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).polygons,isA$3=object=>!!(object&&"object"==typeof object&&"polygons"in object&&"transforms"in object&&Array.isArray(object.polygons)&&"length"in object.transforms);Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$8,fromPoints:listOfLists=>{if(!Array.isArray(listOfLists))throw new Error("the given vertices must be an array");return create$8(listOfLists.map(create$7))},fromPointsConvex:uniquePoints=>{if(!Array.isArray(uniquePoints))throw new Error("the given points must be an array");const polygons=((points,options={})=>{const instance=new QuickHull(points);return instance.build(),instance.collectFaces(options.skipTriangulation)})(uniquePoints,{skipTriangulation:!0}).map((face=>{const vertices=face.map((index=>uniquePoints[index]));return create$7(vertices)}));return create$8(polygons)},fromCompactBinary:data=>{if(1!==data[0])throw new Error("invalid compact binary data");const created=create$8();created.transforms=clone$a(data.slice(1,17));const numberOfVertices=data[21];let ci=22,vi=data.length-3*numberOfVertices;for(;vi<data.length;){const verticesPerPolygon=data[ci];ci++;const vertices=[];for(let i=0;i<verticesPerPolygon;i++)vertices.push(fromValues$3(data[vi],data[vi+1],data[vi+2])),vi+=3;created.polygons.push(create$7(vertices))}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},invert:geometry=>{const newPolygons=toPolygons$1(geometry).map((polygon=>invert$1(polygon)));return create$8(newPolygons)},isA:isA$3,toPoints:geometry=>toPolygons$1(geometry).map((polygon=>toVertices$1(polygon))),toPolygons:toPolygons$1,toString:geometry=>{const polygons=toPolygons$1(geometry);let result="geom3 ("+polygons.length+" polygons):\n";return polygons.forEach((polygon=>{result+=" "+toString$6(polygon)+"\n"})),result},toCompactBinary:geometry=>{const polygons=geometry.polygons,transforms=geometry.transforms,numberOfPolygons=polygons.length,numberOfVertices=polygons.reduce(((count,polygon)=>count+polygon.vertices.length),0);let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+numberOfPolygons+3*numberOfVertices);compacted[0]=1,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3],compacted[21]=numberOfVertices;let ci=22,vi=ci+numberOfPolygons;return polygons.forEach((polygon=>{const vertices=toVertices$1(polygon);compacted[ci]=vertices.length,ci++;for(let i=0;i<vertices.length;i++){const vertex=vertices[i];compacted[vi+0]=vertex[0],compacted[vi+1]=vertex[1],compacted[vi+2]=vertex[2],vi+=3}})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$3(object))throw new Error("invalid geom3 structure");if(object.polygons.forEach(validate$4),(object=>{const edgeCount=new Map;object.polygons.forEach((({vertices:vertices})=>{vertices.forEach(((v,i)=>{const edge=`${v}/${vertices[(i+1)%vertices.length]}`,count=edgeCount.has(edge)?edgeCount.get(edge):0;edgeCount.set(edge,count+1)}))}));const nonManifold=[];if(edgeCount.forEach(((count,edge)=>{const complementEdge=edge.split("/").reverse().join("/");count!==edgeCount.get(complementEdge)&&nonManifold.push(edge.replace("/"," -> "))})),nonManifold.length>0)throw new Error(`non-manifold edges ${nonManifold.length}\n${nonManifold.join("\n")}`)})(object),!object.transforms.every(Number.isFinite))throw new Error(`geom3 invalid transforms ${object.transforms}`)}});const clone$4=geometry=>Object.assign({},geometry),close=geometry=>{if(geometry.isClosed)return geometry;const cloned=clone$4(geometry);if(cloned.isClosed=!0,cloned.points.length>1){const points=cloned.points,p0=points[0];let pn=points[points.length-1];for(;distance(p0,pn)<EPS*EPS&&(points.pop(),1!==points.length);)pn=points[points.length-1]}return cloned},create$5=points=>(void 0===points&&(points=[]),{points:points,isClosed:!1,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),fromPoints$2=(options,points)=>{let{closed:closed}=Object.assign({},{closed:!1},options),created=create$5();if(created.points=points.map((point=>clone$8(point))),created.points.length>1){const p0=created.points[0],pn=created.points[created.points.length-1];distance(p0,pn)<EPS*EPS&&(closed=!0)}return!0===closed&&(created=close(created)),created},toPoints$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.points=geometry.points.map((point=>transform$b([0,0],point,geometry.transforms))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).points,concat=(...paths)=>{let isClosed=!1,newPoints=[];return paths.forEach(((path,i)=>{const tmp=toPoints$1(path).slice();if(newPoints.length>0&&tmp.length>0&&equals$6(tmp[0],newPoints[newPoints.length-1])&&tmp.shift(),tmp.length>0&&isClosed)throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`);isClosed=path.isClosed,newPoints=newPoints.concat(tmp)})),fromPoints$2({closed:isClosed},newPoints)},appendPoints=(points,geometry)=>concat(geometry,create$5(points)),isA$2=object=>!!(object&&"object"==typeof object&&"points"in object&&"transforms"in object&&"isClosed"in object&&Array.isArray(object.points)&&"length"in object.transforms);Object.freeze({__proto__:null,appendArc:(options,geometry)=>{let{endpoint:endpoint,radius:radius,xaxisRotation:xaxisRotation,clockwise:clockwise,large:large,segments:segments}=Object.assign({},{radius:[0,0],xaxisRotation:0,clockwise:!1,large:!1,segments:16},options);if(!Array.isArray(endpoint))throw new Error("endpoint must be an array of X and Y values");if(endpoint.length<2)throw new Error("endpoint must contain X and Y values");if(endpoint=clone$8(endpoint),!Array.isArray(radius))throw new Error("radius must be an array of X and Y values");if(radius.length<2)throw new Error("radius must contain X and Y values");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given path cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the arc)");let xRadius=radius[0],yRadius=radius[1];const startpoint=points[points.length-1];xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5,endpoint=fromValues$2(Math.round(1e5*endpoint[0])/1e5,Math.round(1e5*endpoint[1])/1e5);const sweepFlag=!clockwise;let newPoints=[];if(0===xRadius||0===yRadius)newPoints.push(endpoint);else{xRadius=Math.abs(xRadius),yRadius=Math.abs(yRadius);const phi=xaxisRotation,cosPhi=Math.cos(phi),sinPhi=Math.sin(phi),minusHalfDistance=subtract$1([0,0],startpoint,endpoint);scale$1(minusHalfDistance,minusHalfDistance,.5);const x=Math.round(1e5*(cosPhi*minusHalfDistance[0]+sinPhi*minusHalfDistance[1]))/1e5,y=Math.round(1e5*(-sinPhi*minusHalfDistance[0]+cosPhi*minusHalfDistance[1]))/1e5,startTranslated=fromValues$2(x,y),bigLambda=startTranslated[0]*startTranslated[0]/(xRadius*xRadius)+startTranslated[1]*startTranslated[1]/(yRadius*yRadius);if(bigLambda>1){const sqrtBigLambda=Math.sqrt(bigLambda);xRadius*=sqrtBigLambda,yRadius*=sqrtBigLambda,xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5}let multiplier1=Math.sqrt((xRadius*xRadius*yRadius*yRadius-xRadius*xRadius*startTranslated[1]*startTranslated[1]-yRadius*yRadius*startTranslated[0]*startTranslated[0])/(xRadius*xRadius*startTranslated[1]*startTranslated[1]+yRadius*yRadius*startTranslated[0]*startTranslated[0]));sweepFlag===large&&(multiplier1=-multiplier1);const centerTranslated=fromValues$2(xRadius*startTranslated[1]/yRadius,-yRadius*startTranslated[0]/xRadius);scale$1(centerTranslated,centerTranslated,multiplier1);let center=fromValues$2(cosPhi*centerTranslated[0]-sinPhi*centerTranslated[1],sinPhi*centerTranslated[0]+cosPhi*centerTranslated[1]);center=add(center,center,scale$1([0,0],add([0,0],startpoint,endpoint),.5));const vector1=fromValues$2((startTranslated[0]-centerTranslated[0])/xRadius,(startTranslated[1]-centerTranslated[1])/yRadius),vector2=fromValues$2((-startTranslated[0]-centerTranslated[0])/xRadius,(-startTranslated[1]-centerTranslated[1])/yRadius),theta1=angleRadians(vector1);let deltatheta=angleRadians(vector2)-theta1;deltatheta%=TAU,!sweepFlag&&deltatheta>0?deltatheta-=TAU:sweepFlag&&deltatheta<0&&(deltatheta+=TAU);let numSteps=Math.ceil(Math.abs(deltatheta)/TAU*segments)+1;numSteps<1&&(numSteps=1);for(let step=1;step<numSteps;step++){const theta=theta1+step/numSteps*deltatheta,cosTheta=Math.cos(theta),sinTheta=Math.sin(theta),point=fromValues$2(cosPhi*xRadius*cosTheta-sinPhi*yRadius*sinTheta,sinPhi*xRadius*cosTheta+cosPhi*yRadius*sinTheta);add(point,point,center),newPoints.push(point)}numSteps&&newPoints.push(options.endpoint)}return newPoints=points.concat(newPoints),fromPoints$2({},newPoints)},appendBezier:(options,geometry)=>{let{controlPoints:controlPoints,segments:segments}=Object.assign({},{segments:16},options);if(!Array.isArray(controlPoints))throw new Error("controlPoints must be an array of one or more points");if(controlPoints.length<1)throw new Error("controlPoints must be an array of one or more points");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given geometry cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the bezier curve)");if(controlPoints=controlPoints.slice(),null===controlPoints[0]){if(controlPoints.length<2)throw new Error("a null control point must be passed with one more control points");let lastBezierControlPoint=points[points.length-2];if("lastBezierControlPoint"in geometry&&(lastBezierControlPoint=geometry.lastBezierControlPoint),!Array.isArray(lastBezierControlPoint))throw new Error("the given path must contain TWO or more points if given a null control point");const controlPoint=scale$1([0,0],points[points.length-1],2);subtract$1(controlPoint,controlPoint,lastBezierControlPoint),controlPoints[0]=controlPoint}controlPoints.unshift(points[points.length-1]);const bezierOrder=controlPoints.length-1,factorials=[];let fact=1;for(let i=0;i<=bezierOrder;++i)i>0&&(fact*=i),factorials.push(fact);const binomials=[];for(let i=0;i<=bezierOrder;++i){const binomial=factorials[bezierOrder]/(factorials[i]*factorials[bezierOrder-i]);binomials.push(binomial)}const v0=[0,0],v1=[0,0],v3=[0,0,0],getPointForT=t=>{let tk=1,oneMinusTNMinusK=Math.pow(1-t,bezierOrder);const invOneMinusT=1!==t?1/(1-t):1,point=[0,0];for(let k=0;k<=bezierOrder;++k){k===bezierOrder&&(oneMinusTNMinusK=1);const bernsteinCoefficient=binomials[k]*tk*oneMinusTNMinusK,derivativePoint=scale$1(v0,controlPoints[k],bernsteinCoefficient);add(point,point,derivativePoint),tk*=t,oneMinusTNMinusK*=invOneMinusT}return point},newPoints=[],newPointsT=[],numSteps=bezierOrder+1;for(let i=0;i<numSteps;++i){const t=i/(numSteps-1),point=getPointForT(t);newPoints.push(point),newPointsT.push(t)}let subdivideBase=1;const maxAngle=TAU/segments,maxSinAngle=Math.sin(maxAngle);for(;subdivideBase<newPoints.length-1;){const dir1=subtract$1(v0,newPoints[subdivideBase],newPoints[subdivideBase-1]);normalize(dir1,dir1);const dir2=subtract$1(v1,newPoints[subdivideBase+1],newPoints[subdivideBase]);normalize(dir2,dir2);const sinAngle=cross(v3,dir1,dir2);if(Math.abs(sinAngle[2])>maxSinAngle){const t0=newPointsT[subdivideBase-1],t1=newPointsT[subdivideBase+1],newt0=t0+1*(t1-t0)/3,newt1=t0+2*(t1-t0)/3,point0=getPointForT(newt0),point1=getPointForT(newt1);newPoints.splice(subdivideBase,1,point0,point1),newPointsT.splice(subdivideBase,1,newt0,newt1),subdivideBase--,subdivideBase<1&&(subdivideBase=1)}else++subdivideBase}newPoints.shift();const result=appendPoints(newPoints,geometry);return result.lastBezierControlPoint=controlPoints[controlPoints.length-2],result},appendPoints:appendPoints,clone:clone$4,close:close,concat:concat,create:create$5,equals:(a,b)=>{if(a.isClosed!==b.isClosed)return!1;if(a.points.length!==b.points.length)return!1;const aPoints=toPoints$1(a),bPoints=toPoints$1(b),length=aPoints.length;let offset=0;do{let unequal=!1;for(let i=0;i<length;i++)if(!equals$6(aPoints[i],bPoints[(i+offset)%length])){unequal=!0;break}if(!1===unequal)return!0;if(!a.isClosed)return!1}while(++offset<length);return!1},fromPoints:fromPoints$2,fromCompactBinary:data=>{if(2!==data[0])throw new Error("invalid compact binary data");const created=create$5();created.transforms=clone$a(data.slice(1,17)),created.isClosed=!!data[17];for(let i=22;i<data.length;i+=2){const point=fromValues$2(data[i],data[i+1]);created.points.push(point)}return data[18]>=0&&(created.color=[data[18],data[19],data[20],data[21]]),created},isA:isA$2,reverse:geometry=>{const cloned=clone$4(geometry);return cloned.points=geometry.points.slice().reverse(),cloned},toPoints:toPoints$1,toString:geometry=>{const points=toPoints$1(geometry);let result="path ("+points.length+" points, "+geometry.isClosed+"):\n[\n";return points.forEach((point=>{result+=" "+toString$9(point)+",\n"})),result+="]\n",result},toCompactBinary:geometry=>{const points=geometry.points,transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+2*points.length);compacted[0]=2,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=geometry.isClosed?1:0,compacted[18]=color[0],compacted[19]=color[1],compacted[20]=color[2],compacted[21]=color[3];for(let j=0;j<points.length;j++){const ci=2*j+22,point=points[j];compacted[ci]=point[0],compacted[ci+1]=point[1]}return compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$2(object))throw new Error("invalid path2 structure");if(object.points.length>1)for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`path2 has duplicate point ${object.points[i]}`);if(object.points.forEach((point=>{if(!point.every(Number.isFinite))throw new Error(`path2 invalid point ${point}`)})),!object.transforms.every(Number.isFinite))throw new Error(`path2 invalid transforms ${object.transforms}`)}});const getPermutations=function(c){const permutations=[];for(let i=0;i<=c;i++)permutations.push(factorial(c)/(factorial(i)*factorial(c-i)));return permutations},factorial=function(b){let out=1;for(let i=2;i<=b;i++)out*=i;return out},valueAt=(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier valueAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierFunction(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierFunction(bezier,singleDimensionPoints,t))}return result}},bezierFunction=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<=n;i++)result+=bezier.permutations[i]*Math.pow(1-t,n-i)*Math.pow(t,i)*p[i];return result},bezierTangent=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<n;i++){const q=n*(p[i+1]-p[i]);result+=bezier.tangentPermutations[i]*Math.pow(1-t,n-1-i)*Math.pow(t,i)*q}return result},lengths=(segments,bezier)=>{let sum=0;const lengths=[0];let previous=valueAt(0,bezier);for(let index=1;index<=segments;index++){const current=valueAt(index/segments,bezier);sum+=distanceBetween(current,previous),lengths.push(sum),previous=current}return lengths},distanceBetween=(a,b)=>{if(Number.isFinite(a)&&Number.isFinite(b))return Math.abs(a-b);if(Array.isArray(a)&&Array.isArray(b)){if(a.length!==b.length)throw new Error("The operands must have the same number of dimensions.");let sum=0;for(let i=0;i<a.length;i++)sum+=(b[i]-a[i])*(b[i]-a[i]);return Math.sqrt(sum)}throw new Error("The operands must be of the same type, either number or array.")};Object.freeze({__proto__:null,create:points=>{if(!Array.isArray(points))throw new Error("Bezier points must be a valid array/");if(points.length<2)throw new Error("Bezier points must contain at least 2 values.");const pointType=function(points){let firstPointType=null;return points.forEach((point=>{let pType="";if(Number.isFinite(point))pType="float_single";else{if(!Array.isArray(point))throw new Error("Bezier points must all be numbers or arrays of number.");point.forEach((val=>{if(!Number.isFinite(val))throw new Error("Bezier point values must all be numbers.")})),pType="float_"+point.length}if(null==firstPointType)firstPointType=pType;else if(firstPointType!==pType)throw new Error("Bezier points must be either all numbers or all arrays of numbers of the same size.")})),firstPointType}(points);return{points:points,pointType:pointType,dimensions:"float_single"===pointType?0:points[0].length,permutations:getPermutations(points.length-1),tangentPermutations:getPermutations(points.length-2)}},valueAt:valueAt,tangentAt:(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier tangentAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierTangent(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierTangent(bezier,singleDimensionPoints,t))}return result}},lengths:lengths,length:(segments,bezier)=>lengths(segments,bezier)[segments],arcLengthToT:(options,bezier)=>{const{distance:distance,segments:segments}=Object.assign({},{distance:0,segments:100},options),arcLengths=lengths(segments,bezier);let startIndex=0,endIndex=segments;for(;startIndex<=endIndex;){const middleIndex=Math.floor(startIndex+(endIndex-startIndex)/2),diff=arcLengths[middleIndex]-distance;if(diff<0)startIndex=middleIndex+1;else{if(!(diff>0)){endIndex=middleIndex;break}endIndex=middleIndex-1}}const targetIndex=endIndex;if(arcLengths[targetIndex]===distance)return targetIndex/segments;const lengthBefore=arcLengths[targetIndex];return(targetIndex+(distance-lengthBefore)/(arcLengths[targetIndex+1]-lengthBefore))/segments}});const area$1=points=>{let area=0;for(let i=0;i<points.length;i++){const j=(i+1)%points.length;area+=points[i][0]*points[j][1],area-=points[j][0]*points[i][1]}return area/2},measureArea$1=polygon=>area$1(polygon.points),create$3=points=>((void 0===points||points.length<3)&&(points=[]),{points:points}),reverse$3=polygon=>{const points=polygon.points.slice().reverse();return create$3(points)},arePointsInside=(points,polygon)=>0===points.length||polygon.points.length<3?0:(measureArea$1(polygon)<0&&(polygon=reverse$3(polygon)),points.reduce(((acc,point)=>acc+isPointInside(point,polygon.points)),0)===points.length?1:0),isPointInside=(point,polygon)=>{const numPoints=polygon.length,tx=point[0],ty=point[1];let vtx0=polygon[numPoints-1],vtx1=polygon[0],yFlag0=vtx0[1]>ty,insideFlag=0,i=0;for(let j=numPoints+1;--j;){const yFlag1=vtx1[1]>ty;if(yFlag0!==yFlag1){const xFlag0=vtx0[0]>tx,xFlag1=vtx1[0]>tx;(xFlag0&&xFlag1||vtx1[0]-(vtx1[1]-ty)*(vtx0[0]-vtx1[0])/(vtx0[1]-vtx1[1])>=tx)&&(insideFlag=!insideFlag)}yFlag0=yFlag1,vtx0=vtx1,vtx1=polygon[++i]}return insideFlag},isA$1=object=>!!(object&&"object"==typeof object&&"points"in object&&Array.isArray(object.points)),crossBetweenSegments=(p1,p2,p3)=>{const X1=p2[0]-p1[0],Y1=p2[1]-p1[1],X2=p3[0]-p1[0];return X1*(p3[1]-p1[1])-Y1*X2};Object.freeze({__proto__:null,arePointsInside:arePointsInside,clone:polygon=>Object.assign({},polygon),create:create$3,isA:isA$1,isConvex:polygon=>{const numPoints=polygon.points.length;if(numPoints>2){const points=polygon.points;let prev=0,curr=0;for(let i=0;i<numPoints;i++)if(curr=crossBetweenSegments(points[i],points[(i+1)%numPoints],points[(i+2)%numPoints]),0!==curr){if(curr*prev<0)return!1;prev=curr}}return!0},isSimple:polygon=>{const numPoints=polygon.points.length;if(numPoints<3)return!1;if(3===numPoints)return!0;const points=polygon.points,found=new Set;if(points.forEach((v=>found.add(v.toString()))),found.size!==numPoints)return!1;for(let i=0;i<numPoints;i++)for(let j=i+2;j<numPoints;j++){const k=(j+1)%numPoints;if(i!==k){const s0=points[i],s1=points[(i+1)%numPoints],z0=points[j],z1=points[k];if(intersect$1(s0,s1,z0,z1))return!1}}return!0},measureArea:measureArea$1,measureBoundingBox:polygon=>{const points=polygon.points,numPoints=points.length,min=0===numPoints?[0,0]:clone$8(points[0]),max=clone$8(min);for(let i=1;i<numPoints;i++)min$1(min,min,points[i]),max$1(max,max,points[i]);return[min,max]},reverse:reverse$3,toPoints:polygon=>polygon.points,toString:polygon=>`poly2: [${polygon.points.map(toString$9).join(", ")}]`,transform:(matrix,polygon)=>{const points=polygon.points.map((point=>transform$b([0,0],point,matrix)));return isMirroring(matrix)&&points.reverse(),create$3(points)},validate:object=>{if(!isA$1(object))throw new Error("invalid poly2 structure");if(object.points.length<3)throw new Error(`poly2 not enough points ${object.points.length}`);if(measureArea$1(object)<=0)throw new Error("poly2 area must be greater than zero");for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`poly2 duplicate point at ${i}: [${object.points[i]}]`);object.points.forEach((point=>{if(2!==point.length)throw new Error(`poly2 invalid point ${point}`);if(!point.every(Number.isFinite))throw new Error(`poly2 invalid point ${point}`)}))}});const calculatePlane=slice=>{if(slice.contours.length<1)throw new Error("slices must have at least one contour to calculate a plane");const middle=[0,0,0];let n=0;slice.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(middle,middle,vertex),n++}))})),scale$3(middle,middle,1/n);let farthestBefore,farthestVertex,farthestAfter,farthestContour=[],distance=0;slice.contours.forEach((contour=>{let prev=contour[contour.length-1];contour.forEach((vertex=>{if(!equals$7(prev,vertex)){const d=squaredDistance$1(middle,vertex);d>distance&&(farthestContour=contour,farthestBefore=prev,farthestVertex=vertex,distance=d)}prev=vertex}))}));let prev=farthestContour[farthestContour.length-1];for(let i=0;i<farthestContour.length;i++){const vertex=farthestContour[i];if(!equals$7(prev,vertex)&&equals$7(prev,farthestVertex)){farthestAfter=vertex;break}prev=vertex}return fromPoints$4([0,0,0,0],farthestBefore,farthestVertex,farthestAfter)},create$2=(contours=[])=>({contours:contours}),isA=object=>!!(object&&"object"==typeof object&&"contours"in object&&Array.isArray(object.contours));class Node$2{constructor(i,x,y){this.i=i,this.x=x,this.y=y,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}}const insertNode=(i,x,y,last)=>{const p=new Node$2(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p},removeNode=p=>{p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)},pointInTriangle=(ax,ay,bx,by,cx,cy,px,py)=>(cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0,area=(p,q,r)=>(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y),linkedPolygon=(data,start,end,dim,clockwise)=>{let last;if(clockwise===signedArea$1(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);return last&&equals$2(last,last.next)&&(removeNode(last),last=last.next),last},filterPoints=(start,end)=>{if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals$2(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end},cureLocalIntersections=(start,triangles,dim)=>{let p=start;do{const a=p.prev,b=p.next.next;!equals$2(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i/dim),triangles.push(p.i/dim),triangles.push(b.i/dim),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)},locallyInside=(a,b)=>area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0,splitPolygon=(a,b)=>{const a2=new Node$2(a.i,a.x,a.y),b2=new Node$2(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2},isValidDiagonal=(a,b)=>a.next.i!==b.i&&a.prev.i!==b.i&&!((a,b)=>{let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1})(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&((a,b)=>{let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside})(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals$2(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0),intersects=(p1,q1,p2,q2)=>{const o1=Math.sign(area(p1,q1,p2)),o2=Math.sign(area(p1,q1,q2)),o3=Math.sign(area(p2,q2,p1)),o4=Math.sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||!(0!==o1||!onSegment(p1,p2,q1))||!(0!==o2||!onSegment(p1,q2,q1))||!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2))},onSegment=(p,q,r)=>q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y),signedArea$1=(data,start,end,dim)=>{let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum},equals$2=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y,eliminateHole=(hole,outerNode)=>{const bridge=findHoleBridge(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole),filteredBridge=filterPoints(bridge,bridge.next);return filterPoints(bridgeReverse,bridgeReverse.next),outerNode===bridge?filteredBridge:outerNode},findHoleBridge=(hole,outerNode)=>{let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){if(qx=x,x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next}m=p.x<p.next.x?p:p.next}}p=p.next}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m},sectorContainsSector=(m,p)=>area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0,getLeftmost=start=>{let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost},earcutLinked=(ear,triangles,dim,minX,minY,invSize,pass)=>{if(!ear)return;!pass&&invSize&&indexCurve(ear,minX,minY,invSize);let prev,next,stop=ear;for(;ear.prev!==ear.next;)if(prev=ear.prev,next=ear.next,invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i/dim),triangles.push(ear.i/dim),triangles.push(next.i/dim),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?(ear=cureLocalIntersections(filterPoints(ear),triangles,dim),earcutLinked(ear,triangles,dim,minX,minY,invSize,2)):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}},isEar=ear=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;let p=ear.next.next;for(;p!==ear.prev;){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0},isEarHashed=(ear,minX,minY,invSize)=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y,minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0},splitEarcut=(start,triangles,dim,minX,minY,invSize)=>{let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize),void earcutLinked(c,triangles,dim,minX,minY,invSize)}b=b.next}a=a.next}while(a!==start)},indexCurve=(start,minX,minY,invSize)=>{let p=start;do{null===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,((list,fn)=>{let i,p,q,e,numMerges,inSize=1;do{p=list,list=null;let tail=null;for(numMerges=0;p;){numMerges++,q=p;let pSize=0;for(i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||fn(p)<=fn(q))?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1)})(p,(p=>p.z))},zOrder=(x,y,minX,minY,invSize)=>(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=32767*(x-minX)*invSize)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=32767*(y-minY)*invSize)|y<<8))|y<<4))|y<<2))|y<<1))<<1;class PolygonHierarchy{constructor(slice){this.plane=calculatePlane(slice);const rightVector=orthogonal([0,0,0],this.plane),perp=cross$1([0,0,0],this.plane,rightVector);this.v=normalize$1(perp,perp),this.u=cross$1([0,0,0],this.v,this.plane),this.basisMap=new Map;const projected=slice.contours.map((part=>part.map((v=>this.to2D(v))))),geometry=create$a(projected);this.roots=(geometry=>{const outlines=toOutlines(geometry),solids=[],holes=[];outlines.forEach(((outline,i)=>{const a=area$1(outline);a<0?holes.push(i):a>0&&solids.push(i)}));const children=[],parents=[];return solids.forEach(((s,i)=>{const solid=outlines[s];children[i]=[],holes.forEach(((h,j)=>{const hole=outlines[h];arePointsInside([hole[0]],create$3(solid))&&(children[i].push(h),parents[j]||(parents[j]=[]),parents[j].push(i))}))})),holes.forEach(((h,j)=>{if(parents[j]&&parents[j].length>1){const directParent=((list,score)=>{let bestIndex,best;return list.forEach(((item,index)=>{const value=score(item);(void 0===best||value<best)&&(bestIndex=index,best=value)})),bestIndex})(parents[j],(p=>children[p].length));parents[j].forEach(((p,i)=>{i!==directParent&&(children[p]=children[p].filter((c=>c!==h)))}))}})),children.map(((holes,i)=>({solid:outlines[solids[i]],holes:holes.map((h=>outlines[h]))})))})(geometry)}to2D(vector3){const vector2=fromValues$2(dot$2(vector3,this.u),dot$2(vector3,this.v));return this.basisMap.set(vector2,vector3),vector2}to3D(vector2){const original=this.basisMap.get(vector2);if(original)return original;{console.log("Warning: point not in original slice");const v1=scale$3([0,0,0],this.u,vector2[0]),v2=scale$3([0,0,0],this.v,vector2[1]),planeOrigin=scale$3([0,0,0],this.plane,this.plane[3]),v3=add$1(v1,v1,planeOrigin);return add$1(v2,v2,v3)}}}Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:(a,b)=>{if(a.contours.length!==b.contours.length)return!1;const len=a.contours.length;for(let i=0;i<len;i++){const aVertex=a.contours[i];for(let j=0;j<len;j++){const bVertex=b.contours[j];if(!equals$7(aVertex,bVertex))return!1}}return!0},fromGeom2:geometry=>{const contours=toOutlines(geometry).map((outline=>outline.map((point=>fromVec2([0,0,0],point)))));return create$2(contours)},fromVertices:vertices=>{if(!Array.isArray(vertices))throw new Error("the given vertices must be an array");if(vertices.length<3)throw new Error("the given vertices must contain THREE or more vertices");const cloned=vertices.map((vertex=>3===vertex.length?vertex:fromVec2([0,0,0],vertex)));return create$2([cloned])},isA:isA,reverse:slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},toEdges:slice=>{const edges=[];return slice.contours.forEach((contour=>{contour.forEach(((vertex,i)=>{const next=contour[(i+1)%contour.length];edges.push([vertex,next])}))})),edges},toVertices:slice=>{const vertices=[];return slice.contours.forEach((contour=>{contour.forEach((vertex=>{vertices.push(vertex)}))})),vertices},toPolygons:slice=>{const hierarchy=new PolygonHierarchy(slice),polygons=[];return hierarchy.roots.forEach((({solid:solid,holes:holes})=>{let index=solid.length;const holesIndex=[];holes.forEach(((hole,i)=>{holesIndex.push(index),index+=hole.length}));const vertices=[solid,...holes].flat(),getVertex=i=>hierarchy.to3D(vertices[i]),indices=((data,holeIndices,dim=2)=>{const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedPolygon(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,maxX,maxY,invSize;if(hasHoles&&(outerNode=((data,holeIndices,outerNode,dim)=>{const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const start=holeIndices[i]*dim,end=i<len-1?holeIndices[i+1]*dim:data.length,list=linkedPolygon(data,start,end,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(((a,b)=>a.x-b.x));for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode),outerNode=filterPoints(outerNode,outerNode.next);return outerNode})(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=maxX=data[0],minY=maxY=data[1];for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?1/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize),triangles})(vertices.flat(),holesIndex);for(let i=0;i<indices.length;i+=3){const tri=indices.slice(i,i+3).map(getVertex);polygons.push(fromVerticesAndPlane(tri,hierarchy.plane))}})),polygons},toString:slice=>{let result="slice ("+slice.contours.length+" contours):\n[\n";return slice.contours.forEach((contour=>{result+=" ["+contour.map(toString$b).join()+"],\n"})),result+="]\n",result},transform:(matrix,slice)=>{const contours=slice.contours.map((contour=>contour.map((vertex=>transform$c([0,0,0],vertex,matrix)))));return create$2(contours)},validate:object=>{if(!isA(object))throw new Error("invalid slice structure");const slicePlane=calculatePlane(object);object.contours.forEach(((contour,i)=>{if(contour.length<3)throw new Error(`slice contour ${i} must contain at least 3 vertices`);const contourPlane=plane(create$7(contour));if(!equals$5(slicePlane,contourPlane))throw new Error("slice contours must be coplanar");for(let i=0;i<contour.length;i++){if(!contour[i].every(Number.isFinite))throw new Error(`slice contour ${i} must contain finite vertices`);const j=(i+1)%contour.length;if(equals$7(contour[i],contour[j]))throw new Error(`slice contour ${i} has duplicate vertex ${contour[i]}`)}}))}});const direction$1=line=>{const vector=normal([0,0],line);return negate(vector,vector),vector},origin$1=line=>scale$1([0,0],line,line[2]),copy$1=(out,line)=>(out[0]=line[0],out[1]=line[1],out[2]=line[2],out),fromPoints$1=(out,point1,point2)=>{const vector=subtract$1([0,0],point2,point1);normal(vector,vector),normalize(vector,vector);const distance=dot$1(point1,vector);return out[0]=vector[0],out[1]=vector[1],out[2]=distance,out},fromValues=(x,y,d)=>{const out=[0,1,0];return out[0]=x,out[1]=y,out[2]=d,out},solve2Linear=(a,b,c,d,u,v)=>{const invdet=1/(a*d-b*c);let x=u*d-b*v,y=-u*c+a*v;return x*=invdet,y*=invdet,[x,y]};Object.freeze({__proto__:null,clone:line=>{const out=[0,1,0];return out[0]=line[0],out[1]=line[1],out[2]=line[2],out},closestPoint:(line,point)=>{const orig=origin$1(line),dir=direction$1(line),v=subtract$1([0,0],point,orig),dist=dot$1(v,dir);return scale$1(v,dir,dist),add(v,v,orig),v},copy:copy$1,create:()=>[0,1,0],direction:direction$1,distanceToPoint:(line,point)=>{let distance=dot$1(point,line);return distance=Math.abs(distance-line[2]),distance},equals:(line1,line2)=>line1[0]===line2[0]&&line1[1]===line2[1]&&line1[2]===line2[2],fromPoints:fromPoints$1,fromValues:fromValues,intersectPointOfLines:(line1,line2)=>{const point=solve2Linear(line1[0],line1[1],line2[0],line2[1],line1[2],line2[2]);return clone$8(point)},origin:origin$1,reverse:(out,line)=>{const normal=negate([0,0],line),distance=-line[2];return copy$1(out,fromValues(normal[0],normal[1],distance))},toString:line=>`line2: (${line[0].toFixed(7)}, ${line[1].toFixed(7)}, ${line[2].toFixed(7)})`,transform:(out,line,matrix)=>{const org=origin$1(line),dir=direction$1(line);return transform$b(org,org,matrix),transform$b(dir,dir,matrix),fromPoints$1(out,org,dir)},xAtY:(line,y)=>{let x=(line[2]-line[1]*y)/line[0];return Number.isNaN(x)&&(x=origin$1(line)[0]),x}});const create=()=>[fromValues$3(0,0,0),fromValues$3(0,0,1)],closestPoint=(line,point)=>{const lPoint=line[0],lDirection=line[1],a=dot$2(subtract$3([0,0,0],point,lPoint),lDirection),b=dot$2(lDirection,lDirection),closestPoint=scale$3([0,0,0],lDirection,a/b);return add$1(closestPoint,closestPoint,lPoint),closestPoint},fromPointAndDirection=(out,point,direction)=>{const unit=normalize$1([0,0,0],direction);return copy$4(out[0],point),copy$4(out[1],unit),out};Object.freeze({__proto__:null,clone:line=>{const out=create();return copy$4(out[0],line[0]),copy$4(out[1],line[1]),out},closestPoint:closestPoint,copy:(out,line)=>(copy$4(out[0],line[0]),copy$4(out[1],line[1]),out),create:create,direction:line=>line[1],distanceToPoint:(line,point)=>{const closest=closestPoint(line,point),distanceVector=subtract$3([0,0,0],point,closest);return length$2(distanceVector)},equals:(line1,line2)=>!!equals$7(line1[1],line2[1])&&!!equals$7(line1[0],line2[0]),fromPlanes:(out,plane1,plane2)=>{let direction=cross$1([0,0,0],plane1,plane2),length=length$2(direction);if(length<EPS)throw new Error("parallel planes do not intersect");length=1/length,direction=scale$3(direction,direction,length);const absX=Math.abs(direction[0]),absY=Math.abs(direction[1]),absZ=Math.abs(direction[2]);let origin,r;return absX>=absY&&absX>=absZ?(r=solve2Linear(plane1[1],plane1[2],plane2[1],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(0,r[0],r[1])):absY>=absX&&absY>=absZ?(r=solve2Linear(plane1[0],plane1[2],plane2[0],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(r[0],0,r[1])):(r=solve2Linear(plane1[0],plane1[1],plane2[0],plane2[1],plane1[3],plane2[3]),origin=fromValues$3(r[0],r[1],0)),fromPointAndDirection(out,origin,direction)},fromPointAndDirection:fromPointAndDirection,fromPoints:(out,point1,point2)=>{const direction=subtract$3([0,0,0],point2,point1);return fromPointAndDirection(out,point1,direction)},intersectPointOfLineAndPlane:(line,plane)=>{const pNormal=plane,pw=plane[3],lPoint=line[0],lDirection=line[1],labda=(pw-dot$2(pNormal,lPoint))/dot$2(pNormal,lDirection);return add$1([0,0,0],lPoint,scale$3([0,0,0],lDirection,labda))},origin:line=>line[0],reverse:(out,line)=>{const point=clone$9(line[0]),direction=negate$1([0,0,0],line[1]);return fromPointAndDirection(out,point,direction)},toString:line=>{const point=line[0],direction=line[1];return`line3: point: (${point[0].toFixed(7)}, ${point[1].toFixed(7)}, ${point[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`},transform:(out,line,matrix)=>{const point=line[0],direction=line[1],pointPlusDirection=add$1([0,0,0],point,direction),newPoint=transform$c([0,0,0],point,matrix),newPointPlusDirection=transform$c(pointPlusDirection,pointPlusDirection,matrix),newDirection=subtract$3(newPointPlusDirection,newPointPlusDirection,newPoint);return fromPointAndDirection(out,newPoint,newDirection)}});const isNumberArray=(array,dimension)=>!!(Array.isArray(array)&&array.length>=dimension)&&array.every((n=>Number.isFinite(n)));class BinaryReader{constructor(data){this._buffer=data,this._pos=0}readInt8(){return this._decodeInt(8,!0)}readUInt8(){return this._decodeInt(8,!1)}readInt16(){return this._decodeInt(16,!0)}readUInt16(){return this._decodeInt(16,!1)}readInt32(){return this._decodeInt(32,!0)}readUInt32(){return this._decodeInt(32,!1)}readFloat(){return this._decodeFloat(23,8)}readDouble(){return this._decodeFloat(52,11)}readChar(){return this.readString(1)}readString(length){this._checkSize(8*length);const result=this._buffer.substr(this._pos,length);return this._pos+=length,result}seek(pos){this._pos=pos,this._checkSize(0)}getPosition(){return this._pos}getSize(){return this._buffer.length}_decodeFloat(precisionBits,exponentBits){const length=precisionBits+exponentBits+1,size=length>>3;this._checkSize(length);const bias=Math.pow(2,exponentBits-1)-1,signal=this._readBits(precisionBits+exponentBits,1,size),exponent=this._readBits(precisionBits,exponentBits,size);let significand=0,divisor=2,curByte=0,startBit=0;do{const byteValue=this._readByte(++curByte,size);startBit=precisionBits%8||8;let mask=1<<startBit;for(;mask>>=1;)byteValue&mask&&(significand+=1/divisor),divisor*=2}while(precisionBits-=startBit);return this._pos+=size,exponent===1+(bias<<1)?significand?NaN:signal?-1/0:1/0:(1+-2*signal)*(exponent||significand?exponent?Math.pow(2,exponent-bias)*(1+significand):Math.pow(2,1-bias)*significand:0)}_decodeInt(bits,signed){const x=this._readBits(0,bits,bits/8),max=Math.pow(2,bits),result=signed&&x>=max/2?x-max:x;return this._pos+=bits/8,result}_shl(a,b){for(++b;--b;a=1073741824==(1073741824&(a%=2147483648))?2*a:2*(a-1073741824)+2147483647+1);return a}_readByte(i,size){return 255&this._buffer.charCodeAt(this._pos+size-i-1)}_readBits(start,length,size){const offsetLeft=(start+length)%8,offsetRight=start%8,curByte=size-(start>>3)-1;let lastByte=size+(-(start+length)>>3),diff=curByte-lastByte,sum=this._readByte(curByte,size)>>offsetRight&(1<<(diff?8-offsetRight:length))-1;for(diff&&offsetLeft&&(sum+=(this._readByte(lastByte++,size)&(1<<offsetLeft)-1)<<(diff--<<3)-offsetRight);diff;)sum+=this._shl(this._readByte(lastByte++,size),(diff--<<3)-offsetRight);return sum}_checkSize(neededBits){this._pos,Math.ceil(neededBits/8),this._buffer.length}}const bufferToBinaryString=buffer=>{let binary="";const bytes=new Uint8Array(buffer),length=bytes.byteLength;for(let i=0;i<length;i++)binary+=String.fromCharCode(bytes[i]);return binary},isBuffer=obj=>void 0!==obj.byteLength&&"function"==typeof obj.slice,isDataBinaryRobust=data=>{const text=(buf=>{if("string"!=typeof buf){const arrayBuffer=new Uint8Array(buf);let str="";for(let i=0;i<buf.byteLength;i++)str+=String.fromCharCode(arrayBuffer[i]);return str}return buf})(data);return null===/vertex[\s]+([-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+/g.exec(text)},formatAsJscad=(data,addMetaData,version,filename)=>{let code="";return addMetaData&&(code=`\n //\n // producer: JSCAD STL Deserializer ${version}\n // date: ${new Date}\n // source: ${filename}\n // objects: ${data.length}\n //\n `),code+="import * from '@jscad/modeling'\n",code+=data.join("\n"),code+=`\nexport const main = () => {\n return [${data.map(((d,i)=>`solid${i+1}()`))}]\n}\n`,code},formatAsCsg=data=>data,deserializeBinarySTL=(stl,filename,version,elementFormatter)=>{const vertices=[],triangles=[],normals=[],colors=[];let vertexIndex=0,err=0,mcolor=null;const umask=parseInt("01000000000000000",2),rmask=parseInt("00000000000011111",2),gmask=parseInt("00000001111100000",2),bmask=parseInt("00111110000000000",2),br=new BinaryReader(stl);let m=0,c=0,r=0,g=0,b=0,a=0;for(let i=0;i<80;i++)switch(m){case 6:r=br.readUInt8(),m+=1;continue;case 7:g=br.readUInt8(),m+=1;continue;case 8:b=br.readUInt8(),m+=1;continue;case 9:a=br.readUInt8(),m+=1;continue;default:switch(c=br.readChar(),c){case"C":case"O":case"L":case"R":case"=":m+=1}}10===m&&(mcolor=[r/255,g/255,b/255,a/255]);const totalTriangles=br.readUInt32();for(let tr=0;tr<totalTriangles;tr++){const no=[];no.push(br.readFloat()),no.push(br.readFloat()),no.push(br.readFloat());let v1=[];v1.push(br.readFloat()),v1.push(br.readFloat()),v1.push(br.readFloat());const v2=[];v2.push(br.readFloat()),v2.push(br.readFloat()),v2.push(br.readFloat());let v3=[];v3.push(br.readFloat()),v3.push(br.readFloat()),v3.push(br.readFloat());let skip=0;for(let i=0;i<3;i++)isNaN(v1[i])&&skip++,isNaN(v2[i])&&skip++,isNaN(v3[i])&&skip++,isNaN(no[i])&&skip++;skip>0&&console.log("bad triangle vertice coords/normal: ",skip),err+=skip;const triangle=[];triangle.push(vertexIndex++),triangle.push(vertexIndex++),triangle.push(vertexIndex++);const abc=br.readUInt16();let color=null;if(10===m&&(color=0==(abc&umask)?[(abc&rmask)/31,((abc&gmask)>>>5)/31,((abc&bmask)>>>10)/31,255]:mcolor,colors.push(color)),0===skip){const e1=index$d.subtract(index$d.create(),v2,v1),e2=index$d.subtract(index$d.create(),v3,v1),cr=index$d.cross(index$d.create(),e1,e2);if(index$d.dot(no,cr)>0){const tmp=v3;v3=v1,v1=tmp}}vertices.push(v1),vertices.push(v2),vertices.push(v3),triangles.push(triangle),normals.push(no)}return err&&console.warn(`WARNING: import errors: ${err} (some triangles might be misaligned or missing)`),[elementFormatter({vertices:vertices,triangles:triangles,normals:normals,colors:colors,index:1})]},deserializeAsciiSTL=(stl,filename,version,elementFormatter)=>{let converted=0;const objects=stl.split("endsolid"),elements=[];for(let o=1;o<objects.length;o++){const patt=/\bfacet[\s\S]*?endloop/gim,vertices=[],triangles=[],colors=[];let vertexIndex=0,err=0;const match=stl.match(patt);if(null!=match){for(let i=0;i<match.length;i++){const v=/\bfacet\s+normal\s+(\S+)\s+(\S+)\s+(\S+)\s+outer\s+loop\s+vertex\s+(\S+)\s+(\S+)\s+(\S+)\s+vertex\s+(\S+)\s+(\S+)\s+(\S+)\s+vertex\s+(\S+)\s+(\S+)\s+(\S+)\s*/gim.exec(match[i]);if(null==v)continue;if(13!==v.length){console.log("Failed to parse "+match[i]);break}let skip=0;for(let k=0;k<v.length;k++)"NaN"===v[k]&&(console.log("bad normal or triangle vertice #"+converted+" "+k+": '"+v[k]+"', skipped"),skip++);if(err+=skip,skip)continue;let j=1;const no=[];no.push(parseFloat(v[j++])),no.push(parseFloat(v[j++])),no.push(parseFloat(v[j++]));let v1=[];v1.push(parseFloat(v[j++])),v1.push(parseFloat(v[j++])),v1.push(parseFloat(v[j++]));const v2=[];v2.push(parseFloat(v[j++])),v2.push(parseFloat(v[j++])),v2.push(parseFloat(v[j++]));let v3=[];v3.push(parseFloat(v[j++])),v3.push(parseFloat(v[j++])),v3.push(parseFloat(v[j++]));const triangle=[];if(triangle.push(vertexIndex++),triangle.push(vertexIndex++),triangle.push(vertexIndex++),0===skip){const e1=index$d.subtract(index$d.create(),v2,v1),e2=index$d.subtract(index$d.create(),v3,v1),cr=index$d.cross(index$d.create(),e1,e2);if(index$d.dot(no,cr)>0){const tmp=v3;v3=v1,v1=tmp}}vertices.push(v1),vertices.push(v2),vertices.push(v3),triangles.push(triangle),converted++}err&&console.warn(`WARNING: import errors: ${err} (some triangles might be misaligned or missing)`),elements.push(elementFormatter({vertices:vertices,triangles:triangles,colors:colors,index:o}))}}return elements},toPolyhedron=(points,faces,normals,colors)=>(colors&&faces.length!==colors.length&&(colors=void 0),(options=>{const{points:points,faces:faces,colors:colors,orientation:orientation}=Object.assign({},{points:[],faces:[],colors:void 0,orientation:"outward"},options);if(!Array.isArray(points)||!Array.isArray(faces))throw new Error("points and faces must be arrays");if(points.length<3)throw new Error("three or more points are required");if(faces.length<1)throw new Error("one or more faces are required");if(colors){if(!Array.isArray(colors))throw new Error("colors must be an array");if(colors.length!==faces.length)throw new Error("faces and colors must have the same length")}points.forEach(((vertex,i)=>{if(!isNumberArray(vertex,3))throw new Error(`vertex ${i} must be an array of X, Y, Z values`)})),faces.forEach(((face,i)=>{if(face.length<3)throw new Error(`face ${i} must contain 3 or more indexes`);if(!isNumberArray(face,face.length))throw new Error(`face ${i} must be an array of numbers`)})),"outward"!==orientation&&faces.forEach((face=>face.reverse()));const polygons=faces.map(((face,findex)=>{const polygon=create$7(face.map((pindex=>points[pindex])));return colors&&colors[findex]&&(polygon.color=colors[findex]),polygon}));return create$8(polygons)})({orientation:"inward",points:points,faces:faces,colors:colors})),toScript=(points,faces,normals,colors,index)=>{let src=`\n//\n// solid ${index} : ${points.length} points, ${faces.length} faces, ${colors.length} colors\n//\nconst solid${index} = () => {\n`;src+=" const points = [\n";for(let i=0;i<points.length;i++)src+=` [${points[i]}],\n`;src+=" ]\n",src+=" const faces = [\n";for(let i=0;i<faces.length;i++)src+=` [${faces[i]}],\n`;if(src+=" ]\n",colors&&faces.length===colors.length){src+=" const colors = [\n";for(let i=0;i<colors.length;i++)src+=` [${colors[i]}],\n`;src+=" ]\n"}else src+=" const colors = null\n";return src+=" return polyhedron({points, faces, colors, orientation: 'inside'})\n}\n",src};exports.deserialize=(options,stl)=>{const defaults={filename:"stl",version:"3.0.1-alpha.0",addMetaData:!0,output:"script"};(options=Object.assign({},defaults,options))&&options.statusCallback&&options.statusCallback({progress:0});const{filename:filename,version:version,output:output,addMetaData:addMetaData}=options;stl=isBuffer(stl)?bufferToBinaryString(stl):stl;const isBinary=isDataBinaryRobust(stl);options&&options.statusCallback&&options.statusCallback({progress:33}),options&&options.statusCallback&&options.statusCallback({progress:66});const result=("script"===output?formatAsJscad:formatAsCsg)((isBinary?deserializeBinarySTL:deserializeAsciiSTL)(stl,filename,version,"script"===output?({vertices:vertices,triangles:triangles,normals:normals,colors:colors,index:index})=>toScript(vertices,triangles,null,colors,index):({vertices:vertices,triangles:triangles,normals:normals,colors:colors})=>toPolyhedron(vertices,triangles,null,colors)),addMetaData,version,filename);return options&&options.statusCallback&&options.statusCallback({progress:100}),result},exports.mimeType="model/stl",Object.defineProperty(exports,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).jscadStlDeserializer={});
14
+ const cssColors={black:[0,0,0],silver:[192/255,192/255,192/255],gray:[128/255,128/255,128/255],white:[1,1,1],maroon:[128/255,0,0],red:[1,0,0],purple:[128/255,0,128/255],fuchsia:[1,0,1],green:[0,128/255,0],lime:[0,1,0],olive:[128/255,128/255,0],yellow:[1,1,0],navy:[0,0,128/255],blue:[0,0,1],teal:[0,128/255,128/255],aqua:[0,1,1],aliceblue:[240/255,248/255,1],antiquewhite:[250/255,235/255,215/255],aquamarine:[127/255,1,212/255],azure:[240/255,1,1],beige:[245/255,245/255,220/255],bisque:[1,228/255,196/255],blanchedalmond:[1,235/255,205/255],blueviolet:[138/255,43/255,226/255],brown:[165/255,42/255,42/255],burlywood:[222/255,184/255,135/255],cadetblue:[95/255,158/255,160/255],chartreuse:[127/255,1,0],chocolate:[210/255,105/255,30/255],coral:[1,127/255,80/255],cornflowerblue:[100/255,149/255,237/255],cornsilk:[1,248/255,220/255],crimson:[220/255,20/255,60/255],cyan:[0,1,1],darkblue:[0,0,139/255],darkcyan:[0,139/255,139/255],darkgoldenrod:[184/255,134/255,11/255],darkgray:[169/255,169/255,169/255],darkgreen:[0,100/255,0],darkgrey:[169/255,169/255,169/255],darkkhaki:[189/255,183/255,107/255],darkmagenta:[139/255,0,139/255],darkolivegreen:[85/255,107/255,47/255],darkorange:[1,140/255,0],darkorchid:[.6,50/255,.8],darkred:[139/255,0,0],darksalmon:[233/255,150/255,122/255],darkseagreen:[143/255,188/255,143/255],darkslateblue:[72/255,61/255,139/255],darkslategray:[47/255,79/255,79/255],darkslategrey:[47/255,79/255,79/255],darkturquoise:[0,206/255,209/255],darkviolet:[148/255,0,211/255],deeppink:[1,20/255,147/255],deepskyblue:[0,191/255,1],dimgray:[105/255,105/255,105/255],dimgrey:[105/255,105/255,105/255],dodgerblue:[30/255,144/255,1],firebrick:[178/255,34/255,34/255],floralwhite:[1,250/255,240/255],forestgreen:[34/255,139/255,34/255],gainsboro:[220/255,220/255,220/255],ghostwhite:[248/255,248/255,1],gold:[1,215/255,0],goldenrod:[218/255,165/255,32/255],greenyellow:[173/255,1,47/255],grey:[128/255,128/255,128/255],honeydew:[240/255,1,240/255],hotpink:[1,105/255,180/255],indianred:[205/255,92/255,92/255],indigo:[75/255,0,130/255],ivory:[1,1,240/255],khaki:[240/255,230/255,140/255],lavender:[230/255,230/255,250/255],lavenderblush:[1,240/255,245/255],lawngreen:[124/255,252/255,0],lemonchiffon:[1,250/255,205/255],lightblue:[173/255,216/255,230/255],lightcoral:[240/255,128/255,128/255],lightcyan:[224/255,1,1],lightgoldenrodyellow:[250/255,250/255,210/255],lightgray:[211/255,211/255,211/255],lightgreen:[144/255,238/255,144/255],lightgrey:[211/255,211/255,211/255],lightpink:[1,182/255,193/255],lightsalmon:[1,160/255,122/255],lightseagreen:[32/255,178/255,170/255],lightskyblue:[135/255,206/255,250/255],lightslategray:[119/255,136/255,.6],lightslategrey:[119/255,136/255,.6],lightsteelblue:[176/255,196/255,222/255],lightyellow:[1,1,224/255],limegreen:[50/255,205/255,50/255],linen:[250/255,240/255,230/255],magenta:[1,0,1],mediumaquamarine:[.4,205/255,170/255],mediumblue:[0,0,205/255],mediumorchid:[186/255,85/255,211/255],mediumpurple:[147/255,112/255,219/255],mediumseagreen:[60/255,179/255,113/255],mediumslateblue:[123/255,104/255,238/255],mediumspringgreen:[0,250/255,154/255],mediumturquoise:[72/255,209/255,.8],mediumvioletred:[199/255,21/255,133/255],midnightblue:[25/255,25/255,112/255],mintcream:[245/255,1,250/255],mistyrose:[1,228/255,225/255],moccasin:[1,228/255,181/255],navajowhite:[1,222/255,173/255],oldlace:[253/255,245/255,230/255],olivedrab:[107/255,142/255,35/255],orange:[1,165/255,0],orangered:[1,69/255,0],orchid:[218/255,112/255,214/255],palegoldenrod:[238/255,232/255,170/255],palegreen:[152/255,251/255,152/255],paleturquoise:[175/255,238/255,238/255],palevioletred:[219/255,112/255,147/255],papayawhip:[1,239/255,213/255],peachpuff:[1,218/255,185/255],peru:[205/255,133/255,63/255],pink:[1,192/255,203/255],plum:[221/255,160/255,221/255],powderblue:[176/255,224/255,230/255],rosybrown:[188/255,143/255,143/255],royalblue:[65/255,105/255,225/255],saddlebrown:[139/255,69/255,19/255],salmon:[250/255,128/255,114/255],sandybrown:[244/255,164/255,96/255],seagreen:[46/255,139/255,87/255],seashell:[1,245/255,238/255],sienna:[160/255,82/255,45/255],skyblue:[135/255,206/255,235/255],slateblue:[106/255,90/255,205/255],slategray:[112/255,128/255,144/255],slategrey:[112/255,128/255,144/255],snow:[1,250/255,250/255],springgreen:[0,1,127/255],steelblue:[70/255,130/255,180/255],tan:[210/255,180/255,140/255],thistle:[216/255,191/255,216/255],tomato:[1,99/255,71/255],turquoise:[64/255,224/255,208/255],violet:[238/255,130/255,238/255],wheat:[245/255,222/255,179/255],whitesmoke:[245/255,245/255,245/255],yellowgreen:[154/255,205/255,50/255]},clone$b=geometry=>Object.assign({},geometry),clone$a=matrix=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},copy$5=(out,matrix)=>(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out),EPS=1e-5,NEPS=1e-13,TAU=2*Math.PI,rezero=n=>Math.abs(n)<NEPS?0:n,sin=radians=>rezero(Math.sin(radians)),cos=radians=>rezero(Math.cos(radians)),identity=out=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromRotation=(out,rad,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return identity(out);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(rad),c=cos(rad),t=1-c;return out[0]=x*x*t+c,out[1]=y*x*t+z*s,out[2]=z*x*t-y*s,out[3]=0,out[4]=x*y*t-z*s,out[5]=y*y*t+c,out[6]=z*y*t+x*s,out[7]=0,out[8]=x*z*t+y*s,out[9]=y*z*t-x*s,out[10]=z*z*t+c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromScaling=(out,vector)=>(out[0]=vector[0],out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=vector[1],out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=vector[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromTaitBryanRotation=(out,yaw,pitch,roll)=>{const sy=sin(yaw),cy=cos(yaw),sp=sin(pitch),cp=cos(pitch),sr=sin(roll),cr=cos(roll);return out[0]=cp*cy,out[1]=cp*sy,out[2]=-sp,out[3]=0,out[4]=sr*sp*cy-cr*sy,out[5]=cr*cy+sr*sp*sy,out[6]=sr*cp,out[7]=0,out[8]=sr*sy+cr*sp*cy,out[9]=cr*sp*sy-sr*cy,out[10]=cr*cp,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromTranslation=(out,vector)=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=vector[0],out[13]=vector[1],out[14]=vector[2],out[15]=1,out),fromValues$4=(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33)=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=m00,out[1]=m01,out[2]=m02,out[3]=m03,out[4]=m10,out[5]=m11,out[6]=m12,out[7]=m13,out[8]=m20,out[9]=m21,out[10]=m22,out[11]=m23,out[12]=m30,out[13]=m31,out[14]=m32,out[15]=m33,out},abs$1=(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out[2]=Math.abs(vector[2]),out),add$1=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out),dot$2=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2],clone$9=vector=>{const out=[0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out},copy$4=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out),cross$1=(out,a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];return out[0]=ay*bz-az*by,out[1]=az*bx-ax*bz,out[2]=ax*by-ay*bx,out},distance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return Math.sqrt(x*x+y*y+z*z)},divide$1=(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out[2]=a[2]/b[2],out),equals$7=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2],fromScalar$2=(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out),fromValues$3=(x,y,z)=>{const out=[0,0,0];return out[0]=x,out[1]=y,out[2]=z,out},fromVec2=(out,vector,z=0)=>(out[0]=vector[0],out[1]=vector[1],out[2]=z,out),length$2=vector=>{const x=vector[0],y=vector[1],z=vector[2];return Math.sqrt(x*x+y*y+z*z)},max$1=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out[2]=Math.max(a[2],b[2]),out),min$1=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out[2]=Math.min(a[2],b[2]),out),multiply$2=(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out[2]=a[2]*b[2],out),negate$1=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out[2]=-vector[2],out),normalize$1=(out,vector)=>{const x=vector[0],y=vector[1],z=vector[2];let len=x*x+y*y+z*z;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out[2]=z*len,out},orthogonal=(out,vector)=>{const bV=abs$1([0,0,0],vector),b0=0+(bV[0]<bV[1]&&bV[0]<bV[2]),b1=0+(bV[1]<=bV[0]&&bV[1]<bV[2]),b2=0+(bV[2]<=bV[0]&&bV[2]<=bV[1]);return cross$1(out,vector,[b0,b1,b2])},rotateZ$2=(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],r[0]=p[0]*Math.cos(radians)-p[1]*Math.sin(radians),r[1]=p[0]*Math.sin(radians)+p[1]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=vector[2],out},scale$3=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out[2]=vector[2]*amount,out),snap$2=(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out[2]=Math.round(vector[2]/epsilon)*epsilon+0,out),squaredDistance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return x*x+y*y+z*z},squaredLength$1=vector=>{const x=vector[0],y=vector[1],z=vector[2];return x*x+y*y+z*z},subtract$3=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out),toString$b=vec=>`[${vec[0].toFixed(7)}, ${vec[1].toFixed(7)}, ${vec[2].toFixed(7)}]`,transform$c=(out,vector,matrix)=>{const x=vector[0],y=vector[1],z=vector[2];let w=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15];return w=w||1,out[0]=(matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12])/w,out[1]=(matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13])/w,out[2]=(matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14])/w,out};var index$j=Object.freeze({__proto__:null,abs:abs$1,add:add$1,angle:(a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2],mag=Math.sqrt(ax*ax+ay*ay+az*az)*Math.sqrt(bx*bx+by*by+bz*bz),cosine=mag&&dot$2(a,b)/mag;return Math.acos(Math.min(Math.max(cosine,-1),1))},clone:clone$9,copy:copy$4,create:()=>[0,0,0],cross:cross$1,distance:distance$1,divide:divide$1,dot:dot$2,equals:equals$7,fromScalar:fromScalar$2,fromValues:fromValues$3,fromVec2:fromVec2,length:length$2,lerp:(out,a,b,t)=>(out[0]=a[0]+t*(b[0]-a[0]),out[1]=a[1]+t*(b[1]-a[1]),out[2]=a[2]+t*(b[2]-a[2]),out),max:max$1,min:min$1,multiply:multiply$2,negate:negate$1,normalize:normalize$1,orthogonal:orthogonal,rotateX:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[0],r[1]=p[1]*Math.cos(radians)-p[2]*Math.sin(radians),r[2]=p[1]*Math.sin(radians)+p[2]*Math.cos(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateY:(out,vector,origin,radians)=>{const p=[],r=[];return p[0]=vector[0]-origin[0],p[1]=vector[1]-origin[1],p[2]=vector[2]-origin[2],r[0]=p[2]*Math.sin(radians)+p[0]*Math.cos(radians),r[1]=p[1],r[2]=p[2]*Math.cos(radians)-p[0]*Math.sin(radians),out[0]=r[0]+origin[0],out[1]=r[1]+origin[1],out[2]=r[2]+origin[2],out},rotateZ:rotateZ$2,scale:scale$3,snap:snap$2,squaredDistance:squaredDistance$1,squaredLength:squaredLength$1,subtract:subtract$3,toString:toString$b,transform:transform$c});const fromVectorRotation=(out,source,target)=>{const sourceNormal=normalize$1([0,0,0],source),targetNormal=normalize$1([0,0,0],target),axis=cross$1([0,0,0],targetNormal,sourceNormal),cosA=dot$2(targetNormal,sourceNormal);if(-1===cosA)return fromRotation(out,Math.PI,orthogonal(axis,sourceNormal));const k=1/(1+cosA);return out[0]=axis[0]*axis[0]*k+cosA,out[1]=axis[1]*axis[0]*k-axis[2],out[2]=axis[2]*axis[0]*k+axis[1],out[3]=0,out[4]=axis[0]*axis[1]*k+axis[2],out[5]=axis[1]*axis[1]*k+cosA,out[6]=axis[2]*axis[1]*k-axis[0],out[7]=0,out[8]=axis[0]*axis[2]*k-axis[1],out[9]=axis[1]*axis[2]*k+axis[0],out[10]=axis[2]*axis[2]*k+cosA,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromXRotation=(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=c,out[6]=s,out[7]=0,out[8]=0,out[9]=-s,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation=(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=s,out[2]=0,out[3]=0,out[4]=-s,out[5]=c,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},isIdentity=matrix=>1===matrix[0]&&0===matrix[1]&&0===matrix[2]&&0===matrix[3]&&0===matrix[4]&&1===matrix[5]&&0===matrix[6]&&0===matrix[7]&&0===matrix[8]&&0===matrix[9]&&1===matrix[10]&&0===matrix[11]&&0===matrix[12]&&0===matrix[13]&&0===matrix[14]&&1===matrix[15],isMirroring=matrix=>{const x=matrix[4]*matrix[9]-matrix[8]*matrix[5],y=matrix[8]*matrix[1]-matrix[0]*matrix[9],z=matrix[0]*matrix[5]-matrix[4]*matrix[1];return x*matrix[2]+y*matrix[6]+z*matrix[10]<0},isZero=num=>Math.abs(num)<Number.EPSILON,mirrorByPlane=(out,plane)=>{const[nx,ny,nz,w]=plane;return out[0]=1-2*nx*nx,out[1]=-2*ny*nx,out[2]=-2*nz*nx,out[3]=0,out[4]=-2*nx*ny,out[5]=1-2*ny*ny,out[6]=-2*nz*ny,out[7]=0,out[8]=-2*nx*nz,out[9]=-2*ny*nz,out[10]=1-2*nz*nz,out[11]=0,out[12]=2*nx*w,out[13]=2*ny*w,out[14]=2*nz*w,out[15]=1,out},multiply$1=(out,a,b)=>{const a00=a[0],a01=a[1],a02=a[2],a03=a[3],a10=a[4],a11=a[5],a12=a[6],a13=a[7],a20=a[8],a21=a[9],a22=a[10],a23=a[11],a30=a[12],a31=a[13],a32=a[14],a33=a[15];let b0=b[0],b1=b[1],b2=b[2],b3=b[3];return out[0]=b0*a00+b1*a10+b2*a20+b3*a30,out[1]=b0*a01+b1*a11+b2*a21+b3*a31,out[2]=b0*a02+b1*a12+b2*a22+b3*a32,out[3]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[4],b1=b[5],b2=b[6],b3=b[7],out[4]=b0*a00+b1*a10+b2*a20+b3*a30,out[5]=b0*a01+b1*a11+b2*a21+b3*a31,out[6]=b0*a02+b1*a12+b2*a22+b3*a32,out[7]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[8],b1=b[9],b2=b[10],b3=b[11],out[8]=b0*a00+b1*a10+b2*a20+b3*a30,out[9]=b0*a01+b1*a11+b2*a21+b3*a31,out[10]=b0*a02+b1*a12+b2*a22+b3*a32,out[11]=b0*a03+b1*a13+b2*a23+b3*a33,b0=b[12],b1=b[13],b2=b[14],b3=b[15],out[12]=b0*a00+b1*a10+b2*a20+b3*a30,out[13]=b0*a01+b1*a11+b2*a21+b3*a31,out[14]=b0*a02+b1*a12+b2*a22+b3*a32,out[15]=b0*a03+b1*a13+b2*a23+b3*a33,out},translate$1=(out,matrix,offsets)=>{const x=offsets[0],y=offsets[1],z=offsets[2];let a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23;return matrix===out?(out[12]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12],out[13]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13],out[14]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14],out[15]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]):(a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],out[0]=a00,out[1]=a01,out[2]=a02,out[3]=a03,out[4]=a10,out[5]=a11,out[6]=a12,out[7]=a13,out[8]=a20,out[9]=a21,out[10]=a22,out[11]=a23,out[12]=a00*x+a10*y+a20*z+matrix[12],out[13]=a01*x+a11*y+a21*z+matrix[13],out[14]=a02*x+a12*y+a22*z+matrix[14],out[15]=a03*x+a13*y+a23*z+matrix[15]),out};var index$i=Object.freeze({__proto__:null,add:(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out[3]=a[3]+b[3],out[4]=a[4]+b[4],out[5]=a[5]+b[5],out[6]=a[6]+b[6],out[7]=a[7]+b[7],out[8]=a[8]+b[8],out[9]=a[9]+b[9],out[10]=a[10]+b[10],out[11]=a[11]+b[11],out[12]=a[12]+b[12],out[13]=a[13]+b[13],out[14]=a[14]+b[14],out[15]=a[15]+b[15],out),clone:clone$a,copy:copy$5,create:()=>[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],equals:(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15],fromRotation:fromRotation,fromScaling:fromScaling,fromTaitBryanRotation:fromTaitBryanRotation,fromTranslation:fromTranslation,fromValues:fromValues$4,fromVectorRotation:fromVectorRotation,fromXRotation:fromXRotation,fromYRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=0,out[2]=-s,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=s,out[9]=0,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation:fromZRotation,identity:identity,invert:(out,matrix)=>{const a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],a30=matrix[12],a31=matrix[13],a32=matrix[14],a33=matrix[15],b00=a00*a11-a01*a10,b01=a00*a12-a02*a10,b02=a00*a13-a03*a10,b03=a01*a12-a02*a11,b04=a01*a13-a03*a11,b05=a02*a13-a03*a12,b06=a20*a31-a21*a30,b07=a20*a32-a22*a30,b08=a20*a33-a23*a30,b09=a21*a32-a22*a31,b10=a21*a33-a23*a31,b11=a22*a33-a23*a32;let det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;return det?(det=1/det,out[0]=(a11*b11-a12*b10+a13*b09)*det,out[1]=(a02*b10-a01*b11-a03*b09)*det,out[2]=(a31*b05-a32*b04+a33*b03)*det,out[3]=(a22*b04-a21*b05-a23*b03)*det,out[4]=(a12*b08-a10*b11-a13*b07)*det,out[5]=(a00*b11-a02*b08+a03*b07)*det,out[6]=(a32*b02-a30*b05-a33*b01)*det,out[7]=(a20*b05-a22*b02+a23*b01)*det,out[8]=(a10*b10-a11*b08+a13*b06)*det,out[9]=(a01*b08-a00*b10-a03*b06)*det,out[10]=(a30*b04-a31*b02+a33*b00)*det,out[11]=(a21*b02-a20*b04-a23*b00)*det,out[12]=(a11*b07-a10*b09-a12*b06)*det,out[13]=(a00*b09-a01*b07+a02*b06)*det,out[14]=(a31*b01-a30*b03-a32*b00)*det,out[15]=(a20*b03-a21*b01+a22*b00)*det,out):null},isIdentity:isIdentity,isMirroring:isMirroring,isOnlyTransformScale:matrix=>isZero(matrix[1])&&isZero(matrix[2])&&isZero(matrix[3])&&isZero(matrix[4])&&isZero(matrix[6])&&isZero(matrix[7])&&isZero(matrix[8])&&isZero(matrix[9])&&isZero(matrix[11])&&1===matrix[15],mirrorByPlane:mirrorByPlane,multiply:multiply$1,rotate:(out,matrix,radians,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return copy$5(out,matrix);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(radians),c=cos(radians),t=1-c,a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],b00=x*x*t+c,b01=y*x*t+z*s,b02=z*x*t-y*s,b10=x*y*t-z*s,b11=y*y*t+c,b12=z*y*t+x*s,b20=x*z*t+y*s,b21=y*z*t-x*s,b22=z*z*t+c;return out[0]=a00*b00+a10*b01+a20*b02,out[1]=a01*b00+a11*b01+a21*b02,out[2]=a02*b00+a12*b01+a22*b02,out[3]=a03*b00+a13*b01+a23*b02,out[4]=a00*b10+a10*b11+a20*b12,out[5]=a01*b10+a11*b11+a21*b12,out[6]=a02*b10+a12*b11+a22*b12,out[7]=a03*b10+a13*b11+a23*b12,out[8]=a00*b20+a10*b21+a20*b22,out[9]=a01*b20+a11*b21+a21*b22,out[10]=a02*b20+a12*b21+a22*b22,out[11]=a03*b20+a13*b21+a23*b22,matrix!==out&&(out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out},rotateX:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[4]=a10*c+a20*s,out[5]=a11*c+a21*s,out[6]=a12*c+a22*s,out[7]=a13*c+a23*s,out[8]=a20*c-a10*s,out[9]=a21*c-a11*s,out[10]=a22*c-a12*s,out[11]=a23*c-a13*s,out},rotateY:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c-a20*s,out[1]=a01*c-a21*s,out[2]=a02*c-a22*s,out[3]=a03*c-a23*s,out[8]=a00*s+a20*c,out[9]=a01*s+a21*c,out[10]=a02*s+a22*c,out[11]=a03*s+a23*c,out},rotateZ:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7];return matrix!==out&&(out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c+a10*s,out[1]=a01*c+a11*s,out[2]=a02*c+a12*s,out[3]=a03*c+a13*s,out[4]=a10*c-a00*s,out[5]=a11*c-a01*s,out[6]=a12*c-a02*s,out[7]=a13*c-a03*s,out},scale:(out,matrix,dimensions)=>{const x=dimensions[0],y=dimensions[1],z=dimensions[2];return out[0]=matrix[0]*x,out[1]=matrix[1]*x,out[2]=matrix[2]*x,out[3]=matrix[3]*x,out[4]=matrix[4]*y,out[5]=matrix[5]*y,out[6]=matrix[6]*y,out[7]=matrix[7]*y,out[8]=matrix[8]*z,out[9]=matrix[9]*z,out[10]=matrix[10]*z,out[11]=matrix[11]*z,out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},subtract:(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out[3]=a[3]-b[3],out[4]=a[4]-b[4],out[5]=a[5]-b[5],out[6]=a[6]-b[6],out[7]=a[7]-b[7],out[8]=a[8]-b[8],out[9]=a[9]-b[9],out[10]=a[10]-b[10],out[11]=a[11]-b[11],out[12]=a[12]-b[12],out[13]=a[13]-b[13],out[14]=a[14]-b[14],out[15]=a[15]-b[15],out),toString:mat=>mat.map((n=>n.toFixed(7))).toString(),translate:translate$1});const create$a=(outlines=[])=>({outlines:outlines,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),add=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out),angleRadians=vector=>Math.atan2(vector[1],vector[0]),angleDegrees=vector=>57.29577951308232*angleRadians(vector),clone$8=vector=>{const out=[0,0];return out[0]=vector[0],out[1]=vector[1],out},cross=(out,a,b)=>(out[0]=0,out[1]=0,out[2]=a[0]*b[1]-a[1]*b[0],out),distance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)},dot$1=(a,b)=>a[0]*b[0]+a[1]*b[1],equals$6=(a,b)=>a[0]===b[0]&&a[1]===b[1],fromAngleRadians=(out,radians)=>(out[0]=cos(radians),out[1]=sin(radians),out),fromValues$2=(x,y)=>{const out=[0,0];return out[0]=x,out[1]=y,out},max=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out),min=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out),negate=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out),rotate$1=(out,vector,origin,radians)=>{const x=vector[0]-origin[0],y=vector[1]-origin[1],c=Math.cos(radians),s=Math.sin(radians);return out[0]=x*c-y*s+origin[0],out[1]=x*s+y*c+origin[1],out},normal=(out,vector)=>rotate$1(out,vector,[0,0],TAU/4),normalize=(out,vector)=>{const x=vector[0],y=vector[1];let len=x*x+y*y;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out},scale$1=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out),snap$1=(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out),squaredDistance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y},subtract$1=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out),toString$9=vector=>`[${vector[0].toFixed(7)}, ${vector[1].toFixed(7)}]`,transform$b=(out,vector,matrix)=>{const x=vector[0],y=vector[1];return out[0]=matrix[0]*x+matrix[4]*y+matrix[12],out[1]=matrix[1]*x+matrix[5]*y+matrix[13],out};var index$h=Object.freeze({__proto__:null,abs:(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out),add:add,angle:angleRadians,angleDegrees:angleDegrees,angleRadians:angleRadians,clone:clone$8,copy:(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out),create:()=>[0,0],cross:cross,distance:distance,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out),dot:dot$1,equals:equals$6,fromAngleDegrees:(out,degrees)=>fromAngleRadians(out,.017453292519943295*degrees),fromAngleRadians:fromAngleRadians,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out),fromValues:fromValues$2,length:vector=>Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]),lerp:(out,a,b,t)=>{const ax=a[0],ay=a[1];return out[0]=ax+t*(b[0]-ax),out[1]=ay+t*(b[1]-ay),out},max:max,min:min,multiply:(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out),negate:negate,normal:normal,normalize:normalize,rotate:rotate$1,scale:scale$1,snap:snap$1,squaredDistance:squaredDistance,squaredLength:vector=>{const x=vector[0],y=vector[1];return x*x+y*y},subtract:subtract$1,toString:toString$9,transform:transform$b});const fromSides=sides=>{const pointMap=(sides=>{const pointMap=new Map,edges=(sides=>{const unique=new Map,getUniquePoint=point=>{const key=point.toString();return unique.has(key)?unique.get(key):(unique.set(key,point),point)};return sides.map((side=>side.map(getUniquePoint)))})(sides);return edges.forEach((edge=>{pointMap.has(edge[0])?pointMap.get(edge[0]).push(edge):pointMap.set(edge[0],[edge])})),pointMap})(sides),outlines=[];for(;;){let startSide;for(const[point,edges]of pointMap){if(startSide=edges.shift(),startSide)break;pointMap.delete(point)}if(void 0===startSide)break;const connectedPoints=[],startPoint=startSide[0];for(;;){connectedPoints.push(startSide[0]);const nextPoint=startSide[1];if(nextPoint===startPoint)break;const nextPossibleSides=pointMap.get(nextPoint);if(!nextPossibleSides)throw new Error(`geometry is not closed at point ${nextPoint}`);const nextSide=popNextSide(startSide,nextPossibleSides);0===nextPossibleSides.length&&pointMap.delete(nextPoint),startSide=nextSide}connectedPoints.length>0&&connectedPoints.push(connectedPoints.shift()),outlines.push(connectedPoints)}return pointMap.clear(),create$a(outlines)},popNextSide=(startSide,nextSides)=>{if(1===nextSides.length)return nextSides.pop();const v0=[0,0],startAngle=angleDegrees(subtract$1(v0,startSide[1],startSide[0]));let bestAngle,bestIndex;nextSides.forEach(((nextSide,index)=>{let angle=angleDegrees(subtract$1(v0,nextSide[1],nextSide[0]))-startAngle;angle<-180&&(angle+=360),angle>=180&&(angle-=360),(void 0===bestIndex||angle>bestAngle)&&(bestIndex=index,bestAngle=angle)}));const nextSide=nextSides[bestIndex];return nextSides.splice(bestIndex,1),nextSide},isA$5=object=>!!(object&&"object"==typeof object&&"outlines"in object&&"transforms"in object&&Array.isArray(object.outlines)&&"length"in object.transforms),toOutlines=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.outlines=geometry.outlines.map((outline=>outline.map((point=>transform$b([0,0],point,geometry.transforms))))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).outlines,reverse$5=geometry=>{const outlines=toOutlines(geometry).map((outline=>outline.slice().reverse())),reversed=create$a(outlines);return geometry.color&&(reversed.color=geometry.color),reversed},toPoints$3=geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},toSides=geometry=>{const sides=[];return toOutlines(geometry).forEach((outline=>{outline.forEach(((point,i)=>{const j=(i+1)%outline.length;sides.push([point,outline[j]])}))})),sides},transform$a=(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms),transformed=Object.assign({},geometry,{transforms:transforms});return matrix[0]*matrix[5]-matrix[4]*matrix[1]<0?reverse$5(transformed):transformed},intersect$1=(p1,p2,p3,p4,endpointTouch=!0)=>{if(p1[0]===p2[0]&&p1[1]===p2[1]||p3[0]===p4[0]&&p3[1]===p4[1])return;const denominator=(p4[1]-p3[1])*(p2[0]-p1[0])-(p4[0]-p3[0])*(p2[1]-p1[1]);if(Math.abs(denominator)<Number.MIN_VALUE)return;const ua=((p4[0]-p3[0])*(p1[1]-p3[1])-(p4[1]-p3[1])*(p1[0]-p3[0]))/denominator,ub=((p2[0]-p1[0])*(p1[1]-p3[1])-(p2[1]-p1[1])*(p1[0]-p3[0]))/denominator;return ua<0||ua>1||ub<0||ub>1||!(endpointTouch||0!==ua&&1!==ua&&0!==ub&&1!==ub)?void 0:[p1[0]+ua*(p2[0]-p1[0]),p1[1]+ua*(p2[1]-p1[1])]};var geom2=Object.freeze({__proto__:null,clone:clone$b,create:create$a,fromSides:fromSides,fromCompactBinary:data=>{if(0!==data[0])throw new Error("invalid compact binary data");const created=create$a();created.transforms=clone$a(data.slice(1,17));for(let i=21;i<data.length;){const length=data[i++];if(length<0||i+2*length>data.length)throw new Error("invalid compact binary data");const outline=[];for(let j=0;j<length;j++){const x=data[i+2*j],y=data[i+2*j+1];outline.push(fromValues$2(x,y))}created.outlines.push(outline),i+=2*length}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},isA:isA$5,reverse:reverse$5,toOutlines:toOutlines,toPoints:toPoints$3,toSides:toSides,toString:geometry=>{const outlines=toOutlines(geometry);let result="geom2 ("+outlines.length+" outlines):\n[\n";return outlines.forEach((outline=>{result+=" ["+outline.map(toString$9).join()+"]\n"})),result+="]\n",result},toCompactBinary:geometry=>{const transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);let size=21;geometry.outlines.forEach((outline=>{size+=2*outline.length+1}));const compacted=new Float32Array(size);compacted[0]=0,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3];let index=21;return geometry.outlines.forEach((outline=>{compacted[index++]=outline.length,outline.forEach((point=>{compacted[index++]=point[0],compacted[index++]=point[1]}))})),compacted},transform:transform$a,validate:object=>{if(!isA$5(object))throw new Error("invalid geom2 structure");if(object.outlines.forEach(((outline,i)=>{if(outline.length<3)throw new Error(`geom2 outline ${i} must contain at least 3 points`);for(let i=0;i<outline.length;i++){const j=(i+1)%outline.length;if(equals$6(outline[i],outline[j]))throw new Error(`geom2 outline ${i} has duplicate point ${outline[i]}`)}})),toOutlines(object).forEach(((outline,i)=>{for(let a1=0;a1<outline.length;a1++){const a2=(a1+1)%outline.length;for(let b1=0;b1<outline.length;b1++){const b2=(b1+1)%outline.length;if(a1!==b1){const int=intersect$1(outline[a1],outline[a2],outline[b1],outline[b2],!1);if(int)throw new Error(`geom2 outline ${i} self intersection at ${int}`)}}}})),!object.transforms.every(Number.isFinite))throw new Error(`geom2 invalid transforms ${object.transforms}`)}});const clone$7=geometry=>Object.assign({},geometry),create$8=polygons=>(void 0===polygons&&(polygons=[]),{polygons:polygons,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),create$7=vertices=>((void 0===vertices||vertices.length<3)&&(vertices=[]),{vertices:vertices}),clone$6=(...params)=>{let out,poly3;return 1===params.length?(out=create$7(),poly3=params[0]):(out=params[0],poly3=params[1]),out.vertices=poly3.vertices.map((vec=>clone$9(vec))),out},fromVerticesAndPlane=(vertices,plane)=>{const poly=create$7(vertices);return poly.plane=plane,poly},create$6=()=>[0,0,0,0],clone$5=vector=>{const out=[0,0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out},copy$2=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out),equals$5=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3],flip=(out,plane)=>(out[0]=-plane[0],out[1]=-plane[1],out[2]=-plane[2],out[3]=-plane[3],out),fromNormalAndPoint=(out,normal,point)=>{const u=normalize$1([0,0,0],normal),w=dot$2(point,u);return out[0]=u[0],out[1]=u[1],out[2]=u[2],out[3]=w,out},fromValues$1=(x,y,z,w)=>{const out=[0,0,0,0];return out[0]=x,out[1]=y,out[2]=z,out[3]=w,out},fromPoints$4=(out,...vertices)=>{const len=vertices.length,ba=[0,0,0],ca=[0,0,0],vertexNormal=index=>{const a=vertices[index],b=vertices[(index+1)%len],c=vertices[(index+2)%len];return subtract$3(ba,b,a),subtract$3(ca,c,a),cross$1(ba,ba,ca),normalize$1(ba,ba),ba};return out[0]=0,out[1]=0,out[2]=0,3===len?copy$4(out,vertexNormal(0)):(vertices.forEach(((v,i)=>{add$1(out,out,vertexNormal(i))})),normalize$1(out,out)),out[3]=dot$2(out,vertices[0]),out},projectionOfPoint=(plane,point)=>{const a=point[0]*plane[0]+point[1]*plane[1]+point[2]*plane[2]-plane[3],x=point[0]-a*plane[0],y=point[1]-a*plane[1],z=point[2]-a*plane[2];return fromValues$3(x,y,z)},signedDistanceToPoint=(plane,point)=>dot$2(plane,point)-plane[3],toString$7=vec=>`(${vec[0].toFixed(9)}, ${vec[1].toFixed(9)}, ${vec[2].toFixed(9)}, ${vec[3].toFixed(9)})`;var index$g=Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,equals:equals$5,flip:flip,fromNormalAndPoint:fromNormalAndPoint,fromValues:fromValues$1,fromPoints:fromPoints$4,fromPointsRandom:(out,a,b,c)=>{let ba=subtract$3([0,0,0],b,a),ca=subtract$3([0,0,0],c,a);length$2(ba)<EPS&&(ba=orthogonal(ba,ca)),length$2(ca)<EPS&&(ca=orthogonal(ca,ba));let normal=cross$1([0,0,0],ba,ca);length$2(normal)<EPS&&(ca=orthogonal(ca,ba),normal=cross$1(normal,ba,ca)),normal=normalize$1(normal,normal);const w=dot$2(normal,a);return out[0]=normal[0],out[1]=normal[1],out[2]=normal[2],out[3]=w,out},projectionOfPoint:projectionOfPoint,signedDistanceToPoint:signedDistanceToPoint,toString:toString$7,transform:(out,plane,matrix)=>{const isMirror=isMirroring(matrix),r=orthogonal([0,0,0],plane),u=cross$1(r,plane,r),v=cross$1([0,0,0],plane,u);let point1=fromScalar$2([0,0,0],plane[3]);multiply$2(point1,point1,plane);let point2=add$1([0,0,0],point1,u),point3=add$1([0,0,0],point1,v);return point1=transform$c(point1,point1,matrix),point2=transform$c(point2,point2,matrix),point3=transform$c(point3,point3,matrix),fromPoints$4(out,point1,point2,point3),isMirror&&flip(out,out),out}});const invert$1=polygon=>{const vertices=polygon.vertices.slice().reverse(),inverted=create$7(vertices);return polygon.plane&&(inverted.plane=flip([0,0,0,0],polygon.plane)),inverted},isA$4=object=>!!(object&&"object"==typeof object&&"vertices"in object&&Array.isArray(object.vertices)),isConvex$1=polygon=>areVerticesConvex(polygon.vertices),areVerticesConvex=vertices=>{const numVertices=vertices.length;if(numVertices>2){const normal=fromPoints$4([0,0,0,0],...vertices);let prevPrevPos=vertices[numVertices-2],prevPos=vertices[numVertices-1];for(let i=0;i<numVertices;i++){const pos=vertices[i];if(!isConvexVertex(prevPrevPos,prevPos,pos,normal))return!1;prevPrevPos=prevPos,prevPos=pos}}return!0},isConvexVertex=(prevVertex,vertex,nextVertex,normal)=>{const crossProduct=cross$1([0,0,0],subtract$3([0,0,0],vertex,prevVertex),subtract$3([0,0,0],nextVertex,vertex));return dot$2(crossProduct,normal)>=0},plane=polygon=>(polygon.plane||(polygon.plane=fromPoints$4([0,0,0,0],...polygon.vertices)),polygon.plane),measureArea$2=polygon=>{const n=polygon.vertices.length;if(n<3)return 0;const vertices=polygon.vertices,normal=plane(polygon),ax=Math.abs(normal[0]),ay=Math.abs(normal[1]),az=Math.abs(normal[2]);if(ax+ay+az===0)return 0;let coord=3;ax>ay&&ax>az?coord=1:ay>az&&(coord=2);let area=0,h=0,i=1,j=2;switch(coord){case 1:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][1]*(vertices[j][2]-vertices[h][2]);area+=vertices[0][1]*(vertices[1][2]-vertices[n-1][2]),area/=2*normal[0];break;case 2:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][2]*(vertices[j][0]-vertices[h][0]);area+=vertices[0][2]*(vertices[1][0]-vertices[n-1][0]),area/=2*normal[1];break;default:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][0]*(vertices[j][1]-vertices[h][1]);area+=vertices[0][0]*(vertices[1][1]-vertices[n-1][1]),area/=2*normal[2]}return area};var index$f=Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,dot:(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],equals:equals$5,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out[3]=scalar,out),fromValues:fromValues$1,toString:toString$7,transform:(out,vector,matrix)=>{const[x,y,z,w]=vector;return out[0]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12]*w,out[1]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13]*w,out[2]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14]*w,out[3]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]*w,out}});const cache$4=new WeakMap,measureBoundingSphere$1=(out,polygon)=>{const vertices=polygon.vertices;if(0===vertices.length)return out[0]=0,out[1]=0,out[2]=0,out[3]=0,out;let minx=vertices[0],miny=minx,minz=minx,maxx=minx,maxy=minx,maxz=minx;for(let i=0;i<vertices.length;i++){const v=vertices[i];minx[0]>v[0]&&(minx=v),miny[1]>v[1]&&(miny=v),minz[2]>v[2]&&(minz=v),maxx[0]<v[0]&&(maxx=v),maxy[1]<v[1]&&(maxy=v),maxz[2]<v[2]&&(maxz=v)}out[0]=.5*(minx[0]+maxx[0]),out[1]=.5*(miny[1]+maxy[1]),out[2]=.5*(minz[2]+maxz[2]);const x=out[0]-maxx[0],y=out[1]-maxy[1],z=out[2]-maxz[2];return out[3]=Math.sqrt(x*x+y*y+z*z),out},measureBoundingSphereAndCache=polygon=>{const boundingSphere=cache$4.get(polygon);if(boundingSphere)return boundingSphere;const out=[0,0,0,0];return measureBoundingSphere$1(out,polygon),cache$4.set(polygon,out),out},measureSignedVolume=polygon=>{let signedVolume=0;const vertices=polygon.vertices,cross=[0,0,0];for(let i=0;i<vertices.length-2;i++)cross$1(cross,vertices[i+1],vertices[i+2]),signedVolume+=dot$2(vertices[0],cross);return signedVolume/=6,signedVolume},toVertices$1=polygon=>polygon.vertices,toString$6=polygon=>`poly3: [${polygon.vertices.map(toString$b).join(", ")}]`,transform$7=(matrix,polygon)=>{const vertices=polygon.vertices.map((vertex=>transform$c([0,0,0],vertex,matrix)));return isMirroring(matrix)&&vertices.reverse(),create$7(vertices)},validate$4=object=>{if(!isA$4(object))throw new Error("invalid poly3 structure");if(object.vertices.length<3)throw new Error(`poly3 not enough vertices ${object.vertices.length}`);if(measureArea$2(object)<=0)throw new Error("poly3 area must be greater than zero");for(let i=0;i<object.vertices.length;i++)if(equals$7(object.vertices[i],object.vertices[(i+1)%object.vertices.length]))throw new Error(`poly3 has duplicate vertex ${object.vertices[i]}`);if(!isConvex$1(object))throw new Error("poly3 must be convex");if(object.vertices.forEach((vertex=>{if(!vertex.every(Number.isFinite))throw new Error(`poly3 invalid vertex ${vertex}`)})),object.vertices.length>3){const normal=plane(object);object.vertices.forEach((vertex=>{const dist=Math.abs(signedDistanceToPoint(normal,vertex));if(dist>NEPS)throw new Error(`poly3 must be coplanar: vertex ${vertex} distance ${dist}`)}))}};var poly3=Object.freeze({__proto__:null,clone:clone$6,create:create$7,fromVerticesAndPlane:fromVerticesAndPlane,invert:invert$1,isA:isA$4,isConvex:isConvex$1,measureArea:measureArea$2,measureBoundingBox:polygon=>{const vertices=polygon.vertices,numVertices=vertices.length,min=0===numVertices?[0,0,0]:clone$9(vertices[0]),max=clone$9(min);for(let i=1;i<numVertices;i++)min$1(min,min,vertices[i]),max$1(max,max,vertices[i]);return[min,max]},measureBoundingSphere:measureBoundingSphere$1,measureBoundingSphereAndCache:measureBoundingSphereAndCache,measureSignedVolume:measureSignedVolume,plane:plane,toVertices:toVertices$1,toString:toString$6,transform:transform$7,validate:validate$4});class VertexList{constructor(){this.head=null,this.tail=null}clear(){this.head=this.tail=null}insertBefore(target,node){node.prev=target.prev,node.next=target,node.prev?node.prev.next=node:this.head=node,target.prev=node}insertAfter(target,node){node.prev=target,node.next=target.next,node.next?node.next.prev=node:this.tail=node,target.next=node}add(node){this.head?this.tail.next=node:this.head=node,node.prev=this.tail,node.next=null,this.tail=node}addAll(node){for(this.head?this.tail.next=node:this.head=node,node.prev=this.tail;node.next;)node=node.next;this.tail=node}remove(node){node.prev?node.prev.next=node.next:this.head=node.next,node.next?node.next.prev=node.prev:this.tail=node.prev}removeChain(a,b){a.prev?a.prev.next=b.next:this.head=b.next,b.next?b.next.prev=a.prev:this.tail=a.prev}first(){return this.head}isEmpty(){return!this.head}}class Vertex{constructor(point,index){this.point=point,this.index=index,this.next=null,this.prev=null,this.face=null}}class HalfEdge{constructor(vertex,face){this.vertex=vertex,this.face=face,this.next=null,this.prev=null,this.opposite=null}head(){return this.vertex}tail(){return this.prev?this.prev.vertex:null}length(){return this.tail()?distance$1(this.tail().point,this.head().point):-1}lengthSquared(){return this.tail()?squaredDistance$1(this.tail().point,this.head().point):-1}setOpposite(edge){this.opposite=edge,edge.opposite=this}}class Face{constructor(){this.normal=[],this.centroid=[],this.offset=0,this.outside=null,this.mark=0,this.edge=null,this.nVertices=0}getEdge(i){if("number"!=typeof i)throw Error("requires a number");let it=this.edge;for(;i>0;)it=it.next,i-=1;for(;i<0;)it=it.prev,i+=1;return it}computeNormal(){const e0=this.edge,e1=e0.next;let e2=e1.next;const v2=subtract$3([],e1.head().point,e0.head().point),t=[],v1=[];for(this.nVertices=2,this.normal=[0,0,0];e2!==e0;)copy$4(v1,v2),subtract$3(v2,e2.head().point,e0.head().point),add$1(this.normal,this.normal,cross$1(t,v1,v2)),e2=e2.next,this.nVertices+=1;this.area=length$2(this.normal),this.normal=scale$3(this.normal,this.normal,1/this.area)}computeNormalMinArea(minArea){if(this.computeNormal(),this.area<minArea){let maxEdge,maxSquaredLength=0,edge=this.edge;do{const lengthSquared=edge.lengthSquared();lengthSquared>maxSquaredLength&&(maxEdge=edge,maxSquaredLength=lengthSquared),edge=edge.next}while(edge!==this.edge);const p1=maxEdge.tail().point,p2=maxEdge.head().point,maxVector=subtract$3([],p2,p1),maxLength=Math.sqrt(maxSquaredLength);scale$3(maxVector,maxVector,1/maxLength);const maxProjection=dot$2(this.normal,maxVector);scale$3(maxVector,maxVector,-maxProjection),add$1(this.normal,this.normal,maxVector),normalize$1(this.normal,this.normal)}}computeCentroid(){this.centroid=[0,0,0];let edge=this.edge;do{add$1(this.centroid,this.centroid,edge.head().point),edge=edge.next}while(edge!==this.edge);scale$3(this.centroid,this.centroid,1/this.nVertices)}computeNormalAndCentroid(minArea){void 0!==minArea?this.computeNormalMinArea(minArea):this.computeNormal(),this.computeCentroid(),this.offset=dot$2(this.normal,this.centroid)}distanceToPlane(point){return dot$2(this.normal,point)-this.offset}connectHalfEdges(prev,next){let discardedFace;if(prev.opposite.face===next.opposite.face){const oppositeFace=next.opposite.face;let oppositeEdge;prev===this.edge&&(this.edge=next),3===oppositeFace.nVertices?(oppositeEdge=next.opposite.prev.opposite,oppositeFace.mark=2,discardedFace=oppositeFace):(oppositeEdge=next.opposite.next,oppositeFace.edge===oppositeEdge.prev&&(oppositeFace.edge=oppositeEdge),oppositeEdge.prev=oppositeEdge.prev.prev,oppositeEdge.prev.next=oppositeEdge),next.prev=prev.prev,next.prev.next=next,next.setOpposite(oppositeEdge),oppositeFace.computeNormalAndCentroid()}else prev.next=next,next.prev=prev;return discardedFace}mergeAdjacentFaces(adjacentEdge,discardedFaces){const oppositeEdge=adjacentEdge.opposite,oppositeFace=oppositeEdge.face;discardedFaces.push(oppositeFace),oppositeFace.mark=2;let edge,discardedFace,adjacentEdgePrev=adjacentEdge.prev,adjacentEdgeNext=adjacentEdge.next,oppositeEdgePrev=oppositeEdge.prev,oppositeEdgeNext=oppositeEdge.next;for(;adjacentEdgePrev.opposite.face===oppositeFace;)adjacentEdgePrev=adjacentEdgePrev.prev,oppositeEdgeNext=oppositeEdgeNext.next;for(;adjacentEdgeNext.opposite.face===oppositeFace;)adjacentEdgeNext=adjacentEdgeNext.next,oppositeEdgePrev=oppositeEdgePrev.prev;for(edge=oppositeEdgeNext;edge!==oppositeEdgePrev.next;edge=edge.next)edge.face=this;return this.edge=adjacentEdgeNext,discardedFace=this.connectHalfEdges(oppositeEdgePrev,adjacentEdgeNext),discardedFace&&discardedFaces.push(discardedFace),discardedFace=this.connectHalfEdges(adjacentEdgePrev,oppositeEdgeNext),discardedFace&&discardedFaces.push(discardedFace),this.computeNormalAndCentroid(),discardedFaces}collectIndices(){const indices=[];let edge=this.edge;do{indices.push(edge.head().index),edge=edge.next}while(edge!==this.edge);return indices}static createTriangle(v0,v1,v2,minArea=0){const face=new Face,e0=new HalfEdge(v0,face),e1=new HalfEdge(v1,face),e2=new HalfEdge(v2,face);return e0.next=e2.prev=e1,e1.next=e0.prev=e2,e2.next=e1.prev=e0,face.edge=e0,face.computeNormalAndCentroid(minArea),face}}class QuickHull{constructor(points){if(!Array.isArray(points))throw TypeError("input is not a valid array");if(points.length<4)throw Error("cannot build a simplex out of <4 points");this.tolerance=-1,this.nFaces=0,this.nPoints=points.length,this.faces=[],this.newFaces=[],this.claimed=new VertexList,this.unclaimed=new VertexList,this.vertices=[];for(let i=0;i<points.length;i+=1)this.vertices.push(new Vertex(points[i],i));this.discardedFaces=[],this.vertexPointIndices=[]}addVertexToFace(vertex,face){vertex.face=face,face.outside?this.claimed.insertBefore(face.outside,vertex):this.claimed.add(vertex),face.outside=vertex}removeVertexFromFace(vertex,face){vertex===face.outside&&(vertex.next&&vertex.next.face===face?face.outside=vertex.next:face.outside=null),this.claimed.remove(vertex)}removeAllVerticesFromFace(face){if(face.outside){let end=face.outside;for(;end.next&&end.next.face===face;)end=end.next;return this.claimed.removeChain(face.outside,end),end.next=null,face.outside}}deleteFaceVertices(face,absorbingFace){const faceVertices=this.removeAllVerticesFromFace(face);if(faceVertices)if(absorbingFace){let nextVertex;for(let vertex=faceVertices;vertex;vertex=nextVertex)nextVertex=vertex.next,absorbingFace.distanceToPlane(vertex.point)>this.tolerance?this.addVertexToFace(vertex,absorbingFace):this.unclaimed.add(vertex)}else this.unclaimed.addAll(faceVertices)}resolveUnclaimedPoints(newFaces){let vertexNext=this.unclaimed.first();for(let vertex=vertexNext;vertex;vertex=vertexNext){vertexNext=vertex.next;let maxFace,maxDistance=this.tolerance;for(let i=0;i<newFaces.length;i+=1){const face=newFaces[i];if(0===face.mark){const dist=face.distanceToPlane(vertex.point);if(dist>maxDistance&&(maxDistance=dist,maxFace=face),maxDistance>1e3*this.tolerance)break}}maxFace&&this.addVertexToFace(vertex,maxFace)}}computeExtremes(){const min=[],max=[],minVertices=[],maxVertices=[];let i,j;for(i=0;i<3;i+=1)minVertices[i]=maxVertices[i]=this.vertices[0];for(i=0;i<3;i+=1)min[i]=max[i]=this.vertices[0].point[i];for(i=1;i<this.vertices.length;i+=1){const vertex=this.vertices[i],point=vertex.point;for(j=0;j<3;j+=1)point[j]<min[j]&&(min[j]=point[j],minVertices[j]=vertex);for(j=0;j<3;j+=1)point[j]>max[j]&&(max[j]=point[j],maxVertices[j]=vertex)}return this.tolerance=3*Number.EPSILON*(Math.max(Math.abs(min[0]),Math.abs(max[0]))+Math.max(Math.abs(min[1]),Math.abs(max[1]))+Math.max(Math.abs(min[2]),Math.abs(max[2]))),[minVertices,maxVertices]}createInitialSimplex(){const vertices=this.vertices,[min,max]=this.computeExtremes();let v2,v3,i,j,maxDistance=0,indexMax=0;for(i=0;i<3;i+=1){const distance=max[i].point[i]-min[i].point[i];distance>maxDistance&&(maxDistance=distance,indexMax=i)}const v0=min[indexMax],v1=max[indexMax];for(maxDistance=0,i=0;i<this.vertices.length;i+=1){const vertex=this.vertices[i];if(vertex!==v0&&vertex!==v1){const distance=(point=vertex.point,a=v0.point,b=v1.point,Math.sqrt(((p,a,b)=>{const ab=[],ap=[];subtract$3(ab,b,a),subtract$3(ap,p,a);const area=squaredLength$1(cross$1([],ap,ab)),s=squaredLength$1(ab);if(0===s)throw Error("a and b are the same point");return area/s})(point,a,b)));distance>maxDistance&&(maxDistance=distance,v2=vertex)}}var point,a,b;const normal=fromPoints$4([],v0.point,v1.point,v2.point),distPO=dot$2(v0.point,normal);for(maxDistance=-1,i=0;i<this.vertices.length;i+=1){const vertex=this.vertices[i];if(vertex!==v0&&vertex!==v1&&vertex!==v2){const distance=Math.abs(dot$2(normal,vertex.point)-distPO);distance>maxDistance&&(maxDistance=distance,v3=vertex)}}const faces=[];if(dot$2(v3.point,normal)-distPO<0)for(faces.push(Face.createTriangle(v0,v1,v2),Face.createTriangle(v3,v1,v0),Face.createTriangle(v3,v2,v1),Face.createTriangle(v3,v0,v2)),i=0;i<3;i+=1){const j=(i+1)%3;faces[i+1].getEdge(2).setOpposite(faces[0].getEdge(j)),faces[i+1].getEdge(1).setOpposite(faces[j+1].getEdge(0))}else for(faces.push(Face.createTriangle(v0,v2,v1),Face.createTriangle(v3,v0,v1),Face.createTriangle(v3,v1,v2),Face.createTriangle(v3,v2,v0)),i=0;i<3;i+=1){const j=(i+1)%3;faces[i+1].getEdge(2).setOpposite(faces[0].getEdge((3-i)%3)),faces[i+1].getEdge(0).setOpposite(faces[j+1].getEdge(1))}for(i=0;i<4;i+=1)this.faces.push(faces[i]);for(i=0;i<vertices.length;i+=1){const vertex=vertices[i];if(vertex!==v0&&vertex!==v1&&vertex!==v2&&vertex!==v3){let maxFace;for(maxDistance=this.tolerance,j=0;j<4;j+=1){const distance=faces[j].distanceToPlane(vertex.point);distance>maxDistance&&(maxDistance=distance,maxFace=faces[j])}maxFace&&this.addVertexToFace(vertex,maxFace)}}}reindexFaceAndVertices(){const activeFaces=[];for(let i=0;i<this.faces.length;i+=1){const face=this.faces[i];0===face.mark&&activeFaces.push(face)}this.faces=activeFaces}collectFaces(skipTriangulation){const faceIndices=[];for(let i=0;i<this.faces.length;i+=1){if(0!==this.faces[i].mark)throw Error("attempt to include a destroyed face in the hull");const indices=this.faces[i].collectIndices();if(skipTriangulation)faceIndices.push(indices);else for(let j=0;j<indices.length-2;j+=1)faceIndices.push([indices[0],indices[j+1],indices[j+2]])}return faceIndices}nextVertexToAdd(){if(!this.claimed.isEmpty()){let eyeVertex,vertex,maxDistance=0;const eyeFace=this.claimed.first().face;for(vertex=eyeFace.outside;vertex&&vertex.face===eyeFace;vertex=vertex.next){const distance=eyeFace.distanceToPlane(vertex.point);distance>maxDistance&&(maxDistance=distance,eyeVertex=vertex)}return eyeVertex}}computeHorizon(eyePoint,crossEdge,face,horizon){let edge;this.deleteFaceVertices(face),face.mark=2,edge=crossEdge?crossEdge.next:crossEdge=face.getEdge(0);do{const oppositeEdge=edge.opposite,oppositeFace=oppositeEdge.face;0===oppositeFace.mark&&(oppositeFace.distanceToPlane(eyePoint)>this.tolerance?this.computeHorizon(eyePoint,oppositeEdge,oppositeFace,horizon):horizon.push(edge)),edge=edge.next}while(edge!==crossEdge)}addAdjoiningFace(eyeVertex,horizonEdge){const face=Face.createTriangle(eyeVertex,horizonEdge.tail(),horizonEdge.head());return this.faces.push(face),face.getEdge(-1).setOpposite(horizonEdge.opposite),face.getEdge(0)}addNewFaces(eyeVertex,horizon){let firstSideEdge,previousSideEdge;this.newFaces=[];for(let i=0;i<horizon.length;i+=1){const horizonEdge=horizon[i],sideEdge=this.addAdjoiningFace(eyeVertex,horizonEdge);firstSideEdge?sideEdge.next.setOpposite(previousSideEdge):firstSideEdge=sideEdge,this.newFaces.push(sideEdge.face),previousSideEdge=sideEdge}firstSideEdge.next.setOpposite(previousSideEdge)}oppositeFaceDistance(edge){return edge.face.distanceToPlane(edge.opposite.face.centroid)}doAdjacentMerge(face,mergeType){let edge=face.edge,convex=!0,it=0;do{if(it>=face.nVertices)throw Error("merge recursion limit exceeded");const oppositeFace=edge.opposite.face;let merge=!1;if(2===mergeType?(this.oppositeFaceDistance(edge)>-this.tolerance||this.oppositeFaceDistance(edge.opposite)>-this.tolerance)&&(merge=!0):face.area>oppositeFace.area?this.oppositeFaceDistance(edge)>-this.tolerance?merge=!0:this.oppositeFaceDistance(edge.opposite)>-this.tolerance&&(convex=!1):this.oppositeFaceDistance(edge.opposite)>-this.tolerance?merge=!0:this.oppositeFaceDistance(edge)>-this.tolerance&&(convex=!1),merge){const discardedFaces=face.mergeAdjacentFaces(edge,[]);for(let i=0;i<discardedFaces.length;i+=1)this.deleteFaceVertices(discardedFaces[i],face);return!0}edge=edge.next,it+=1}while(edge!==face.edge);return convex||(face.mark=1),!1}addVertexToHull(eyeVertex){const horizon=[];this.unclaimed.clear(),this.removeVertexFromFace(eyeVertex,eyeVertex.face),this.computeHorizon(eyeVertex.point,null,eyeVertex.face,horizon),this.addNewFaces(eyeVertex,horizon);for(let i=0;i<this.newFaces.length;i+=1){const face=this.newFaces[i];if(0===face.mark)for(;this.doAdjacentMerge(face,1););}for(let i=0;i<this.newFaces.length;i+=1){const face=this.newFaces[i];if(1===face.mark)for(face.mark=0;this.doAdjacentMerge(face,2););}this.resolveUnclaimedPoints(this.newFaces)}build(){let eyeVertex;for(this.createInitialSimplex();eyeVertex=this.nextVertexToAdd();)this.addVertexToHull(eyeVertex);this.reindexFaceAndVertices()}}const runner=(points,options={})=>{const instance=new QuickHull(points);return instance.build(),instance.collectFaces(options.skipTriangulation)},toPolygons$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.polygons=geometry.polygons.map((polygon=>transform$7(geometry.transforms,polygon))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).polygons,isA$3=object=>!!(object&&"object"==typeof object&&"polygons"in object&&"transforms"in object&&Array.isArray(object.polygons)&&"length"in object.transforms),toPoints$2=geometry=>toPolygons$1(geometry).map((polygon=>toVertices$1(polygon))),transform$6=(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})};var geom3=Object.freeze({__proto__:null,clone:clone$7,create:create$8,fromPoints:listOfLists=>{if(!Array.isArray(listOfLists))throw new Error("the given vertices must be an array");return create$8(listOfLists.map(create$7))},fromPointsConvex:uniquePoints=>{if(!Array.isArray(uniquePoints))throw new Error("the given points must be an array");const polygons=runner(uniquePoints,{skipTriangulation:!0}).map((face=>{const vertices=face.map((index=>uniquePoints[index]));return create$7(vertices)}));return create$8(polygons)},fromCompactBinary:data=>{if(1!==data[0])throw new Error("invalid compact binary data");const created=create$8();created.transforms=clone$a(data.slice(1,17));const numberOfVertices=data[21];let ci=22,vi=data.length-3*numberOfVertices;for(;vi<data.length;){const verticesPerPolygon=data[ci];ci++;const vertices=[];for(let i=0;i<verticesPerPolygon;i++)vertices.push(fromValues$3(data[vi],data[vi+1],data[vi+2])),vi+=3;created.polygons.push(create$7(vertices))}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},invert:geometry=>{const newPolygons=toPolygons$1(geometry).map((polygon=>invert$1(polygon)));return create$8(newPolygons)},isA:isA$3,toPoints:toPoints$2,toPolygons:toPolygons$1,toString:geometry=>{const polygons=toPolygons$1(geometry);let result="geom3 ("+polygons.length+" polygons):\n";return polygons.forEach((polygon=>{result+=" "+toString$6(polygon)+"\n"})),result},toCompactBinary:geometry=>{const polygons=geometry.polygons,transforms=geometry.transforms,numberOfPolygons=polygons.length,numberOfVertices=polygons.reduce(((count,polygon)=>count+polygon.vertices.length),0);let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+numberOfPolygons+3*numberOfVertices);compacted[0]=1,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3],compacted[21]=numberOfVertices;let ci=22,vi=ci+numberOfPolygons;return polygons.forEach((polygon=>{const vertices=toVertices$1(polygon);compacted[ci]=vertices.length,ci++;for(let i=0;i<vertices.length;i++){const vertex=vertices[i];compacted[vi+0]=vertex[0],compacted[vi+1]=vertex[1],compacted[vi+2]=vertex[2],vi+=3}})),compacted},transform:transform$6,validate:object=>{if(!isA$3(object))throw new Error("invalid geom3 structure");if(object.polygons.forEach(validate$4),(object=>{const edgeCount=new Map;object.polygons.forEach((({vertices:vertices})=>{vertices.forEach(((v,i)=>{const edge=`${v}/${vertices[(i+1)%vertices.length]}`,count=edgeCount.has(edge)?edgeCount.get(edge):0;edgeCount.set(edge,count+1)}))}));const nonManifold=[];if(edgeCount.forEach(((count,edge)=>{const complementEdge=edge.split("/").reverse().join("/");count!==edgeCount.get(complementEdge)&&nonManifold.push(edge.replace("/"," -> "))})),nonManifold.length>0)throw new Error(`non-manifold edges ${nonManifold.length}\n${nonManifold.join("\n")}`)})(object),!object.transforms.every(Number.isFinite))throw new Error(`geom3 invalid transforms ${object.transforms}`)}});const clone$4=geometry=>Object.assign({},geometry),close=geometry=>{if(geometry.isClosed)return geometry;const cloned=clone$4(geometry);if(cloned.isClosed=!0,cloned.points.length>1){const points=cloned.points,p0=points[0];let pn=points[points.length-1];for(;distance(p0,pn)<EPS*EPS&&(points.pop(),1!==points.length);)pn=points[points.length-1]}return cloned},create$5=points=>(void 0===points&&(points=[]),{points:points,isClosed:!1,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),fromPoints$2=(options,points)=>{let{closed:closed}=Object.assign({},{closed:!1},options),created=create$5();if(created.points=points.map((point=>clone$8(point))),created.points.length>1){const p0=created.points[0],pn=created.points[created.points.length-1];distance(p0,pn)<EPS*EPS&&(closed=!0)}return!0===closed&&(created=close(created)),created},toPoints$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.points=geometry.points.map((point=>transform$b([0,0],point,geometry.transforms))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).points,concat=(...paths)=>{let isClosed=!1,newPoints=[];return paths.forEach(((path,i)=>{const tmp=toPoints$1(path).slice();if(newPoints.length>0&&tmp.length>0&&equals$6(tmp[0],newPoints[newPoints.length-1])&&tmp.shift(),tmp.length>0&&isClosed)throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`);isClosed=path.isClosed,newPoints=newPoints.concat(tmp)})),fromPoints$2({closed:isClosed},newPoints)},appendPoints=(points,geometry)=>concat(geometry,create$5(points)),isA$2=object=>!!(object&&"object"==typeof object&&"points"in object&&"transforms"in object&&"isClosed"in object&&Array.isArray(object.points)&&"length"in object.transforms),transform$5=(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})};var path2=Object.freeze({__proto__:null,appendArc:(options,geometry)=>{let{endpoint:endpoint,radius:radius,xaxisRotation:xaxisRotation,clockwise:clockwise,large:large,segments:segments}=Object.assign({},{radius:[0,0],xaxisRotation:0,clockwise:!1,large:!1,segments:16},options);if(!Array.isArray(endpoint))throw new Error("endpoint must be an array of X and Y values");if(endpoint.length<2)throw new Error("endpoint must contain X and Y values");if(endpoint=clone$8(endpoint),!Array.isArray(radius))throw new Error("radius must be an array of X and Y values");if(radius.length<2)throw new Error("radius must contain X and Y values");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given path cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the arc)");let xRadius=radius[0],yRadius=radius[1];const startpoint=points[points.length-1];xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5,endpoint=fromValues$2(Math.round(1e5*endpoint[0])/1e5,Math.round(1e5*endpoint[1])/1e5);const sweepFlag=!clockwise;let newPoints=[];if(0===xRadius||0===yRadius)newPoints.push(endpoint);else{xRadius=Math.abs(xRadius),yRadius=Math.abs(yRadius);const phi=xaxisRotation,cosPhi=Math.cos(phi),sinPhi=Math.sin(phi),minusHalfDistance=subtract$1([0,0],startpoint,endpoint);scale$1(minusHalfDistance,minusHalfDistance,.5);const x=Math.round(1e5*(cosPhi*minusHalfDistance[0]+sinPhi*minusHalfDistance[1]))/1e5,y=Math.round(1e5*(-sinPhi*minusHalfDistance[0]+cosPhi*minusHalfDistance[1]))/1e5,startTranslated=fromValues$2(x,y),bigLambda=startTranslated[0]*startTranslated[0]/(xRadius*xRadius)+startTranslated[1]*startTranslated[1]/(yRadius*yRadius);if(bigLambda>1){const sqrtBigLambda=Math.sqrt(bigLambda);xRadius*=sqrtBigLambda,yRadius*=sqrtBigLambda,xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5}let multiplier1=Math.sqrt((xRadius*xRadius*yRadius*yRadius-xRadius*xRadius*startTranslated[1]*startTranslated[1]-yRadius*yRadius*startTranslated[0]*startTranslated[0])/(xRadius*xRadius*startTranslated[1]*startTranslated[1]+yRadius*yRadius*startTranslated[0]*startTranslated[0]));sweepFlag===large&&(multiplier1=-multiplier1);const centerTranslated=fromValues$2(xRadius*startTranslated[1]/yRadius,-yRadius*startTranslated[0]/xRadius);scale$1(centerTranslated,centerTranslated,multiplier1);let center=fromValues$2(cosPhi*centerTranslated[0]-sinPhi*centerTranslated[1],sinPhi*centerTranslated[0]+cosPhi*centerTranslated[1]);center=add(center,center,scale$1([0,0],add([0,0],startpoint,endpoint),.5));const vector1=fromValues$2((startTranslated[0]-centerTranslated[0])/xRadius,(startTranslated[1]-centerTranslated[1])/yRadius),vector2=fromValues$2((-startTranslated[0]-centerTranslated[0])/xRadius,(-startTranslated[1]-centerTranslated[1])/yRadius),theta1=angleRadians(vector1);let deltatheta=angleRadians(vector2)-theta1;deltatheta%=TAU,!sweepFlag&&deltatheta>0?deltatheta-=TAU:sweepFlag&&deltatheta<0&&(deltatheta+=TAU);let numSteps=Math.ceil(Math.abs(deltatheta)/TAU*segments)+1;numSteps<1&&(numSteps=1);for(let step=1;step<numSteps;step++){const theta=theta1+step/numSteps*deltatheta,cosTheta=Math.cos(theta),sinTheta=Math.sin(theta),point=fromValues$2(cosPhi*xRadius*cosTheta-sinPhi*yRadius*sinTheta,sinPhi*xRadius*cosTheta+cosPhi*yRadius*sinTheta);add(point,point,center),newPoints.push(point)}numSteps&&newPoints.push(options.endpoint)}return newPoints=points.concat(newPoints),fromPoints$2({},newPoints)},appendBezier:(options,geometry)=>{let{controlPoints:controlPoints,segments:segments}=Object.assign({},{segments:16},options);if(!Array.isArray(controlPoints))throw new Error("controlPoints must be an array of one or more points");if(controlPoints.length<1)throw new Error("controlPoints must be an array of one or more points");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given geometry cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the bezier curve)");if(controlPoints=controlPoints.slice(),null===controlPoints[0]){if(controlPoints.length<2)throw new Error("a null control point must be passed with one more control points");let lastBezierControlPoint=points[points.length-2];if("lastBezierControlPoint"in geometry&&(lastBezierControlPoint=geometry.lastBezierControlPoint),!Array.isArray(lastBezierControlPoint))throw new Error("the given path must contain TWO or more points if given a null control point");const controlPoint=scale$1([0,0],points[points.length-1],2);subtract$1(controlPoint,controlPoint,lastBezierControlPoint),controlPoints[0]=controlPoint}controlPoints.unshift(points[points.length-1]);const bezierOrder=controlPoints.length-1,factorials=[];let fact=1;for(let i=0;i<=bezierOrder;++i)i>0&&(fact*=i),factorials.push(fact);const binomials=[];for(let i=0;i<=bezierOrder;++i){const binomial=factorials[bezierOrder]/(factorials[i]*factorials[bezierOrder-i]);binomials.push(binomial)}const v0=[0,0],v1=[0,0],v3=[0,0,0],getPointForT=t=>{let tk=1,oneMinusTNMinusK=Math.pow(1-t,bezierOrder);const invOneMinusT=1!==t?1/(1-t):1,point=[0,0];for(let k=0;k<=bezierOrder;++k){k===bezierOrder&&(oneMinusTNMinusK=1);const bernsteinCoefficient=binomials[k]*tk*oneMinusTNMinusK,derivativePoint=scale$1(v0,controlPoints[k],bernsteinCoefficient);add(point,point,derivativePoint),tk*=t,oneMinusTNMinusK*=invOneMinusT}return point},newPoints=[],newPointsT=[],numSteps=bezierOrder+1;for(let i=0;i<numSteps;++i){const t=i/(numSteps-1),point=getPointForT(t);newPoints.push(point),newPointsT.push(t)}let subdivideBase=1;const maxAngle=TAU/segments,maxSinAngle=Math.sin(maxAngle);for(;subdivideBase<newPoints.length-1;){const dir1=subtract$1(v0,newPoints[subdivideBase],newPoints[subdivideBase-1]);normalize(dir1,dir1);const dir2=subtract$1(v1,newPoints[subdivideBase+1],newPoints[subdivideBase]);normalize(dir2,dir2);const sinAngle=cross(v3,dir1,dir2);if(Math.abs(sinAngle[2])>maxSinAngle){const t0=newPointsT[subdivideBase-1],t1=newPointsT[subdivideBase+1],newt0=t0+1*(t1-t0)/3,newt1=t0+2*(t1-t0)/3,point0=getPointForT(newt0),point1=getPointForT(newt1);newPoints.splice(subdivideBase,1,point0,point1),newPointsT.splice(subdivideBase,1,newt0,newt1),subdivideBase--,subdivideBase<1&&(subdivideBase=1)}else++subdivideBase}newPoints.shift();const result=appendPoints(newPoints,geometry);return result.lastBezierControlPoint=controlPoints[controlPoints.length-2],result},appendPoints:appendPoints,clone:clone$4,close:close,concat:concat,create:create$5,equals:(a,b)=>{if(a.isClosed!==b.isClosed)return!1;if(a.points.length!==b.points.length)return!1;const aPoints=toPoints$1(a),bPoints=toPoints$1(b),length=aPoints.length;let offset=0;do{let unequal=!1;for(let i=0;i<length;i++)if(!equals$6(aPoints[i],bPoints[(i+offset)%length])){unequal=!0;break}if(!1===unequal)return!0;if(!a.isClosed)return!1}while(++offset<length);return!1},fromPoints:fromPoints$2,fromCompactBinary:data=>{if(2!==data[0])throw new Error("invalid compact binary data");const created=create$5();created.transforms=clone$a(data.slice(1,17)),created.isClosed=!!data[17];for(let i=22;i<data.length;i+=2){const point=fromValues$2(data[i],data[i+1]);created.points.push(point)}return data[18]>=0&&(created.color=[data[18],data[19],data[20],data[21]]),created},isA:isA$2,reverse:geometry=>{const cloned=clone$4(geometry);return cloned.points=geometry.points.slice().reverse(),cloned},toPoints:toPoints$1,toString:geometry=>{const points=toPoints$1(geometry);let result="path ("+points.length+" points, "+geometry.isClosed+"):\n[\n";return points.forEach((point=>{result+=" "+toString$9(point)+",\n"})),result+="]\n",result},toCompactBinary:geometry=>{const points=geometry.points,transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+2*points.length);compacted[0]=2,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=geometry.isClosed?1:0,compacted[18]=color[0],compacted[19]=color[1],compacted[20]=color[2],compacted[21]=color[3];for(let j=0;j<points.length;j++){const ci=2*j+22,point=points[j];compacted[ci]=point[0],compacted[ci+1]=point[1]}return compacted},transform:transform$5,validate:object=>{if(!isA$2(object))throw new Error("invalid path2 structure");if(object.points.length>1)for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`path2 has duplicate point ${object.points[i]}`);if(object.points.forEach((point=>{if(!point.every(Number.isFinite))throw new Error(`path2 invalid point ${point}`)})),!object.transforms.every(Number.isFinite))throw new Error(`path2 invalid transforms ${object.transforms}`)}});const colorize=(color,...objects)=>{if(!Array.isArray(color))throw new Error("color must be an array");if(color.length<3)throw new Error("color must contain R, G and B values");3===color.length&&(color=[color[0],color[1],color[2],1]);const results=objects.map((object=>isA$5(object)?((color,object)=>{const newGeom2=clone$b(object);return newGeom2.color=color,newGeom2})(color,object):isA$3(object)?((color,object)=>{const newGeom3=clone$7(object);return newGeom3.color=color,newGeom3})(color,object):isA$2(object)?((color,object)=>{const newPath2=clone$4(object);return newPath2.color=color,newPath2})(color,object):isA$4(object)?((color,object)=>{const newPoly=clone$6(object);return newPoly.color=color,newPoly})(color,object):Array.isArray(object)?colorize(color,...object):(object.color=color,object)));return 1===results.length?results[0]:results},flatten=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val)),[]),hueToColorComponent=(p,q,t)=>(t<0&&(t+=1),t>1&&(t-=1),t<1/6?p+6*(q-p)*t:t<.5?q:t<2/3?p+(q-p)*(2/3-t)*6:p);Object.freeze({__proto__:null,colorNameToRgb:s=>cssColors[s.toLowerCase()],colorize:colorize,cssColors:cssColors,hexToRgb:notation=>{if((notation=notation.replace("#","")).length<6)throw new Error("the given notation must contain 3 or more hex values");const r=parseInt(notation.substring(0,2),16)/255,g=parseInt(notation.substring(2,4),16)/255,b=parseInt(notation.substring(4,6),16)/255;return notation.length>=8?[r,g,b,parseInt(notation.substring(6,8),16)/255]:[r,g,b]},hslToRgb:(...values)=>{if((values=flatten(values)).length<3)throw new Error("values must contain H, S and L values");const h=values[0],s=values[1],l=values[2];let r=l,g=l,b=l;if(0!==s){const q=l<.5?l*(1+s):l+s-l*s,p=2*l-q;r=hueToColorComponent(p,q,h+1/3),g=hueToColorComponent(p,q,h),b=hueToColorComponent(p,q,h-1/3)}return values.length>3?[r,g,b,values[3]]:[r,g,b]},hsvToRgb:(...values)=>{if((values=flatten(values)).length<3)throw new Error("values must contain H, S and V values");const h=values[0],s=values[1],v=values[2];let r=0,g=0,b=0;const i=Math.floor(6*h),f=6*h-i,p=v*(1-s),q=v*(1-f*s),t=v*(1-(1-f)*s);switch(i%6){case 0:r=v,g=t,b=p;break;case 1:r=q,g=v,b=p;break;case 2:r=p,g=v,b=t;break;case 3:r=p,g=q,b=v;break;case 4:r=t,g=p,b=v;break;case 5:r=v,g=p,b=q}return values.length>3?[r,g,b,values[3]]:[r,g,b]},hueToColorComponent:hueToColorComponent,rgbToHex:(...values)=>{if((values=flatten(values)).length<3)throw new Error("values must contain R, G and B values");const r=255*values[0],g=255*values[1],b=255*values[2];let s=`#${Number(16777216+65536*r+256*g+b).toString(16).substring(1,7)}`;return values.length>3&&(s+=Number(255*values[3]).toString(16)),s},rgbToHsl:(...values)=>{if((values=flatten(values)).length<3)throw new Error("values must contain R, G and B values");const r=values[0],g=values[1],b=values[2],max=Math.max(r,g,b),min=Math.min(r,g,b);let h,s;const l=(max+min)/2;if(max===min)h=s=0;else{const d=max-min;switch(s=l>.5?d/(2-max-min):d/(max+min),max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return values.length>3?[h,s,l,values[3]]:[h,s,l]},rgbToHsv:(...values)=>{if((values=flatten(values)).length<3)throw new Error("values must contain R, G and B values");const r=values[0],g=values[1],b=values[2],max=Math.max(r,g,b),min=Math.min(r,g,b);let h;const v=max,d=max-min,s=0===max?0:d/max;if(max===min)h=0;else{switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4}h/=6}return values.length>3?[h,s,v,values[3]]:[h,s,v]}});const getPermutations=function(c){const permutations=[];for(let i=0;i<=c;i++)permutations.push(factorial(c)/(factorial(i)*factorial(c-i)));return permutations},factorial=function(b){let out=1;for(let i=2;i<=b;i++)out*=i;return out},valueAt=(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier valueAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierFunction(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierFunction(bezier,singleDimensionPoints,t))}return result}},bezierFunction=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<=n;i++)result+=bezier.permutations[i]*Math.pow(1-t,n-i)*Math.pow(t,i)*p[i];return result},bezierTangent=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<n;i++){const q=n*(p[i+1]-p[i]);result+=bezier.tangentPermutations[i]*Math.pow(1-t,n-1-i)*Math.pow(t,i)*q}return result},lengths=(segments,bezier)=>{let sum=0;const lengths=[0];let previous=valueAt(0,bezier);for(let index=1;index<=segments;index++){const current=valueAt(index/segments,bezier);sum+=distanceBetween(current,previous),lengths.push(sum),previous=current}return lengths},distanceBetween=(a,b)=>{if(Number.isFinite(a)&&Number.isFinite(b))return Math.abs(a-b);if(Array.isArray(a)&&Array.isArray(b)){if(a.length!==b.length)throw new Error("The operands must have the same number of dimensions.");let sum=0;for(let i=0;i<a.length;i++)sum+=(b[i]-a[i])*(b[i]-a[i]);return Math.sqrt(sum)}throw new Error("The operands must be of the same type, either number or array.")};var index$d=Object.freeze({__proto__:null,create:points=>{if(!Array.isArray(points))throw new Error("Bezier points must be a valid array/");if(points.length<2)throw new Error("Bezier points must contain at least 2 values.");const pointType=function(points){let firstPointType=null;return points.forEach((point=>{let pType="";if(Number.isFinite(point))pType="float_single";else{if(!Array.isArray(point))throw new Error("Bezier points must all be numbers or arrays of number.");point.forEach((val=>{if(!Number.isFinite(val))throw new Error("Bezier point values must all be numbers.")})),pType="float_"+point.length}if(null==firstPointType)firstPointType=pType;else if(firstPointType!==pType)throw new Error("Bezier points must be either all numbers or all arrays of numbers of the same size.")})),firstPointType}(points);return{points:points,pointType:pointType,dimensions:"float_single"===pointType?0:points[0].length,permutations:getPermutations(points.length-1),tangentPermutations:getPermutations(points.length-2)}},valueAt:valueAt,tangentAt:(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier tangentAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierTangent(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierTangent(bezier,singleDimensionPoints,t))}return result}},lengths:lengths,length:(segments,bezier)=>lengths(segments,bezier)[segments],arcLengthToT:(options,bezier)=>{const{distance:distance,segments:segments}=Object.assign({},{distance:0,segments:100},options),arcLengths=lengths(segments,bezier);let startIndex=0,endIndex=segments;for(;startIndex<=endIndex;){const middleIndex=Math.floor(startIndex+(endIndex-startIndex)/2),diff=arcLengths[middleIndex]-distance;if(diff<0)startIndex=middleIndex+1;else{if(!(diff>0)){endIndex=middleIndex;break}endIndex=middleIndex-1}}const targetIndex=endIndex;if(arcLengths[targetIndex]===distance)return targetIndex/segments;const lengthBefore=arcLengths[targetIndex];return(targetIndex+(distance-lengthBefore)/(arcLengths[targetIndex+1]-lengthBefore))/segments}});Object.freeze({__proto__:null,bezier:index$d});const area$1=points=>{let area=0;for(let i=0;i<points.length;i++){const j=(i+1)%points.length;area+=points[i][0]*points[j][1],area-=points[j][0]*points[i][1]}return area/2},measureArea$1=polygon=>area$1(polygon.points),create$3=points=>((void 0===points||points.length<3)&&(points=[]),{points:points}),reverse$3=polygon=>{const points=polygon.points.slice().reverse();return create$3(points)},arePointsInside=(points,polygon)=>0===points.length||polygon.points.length<3?0:(measureArea$1(polygon)<0&&(polygon=reverse$3(polygon)),points.reduce(((acc,point)=>acc+isPointInside(point,polygon.points)),0)===points.length?1:0),isPointInside=(point,polygon)=>{const numPoints=polygon.length,tx=point[0],ty=point[1];let vtx0=polygon[numPoints-1],vtx1=polygon[0],yFlag0=vtx0[1]>ty,insideFlag=0,i=0;for(let j=numPoints+1;--j;){const yFlag1=vtx1[1]>ty;if(yFlag0!==yFlag1){const xFlag0=vtx0[0]>tx,xFlag1=vtx1[0]>tx;(xFlag0&&xFlag1||vtx1[0]-(vtx1[1]-ty)*(vtx0[0]-vtx1[0])/(vtx0[1]-vtx1[1])>=tx)&&(insideFlag=!insideFlag)}yFlag0=yFlag1,vtx0=vtx1,vtx1=polygon[++i]}return insideFlag},isA$1=object=>!!(object&&"object"==typeof object&&"points"in object&&Array.isArray(object.points)),crossBetweenSegments=(p1,p2,p3)=>{const X1=p2[0]-p1[0],Y1=p2[1]-p1[1],X2=p3[0]-p1[0];return X1*(p3[1]-p1[1])-Y1*X2};var poly2=Object.freeze({__proto__:null,arePointsInside:arePointsInside,clone:polygon=>Object.assign({},polygon),create:create$3,isA:isA$1,isConvex:polygon=>{const numPoints=polygon.points.length;if(numPoints>2){const points=polygon.points;let prev=0,curr=0;for(let i=0;i<numPoints;i++)if(curr=crossBetweenSegments(points[i],points[(i+1)%numPoints],points[(i+2)%numPoints]),0!==curr){if(curr*prev<0)return!1;prev=curr}}return!0},isSimple:polygon=>{const numPoints=polygon.points.length;if(numPoints<3)return!1;if(3===numPoints)return!0;const points=polygon.points,found=new Set;if(points.forEach((v=>found.add(v.toString()))),found.size!==numPoints)return!1;for(let i=0;i<numPoints;i++)for(let j=i+2;j<numPoints;j++){const k=(j+1)%numPoints;if(i!==k){const s0=points[i],s1=points[(i+1)%numPoints],z0=points[j],z1=points[k];if(intersect$1(s0,s1,z0,z1))return!1}}return!0},measureArea:measureArea$1,measureBoundingBox:polygon=>{const points=polygon.points,numPoints=points.length,min$1=0===numPoints?[0,0]:clone$8(points[0]),max$1=clone$8(min$1);for(let i=1;i<numPoints;i++)min(min$1,min$1,points[i]),max(max$1,max$1,points[i]);return[min$1,max$1]},reverse:reverse$3,toPoints:polygon=>polygon.points,toString:polygon=>`poly2: [${polygon.points.map(toString$9).join(", ")}]`,transform:(matrix,polygon)=>{const points=polygon.points.map((point=>transform$b([0,0],point,matrix)));return isMirroring(matrix)&&points.reverse(),create$3(points)},validate:object=>{if(!isA$1(object))throw new Error("invalid poly2 structure");if(object.points.length<3)throw new Error(`poly2 not enough points ${object.points.length}`);if(measureArea$1(object)<=0)throw new Error("poly2 area must be greater than zero");for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`poly2 duplicate point at ${i}: [${object.points[i]}]`);object.points.forEach((point=>{if(2!==point.length)throw new Error(`poly2 invalid point ${point}`);if(!point.every(Number.isFinite))throw new Error(`poly2 invalid point ${point}`)}))}});const calculatePlane=slice=>{if(slice.contours.length<1)throw new Error("slices must have at least one contour to calculate a plane");const middle=[0,0,0];let n=0;slice.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(middle,middle,vertex),n++}))})),scale$3(middle,middle,1/n);let farthestBefore,farthestVertex,farthestAfter,farthestContour=[],distance=0;slice.contours.forEach((contour=>{let prev=contour[contour.length-1];contour.forEach((vertex=>{if(!equals$7(prev,vertex)){const d=squaredDistance$1(middle,vertex);d>distance&&(farthestContour=contour,farthestBefore=prev,farthestVertex=vertex,distance=d)}prev=vertex}))}));let prev=farthestContour[farthestContour.length-1];for(let i=0;i<farthestContour.length;i++){const vertex=farthestContour[i];if(!equals$7(prev,vertex)&&equals$7(prev,farthestVertex)){farthestAfter=vertex;break}prev=vertex}return fromPoints$4([0,0,0,0],farthestBefore,farthestVertex,farthestAfter)},create$2=(contours=[])=>({contours:contours}),equals$3=(a,b)=>{if(a.contours.length!==b.contours.length)return!1;const len=a.contours.length;for(let i=0;i<len;i++){const aVertex=a.contours[i];for(let j=0;j<len;j++){const bVertex=b.contours[j];if(!equals$7(aVertex,bVertex))return!1}}return!0},fromGeom2=geometry=>{const contours=toOutlines(geometry).map((outline=>outline.map((point=>fromVec2([0,0,0],point)))));return create$2(contours)},fromVertices=vertices=>{if(!Array.isArray(vertices))throw new Error("the given vertices must be an array");if(vertices.length<3)throw new Error("the given vertices must contain THREE or more vertices");const cloned=vertices.map((vertex=>3===vertex.length?vertex:fromVec2([0,0,0],vertex)));return create$2([cloned])},isA=object=>!!(object&&"object"==typeof object&&"contours"in object&&Array.isArray(object.contours)),reverse$2=slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},toEdges=slice=>{const edges=[];return slice.contours.forEach((contour=>{contour.forEach(((vertex,i)=>{const next=contour[(i+1)%contour.length];edges.push([vertex,next])}))})),edges};class Node$2{constructor(i,x,y){this.i=i,this.x=x,this.y=y,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}}const insertNode=(i,x,y,last)=>{const p=new Node$2(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p},removeNode=p=>{p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)},pointInTriangle=(ax,ay,bx,by,cx,cy,px,py)=>(cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0,area=(p,q,r)=>(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y),linkedPolygon=(data,start,end,dim,clockwise)=>{let last;if(clockwise===signedArea$1(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);return last&&equals$2(last,last.next)&&(removeNode(last),last=last.next),last},filterPoints=(start,end)=>{if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals$2(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end},cureLocalIntersections=(start,triangles,dim)=>{let p=start;do{const a=p.prev,b=p.next.next;!equals$2(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i/dim),triangles.push(p.i/dim),triangles.push(b.i/dim),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)},locallyInside=(a,b)=>area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0,splitPolygon=(a,b)=>{const a2=new Node$2(a.i,a.x,a.y),b2=new Node$2(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2},isValidDiagonal=(a,b)=>a.next.i!==b.i&&a.prev.i!==b.i&&!((a,b)=>{let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1})(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&((a,b)=>{let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside})(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals$2(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0),intersects=(p1,q1,p2,q2)=>{const o1=Math.sign(area(p1,q1,p2)),o2=Math.sign(area(p1,q1,q2)),o3=Math.sign(area(p2,q2,p1)),o4=Math.sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||!(0!==o1||!onSegment(p1,p2,q1))||!(0!==o2||!onSegment(p1,q2,q1))||!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2))},onSegment=(p,q,r)=>q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y),signedArea$1=(data,start,end,dim)=>{let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum},equals$2=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y,eliminateHole=(hole,outerNode)=>{const bridge=findHoleBridge(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole),filteredBridge=filterPoints(bridge,bridge.next);return filterPoints(bridgeReverse,bridgeReverse.next),outerNode===bridge?filteredBridge:outerNode},findHoleBridge=(hole,outerNode)=>{let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){if(qx=x,x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next}m=p.x<p.next.x?p:p.next}}p=p.next}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m},sectorContainsSector=(m,p)=>area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0,getLeftmost=start=>{let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost},earcutLinked=(ear,triangles,dim,minX,minY,invSize,pass)=>{if(!ear)return;!pass&&invSize&&indexCurve(ear,minX,minY,invSize);let prev,next,stop=ear;for(;ear.prev!==ear.next;)if(prev=ear.prev,next=ear.next,invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i/dim),triangles.push(ear.i/dim),triangles.push(next.i/dim),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?(ear=cureLocalIntersections(filterPoints(ear),triangles,dim),earcutLinked(ear,triangles,dim,minX,minY,invSize,2)):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}},isEar=ear=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;let p=ear.next.next;for(;p!==ear.prev;){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0},isEarHashed=(ear,minX,minY,invSize)=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y,minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0},splitEarcut=(start,triangles,dim,minX,minY,invSize)=>{let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize),void earcutLinked(c,triangles,dim,minX,minY,invSize)}b=b.next}a=a.next}while(a!==start)},indexCurve=(start,minX,minY,invSize)=>{let p=start;do{null===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,((list,fn)=>{let i,p,q,e,numMerges,inSize=1;do{p=list,list=null;let tail=null;for(numMerges=0;p;){numMerges++,q=p;let pSize=0;for(i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||fn(p)<=fn(q))?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1)})(p,(p=>p.z))},zOrder=(x,y,minX,minY,invSize)=>(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=32767*(x-minX)*invSize)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=32767*(y-minY)*invSize)|y<<8))|y<<4))|y<<2))|y<<1))<<1;class PolygonHierarchy{constructor(slice){this.plane=calculatePlane(slice);const rightVector=orthogonal([0,0,0],this.plane),perp=cross$1([0,0,0],this.plane,rightVector);this.v=normalize$1(perp,perp),this.u=cross$1([0,0,0],this.v,this.plane),this.basisMap=new Map;const projected=slice.contours.map((part=>part.map((v=>this.to2D(v))))),geometry=create$a(projected);this.roots=(geometry=>{const outlines=toOutlines(geometry),solids=[],holes=[];outlines.forEach(((outline,i)=>{const a=area$1(outline);a<0?holes.push(i):a>0&&solids.push(i)}));const children=[],parents=[];return solids.forEach(((s,i)=>{const solid=outlines[s];children[i]=[],holes.forEach(((h,j)=>{const hole=outlines[h];arePointsInside([hole[0]],create$3(solid))&&(children[i].push(h),parents[j]||(parents[j]=[]),parents[j].push(i))}))})),holes.forEach(((h,j)=>{if(parents[j]&&parents[j].length>1){const directParent=((list,score)=>{let bestIndex,best;return list.forEach(((item,index)=>{const value=score(item);(void 0===best||value<best)&&(bestIndex=index,best=value)})),bestIndex})(parents[j],(p=>children[p].length));parents[j].forEach(((p,i)=>{i!==directParent&&(children[p]=children[p].filter((c=>c!==h)))}))}})),children.map(((holes,i)=>({solid:outlines[solids[i]],holes:holes.map((h=>outlines[h]))})))})(geometry)}to2D(vector3){const vector2=fromValues$2(dot$2(vector3,this.u),dot$2(vector3,this.v));return this.basisMap.set(vector2,vector3),vector2}to3D(vector2){const original=this.basisMap.get(vector2);if(original)return original;{console.log("Warning: point not in original slice");const v1=scale$3([0,0,0],this.u,vector2[0]),v2=scale$3([0,0,0],this.v,vector2[1]),planeOrigin=scale$3([0,0,0],this.plane,this.plane[3]),v3=add$1(v1,v1,planeOrigin);return add$1(v2,v2,v3)}}}const toPolygons=slice=>{const hierarchy=new PolygonHierarchy(slice),polygons=[];return hierarchy.roots.forEach((({solid:solid,holes:holes})=>{let index=solid.length;const holesIndex=[];holes.forEach(((hole,i)=>{holesIndex.push(index),index+=hole.length}));const vertices=[solid,...holes].flat(),getVertex=i=>hierarchy.to3D(vertices[i]),indices=((data,holeIndices,dim=2)=>{const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedPolygon(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,maxX,maxY,invSize;if(hasHoles&&(outerNode=((data,holeIndices,outerNode,dim)=>{const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const start=holeIndices[i]*dim,end=i<len-1?holeIndices[i+1]*dim:data.length,list=linkedPolygon(data,start,end,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(((a,b)=>a.x-b.x));for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode),outerNode=filterPoints(outerNode,outerNode.next);return outerNode})(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=maxX=data[0],minY=maxY=data[1];for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?1/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize),triangles})(vertices.flat(),holesIndex);for(let i=0;i<indices.length;i+=3){const tri=indices.slice(i,i+3).map(getVertex);polygons.push(fromVerticesAndPlane(tri,hierarchy.plane))}})),polygons},transform$3=(matrix,slice)=>{const contours=slice.contours.map((contour=>contour.map((vertex=>transform$c([0,0,0],vertex,matrix)))));return create$2(contours)};Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:equals$3,fromGeom2:fromGeom2,fromVertices:fromVertices,isA:isA,reverse:reverse$2,toEdges:toEdges,toVertices:slice=>{const vertices=[];return slice.contours.forEach((contour=>{contour.forEach((vertex=>{vertices.push(vertex)}))})),vertices},toPolygons:toPolygons,toString:slice=>{let result="slice ("+slice.contours.length+" contours):\n[\n";return slice.contours.forEach((contour=>{result+=" ["+contour.map(toString$b).join()+"],\n"})),result+="]\n",result},transform:transform$3,validate:object=>{if(!isA(object))throw new Error("invalid slice structure");const slicePlane=calculatePlane(object);object.contours.forEach(((contour,i)=>{if(contour.length<3)throw new Error(`slice contour ${i} must contain at least 3 vertices`);const contourPlane=plane(create$7(contour));if(!equals$5(slicePlane,contourPlane))throw new Error("slice contours must be coplanar");for(let i=0;i<contour.length;i++){if(!contour[i].every(Number.isFinite))throw new Error(`slice contour ${i} must contain finite vertices`);const j=(i+1)%contour.length;if(equals$7(contour[i],contour[j]))throw new Error(`slice contour ${i} has duplicate vertex ${contour[i]}`)}}))}});const direction$1=line=>{const vector=normal([0,0],line);return negate(vector,vector),vector},origin$1=line=>scale$1([0,0],line,line[2]),copy$1=(out,line)=>(out[0]=line[0],out[1]=line[1],out[2]=line[2],out),fromPoints$1=(out,point1,point2)=>{const vector=subtract$1([0,0],point2,point1);normal(vector,vector),normalize(vector,vector);const distance=dot$1(point1,vector);return out[0]=vector[0],out[1]=vector[1],out[2]=distance,out},fromValues=(x,y,d)=>{const out=[0,1,0];return out[0]=x,out[1]=y,out[2]=d,out},solve2Linear=(a,b,c,d,u,v)=>{const invdet=1/(a*d-b*c);let x=u*d-b*v,y=-u*c+a*v;return x*=invdet,y*=invdet,[x,y]},intersectPointOfLines=(line1,line2)=>{const point=solve2Linear(line1[0],line1[1],line2[0],line2[1],line1[2],line2[2]);return clone$8(point)};var index$a=Object.freeze({__proto__:null,clone:line=>{const out=[0,1,0];return out[0]=line[0],out[1]=line[1],out[2]=line[2],out},closestPoint:(line,point)=>{const orig=origin$1(line),dir=direction$1(line),v=subtract$1([0,0],point,orig),dist=dot$1(v,dir);return scale$1(v,dir,dist),add(v,v,orig),v},copy:copy$1,create:()=>[0,1,0],direction:direction$1,distanceToPoint:(line,point)=>{let distance=dot$1(point,line);return distance=Math.abs(distance-line[2]),distance},equals:(line1,line2)=>line1[0]===line2[0]&&line1[1]===line2[1]&&line1[2]===line2[2],fromPoints:fromPoints$1,fromValues:fromValues,intersectPointOfLines:intersectPointOfLines,origin:origin$1,reverse:(out,line)=>{const normal=negate([0,0],line),distance=-line[2];return copy$1(out,fromValues(normal[0],normal[1],distance))},toString:line=>`line2: (${line[0].toFixed(7)}, ${line[1].toFixed(7)}, ${line[2].toFixed(7)})`,transform:(out,line,matrix)=>{const org=origin$1(line),dir=direction$1(line);return transform$b(org,org,matrix),transform$b(dir,dir,matrix),fromPoints$1(out,org,dir)},xAtY:(line,y)=>{let x=(line[2]-line[1]*y)/line[0];return Number.isNaN(x)&&(x=origin$1(line)[0]),x}});const create=()=>[fromValues$3(0,0,0),fromValues$3(0,0,1)],closestPoint=(line,point)=>{const lPoint=line[0],lDirection=line[1],a=dot$2(subtract$3([0,0,0],point,lPoint),lDirection),b=dot$2(lDirection,lDirection),closestPoint=scale$3([0,0,0],lDirection,a/b);return add$1(closestPoint,closestPoint,lPoint),closestPoint},fromPointAndDirection=(out,point,direction)=>{const unit=normalize$1([0,0,0],direction);return copy$4(out[0],point),copy$4(out[1],unit),out};var index$9=Object.freeze({__proto__:null,clone:line=>{const out=create();return copy$4(out[0],line[0]),copy$4(out[1],line[1]),out},closestPoint:closestPoint,copy:(out,line)=>(copy$4(out[0],line[0]),copy$4(out[1],line[1]),out),create:create,direction:line=>line[1],distanceToPoint:(line,point)=>{const closest=closestPoint(line,point),distanceVector=subtract$3([0,0,0],point,closest);return length$2(distanceVector)},equals:(line1,line2)=>!!equals$7(line1[1],line2[1])&&!!equals$7(line1[0],line2[0]),fromPlanes:(out,plane1,plane2)=>{let direction=cross$1([0,0,0],plane1,plane2),length=length$2(direction);if(length<EPS)throw new Error("parallel planes do not intersect");length=1/length,direction=scale$3(direction,direction,length);const absX=Math.abs(direction[0]),absY=Math.abs(direction[1]),absZ=Math.abs(direction[2]);let origin,r;return absX>=absY&&absX>=absZ?(r=solve2Linear(plane1[1],plane1[2],plane2[1],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(0,r[0],r[1])):absY>=absX&&absY>=absZ?(r=solve2Linear(plane1[0],plane1[2],plane2[0],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(r[0],0,r[1])):(r=solve2Linear(plane1[0],plane1[1],plane2[0],plane2[1],plane1[3],plane2[3]),origin=fromValues$3(r[0],r[1],0)),fromPointAndDirection(out,origin,direction)},fromPointAndDirection:fromPointAndDirection,fromPoints:(out,point1,point2)=>{const direction=subtract$3([0,0,0],point2,point1);return fromPointAndDirection(out,point1,direction)},intersectPointOfLineAndPlane:(line,plane)=>{const pNormal=plane,pw=plane[3],lPoint=line[0],lDirection=line[1],labda=(pw-dot$2(pNormal,lPoint))/dot$2(pNormal,lDirection);return add$1([0,0,0],lPoint,scale$3([0,0,0],lDirection,labda))},origin:line=>line[0],reverse:(out,line)=>{const point=clone$9(line[0]),direction=negate$1([0,0,0],line[1]);return fromPointAndDirection(out,point,direction)},toString:line=>{const point=line[0],direction=line[1];return`line3: point: (${point[0].toFixed(7)}, ${point[1].toFixed(7)}, ${point[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`},transform:(out,line,matrix)=>{const point=line[0],direction=line[1],pointPlusDirection=add$1([0,0,0],point,direction),newPoint=transform$c([0,0,0],point,matrix),newPointPlusDirection=transform$c(pointPlusDirection,pointPlusDirection,matrix),newDirection=subtract$3(newPointPlusDirection,newPointPlusDirection,newPoint);return fromPointAndDirection(out,newPoint,newDirection)}});Object.freeze({__proto__:null,line2:index$a,line3:index$9,mat4:index$i,plane:index$g,vec2:index$h,vec3:index$j,vec4:index$f,cos:cos,sin:sin,area:area$1,EPS:EPS,NEPS:NEPS,TAU:TAU});const cache$3=new WeakMap,measureArea=(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>isA$2(geometry)?0:isA$5(geometry)?(geometry=>{let area=cache$3.get(geometry);return area||(area=toSides(geometry).reduce(((area,side)=>area+(side[0][0]*side[1][1]-side[0][1]*side[1][0])),0),area*=.5,cache$3.set(geometry,area),area)})(geometry):isA$3(geometry)?(geometry=>{let area=cache$3.get(geometry);return area||(area=toPolygons$1(geometry).reduce(((area,polygon)=>area+measureArea$2(polygon)),0),cache$3.set(geometry,area),area)})(geometry):isA(geometry)?(geometry=>{let area=cache$3.get(geometry);return area||(area=0,geometry.contours.forEach((contour=>{area+=measureArea$2(create$7(contour))})),cache$3.set(geometry,area),area)})(geometry):0));return 1===results.length?results[0]:results},cache$2=new WeakMap,expand2=(bbox,point)=>{0===bbox.length?(bbox[0]=fromVec2([0,0,0],point),bbox[1]=fromVec2([0,0,0],point)):(min(bbox[0],bbox[0],point),max(bbox[1],bbox[1],point))},expand3=(bbox,vertex)=>{0===bbox.length?(bbox[0]=clone$9(vertex),bbox[1]=clone$9(vertex)):(min$1(bbox[0],bbox[0],vertex),max$1(bbox[1],bbox[1],vertex))},measureCached$1=(geometry,measureFn)=>{let boundingBox=cache$2.get(geometry);return boundingBox||(boundingBox=measureFn(geometry),0===boundingBox.length&&(boundingBox[0]=[0,0,0],boundingBox[1]=[0,0,0]),cache$2.set(geometry,boundingBox),boundingBox)},measureBoundingBoxOfPath2=geometry=>{const boundingBox=[];return toPoints$1(geometry).forEach((point=>{expand2(boundingBox,point)})),boundingBox},measureBoundingBoxOfGeom2=geometry=>{const boundingBox=[];return toPoints$3(geometry).forEach((point=>{expand2(boundingBox,point)})),boundingBox},measureBoundingBoxOfGeom3=geometry=>{const boundingBox=[];return toPolygons$1(geometry).forEach((polygon=>{toVertices$1(polygon).forEach((vertex=>{expand3(boundingBox,vertex)}))})),boundingBox},measureBoundingBoxOfSlice=geometry=>{const boundingBox=[];return geometry.contours.forEach((contour=>{contour.forEach((vertex=>{expand3(boundingBox,vertex)}))})),boundingBox},measureBoundingBox=(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>isA$2(geometry)?measureCached$1(geometry,measureBoundingBoxOfPath2):isA$5(geometry)?measureCached$1(geometry,measureBoundingBoxOfGeom2):isA$3(geometry)?measureCached$1(geometry,measureBoundingBoxOfGeom3):isA(geometry)?measureCached$1(geometry,measureBoundingBoxOfSlice):[[0,0,0],[0,0,0]]));return 1===results.length?results[0]:results},measureAggregateBoundingBox=(...geometries)=>{geometries=flatten(geometries);const bounds=measureBoundingBox(geometries);if(1===geometries.length)return bounds;const result=[[Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE],[-Number.MAX_VALUE,-Number.MAX_VALUE,-Number.MAX_VALUE]];return bounds.reduce(((result,item)=>[min$1(result[0],result[0],item[0]),max$1(result[1],result[1],item[1])]),result)},calculateEpsilonFromBounds=(bounds,dimensions)=>{let total=0;for(let i=0;i<dimensions;i++)total+=bounds[1][i]-bounds[0][i];return EPS*total/dimensions},cache$1=new WeakMap,measureVolume=(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>isA$3(geometry)?(geometry=>{let volume=cache$1.get(geometry);return volume||(volume=toPolygons$1(geometry).reduce(((volume,polygon)=>volume+measureSignedVolume(polygon)),0),cache$1.set(geometry,volume),volume)})(geometry):0));return 1===results.length?results[0]:results},cache=new WeakMap,measureCached=(geometry,measureFn)=>{let boundingSphere=cache.get(geometry);return boundingSphere||(boundingSphere=measureFn(geometry),0===boundingSphere.length&&(boundingSphere[0]=[0,0,0],boundingSphere[1]=0),cache.set(geometry,boundingSphere),boundingSphere)},measureBoundingSphereOfPoints=points=>{const centroid=[0,0,0];let radius=0;if(points.length>0){let numPoints=0;const temp=[0,0,0];points.forEach((point=>{add$1(centroid,centroid,fromVec2(temp,point,0)),numPoints++})),scale$3(centroid,centroid,1/numPoints),points.forEach((point=>{radius=Math.max(radius,squaredDistance(centroid,point))})),radius=Math.sqrt(radius)}return[centroid,radius]},measureBoundingSphereOfPath2=geometry=>measureBoundingSphereOfPoints(toPoints$1(geometry)),measureBoundingSphereOfGeom2=geometry=>measureBoundingSphereOfPoints(toPoints$3(geometry)),measureBoundingSphereOfGeom3=geometry=>{const centroid=[0,0,0];let radius=0;const polygons=toPolygons$1(geometry);if(polygons.length>0){let numVertices=0;polygons.forEach((polygon=>{toVertices$1(polygon).forEach((vertex=>{add$1(centroid,centroid,vertex),numVertices++}))})),scale$3(centroid,centroid,1/numVertices),polygons.forEach((polygon=>{toVertices$1(polygon).forEach((vertex=>{radius=Math.max(radius,squaredDistance$1(centroid,vertex))}))})),radius=Math.sqrt(radius)}return[centroid,radius]},measureBoundingSphereOfSlice=geometry=>{const centroid=[0,0,0];let radius=0,numVertices=0;return geometry.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(centroid,centroid,vertex),numVertices++}))})),numVertices>0&&(scale$3(centroid,centroid,1/numVertices),geometry.contours.forEach((contour=>{contour.forEach((vertex=>{radius=Math.max(radius,squaredDistance$1(centroid,vertex))}))})),radius=Math.sqrt(radius)),[centroid,radius]},cacheOfCenterOfMass=new WeakMap,measureEpsilon=(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>isA$2(geometry)||isA$5(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),2):isA$3(geometry)||isA(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),3):0));return 1===results.length?results[0]:results};Object.freeze({__proto__:null,measureAggregateArea:(...geometries)=>{geometries=flatten(geometries);const areas=measureArea(geometries);return 1===geometries.length?areas:areas.reduce(((result,area)=>result+area),0)},measureAggregateBoundingBox:measureAggregateBoundingBox,measureAggregateEpsilon:(...geometries)=>{geometries=flatten(geometries);const bounds=measureAggregateBoundingBox(geometries);let dimensions=0;return dimensions=geometries.reduce(((dimensions,geometry)=>isA$2(geometry)||isA$5(geometry)?Math.max(dimensions,2):isA$3(geometry)?Math.max(dimensions,3):0),dimensions),calculateEpsilonFromBounds(bounds,dimensions)},measureAggregateVolume:(...geometries)=>{geometries=flatten(geometries);const volumes=measureVolume(geometries);return 1===geometries.length?volumes:volumes.reduce(((result,volume)=>result+volume),0)},measureArea:measureArea,measureBoundingBox:measureBoundingBox,measureBoundingSphere:(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>isA$2(geometry)?measureCached(geometry,measureBoundingSphereOfPath2):isA$5(geometry)?measureCached(geometry,measureBoundingSphereOfGeom2):isA$3(geometry)?measureCached(geometry,measureBoundingSphereOfGeom3):isA(geometry)?measureCached(geometry,measureBoundingSphereOfSlice):[[0,0,0],0]));return 1===results.length?results[0]:results},measureCenter:(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>{const bounds=measureBoundingBox(geometry);return[bounds[0][0]+(bounds[1][0]-bounds[0][0])/2,bounds[0][1]+(bounds[1][1]-bounds[0][1])/2,bounds[0][2]+(bounds[1][2]-bounds[0][2])/2]}));return 1===results.length?results[0]:results},measureCenterOfMass:(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>isA$5(geometry)?(geometry=>{let centerOfMass=cacheOfCenterOfMass.get(geometry);if(void 0!==centerOfMass)return centerOfMass;const sides=toSides(geometry);let area=0,x=0,y=0;if(sides.length>0){for(let i=0;i<sides.length;i++){const p1=sides[i][0],p2=sides[i][1],a=p1[0]*p2[1]-p1[1]*p2[0];area+=a,x+=(p1[0]+p2[0])*a,y+=(p1[1]+p2[1])*a}area/=2;const f=1/(6*area);x*=f,y*=f}return centerOfMass=fromValues$3(x,y,0),cacheOfCenterOfMass.set(geometry,centerOfMass),centerOfMass})(geometry):isA$3(geometry)?(geometry=>{let centerOfMass=cacheOfCenterOfMass.get(geometry);if(void 0!==centerOfMass)return centerOfMass;centerOfMass=[0,0,0];const polygons=toPolygons$1(geometry);if(0===polygons.length)return centerOfMass;let totalVolume=0;const vector=[0,0,0];return polygons.forEach((polygon=>{const vertices=polygon.vertices;for(let i=0;i<vertices.length-2;i++){cross$1(vector,vertices[i+1],vertices[i+2]);const volume=dot$2(vertices[0],vector)/6;totalVolume+=volume,add$1(vector,vertices[0],vertices[i+1]),add$1(vector,vector,vertices[i+2]);const weightedCenter=scale$3(vector,vector,1/4*volume);add$1(centerOfMass,centerOfMass,weightedCenter)}})),scale$3(centerOfMass,centerOfMass,1/totalVolume),cacheOfCenterOfMass.set(geometry,centerOfMass),centerOfMass})(geometry):[0,0,0]));return 1===results.length?results[0]:results},measureDimensions:(...geometries)=>{const results=(geometries=flatten(geometries)).map((geometry=>{const boundingBox=measureBoundingBox(geometry);return[boundingBox[1][0]-boundingBox[0][0],boundingBox[1][1]-boundingBox[0][1],boundingBox[1][2]-boundingBox[0][2]]}));return 1===results.length?results[0]:results},measureEpsilon:measureEpsilon,measureVolume:measureVolume});const isNumberArray=(array,dimension)=>!!(Array.isArray(array)&&array.length>=dimension)&&array.every((n=>Number.isFinite(n))),isGT=(value,constant)=>Number.isFinite(value)&&value>constant,isGTE=(value,constant)=>Number.isFinite(value)&&value>=constant,ellipse=options=>{const defaults={center:[0,0],radius:[1,1],startAngle:0,endAngle:TAU,segments:32};let{center:center,radius:radius,startAngle:startAngle,endAngle:endAngle,segments:segments}=Object.assign({},defaults,options);if(!isNumberArray(center,2))throw new Error("center must be an array of X and Y values");if(!isNumberArray(radius,2))throw new Error("radius must be an array of X and Y values");if(!radius.every((n=>n>=0)))throw new Error("radius values must be positive");if(!isGTE(startAngle,0))throw new Error("startAngle must be positive");if(!isGTE(endAngle,0))throw new Error("endAngle must be positive");if(!isGTE(segments,3))throw new Error("segments must be three or more");if(0===radius[0]||0===radius[1])return create$a();startAngle%=TAU,endAngle%=TAU;let rotation=TAU;startAngle<endAngle&&(rotation=endAngle-startAngle),startAngle>endAngle&&(rotation=endAngle+(TAU-startAngle));const minRadius=Math.min(radius[0],radius[1]);if(rotation<Math.acos((minRadius*minRadius+minRadius*minRadius-EPS*EPS)/(2*minRadius*minRadius)))throw new Error("startAngle and endAngle do not define a significant rotation");segments=Math.floor(segments*(rotation/TAU));const centerV=clone$8(center),step=rotation/segments,points=[];segments=rotation<TAU?segments+1:segments;for(let i=0;i<segments;i++){const angle=step*i+startAngle,point=fromValues$2(radius[0]*cos(angle),radius[1]*sin(angle));add(point,centerV,point),points.push(point)}return rotation<TAU&&points.push(centerV),create$a([points])},circle=options=>{const defaults={center:[0,0],radius:1,startAngle:0,endAngle:TAU,segments:32};let{center:center,radius:radius,startAngle:startAngle,endAngle:endAngle,segments:segments}=Object.assign({},defaults,options);if(!isGTE(radius,0))throw new Error("radius must be positive");return radius=[radius,radius],ellipse({center:center,radius:radius,startAngle:startAngle,endAngle:endAngle,segments:segments})},cuboid=options=>{const{center:center,size:size}=Object.assign({},{center:[0,0,0],size:[2,2,2]},options);if(!isNumberArray(center,3))throw new Error("center must be an array of X, Y and Z values");if(!isNumberArray(size,3))throw new Error("size must be an array of width, depth and height values");if(!size.every((n=>n>=0)))throw new Error("size values must be positive");return 0===size[0]||0===size[1]||0===size[2]?create$8():create$8([[[0,4,6,2],[-1,0,0]],[[1,3,7,5],[1,0,0]],[[0,1,5,4],[0,-1,0]],[[2,6,7,3],[0,1,0]],[[0,2,3,1],[0,0,-1]],[[4,5,7,6],[0,0,1]]].map((info=>{const vertices=info[0].map((i=>[center[0]+size[0]/2*(2*!!(1&i)-1),center[1]+size[1]/2*(2*!!(2&i)-1),center[2]+size[2]/2*(2*!!(4&i)-1)]));return create$7(vertices)})))},cylinderElliptic=options=>{const defaults={center:[0,0,0],height:2,startRadius:[1,1],startAngle:0,endRadius:[1,1],endAngle:TAU,segments:32};let{center:center,height:height,startRadius:startRadius,startAngle:startAngle,endRadius:endRadius,endAngle:endAngle,segments:segments}=Object.assign({},defaults,options);if(!isNumberArray(center,3))throw new Error("center must be an array of X, Y and Z values");if(!isGT(height,0))throw new Error("height must be greater then zero");if(!isNumberArray(startRadius,2))throw new Error("startRadius must be an array of X and Y values");if(!startRadius.every((n=>n>=0)))throw new Error("startRadius values must be positive");if(!isNumberArray(endRadius,2))throw new Error("endRadius must be an array of X and Y values");if(!endRadius.every((n=>n>=0)))throw new Error("endRadius values must be positive");if(endRadius.every((n=>0===n))&&startRadius.every((n=>0===n)))throw new Error("at least one radius must be positive");if(!isGTE(startAngle,0))throw new Error("startAngle must be positive");if(!isGTE(endAngle,0))throw new Error("endAngle must be positive");if(!isGTE(segments,4))throw new Error("segments must be four or more");startAngle%=TAU,endAngle%=TAU;let rotation=TAU;startAngle<endAngle&&(rotation=endAngle-startAngle),startAngle>endAngle&&(rotation=endAngle+(TAU-startAngle));const minRadius=Math.min(startRadius[0],startRadius[1],endRadius[0],endRadius[1]),minAngle=Math.acos((minRadius*minRadius+minRadius*minRadius-EPS*EPS)/(2*minRadius*minRadius));if(rotation<minAngle)throw new Error("startAngle and endAngle do not define a significant rotation");const slices=Math.floor(segments*(rotation/TAU)),start=fromValues$3(0,0,-height/2),end=fromValues$3(0,0,height/2),ray=subtract$3([0,0,0],end,start),axisX=fromValues$3(1,0,0),axisY=fromValues$3(0,1,0),v1=[0,0,0],v2=[0,0,0],v3=[0,0,0],genVertex=(stack,slice,radius)=>{const angle=slice*rotation+startAngle;return scale$3(v1,axisX,radius[0]*cos(angle)),scale$3(v2,axisY,radius[1]*sin(angle)),add$1(v1,v1,v2),scale$3(v3,ray,stack),add$1(v3,v3,start),add$1([0,0,0],v1,v3)},fromVertices=(...vertices)=>{const newVertices=vertices.map((vertex=>add$1([0,0,0],vertex,center)));return create$7(newVertices)},polygons=[];for(let i=0;i<slices;i++){const t0=i/slices;let t1=(i+1)/slices;rotation===TAU&&i===slices-1&&(t1=0),endRadius[0]===startRadius[0]&&endRadius[1]===startRadius[1]?(polygons.push(fromVertices(start,genVertex(0,t1,endRadius),genVertex(0,t0,endRadius))),polygons.push(fromVertices(genVertex(0,t1,endRadius),genVertex(1,t1,endRadius),genVertex(1,t0,endRadius),genVertex(0,t0,endRadius))),polygons.push(fromVertices(end,genVertex(1,t0,endRadius),genVertex(1,t1,endRadius)))):(startRadius[0]>0&&startRadius[1]>0&&polygons.push(fromVertices(start,genVertex(0,t1,startRadius),genVertex(0,t0,startRadius))),(startRadius[0]>0||startRadius[1]>0)&&polygons.push(fromVertices(genVertex(0,t0,startRadius),genVertex(0,t1,startRadius),genVertex(1,t0,endRadius))),endRadius[0]>0&&endRadius[1]>0&&polygons.push(fromVertices(end,genVertex(1,t0,endRadius),genVertex(1,t1,endRadius))),(endRadius[0]>0||endRadius[1]>0)&&polygons.push(fromVertices(genVertex(1,t0,endRadius),genVertex(0,t1,startRadius),genVertex(1,t1,endRadius))))}return rotation<TAU&&(polygons.push(fromVertices(start,genVertex(0,0,startRadius),end)),polygons.push(fromVertices(genVertex(0,0,startRadius),genVertex(1,0,endRadius),end)),polygons.push(fromVertices(start,end,genVertex(0,1,startRadius))),polygons.push(fromVertices(genVertex(0,1,startRadius),end,genVertex(1,1,endRadius)))),create$8(polygons)},cylinder=options=>{const{center:center,height:height,radius:radius,segments:segments}=Object.assign({},{center:[0,0,0],height:2,radius:1,segments:32},options);if(!isGTE(radius,0))throw new Error("radius must be positive");return 0===height||0===radius?create$8():cylinderElliptic({center:center,height:height,startRadius:[radius,radius],endRadius:[radius,radius],segments:segments})},ellipsoid=options=>{const{center:center,radius:radius,segments:segments,axes:axes}=Object.assign({},{center:[0,0,0],radius:[1,1,1],segments:32,axes:[[1,0,0],[0,-1,0],[0,0,1]]},options);if(!isNumberArray(center,3))throw new Error("center must be an array of X, Y and Z values");if(!isNumberArray(radius,3))throw new Error("radius must be an array of X, Y and Z values");if(!radius.every((n=>n>=0)))throw new Error("radius values must be positive");if(!isGTE(segments,4))throw new Error("segments must be four or more");if(0===radius[0]||0===radius[1]||0===radius[2])return create$8();const xVector=scale$3([0,0,0],normalize$1([0,0,0],axes[0]),radius[0]),yVector=scale$3([0,0,0],normalize$1([0,0,0],axes[1]),radius[1]),zVector=scale$3([0,0,0],normalize$1([0,0,0],axes[2]),radius[2]),qSegments=Math.round(segments/4);let prevCylinderVertex;const polygons=[],p1=[0,0,0],p2=[0,0,0];for(let slice1=0;slice1<=segments;slice1++){const angle=TAU*slice1/segments,cylinderVertex=add$1([0,0,0],scale$3(p1,xVector,cos(angle)),scale$3(p2,yVector,sin(angle)));if(slice1>0){let prevCosPitch,prevSinPitch;for(let slice2=0;slice2<=qSegments;slice2++){const pitch=TAU/4*slice2/qSegments,cosPitch=cos(pitch),sinPitch=sin(pitch);if(slice2>0){let vertex,vertices=[];vertex=subtract$3([0,0,0],scale$3(p1,prevCylinderVertex,prevCosPitch),scale$3(p2,zVector,prevSinPitch)),vertices.push(add$1(vertex,vertex,center)),vertex=subtract$3([0,0,0],scale$3(p1,cylinderVertex,prevCosPitch),scale$3(p2,zVector,prevSinPitch)),vertices.push(add$1(vertex,vertex,center)),slice2<qSegments&&(vertex=subtract$3([0,0,0],scale$3(p1,cylinderVertex,cosPitch),scale$3(p2,zVector,sinPitch)),vertices.push(add$1(vertex,vertex,center))),vertex=subtract$3([0,0,0],scale$3(p1,prevCylinderVertex,cosPitch),scale$3(p2,zVector,sinPitch)),vertices.push(add$1(vertex,vertex,center)),polygons.push(create$7(vertices)),vertices=[],vertex=add$1([0,0,0],scale$3(p1,prevCylinderVertex,prevCosPitch),scale$3(p2,zVector,prevSinPitch)),vertices.push(add$1([0,0,0],center,vertex)),vertex=add$1(vertex,scale$3(p1,cylinderVertex,prevCosPitch),scale$3(p2,zVector,prevSinPitch)),vertices.push(add$1([0,0,0],center,vertex)),slice2<qSegments&&(vertex=add$1(vertex,scale$3(p1,cylinderVertex,cosPitch),scale$3(p2,zVector,sinPitch)),vertices.push(add$1([0,0,0],center,vertex))),vertex=add$1(vertex,scale$3(p1,prevCylinderVertex,cosPitch),scale$3(p2,zVector,sinPitch)),vertices.push(add$1([0,0,0],center,vertex)),vertices.reverse(),polygons.push(create$7(vertices))}prevCosPitch=cosPitch,prevSinPitch=sinPitch}}prevCylinderVertex=cylinderVertex}return create$8(polygons)},polyhedron=options=>{const{points:points,faces:faces,colors:colors,orientation:orientation}=Object.assign({},{points:[],faces:[],colors:void 0,orientation:"outward"},options);if(!Array.isArray(points)||!Array.isArray(faces))throw new Error("points and faces must be arrays");if(points.length<3)throw new Error("three or more points are required");if(faces.length<1)throw new Error("one or more faces are required");if(colors){if(!Array.isArray(colors))throw new Error("colors must be an array");if(colors.length!==faces.length)throw new Error("faces and colors must have the same length")}points.forEach(((vertex,i)=>{if(!isNumberArray(vertex,3))throw new Error(`vertex ${i} must be an array of X, Y, Z values`)})),faces.forEach(((face,i)=>{if(face.length<3)throw new Error(`face ${i} must contain 3 or more indexes`);if(!isNumberArray(face,face.length))throw new Error(`face ${i} must be an array of numbers`)})),"outward"!==orientation&&faces.forEach((face=>face.reverse()));const polygons=faces.map(((face,findex)=>{const polygon=create$7(face.map((pindex=>points[pindex])));return colors&&colors[findex]&&(polygon.color=colors[findex]),polygon}));return create$8(polygons)},rectangle=options=>{const{center:center,size:size}=Object.assign({},{center:[0,0],size:[2,2]},options);if(!isNumberArray(center,2))throw new Error("center must be an array of X and Y values");if(!isNumberArray(size,2))throw new Error("size must be an array of X and Y values");if(!size.every((n=>n>=0)))throw new Error("size values must be positive");if(0===size[0]||0===size[1])return create$a();const point=[size[0]/2,size[1]/2],swapped=[point[0],-point[1]],points=[subtract$1([0,0],center,point),add([0,0],center,swapped),add([0,0],center,point),subtract$1([0,0],center,swapped)];return create$a([points])},createCorners=(center,size,radius,segments,slice,positive)=>{const pitch=TAU/4*slice/segments,cosPitch=cos(pitch),sinPitch=sin(pitch),layerSegments=segments-slice;let layerRadius=radius*cosPitch,layerOffset=size[2]-(radius-radius*sinPitch);positive||(layerOffset=radius-radius*sinPitch-size[2]),layerRadius=layerRadius>EPS?layerRadius:0;const corner0=add$1([0,0,0],center,[size[0]-radius,size[1]-radius,layerOffset]),corner1=add$1([0,0,0],center,[radius-size[0],size[1]-radius,layerOffset]),corner2=add$1([0,0,0],center,[radius-size[0],radius-size[1],layerOffset]),corner3=add$1([0,0,0],center,[size[0]-radius,radius-size[1],layerOffset]),corner0Vertices=[],corner1Vertices=[],corner2Vertices=[],corner3Vertices=[];for(let i=0;i<=layerSegments;i++){const point2d=fromAngleRadians([0,0],layerSegments>0?TAU/4*i/layerSegments:0);scale$1(point2d,point2d,layerRadius);const point3d=fromVec2([0,0,0],point2d);corner0Vertices.push(add$1([0,0,0],corner0,point3d)),rotateZ$2(point3d,point3d,[0,0,0],TAU/4),corner1Vertices.push(add$1([0,0,0],corner1,point3d)),rotateZ$2(point3d,point3d,[0,0,0],TAU/4),corner2Vertices.push(add$1([0,0,0],corner2,point3d)),rotateZ$2(point3d,point3d,[0,0,0],TAU/4),corner3Vertices.push(add$1([0,0,0],corner3,point3d))}return positive?[corner0Vertices,corner1Vertices,corner2Vertices,corner3Vertices]:(corner0Vertices.reverse(),corner1Vertices.reverse(),corner2Vertices.reverse(),corner3Vertices.reverse(),[corner3Vertices,corner2Vertices,corner1Vertices,corner0Vertices])},stitchCorners=(previousCorners,currentCorners)=>{const polygons=[];for(let i=0;i<previousCorners.length;i++){const previous=previousCorners[i],current=currentCorners[i];for(let j=0;j<previous.length-1;j++)polygons.push(create$7([previous[j],previous[j+1],current[j]])),j<current.length-1&&polygons.push(create$7([current[j],previous[j+1],current[j+1]]))}return polygons},stitchWalls=(previousCorners,currentCorners)=>{const polygons=[];for(let i=0;i<previousCorners.length;i++){let previous=previousCorners[i],current=currentCorners[i];const p0=previous[previous.length-1],c0=current[current.length-1],j=(i+1)%previousCorners.length;previous=previousCorners[j],current=currentCorners[j];const p1=previous[0],c1=current[0];polygons.push(create$7([p0,p1,c1,c0]))}return polygons},stitchSides=(bottomCorners,topCorners)=>{bottomCorners=(bottomCorners=[bottomCorners[3],bottomCorners[2],bottomCorners[1],bottomCorners[0]]).map((corner=>corner.slice().reverse()));const bottomVertices=[];bottomCorners.forEach((corner=>{corner.forEach((vertex=>bottomVertices.push(vertex)))}));const topVertices=[];topCorners.forEach((corner=>{corner.forEach((vertex=>topVertices.push(vertex)))}));const polygons=[];for(let i=0;i<topVertices.length;i++){const j=(i+1)%topVertices.length;polygons.push(create$7([bottomVertices[i],bottomVertices[j],topVertices[j],topVertices[i]]))}return polygons},sphere=options=>{let{center:center,radius:radius,segments:segments,axes:axes}=Object.assign({},{center:[0,0,0],radius:1,segments:32,axes:[[1,0,0],[0,-1,0],[0,0,1]]},options);if(!isGTE(radius,0))throw new Error("radius must be positive");return radius=[radius,radius,radius],ellipsoid({center:center,radius:radius,segments:segments,axes:axes})},getPoints=(vertices,radius,startAngle,center)=>{const a=TAU/vertices,points=[];for(let i=0;i<vertices;i++){const point=fromAngleRadians([0,0],a*i+startAngle);scale$1(point,point,radius),add(point,center,point),points.push(point)}return points},mirror=(options,...objects)=>{const{origin:origin,normal:normal}=Object.assign({},{origin:[0,0,0],normal:[0,0,1]},options),planeOfMirror=fromNormalAndPoint([0,0,0,0],normal,origin);if(Number.isNaN(planeOfMirror[0]))throw new Error("the given origin and normal do not define a proper plane");const matrix=mirrorByPlane([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],planeOfMirror),results=objects.map((object=>isA$2(object)?transform$5(matrix,object):isA$5(object)?transform$a(matrix,object):isA$3(object)?transform$6(matrix,object):Array.isArray(object)?mirror(options,...object):object));return 1===results.length?results[0]:results},mirrorX=(...objects)=>mirror({normal:[1,0,0]},...objects),gcd=(a,b)=>a===b?a:a<b?gcd(b,a):1===b?1:0===b?a:gcd(b,a%b),repartitionEdges=(newLength,edges)=>{const multiple=newLength/edges.length;if(1===multiple)return edges;const divisor=fromValues$3(multiple,multiple,multiple),increment=[0,0,0],newEdges=[];return edges.forEach((edge=>{subtract$3(increment,edge[1],edge[0]),divide$1(increment,increment,divisor);let prev=edge[0];for(let i=1;i<=multiple;++i){const next=add$1([0,0,0],prev,increment);newEdges.push([prev,next]),prev=next}})),newEdges},EPSAREA=EPS*EPS/2*Math.sin(Math.PI/3),extrudeWalls=(slice0,slice1)=>{let edges0=toEdges(slice0),edges1=toEdges(slice1);if(edges0.length!==edges1.length){const newLength=(a=edges0.length)*(b=edges1.length)/gcd(a,b);newLength!==edges0.length&&(edges0=repartitionEdges(newLength,edges0)),newLength!==edges1.length&&(edges1=repartitionEdges(newLength,edges1))}var a,b;const walls=[];return edges0.forEach(((edge0,i)=>{const edge1=edges1[i],poly0=create$7([edge0[0],edge0[1],edge1[1]]),poly0area=measureArea$2(poly0);Number.isFinite(poly0area)&&poly0area>EPSAREA&&walls.push(poly0);const poly1=create$7([edge0[0],edge1[1],edge1[0]]),poly1area=measureArea$2(poly1);Number.isFinite(poly1area)&&poly1area>EPSAREA&&walls.push(poly1)})),walls},defaultCallback=(progress,index,base)=>{let baseSlice=null;return isA$5(base)&&(baseSlice=fromGeom2(base)),isA$4(base)&&(baseSlice=fromVertices(toVertices$1(base))),0===progress||1===progress?transform$3(fromTranslation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],[0,0,progress]),baseSlice):null},extrudeFromSlices=(options,base)=>{const defaults={numberOfSlices:2,capStart:!0,capEnd:!0,close:!1,callback:defaultCallback},{numberOfSlices:numberOfSlices,capStart:capStart,capEnd:capEnd,close:close,callback:generate}=Object.assign({},defaults,options);if(numberOfSlices<2)throw new Error("numberOfSlices must be 2 or more");const sMax=numberOfSlices-1;let startSlice=null,endSlice=null,prevSlice=null,polygons=[];for(let s=0;s<numberOfSlices;s++){const currentSlice=generate(s/sMax,s,base);if(currentSlice){if(!isA(currentSlice))throw new Error("the callback function must return slice objects");if(0===currentSlice.contours.length)throw new Error("the callback function must return slices with one or more contours");prevSlice&&(polygons=polygons.concat(extrudeWalls(prevSlice,currentSlice))),0===s&&(startSlice=currentSlice),s===numberOfSlices-1&&(endSlice=currentSlice),prevSlice=currentSlice}}if(capEnd){const endPolygons=toPolygons(endSlice);polygons=polygons.concat(endPolygons)}if(capStart){const startPolygons=toPolygons(startSlice).map(invert$1);polygons=polygons.concat(startPolygons)}return capStart||capEnd||close&&!equals$3(endSlice,startSlice)&&(polygons=polygons.concat(extrudeWalls(endSlice,startSlice))),create$8(polygons)},extrudeRotate=(options,geometry)=>{const defaults={segments:12,startAngle:0,angle:TAU,overflow:"cap"};let{segments:segments,startAngle:startAngle,angle:angle,overflow:overflow}=Object.assign({},defaults,options);if(segments<3)throw new Error("segments must be greater then 3");startAngle=Math.abs(startAngle)>TAU?startAngle%TAU:startAngle,angle=Math.abs(angle)>TAU?angle%TAU:angle;let endAngle=startAngle+angle;if(endAngle=Math.abs(endAngle)>TAU?endAngle%TAU:endAngle,endAngle<startAngle){const x=startAngle;startAngle=endAngle,endAngle=x}let totalRotation=endAngle-startAngle;if(totalRotation<=0&&(totalRotation=TAU),Math.abs(totalRotation)<TAU){const anglePerSegment=TAU/segments;segments=Math.floor(Math.abs(totalRotation)/anglePerSegment),Math.abs(totalRotation)>segments*anglePerSegment&&segments++}let shapeSides=toSides(geometry);if(0===shapeSides.length)return create$8();let sliceGeometry=geometry;const pointsWithNegativeX=shapeSides.filter((s=>s[0][0]<0)),pointsWithPositiveX=shapeSides.filter((s=>s[0][0]>=0));pointsWithNegativeX.length>0&&pointsWithPositiveX.length>0&&"cap"===overflow&&(pointsWithNegativeX.length>pointsWithPositiveX.length?(shapeSides=shapeSides.map((side=>{let point0=side[0],point1=side[1];return point0=[Math.min(point0[0],0),point0[1]],point1=[Math.min(point1[0],0),point1[1]],[point0,point1]})),sliceGeometry=fromSides(shapeSides),sliceGeometry=mirrorX(sliceGeometry)):pointsWithPositiveX.length>=pointsWithNegativeX.length&&(shapeSides=shapeSides.map((side=>{let point0=side[0],point1=side[1];return point0=[Math.max(point0[0],0),point0[1]],point1=[Math.max(point1[0],0),point1[1]],[point0,point1]})),sliceGeometry=fromSides(shapeSides)));const rotationPerSlice=totalRotation/segments,isCapped=Math.abs(totalRotation)<TAU;let baseSlice=fromGeom2(sliceGeometry);baseSlice=reverse$2(baseSlice);const matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],output=extrudeFromSlices(options={numberOfSlices:segments+1,capStart:isCapped,capEnd:isCapped,close:!isCapped,callback:(progress,index,base)=>{let Zrotation=rotationPerSlice*index+startAngle;return totalRotation===TAU&&index===segments&&(Zrotation=startAngle),multiply$1(matrix,fromZRotation(matrix,Zrotation),fromXRotation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],TAU/4)),transform$3(matrix,base)}},baseSlice);return geometry.color&&(output.color=geometry.color),output},rotate=(angles,...objects)=>{if(!Array.isArray(angles))throw new Error("angles must be an array");for(angles=angles.slice();angles.length<3;)angles.push(0);const yaw=angles[2],pitch=angles[1],roll=angles[0],matrix=fromTaitBryanRotation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],yaw,pitch,roll),results=objects.map((object=>isA$2(object)?transform$5(matrix,object):isA$5(object)?transform$a(matrix,object):isA$3(object)?transform$6(matrix,object):Array.isArray(object)?rotate(angles,...object):object));return 1===results.length?results[0]:results},translate=(offset,...objects)=>{if(!Array.isArray(offset))throw new Error("offset must be an array");for(offset=offset.slice();offset.length<3;)offset.push(0);const matrix=fromTranslation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],offset),results=objects.map((object=>isA$2(object)?transform$5(matrix,object):isA$5(object)?transform$a(matrix,object):isA$3(object)?transform$6(matrix,object):Array.isArray(object)?translate(offset,...object):object));return 1===results.length?results[0]:results},solveAngleFromSSS=(a,b,c)=>Math.acos((a*a+b*b-c*c)/(2*a*b)),createTriangle=(A,B,C,a,b,c)=>{const p0=fromValues$2(0,0),p1=fromValues$2(c,0),p2=fromValues$2(a,0);return add(p2,rotate$1(p2,p2,[0,0],Math.PI-B),p1),create$a([[p0,p1,p2]])};Object.freeze({__proto__:null,arc:options=>{const defaults={center:[0,0],radius:1,startAngle:0,endAngle:TAU,makeTangent:!1,segments:32};let{center:center,radius:radius,startAngle:startAngle,endAngle:endAngle,makeTangent:makeTangent,segments:segments}=Object.assign({},defaults,options);if(!isNumberArray(center,2))throw new Error("center must be an array of X and Y values");if(!isGT(radius,0))throw new Error("radius must be greater than zero");if(!isGTE(startAngle,0))throw new Error("startAngle must be positive");if(!isGTE(endAngle,0))throw new Error("endAngle must be positive");if(!isGTE(segments,4))throw new Error("segments must be four or more");startAngle%=TAU,endAngle%=TAU;let rotation=TAU;startAngle<endAngle&&(rotation=endAngle-startAngle),startAngle>endAngle&&(rotation=endAngle+(TAU-startAngle));const minAngle=Math.acos((radius*radius+radius*radius-EPS*EPS)/(2*radius*radius)),centerV=clone$8(center);let point;const pointArray=[];if(rotation<minAngle)point=fromAngleRadians([0,0],startAngle),scale$1(point,point,radius),add(point,point,centerV),pointArray.push(point);else{const numSteps=Math.max(1,Math.floor(segments*(rotation/TAU)))+1;let edgeStepSize=.5*numSteps/rotation;edgeStepSize>.25&&(edgeStepSize=.25);const totalSteps=makeTangent?numSteps+2:numSteps;for(let i=0;i<=totalSteps;i++){let step=i;makeTangent&&(step=(i-1)*(numSteps-2*edgeStepSize)/numSteps+edgeStepSize,step<0&&(step=0),step>numSteps&&(step=numSteps)),point=fromAngleRadians([0,0],startAngle+step*(rotation/numSteps)),scale$1(point,point,radius),add(point,point,centerV),pointArray.push(point)}}return fromPoints$2({closed:!1},pointArray)},circle:circle,cube:options=>{let{center:center,size:size}=Object.assign({},{center:[0,0,0],size:2},options);if(!isGTE(size,0))throw new Error("size must be positive");return size=[size,size,size],cuboid({center:center,size:size})},cuboid:cuboid,cylinder:cylinder,cylinderElliptic:cylinderElliptic,ellipse:ellipse,ellipsoid:ellipsoid,geodesicSphere:options=>{let{radius:radius,frequency:frequency}=Object.assign({},{radius:1,frequency:6},options);if(!isGTE(radius,0))throw new Error("radius must be positive");if(!isGTE(frequency,6))throw new Error("frequency must be six or more");if(0===radius)return create$8();frequency=Math.floor(frequency/6);const ci=[[.850651,0,-.525731],[.850651,-0,.525731],[-.850651,-0,.525731],[-.850651,0,-.525731],[0,-.525731,.850651],[0,.525731,.850651],[0,.525731,-.850651],[0,-.525731,-.850651],[-.525731,-.850651,-0],[.525731,-.850651,-0],[.525731,.850651,0],[-.525731,.850651,0]],ti=[[0,9,1],[1,10,0],[6,7,0],[10,6,0],[7,9,0],[5,1,4],[4,1,9],[5,10,1],[2,8,3],[3,11,2],[2,5,4],[4,8,2],[2,11,5],[3,7,6],[6,11,3],[8,7,3],[9,8,4],[11,10,5],[10,11,6],[8,9,7]],geodesicSubDivide=(p,frequency,offset)=>{const p1=p[0],p2=p[1],p3=p[2];let n=offset;const c=[],f=[];for(let i=0;i<frequency;i++)for(let j=0;j<frequency-i;j++){const t0=i/frequency,t1=(i+1)/frequency,s0=j/(frequency-i),s1=(j+1)/(frequency-i),s2=frequency-i-1?j/(frequency-i-1):1,q=[];q[0]=mix3(mix3(p1,p2,s0),p3,t0),q[1]=mix3(mix3(p1,p2,s1),p3,t0),q[2]=mix3(mix3(p1,p2,s2),p3,t1);for(let k=0;k<3;k++){const r=length$2(q[k]);for(let l=0;l<3;l++)q[k][l]/=r}if(c.push(q[0],q[1],q[2]),f.push([n,n+1,n+2]),n+=3,j<frequency-i-1){const s3=frequency-i-1?(j+1)/(frequency-i-1):1;q[0]=mix3(mix3(p1,p2,s1),p3,t0),q[1]=mix3(mix3(p1,p2,s3),p3,t1),q[2]=mix3(mix3(p1,p2,s2),p3,t1);for(let k=0;k<3;k++){const r=length$2(q[k]);for(let l=0;l<3;l++)q[k][l]/=r}c.push(q[0],q[1],q[2]),f.push([n,n+1,n+2]),n+=3}}return{vertices:c,triangles:f,offset:n}},mix3=(a,b,f)=>{const _f=1-f,c=[];for(let i=0;i<3;i++)c[i]=a[i]*_f+b[i]*f;return c};let vertices=[],faces=[],offset=0;for(let i=0;i<ti.length;i++){const g=geodesicSubDivide([ci[ti[i][0]],ci[ti[i][1]],ci[ti[i][2]]],frequency,offset);vertices=vertices.concat(g.vertices),faces=faces.concat(g.triangles),offset=g.offset}let geometry=polyhedron({points:vertices,faces:faces,orientation:"inward"});return 1!==radius&&(geometry=transform$6(fromScaling([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],[radius,radius,radius]),geometry)),geometry},line:points=>{if(!Array.isArray(points))throw new Error("points must be an array");return fromPoints$2({},points)},polygon:options=>{const{points:points,paths:paths,orientation:orientation}=Object.assign({},{points:[],paths:[],orientation:"counterclockwise"},options);if(!Array.isArray(points)||!Array.isArray(paths))throw new Error("points and paths must be arrays");let listOfPolys=points;Array.isArray(points[0])&&(Array.isArray(points[0][0])||(listOfPolys=[points])),listOfPolys.forEach(((list,i)=>{if(!Array.isArray(list))throw new Error("list of points "+i+" must be an array");if(list.length<3)throw new Error("list of points "+i+" must contain three or more points");list.forEach(((point,j)=>{if(!Array.isArray(point))throw new Error("list of points "+i+", point "+j+" must be an array");if(point.length<2)throw new Error("list of points "+i+", point "+j+" must contain by X and Y values")}))}));let listOfPaths=paths;if(0===paths.length){let count=0;listOfPaths=listOfPolys.map((list=>list.map((point=>count++))))}const allPoints=[];listOfPolys.forEach((list=>list.forEach((point=>allPoints.push(point)))));const outlines=[];listOfPaths.forEach((path=>{const setOfPoints=path.map((index=>allPoints[index]));outlines.push(setOfPoints)}));let geometry=create$a(outlines);return"clockwise"===orientation&&(geometry=reverse$5(geometry)),geometry},polyhedron:polyhedron,rectangle:rectangle,roundedCuboid:options=>{let{center:center,size:size,roundRadius:roundRadius,segments:segments}=Object.assign({},{center:[0,0,0],size:[2,2,2],roundRadius:.2,segments:32},options);if(!isNumberArray(center,3))throw new Error("center must be an array of X, Y and Z values");if(!isNumberArray(size,3))throw new Error("size must be an array of X, Y and Z values");if(!size.every((n=>n>=0)))throw new Error("size values must be positive");if(!isGTE(roundRadius,0))throw new Error("roundRadius must be positive");if(!isGTE(segments,4))throw new Error("segments must be four or more");if(0===size[0]||0===size[1]||0===size[2])return create$8();if(0===roundRadius)return cuboid({center:center,size:size});if(size=size.map((v=>v/2)),roundRadius>size[0]-EPS||roundRadius>size[1]-EPS||roundRadius>size[2]-EPS)throw new Error("roundRadius must be smaller than the radius of all dimensions");segments=Math.floor(segments/4);let prevCornersPos=null,prevCornersNeg=null,polygons=[];for(let slice=0;slice<=segments;slice++){const cornersPos=createCorners(center,size,roundRadius,segments,slice,!0),cornersNeg=createCorners(center,size,roundRadius,segments,slice,!1);if(0===slice&&(polygons=polygons.concat(stitchSides(cornersNeg,cornersPos))),prevCornersPos&&(polygons=polygons.concat(stitchCorners(prevCornersPos,cornersPos),stitchWalls(prevCornersPos,cornersPos))),prevCornersNeg&&(polygons=polygons.concat(stitchCorners(prevCornersNeg,cornersNeg),stitchWalls(prevCornersNeg,cornersNeg))),slice===segments){let vertices=cornersPos.map((corner=>corner[0]));polygons.push(create$7(vertices)),vertices=cornersNeg.map((corner=>corner[0])),polygons.push(create$7(vertices))}prevCornersPos=cornersPos,prevCornersNeg=cornersNeg}return create$8(polygons)},roundedCylinder:options=>{const{center:center,height:height,radius:radius,roundRadius:roundRadius,segments:segments}=Object.assign({},{center:[0,0,0],height:2,radius:1,roundRadius:.2,segments:32},options);if(!isNumberArray(center,3))throw new Error("center must be an array of X, Y and Z values");if(!isGTE(height,0))throw new Error("height must be positive");if(!isGTE(radius,0))throw new Error("radius must be positive");if(!isGTE(roundRadius,0))throw new Error("roundRadius must be positive");if(roundRadius>radius)throw new Error("roundRadius must be smaller than the radius");if(!isGTE(segments,4))throw new Error("segments must be four or more");if(0===height||0===radius)return create$8();if(0===roundRadius)return cylinder({center:center,height:height,radius:radius});const start=[0,0,-height/2],end=[0,0,height/2],direction=subtract$3([0,0,0],end,start);if(2*roundRadius>length$2(direction)-EPS)throw new Error("height must be larger than twice roundRadius");let defaultNormal;defaultNormal=Math.abs(direction[0])>Math.abs(direction[1])?fromValues$3(0,1,0):fromValues$3(1,0,0);const zVector=scale$3([0,0,0],normalize$1([0,0,0],direction),roundRadius),xVector=scale$3([0,0,0],normalize$1([0,0,0],cross$1([0,0,0],zVector,defaultNormal)),radius),yVector=scale$3([0,0,0],normalize$1([0,0,0],cross$1([0,0,0],xVector,zVector)),radius);add$1(start,start,zVector),subtract$3(end,end,zVector);const qSegments=Math.floor(.25*segments),fromVertices=vertices=>{const newVertices=vertices.map((vertex=>add$1(vertex,vertex,center)));return create$7(newVertices)},polygons=[],v1=[0,0,0],v2=[0,0,0];let prevCylinderVertex;for(let slice1=0;slice1<=segments;slice1++){const angle=TAU*slice1/segments,cylinderVertex=add$1([0,0,0],scale$3(v1,xVector,cos(angle)),scale$3(v2,yVector,sin(angle)));if(slice1>0){let prevCosPitch,prevSinPitch,vertex,vertices=[];vertices.push(add$1([0,0,0],start,cylinderVertex)),vertices.push(add$1([0,0,0],start,prevCylinderVertex)),vertices.push(add$1([0,0,0],end,prevCylinderVertex)),vertices.push(add$1([0,0,0],end,cylinderVertex)),polygons.push(fromVertices(vertices));for(let slice2=0;slice2<=qSegments;slice2++){const pitch=TAU/4*slice2/qSegments,cosPitch=cos(pitch),sinPitch=sin(pitch);slice2>0&&(vertices=[],vertex=add$1([0,0,0],start,subtract$3(v1,scale$3(v1,prevCylinderVertex,prevCosPitch),scale$3(v2,zVector,prevSinPitch))),vertices.push(vertex),vertex=add$1([0,0,0],start,subtract$3(v1,scale$3(v1,cylinderVertex,prevCosPitch),scale$3(v2,zVector,prevSinPitch))),vertices.push(vertex),slice2<qSegments&&(vertex=add$1([0,0,0],start,subtract$3(v1,scale$3(v1,cylinderVertex,cosPitch),scale$3(v2,zVector,sinPitch))),vertices.push(vertex)),vertex=add$1([0,0,0],start,subtract$3(v1,scale$3(v1,prevCylinderVertex,cosPitch),scale$3(v2,zVector,sinPitch))),vertices.push(vertex),polygons.push(fromVertices(vertices)),vertices=[],vertex=add$1([0,0,0],scale$3(v1,prevCylinderVertex,prevCosPitch),scale$3(v2,zVector,prevSinPitch)),add$1(vertex,vertex,end),vertices.push(vertex),vertex=add$1([0,0,0],scale$3(v1,cylinderVertex,prevCosPitch),scale$3(v2,zVector,prevSinPitch)),add$1(vertex,vertex,end),vertices.push(vertex),slice2<qSegments&&(vertex=add$1([0,0,0],scale$3(v1,cylinderVertex,cosPitch),scale$3(v2,zVector,sinPitch)),add$1(vertex,vertex,end),vertices.push(vertex)),vertex=add$1([0,0,0],scale$3(v1,prevCylinderVertex,cosPitch),scale$3(v2,zVector,sinPitch)),add$1(vertex,vertex,end),vertices.push(vertex),vertices.reverse(),polygons.push(fromVertices(vertices))),prevCosPitch=cosPitch,prevSinPitch=sinPitch}}prevCylinderVertex=cylinderVertex}return create$8(polygons)},roundedRectangle:options=>{let{center:center,size:size,roundRadius:roundRadius,segments:segments}=Object.assign({},{center:[0,0],size:[2,2],roundRadius:.2,segments:32},options);if(!isNumberArray(center,2))throw new Error("center must be an array of X and Y values");if(!isNumberArray(size,2))throw new Error("size must be an array of X and Y values");if(!size.every((n=>n>=0)))throw new Error("size values must be positive");if(!isGTE(roundRadius,0))throw new Error("roundRadius must be positive");if(!isGTE(segments,4))throw new Error("segments must be four or more");if(0===size[0]||0===size[1])return create$a();if(0===roundRadius)return rectangle({center:center,size:size});if(size=size.map((v=>v/2)),roundRadius>size[0]-EPS||roundRadius>size[1]-EPS)throw new Error("roundRadius must be smaller than the radius of all dimensions");const cornerSegments=Math.floor(segments/4),corner0=add([0,0],center,[size[0]-roundRadius,size[1]-roundRadius]),corner1=add([0,0],center,[roundRadius-size[0],size[1]-roundRadius]),corner2=add([0,0],center,[roundRadius-size[0],roundRadius-size[1]]),corner3=add([0,0],center,[size[0]-roundRadius,roundRadius-size[1]]),corner0Points=[],corner1Points=[],corner2Points=[],corner3Points=[];for(let i=0;i<=cornerSegments;i++){const point=fromAngleRadians([0,0],TAU/4*i/cornerSegments);scale$1(point,point,roundRadius),corner0Points.push(add([0,0],corner0,point)),rotate$1(point,point,[0,0],TAU/4),corner1Points.push(add([0,0],corner1,point)),rotate$1(point,point,[0,0],TAU/4),corner2Points.push(add([0,0],corner2,point)),rotate$1(point,point,[0,0],TAU/4),corner3Points.push(add([0,0],corner3,point))}const points=corner0Points.concat(corner1Points,corner2Points,corner3Points);return create$a([points])},sphere:sphere,square:options=>{let{center:center,size:size}=Object.assign({},{center:[0,0],size:2},options);if(!isGTE(size,0))throw new Error("size must be positive");return size=[size,size],rectangle({center:center,size:size})},star:options=>{let{center:center,vertices:vertices,outerRadius:outerRadius,innerRadius:innerRadius,density:density,startAngle:startAngle}=Object.assign({},{center:[0,0],vertices:5,outerRadius:1,innerRadius:0,density:2,startAngle:0},options);if(!isNumberArray(center,2))throw new Error("center must be an array of X and Y values");if(!isGTE(vertices,2))throw new Error("vertices must be two or more");if(!isGT(outerRadius,0))throw new Error("outerRadius must be greater than zero");if(!isGTE(innerRadius,0))throw new Error("innerRadius must be greater than zero");if(!isGTE(startAngle,0))throw new Error("startAngle must be greater than zero");if(vertices=Math.floor(vertices),density=Math.floor(density),startAngle%=TAU,0===innerRadius){if(!isGTE(density,2))throw new Error("density must be two or more");innerRadius=outerRadius*((vertices,density)=>vertices>0&&density>1&&density<vertices/2?Math.cos(Math.PI*density/vertices)/Math.cos(Math.PI*(density-1)/vertices):0)(vertices,density)}const centerV=clone$8(center),outerPoints=getPoints(vertices,outerRadius,startAngle,centerV),innerPoints=getPoints(vertices,innerRadius,startAngle+Math.PI/vertices,centerV),allPoints=[];for(let i=0;i<vertices;i++)allPoints.push(outerPoints[i]),allPoints.push(innerPoints[i]);return create$a([allPoints])},torus:options=>{const defaults={innerRadius:1,innerSegments:32,outerRadius:4,outerSegments:32,innerRotation:0,startAngle:0,outerRotation:TAU},{innerRadius:innerRadius,innerSegments:innerSegments,outerRadius:outerRadius,outerSegments:outerSegments,innerRotation:innerRotation,startAngle:startAngle,outerRotation:outerRotation}=Object.assign({},defaults,options);if(!isGT(innerRadius,0))throw new Error("innerRadius must be greater than zero");if(!isGTE(innerSegments,3))throw new Error("innerSegments must be three or more");if(!isGT(outerRadius,0))throw new Error("outerRadius must be greater than zero");if(!isGTE(outerSegments,3))throw new Error("outerSegments must be three or more");if(!isGTE(startAngle,0))throw new Error("startAngle must be positive");if(!isGT(outerRotation,0))throw new Error("outerRotation must be greater than zero");if(innerRadius>=outerRadius)throw new Error("inner circle is too large to rotate about the outer circle");let innerCircle=circle({radius:innerRadius,segments:innerSegments});return 0!==innerRotation&&(innerCircle=rotate([0,0,innerRotation],innerCircle)),innerCircle=translate([outerRadius,0],innerCircle),extrudeRotate({startAngle:startAngle,angle:outerRotation,segments:outerSegments},innerCircle)},triangle:options=>{let{type:type,values:values}=Object.assign({},{type:"SSS",values:[1,1,1]},options);if("string"!=typeof type)throw new Error("triangle type must be a string");if(type=type.toUpperCase(),"A"!==type[0]&&"S"!==type[0]||"A"!==type[1]&&"S"!==type[1]||"A"!==type[2]&&"S"!==type[2])throw new Error("triangle type must contain three letters; A or S");if(!isNumberArray(values,3))throw new Error("triangle values must contain three values");if(!values.every((n=>n>0)))throw new Error("triangle values must be greater than zero");switch(type){case"AAA":return(angles=>{if(Math.abs(angles[0]+angles[1]+angles[2]-Math.PI)>NEPS)throw new Error("AAA triangles require angles that sum to PI");const A=angles[0],B=angles[1],C=Math.PI-A-B,a=1/Math.sin(C)*Math.sin(A),b=1/Math.sin(C)*Math.sin(B);return createTriangle(A,B,C,a,b,1)})(values);case"AAS":return(values=>{const A=values[0],B=values[1],C=Math.PI+NEPS-A-B;if(C<NEPS)throw new Error("AAS triangles require angles that sum to PI");const a=values[2],b=a/Math.sin(A)*Math.sin(B),c=a/Math.sin(A)*Math.sin(C);return createTriangle(A,B,C,a,b,c)})(values);case"ASA":return(values=>{const A=values[0],B=values[2],C=Math.PI+NEPS-A-B;if(C<NEPS)throw new Error("ASA triangles require angles that sum to PI");const c=values[1],a=c/Math.sin(C)*Math.sin(A),b=c/Math.sin(C)*Math.sin(B);return createTriangle(A,B,C,a,b,c)})(values);case"SAS":return(values=>{const c=values[0],B=values[1],a=values[2],b=((a,C,b)=>C>NEPS?Math.sqrt(a*a+b*b-2*a*b*Math.cos(C)):Math.sqrt((a-b)*(a-b)+a*b*C*C*(1-C*C/12)))(c,B,a),A=solveAngleFromSSS(b,c,a),C=Math.PI-A-B;return createTriangle(A,B,C,a,b,c)})(values);case"SSA":return(values=>{const c=values[0],a=values[1],C=values[2],A=Math.asin(a*Math.sin(C)/c),B=Math.PI-A-C,b=c/Math.sin(C)*Math.sin(B);return createTriangle(A,B,C,a,b,c)})(values);case"SSS":return(lengths=>{const a=lengths[1],b=lengths[2],c=lengths[0];if(a+b<=c||b+c<=a||c+a<=b)throw new Error("SSS triangle is incorrect, as the longest side is longer than the sum of the other sides");const A=solveAngleFromSSS(b,c,a),B=solveAngleFromSSS(c,a,b),C=Math.PI-A-B;return createTriangle(A,B,C,a,b,c)})(values);default:throw new Error("invalid triangle type, try again")}}});const simplex={height:14,32:[16],33:[10,5,21,5,7,void 0,5,2,4,1,5,0,6,1,5,2],34:[16,4,21,4,14,void 0,12,21,12,14],35:[21,11,25,4,-7,void 0,17,25,10,-7,void 0,4,12,18,12,void 0,3,6,17,6],36:[20,8,25,8,-4,void 0,12,25,12,-4,void 0,17,18,15,20,12,21,8,21,5,20,3,18,3,16,4,14,5,13,7,12,13,10,15,9,16,8,17,6,17,3,15,1,12,0,8,0,5,1,3,3],37:[24,21,21,3,0,void 0,8,21,10,19,10,17,9,15,7,14,5,14,3,16,3,18,4,20,6,21,8,21,10,20,13,19,16,19,19,20,21,21,void 0,17,7,15,6,14,4,14,2,16,0,18,0,20,1,21,3,21,5,19,7,17,7],38:[26,23,12,23,13,22,14,21,14,20,13,19,11,17,6,15,3,13,1,11,0,7,0,5,1,4,2,3,4,3,6,4,8,5,9,12,13,13,14,14,16,14,18,13,20,11,21,9,20,8,18,8,16,9,13,11,10,16,3,18,1,20,0,22,0,23,1,23,2],39:[10,5,19,4,20,5,21,6,20,6,18,5,16,4,15],40:[14,11,25,9,23,7,20,5,16,4,11,4,7,5,2,7,-2,9,-5,11,-7],41:[14,3,25,5,23,7,20,9,16,10,11,10,7,9,2,7,-2,5,-5,3,-7],42:[16,8,21,8,9,void 0,3,18,13,12,void 0,13,18,3,12],43:[26,13,18,13,0,void 0,4,9,22,9],44:[10,6,1,5,0,4,1,5,2,6,1,6,-1,5,-3,4,-4],45:[26,4,9,22,9],46:[10,5,2,4,1,5,0,6,1,5,2],47:[22,20,25,2,-7],48:[20,9,21,6,20,4,17,3,12,3,9,4,4,6,1,9,0,11,0,14,1,16,4,17,9,17,12,16,17,14,20,11,21,9,21],49:[20,6,17,8,18,11,21,11,0],50:[20,4,16,4,17,5,19,6,20,8,21,12,21,14,20,15,19,16,17,16,15,15,13,13,10,3,0,17,0],51:[20,5,21,16,21,10,13,13,13,15,12,16,11,17,8,17,6,16,3,14,1,11,0,8,0,5,1,4,2,3,4],52:[20,13,21,3,7,18,7,void 0,13,21,13,0],53:[20,15,21,5,21,4,12,5,13,8,14,11,14,14,13,16,11,17,8,17,6,16,3,14,1,11,0,8,0,5,1,4,2,3,4],54:[20,16,18,15,20,12,21,10,21,7,20,5,17,4,12,4,7,5,3,7,1,10,0,11,0,14,1,16,3,17,6,17,7,16,10,14,12,11,13,10,13,7,12,5,10,4,7],55:[20,17,21,7,0,void 0,3,21,17,21],56:[20,8,21,5,20,4,18,4,16,5,14,7,13,11,12,14,11,16,9,17,7,17,4,16,2,15,1,12,0,8,0,5,1,4,2,3,4,3,7,4,9,6,11,9,12,13,13,15,14,16,16,16,18,15,20,12,21,8,21],57:[20,16,14,15,11,13,9,10,8,9,8,6,9,4,11,3,14,3,15,4,18,6,20,9,21,10,21,13,20,15,18,16,14,16,9,15,4,13,1,10,0,8,0,5,1,4,3],58:[10,5,14,4,13,5,12,6,13,5,14,void 0,5,2,4,1,5,0,6,1,5,2],59:[10,5,14,4,13,5,12,6,13,5,14,void 0,6,1,5,0,4,1,5,2,6,1,6,-1,5,-3,4,-4],60:[24,20,18,4,9,20,0],61:[26,4,12,22,12,void 0,4,6,22,6],62:[24,4,18,20,9,4,0],63:[18,3,16,3,17,4,19,5,20,7,21,11,21,13,20,14,19,15,17,15,15,14,13,13,12,9,10,9,7,void 0,9,2,8,1,9,0,10,1,9,2],64:[27,18,13,17,15,15,16,12,16,10,15,9,14,8,11,8,8,9,6,11,5,14,5,16,6,17,8,void 0,12,16,10,14,9,11,9,8,10,6,11,5,void 0,18,16,17,8,17,6,19,5,21,5,23,7,24,10,24,12,23,15,22,17,20,19,18,20,15,21,12,21,9,20,7,19,5,17,4,15,3,12,3,9,4,6,5,4,7,2,9,1,12,0,15,0,18,1,20,2,21,3,void 0,19,16,18,8,18,6,19,5],65:[18,9,21,1,0,void 0,9,21,17,0,void 0,4,7,14,7],66:[21,4,21,4,0,void 0,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,void 0,4,11,13,11,16,10,17,9,18,7,18,4,17,2,16,1,13,0,4,0],67:[21,18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5],68:[21,4,21,4,0,void 0,4,21,11,21,14,20,16,18,17,16,18,13,18,8,17,5,16,3,14,1,11,0,4,0],69:[19,4,21,4,0,void 0,4,21,17,21,void 0,4,11,12,11,void 0,4,0,17,0],70:[18,4,21,4,0,void 0,4,21,17,21,void 0,4,11,12,11],71:[21,18,16,17,18,15,20,13,21,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,18,8,void 0,13,8,18,8],72:[22,4,21,4,0,void 0,18,21,18,0,void 0,4,11,18,11],73:[8,4,21,4,0],74:[16,12,21,12,5,11,2,10,1,8,0,6,0,4,1,3,2,2,5,2,7],75:[21,4,21,4,0,void 0,18,21,4,7,void 0,9,12,18,0],76:[17,4,21,4,0,void 0,4,0,16,0],77:[24,4,21,4,0,void 0,4,21,12,0,void 0,20,21,12,0,void 0,20,21,20,0],78:[22,4,21,4,0,void 0,4,21,18,0,void 0,18,21,18,0],79:[22,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21],80:[21,4,21,4,0,void 0,4,21,13,21,16,20,17,19,18,17,18,14,17,12,16,11,13,10,4,10],81:[22,9,21,7,20,5,18,4,16,3,13,3,8,4,5,5,3,7,1,9,0,13,0,15,1,17,3,18,5,19,8,19,13,18,16,17,18,15,20,13,21,9,21,void 0,12,4,18,-2],82:[21,4,21,4,0,void 0,4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13,11,4,11,void 0,11,11,18,0],83:[20,17,18,15,20,12,21,8,21,5,20,3,18,3,16,4,14,5,13,7,12,13,10,15,9,16,8,17,6,17,3,15,1,12,0,8,0,5,1,3,3],84:[16,8,21,8,0,void 0,1,21,15,21],85:[22,4,21,4,6,5,3,7,1,10,0,12,0,15,1,17,3,18,6,18,21],86:[18,1,21,9,0,void 0,17,21,9,0],87:[24,2,21,7,0,void 0,12,21,7,0,void 0,12,21,17,0,void 0,22,21,17,0],88:[20,3,21,17,0,void 0,17,21,3,0],89:[18,1,21,9,11,9,0,void 0,17,21,9,11],90:[20,17,21,3,0,void 0,3,21,17,21,void 0,3,0,17,0],91:[14,4,25,4,-7,void 0,5,25,5,-7,void 0,4,25,11,25,void 0,4,-7,11,-7],92:[14,0,21,14,-3],93:[14,9,25,9,-7,void 0,10,25,10,-7,void 0,3,25,10,25,void 0,3,-7,10,-7],94:[16,6,15,8,18,10,15,void 0,3,12,8,17,13,12,void 0,8,17,8,0],95:[16,0,-2,16,-2],96:[10,6,21,5,20,4,18,4,16,5,15,6,16,5,17],97:[19,15,14,15,0,void 0,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3],98:[19,4,21,4,0,void 0,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3],99:[18,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3],100:[19,15,21,15,0,void 0,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3],101:[18,3,8,15,8,15,10,14,12,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3],102:[12,10,21,8,21,6,20,5,17,5,0,void 0,2,14,9,14],103:[19,15,14,15,-2,14,-5,13,-6,11,-7,8,-7,6,-6,void 0,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3],104:[19,4,21,4,0,void 0,4,10,7,13,9,14,12,14,14,13,15,10,15,0],105:[8,3,21,4,20,5,21,4,22,3,21,void 0,4,14,4,0],106:[10,5,21,6,20,7,21,6,22,5,21,void 0,6,14,6,-3,5,-6,3,-7,1,-7],107:[17,4,21,4,0,void 0,14,14,4,4,void 0,8,8,15,0],108:[8,4,21,4,0],109:[30,4,14,4,0,void 0,4,10,7,13,9,14,12,14,14,13,15,10,15,0,void 0,15,10,18,13,20,14,23,14,25,13,26,10,26,0],110:[19,4,14,4,0,void 0,4,10,7,13,9,14,12,14,14,13,15,10,15,0],111:[19,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3,16,6,16,8,15,11,13,13,11,14,8,14],112:[19,4,14,4,-7,void 0,4,11,6,13,8,14,11,14,13,13,15,11,16,8,16,6,15,3,13,1,11,0,8,0,6,1,4,3],113:[19,15,14,15,-7,void 0,15,11,13,13,11,14,8,14,6,13,4,11,3,8,3,6,4,3,6,1,8,0,11,0,13,1,15,3],114:[13,4,14,4,0,void 0,4,8,5,11,7,13,9,14,12,14],115:[17,14,11,13,13,10,14,7,14,4,13,3,11,4,9,6,8,11,7,13,6,14,4,14,3,13,1,10,0,7,0,4,1,3,3],116:[12,5,21,5,4,6,1,8,0,10,0,void 0,2,14,9,14],117:[19,4,14,4,4,5,1,7,0,10,0,12,1,15,4,void 0,15,14,15,0],118:[16,2,14,8,0,void 0,14,14,8,0],119:[22,3,14,7,0,void 0,11,14,7,0,void 0,11,14,15,0,void 0,19,14,15,0],120:[17,3,14,14,0,void 0,14,14,3,0],121:[16,2,14,8,0,void 0,14,14,8,0,6,-4,4,-6,2,-7,1,-7],122:[17,14,14,3,0,void 0,3,14,14,14,void 0,3,0,14,0],123:[14,9,25,7,24,6,23,5,21,5,19,6,17,7,16,8,14,8,12,6,10,void 0,7,24,6,22,6,20,7,18,8,17,9,15,9,13,8,11,4,9,8,7,9,5,9,3,8,1,7,0,6,-2,6,-4,7,-6,void 0,6,8,8,6,8,4,7,2,6,1,5,-1,5,-3,6,-5,7,-6,9,-7],124:[8,4,25,4,-7],125:[14,5,25,7,24,8,23,9,21,9,19,8,17,7,16,6,14,6,12,8,10,void 0,7,24,8,22,8,20,7,18,6,17,5,15,5,13,6,11,10,9,6,7,5,5,5,3,6,1,7,0,8,-2,8,-4,7,-6,void 0,8,8,6,6,6,4,7,2,8,1,9,-1,9,-3,8,-5,7,-6,5,-7],126:[24,3,6,3,8,4,11,6,12,8,12,10,11,14,8,16,7,18,7,20,8,21,10,void 0,3,8,4,10,6,11,8,11,10,10,14,7,16,6,18,6,20,7,21,10,21,12]},defaultsVectorParams$1={xOffset:0,yOffset:0,font:simplex,height:14,extrudeOffset:0},vectorChar=(options,text)=>{const{xOffset:xOffset,yOffset:yOffset,font:font,height:height,extrudeOffset:extrudeOffset}=Object.assign({},defaultsVectorParams$1,options);if("string"!=typeof text||1!==text.length)throw new Error("text must be a single character");let code=text.charCodeAt(0);code&&font[code]||(code=63);const glyph=[].concat(font[code]),ratio=(height-extrudeOffset)/font.height,extrudeYOffset=extrudeOffset/2,width=glyph.shift()*ratio,paths=[];let polyline=[];for(let i=0,il=glyph.length;i<il;i+=2){const gx=ratio*glyph[i]+xOffset,gy=ratio*glyph[i+1]+yOffset+extrudeYOffset;void 0===glyph[i]?(paths.push(fromPoints$2({},polyline)),polyline=[],i--):polyline.push(fromValues$2(gx,gy))}return polyline.length&&paths.push(fromPoints$2({},polyline)),{width:width,height:height,paths:paths}},defaultsVectorParams={xOffset:0,yOffset:0,align:"left",font:simplex,height:14,lineSpacing:30/14,letterSpacing:0,extrudeOffset:0},matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],translateLine=(options,line)=>{const{x:x,y:y}=Object.assign({x:0,y:0},options);return identity(matrix),translate$1(matrix,matrix,[x,y,0]),line.chars=line.chars.map((vchar=>(vchar.paths=vchar.paths.map((path=>transform$5(matrix,path))),vchar))),line};Object.freeze({__proto__:null,vectorChar:vectorChar,vectorText:(options,text)=>{const{xOffset:xOffset,yOffset:yOffset,font:font,height:height,align:align,extrudeOffset:extrudeOffset,lineSpacing:lineSpacing,letterSpacing:letterSpacing}=Object.assign({},defaultsVectorParams,options);if("string"!=typeof text)throw new Error("text must be a string");const extraLetterSpacing=height*letterSpacing;let maxWidth=0,line={width:0,height:0,chars:[]},lines=[];const pushLine=()=>{maxWidth=Math.max(maxWidth,line.width),line.chars.length&&lines.push(line),line={width:0,height:0,chars:[]}};let vchar,x=xOffset,y=yOffset;const il=text.length;for(let i=0;i<il;i++){const character=text[i];if("\n"===character){pushLine(),x=xOffset,y-=height*lineSpacing;continue}vchar=vectorChar({xOffset:x,yOffset:y,font:font,height:height,extrudeOffset:extrudeOffset},character);const width=vchar.width+extraLetterSpacing;x+=width,line.width+=width,line.height=Math.max(line.height,vchar.height)," "!==character&&(line.chars=line.chars.concat(vchar))}return line.chars.length&&pushLine(),lines=lines.map((line=>{const diff=maxWidth-line.width;return"right"===align?translateLine({x:diff},line):"center"===align?translateLine({x:diff/2},line):line})),lines}}),Object.freeze({__proto__:null,degToRad:degrees=>.017453292519943295*degrees,flatten:flatten,radiusToSegments:(radius,minimumLength,minimumAngle)=>{const ss=minimumLength>0?radius*TAU/minimumLength:0,as=minimumAngle>0?TAU/minimumAngle:0;return Math.ceil(Math.max(ss,as,4))},radToDeg:radians=>57.29577951308232*radians});const areAllShapesTheSameType=shapes=>{let previousType;for(const shape of shapes){let currentType=0;if(isA$5(shape)&&(currentType=1),isA$3(shape)&&(currentType=2),isA$2(shape)&&(currentType=3),previousType&&currentType!==previousType)return!1;previousType=currentType}return!0},coalesce=arr=>flattenHelper(arr,[]),flattenHelper=(arr,out)=>(Array.isArray(arr)?arr.forEach((child=>flattenHelper(child,out))):null!=arr&&void 0!==arr&&out.push(arr),out),DEFAULT_COMPARE=(a,b)=>a>b?1:a<b?-1:0;class Node$1{constructor(key,data){this.key=key,this.data=data,this.left=null,this.right=null,this.next=null}}const splay=(key,t,comparator)=>{const N=new Node$1(null,null);let left=N,right=N;for(;;){const cmp=comparator(key,t.key);if(cmp<0){if(null===t.left)break;if(comparator(key,t.left.key)<0){const y=t.left;if(t.left=y.right,y.right=t,null===(t=y).left)break}right.left=t,right=t,t=t.left}else{if(!(cmp>0))break;if(null===t.right)break;if(comparator(key,t.right.key)>0){const y=t.right;if(t.right=y.left,y.left=t,null===(t=y).right)break}left.right=t,left=t,t=t.right}}return left.right=t.left,right.left=t.right,t.left=N.right,t.right=N.left,t};class Tree$1{constructor(comparator=DEFAULT_COMPARE){this.comparator=comparator,this._root=null}insert(key,data){return this._root=((key,data,root,comparator)=>{const node=new Node$1(key,data);if(null===root)return node;const cmp=comparator(key,(root=splay(key,root,comparator)).key);return cmp<0?(node.left=root.left,node.right=root,root.left=null):cmp>=0&&(node.right=root.right,node.left=root,root.right=null),node})(key,data,this._root,this.comparator),this._root}remove(key){this._root=this._remove(key)}_remove(key){if(null===this._root)return null;let x;const t=splay(key,this._root,this.comparator);return 0===this.comparator(key,t.key)?(null===t.left?x=t.right:(x=splay(key,t.left,this.comparator),x.right=t.right),x):t}find(key){return this._root&&(this._root=splay(key,this._root,this.comparator),0!==this.comparator(key,this._root.key))?null:this._root}minNode(t=this._root){if(t)for(;t.left;)t=t.left;return t}maxNode(t=this._root){if(t)for(;t.right;)t=t.right;return t}next(node){let successor=null;if(node.right){for(successor=node.right;successor.left;)successor=successor.left;return successor}let root=this._root;for(;root;){const cmp=this.comparator(node.key,root.key);if(0===cmp)break;cmp<0?(successor=root,root=root.left):root=root.right}return successor}prev(node){let predecessor=null;if(node.left){for(predecessor=node.left;predecessor.right;)predecessor=predecessor.right;return predecessor}let root=this._root;for(;root;){const cmp=this.comparator(node.key,root.key);if(0===cmp)break;cmp<0?root=root.left:(predecessor=root,root=root.right)}return predecessor}}const computeFields=(event,prev,operation)=>{null===prev?(event.inOut=!1,event.otherInOut=!0):(event.isSubject===prev.isSubject?(event.inOut=!prev.inOut,event.otherInOut=prev.otherInOut):(event.inOut=!prev.otherInOut,event.otherInOut=prev.isVertical()?!prev.inOut:prev.inOut),prev&&(event.prevInResult=!inResult(prev,operation)||prev.isVertical()?prev.prevInResult:prev));const isInResult=inResult(event,operation);event.resultTransition=isInResult?determineResultTransition(event,operation):0},inResult=(event,operation)=>{switch(event.type){case 0:switch(operation){case 0:return!event.otherInOut;case 1:return event.otherInOut;case 2:return event.isSubject&&event.otherInOut||!event.isSubject&&!event.otherInOut;case 3:return!0}break;case 2:return 0===operation||1===operation;case 3:return 2===operation;case 1:return!1}return!1},determineResultTransition=(event,operation)=>{const thisIn=!event.inOut,thatIn=!event.otherInOut;let isIn;switch(operation){case 0:isIn=thisIn&&thatIn;break;case 1:isIn=thisIn||thatIn;break;case 3:isIn=thisIn^thatIn;break;case 2:isIn=event.isSubject?thisIn&&!thatIn:thatIn&&!thisIn}return isIn?1:-1};class SweepEvent{constructor(point,left,otherEvent,isSubject,type=0){this.left=left,this.point=point,this.otherEvent=otherEvent,this.isSubject=isSubject,this.type=type,this.inOut=!1,this.otherInOut=!1,this.prevInResult=null,this.resultTransition=0,this.otherPos=-1,this.outputContourId=-1,this.isExteriorRing=!0}isBelow(p){const p0=this.point,p1=this.otherEvent.point;return this.left?(p0[0]-p[0])*(p1[1]-p[1])-(p1[0]-p[0])*(p0[1]-p[1])>0:(p1[0]-p[0])*(p0[1]-p[1])-(p0[0]-p[0])*(p1[1]-p[1])>0}isAbove(p){return!this.isBelow(p)}isVertical(){return this.point[0]===this.otherEvent.point[0]}get inResult(){return 0!==this.resultTransition}}const signedArea=(p0,p1,p2)=>{const res=(ax=p0[0],ay=p0[1],bx=p1[0],by=p1[1],cx=p2[0],(ay-(cy=p2[1]))*(bx-cx)-(ax-cx)*(by-cy));var ax,ay,bx,by,cx,cy;return res>0?-1:res<0?1:0},compareEvents=(e1,e2)=>{const p1=e1.point,p2=e2.point;return p1[0]>p2[0]?1:p1[0]<p2[0]?-1:p1[1]!==p2[1]?p1[1]>p2[1]?1:-1:e1.left!==e2.left?e1.left?1:-1:0!==signedArea(p1,e1.otherEvent.point,e2.otherEvent.point)?e1.isBelow(e2.otherEvent.point)?-1:1:!e1.isSubject&&e2.isSubject?1:-1},divideSegment=(segment,point,queue)=>{const r=new SweepEvent(point,!1,segment,segment.isSubject),l=new SweepEvent(point,!0,segment.otherEvent,segment.isSubject);return r.contourId=l.contourId=segment.contourId,compareEvents(l,segment.otherEvent)>0&&(segment.otherEvent.left=!0,l.left=!1),segment.otherEvent.otherEvent=l,segment.otherEvent=r,queue.push(l),queue.push(r),queue},crossProduct=(a,b)=>a[0]*b[1]-a[1]*b[0],possibleIntersection=(se1,se2,queue)=>{const inter=((a1,a2,b1,b2,noEndpointTouch=!1)=>{const va=[a2[0]-a1[0],a2[1]-a1[1]],vb=[b2[0]-b1[0],b2[1]-b1[1]],toPoint=(p,s,d)=>[p[0]+s*d[0],p[1]+s*d[1]],v1=[b1[0]-a1[0],b1[1]-a1[1]];let kross=crossProduct(va,vb),sqrKross=kross*kross;if(sqrKross>0){const s=crossProduct(v1,vb)/kross;if(s<0||s>1)return null;const t=crossProduct(v1,va)/kross;return t<0||t>1?null:0===s||1===s?noEndpointTouch?null:[toPoint(a1,s,va)]:0===t||1===t?noEndpointTouch?null:[toPoint(b1,t,vb)]:[toPoint(a1,s,va)]}if(kross=crossProduct(v1,va),sqrKross=kross*kross,sqrKross>0)return null;const sqrLenA=dot$1(va,va),sa=dot$1(va,v1)/sqrLenA,sb=sa+dot$1(va,vb)/sqrLenA,smin=Math.min(sa,sb),smax=Math.max(sa,sb);return smin<=1&&smax>=0?1===smin?noEndpointTouch?null:[toPoint(a1,smin>0?smin:0,va)]:0===smax?noEndpointTouch?null:[toPoint(a1,smax<1?smax:1,va)]:noEndpointTouch&&0===smin&&1===smax?null:[toPoint(a1,smin>0?smin:0,va),toPoint(a1,smax<1?smax:1,va)]:null})(se1.point,se1.otherEvent.point,se2.point,se2.otherEvent.point),nIntersections=inter?inter.length:0;if(0===nIntersections)return 0;if(1===nIntersections&&(equals$6(se1.point,se2.point)||equals$6(se1.otherEvent.point,se2.otherEvent.point)))return 0;if(1===nIntersections)return equals$6(se1.point,inter[0])||equals$6(se1.otherEvent.point,inter[0])||divideSegment(se1,inter[0],queue),equals$6(se2.point,inter[0])||equals$6(se2.otherEvent.point,inter[0])||divideSegment(se2,inter[0],queue),1;if(2===nIntersections&&se1.isSubject===se2.isSubject)return 0;const segmentEvents=[];let leftCoincide=!1,rightCoincide=!1;return equals$6(se1.point,se2.point)?leftCoincide=!0:1===compareEvents(se1,se2)?segmentEvents.push(se2,se1):segmentEvents.push(se1,se2),equals$6(se1.otherEvent.point,se2.otherEvent.point)?rightCoincide=!0:1===compareEvents(se1.otherEvent,se2.otherEvent)?segmentEvents.push(se2.otherEvent,se1.otherEvent):segmentEvents.push(se1.otherEvent,se2.otherEvent),leftCoincide?(se2.type=1,se1.type=se2.inOut===se1.inOut?2:3,rightCoincide||divideSegment(segmentEvents[1].otherEvent,segmentEvents[0].point,queue),2):rightCoincide?(divideSegment(segmentEvents[0],segmentEvents[1].point,queue),3):segmentEvents[0]!==segmentEvents[3].otherEvent?(divideSegment(segmentEvents[0],segmentEvents[1].point,queue),divideSegment(segmentEvents[1],segmentEvents[2].point,queue),4):(divideSegment(segmentEvents[0],segmentEvents[1].point,queue),divideSegment(segmentEvents[3].otherEvent,segmentEvents[2].point,queue),5)},compareSegments=(le1,le2)=>{if(le1===le2)return 0;if(0!==signedArea(le1.point,le1.otherEvent.point,le2.point)||0!==signedArea(le1.point,le1.otherEvent.point,le2.otherEvent.point))return equals$6(le1.point,le2.point)?le1.isBelow(le2.otherEvent.point)?-1:1:le1.point[0]===le2.point[0]?le1.point[1]<le2.point[1]?-1:1:1===compareEvents(le1,le2)?le2.isAbove(le1.point)?-1:1:le1.isBelow(le2.point)?-1:1;if(le1.isSubject!==le2.isSubject)return le1.isSubject?-1:1;{let p1=le1.point,p2=le2.point;if(p1[0]===p2[0]&&p1[1]===p2[1])return p1=le1.otherEvent.point,p2=le2.otherEvent.point,p1[0]===p2[0]&&p1[1]===p2[1]?0:le1.contourId>le2.contourId?1:-1}return 1===compareEvents(le1,le2)?1:-1};class Contour{constructor(){this.points=[],this.holeIds=[],this.holeOf=null,this.depth=0}isExterior(){return null==this.holeOf}}const nextPos=(pos,resultEvents,processed,origPos)=>{const length=resultEvents.length,p0=resultEvents[pos].point;let p1,newPos=pos+1;for(newPos<length&&(p1=resultEvents[newPos].point);newPos<length&&p1[0]===p0[0]&&p1[1]===p0[1];){if(!processed[newPos])return newPos;newPos++,newPos<length&&(p1=resultEvents[newPos].point)}for(newPos=pos-1;processed[newPos]&&newPos>origPos;)newPos--;return newPos},initializeContourFromContext=(event,contours,contourId)=>{const contour=new Contour;if(null!=event.prevInResult){const prevInResult=event.prevInResult,lowerContourId=prevInResult.outputContourId,lowerResultTransition=prevInResult.resultTransition;if(lowerContourId<0)contour.holeOf=null,contour.depth=0;else if(lowerResultTransition>0){const lowerContour=contours[lowerContourId];if(null!=lowerContour.holeOf){const parentContourId=lowerContour.holeOf;contours[parentContourId].holeIds.push(contourId),contour.holeOf=parentContourId,contour.depth=contours[lowerContourId].depth}else contours[lowerContourId].holeIds.push(contourId),contour.holeOf=lowerContourId,contour.depth=contours[lowerContourId].depth+1}else contour.depth=contours[lowerContourId].depth}return contour};class Queue{constructor(data,compare){if(this.data=data,this.length=this.data.length,this.compare=compare,this.length>0)for(let i=(this.length>>1)-1;i>=0;i--)this._down(i)}push(item){this.data.push(item),this._up(this.length++)}pop(){if(0===this.length)return;const top=this.data[0],bottom=this.data.pop();return--this.length>0&&(this.data[0]=bottom,this._down(0)),top}peek(){return this.data[0]}_up(pos){const{data:data,compare:compare}=this,item=data[pos];for(;pos>0;){const parent=pos-1>>1,current=data[parent];if(compare(item,current)>=0)break;data[pos]=current,pos=parent}data[pos]=item}_down(pos){const{data:data,compare:compare}=this,halfLength=this.length>>1,item=data[pos];for(;pos<halfLength;){let bestChild=1+(pos<<1);const right=bestChild+1;if(right<this.length&&compare(data[right],data[bestChild])<0&&(bestChild=right),compare(data[bestChild],item)>=0)break;data[pos]=data[bestChild],pos=bestChild}data[pos]=item}}let externalRingId=0;const processPolygon=(contourOrHole,isSubject,ringId,queue,bbox,isExteriorRing)=>{const len=contourOrHole.length-1;for(let i=0;i<len;i++){const s1=contourOrHole[i],s2=contourOrHole[i+1],e1=new SweepEvent(s1,!1,void 0,isSubject),e2=new SweepEvent(s2,!1,e1,isSubject);if(e1.otherEvent=e2,s1[0]===s2[0]&&s1[1]===s2[1])continue;e1.contourId=e2.contourId=ringId,isExteriorRing||(e1.isExteriorRing=!1,e2.isExteriorRing=!1),compareEvents(e1,e2)>0?e2.left=!0:e1.left=!0;const x=s1[0],y=s1[1];bbox[0]=Math.min(bbox[0],x),bbox[1]=Math.min(bbox[1],y),bbox[2]=Math.max(bbox[2],x),bbox[3]=Math.max(bbox[3],y),queue.push(e1),queue.push(e2)}},EMPTY=[],toMartinez=geometry=>{const outlines=[];return toOutlines(geometry).forEach((outline=>{equals$6(outline[0],outline[outline.length-1])?outlines.push(outline):outlines.push([...outline,outline[0]])})),[outlines]},fromOutlines=outlines=>(outlines.forEach((outline=>{equals$6(outline[0],outline[outline.length-1])&&outline.pop()})),outlines=outlines.filter((o=>o.length>=3)),create$a(outlines)),boolean=(subjectGeom,clippingGeom,operation)=>{const subject=toMartinez(subjectGeom),clipping=toMartinez(clippingGeom);let trivial=((subject,clipping,operation)=>{let result=null;if(subject.length*clipping.length==0){if(0===operation)return EMPTY;2===operation?result=subject:1!==operation&&3!==operation||(result=0===subject.length?clipping:subject)}return result===EMPTY?create$a():result?fromOutlines(result.flat()):null})(subject,clipping,operation);if(trivial)return trivial;const sbbox=[1/0,1/0,-1/0,-1/0],cbbox=[1/0,1/0,-1/0,-1/0],eventQueue=((subject,clipping,sbbox,cbbox,operation)=>{const eventQueue=new Queue([],compareEvents);for(let i=0;i<subject.length;i++){const polygonSet=subject[i];for(let j=0;j<polygonSet.length;j++){const isExteriorRing=0===j;isExteriorRing&&externalRingId++,processPolygon(polygonSet[j],!0,externalRingId,eventQueue,sbbox,isExteriorRing)}}for(let i=0;i<clipping.length;i++){const polygonSet=clipping[i];for(let j=0;j<polygonSet.length;j++){let isExteriorRing=0===j;2===operation&&(isExteriorRing=!1),isExteriorRing&&externalRingId++,processPolygon(polygonSet[j],!1,externalRingId,eventQueue,cbbox,isExteriorRing)}}return eventQueue})(subject,clipping,sbbox,cbbox,operation);if(trivial=((subject,clipping,sbbox,cbbox,operation)=>{let result=null;return(sbbox[0]>cbbox[2]||cbbox[0]>sbbox[2]||sbbox[1]>cbbox[3]||cbbox[1]>sbbox[3])&&(0===operation?result=EMPTY:2===operation?result=subject:1!==operation&&3!==operation||(result=subject.concat(clipping))),result===EMPTY?create$a():result?fromOutlines(result.flat()):null})(subject,clipping,sbbox,cbbox,operation),trivial)return trivial;const sortedEvents=((eventQueue,subject,clipping,sbbox,cbbox,operation)=>{const sweepLine=new Tree$1(compareSegments),sortedEvents=[],rightBound=Math.min(sbbox[2],cbbox[2]);let prev,next,begin;for(;0!==eventQueue.length;){const event=eventQueue.pop();if(sortedEvents.push(event),0===operation&&event.point[0]>rightBound||2===operation&&event.point[0]>sbbox[2])break;if(event.left){next=prev=sweepLine.insert(event),begin=sweepLine.minNode(),prev=prev!==begin?sweepLine.prev(prev):null,next=sweepLine.next(next);const prevEvent=prev?prev.key:null;let prevprevEvent;if(computeFields(event,prevEvent,operation),next&&2===possibleIntersection(event,next.key,eventQueue)&&(computeFields(event,prevEvent,operation),computeFields(next.key,event,operation)),prev&&2===possibleIntersection(prev.key,event,eventQueue)){let prevprev=prev;prevprev=prevprev!==begin?sweepLine.prev(prevprev):null,prevprevEvent=prevprev?prevprev.key:null,computeFields(prevEvent,prevprevEvent,operation),computeFields(event,prevEvent,operation)}}else next=prev=sweepLine.find(event.otherEvent),prev&&next&&(prev=prev!==begin?sweepLine.prev(prev):null,next=sweepLine.next(next),sweepLine.remove(event.otherEvent),next&&prev&&possibleIntersection(prev.key,next.key,eventQueue))}return sortedEvents})(eventQueue,0,0,sbbox,cbbox,operation),contours=(sortedEvents=>{const resultEvents=(sortedEvents=>{const resultEvents=[];sortedEvents.forEach((e=>{(e.left&&e.inResult||!e.left&&e.otherEvent.inResult)&&resultEvents.push(e)}));let sorted=!1;for(;!sorted;){sorted=!0;const len=resultEvents.length;for(let i=0;i<len;i++)if(i+1<len&&1===compareEvents(resultEvents[i],resultEvents[i+1])){const tmp=resultEvents[i];resultEvents[i]=resultEvents[i+1],resultEvents[i+1]=tmp,sorted=!1}}return resultEvents.forEach(((e,i)=>{e.otherPos=i})),resultEvents.forEach((e=>{if(!e.left){const otherPos=e.otherPos;e.otherPos=e.otherEvent.otherPos,e.otherEvent.otherPos=otherPos}})),resultEvents})(sortedEvents),evlen=resultEvents.length,processed=[],contours=[];for(let i=0;i<evlen;i++){if(processed[i])continue;const contourId=contours.length,contour=initializeContourFromContext(resultEvents[i],contours,contourId),markAsProcessed=pos=>{processed[pos]=!0,pos<evlen&&(resultEvents[pos].outputContourId=contourId)};let pos=i;const origPos=i;for(contour.points.push(resultEvents[pos].point);markAsProcessed(pos),pos=resultEvents[pos].otherPos,markAsProcessed(pos),contour.points.push(resultEvents[pos].point),pos=nextPos(pos,resultEvents,processed,origPos),!(pos===origPos||pos>=evlen););contours.push(contour)}return contours})(sortedEvents),polygons=[];for(let i=0;i<contours.length;i++){const contour=contours[i];if(contour.isExterior()){const rings=[contour.points];for(let j=0;j<contour.holeIds.length;j++){const holePoints=contours[contour.holeIds[j]].points,hole=[];for(let k=holePoints.length-2;k>=0;k--)hole.push(holePoints[k]);rings.push(hole)}polygons.push(rings)}}return polygons.length?fromOutlines(polygons.flat()):create$a()},interpolateBetween2DPointsForY=(point1,point2,y)=>{let t,f1=y-point1[1],f2=point2[1]-point1[1];return f2<0&&(f1=-f1,f2=-f2),t=f1<=0?0:f1>=f2?1:f2<1e-10?.5:f1/f2,point1[0]+t*(point2[0]-point1[0])};class OrthonormalFormula{constructor(plane){this.plane=plane;const rightVector=orthogonal([0,0,0],plane);this.v=normalize$1(rightVector,cross$1(rightVector,plane,rightVector)),this.u=cross$1([0,0,0],this.v,plane),this.planeOrigin=scale$3([0,0,0],plane,plane[3]),this.basisMap=new Map}getProjectionMatrix(){return fromValues$4(this.u[0],this.v[0],this.plane[0],0,this.u[1],this.v[1],this.plane[1],0,this.u[2],this.v[2],this.plane[2],0,0,0,-this.plane[3],1)}getInverseProjectionMatrix(){return fromValues$4(this.u[0],this.u[1],this.u[2],0,this.v[0],this.v[1],this.v[2],0,this.plane[0],this.plane[1],this.plane[2],0,this.planeOrigin[0],this.planeOrigin[1],this.planeOrigin[2],1)}to2D(vertex){const point=fromValues$2(dot$2(vertex,this.u),dot$2(vertex,this.v));return this.basisMap.set(point,vertex),point}to3D(point){const original=this.basisMap.get(point);if(original)return original;const v1=scale$3([0,0,0],this.u,point[0]),v2=scale$3([0,0,0],this.v,point[1]),v3=add$1(v1,v1,this.planeOrigin);return add$1(v2,v2,v3)}}const insertSorted=(array,element,compareFunc)=>{let leftBound=0,rightBound=array.length;for(;rightBound>leftBound;){const testIndex=Math.floor((leftBound+rightBound)/2);compareFunc(element,array[testIndex])>0?leftBound=testIndex+1:rightBound=testIndex}array.splice(leftBound,0,element)},fnNumberSort=(a,b)=>a-b,retessellate=geometry=>{if(geometry.isRetesselated)return geometry;const polygons=toPolygons$1(geometry).map(((polygon,index)=>({vertices:polygon.vertices,plane:plane(polygon),index:index}))),classified=classifyPolygons(polygons),destPolygons=[];classified.forEach((group=>{if(Array.isArray(group)){const reTessellateCoplanarPolygons=(sourcePolygons=>{if(sourcePolygons.length<2)return sourcePolygons;const destPolygons=[],numPolygons=sourcePolygons.length,plane$1=plane(sourcePolygons[0]),orthonormalFormula=new OrthonormalFormula(plane$1),polygonVertices2d=[],polygonTopVertexIndexes=[],topy2polygonIndexes=new Map,yCoordinateToPolygonIndexes=new Map,yCoordinateBins=new Map;for(let polygonIndex=0;polygonIndex<numPolygons;polygonIndex++){const poly3d=sourcePolygons[polygonIndex];let vertices2d=[],numVertices=poly3d.vertices.length,minIndex=-1;if(numVertices>0){let miny,maxy;for(let i=0;i<numVertices;i++){let pos2d=orthonormalFormula.to2D(poly3d.vertices[i]);const yCoordinateBin=Math.floor(999999.9999999999*pos2d[1]);let newY;yCoordinateBins.has(yCoordinateBin)?newY=yCoordinateBins.get(yCoordinateBin):yCoordinateBins.has(yCoordinateBin+1)?newY=yCoordinateBins.get(yCoordinateBin+1):yCoordinateBins.has(yCoordinateBin-1)?newY=yCoordinateBins.get(yCoordinateBin-1):(newY=pos2d[1],yCoordinateBins.set(yCoordinateBin,pos2d[1])),pos2d=fromValues$2(pos2d[0],newY),vertices2d.push(pos2d);const y=pos2d[1];(0===i||y<miny)&&(miny=y,minIndex=i),(0===i||y>maxy)&&(maxy=y);let polygonIndexes=yCoordinateToPolygonIndexes.get(y);polygonIndexes||(polygonIndexes=[],yCoordinateToPolygonIndexes.set(y,polygonIndexes)),polygonIndexes[polygonIndex]=!0}if(miny>=maxy)vertices2d=[],numVertices=0,minIndex=-1;else{let polygonIndexes=topy2polygonIndexes.get(miny);polygonIndexes||(polygonIndexes=[],topy2polygonIndexes.set(miny,polygonIndexes)),polygonIndexes.push(polygonIndex)}}vertices2d.reverse(),minIndex=numVertices-minIndex-1,polygonVertices2d.push(vertices2d),polygonTopVertexIndexes.push(minIndex)}const yCoordinates=[];yCoordinateToPolygonIndexes.forEach(((polylist,y)=>yCoordinates.push(y))),yCoordinates.sort(fnNumberSort);let activePolygons=[],prevOutPolygonRow=[];for(let yIndex=0;yIndex<yCoordinates.length;yIndex++){const newOutPolygonRow=[],yCoordinate=yCoordinates[yIndex],polygonIndexesWithCorner=yCoordinateToPolygonIndexes.get(yCoordinate);for(let activePolygonIndex=0;activePolygonIndex<activePolygons.length;++activePolygonIndex){const activePolygon=activePolygons[activePolygonIndex],polygonIndex=activePolygon.polygonIndex;if(polygonIndexesWithCorner[polygonIndex]){const vertices2d=polygonVertices2d[polygonIndex],numVertices=vertices2d.length;let newLeftVertexIndex=activePolygon.leftVertexIndex,newRightVertexIndex=activePolygon.rightVertexIndex;for(;;){let nextLeftVertexIndex=newLeftVertexIndex+1;if(nextLeftVertexIndex>=numVertices&&(nextLeftVertexIndex=0),vertices2d[nextLeftVertexIndex][1]!==yCoordinate)break;newLeftVertexIndex=nextLeftVertexIndex}let nextRightVertexIndex=newRightVertexIndex-1;if(nextRightVertexIndex<0&&(nextRightVertexIndex=numVertices-1),vertices2d[nextRightVertexIndex][1]===yCoordinate&&(newRightVertexIndex=nextRightVertexIndex),newLeftVertexIndex!==activePolygon.leftVertexIndex&&newLeftVertexIndex===newRightVertexIndex)activePolygons.splice(activePolygonIndex,1),--activePolygonIndex;else{activePolygon.leftVertexIndex=newLeftVertexIndex,activePolygon.rightVertexIndex=newRightVertexIndex,activePolygon.topLeft=vertices2d[newLeftVertexIndex],activePolygon.topRight=vertices2d[newRightVertexIndex];let nextLeftVertexIndex=newLeftVertexIndex+1;nextLeftVertexIndex>=numVertices&&(nextLeftVertexIndex=0),activePolygon.bottomLeft=vertices2d[nextLeftVertexIndex];let nextRightVertexIndex=newRightVertexIndex-1;nextRightVertexIndex<0&&(nextRightVertexIndex=numVertices-1),activePolygon.bottomRight=vertices2d[nextRightVertexIndex]}}}let nextYcoordinate;if(yIndex>=yCoordinates.length-1)activePolygons=[],nextYcoordinate=null;else{nextYcoordinate=Number(yCoordinates[yIndex+1]);const middleYcoordinate=.5*(yCoordinate+nextYcoordinate),startingPolygonIndexes=topy2polygonIndexes.get(yCoordinate);for(const polygonIndexKey in startingPolygonIndexes){const polygonIndex=startingPolygonIndexes[polygonIndexKey],vertices2d=polygonVertices2d[polygonIndex],numVertices=vertices2d.length,topVertexIndex=polygonTopVertexIndexes[polygonIndex];let topLeftVertexIndex=topVertexIndex;for(;;){let i=topLeftVertexIndex+1;if(i>=numVertices&&(i=0),vertices2d[i][1]!==yCoordinate)break;if(i===topVertexIndex)break;topLeftVertexIndex=i}let topRightVertexIndex=topVertexIndex;for(;;){let i=topRightVertexIndex-1;if(i<0&&(i=numVertices-1),vertices2d[i][1]!==yCoordinate)break;if(i===topLeftVertexIndex)break;topRightVertexIndex=i}let nextLeftVertexIndex=topLeftVertexIndex+1;nextLeftVertexIndex>=numVertices&&(nextLeftVertexIndex=0);let nextRightVertexIndex=topRightVertexIndex-1;nextRightVertexIndex<0&&(nextRightVertexIndex=numVertices-1);const newActivePolygon={polygonIndex:polygonIndex,leftVertexIndex:topLeftVertexIndex,rightVertexIndex:topRightVertexIndex,topLeft:vertices2d[topLeftVertexIndex],topRight:vertices2d[topRightVertexIndex],bottomLeft:vertices2d[nextLeftVertexIndex],bottomRight:vertices2d[nextRightVertexIndex]};insertSorted(activePolygons,newActivePolygon,((el1,el2)=>{const x1=interpolateBetween2DPointsForY(el1.topLeft,el1.bottomLeft,middleYcoordinate),x2=interpolateBetween2DPointsForY(el2.topLeft,el2.bottomLeft,middleYcoordinate);return x1>x2?1:x1<x2?-1:0}))}}for(const activePolygonKey in activePolygons){const activePolygon=activePolygons[activePolygonKey];let x=interpolateBetween2DPointsForY(activePolygon.topLeft,activePolygon.bottomLeft,yCoordinate);const topLeft=fromValues$2(x,yCoordinate);x=interpolateBetween2DPointsForY(activePolygon.topRight,activePolygon.bottomRight,yCoordinate);const topRight=fromValues$2(x,yCoordinate);x=interpolateBetween2DPointsForY(activePolygon.topLeft,activePolygon.bottomLeft,nextYcoordinate);const bottomLeft=fromValues$2(x,nextYcoordinate);x=interpolateBetween2DPointsForY(activePolygon.topRight,activePolygon.bottomRight,nextYcoordinate);const bottomRight=fromValues$2(x,nextYcoordinate),outPolygon={topLeft:topLeft,topRight:topRight,bottomLeft:bottomLeft,bottomRight:bottomRight,leftLine:fromPoints$1([0,1,0],topLeft,bottomLeft),rightLine:fromPoints$1([0,1,0],bottomRight,topRight)};if(newOutPolygonRow.length>0){const prevOutPolygon=newOutPolygonRow[newOutPolygonRow.length-1],d1=distance(outPolygon.topLeft,prevOutPolygon.topRight),d2=distance(outPolygon.bottomLeft,prevOutPolygon.bottomRight);d1<EPS&&d2<EPS&&(outPolygon.topLeft=prevOutPolygon.topLeft,outPolygon.leftLine=prevOutPolygon.leftLine,outPolygon.bottomLeft=prevOutPolygon.bottomLeft,newOutPolygonRow.splice(newOutPolygonRow.length-1,1))}newOutPolygonRow.push(outPolygon)}if(yIndex>0){const prevContinuedIndexes=new Set,matchedIndexes=new Set;for(let i=0;i<newOutPolygonRow.length;i++){const thisPolygon=newOutPolygonRow[i];for(let ii=0;ii<prevOutPolygonRow.length;ii++)if(!matchedIndexes.has(ii)){const prevPolygon=prevOutPolygonRow[ii];if(distance(prevPolygon.bottomLeft,thisPolygon.topLeft)<EPS&&distance(prevPolygon.bottomRight,thisPolygon.topRight)<EPS){matchedIndexes.add(ii);const v1=direction$1(thisPolygon.leftLine),v2=direction$1(prevPolygon.leftLine),d1=v1[0]-v2[0],v3=direction$1(thisPolygon.rightLine),v4=direction$1(prevPolygon.rightLine),d2=v3[0]-v4[0],leftLineContinues=Math.abs(d1)<EPS,rightLineContinues=Math.abs(d2)<EPS;(leftLineContinues||d1>=0)&&(rightLineContinues||d2>=0)&&(thisPolygon.outPolygon=prevPolygon.outPolygon,thisPolygon.leftLineContinues=leftLineContinues,thisPolygon.rightLineContinues=rightLineContinues,prevContinuedIndexes.add(ii));break}}}for(let ii=0;ii<prevOutPolygonRow.length;ii++)if(!prevContinuedIndexes.has(ii)){const prevPolygon=prevOutPolygonRow[ii];prevPolygon.outPolygon.rightPoints.push(prevPolygon.bottomRight),distance(prevPolygon.bottomRight,prevPolygon.bottomLeft)>EPS&&prevPolygon.outPolygon.leftPoints.push(prevPolygon.bottomLeft),prevPolygon.outPolygon.leftPoints.reverse();const vertices3d=prevPolygon.outPolygon.rightPoints.concat(prevPolygon.outPolygon.leftPoints).map((point2d=>orthonormalFormula.to3D(point2d))),polygon=fromVerticesAndPlane(vertices3d,plane$1);polygon.vertices.length&&destPolygons.push(polygon)}}for(let i=0;i<newOutPolygonRow.length;i++){const thisPolygon=newOutPolygonRow[i];thisPolygon.outPolygon?(thisPolygon.leftLineContinues||thisPolygon.outPolygon.leftPoints.push(thisPolygon.topLeft),thisPolygon.rightLineContinues||thisPolygon.outPolygon.rightPoints.push(thisPolygon.topRight)):(thisPolygon.outPolygon={leftPoints:[],rightPoints:[]},thisPolygon.outPolygon.leftPoints.push(thisPolygon.topLeft),distance(thisPolygon.topLeft,thisPolygon.topRight)>EPS&&thisPolygon.outPolygon.rightPoints.push(thisPolygon.topRight))}prevOutPolygonRow=newOutPolygonRow}return destPolygons})(group);destPolygons.push(...reTessellateCoplanarPolygons)}else destPolygons.push(group)}));const result=create$8(destPolygons);return result.isRetesselated=!0,result},classifyPolygons=polygons=>{let clusters=[polygons];const nonCoplanar=[];for(let component=3;component>=0;component--){const maybeCoplanar=[],tolerance=3===component?15e-9:NEPS;clusters.forEach((cluster=>{cluster.sort(byPlaneComponent(component,tolerance));let startIndex=0;for(let i=1;i<cluster.length;i++)cluster[i].plane[component]-cluster[startIndex].plane[component]>tolerance&&(i-startIndex==1?nonCoplanar.push(cluster[startIndex]):maybeCoplanar.push(cluster.slice(startIndex,i)),startIndex=i);cluster.length-startIndex==1?nonCoplanar.push(cluster[startIndex]):maybeCoplanar.push(cluster.slice(startIndex))})),clusters=maybeCoplanar}const result=[];return clusters.forEach((cluster=>{cluster[0]&&(result[cluster[0].index]=cluster)})),nonCoplanar.forEach((polygon=>{result[polygon.index]=polygon})),result},byPlaneComponent=(component,tolerance)=>(a,b)=>a.plane[component]-b.plane[component]>tolerance?1:b.plane[component]-a.plane[component]>tolerance?-1:0;class Node{constructor(parent){this.plane=null,this.front=null,this.back=null,this.polygontreenodes=[],this.parent=parent}invert(){const queue=[this];let node;for(let i=0;i<queue.length;i++){node=queue[i],null!==node.plane&&(node.plane=flip([0,0,0,0],node.plane)),null!==node.front&&queue.push(node.front),null!==node.back&&queue.push(node.back);const temp=node.front;node.front=node.back,node.back=temp}}clipPolygons(polygonTreeNodes,alsoRemoveCoplanarFront){let node,current={node:this,polygonTreeNodes:polygonTreeNodes};const stack=[];do{if(node=current.node,polygonTreeNodes=current.polygonTreeNodes,null!==node.plane){const plane=node.plane,backNodes=[],frontNodes=[],coplanarFrontNodes=alsoRemoveCoplanarFront?backNodes:frontNodes;for(let i=0;i<polygonTreeNodes.length;i++){const treeNode=polygonTreeNodes[i];treeNode.canSplit()&&treeNode.splitByPlane(plane,coplanarFrontNodes,backNodes,frontNodes,backNodes)}null!==node.front&&frontNodes.length>0&&stack.push({node:node.front,polygonTreeNodes:frontNodes});const numBackNodes=backNodes.length;if(null!==node.back&&numBackNodes>0)stack.push({node:node.back,polygonTreeNodes:backNodes});else for(let i=0;i<numBackNodes;i++)backNodes[i].remove()}current=stack.pop()}while(void 0!==current)}clipTo(bsptree,alsoRemoveCoplanarFront){let node=this;const stack=[];do{node.polygontreenodes.length>0&&bsptree.clipPolygons(node.polygontreenodes,alsoRemoveCoplanarFront),null!==node.front&&stack.push(node.front),null!==node.back&&stack.push(node.back),node=stack.pop()}while(void 0!==node)}addPolygonTreeNodes(newPolygonTreeNodes){let current={node:this,polygonTreeNodes:newPolygonTreeNodes};const stack=[];do{const node=current.node,polygonTreeNodes=current.polygonTreeNodes,len=polygonTreeNodes.length;if(0===len){current=stack.pop();continue}if(null===node.plane){let index=0;index=Math.floor(len/2);const bestPoly=polygonTreeNodes[index].getPolygon();node.plane=plane(bestPoly)}const frontNodes=[],backNodes=[];for(let i=0;i<len;++i)polygonTreeNodes[i].splitByPlane(node.plane,node.polygontreenodes,backNodes,frontNodes,backNodes);frontNodes.length>0&&(null===node.front&&(node.front=new Node(node)),len===frontNodes.length&&0===backNodes.length?node.front.polygontreenodes=frontNodes:stack.push({node:node.front,polygonTreeNodes:frontNodes})),backNodes.length>0&&(null===node.back&&(node.back=new Node(node)),len===backNodes.length&&0===frontNodes.length?node.back.polygontreenodes=backNodes:stack.push({node:node.back,polygonTreeNodes:backNodes})),current=stack.pop()}while(void 0!==current)}}const splitLineSegmentByPlane=(plane,p1,p2)=>{const direction=subtract$3([0,0,0],p2,p1);let lambda=(plane[3]-dot$2(plane,p1))/dot$2(plane,direction);return Number.isNaN(lambda)?lambda=0:lambda>1?lambda=1:lambda<0&&(lambda=0),scale$3(direction,direction,lambda),add$1(direction,p1,direction),direction},splitResult={type:0,front:null,back:null};class PolygonTreeNode{constructor(parent,polygon){this.parent=parent,this.polygon=polygon,this.children=[]}addPolygons(polygons){if(!this.isRootNode())throw new Error("PolygonTreeNode01");for(let i=0;i<polygons.length;i++)this.addChild(polygons[i])}remove(){this.polygon=null;const parentschildren=this.parent.children,i=parentschildren.indexOf(this);if(i<0)throw new Error("PolyTreeNode02");parentschildren.splice(i,1),this.parent._recursivelyInvalidatePolygon()}canSplit(){return null!=this.polygon||this.children.length>0}isRootNode(){return!this.parent}invert(){if(!this.isRootNode())throw new Error("PolyTreeNode03");this._invertSub()}getPolygon(){if(null===this.polygon)throw new Error("PolyTreeNode04");return this.polygon}getPolygons(result){let children=[this];const queue=[children];let i,j,l,node;for(i=0;i<queue.length;++i)for(children=queue[i],j=0,l=children.length;j<l;j++)node=children[j],null!==node.polygon?result.push(node.polygon):node.children.length>0&&queue.push(node.children)}getPolygonsNew(result){if(null!==this.polygon)result.push(this.polygon);else for(let i=0;i<this.children.length;i++)this.children[i].getPolygons(result)}splitByPlaneOld(plane,coplanarfrontnodes,coplanarbacknodes,frontnodes,backnodes){if(this.children.length>0){const queue=[this.children];let i,j,l,node,nodes;for(i=0;i<queue.length;i++)for(nodes=queue[i],j=0,l=nodes.length;j<l;j++)node=nodes[j],node.children.length>0?queue.push(node.children):null!==this.polygon&&node._splitByPlane(plane,coplanarfrontnodes,coplanarbacknodes,frontnodes,backnodes)}else null!==this.polygon&&this._splitByPlane(plane,coplanarfrontnodes,coplanarbacknodes,frontnodes,backnodes)}splitByPlane(plane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes){if(this.children.length>0)for(let i=0;i<this.children.length;i++)this.children[i].splitByPlane(plane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes);else null!==this.polygon&&this._splitByPlane(plane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes)}_splitByPlane(splane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes){const bounds=measureBoundingSphereAndCache(this.polygon),sphereRadius=bounds[3]+EPS,d=dot$2(splane,bounds)-splane[3];if(d>sphereRadius)frontNodes.push(this);else if(d<-sphereRadius)backNodes.push(this);else switch(((result,splane,polygon)=>{const vertices=polygon.vertices,numVertices=vertices.length,pplane=plane(polygon);if(equals$5(pplane,splane))result.type=0;else{let hasFront=!1,hasBack=!1;const vertexIsBack=[],MINEPS=-EPS;for(let i=0;i<numVertices;i++){const t=dot$2(splane,vertices[i])-splane[3],isback=t<MINEPS;vertexIsBack.push(isback),t>EPS&&(hasFront=!0),t<MINEPS&&(hasBack=!0)}if(hasFront||hasBack)if(hasBack)if(hasFront){const frontVertices=[],backVertices=[];let isback=vertexIsBack[0];for(let vertexIndex=0;vertexIndex<numVertices;vertexIndex++){const vertex=vertices[vertexIndex];let nextVertexIndex=vertexIndex+1;nextVertexIndex>=numVertices&&(nextVertexIndex=0);const nextIsBack=vertexIsBack[nextVertexIndex];if(isback===nextIsBack)isback?backVertices.push(vertex):frontVertices.push(vertex);else{const nextPoint=vertices[nextVertexIndex],intersectionPoint=splitLineSegmentByPlane(splane,vertex,nextPoint);isback?(backVertices.push(vertex),backVertices.push(intersectionPoint),frontVertices.push(intersectionPoint)):(frontVertices.push(vertex),frontVertices.push(intersectionPoint),backVertices.push(intersectionPoint))}isback=nextIsBack}const EPS_SQUARED=EPS*EPS;if(backVertices.length>=3){let prevVertex=backVertices[backVertices.length-1];for(let vertexIndex=0;vertexIndex<backVertices.length;vertexIndex++){const vertex=backVertices[vertexIndex];squaredDistance$1(vertex,prevVertex)<EPS_SQUARED&&(backVertices.splice(vertexIndex,1),vertexIndex--),prevVertex=vertex}}if(frontVertices.length>=3){let prevVertex=frontVertices[frontVertices.length-1];for(let vertexIndex=0;vertexIndex<frontVertices.length;vertexIndex++){const vertex=frontVertices[vertexIndex];squaredDistance$1(vertex,prevVertex)<EPS_SQUARED&&(frontVertices.splice(vertexIndex,1),vertexIndex--),prevVertex=vertex}}result.type=4,result.front=frontVertices.length>=3?fromVerticesAndPlane(frontVertices,pplane):null,result.back=backVertices.length>=3?fromVerticesAndPlane(backVertices,pplane):null}else result.type=3;else result.type=2;else{const t=dot$2(splane,pplane);result.type=t>=0?0:1}}})(splitResult,splane,this.polygon),splitResult.type){case 0:coplanarFrontNodes.push(this);break;case 1:coplanarBackNodes.push(this);break;case 2:frontNodes.push(this);break;case 3:backNodes.push(this);break;case 4:if(null!==splitResult.front){const frontNode=this.addChild(splitResult.front);frontNodes.push(frontNode)}if(null!==splitResult.back){const backNode=this.addChild(splitResult.back);backNodes.push(backNode)}}}addChild(polygon){const newChild=new PolygonTreeNode(this,polygon);return this.children.push(newChild),newChild}_invertSub(){let children=[this];const queue=[children];let i,j,l,node;for(i=0;i<queue.length;i++)for(children=queue[i],j=0,l=children.length;j<l;j++)node=children[j],null!==node.polygon&&(node.polygon=invert$1(node.polygon)),node.children.length>0&&queue.push(node.children)}_invertSubNew(){null!==this.polygon&&(this.polygon=invert$1(this.polygon));for(let i=0;i<this.children.length;i++)this.children[i]._invertSub()}_recursivelyInvalidatePolygon(){this.polygon=null,null!==this.parent&&this.parent._recursivelyInvalidatePolygon()}clear(){for(let i=0;i<this.children.length;i++)this.children[i].clear();this.children.length=0,null!==this.polygon&&(this.polygon=null),this.parent=null}toString(){let result="",children=[this];const queue=[children];let i,j,l,node;for(i=0;i<queue.length;++i){children=queue[i];const prefix=" ".repeat(i);for(j=0,l=children.length;j<l;j++)node=children[j],result+=`${prefix}PolygonTreeNode (${node.isRootNode()}): ${node.children.length}`,null!==node.polygon?result+=`\n ${prefix}polygon: ${node.polygon.vertices}\n`:result+="\n",node.children.length>0&&queue.push(node.children)}return result}}class Tree{constructor(polygons){this.polygonTree=new PolygonTreeNode(null,null),this.rootnode=new Node(null),polygons&&this.addPolygons(polygons)}invert(){this.polygonTree.invert(),this.rootnode.invert()}clipTo(tree,alsoRemoveCoplanarFront=!1){this.rootnode.clipTo(tree.rootnode,alsoRemoveCoplanarFront)}allPolygons(){const result=[];return this.polygonTree.getPolygons(result),result}addPolygons(polygons){const polygonTreeNodes=new Array(polygons.length);for(let i=0;i<polygons.length;i++)polygonTreeNodes[i]=this.polygonTree.addChild(polygons[i]);this.rootnode.addPolygonTreeNodes(polygonTreeNodes)}addPolygonsNew(polygons){this.polygonTree.addPolygons(polygons),this.rootnode.addPolygonTreeNodes(this.polygonTree.children)}clear(){this.polygonTree.clear()}toString(){return"Tree: "+this.polygonTree.toString("")}}const mayOverlap=(geometry1,geometry2)=>{if(0===geometry1.polygons.length||0===geometry2.polygons.length)return!1;const bounds1=measureBoundingBox(geometry1),min1=bounds1[0],max1=bounds1[1],bounds2=measureBoundingBox(geometry2),min2=bounds2[0],max2=bounds2[1];return!(min2[0]-max1[0]>EPS||min1[0]-max2[0]>EPS||min2[1]-max1[1]>EPS||min1[1]-max2[1]>EPS||min2[2]-max1[2]>EPS||min1[2]-max2[2]>EPS)},scission=(...objects)=>{const results=objects.map((object=>isA$3(object)?(geometry=>{const eps=measureEpsilon(geometry),polygons=toPolygons$1(geometry),pl=polygons.length,indexesPerVertex=new Map,temp=[0,0,0];polygons.forEach(((polygon,index)=>{polygon.vertices.forEach((vertex=>{((map,vertex,index)=>{const key=`${vertex}`,mapping=map.get(key);void 0===mapping?map.set(key,[index]):mapping.push(index)})(indexesPerVertex,snap$2(temp,vertex,eps),index)}))}));const indexesPerPolygon=polygons.map((polygon=>{let indexes=[];return polygon.vertices.forEach((vertex=>{indexes=indexes.concat(((map,vertex)=>{const key=`${vertex}`;return map.get(key)})(indexesPerVertex,snap$2(temp,vertex,eps)))})),{e:1,d:(array=indexes,array.sort(((a,b)=>a-b)).filter(((item,pos,ary)=>!pos||item!==ary[pos-1])))};var array}));indexesPerVertex.clear();let merges=0;const ippl=indexesPerPolygon.length;for(let i=0;i<ippl;i++){const mapi=indexesPerPolygon[i];if(mapi.e>0){const indexes=new Array(pl);indexes[i]=!0;do{merges=0,indexes.forEach(((e,j)=>{const mapj=indexesPerPolygon[j];if(mapj.e>0){mapj.e=-1;for(let d=0;d<mapj.d.length;d++)indexes[mapj.d[d]]=!0;merges++}}))}while(merges>0);mapi.indexes=indexes}}const newgeometries=[];for(let i=0;i<ippl;i++)if(indexesPerPolygon[i].indexes){const newpolygons=[];indexesPerPolygon[i].indexes.forEach(((e,p)=>newpolygons.push(polygons[p]))),newgeometries.push(create$8(newpolygons))}return newgeometries})(object):Array.isArray(object)?scission(...object):object));return 1===results.length?results[0]:results},unionGeom2=geometries=>{let newGeometry=geometries.shift();return geometries.forEach((geometry=>{newGeometry=boolean(newGeometry,geometry,1)})),newGeometry},unionGeom3Sub=(geometry1,geometry2)=>{if(!mayOverlap(geometry1,geometry2))return unionForNonIntersecting(geometry1,geometry2);const a=new Tree(toPolygons$1(geometry1)),b=new Tree(toPolygons$1(geometry2));a.clipTo(b,!1),b.clipTo(a),b.invert(),b.clipTo(a),b.invert();const newPolygons=a.allPolygons().concat(b.allPolygons());return create$8(newPolygons)},unionForNonIntersecting=(geometry1,geometry2)=>{let newpolygons=toPolygons$1(geometry1);return newpolygons=newpolygons.concat(toPolygons$1(geometry2)),create$8(newpolygons)},union=(...geometries)=>{if(0===(geometries=coalesce(geometries)).length)return;if(!areAllShapesTheSameType(geometries))throw new Error("union arguments must be the same geometry type");const geometry=geometries[0];if(isA$5(geometry))return unionGeom2(geometries);if(isA$3(geometry))return(geometries=>{let i;for(i=1;i<geometries.length;i+=2)geometries.push(unionGeom3Sub(geometries[i-1],geometries[i]));let newGeometry=geometries[i-1];return newGeometry=retessellate(newGeometry),newGeometry})(geometries);throw new Error("union unsupported geometry type")};Object.freeze({__proto__:null,intersect:(...geometries)=>{if(0===(geometries=coalesce(geometries)).length)return;if(!areAllShapesTheSameType(geometries))throw new Error("intersect arguments must be the same geometry type");const geometry=geometries[0];if(isA$5(geometry))return(geometries=>{let newGeometry=geometries.shift();return geometries.forEach((geometry=>{newGeometry=boolean(newGeometry,geometry,0)})),newGeometry})(geometries);if(isA$3(geometry))return(geometries=>{let newGeometry=geometries.shift();return geometries.forEach((geometry=>{newGeometry=((geometry1,geometry2)=>{if(!mayOverlap(geometry1,geometry2))return create$8();const a=new Tree(toPolygons$1(geometry1)),b=new Tree(toPolygons$1(geometry2));a.invert(),b.clipTo(a),b.invert(),a.clipTo(b),b.clipTo(a),a.addPolygons(b.allPolygons()),a.invert();const newPolygons=a.allPolygons();return create$8(newPolygons)})(newGeometry,geometry)})),newGeometry=retessellate(newGeometry),newGeometry})(geometries);throw new Error("intersect unsupported geometry type")},scission:scission,subtract:(...geometries)=>{if(0===(geometries=coalesce(geometries)).length)return;if(!areAllShapesTheSameType(geometries))throw new Error("subtract arguments must be the same geometry type");const geometry=geometries[0];if(isA$5(geometry))return(geometries=>{let newGeometry=geometries.shift();return geometries.forEach((geometry=>{newGeometry=boolean(newGeometry,geometry,2)})),newGeometry})(geometries);if(isA$3(geometry))return(geometries=>{let newGeometry=geometries.shift();return geometries.forEach((geometry=>{newGeometry=((geometry1,geometry2)=>{if(!mayOverlap(geometry1,geometry2))return clone$7(geometry1);const a=new Tree(toPolygons$1(geometry1)),b=new Tree(toPolygons$1(geometry2));a.invert(),a.clipTo(b),b.clipTo(a,!0),a.addPolygons(b.allPolygons()),a.invert();const newPolygons=a.allPolygons();return create$8(newPolygons)})(newGeometry,geometry)})),newGeometry=retessellate(newGeometry),newGeometry})(geometries);throw new Error("subtract unsupported geometry type")},union:union});const extrudeLinearGeom2=(options,geometry)=>{let{offset:offset,twistAngle:twistAngle,twistSteps:twistSteps,repair:repair}=Object.assign({},{offset:[0,0,1],twistAngle:0,twistSteps:12,repair:!0},options);if(twistSteps<1)throw new Error("twistSteps must be 1 or more");0===twistAngle&&(twistSteps=1);const offsetV=clone$9(offset);let baseSlice=fromGeom2(geometry);offsetV[2]<0&&(baseSlice=reverse$2(baseSlice));const matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],output=extrudeFromSlices(options={numberOfSlices:twistSteps+1,capStart:!0,capEnd:!0,repair:repair,callback:(progress,index,base)=>{const Zrotation=index/twistSteps*twistAngle,Zoffset=scale$3([0,0,0],offsetV,index/twistSteps);return multiply$1(matrix,fromZRotation(matrix,Zrotation),fromTranslation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],Zoffset)),transform$3(matrix,base)}},baseSlice);return geometry.color&&(output.color=geometry.color),output},extrudeLinear=(options,...objects)=>{const{height:height,twistAngle:twistAngle,twistSteps:twistSteps,repair:repair}=Object.assign({},{height:1,twistAngle:0,twistSteps:1,repair:!0},options);options={offset:[0,0,height],twistAngle:twistAngle,twistSteps:twistSteps,repair:repair};const results=objects.map((object=>isA$2(object)?((options,geometry)=>{if(!geometry.isClosed)throw new Error("extruded path must be closed");const points=toPoints$1(geometry),geometry2=create$a([points]);return geometry.color&&(geometry2.color=geometry.color),extrudeLinearGeom2(options,geometry2)})(options,object):isA$5(object)?extrudeLinearGeom2(options,object):Array.isArray(object)?extrudeLinear(options,...object):object));return 1===results.length?results[0]:results},aboutEqualNormals=(a,b)=>Math.abs(a[0]-b[0])<=NEPS&&Math.abs(a[1]-b[1])<=NEPS&&Math.abs(a[2]-b[2])<=NEPS,project=(options,...objects)=>{const{axis:axis,origin:origin}=Object.assign({},{axis:[0,0,1],origin:[0,0,0]},options);options={axis:axis,origin:origin};const results=objects.map((object=>isA$3(object)?((options,geometry)=>{const projPlane=fromNormalAndPoint([0,0,0,0],options.axis,options.origin);if(Number.isNaN(projPlane[0])||Number.isNaN(projPlane[1])||Number.isNaN(projPlane[2])||Number.isNaN(projPlane[3]))throw new Error("project: invalid axis or origin");const epsilon=measureEpsilon(geometry),epsilonArea=epsilon*epsilon*Math.sqrt(3)/4;if(0===epsilon)return create$a();const polygons=toPolygons$1(geometry);let projPolys=[];for(let i=0;i<polygons.length;i++){const newVertices=polygons[i].vertices.map((v=>projectionOfPoint(projPlane,v))),newPoly=create$7(newVertices),newPlane=plane(newPoly);aboutEqualNormals(projPlane,newPlane)&&(measureArea$2(newPoly)<epsilonArea||projPolys.push(newPoly))}if(!aboutEqualNormals(projPlane,[0,0,1])){const rotation=fromVectorRotation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],projPlane,[0,0,1]);projPolys=projPolys.map((p=>transform$7(rotation,p)))}projPolys=projPolys.sort(((a,b)=>measureArea$2(b)-measureArea$2(a)));const projGeoms=projPolys.map((p=>{const cloned=p.vertices.map(clone$8);return create$a([cloned])})),output=unionGeom2(projGeoms);return geometry.color&&(output.color=geometry.color),output})(options,object):Array.isArray(object)?project(options,...object):object));return 1===results.length?results[0]:results};var extrusion=Object.freeze({__proto__:null,extrudeFromSlices:extrudeFromSlices,extrudeLinear:extrudeLinear,extrudeRotate:extrudeRotate,extrudeHelical:(options,geometry)=>{const defaults={angle:TAU,startAngle:0,pitch:10,endOffset:0,segmentsPerRotation:32},{angle:angle,endOffset:endOffset,segmentsPerRotation:segmentsPerRotation,startAngle:startAngle}=Object.assign({},defaults,options);let pitch;if(pitch=!options.pitch&&options.height?options.height/(angle/TAU):options.pitch?options.pitch:defaults.pitch,segmentsPerRotation<3)throw new Error("The number of segments per rotation needs to be at least 3.");let baseSlice=fromGeom2(geometry);measureBoundingBox(geometry)[1][0]<=0&&(baseSlice=reverse$2(baseSlice));const calculatedSegments=Math.round(segmentsPerRotation/TAU*Math.abs(angle)),segments=calculatedSegments>=2?calculatedSegments:2,step1=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];let matrix;return extrudeFromSlices({numberOfSlices:segments+1,callback:(progress,index,base)=>{const zRotation=startAngle+angle/segments*index;return multiply$1(step1,fromTranslation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],[endOffset/segments*index,0,(zRotation-startAngle)/TAU*pitch*Math.sign(angle)]),fromXRotation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],-TAU/4*Math.sign(angle))),matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],multiply$1(matrix,fromZRotation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],zRotation),step1),transform$3(matrix,baseSlice)}},baseSlice)},project:project});const hullPoints2=uniquePoints=>{let min=fromValues$2(1/0,1/0);uniquePoints.forEach((point=>{(point[1]<min[1]||point[1]===min[1]&&point[0]<min[0])&&(min=point)}));const squaredDistance$1=point=>squaredDistance(point,min),polarAngle=point=>point[0]===min[0]&&point[1]===min[1]?-1/0:-(point[0]-min[0])/(point[1]-min[1]),sorted=uniquePoints;sorted.sort(((pt1,pt2)=>{const pa1=polarAngle(pt1),pa2=polarAngle(pt2);return pa1===pa2?squaredDistance$1(pt1)-squaredDistance$1(pt2):pa1-pa2}));const stack=[];return sorted.forEach((point=>{let cnt=stack.length;for(;cnt>1&&ccw(stack[cnt-2],stack[cnt-1],point)<=Number.EPSILON;)stack.pop(),cnt=stack.length;stack.push(point)})),stack},ccw=(v1,v2,v3)=>(v2[0]-v1[0])*(v3[1]-v1[1])-(v2[1]-v1[1])*(v3[0]-v1[0]),toUniquePoints=geometries=>{const found=new Set,uniquePoints=[],addPoint=point=>{const key=point.toString();found.has(key)||(uniquePoints.push(point),found.add(key))};return geometries.forEach((geometry=>{isA$5(geometry)?toPoints$3(geometry).forEach(addPoint):isA$3(geometry)?toPoints$2(geometry).forEach((points=>points.forEach(addPoint))):isA$2(geometry)&&toPoints$1(geometry).forEach(addPoint)})),uniquePoints},hullPoints3=uniquePoints=>runner(uniquePoints,{skipTriangulation:!0}).map((face=>{const vertices=face.map((index=>uniquePoints[index]));return create$7(vertices)})),hull=(...geometries)=>{if(0===(geometries=coalesce(geometries)).length)return;if(!areAllShapesTheSameType(geometries))throw new Error("only hulls of the same type are supported");const geometry=geometries[0];return isA$2(geometry)?(geometries=>{const unique=toUniquePoints(geometries),hullPoints=hullPoints2(unique);return fromPoints$2({closed:!0},hullPoints)})(geometries):isA$5(geometry)?(geometries=>{const unique=toUniquePoints(geometries),hullPoints=hullPoints2(unique);return hullPoints.length<3?create$a():create$a([hullPoints])})(geometries):isA$3(geometry)?(geometries=>{const unique=toUniquePoints(geometries);return 0===unique.length?create$8():create$8(hullPoints3(unique))})(geometries):geometry};Object.freeze({__proto__:null,hull:hull,hullChain:(...geometries)=>{if(0===(geometries=coalesce(geometries)).length)return;if(1===geometries.length)return geometries[0];if(!areAllShapesTheSameType(geometries))throw new Error("only hulls of the same type are supported");const hulls=[];for(let i=1;i<geometries.length;i++)hulls.push(hull(geometries[i-1],geometries[i]));return union(hulls)},hullPoints2:hullPoints2,hullPoints3:hullPoints3});const snapPolygons=(epsilon,polygons)=>{let newPolygons=polygons.map((polygon=>{const snapVertices=polygon.vertices.map((vertex=>snap$2([0,0,0],vertex,epsilon))),newVertices=[];for(let i=0;i<snapVertices.length;i++){const j=(i+1)%snapVertices.length;equals$7(snapVertices[i],snapVertices[j])||newVertices.push(snapVertices[i])}const newPolygon=create$7(newVertices);return polygon.color&&(newPolygon.color=polygon.color),newPolygon}));const epsilonArea=epsilon*epsilon*Math.sqrt(3)/4;return newPolygons=newPolygons.filter((polygon=>((epsilon,polygon)=>{const area=Math.abs(measureArea$2(polygon));return Number.isFinite(area)&&area>epsilon})(epsilonArea,polygon))),newPolygons},createEdges=polygon=>{const vertices=toVertices$1(polygon),edges=[];for(let i=0;i<vertices.length;i++){const j=(i+1)%vertices.length,edge={v1:vertices[i],v2:vertices[j]};edges.push(edge)}for(let i=0;i<edges.length;i++){const j=(i+1)%vertices.length;edges[i].next=edges[j],edges[j].prev=edges[i]}return edges},insertEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.set(key,edge)},deleteEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.delete(key)},findOppositeEdge=(edges,edge)=>{const key=`${edge.v2}:${edge.v1}`;return edges.get(key)},calculateAnglesBetween=(current,opposite,normal)=>{let v0=current.prev.v1,v1=current.prev.v2,v2=opposite.next.v2;const angle1=calculateAngle(v0,v1,v2,normal);return v0=opposite.prev.v1,v1=opposite.prev.v2,v2=current.next.v2,[angle1,calculateAngle(v0,v1,v2,normal)]},v1=[0,0,0],v2=[0,0,0],calculateAngle=(prevVertex,midVertex,nextVertex,normal)=>{const d0=subtract$3(v1,midVertex,prevVertex),d1=subtract$3(v2,nextVertex,midVertex);return cross$1(d0,d0,d1),dot$2(d0,normal)},mergePolygons=(epsilon,polygons)=>{const polygonsPerPlane=[];polygons.forEach((polygon=>{const mapping=polygonsPerPlane.find((element=>{return plane1=element[0],plane2=plane(polygon),Math.abs(plane1[3]-plane2[3])<15e-8&&aboutEqualNormals(plane1,plane2);var plane1,plane2}));mapping?mapping[1].push(polygon):polygonsPerPlane.push([plane(polygon),[polygon]])}));let destPolygons=[];return polygonsPerPlane.forEach((mapping=>{const retesselatedPolygons=(sourcePolygons=>{if(sourcePolygons.length<2)return sourcePolygons;const normal=sourcePolygons[0].plane,polygons=sourcePolygons.slice(),edgeList=new Map;for(;polygons.length>0;){const polygon=polygons.shift(),edges=createEdges(polygon);for(let i=0;i<edges.length;i++){const current=edges[i],opposite=findOppositeEdge(edgeList,current);if(opposite){const angles=calculateAnglesBetween(current,opposite,normal);if(angles[0]>=0&&angles[1]>=0){const edge1=opposite.next,edge2=current.next;current.prev.next=opposite.next,current.next.prev=opposite.prev,opposite.prev.next=current.next,opposite.next.prev=current.prev,current.v1=null,current.v2=null,current.next=null,current.prev=null,deleteEdge(edgeList,opposite),opposite.v1=null,opposite.v2=null,opposite.next=null,opposite.prev=null;const mergeEdges=(list,e1,e2)=>{const newEdge={v1:e2.v1,v2:e1.v2,next:e1.next,prev:e2.prev};e2.prev.next=newEdge,e1.next.prev=newEdge,deleteEdge(list,e1),e1.v1=null,e1.v2=null,e1.next=null,e1.prev=null,deleteEdge(list,e2),e2.v1=null,e2.v2=null,e2.next=null,e2.prev=null};0===angles[0]&&mergeEdges(edgeList,edge1,edge1.prev),0===angles[1]&&mergeEdges(edgeList,edge2,edge2.prev)}}else current.next&&insertEdge(edgeList,current)}}const destPolygons=[];return edgeList.forEach((edge=>{const polygon=(edge=>{const vertices=[];for(;edge.next;){const next=edge.next;vertices.push(edge.v1),edge.v1=null,edge.v2=null,edge.next=null,edge.prev=null,edge=next}return vertices.length>0?create$7(vertices):null})(edge);polygon&&destPolygons.push(polygon)})),edgeList.clear(),destPolygons})(mapping[1]);destPolygons=destPolygons.concat(retesselatedPolygons)})),destPolygons},getTag=vertex=>`${vertex}`,addSide=(sideMap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),newSideTag=`${startTag}/${endTag}`,reverseSideTag=`${endTag}/${startTag}`;if(sideMap.has(reverseSideTag))return deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,vertex1,vertex0,null),null;const newSideObj={vertex0:vertex0,vertex1:vertex1,polygonIndex:polygonIndex};return sideMap.has(newSideTag)?sideMap.get(newSideTag).push(newSideObj):sideMap.set(newSideTag,[newSideObj]),vertextag2sidestart.has(startTag)?vertextag2sidestart.get(startTag).push(newSideTag):vertextag2sidestart.set(startTag,[newSideTag]),vertextag2sideend.has(endTag)?vertextag2sideend.get(endTag).push(newSideTag):vertextag2sideend.set(endTag,[newSideTag]),newSideTag},deleteSide=(sidemap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),sideTag=`${startTag}/${endTag}`;let idx=-1;const sideObjs=sidemap.get(sideTag);for(let i=0;i<sideObjs.length;i++){const sideObj=sideObjs[i];let sideTag=getTag(sideObj.vertex0);if(sideTag===startTag&&(sideTag=getTag(sideObj.vertex1),sideTag===endTag&&(null===polygonIndex||sideObj.polygonIndex===polygonIndex))){idx=i;break}}sideObjs.splice(idx,1),0===sideObjs.length&&sidemap.delete(sideTag),idx=vertextag2sidestart.get(startTag).indexOf(sideTag),vertextag2sidestart.get(startTag).splice(idx,1),0===vertextag2sidestart.get(startTag).length&&vertextag2sidestart.delete(startTag),idx=vertextag2sideend.get(endTag).indexOf(sideTag),vertextag2sideend.get(endTag).splice(idx,1),0===vertextag2sideend.get(endTag).length&&vertextag2sideend.delete(endTag)},generalizeGeom3=(options,geometry)=>{const{snap:snap,simplify:simplify,triangulate:triangulate}=Object.assign({},{snap:!1,simplify:!1,triangulate:!1},options),epsilon=measureEpsilon(geometry);let polygons=toPolygons$1(geometry);snap&&(polygons=snapPolygons(epsilon,polygons)),simplify&&(polygons=mergePolygons(0,polygons)),triangulate&&(polygons=(polygons=>{const sideMap=new Map;for(let polygonIndex=0;polygonIndex<polygons.length;polygonIndex++){const polygon=polygons[polygonIndex],numVertices=polygon.vertices.length;if(numVertices>=3){let vertex=polygon.vertices[0],vertexTag=getTag(vertex);for(let vertexIndex=0;vertexIndex<numVertices;vertexIndex++){let nextVertexIndex=vertexIndex+1;nextVertexIndex===numVertices&&(nextVertexIndex=0);const nextVertex=polygon.vertices[nextVertexIndex],nextVertexTag=getTag(nextVertex),sideTag=`${vertexTag}/${nextVertexTag}`,reverseSideTag=`${nextVertexTag}/${vertexTag}`;if(sideMap.has(reverseSideTag)){const ar=sideMap.get(reverseSideTag);ar.splice(-1,1),0===ar.length&&sideMap.delete(reverseSideTag)}else{const sideobj={vertex0:vertex,vertex1:nextVertex,polygonIndex:polygonIndex};sideMap.has(sideTag)?sideMap.get(sideTag).push(sideobj):sideMap.set(sideTag,[sideobj])}vertex=nextVertex,vertexTag=nextVertexTag}}else console.warn("warning: invalid polygon found during insertTjunctions")}if(sideMap.size>0){const vertextag2sidestart=new Map,vertextag2sideend=new Map,sidesToCheck=new Map;for(const[sidetag,sideObjs]of sideMap)sidesToCheck.set(sidetag,!0),sideObjs.forEach((sideObj=>{const starttag=getTag(sideObj.vertex0),endtag=getTag(sideObj.vertex1);vertextag2sidestart.has(starttag)?vertextag2sidestart.get(starttag).push(sidetag):vertextag2sidestart.set(starttag,[sidetag]),vertextag2sideend.has(endtag)?vertextag2sideend.get(endtag).push(sidetag):vertextag2sideend.set(endtag,[sidetag])}));const newPolygons=polygons.slice(0);for(;0!==sideMap.size;){for(const sideTag of sideMap.keys())sidesToCheck.set(sideTag,!0);let doneSomething=!1;for(;;){const sideTags=Array.from(sidesToCheck.keys());if(0===sideTags.length)break;const sideTagToCheck=sideTags[0];let doneWithSide=!0;if(sideMap.has(sideTagToCheck)){const sideObj=sideMap.get(sideTagToCheck)[0];for(let directionIndex=0;directionIndex<2;directionIndex++){const startVertex=0===directionIndex?sideObj.vertex0:sideObj.vertex1,endVertex=0===directionIndex?sideObj.vertex1:sideObj.vertex0,startVertexTag=getTag(startVertex),endVertexTag=getTag(endVertex);let matchingSides=[];0===directionIndex?vertextag2sideend.has(startVertexTag)&&(matchingSides=vertextag2sideend.get(startVertexTag)):vertextag2sidestart.has(startVertexTag)&&(matchingSides=vertextag2sidestart.get(startVertexTag));for(let matchingSideIndex=0;matchingSideIndex<matchingSides.length;matchingSideIndex++){const matchingSideTag=matchingSides[matchingSideIndex],matchingSide=sideMap.get(matchingSideTag)[0],matchingSideStartVertex=0===directionIndex?matchingSide.vertex0:matchingSide.vertex1;if(0===directionIndex?matchingSide.vertex1:matchingSide.vertex0,getTag(matchingSideStartVertex)===endVertexTag){deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,startVertex,endVertex,null),deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,startVertex,null),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}{const startPos=startVertex,endPos=endVertex,direction=subtract$3([0,0,0],matchingSideStartVertex,startPos),t=dot$2(subtract$3([0,0,0],endPos,startPos),direction)/dot$2(direction,direction);if(t>0&&t<1){const closestVertex=scale$3([0,0,0],direction,t);if(add$1(closestVertex,closestVertex,startPos),squaredDistance$1(closestVertex,endPos)<EPS*EPS){const polygonIndex=matchingSide.polygonIndex,polygon=newPolygons[polygonIndex],insertionVertexTag=getTag(matchingSide.vertex1);let insertionVertexTagIndex=-1;for(let i=0;i<polygon.vertices.length;i++)if(getTag(polygon.vertices[i])===insertionVertexTag){insertionVertexTagIndex=i;break}const newVertices=polygon.vertices.slice(0);newVertices.splice(insertionVertexTagIndex,0,endVertex);const newPolygon=create$7(newVertices);newPolygons[polygonIndex]=newPolygon,deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,matchingSide.vertex1,polygonIndex);const newSideTag1=addSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,endVertex,polygonIndex),newSideTag2=addSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,matchingSide.vertex1,polygonIndex);null!==newSideTag1&&sidesToCheck.set(newSideTag1,!0),null!==newSideTag2&&sidesToCheck.set(newSideTag2,!0),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}}}}}}doneWithSide&&sidesToCheck.delete(sideTagToCheck)}if(!doneSomething)break}polygons=newPolygons}return sideMap.clear(),polygons})(polygons),polygons=((epsilon,polygons)=>{const triangles=[];return polygons.forEach((polygon=>{((epsilon,polygon,triangles)=>{const nv=polygon.vertices.length;if(nv>3){if(nv>4){const midpoint=[0,0,0];polygon.vertices.forEach((vertex=>add$1(midpoint,midpoint,vertex))),snap$2(midpoint,divide$1(midpoint,midpoint,[nv,nv,nv]),epsilon);for(let i=0;i<nv;i++){const poly=create$7([midpoint,polygon.vertices[i],polygon.vertices[(i+1)%nv]]);polygon.color&&(poly.color=polygon.color),triangles.push(poly)}return}const poly0=create$7([polygon.vertices[0],polygon.vertices[1],polygon.vertices[2]]),poly1=create$7([polygon.vertices[0],polygon.vertices[2],polygon.vertices[3]]);return polygon.color&&(poly0.color=polygon.color,poly1.color=polygon.color),void triangles.push(poly0,poly1)}triangles.push(polygon)})(epsilon,polygon,triangles)})),triangles})(epsilon,polygons));const clone=Object.assign({},geometry);return clone.polygons=polygons,clone},generalize=(options,...geometries)=>{const results=geometries.map((geometry=>isA$2(geometry)||isA$5(geometry)?((options,geometry)=>geometry)(0,geometry):isA$3(geometry)?generalizeGeom3(options,geometry):Array.isArray(geometry)?generalize(options,...geometry):geometry));return 1===results.length?results[0]:results},snap=(...geometries)=>{const results=geometries.map((geometry=>isA$2(geometry)?(geometry=>{const epsilon=measureEpsilon(geometry),newPoints=toPoints$1(geometry).map((point=>snap$1([0,0],point,epsilon)));return create$5(newPoints)})(geometry):isA$5(geometry)?(geometry=>{const epsilon=measureEpsilon(geometry);let newOutlines=toOutlines(geometry).map((outline=>{let prev=snap$1([0,0],outline[outline.length-1],epsilon);const newOutline=[];return outline.forEach((point=>{const snapped=snap$1([0,0],point,epsilon);equals$6(prev,snapped)||newOutline.push(snapped),prev=snapped})),newOutline}));return newOutlines=newOutlines.filter((outline=>measureArea$1(create$3(outline)))),create$a(newOutlines)})(geometry):isA$3(geometry)?(geometry=>{const epsilon=measureEpsilon(geometry),polygons=toPolygons$1(geometry),newPolygons=snapPolygons(epsilon,polygons);return create$8(newPolygons)})(geometry):Array.isArray(geometry)?snap(...geometry):geometry));return 1===results.length?results[0]:results};Object.freeze({__proto__:null,generalize:generalize,snap:snap,retessellate:retessellate});const offsetFromPoints=(options,points)=>{let{delta:delta,corners:corners,closed:closed,segments:segments}=Object.assign({},{delta:1,corners:"edge",closed:!1,segments:16},options);if(Math.abs(delta)<EPS)return points;if(points.length<2)return points;let rotation=options.closed?area$1(points):1;0===rotation&&(rotation=1);const orientation=rotation>0&&delta>=0||rotation<0&&delta<0;delta=Math.abs(delta);let previousSegment=null,newPoints=[];const newCorners=[],of=[0,0],n=points.length;for(let i=0;i<n;i++){const j=(i+1)%n,p0=points[i],p1=points[j];orientation?subtract$1(of,p0,p1):subtract$1(of,p1,p0),normal(of,of),normalize(of,of),scale$1(of,of,delta);const n0=add([0,0],p0,of),n1=add([0,0],p1,of),currentSegment=[n0,n1];if(null!=previousSegment&&(closed||!closed&&0!==j)){const ip=intersect$1(previousSegment[0],previousSegment[1],currentSegment[0],currentSegment[1],!0);ip?(newPoints.pop(),currentSegment[0]=ip):newCorners.push({c:p0,s0:previousSegment,s1:currentSegment})}previousSegment=[n0,n1],(0!==j||closed)&&(newPoints.push(currentSegment[0]),newPoints.push(currentSegment[1]))}if(closed&&null!=previousSegment){const n0=newPoints[0],n1=newPoints[1],ip=intersect$1(previousSegment[0],previousSegment[1],n0,n1,!0);if(ip)newPoints[0]=ip,newPoints.pop();else{const p0=points[0],currentSegment=[n0,n1];newCorners.push({c:p0,s0:previousSegment,s1:currentSegment})}}if("edge"===corners){const pointIndex=new Map;newPoints.forEach(((point,index)=>pointIndex.set(point,index)));const line0=[0,1,0],line1=[0,1,0];newCorners.forEach((corner=>{fromPoints$1(line0,corner.s0[0],corner.s0[1]),fromPoints$1(line1,corner.s1[0],corner.s1[1]);const ip=intersectPointOfLines(line0,line1);if(Number.isFinite(ip[0])&&Number.isFinite(ip[1])){const p0=corner.s0[1],i=pointIndex.get(p0);newPoints[i]=ip,newPoints[(i+1)%newPoints.length]=void 0}else{const p0=corner.s1[0],i=pointIndex.get(p0);newPoints[i]=void 0}})),newPoints=newPoints.filter((p=>void 0!==p))}if("round"===corners){let cornerSegments=Math.floor(segments/4);const v0=[0,0];newCorners.forEach((corner=>{let rotation=angleRadians(subtract$1(v0,corner.s1[0],corner.c));if(rotation-=angleRadians(subtract$1(v0,corner.s0[1],corner.c)),orientation&&rotation<0&&(rotation+=Math.PI,rotation<0&&(rotation+=Math.PI)),!orientation&&rotation>0&&(rotation-=Math.PI,rotation>0&&(rotation-=Math.PI)),0!==rotation){cornerSegments=Math.floor(segments*(Math.abs(rotation)/TAU));const step=rotation/cornerSegments,start=angleRadians(subtract$1(v0,corner.s0[1],corner.c)),cornerPoints=[];for(let i=1;i<cornerSegments;i++){const point=fromAngleRadians([0,0],start+step*i);scale$1(point,point,delta),add(point,point,corner.c),cornerPoints.push(point)}if(cornerPoints.length>0){const p0=corner.s0[1];let i=newPoints.findIndex((point=>equals$6(p0,point)));i=(i+1)%newPoints.length,newPoints.splice(i,0,...cornerPoints)}}else{const p0=corner.s1[0],i=newPoints.findIndex((point=>equals$6(p0,point)));newPoints.splice(i,1)}}))}return newPoints},mapPlaneToVertex=(map,vertex,plane)=>{const key=vertex.toString();if(map.has(key))map.get(key)[1].push(plane);else{const entry=[vertex,[plane]];map.set(key,entry)}},mapPlaneToEdge=(map,edge,plane)=>{const key0=edge[0].toString(),key1=edge[1].toString(),key=key0<key1?`${key0},${key1}`:`${key1},${key0}`;if(map.has(key))map.get(key)[1].push(plane);else{const entry=[edge,[plane]];map.set(key,entry)}},addUniqueAngle=(map,angle)=>{map.findIndex((item=>item===angle))<0&&map.push(angle)},offset=(options,...objects)=>{const results=objects.map((object=>isA$2(object)?((options,geometry)=>{const{delta:delta,corners:corners,segments:segments}=Object.assign({},{delta:1,corners:"edge",segments:16},options);if(delta<=0)throw new Error("the given delta must be positive for paths");if("edge"!==corners&&"chamfer"!==corners&&"round"!==corners)throw new Error('corners must be "edge", "chamfer", or "round"');const closed=geometry.isClosed,points=toPoints$1(geometry),paths={points:points,external:offsetFromPoints({delta:delta,corners:corners,segments:segments,closed:closed},points),internal:offsetFromPoints({delta:-delta,corners:corners,segments:segments,closed:closed},points)},output=geometry.isClosed?(paths=>{let{external:external,internal:internal}=paths;return external.length<2?create$a():(area$1(external)<0?external=external.reverse():internal=internal.reverse(),create$a([external,internal]))})(paths):((paths,segments,corners,delta)=>{const{points:points,external:external,internal:internal}=paths;if(0===points.length)return create$a();if(1===points.length)return circle({center:points[0],radius:delta});const capSegments=Math.floor(segments/2),e2iCap=[],i2eCap=[];if("round"===corners&&capSegments>0){const step=Math.PI/capSegments,eCorner=points[points.length-1],e2iStart=angleRadians(subtract$1([0,0],external[external.length-1],eCorner)),iCorner=points[0],i2eStart=angleRadians(subtract$1([0,0],internal[0],iCorner));for(let i=1;i<capSegments;i++){let radians=e2iStart+step*i,point=fromAngleRadians([0,0],radians);scale$1(point,point,delta),add(point,point,eCorner),e2iCap.push(point),radians=i2eStart+step*i,point=fromAngleRadians([0,0],radians),scale$1(point,point,delta),add(point,point,iCorner),i2eCap.push(point)}}const allPoints=[];return allPoints.push(...external,...e2iCap,...internal.reverse(),...i2eCap),create$a([allPoints])})(paths,segments,corners,delta);return geometry.color&&(output.color=geometry.color),output})(options,object):isA$5(object)?((options,geometry)=>{const{delta:delta,corners:corners,segments:segments,expandHoles:expandHoles}=Object.assign({},{delta:1,corners:"edge",segments:16,expandHoles:!1},options);if("edge"!==corners&&"chamfer"!==corners&&"round"!==corners)throw new Error('corners must be "edge", "chamfer", or "round"');if(!Number.isFinite(delta))throw new Error("delta must be a finite number");if("round"===corners&&!Number.isFinite(segments))throw new Error("segments must be a finite number");if("round"===corners&&!(segments>0))throw new Error("segments must be greater than zero");const outlines=toOutlines(geometry),newOutlines=outlines.map((outline=>{let outside=!0;if(expandHoles){const level=outlines.reduce(((acc,polygon)=>acc+arePointsInside(outline,create$3(polygon))),0);outside=level%2==0}return offsetFromPoints(options={delta:outside?delta:-delta,corners:corners,closed:!0,segments:segments},outline)})),output=create$a(newOutlines);return geometry.color&&(output.color=geometry.color),output})(options,object):isA$3(object)?((options,geometry)=>{const{delta:delta,corners:corners,segments:segments}=Object.assign({},{delta:1,corners:"round",segments:12},options);if("round"!==corners)throw new Error('corners must be "round" for 3D geometries');const expanded=((options,geometry)=>{const{delta:delta,segments:segments}=Object.assign({},{delta:1,segments:12},options);let result=create$8();const vertices2planes=new Map,edges2planes=new Map,v1=[0,0,0],v2=[0,0,0];return toPolygons$1(geometry).forEach((polygon=>{const extrudeVector=scale$3([0,0,0],plane(polygon),2*delta),extrudedFace=((offsetVector,polygon1)=>{dot$2(plane(polygon1),offsetVector)>0&&(polygon1=invert$1(polygon1));const newPolygons=[polygon1],polygon2=transform$7(fromTranslation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],offsetVector),polygon1),numVertices=polygon1.vertices.length;for(let i=0;i<numVertices;i++){const nexti=i<numVertices-1?i+1:0,sideFacePolygon=create$7([polygon1.vertices[i],polygon2.vertices[i],polygon2.vertices[nexti],polygon1.vertices[nexti]]);newPolygons.push(sideFacePolygon)}return newPolygons.push(invert$1(polygon2)),create$8(newPolygons)})(extrudeVector,transform$7(fromTranslation([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],scale$3([0,0,0],extrudeVector,-.5)),polygon));result=unionGeom3Sub(result,extrudedFace);const vertices=polygon.vertices;for(let i=0;i<vertices.length;i++){mapPlaneToVertex(vertices2planes,vertices[i],plane(polygon));const j=(i+1)%vertices.length,edge=[vertices[i],vertices[j]];mapPlaneToEdge(edges2planes,edge,plane(polygon))}})),edges2planes.forEach((item=>{const edge=item[0],planes=item[1],startVertex=edge[0],endVertex=edge[1],zBase=subtract$3([0,0,0],endVertex,startVertex);normalize$1(zBase,zBase);const xBase=planes[0],yBase=cross$1([0,0,0],xBase,zBase);let angles=[];for(let i=0;i<segments;i++)addUniqueAngle(angles,i*TAU/segments);for(let i=0,iMax=planes.length;i<iMax;i++){const planeNormal=planes[i],si=dot$2(yBase,planeNormal),co=dot$2(xBase,planeNormal);let angle=Math.atan2(si,co);angle<0&&(angle+=TAU),addUniqueAngle(angles,angle),angle=Math.atan2(-si,-co),angle<0&&(angle+=TAU),addUniqueAngle(angles,angle)}angles=angles.sort(fnNumberSort);const numAngles=angles.length;let prevP1,prevP2;const startFaceVertices=[],endFaceVertices=[],polygons=[];for(let i=-1;i<numAngles;i++){const angle=angles[i<0?i+numAngles:i],si=Math.sin(angle),co=Math.cos(angle);scale$3(v1,xBase,co*delta),scale$3(v2,yBase,si*delta),add$1(v1,v1,v2);const p1=add$1([0,0,0],startVertex,v1),p2=add$1([0,0,0],endVertex,v1);let skip=!1;if(i>=0&&distance$1(p1,prevP1)<EPS&&(skip=!0),!skip){if(i>=0){startFaceVertices.push(p1),endFaceVertices.push(p2);const polygon=create$7([prevP2,p2,p1,prevP1]);polygons.push(polygon)}prevP1=p1,prevP2=p2}}endFaceVertices.reverse(),polygons.push(create$7(startFaceVertices)),polygons.push(create$7(endFaceVertices));const cylinder=create$8(polygons);result=unionGeom3Sub(result,cylinder)})),vertices2planes.forEach((item=>{const vertex=item[0],planes=item[1],xaxis=planes[0];let bestzaxis=null,bestzaxisOrthogonality=0;for(let i=1;i<planes.length;i++){const normal=planes[i],cross=cross$1(v1,xaxis,normal),crossLength=length$2(cross);crossLength>.05&&crossLength>bestzaxisOrthogonality&&(bestzaxisOrthogonality=crossLength,bestzaxis=normal)}bestzaxis||(bestzaxis=orthogonal(v1,xaxis));const yaxis=cross$1(v1,xaxis,bestzaxis);normalize$1(yaxis,yaxis);const zaxis=cross$1(v2,yaxis,xaxis),corner=sphere({center:[vertex[0],vertex[1],vertex[2]],radius:delta,segments:segments,axes:[xaxis,yaxis,zaxis]});result=unionGeom3Sub(result,corner)})),retessellate(result)})(options={delta:delta,corners:corners,segments:segments},geometry),output=union(geometry,expanded);return geometry.color&&(output.color=geometry.color),output})(options,object):Array.isArray(object)?offset(options,...object):object));return 1===results.length?results[0]:results};Object.freeze({__proto__:null,offset:offset,offsetFromPoints:offsetFromPoints});const padArrayToLength=(anArray,padding,targetLength)=>{for(anArray=anArray.slice();anArray.length<targetLength;)anArray.push(padding);return anArray},alignGeometries=(geometries,modes,relativeTo)=>{const bounds=measureAggregateBoundingBox(geometries),translation=[0,0,0];for(let i=0;i<3;i++)"center"===modes[i]?translation[i]=relativeTo[i]-(bounds[0][i]+bounds[1][i])/2:"max"===modes[i]?translation[i]=relativeTo[i]-bounds[1][i]:"min"===modes[i]&&(translation[i]=relativeTo[i]-bounds[0][i]);return translate(translation,geometries)},center=(options,...objects)=>{const{axes:axes,relativeTo:relativeTo}=Object.assign({},{axes:[!0,!0,!0],relativeTo:[0,0,0]},options);if(3!==relativeTo.length)throw new Error("relativeTo must be an array of length 3");options={axes:axes,relativeTo:relativeTo};const results=objects.map((object=>isA$2(object)||isA$5(object)||isA$3(object)||Array.isArray(object)?((options,object)=>{const{axes:axes,relativeTo:relativeTo}=Object.assign({},{axes:[!0,!0,!0],relativeTo:[0,0,0]},options),bounds=measureAggregateBoundingBox(object),offset=[0,0,0];return axes[0]&&(offset[0]=relativeTo[0]-(bounds[0][0]+(bounds[1][0]-bounds[0][0])/2)),axes[1]&&(offset[1]=relativeTo[1]-(bounds[0][1]+(bounds[1][1]-bounds[0][1])/2)),axes[2]&&(offset[2]=relativeTo[2]-(bounds[0][2]+(bounds[1][2]-bounds[0][2])/2)),translate(offset,object)})(options,object):object));return 1===results.length?results[0]:results},scale=(factors,...objects)=>{if(!Array.isArray(factors))throw new Error("factors must be an array");for(factors=factors.slice();factors.length<3;)factors.push(1);if(factors[0]<=0||factors[1]<=0||factors[2]<=0)throw new Error("factors must be positive");const matrix=fromScaling([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],factors),results=objects.map((object=>isA$2(object)?transform$5(matrix,object):isA$5(object)?transform$a(matrix,object):isA$3(object)?transform$6(matrix,object):Array.isArray(object)?scale(factors,...object):object));return 1===results.length?results[0]:results},transform=(matrix,...objects)=>{const results=objects.map((object=>isA$2(object)?transform$5(matrix,object):isA$5(object)?transform$a(matrix,object):isA$3(object)?transform$6(matrix,object):Array.isArray(object)?transform(matrix,...object):object));return 1===results.length?results[0]:results};Object.freeze({__proto__:null,align:(options,...geometries)=>{options=(options=>{if(!Array.isArray(options.modes)||options.modes.length>3)throw new Error("align(): modes must be an array of length <= 3");if(options.modes=padArrayToLength(options.modes,"none",3),3!==options.modes.filter((mode=>["center","max","min","none"].includes(mode))).length)throw new Error('align(): all modes must be one of "center", "max" or "min"');if(!Array.isArray(options.relativeTo)||options.relativeTo.length>3)throw new Error("align(): relativeTo must be an array of length <= 3");if(options.relativeTo=padArrayToLength(options.relativeTo,0,3),3!==options.relativeTo.filter((alignVal=>Number.isFinite(alignVal)||null==alignVal)).length)throw new Error("align(): all relativeTo values must be a number, or null.");if("boolean"!=typeof options.grouped)throw new Error("align(): grouped must be a boolean value.");return options})(options=Object.assign({},{modes:["center","center","min"],relativeTo:[0,0,0],grouped:!1},options));let{modes:modes,relativeTo:relativeTo,grouped:grouped}=options;if(relativeTo.filter((val=>null==val)).length){const bounds=measureAggregateBoundingBox(geometries);relativeTo=((relativeTo,modes,bounds)=>{for(let i=0;i<3;i++)null==relativeTo[i]&&("center"===modes[i]?relativeTo[i]=(bounds[0][i]+bounds[1][i])/2:"max"===modes[i]?relativeTo[i]=bounds[1][i]:"min"===modes[i]&&(relativeTo[i]=bounds[0][i]));return relativeTo})(relativeTo,modes,bounds)}return grouped?(geometries=coalesce(geometries),geometries=alignGeometries(geometries,modes,relativeTo)):geometries=geometries.map((geometry=>alignGeometries(geometry,modes,relativeTo))),1===geometries.length?geometries[0]:geometries},center:center,centerX:(...objects)=>center({axes:[!0,!1,!1]},...objects),centerY:(...objects)=>center({axes:[!1,!0,!1]},...objects),centerZ:(...objects)=>center({axes:[!1,!1,!0]},...objects),mirror:mirror,mirrorX:mirrorX,mirrorY:(...objects)=>mirror({normal:[0,1,0]},...objects),mirrorZ:(...objects)=>mirror({normal:[0,0,1]},...objects),rotate:rotate,rotateX:(angle,...objects)=>rotate([angle,0,0],...objects),rotateY:(angle,...objects)=>rotate([0,angle,0],...objects),rotateZ:(angle,...objects)=>rotate([0,0,angle],...objects),scale:scale,scaleX:(factor,...objects)=>scale([factor,1,1],...objects),scaleY:(factor,...objects)=>scale([1,factor,1],...objects),scaleZ:(factor,...objects)=>scale([1,1,factor],...objects),translate:translate,translateX:(offset,...objects)=>translate([offset,0,0],...objects),translateY:(offset,...objects)=>translate([0,offset,0],...objects),translateZ:(offset,...objects)=>translate([0,0,offset],...objects),transform:transform});const geometries={geom2:{...geom2,create:sides=>fromSides(sides),fromPoints:points=>geometries.geom2.create([points])},geom3:geom3,path2:path2,poly2:poly2,poly3:{...poly3,fromPoints:points=>create$7([points]),fromPointsAndPlane:fromVerticesAndPlane,toPoints:toVertices$1}},extrusions={...extrusion,extrudeRectangular:(opt,geom)=>extrusions.extrudeLinear(opt,offset(opt,geom)),slice:geometries.slice};class BinaryReader{constructor(data){this._buffer=data,this._pos=0}readInt8(){return this._decodeInt(8,!0)}readUInt8(){return this._decodeInt(8,!1)}readInt16(){return this._decodeInt(16,!0)}readUInt16(){return this._decodeInt(16,!1)}readInt32(){return this._decodeInt(32,!0)}readUInt32(){return this._decodeInt(32,!1)}readFloat(){return this._decodeFloat(23,8)}readDouble(){return this._decodeFloat(52,11)}readChar(){return this.readString(1)}readString(length){this._checkSize(8*length);const result=this._buffer.substr(this._pos,length);return this._pos+=length,result}seek(pos){this._pos=pos,this._checkSize(0)}getPosition(){return this._pos}getSize(){return this._buffer.length}_decodeFloat(precisionBits,exponentBits){const length=precisionBits+exponentBits+1,size=length>>3;this._checkSize(length);const bias=Math.pow(2,exponentBits-1)-1,signal=this._readBits(precisionBits+exponentBits,1,size),exponent=this._readBits(precisionBits,exponentBits,size);let significand=0,divisor=2,curByte=0,startBit=0;do{const byteValue=this._readByte(++curByte,size);startBit=precisionBits%8||8;let mask=1<<startBit;for(;mask>>=1;)byteValue&mask&&(significand+=1/divisor),divisor*=2}while(precisionBits-=startBit);return this._pos+=size,exponent===1+(bias<<1)?significand?NaN:signal?-1/0:1/0:(1+-2*signal)*(exponent||significand?exponent?Math.pow(2,exponent-bias)*(1+significand):Math.pow(2,1-bias)*significand:0)}_decodeInt(bits,signed){const x=this._readBits(0,bits,bits/8),max=Math.pow(2,bits),result=signed&&x>=max/2?x-max:x;return this._pos+=bits/8,result}_shl(a,b){for(++b;--b;a=1073741824==(1073741824&(a%=2147483648))?2*a:2*(a-1073741824)+2147483647+1);return a}_readByte(i,size){return 255&this._buffer.charCodeAt(this._pos+size-i-1)}_readBits(start,length,size){const offsetLeft=(start+length)%8,offsetRight=start%8,curByte=size-(start>>3)-1;let lastByte=size+(-(start+length)>>3),diff=curByte-lastByte,sum=this._readByte(curByte,size)>>offsetRight&(1<<(diff?8-offsetRight:length))-1;for(diff&&offsetLeft&&(sum+=(this._readByte(lastByte++,size)&(1<<offsetLeft)-1)<<(diff--<<3)-offsetRight);diff;)sum+=this._shl(this._readByte(lastByte++,size),(diff--<<3)-offsetRight);return sum}_checkSize(neededBits){this._pos,Math.ceil(neededBits/8),this._buffer.length}}const bufferToBinaryString=buffer=>{let binary="";const bytes=new Uint8Array(buffer),length=bytes.byteLength;for(let i=0;i<length;i++)binary+=String.fromCharCode(bytes[i]);return binary},isBuffer=obj=>void 0!==obj.byteLength&&"function"==typeof obj.slice,isDataBinaryRobust=data=>{const text=(buf=>{if("string"!=typeof buf){const arrayBuffer=new Uint8Array(buf);let str="";for(let i=0;i<buf.byteLength;i++)str+=String.fromCharCode(arrayBuffer[i]);return str}return buf})(data);return null===/vertex[\s]+([-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+/g.exec(text)},formatAsJscad=(data,addMetaData,version,filename)=>{let code="";return addMetaData&&(code=`\n //\n // producer: JSCAD STL Deserializer ${version}\n // date: ${new Date}\n // source: ${filename}\n // objects: ${data.length}\n //\n `),code+="import * from '@jscad/modeling'\n",code+=data.join("\n"),code+=`\nexport const main = () => {\n return [${data.map(((d,i)=>`solid${i+1}()`))}]\n}\n`,code},formatAsCsg=data=>data,deserializeBinarySTL=(stl,filename,version,elementFormatter)=>{const vertices=[],triangles=[],normals=[],colors=[];let vertexIndex=0,err=0,mcolor=null;const umask=parseInt("01000000000000000",2),rmask=parseInt("00000000000011111",2),gmask=parseInt("00000001111100000",2),bmask=parseInt("00111110000000000",2),br=new BinaryReader(stl);let m=0,c=0,r=0,g=0,b=0,a=0;for(let i=0;i<80;i++)switch(m){case 6:r=br.readUInt8(),m+=1;continue;case 7:g=br.readUInt8(),m+=1;continue;case 8:b=br.readUInt8(),m+=1;continue;case 9:a=br.readUInt8(),m+=1;continue;default:switch(c=br.readChar(),c){case"C":case"O":case"L":case"R":case"=":m+=1}}10===m&&(mcolor=[r/255,g/255,b/255,a/255]);const totalTriangles=br.readUInt32();for(let tr=0;tr<totalTriangles;tr++){const no=[];no.push(br.readFloat()),no.push(br.readFloat()),no.push(br.readFloat());let v1=[];v1.push(br.readFloat()),v1.push(br.readFloat()),v1.push(br.readFloat());const v2=[];v2.push(br.readFloat()),v2.push(br.readFloat()),v2.push(br.readFloat());let v3=[];v3.push(br.readFloat()),v3.push(br.readFloat()),v3.push(br.readFloat());let skip=0;for(let i=0;i<3;i++)isNaN(v1[i])&&skip++,isNaN(v2[i])&&skip++,isNaN(v3[i])&&skip++,isNaN(no[i])&&skip++;skip>0&&console.log("bad triangle vertice coords/normal: ",skip),err+=skip;const triangle=[];triangle.push(vertexIndex++),triangle.push(vertexIndex++),triangle.push(vertexIndex++);const abc=br.readUInt16();let color=null;if(10===m&&(color=0==(abc&umask)?[(abc&rmask)/31,((abc&gmask)>>>5)/31,((abc&bmask)>>>10)/31,255]:mcolor,colors.push(color)),0===skip){const e1=index$j.subtract(index$j.create(),v2,v1),e2=index$j.subtract(index$j.create(),v3,v1),cr=index$j.cross(index$j.create(),e1,e2);if(index$j.dot(no,cr)>0){const tmp=v3;v3=v1,v1=tmp}}vertices.push(v1),vertices.push(v2),vertices.push(v3),triangles.push(triangle),normals.push(no)}return err&&console.warn(`WARNING: import errors: ${err} (some triangles might be misaligned or missing)`),[elementFormatter({vertices:vertices,triangles:triangles,normals:normals,colors:colors,index:1})]},deserializeAsciiSTL=(stl,filename,version,elementFormatter)=>{let converted=0;const objects=stl.split("endsolid"),elements=[];for(let o=1;o<objects.length;o++){const patt=/\bfacet[\s\S]*?endloop/gim,vertices=[],triangles=[],colors=[];let vertexIndex=0,err=0;const match=stl.match(patt);if(null!=match){for(let i=0;i<match.length;i++){const v=/\bfacet\s+normal\s+(\S+)\s+(\S+)\s+(\S+)\s+outer\s+loop\s+vertex\s+(\S+)\s+(\S+)\s+(\S+)\s+vertex\s+(\S+)\s+(\S+)\s+(\S+)\s+vertex\s+(\S+)\s+(\S+)\s+(\S+)\s*/gim.exec(match[i]);if(null==v)continue;if(13!==v.length){console.log("Failed to parse "+match[i]);break}let skip=0;for(let k=0;k<v.length;k++)"NaN"===v[k]&&(console.log("bad normal or triangle vertice #"+converted+" "+k+": '"+v[k]+"', skipped"),skip++);if(err+=skip,skip)continue;let j=1;const no=[];no.push(parseFloat(v[j++])),no.push(parseFloat(v[j++])),no.push(parseFloat(v[j++]));let v1=[];v1.push(parseFloat(v[j++])),v1.push(parseFloat(v[j++])),v1.push(parseFloat(v[j++]));const v2=[];v2.push(parseFloat(v[j++])),v2.push(parseFloat(v[j++])),v2.push(parseFloat(v[j++]));let v3=[];v3.push(parseFloat(v[j++])),v3.push(parseFloat(v[j++])),v3.push(parseFloat(v[j++]));const triangle=[];if(triangle.push(vertexIndex++),triangle.push(vertexIndex++),triangle.push(vertexIndex++),0===skip){const e1=index$j.subtract(index$j.create(),v2,v1),e2=index$j.subtract(index$j.create(),v3,v1),cr=index$j.cross(index$j.create(),e1,e2);if(index$j.dot(no,cr)>0){const tmp=v3;v3=v1,v1=tmp}}vertices.push(v1),vertices.push(v2),vertices.push(v3),triangles.push(triangle),converted++}err&&console.warn(`WARNING: import errors: ${err} (some triangles might be misaligned or missing)`),elements.push(elementFormatter({vertices:vertices,triangles:triangles,colors:colors,index:o}))}}return elements},toPolyhedron=(points,faces,normals,colors)=>(colors&&faces.length!==colors.length&&(colors=void 0),polyhedron({orientation:"inward",points:points,faces:faces,colors:colors})),toScript=(points,faces,normals,colors,index)=>{let src=`\n//\n// solid ${index} : ${points.length} points, ${faces.length} faces, ${colors.length} colors\n//\nconst solid${index} = () => {\n`;src+=" const points = [\n";for(let i=0;i<points.length;i++)src+=` [${points[i]}],\n`;src+=" ]\n",src+=" const faces = [\n";for(let i=0;i<faces.length;i++)src+=` [${faces[i]}],\n`;if(src+=" ]\n",colors&&faces.length===colors.length){src+=" const colors = [\n";for(let i=0;i<colors.length;i++)src+=` [${colors[i]}],\n`;src+=" ]\n"}else src+=" const colors = null\n";return src+=" return polyhedron({points, faces, colors, orientation: 'inside'})\n}\n",src};exports.deserialize=(options,stl)=>{const defaults={filename:"stl",version:"3.0.2-alpha.0",addMetaData:!0,output:"script"};(options=Object.assign({},defaults,options))&&options.statusCallback&&options.statusCallback({progress:0});const{filename:filename,version:version,output:output,addMetaData:addMetaData}=options;stl=isBuffer(stl)?bufferToBinaryString(stl):stl;const isBinary=isDataBinaryRobust(stl);options&&options.statusCallback&&options.statusCallback({progress:33}),options&&options.statusCallback&&options.statusCallback({progress:66});const result=("script"===output?formatAsJscad:formatAsCsg)((isBinary?deserializeBinarySTL:deserializeAsciiSTL)(stl,filename,version,"script"===output?({vertices:vertices,triangles:triangles,normals:normals,colors:colors,index:index})=>toScript(vertices,triangles,null,colors,index):({vertices:vertices,triangles:triangles,normals:normals,colors:colors})=>toPolyhedron(vertices,triangles,null,colors)),addMetaData,version,filename);return options&&options.statusCallback&&options.statusCallback({progress:100}),result},exports.mimeType="model/stl",Object.defineProperty(exports,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).jscadStlDeserializer={});