@jscad/x3d-deserializer 2.2.5 → 3.0.0-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.
@@ -0,0 +1,37 @@
1
+ /**
2
+ * X3D Deserializer for JSCAD
3
+ * @module @jscad/x3d-deserializer
4
+ * @version 3.0.0-alpha.0
5
+ * @license MIT
6
+ */
7
+ /**
8
+ * Constructive Solid Geometry (CSG) Library for JSCAD
9
+ * @module @jscad/modeling
10
+ * @version 3.0.0-alpha.0
11
+ * @license MIT
12
+ */
13
+ const flatten$1=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten$1(val)):acc.concat(val)),[]),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,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},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},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$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},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:(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: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$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:vector=>{const x=vector[0],y=vector[1],z=vector[2];return x*x+y*y+z*z},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};var index$c=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:fromTaitBryanRotation,fromTranslation:fromTranslation,fromValues:fromValues$4,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,toPoints$3=geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},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);return Object.assign({},geometry,{transforms:transforms})},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 index$a=Object.freeze({__proto__:null,clone:clone$b,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:geometry=>{const outlines=toOutlines(geometry).map((outline=>outline.slice().reverse())),reversed=create$a(outlines);return geometry.color&&(reversed.color=geometry.color),reversed},toOutlines:toOutlines,toPoints:toPoints$3,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: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),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,measureBoundingSphere$1=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},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}`)}))}};var index$7=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$2(min,min,vertices[i]),max$2(max,max,vertices[i]);return[min,max]},measureBoundingSphere:measureBoundingSphere$1,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});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),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 index$6=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))},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: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 index$5=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");if(3===color.length&&(color=[color[0],color[1],color[2],1]),0===(objects=flatten$1(objects)).length)throw new Error("wrong number of arguments");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):(object.color=color,object)));return 1===results.length?results[0]:results},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};var index$3=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}),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)),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)};var index$2=Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:equals$3,fromGeom2:fromGeom2,fromVertices:fromVertices,isA:isA,reverse:slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},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]};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 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$1(bbox[0],bbox[0],point),max$1(bbox[1],bbox[1],point))},expand3=(bbox,vertex)=>{0===bbox.length?(bbox[0]=clone$9(vertex),bbox[1]=clone$9(vertex)):(min$2(bbox[0],bbox[0],vertex),max$2(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)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=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},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,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=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],(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])})({center:center,radius:radius,startAngle:startAngle,endAngle:endAngle,segments:segments})},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)},line=points=>{if(!Array.isArray(points))throw new Error("points must be an array");return fromPoints$2({},points)},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],(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)})({center:center,radius:radius,segments:segments,axes:axes})},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),newEdges=[];return edges.forEach((edge=>{const increment=subtract$3([0,0,0],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},rotateX=(angle,...objects)=>((angles,...objects)=>{if(!Array.isArray(angles))throw new Error("angles must be an array");if(0===(objects=flatten$1(objects)).length)throw new Error("wrong number of arguments");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):object));return 1===results.length?results[0]:results})([angle,0,0],objects),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=(i,t,comparator)=>{const N=new Node$1(null,null);let l=N,r=N;for(;;){const cmp=comparator(i,t.key);if(cmp<0){if(null===t.left)break;if(comparator(i,t.left.key)<0){const y=t.left;if(t.left=y.right,y.right=t,null===(t=y).left)break}r.left=t,r=t,t=t.left}else{if(!(cmp>0))break;if(null===t.right)break;if(comparator(i,t.right.key)>0){const y=t.right;if(t.right=y.left,y.left=t,null===(t=y).right)break}l.right=t,l=t,t=t.right}}return l.right=t.left,r.left=t.right,t.left=N.right,t.right=N.left,t},insert=(i,data,t,comparator)=>{const node=new Node$1(i,data);if(null===t)return node.left=node.right=null,node;const cmp=comparator(i,(t=splay(i,t,comparator)).key);return cmp<0?(node.left=t.left,node.right=t,t.left=null):cmp>=0&&(node.right=t.right,node.left=t,t.right=null),node},split=(key,v,comparator)=>{let left=null,right=null;if(v){const cmp=comparator((v=splay(key,v,comparator)).key,key);0===cmp?(left=v.left,right=v.right):cmp<0?(right=v.right,v.right=null,left=v):(left=v.left,v.left=null,right=v)}return{left:left,right:right}},printRow=(root,prefix,isTail,out,printNode)=>{if(root){out(`${prefix}${isTail?"└── ":"├── "}${printNode(root)}\n`);const indent=prefix+(isTail?" ":"│ ");root.left&&printRow(root.left,indent,!1,out,printNode),root.right&&printRow(root.right,indent,!0,out,printNode)}};class Tree$1{constructor(comparator=DEFAULT_COMPARE){this._comparator=comparator,this._root=null,this._size=0}insert(key,data){return this._size++,this._root=insert(key,data,this._root,this._comparator),this._root}add(key,data){const node=new Node$1(key,data);null===this._root&&(node.left=node.right=null,this._size++,this._root=node);const comparator=this._comparator,t=splay(key,this._root,comparator),cmp=comparator(key,t.key);return 0===cmp?this._root=t:(cmp<0?(node.left=t.left,node.right=t,t.left=null):cmp>0&&(node.right=t.right,node.left=t,t.right=null),this._size++,this._root=node),this._root}remove(key){this._root=this._remove(key,this._root,this._comparator)}_remove(i,t,comparator){let x;return null===t?null:0===comparator(i,(t=splay(i,t,comparator)).key)?(null===t.left?x=t.right:(x=splay(i,t.left,comparator),x.right=t.right),this._size--,x):t}pop(){let node=this._root;if(node){for(;node.left;)node=node.left;return this._root=splay(node.key,this._root,this._comparator),this._root=this._remove(node.key,this._root,this._comparator),{key:node.key,data:node.data}}return null}findStatic(key){let current=this._root;const compare=this._comparator;for(;current;){const cmp=compare(key,current.key);if(0===cmp)return current;current=cmp<0?current.left:current.right}return null}find(key){return this._root&&(this._root=splay(key,this._root,this._comparator),0!==this._comparator(key,this._root.key))?null:this._root}contains(key){let current=this._root;const compare=this._comparator;for(;current;){const cmp=compare(key,current.key);if(0===cmp)return!0;current=cmp<0?current.left:current.right}return!1}forEach(visitor,ctx){let current=this._root;const Q=[];let done=!1;for(;!done;)null!==current?(Q.push(current),current=current.left):0!==Q.length?(current=Q.pop(),visitor.call(ctx,current),current=current.right):done=!0;return this}range(low,high,fn,ctx){const Q=[],compare=this._comparator;let cmp,node=this._root;for(;0!==Q.length||node;)if(node)Q.push(node),node=node.left;else{if(node=Q.pop(),cmp=compare(node.key,high),cmp>0)break;if(compare(node.key,low)>=0&&fn.call(ctx,node))return this;node=node.right}return this}keys(){const keys=[];return this.forEach((({key:key})=>keys.push(key))),keys}values(){const values=[];return this.forEach((({data:data})=>values.push(data))),values}min(){return this._root?this.minNode(this._root).key:null}max(){return this._root?this.maxNode(this._root).key:null}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}at(index){let current=this._root,done=!1,i=0;const Q=[];for(;!done;)if(current)Q.push(current),current=current.left;else if(Q.length>0){if(current=Q.pop(),i===index)return current;i++,current=current.right}else done=!0;return null}next(d){let root=this._root,successor=null;if(d.right){for(successor=d.right;successor.left;)successor=successor.left;return successor}const comparator=this._comparator;for(;root;){const cmp=comparator(d.key,root.key);if(0===cmp)break;cmp<0?(successor=root,root=root.left):root=root.right}return successor}prev(d){let root=this._root,predecessor=null;if(null!==d.left){for(predecessor=d.left;predecessor.right;)predecessor=predecessor.right;return predecessor}const comparator=this._comparator;for(;root;){const cmp=comparator(d.key,root.key);if(0===cmp)break;cmp<0?root=root.left:(predecessor=root,root=root.right)}return predecessor}clear(){return this._root=null,this._size=0,this}toList(){return toList(this._root)}load(keys,values=[],presort=!1){let size=keys.length;const comparator=this._comparator;if(presort&&sort(keys,values,0,size-1,comparator),null===this._root)this._root=loadRecursive(keys,values,0,size),this._size=size;else{const mergedList=mergeLists(this.toList(),createList(keys,values),comparator);size=this._size+size,this._root=sortedListToBST({head:mergedList},0,size)}return this}isEmpty(){return null===this._root}size(){return this._size}root(){return this._root}toString(printNode=(n=>String(n.key))){const out=[];return printRow(this._root,"",!0,(v=>out.push(v)),printNode),out.join("")}update(key,newKey,newData){const comparator=this._comparator;let{left:left,right:right}=split(key,this._root,comparator);comparator(key,newKey)<0?right=insert(newKey,newData,right,comparator):left=insert(newKey,newData,left,comparator),this._root=((left,right,comparator)=>null===right?left:(null===left||((right=splay(left.key,right,comparator)).left=left),right))(left,right,comparator)}split(key){return split(key,this._root,this._comparator)}*[Symbol.iterator](){let n=this.minNode();for(;n;)yield n,n=this.next(n)}}const loadRecursive=(keys,values,start,end)=>{const size=end-start;if(size>0){const middle=start+Math.floor(size/2),key=keys[middle],data=values[middle],node=new Node$1(key,data);return node.left=loadRecursive(keys,values,start,middle),node.right=loadRecursive(keys,values,middle+1,end),node}return null},createList=(keys,values)=>{const head=new Node$1(null,null);let p=head;for(let i=0;i<keys.length;i++)p=p.next=new Node$1(keys[i],values[i]);return p.next=null,head.next},toList=root=>{let current=root;const Q=[];let done=!1;const head=new Node$1(null,null);let p=head;for(;!done;)current?(Q.push(current),current=current.left):Q.length>0?(current=p=p.next=Q.pop(),current=current.right):done=!0;return p.next=null,head.next},sortedListToBST=(list,start,end)=>{const size=end-start;if(size>0){const middle=start+Math.floor(size/2),left=sortedListToBST(list,start,middle),root=list.head;return root.left=left,list.head=list.head.next,root.right=sortedListToBST(list,middle+1,end),root}return null},mergeLists=(l1,l2,compare)=>{const head=new Node$1(null,null);let p=head,p1=l1,p2=l2;for(;null!==p1&&null!==p2;)compare(p1.key,p2.key)<0?(p.next=p1,p1=p1.next):(p.next=p2,p2=p2.next),p=p.next;return null!==p1?p.next=p1:null!==p2&&(p.next=p2),head.next},sort=(keys,values,left,right,compare)=>{if(left>=right)return;const pivot=keys[left+right>>1];let i=left-1,j=right+1;for(;;){do{i++}while(compare(keys[i],pivot)<0);do{j--}while(compare(keys[j],pivot)>0);if(i>=j)break;let tmp=keys[i];keys[i]=keys[j],keys[j]=tmp,tmp=values[i],values[i]=values[j],values[j]=tmp}sort(keys,values,left,j,compare),sort(keys,values,j+1,right,compare)},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,edgeType){this.left=left,this.point=point,this.otherEvent=otherEvent,this.isSubject=isSubject,this.type=edgeType||0,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}clone(){const copy=new SweepEvent(this.point,this.left,this.otherEvent,this.isSubject,this.type);return copy.contourId=this.contourId,copy.resultTransition=this.resultTransition,copy.prevInResult=this.prevInResult,copy.isExteriorRing=this.isExteriorRing,copy.inOut=this.inOut,copy.otherInOut=this.otherInOut,copy}}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:specialCases(e1,e2,p1)},specialCases=(e1,e2,p1,p2)=>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=(se,p,queue)=>{const r=new SweepEvent(p,!1,se,se.isSubject),l=new SweepEvent(p,!0,se.otherEvent,se.isSubject);return r.contourId=l.contourId=se.contourId,compareEvents(l,se.otherEvent)>0&&(se.otherEvent.left=!0,l.left=!1),se.otherEvent.otherEvent=l,se.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)=>{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]],e=[b1[0]-a1[0],b1[1]-a1[1]];let kross=crossProduct(va,vb),sqrKross=kross*kross;const sqrLenA=dot$1(va,va);if(sqrKross>0){const s=crossProduct(e,vb)/kross;if(s<0||s>1)return null;const t=crossProduct(e,va)/kross;return t<0||t>1?null:0===s||1===s?[toPoint(a1,s,va)]:0===t||1===t?[toPoint(b1,t,vb)]:[toPoint(a1,s,va)]}if(kross=crossProduct(e,va),sqrKross=kross*kross,sqrKross>0)return null;const sa=dot$1(va,e)/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?[toPoint(a1,smin>0?smin:0,va)]:0===smax?[toPoint(a1,smax<1?smax:1,va)]:[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(2===nIntersections&&se1.isSubject===se2.isSubject)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;const events=[];let leftCoincide=!1,rightCoincide=!1;return equals$6(se1.point,se2.point)?leftCoincide=!0:1===compareEvents(se1,se2)?events.push(se2,se1):events.push(se1,se2),equals$6(se1.otherEvent.point,se2.otherEvent.point)?rightCoincide=!0:1===compareEvents(se1.otherEvent,se2.otherEvent)?events.push(se2.otherEvent,se1.otherEvent):events.push(se1.otherEvent,se2.otherEvent),leftCoincide&&rightCoincide||leftCoincide?(se2.type=1,se1.type=se2.inOut===se1.inOut?2:3,leftCoincide&&!rightCoincide&&divideSegment(events[1].otherEvent,events[0].point,queue),2):rightCoincide?(divideSegment(events[0],events[1].point,queue),3):events[0]!==events[3].otherEvent?(divideSegment(events[0],events[1].point,queue),divideSegment(events[1],events[2].point,queue),3):(divideSegment(events[0],events[1].point,queue),divideSegment(events[3].otherEvent,events[2].point,queue),3)},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=null}isExterior(){return null==this.holeOf}}const nextPos=(pos,resultEvents,processed,origPos)=>{let newPos=pos+1;const p=resultEvents[pos].point;let p1;const length=resultEvents.length;for(newPos<length&&(p1=resultEvents[newPos].point);newPos<length&&p1[0]===p[0]&&p1[1]===p[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.holeOf=null,contour.depth=contours[lowerContourId].depth}else contour.holeOf=null,contour.depth=0;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}}const max=Math.max,min=Math.min;let contourId=0;const processPolygon=(contourOrHole,isSubject,depth,queue,bbox,isExteriorRing)=>{const len=contourOrHole.length-1;let s1,s2,e1,e2;for(let i=0;i<len;i++){if(s1=contourOrHole[i],s2=contourOrHole[i+1],e1=new SweepEvent(s1,!1,void 0,isSubject),e2=new SweepEvent(s2,!1,e1,isSubject),e1.otherEvent=e2,s1[0]===s2[0]&&s1[1]===s2[1])continue;e1.contourId=e2.contourId=depth,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]=min(bbox[0],x),bbox[1]=min(bbox[1],y),bbox[2]=max(bbox[2],x),bbox[3]=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);let polygonSet,isExteriorRing,i,ii,j,jj;for(i=0,ii=subject.length;i<ii;i++)for(polygonSet=subject[i],j=0,jj=polygonSet.length;j<jj;j++)isExteriorRing=0===j,isExteriorRing&&contourId++,processPolygon(polygonSet[j],!0,contourId,eventQueue,sbbox,isExteriorRing);for(i=0,ii=clipping.length;i<ii;i++)for(polygonSet=clipping[i],j=0,jj=polygonSet.length;j<jj;j++)isExteriorRing=0===j,2===operation&&(isExteriorRing=!1),isExteriorRing&&contourId++,processPolygon(polygonSet[j],!1,contourId,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;){let 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 event=event.otherEvent,next=prev=sweepLine.find(event),prev&&next&&(prev=prev!==begin?sweepLine.prev(prev):null,next=sweepLine.next(next),sweepLine.remove(event),next&&prev&&possibleIntersection(prev.key,next.key,eventQueue))}return sortedEvents})(eventQueue,0,0,sbbox,cbbox,operation),contours=(sortedEvents=>{const resultEvents=(sortedEvents=>{let event,i,len,tmp;const resultEvents=[];for(i=0,len=sortedEvents.length;i<len;i++)event=sortedEvents[i],(event.left&&event.inResult||!event.left&&event.otherEvent.inResult)&&resultEvents.push(event);let sorted=!1;for(;!sorted;)for(sorted=!0,i=0,len=resultEvents.length;i<len;i++)i+1<len&&1===compareEvents(resultEvents[i],resultEvents[i+1])&&(tmp=resultEvents[i],resultEvents[i]=resultEvents[i+1],resultEvents[i+1]=tmp,sorted=!1);for(i=0,len=resultEvents.length;i<len;i++)event=resultEvents[i],event.otherPos=i;for(i=0,len=resultEvents.length;i<len;i++)event=resultEvents[i],event.left||(tmp=event.otherPos,event.otherPos=event.otherEvent.otherPos,event.otherEvent.otherPos=tmp);return resultEvents})(sortedEvents),len=resultEvents.length,processed={},contours=[];for(let i=0;i<len;i++){if(processed[i])continue;const contourId=contours.length,contour=initializeContourFromContext(resultEvents[i],contours,contourId),markAsProcessed=pos=>{processed[pos]=!0,pos<resultEvents.length&&resultEvents[pos]&&(resultEvents[pos].outputContourId=contourId)};let pos=i;const origPos=i,initial=resultEvents[i].point;for(contour.points.push(initial);markAsProcessed(pos),pos=resultEvents[pos].otherPos,markAsProcessed(pos),contour.points.push(resultEvents[pos].point),pos=nextPos(pos,resultEvents,processed,origPos),!(pos===origPos||pos>=resultEvents.length)&&resultEvents[pos];);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?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,classifyPolygons=polygons=>{let clusters=[polygons];const nonCoplanar=[];for(let component=3;component>=0;component--){const maybeCoplanar=[],tolerance=3===component?15e-9:1e-13;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],node.plane&&(node.plane=flip([0,0,0,0],node.plane)),node.front&&queue.push(node.front),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,node.plane){const plane=node.plane,backNodes=[],frontNodes=[],coplanarFrontNodes=alsoRemoveCoplanarFront?backNodes:frontNodes;polygonTreeNodes.forEach((treeNode=>{treeNode.isRemoved()||treeNode.splitByPlane(plane,coplanarFrontNodes,backNodes,frontNodes,backNodes)})),node.front&&frontNodes.length>0&&stack.push({node:node.front,polygonTreeNodes:frontNodes});const numBackNodes=backNodes.length;if(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(tree,alsoRemoveCoplanarFront){let node=this;const stack=[];do{node.polygontreenodes.length>0&&tree.rootnode.clipPolygons(node.polygontreenodes,alsoRemoveCoplanarFront),node.front&&stack.push(node.front),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(!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&&(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&&(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};class PolygonTreeNode{constructor(parent,polygon){this.parent=parent,this.children=[],this.polygon=polygon,this.removed=!1}addPolygons(polygons){if(!this.isRootNode())throw new Error("Assertion failed");const _this=this;polygons.forEach((polygon=>{_this.addChild(polygon)}))}remove(){if(!this.removed){this.removed=!0,this.polygon=null;const parentschildren=this.parent.children,i=parentschildren.indexOf(this);if(i<0)throw new Error("Assertion failed");parentschildren.splice(i,1),this.parent.recursivelyInvalidatePolygon()}}isRemoved(){return this.removed}isRootNode(){return!this.parent}invert(){if(!this.isRootNode())throw new Error("Assertion failed");this.invertSub()}getPolygon(){if(!this.polygon)throw new Error("Assertion failed");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],node.polygon?result.push(node.polygon):node.children.length>0&&queue.push(node.children)}splitByPlane(plane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes){if(this.children.length){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):node._splitByPlane(plane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes)}else this._splitByPlane(plane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes)}_splitByPlane(splane,coplanarFrontNodes,coplanarBackNodes,frontNodes,backNodes){const polygon=this.polygon;if(polygon){const bound=measureBoundingSphere$1(polygon),sphereRadius=bound[3]+EPS,d=dot$2(splane,bound)-splane[3];if(d>sphereRadius)frontNodes.push(this);else if(d<-sphereRadius)backNodes.push(this);else{const splitResult=((splane,polygon)=>{const result={type:null,front:null,back:null},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){result.type=4;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}}frontVertices.length>=3&&(result.front=fromVerticesAndPlane(frontVertices,pplane)),backVertices.length>=3&&(result.back=fromVerticesAndPlane(backVertices,pplane))}else result.type=3;else result.type=2;else{const t=dot$2(splane,pplane);result.type=t>=0?0:1}}return result})(splane,polygon);switch(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(splitResult.front){const frontNode=this.addChild(splitResult.front);frontNodes.push(frontNode)}if(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],node.polygon&&(node.polygon=invert$1(node.polygon)),node.children.length>0&&queue.push(node.children)}recursivelyInvalidatePolygon(){this.polygon=null,this.parent&&this.parent.recursivelyInvalidatePolygon()}clear(){let children=[this];const queue=[children];for(let i=0;i<queue.length;++i){children=queue[i];const l=children.length;for(let j=0;j<l;j++){const node=children[j];node.polygon&&(node.polygon=null),node.parent&&(node.parent=null),node.children.length>0&&queue.push(node.children),node.children=[]}}}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}`,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,this.rootnode=new Node(null),polygons&&this.addPolygons(polygons)}invert(){this.polygonTree.invert(),this.rootnode.invert()}clipTo(tree,alsoRemoveCoplanarFront=!1){this.rootnode.clipTo(tree,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)}clear(){this.polygonTree.clear()}toString(){return"Tree: "+this.polygonTree.toString("")}}const subtractGeom3=(...geometries)=>{let newGeometry=(geometries=flatten$1(geometries)).shift();return geometries.forEach((geometry=>{newGeometry=((geometry1,geometry2)=>{if(!((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)})(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=(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})(newGeometry),newGeometry},subtract=(...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("subtract wrong number of arguments");if(!(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})(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=flatten$1(geometries)).shift();return geometries.forEach((geometry=>{newGeometry=boolean(newGeometry,geometry,2)})),newGeometry})(geometries);if(isA$3(geometry))return subtractGeom3(geometries);throw new Error("subtract unsupported geometry type")},createTransform=(center,rotation,scale,scaleOrientation,translation)=>{const matrix=index$c.create(),temp=index$c.create();return index$c.multiply(matrix,matrix,index$c.fromTranslation(temp,translation)),index$c.multiply(matrix,matrix,index$c.fromTranslation(temp,center)),index$c.multiply(matrix,matrix,index$c.fromRotation(temp,rotation[3],rotation)),index$c.multiply(matrix,matrix,index$c.fromRotation(temp,scaleOrientation[3],scaleOrientation)),index$c.multiply(matrix,matrix,index$c.fromScaling(temp,scale)),index$c.multiply(matrix,matrix,index$c.fromRotation(temp,scaleOrientation[3],index$d.negate(index$d.create(),scaleOrientation))),index$c.multiply(matrix,matrix,index$c.fromTranslation(temp,index$d.negate(index$d.create(),center))),matrix},x3dTypes_X3D=0,x3dTypes_UNIT=1,x3dTypes_META=2,x3dTypes_SCENE=3,x3dTypes_TRANSFORM=4,x3dTypes_SHAPE=5,x3dTypes_GROUP=6,x3dTypes_APPEARANCE=7,x3dTypes_TRIANGLESET=10,x3dTypes_TRIANGLEFANSET=11,x3dTypes_TRIANGLESTRIPSET=12,x3dTypes_QUADSET=13,x3dTypes_INDEXEDTRIANGLESET=14,x3dTypes_INDEXEDTRIANGLEFANSET=15,x3dTypes_INDEXEDTRIANGLESTRIPSET=16,x3dTypes_INDEXEDQUADSET=17,x3dTypes_ELEVATIONGRID=18,x3dTypes_INDEXEDFACESET=19,x3dTypes_LINESET=20,x3dTypes_INDEXEDLINESET=21,x3dTypes_BOX=50,x3dTypes_CONE=51,x3dTypes_CYLINDER=52,x3dTypes_SPHERE=53,x3dTypes_EXTRUSION=54,x3dTypes_ARC2D=61,x3dTypes_ARCCLOSE2D=62,x3dTypes_CIRCLE2D=63,x3dTypes_DISK2D=64,x3dTypes_POLYLINE2D=65,x3dTypes_RECTANGLE2D=66,x3dTypes_TRIANGLESET2D=67,x3dTypes_COLOR=91,x3dTypes_COORDINATE=92,x3dTypes_MATERIAL=93,x3dGroup=element=>{const obj={definition:x3dTypes_GROUP,objects:[]};return obj},isZeroVector=vector=>vector[0]+0===0&&vector[1]+0===0&&vector[2]+0===0,calculateZaxis=(z,p,i,n)=>{const a=index$d.subtract(index$d.create(),n,i),b=index$d.subtract(index$d.create(),p,i);return index$d.normalize(z,index$d.cross(z,a,b))},extrudeX3D=x3dshape=>{let{beginCap:beginCap,endCap:endCap,crossSection:crossSection,orientations:orientations,scales:scales,spine:spine}=Object.assign({},x3dshape);if(index$3.measureArea(index$3.create(crossSection))<0&&crossSection.reverse(),1===scales.length&&(scales=spine.map((s=>scales[0]))),1===orientations.length&&(orientations=spine.map((s=>orientations[0]))),spine.length!==scales.length||spine.length!==orientations.length)throw new Error(`invalid X3D specification; spine scale orientaion length must be the same; ${spine.length}`);const initialShape=index$a.create([crossSection]),initialSlice=index$2.fromGeom2(initialShape);let yaxes=(spine=>{const slength=spine.length,closed=index$d.equals(spine[0],spine[slength-1]),yaxes=[];for(let i=0;i<slength;i++){const yaxis=index$d.create();0===i?closed?index$d.normalize(yaxis,index$d.subtract(yaxis,spine[1],spine[slength-2])):index$d.normalize(yaxis,index$d.subtract(yaxis,spine[1],spine[0])):i===slength-1?closed?index$d.normalize(yaxis,index$d.subtract(yaxis,spine[1],spine[slength-2])):index$d.normalize(yaxis,index$d.subtract(yaxis,spine[slength-1],spine[slength-2])):index$d.normalize(yaxis,index$d.subtract(yaxis,spine[i+1],spine[i-1])),yaxes.push(yaxis)}return yaxes})(spine),zaxes=(spine=>{const slength=spine.length,closed=index$d.equals(spine[0],spine[slength-1]),zaxes=[];let previousZaxis;for(let i=0;i<slength;i++){const zaxis=index$d.create();0===i?closed?calculateZaxis(zaxis,spine[slength-2],spine[0],spine[1]):slength>2&&calculateZaxis(zaxis,spine[0],spine[1],spine[2]):i===slength-1?closed?calculateZaxis(zaxis,spine[slength-2],spine[0],spine[1]):slength>2&&calculateZaxis(zaxis,spine[slength-3],spine[slength-2],spine[slength-1]):calculateZaxis(zaxis,spine[i-1],spine[i],spine[i+1]),previousZaxis&&index$d.dot(previousZaxis,zaxis)<0&&index$d.negate(zaxis,zaxis),zaxes.push(zaxis),previousZaxis=zaxis}if(isZeroVector(zaxes[0]))for(let i=1;i<zaxes.length;i++)if(!isZeroVector(zaxes[i])){zaxes[0]=zaxes[i];break}for(let i=1;i<zaxes.length;i++)isZeroVector(zaxes[i])&&!isZeroVector(zaxes[i-1])&&index$d.clone(zaxes[i],zaxes[i-1]);return zaxes})(spine),xaxes=((yaxes,zaxes)=>{const xaxes=[];for(let i=0;i<yaxes.length;i++){const xaxis=index$d.create();xaxes.push(index$d.normalize(xaxis,index$d.cross(xaxis,yaxes[i],zaxes[i])))}return xaxes})(yaxes,zaxes);const y0direction=[0,1,0],y0matrix=index$c.fromVectorRotation(index$c.create(),index$d.fromValues(0,0,1),y0direction);return zaxes.reduce(((acc,axis)=>acc&&isZeroVector(axis)),!0)&&(index$d.subtract(y0direction,spine[1],spine[0]),index$c.fromVectorRotation(y0matrix,index$d.fromValues(0,0,1),y0direction),xaxes=xaxes.map((axis=>[1,0,0])),yaxes=yaxes.map((axis=>[0,1,0])),zaxes=zaxes.map((axis=>[0,0,1]))),((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)})({numberOfSlices:spine.length,capStart:beginCap,capEnd:endCap,callback:function(progress,count,base){const position=spine[count],scale=index$d.fromVec2(index$d.create(),scales[count],1),orientation=orientations[count],xaxis=xaxes[count],yaxis=yaxes[count],zaxis=zaxes[count],translationMatrix=index$c.fromTranslation(index$c.create(),position),scaleMatrix=index$c.fromScaling(index$c.create(),scale),scpMatrix=((out,xaxis,yaxis,zaxis)=>(out[0]=xaxis[0],out[1]=yaxis[0],out[2]=zaxis[0],out[3]=0,out[4]=xaxis[1],out[5]=yaxis[1],out[6]=zaxis[1],out[7]=0,out[8]=xaxis[2],out[9]=yaxis[2],out[10]=zaxis[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out))(index$c.create(),xaxis,yaxis,zaxis),orientationMatrix=index$c.fromRotation(index$c.create(),orientation[3],orientation),rotationMatrix=index$c.create();index$c.multiply(rotationMatrix,y0matrix,rotationMatrix),index$c.multiply(rotationMatrix,scpMatrix,rotationMatrix),index$c.multiply(rotationMatrix,orientationMatrix,rotationMatrix),index$c.multiply(rotationMatrix,translationMatrix,rotationMatrix);let newslice=base;return newslice=index$2.transform(scaleMatrix,newslice),newslice=index$2.transform(rotationMatrix,newslice),newslice}},initialSlice)},findNode=(x3dtype,objects)=>objects.find((object=>object.definition===x3dtype)),findColor=(objects,options)=>{const appearance=findNode(x3dTypes_APPEARANCE,objects);let material;return appearance&&(material=findNode(x3dTypes_MATERIAL,appearance.objects),material)?material.color?material.color:null:(material=findNode(x3dTypes_MATERIAL,objects),material&&material.color?material.color:null)},pointsToString=triangle=>`[\n ${triangle.map((point=>(point=>`[${point}]`)(point))).join(",\n ")}\n ]`,createColors=(shape,color)=>{if(!color)return null;if(!Array.isArray(shape.colorIndex))return null;let colors=null;var colorIndex,faceColors;return!0===shape.colorPerVertex?colors=((colorIndex,vertexColors)=>{if(!Array.isArray(colorIndex)||!Array.isArray(vertexColors))return null;if(colorIndex.length<0||!Array.isArray(colorIndex[0]))return console.log("ERROR: WRONG FORMAT FOR VERTEXCOLORS"),null;const colors=[];for(let i=0;i<colorIndex.length;i++){const indexes=colorIndex[i];let r=0,g=0,b=0;const a=1;for(let j=0;j<indexes.length;j++){const vertexColor=vertexColors[indexes[j]];vertexColor&&(r+=vertexColor[0],g+=vertexColor[1],b+=vertexColor[2])}const color=[r/indexes.length,g/indexes.length,b/indexes.length,a];colors.push(color)}return colors})(shape.colorIndex,color.colors):(colorIndex=shape.colorIndex,faceColors=color.colors,colors=Array.isArray(colorIndex)&&Array.isArray(faceColors)?colorIndex.map((index=>faceColors[index]?faceColors[index]:null)):null),colors},convertLine=(options,objects)=>{let shape=findNode(x3dTypes_INDEXEDLINESET,objects);if(shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),indexes=shape.indexes,color=findNode(x3dTypes_COLOR,shape.objects);if(coordinate&&indexes){const pointsSet=indexes.map((index=>{let points=index.map((i=>coordinate.points[i]));return points.findIndex((p=>0!==p[2]))>=0&&(console.warn("WARNING: unsupported 3D indexed line set was ignored"),points=[]),points}));!0===shape.colorPerVertex?shape.colorIndex=indexes:shape.colorIndex=indexes.map(((index,i)=>i));return{pointsSet:pointsSet,colors:createColors(shape,color)}}}if(shape=findNode(x3dTypes_LINESET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects),counts=shape.vertexCount;if(coordinate&&counts){let vi=0;const pointsSet=counts.map((count=>{let points=[];for(let i=0;i<count;i++)points.push(coordinate.points[vi]),vi++;return points.findIndex((p=>0!==p[2]))>=0&&(console.warn("WARNING: unsupported 3D line set was ignored"),points=[]),points}));if(!0===shape.colorPerVertex){let ci=0;shape.colorIndex=counts.map((count=>{const index=[];for(let i=0;i<count;i++)index.push(ci),ci++;return index}))}else shape.colorIndex=pointsSet.map(((ps,i)=>i));return{pointsSet:pointsSet,colors:createColors(shape,color)}}}return null},convertMesh=(options,objects)=>{let shape=findNode(x3dTypes_TRIANGLESET,objects);if(shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects);if(coordinate){const points=coordinate.points,numpoints=points.length,numfaces=Math.trunc(numpoints/3),faces=[];for(let ti=0;ti<numfaces;ti++){const pi=3*ti;faces.push([pi,pi+1,pi+2])}const orientation=shape.ccw?"outward":"inward";shape.colorIndex=faces;return{type:"triangles",points:points,faces:faces,colors:createColors(shape,color),orientation:orientation}}}if(shape=findNode(x3dTypes_TRIANGLEFANSET,objects),shape){const fanCount=shape.fanCount,coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects);if(coordinate){const points=coordinate.points,numfans=fanCount.length,faces=[];let fo=0;for(let fi=0;fi<numfans;fi++){const numvertices=Math.trunc(fanCount[fi]);for(let vi=1;vi<numvertices-1;vi++)faces.push([fo,fo+vi,fo+vi+1]);fo+=numvertices}const orientation=shape.ccw?"outward":"inward";shape.colorIndex=faces;return{type:`triangle fans (${numfans})`,points:points,faces:faces,colors:createColors(shape,color),orientation:orientation}}}if(shape=findNode(x3dTypes_TRIANGLESTRIPSET,objects),shape){const stripCount=shape.stripCount,coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects);if(coordinate){const points=coordinate.points,numstrips=stripCount.length,faces=[];let so=0;for(let si=0;si<numstrips;si++){const numvertices=Math.trunc(stripCount[si]);for(let vi=0;vi<numvertices-2;vi++){const face=[so+vi,so+vi+1,so+vi+2];vi%2==1&&face.reverse(),faces.push(face)}so+=numvertices}shape.colorIndex=faces;return{type:`triangle strip (${numstrips})`,points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_QUADSET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects);if(coordinate){const points=coordinate.points,numpoints=points.length,numquads=Math.trunc(numpoints/4),faces=[];for(let qi=0;qi<numquads;qi++){const pi=4*qi;faces.push([pi,pi+1,pi+2,pi+3])}shape.colorIndex=faces;return{type:`quad (${numquads})`,points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_INDEXEDTRIANGLESET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects),index=shape.index;if(coordinate&&index&&index.length>2){const points=coordinate.points,numfaces=Math.trunc(index.length/3),faces=[];for(let fi=0;fi<numfaces;fi++){const pi=3*fi;faces.push([index[pi],index[pi+1],index[pi+2]])}shape.colorIndex=faces;return{type:"indexed triangle",points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_INDEXEDTRIANGLEFANSET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects),fans=shape.fans;if(coordinate&&fans&&fans.length>0){const points=coordinate.points,numfans=fans.length,faces=[];for(let fi=0;fi<numfans;fi++){const fan=fans[fi],numvertices=fan.length;for(let vi=1;vi<numvertices-1;vi++)faces.push([fan[0],fan[vi],fan[vi+1]])}shape.colorIndex=faces;return{type:`indexed triangle fan (${numfans})`,points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_INDEXEDTRIANGLESTRIPSET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects),strips=shape.strips;if(coordinate&&strips&&strips.length>0){const points=coordinate.points,numstrips=strips.length,faces=[];for(let si=0;si<numstrips;si++){const strip=strips[si],numvertices=strip.length;for(let vi=0;vi<numvertices-2;vi++){const face=[strip[vi],strip[vi+1],strip[vi+2]];vi%2==1&&face.reverse(),faces.push(face)}}shape.colorIndex=faces;return{type:`indexed triangle strip (${numstrips})`,points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_INDEXEDQUADSET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),color=findNode(x3dTypes_COLOR,shape.objects),index=shape.index;if(coordinate&&index&&index.length>3){const points=coordinate.points,numquads=Math.trunc(index.length/4),faces=[];for(let qi=0;qi<numquads;qi++){const ii=4*qi;faces.push([index[ii],index[ii+1],index[ii+2],index[ii+3]])}shape.colorIndex=faces;return{type:`indexed quad (${numquads})`,points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_INDEXEDFACESET,objects),shape){const coordinate=findNode(x3dTypes_COORDINATE,shape.objects),faces=shape.faces,color=findNode(x3dTypes_COLOR,shape.objects);if(coordinate&&faces&&faces.length>0){const points=coordinate.points;return{type:`indexed faces (${faces.length})`,points:points,faces:faces,colors:createColors(shape,color),orientation:shape.ccw?"outward":"inward"}}}if(shape=findNode(x3dTypes_ELEVATIONGRID,objects),shape){const height=shape.height,color=findNode(x3dTypes_COLOR,shape.objects);if(height&&height.length>0){const xDimension=shape.xDimension,xSpacing=shape.xSpacing,zDimension=shape.zDimension,zSpacing=shape.zSpacing,points=[];let vi=0;for(let z0=0;z0<zDimension;++z0)for(let x0=0;x0<xDimension;++x0){const x=x0*xSpacing,z=z0*zSpacing,y=height[vi];vi++,points.push([x,y,z])}const faces=[];for(let z0=0;z0<zDimension-1;++z0)for(let x0=0;x0<xDimension-1;++x0){const iTL=x0+z0*xDimension,iTR=x0+1+z0*xDimension,iBL=x0+(z0+1)*xDimension,iBR=x0+1+(z0+1)*xDimension,distances=[Math.abs(height[iTL]),Math.abs(height[iTR]),Math.abs(height[iBL]),Math.abs(height[iBR])];let apexi=0;distances[1]>=distances[0]&&distances[1]>=distances[2]&&distances[1]>=distances[3]&&(apexi=1),distances[2]>=distances[0]&&distances[2]>=distances[1]&&distances[2]>=distances[3]&&(apexi=2),distances[3]>=distances[0]&&distances[3]>=distances[1]&&distances[3]>=distances[2]&&(apexi=3),0===apexi&&faces.push([iTL,iBR,iTR],[iTL,iBL,iBR]),1===apexi&&faces.push([iTR,iBL,iBR],[iTR,iTL,iBL]),2===apexi&&faces.push([iBL,iTR,iTL],[iBL,iBR,iTR]),3===apexi&&faces.push([iBR,iTL,iBL],[iBR,iTR,iTL])}const orientation=shape.ccw?"outward":"inward";!0===shape.colorPerVertex&&(shape.colorIndex=faces);return{type:`elevation grid (${xDimension} X ${zDimension})`,points:points,faces:faces,colors:createColors(shape,color),orientation:orientation}}}return null},instantiateMesh=(options,objects)=>{let geometry;const components=convertMesh(0,objects);return components&&(geometry=(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)})(components)),geometry},translateMesh=(options,objects)=>{const components=convertMesh(0,objects);if(components){const{type:type,points:points,faces:faces,colors:colors,orientation:orientation}=components;return((type,points,faces,colors,orientation)=>{const colorsCode=Array.isArray(colors)?pointsToString(colors):"null";return{primitive:"polyhedron({points, faces, colors, orientation})",code:`\n // 3D ${type} set: ${points.length} points, ${faces.length} faces\n const points = ${pointsToString(points)}\n const faces = ${pointsToString(faces)}\n const colors = ${colorsCode}\n const orientation = '${orientation}'\n`}})(type,points,faces,colors,orientation)}return null},translateShape=(options,object)=>{let code=`\n// shape\nconst createObjects${object.id} = (options) => {\n let objects = []\n`;const objects=object.objects,color=findColor(objects);let primitive,shape=findNode(x3dTypes_BOX,objects);if(shape)primitive=`cuboid({size: [${shape.size}]})`;else if(shape=findNode(x3dTypes_CONE,objects),shape)code+=` const shape = rotateX(-Math.PI/2, cylinderElliptic({startRadius: [${shape.bottomRadius},${shape.bottomRadius}], height: ${shape.height}, segments: ${shape.subdivision}, endRadius: [${shape.topRadius}, ${shape.topRadius}]}))\n`,primitive="shape";else if(shape=findNode(x3dTypes_CYLINDER,objects),shape)code+=` const shape = rotateX(-Math.PI/2, cylinder({radius: ${shape.radius}, height: ${shape.height}, segments: ${shape.subdivision}}))\n`,primitive="shape";else if(shape=findNode(x3dTypes_SPHERE,objects),shape)primitive=`sphere({radius: ${shape.radius}, segments: ${shape.subdivision}})`;else if(shape=findNode(x3dTypes_EXTRUSION,objects),shape){const geometry=extrudeX3D(shape);code+=` const polygons = [\n ${index$6.toPolygons(geometry).map((polygon=>pointsToString(index$7.toVertices(polygon)))).join(",\n ")}\n]\n`,primitive="geom3.fromPoints(polygons)"}if(!primitive)if(shape=findNode(x3dTypes_ARC2D,objects),shape)primitive=`arc({radius: ${shape.radius}, startAngle: ${shape.startAngle}, endAngle: ${shape.endAngle}, segments: ${shape.subdivision}})`;else if(shape=findNode(x3dTypes_ARCCLOSE2D,objects),shape)primitive="PIE"===shape.closureType?`circle({radius: ${shape.radius}, startAngle: ${shape.startAngle}, endAngle: ${shape.endAngle}, segments: ${shape.subdivision}})`:`geom2.create([path2.toPoints(path2.close(arc({radius: ${shape.radius}, startAngle: ${shape.startAngle}, endAngle: ${shape.endAngle}, segments: ${shape.subdivision}})))])`;else if(shape=findNode(x3dTypes_CIRCLE2D,objects),shape)primitive=`arc({radius: ${shape.radius}, segments: ${shape.subdivision}})`;else if(shape=findNode(x3dTypes_DISK2D,objects),shape)primitive=shape.innerRadius===shape.outerRadius?`arc({radius: ${shape.outerRadius}, segments: ${shape.subdivision}})`:0===shape.innerRadius?`circle({radius: ${shape.outerRadius}, segments: ${shape.subdivision}})`:`subtract(circle({radius: ${shape.outerRadius}, segments: ${shape.subdivision}}), primitives.circle({radius: ${shape.innerRadius}, segments: ${shape.subdivision}}))`;else if(shape=findNode(x3dTypes_POLYLINE2D,objects),shape){primitive=`line([[${shape.lineSegments.join("], [")}]])`}else if(shape=findNode(x3dTypes_RECTANGLE2D,objects),shape)primitive=`rectangle({size: [${shape.size}]})`;else if(shape=findNode(x3dTypes_TRIANGLESET2D,objects),shape){const numpoints=shape.vertices.length,numfaces=Math.trunc(numpoints/3);code+=`\n // 2D triangle set: ${numpoints} points, ${numfaces} faces\n const vertices = ${pointsToString(shape.vertices)}\n const triangles = []\n for (let i = 0; i < ${numfaces}; i = i + 3) {\n triangles.push(geom2.create([[vertices[i], vertices[i + 1], vertices[i + 2]]]))\n }\n`,primitive="triangles"}let results=translateMesh(0,objects);return results&&(primitive=results.primitive,code+=results.code),results=((options,objects)=>{const components=convertLine(0,objects);if(components){const{pointsSet:pointsSet,colors:colors}=components;let code=" let lines = []\n";return pointsSet.forEach(((points,i)=>{if(colors){const lineColor=colors[i];code+=` const line${i} = colorize([${lineColor}], primitives.line(${pointsToString(points)}))\n lines.push(line${i})\n`}else code+=` const line${i} = primitives.line(${pointsToString(points)})\n lines.push(line${i})\n`})),{primitive:"...lines",code:code}}return null})(0,objects),results&&(primitive=results.primitive,code+=results.code),primitive&&(code+=color?` objects.push(colorize([${color}], ${primitive}))`:` objects.push(${primitive})`),code+="\n return objects\n}\n",code},translatedList=[],translateDefinition=(options,object)=>{if(translatedList.includes(object.id))return"";translatedList.push(object.id);let code="";switch(object.definition){case x3dTypes_TRANSFORM:code+=((options,object)=>{let code=`\n// transform\nconst createObjects${object.id} = (options) => {\n let objects = []\n`;const objects=object.objects;for(let i=0;i<objects.length;i++)code+=` objects.push(...createObjects${objects[i].id}(options))\n`;return code+=`\n const matrix = [${createTransform(object.center,object.rotation,object.scale,object.scaleOrientation,object.translation)}]\n return transform(matrix, objects)\n}\n`,code+=translateDefinitions(options,objects),code})(options,object);break;case x3dTypes_SHAPE:code+=translateShape(0,object);break;case x3dTypes_GROUP:code+=((options,object)=>{let code=`\n// group\nconst createObjects${object.id} = (options) => {\n let objects = []\n`;const objects=object.objects;for(let i=0;i<objects.length;i++)code+=` objects.push(...createObjects${objects[i].id}(options))\n`;return code+="\n return objects\n}\n",code+=translateDefinitions(options,objects),code})(options,object);break;default:console.log("WARNING: unknown definition: "+object.definition)}return code},translateDefinitions=(options,objects)=>objects.reduce(((code,object,index)=>code+translateDefinition(options,object)),"");var saxes={},ed5$1={};!function(exports){
14
+ /**
15
+ * Character classes and associated utilities for the 5th edition of XML 1.0.
16
+ *
17
+ * @author Louis-Dominique Dubeau
18
+ * @license MIT
19
+ * @copyright Louis-Dominique Dubeau
20
+ */
21
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.CHAR="\t\n\r -퟿-�𐀀-􏿿",exports.S=" \t\r\n",exports.NAME_START_CHAR=":A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿",exports.NAME_CHAR="-"+exports.NAME_START_CHAR+".0-9·̀-ͯ‿-⁀",exports.CHAR_RE=new RegExp("^["+exports.CHAR+"]$","u"),exports.S_RE=new RegExp("^["+exports.S+"]+$","u"),exports.NAME_START_CHAR_RE=new RegExp("^["+exports.NAME_START_CHAR+"]$","u"),exports.NAME_CHAR_RE=new RegExp("^["+exports.NAME_CHAR+"]$","u"),exports.NAME_RE=new RegExp("^["+exports.NAME_START_CHAR+"]["+exports.NAME_CHAR+"]*$","u"),exports.NMTOKEN_RE=new RegExp("^["+exports.NAME_CHAR+"]+$","u");function isNameStartChar(c){return c>=65&&c<=90||c>=97&&c<=122||58===c||95===c||8204===c||8205===c||c>=192&&c<=214||c>=216&&c<=246||c>=248&&c<=767||c>=880&&c<=893||c>=895&&c<=8191||c>=8304&&c<=8591||c>=11264&&c<=12271||c>=12289&&c<=55295||c>=63744&&c<=64975||c>=65008&&c<=65533||c>=65536&&c<=983039}exports.S_LIST=[32,10,13,9],exports.isChar=function(c){return c>=32&&c<=55295||10===c||13===c||9===c||c>=57344&&c<=65533||c>=65536&&c<=1114111},exports.isS=function(c){return 32===c||10===c||13===c||9===c},exports.isNameStartChar=isNameStartChar,exports.isNameChar=function(c){return isNameStartChar(c)||c>=48&&c<=57||45===c||46===c||183===c||c>=768&&c<=879||c>=8255&&c<=8256}}(ed5$1);var ed2$1={};!function(exports){
22
+ /**
23
+ * Character classes and associated utilities for the 2nd edition of XML 1.1.
24
+ *
25
+ * @author Louis-Dominique Dubeau
26
+ * @license MIT
27
+ * @copyright Louis-Dominique Dubeau
28
+ */
29
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.CHAR="-퟿-�𐀀-􏿿",exports.RESTRICTED_CHAR="-\b\v\f--„†-Ÿ",exports.S=" \t\r\n",exports.NAME_START_CHAR=":A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿",exports.NAME_CHAR="-"+exports.NAME_START_CHAR+".0-9·̀-ͯ‿-⁀",exports.CHAR_RE=new RegExp("^["+exports.CHAR+"]$","u"),exports.RESTRICTED_CHAR_RE=new RegExp("^["+exports.RESTRICTED_CHAR+"]$","u"),exports.S_RE=new RegExp("^["+exports.S+"]+$","u"),exports.NAME_START_CHAR_RE=new RegExp("^["+exports.NAME_START_CHAR+"]$","u"),exports.NAME_CHAR_RE=new RegExp("^["+exports.NAME_CHAR+"]$","u"),exports.NAME_RE=new RegExp("^["+exports.NAME_START_CHAR+"]["+exports.NAME_CHAR+"]*$","u"),exports.NMTOKEN_RE=new RegExp("^["+exports.NAME_CHAR+"]+$","u");function isNameStartChar(c){return c>=65&&c<=90||c>=97&&c<=122||58===c||95===c||8204===c||8205===c||c>=192&&c<=214||c>=216&&c<=246||c>=248&&c<=767||c>=880&&c<=893||c>=895&&c<=8191||c>=8304&&c<=8591||c>=11264&&c<=12271||c>=12289&&c<=55295||c>=63744&&c<=64975||c>=65008&&c<=65533||c>=65536&&c<=983039}exports.S_LIST=[32,10,13,9],exports.isChar=function(c){return c>=1&&c<=55295||c>=57344&&c<=65533||c>=65536&&c<=1114111},exports.isRestrictedChar=function(c){return c>=1&&c<=8||11===c||12===c||c>=14&&c<=31||c>=127&&c<=132||c>=134&&c<=159},exports.isCharAndNotRestricted=function(c){return 9===c||10===c||13===c||c>31&&c<127||133===c||c>159&&c<=55295||c>=57344&&c<=65533||c>=65536&&c<=1114111},exports.isS=function(c){return 32===c||10===c||13===c||9===c},exports.isNameStartChar=isNameStartChar,exports.isNameChar=function(c){return isNameStartChar(c)||c>=48&&c<=57||45===c||46===c||183===c||c>=768&&c<=879||c>=8255&&c<=8256}}(ed2$1);var ed3={};!function(exports){function isNCNameStartChar(c){return c>=65&&c<=90||95===c||c>=97&&c<=122||c>=192&&c<=214||c>=216&&c<=246||c>=248&&c<=767||c>=880&&c<=893||c>=895&&c<=8191||c>=8204&&c<=8205||c>=8304&&c<=8591||c>=11264&&c<=12271||c>=12289&&c<=55295||c>=63744&&c<=64975||c>=65008&&c<=65533||c>=65536&&c<=983039}
30
+ /**
31
+ * Character class utilities for XML NS 1.0 edition 3.
32
+ *
33
+ * @author Louis-Dominique Dubeau
34
+ * @license MIT
35
+ * @copyright Louis-Dominique Dubeau
36
+ */
37
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.NC_NAME_START_CHAR="A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿",exports.NC_NAME_CHAR="-"+exports.NC_NAME_START_CHAR+".0-9·̀-ͯ‿-⁀",exports.NC_NAME_START_CHAR_RE=new RegExp("^["+exports.NC_NAME_START_CHAR+"]$","u"),exports.NC_NAME_CHAR_RE=new RegExp("^["+exports.NC_NAME_CHAR+"]$","u"),exports.NC_NAME_RE=new RegExp("^["+exports.NC_NAME_START_CHAR+"]["+exports.NC_NAME_CHAR+"]*$","u"),exports.isNCNameStartChar=isNCNameStartChar,exports.isNCNameChar=function(c){return isNCNameStartChar(c)||45===c||46===c||c>=48&&c<=57||183===c||c>=768&&c<=879||c>=8255&&c<=8256}}(ed3),Object.defineProperty(saxes,"__esModule",{value:!0});var SaxesParser_1=saxes.SaxesParser=saxes.EVENTS=void 0;var isS=ed5$1.isS,isChar10=ed5$1.isChar,isNameStartChar=ed5$1.isNameStartChar,isNameChar=ed5$1.isNameChar,S_LIST=ed5$1.S_LIST,NAME_RE=ed5$1.NAME_RE,isChar11=ed2$1.isChar,isNCNameStartChar=ed3.isNCNameStartChar,isNCNameChar=ed3.isNCNameChar,NC_NAME_RE=ed3.NC_NAME_RE;const XML_NAMESPACE="http://www.w3.org/XML/1998/namespace",XMLNS_NAMESPACE="http://www.w3.org/2000/xmlns/",rootNS={__proto__:null,xml:XML_NAMESPACE,xmlns:XMLNS_NAMESPACE},XML_ENTITIES={__proto__:null,amp:"&",gt:">",lt:"<",quot:'"',apos:"'"},isQuote=c=>34===c||39===c,QUOTES=[34,39],DOCTYPE_TERMINATOR=[...QUOTES,91,62],DTD_TERMINATOR=[...QUOTES,60,93],XML_DECL_NAME_TERMINATOR=[61,63,...S_LIST],ATTRIB_VALUE_UNQUOTED_TERMINATOR=[...S_LIST,62,38,60];function nsPairCheck(parser,prefix,uri){switch(prefix){case"xml":uri!==XML_NAMESPACE&&parser.fail(`xml prefix must be bound to ${XML_NAMESPACE}.`);break;case"xmlns":uri!==XMLNS_NAMESPACE&&parser.fail(`xmlns prefix must be bound to ${XMLNS_NAMESPACE}.`)}switch(uri){case XMLNS_NAMESPACE:parser.fail(""===prefix?`the default namespace may not be set to ${uri}.`:`may not assign a prefix (even "xmlns") to the URI ${XMLNS_NAMESPACE}.`);break;case XML_NAMESPACE:switch(prefix){case"xml":break;case"":parser.fail(`the default namespace may not be set to ${uri}.`);break;default:parser.fail("may not assign the xml namespace to another prefix.")}}}const isNCName=name=>NC_NAME_RE.test(name),isName=name=>NAME_RE.test(name);saxes.EVENTS=["xmldecl","text","processinginstruction","doctype","comment","opentagstart","attribute","opentag","closetag","cdata","error","end","ready"];const EVENT_NAME_TO_HANDLER_NAME={xmldecl:"xmldeclHandler",text:"textHandler",processinginstruction:"piHandler",doctype:"doctypeHandler",comment:"commentHandler",opentagstart:"openTagStartHandler",attribute:"attributeHandler",opentag:"openTagHandler",closetag:"closeTagHandler",cdata:"cdataHandler",error:"errorHandler",end:"endHandler",ready:"readyHandler"};SaxesParser_1=saxes.SaxesParser=class{constructor(opt){this.opt=null!=opt?opt:{},this.fragmentOpt=!!this.opt.fragment;const xmlnsOpt=this.xmlnsOpt=!!this.opt.xmlns;if(this.trackPosition=!1!==this.opt.position,this.fileName=this.opt.fileName,xmlnsOpt){this.nameStartCheck=isNCNameStartChar,this.nameCheck=isNCNameChar,this.isName=isNCName,this.processAttribs=this.processAttribsNS,this.pushAttrib=this.pushAttribNS,this.ns=Object.assign({__proto__:null},rootNS);const additional=this.opt.additionalNamespaces;null!=additional&&(!function(parser,mapping){for(const local of Object.keys(mapping))nsPairCheck(parser,local,mapping[local])}(this,additional),Object.assign(this.ns,additional))}else this.nameStartCheck=isNameStartChar,this.nameCheck=isNameChar,this.isName=isName,this.processAttribs=this.processAttribsPlain,this.pushAttrib=this.pushAttribPlain;this.stateTable=[this.sBegin,this.sBeginWhitespace,this.sDoctype,this.sDoctypeQuote,this.sDTD,this.sDTDQuoted,this.sDTDOpenWaka,this.sDTDOpenWakaBang,this.sDTDComment,this.sDTDCommentEnding,this.sDTDCommentEnded,this.sDTDPI,this.sDTDPIEnding,this.sText,this.sEntity,this.sOpenWaka,this.sOpenWakaBang,this.sComment,this.sCommentEnding,this.sCommentEnded,this.sCData,this.sCDataEnding,this.sCDataEnding2,this.sPIFirstChar,this.sPIRest,this.sPIBody,this.sPIEnding,this.sXMLDeclNameStart,this.sXMLDeclName,this.sXMLDeclEq,this.sXMLDeclValueStart,this.sXMLDeclValue,this.sXMLDeclSeparator,this.sXMLDeclEnding,this.sOpenTag,this.sOpenTagSlash,this.sAttrib,this.sAttribName,this.sAttribNameSawWhite,this.sAttribValue,this.sAttribValueQuoted,this.sAttribValueClosed,this.sAttribValueUnquoted,this.sCloseTag,this.sCloseTagSawWhite],this._init()}get closed(){return this._closed}_init(){var _a;this.openWakaBang="",this.text="",this.name="",this.piTarget="",this.entity="",this.q=null,this.tags=[],this.tag=null,this.topNS=null,this.chunk="",this.chunkPosition=0,this.i=0,this.prevI=0,this.carriedFromPrevious=void 0,this.forbiddenState=0,this.attribList=[];const{fragmentOpt:fragmentOpt}=this;this.state=fragmentOpt?13:0,this.reportedTextBeforeRoot=this.reportedTextAfterRoot=this.closedRoot=this.sawRoot=fragmentOpt,this.xmlDeclPossible=!fragmentOpt,this.xmlDeclExpects=["version"],this.entityReturnState=void 0;let{defaultXMLVersion:defaultXMLVersion}=this.opt;if(void 0===defaultXMLVersion){if(!0===this.opt.forceXMLVersion)throw new Error("forceXMLVersion set but defaultXMLVersion is not set");defaultXMLVersion="1.0"}this.setXMLVersion(defaultXMLVersion),this.positionAtNewLine=0,this.doctype=!1,this._closed=!1,this.xmlDecl={version:void 0,encoding:void 0,standalone:void 0},this.line=1,this.column=0,this.ENTITIES=Object.create(XML_ENTITIES),null===(_a=this.readyHandler)||void 0===_a||_a.call(this)}get position(){return this.chunkPosition+this.i}get columnIndex(){return this.position-this.positionAtNewLine}on(name,handler){this[EVENT_NAME_TO_HANDLER_NAME[name]]=handler}off(name){this[EVENT_NAME_TO_HANDLER_NAME[name]]=void 0}makeError(message){var _a;let msg=null!==(_a=this.fileName)&&void 0!==_a?_a:"";return this.trackPosition&&(msg.length>0&&(msg+=":"),msg+=`${this.line}:${this.column}`),msg.length>0&&(msg+=": "),new Error(msg+message)}fail(message){const err=this.makeError(message),handler=this.errorHandler;if(void 0===handler)throw err;return handler(err),this}write(chunk){if(this.closed)return this.fail("cannot write after close; assign an onready handler.");let end=!1;null===chunk?(end=!0,chunk=""):"object"==typeof chunk&&(chunk=chunk.toString()),void 0!==this.carriedFromPrevious&&(chunk=`${this.carriedFromPrevious}${chunk}`,this.carriedFromPrevious=void 0);let limit=chunk.length;const lastCode=chunk.charCodeAt(limit-1);!end&&(13===lastCode||lastCode>=55296&&lastCode<=56319)&&(this.carriedFromPrevious=chunk[limit-1],limit--,chunk=chunk.slice(0,limit));const{stateTable:stateTable}=this;for(this.chunk=chunk,this.i=0;this.i<limit;)stateTable[this.state].call(this);return this.chunkPosition+=limit,end?this.end():this}close(){return this.write(null)}getCode10(){const{chunk:chunk,i:i}=this;if(this.prevI=i,this.i=i+1,i>=chunk.length)return-1;const code=chunk.charCodeAt(i);if(this.column++,code<55296){if(code>=32||9===code)return code;switch(code){case 10:return this.line++,this.column=0,this.positionAtNewLine=this.position,10;case 13:return 10===chunk.charCodeAt(i+1)&&(this.i=i+2),this.line++,this.column=0,this.positionAtNewLine=this.position,-2;default:return this.fail("disallowed character."),code}}if(code>56319)return code>=57344&&code<=65533||this.fail("disallowed character."),code;const final=65536+1024*(code-55296)+(chunk.charCodeAt(i+1)-56320);return this.i=i+2,final>1114111&&this.fail("disallowed character."),final}getCode11(){const{chunk:chunk,i:i}=this;if(this.prevI=i,this.i=i+1,i>=chunk.length)return-1;const code=chunk.charCodeAt(i);if(this.column++,code<55296){if(code>31&&code<127||code>159&&8232!==code||9===code)return code;switch(code){case 10:return this.line++,this.column=0,this.positionAtNewLine=this.position,10;case 13:{const next=chunk.charCodeAt(i+1);10!==next&&133!==next||(this.i=i+2)}case 133:case 8232:return this.line++,this.column=0,this.positionAtNewLine=this.position,-2;default:return this.fail("disallowed character."),code}}if(code>56319)return code>=57344&&code<=65533||this.fail("disallowed character."),code;const final=65536+1024*(code-55296)+(chunk.charCodeAt(i+1)-56320);return this.i=i+2,final>1114111&&this.fail("disallowed character."),final}getCodeNorm(){const c=this.getCode();return-2===c?10:c}unget(){this.i=this.prevI,this.column--}captureTo(chars){let{i:start}=this;const{chunk:chunk}=this;for(;;){const c=this.getCode(),isNLLike=-2===c,final=isNLLike?10:c;if(-1===final||chars.includes(final))return this.text+=chunk.slice(start,this.prevI),final;isNLLike&&(this.text+=`${chunk.slice(start,this.prevI)}\n`,start=this.i)}}captureToChar(char){let{i:start}=this;const{chunk:chunk}=this;for(;;){let c=this.getCode();switch(c){case-2:this.text+=`${chunk.slice(start,this.prevI)}\n`,start=this.i,c=10;break;case-1:return this.text+=chunk.slice(start),!1}if(c===char)return this.text+=chunk.slice(start,this.prevI),!0}}captureNameChars(){const{chunk:chunk,i:start}=this;for(;;){const c=this.getCode();if(-1===c)return this.name+=chunk.slice(start),-1;if(!isNameChar(c))return this.name+=chunk.slice(start,this.prevI),-2===c?10:c}}skipSpaces(){for(;;){const c=this.getCodeNorm();if(-1===c||!isS(c))return c}}setXMLVersion(version){this.currentXMLVersion=version,"1.0"===version?(this.isChar=isChar10,this.getCode=this.getCode10):(this.isChar=isChar11,this.getCode=this.getCode11)}sBegin(){65279===this.chunk.charCodeAt(0)&&(this.i++,this.column++),this.state=1}sBeginWhitespace(){const iBefore=this.i,c=this.skipSpaces();switch(this.prevI!==iBefore&&(this.xmlDeclPossible=!1),c){case 60:if(this.state=15,0!==this.text.length)throw new Error("no-empty text at start");break;case-1:break;default:this.unget(),this.state=13,this.xmlDeclPossible=!1}}sDoctype(){var _a;const c=this.captureTo(DOCTYPE_TERMINATOR);switch(c){case 62:null===(_a=this.doctypeHandler)||void 0===_a||_a.call(this,this.text),this.text="",this.state=13,this.doctype=!0;break;case-1:break;default:this.text+=String.fromCodePoint(c),91===c?this.state=4:isQuote(c)&&(this.state=3,this.q=c)}}sDoctypeQuote(){const q=this.q;this.captureToChar(q)&&(this.text+=String.fromCodePoint(q),this.q=null,this.state=2)}sDTD(){const c=this.captureTo(DTD_TERMINATOR);-1!==c&&(this.text+=String.fromCodePoint(c),93===c?this.state=2:60===c?this.state=6:isQuote(c)&&(this.state=5,this.q=c))}sDTDQuoted(){const q=this.q;this.captureToChar(q)&&(this.text+=String.fromCodePoint(q),this.state=4,this.q=null)}sDTDOpenWaka(){const c=this.getCodeNorm();switch(this.text+=String.fromCodePoint(c),c){case 33:this.state=7,this.openWakaBang="";break;case 63:this.state=11;break;default:this.state=4}}sDTDOpenWakaBang(){const char=String.fromCodePoint(this.getCodeNorm()),owb=this.openWakaBang+=char;this.text+=char,"-"!==owb&&(this.state="--"===owb?8:4,this.openWakaBang="")}sDTDComment(){this.captureToChar(45)&&(this.text+="-",this.state=9)}sDTDCommentEnding(){const c=this.getCodeNorm();this.text+=String.fromCodePoint(c),this.state=45===c?10:8}sDTDCommentEnded(){const c=this.getCodeNorm();this.text+=String.fromCodePoint(c),62===c?this.state=4:(this.fail("malformed comment."),this.state=8)}sDTDPI(){this.captureToChar(63)&&(this.text+="?",this.state=12)}sDTDPIEnding(){const c=this.getCodeNorm();this.text+=String.fromCodePoint(c),62===c&&(this.state=4)}sText(){0!==this.tags.length?this.handleTextInRoot():this.handleTextOutsideRoot()}sEntity(){let{i:start}=this;const{chunk:chunk}=this;loop:for(;;)switch(this.getCode()){case-2:this.entity+=`${chunk.slice(start,this.prevI)}\n`,start=this.i;break;case 59:{const{entityReturnState:entityReturnState}=this,entity=this.entity+chunk.slice(start,this.prevI);let parsed;this.state=entityReturnState,""===entity?(this.fail("empty entity name."),parsed="&;"):(parsed=this.parseEntity(entity),this.entity=""),13===entityReturnState&&void 0===this.textHandler||(this.text+=parsed);break loop}case-1:this.entity+=chunk.slice(start);break loop}}sOpenWaka(){const c=this.getCode();if(isNameStartChar(c))this.state=34,this.unget(),this.xmlDeclPossible=!1;else switch(c){case 47:this.state=43,this.xmlDeclPossible=!1;break;case 33:this.state=16,this.openWakaBang="",this.xmlDeclPossible=!1;break;case 63:this.state=23;break;default:this.fail("disallowed character in tag name"),this.state=13,this.xmlDeclPossible=!1}}sOpenWakaBang(){switch(this.openWakaBang+=String.fromCodePoint(this.getCodeNorm()),this.openWakaBang){case"[CDATA[":this.sawRoot||this.reportedTextBeforeRoot||(this.fail("text data outside of root node."),this.reportedTextBeforeRoot=!0),this.closedRoot&&!this.reportedTextAfterRoot&&(this.fail("text data outside of root node."),this.reportedTextAfterRoot=!0),this.state=20,this.openWakaBang="";break;case"--":this.state=17,this.openWakaBang="";break;case"DOCTYPE":this.state=2,(this.doctype||this.sawRoot)&&this.fail("inappropriately located doctype declaration."),this.openWakaBang="";break;default:this.openWakaBang.length>=7&&this.fail("incorrect syntax.")}}sComment(){this.captureToChar(45)&&(this.state=18)}sCommentEnding(){var _a;const c=this.getCodeNorm();45===c?(this.state=19,null===(_a=this.commentHandler)||void 0===_a||_a.call(this,this.text),this.text=""):(this.text+=`-${String.fromCodePoint(c)}`,this.state=17)}sCommentEnded(){const c=this.getCodeNorm();62!==c?(this.fail("malformed comment."),this.text+=`--${String.fromCodePoint(c)}`,this.state=17):this.state=13}sCData(){this.captureToChar(93)&&(this.state=21)}sCDataEnding(){const c=this.getCodeNorm();93===c?this.state=22:(this.text+=`]${String.fromCodePoint(c)}`,this.state=20)}sCDataEnding2(){var _a;const c=this.getCodeNorm();switch(c){case 62:null===(_a=this.cdataHandler)||void 0===_a||_a.call(this,this.text),this.text="",this.state=13;break;case 93:this.text+="]";break;default:this.text+=`]]${String.fromCodePoint(c)}`,this.state=20}}sPIFirstChar(){const c=this.getCodeNorm();this.nameStartCheck(c)?(this.piTarget+=String.fromCodePoint(c),this.state=24):63===c||isS(c)?(this.fail("processing instruction without a target."),this.state=63===c?26:25):(this.fail("disallowed character in processing instruction name."),this.piTarget+=String.fromCodePoint(c),this.state=24)}sPIRest(){const{chunk:chunk,i:start}=this;for(;;){const c=this.getCodeNorm();if(-1===c)return void(this.piTarget+=chunk.slice(start));if(!this.nameCheck(c)){this.piTarget+=chunk.slice(start,this.prevI);const isQuestion=63===c;isQuestion||isS(c)?"xml"===this.piTarget?(this.xmlDeclPossible||this.fail("an XML declaration must be at the start of the document."),this.state=isQuestion?33:27):this.state=isQuestion?26:25:(this.fail("disallowed character in processing instruction name."),this.piTarget+=String.fromCodePoint(c));break}}}sPIBody(){if(0===this.text.length){const c=this.getCodeNorm();63===c?this.state=26:isS(c)||(this.text=String.fromCodePoint(c))}else this.captureToChar(63)&&(this.state=26)}sPIEnding(){var _a;const c=this.getCodeNorm();if(62===c){const{piTarget:piTarget}=this;"xml"===piTarget.toLowerCase()&&this.fail("the XML declaration must appear at the start of the document."),null===(_a=this.piHandler)||void 0===_a||_a.call(this,{target:piTarget,body:this.text}),this.piTarget=this.text="",this.state=13}else 63===c?this.text+="?":(this.text+=`?${String.fromCodePoint(c)}`,this.state=25);this.xmlDeclPossible=!1}sXMLDeclNameStart(){const c=this.skipSpaces();63!==c?-1!==c&&(this.state=28,this.name=String.fromCodePoint(c)):this.state=33}sXMLDeclName(){const c=this.captureTo(XML_DECL_NAME_TERMINATOR);if(63===c)return this.state=33,this.name+=this.text,this.text="",void this.fail("XML declaration is incomplete.");if(isS(c)||61===c){if(this.name+=this.text,this.text="",!this.xmlDeclExpects.includes(this.name))switch(this.name.length){case 0:this.fail("did not expect any more name/value pairs.");break;case 1:this.fail(`expected the name ${this.xmlDeclExpects[0]}.`);break;default:this.fail(`expected one of ${this.xmlDeclExpects.join(", ")}`)}this.state=61===c?30:29}}sXMLDeclEq(){const c=this.getCodeNorm();if(63===c)return this.state=33,void this.fail("XML declaration is incomplete.");isS(c)||(61!==c&&this.fail("value required."),this.state=30)}sXMLDeclValueStart(){const c=this.getCodeNorm();if(63===c)return this.state=33,void this.fail("XML declaration is incomplete.");isS(c)||(isQuote(c)?this.q=c:(this.fail("value must be quoted."),this.q=32),this.state=31)}sXMLDeclValue(){const c=this.captureTo([this.q,63]);if(63===c)return this.state=33,this.text="",void this.fail("XML declaration is incomplete.");if(-1===c)return;const value=this.text;switch(this.text="",this.name){case"version":{this.xmlDeclExpects=["encoding","standalone"];const version=value;this.xmlDecl.version=version,/^1\.[0-9]+$/.test(version)?this.opt.forceXMLVersion||this.setXMLVersion(version):this.fail("version number must match /^1\\.[0-9]+$/.");break}case"encoding":/^[A-Za-z][A-Za-z0-9._-]*$/.test(value)||this.fail("encoding value must match /^[A-Za-z0-9][A-Za-z0-9._-]*$/."),this.xmlDeclExpects=["standalone"],this.xmlDecl.encoding=value;break;case"standalone":"yes"!==value&&"no"!==value&&this.fail('standalone value must match "yes" or "no".'),this.xmlDeclExpects=[],this.xmlDecl.standalone=value}this.name="",this.state=32}sXMLDeclSeparator(){const c=this.getCodeNorm();63!==c?(isS(c)||(this.fail("whitespace required."),this.unget()),this.state=27):this.state=33}sXMLDeclEnding(){var _a;62===this.getCodeNorm()?("xml"!==this.piTarget?this.fail("processing instructions are not allowed before root."):"version"!==this.name&&this.xmlDeclExpects.includes("version")&&this.fail("XML declaration must contain a version."),null===(_a=this.xmldeclHandler)||void 0===_a||_a.call(this,this.xmlDecl),this.name="",this.piTarget=this.text="",this.state=13):this.fail("The character ? is disallowed anywhere in XML declarations."),this.xmlDeclPossible=!1}sOpenTag(){var _a;const c=this.captureNameChars();if(-1===c)return;const tag=this.tag={name:this.name,attributes:Object.create(null)};switch(this.name="",this.xmlnsOpt&&(this.topNS=tag.ns=Object.create(null)),null===(_a=this.openTagStartHandler)||void 0===_a||_a.call(this,tag),this.sawRoot=!0,!this.fragmentOpt&&this.closedRoot&&this.fail("documents may contain only one root."),c){case 62:this.openTag();break;case 47:this.state=35;break;default:isS(c)||this.fail("disallowed character in tag name."),this.state=36}}sOpenTagSlash(){62===this.getCode()?this.openSelfClosingTag():(this.fail("forward-slash in opening tag not followed by >."),this.state=36)}sAttrib(){const c=this.skipSpaces();-1!==c&&(isNameStartChar(c)?(this.unget(),this.state=37):62===c?this.openTag():47===c?this.state=35:this.fail("disallowed character in attribute name."))}sAttribName(){const c=this.captureNameChars();61===c?this.state=39:isS(c)?this.state=38:62===c?(this.fail("attribute without value."),this.pushAttrib(this.name,this.name),this.name=this.text="",this.openTag()):-1!==c&&this.fail("disallowed character in attribute name.")}sAttribNameSawWhite(){const c=this.skipSpaces();switch(c){case-1:return;case 61:this.state=39;break;default:this.fail("attribute without value."),this.text="",this.name="",62===c?this.openTag():isNameStartChar(c)?(this.unget(),this.state=37):(this.fail("disallowed character in attribute name."),this.state=36)}}sAttribValue(){const c=this.getCodeNorm();isQuote(c)?(this.q=c,this.state=40):isS(c)||(this.fail("unquoted attribute value."),this.state=42,this.unget())}sAttribValueQuoted(){const{q:q,chunk:chunk}=this;let{i:start}=this;for(;;)switch(this.getCode()){case q:return this.pushAttrib(this.name,this.text+chunk.slice(start,this.prevI)),this.name=this.text="",this.q=null,void(this.state=41);case 38:return this.text+=chunk.slice(start,this.prevI),this.state=14,void(this.entityReturnState=40);case 10:case-2:case 9:this.text+=`${chunk.slice(start,this.prevI)} `,start=this.i;break;case 60:return this.text+=chunk.slice(start,this.prevI),void this.fail("disallowed character.");case-1:return void(this.text+=chunk.slice(start))}}sAttribValueClosed(){const c=this.getCodeNorm();isS(c)?this.state=36:62===c?this.openTag():47===c?this.state=35:isNameStartChar(c)?(this.fail("no whitespace between attributes."),this.unget(),this.state=37):this.fail("disallowed character in attribute name.")}sAttribValueUnquoted(){const c=this.captureTo(ATTRIB_VALUE_UNQUOTED_TERMINATOR);switch(c){case 38:this.state=14,this.entityReturnState=42;break;case 60:this.fail("disallowed character.");break;case-1:break;default:this.text.includes("]]>")&&this.fail('the string "]]>" is disallowed in char data.'),this.pushAttrib(this.name,this.text),this.name=this.text="",62===c?this.openTag():this.state=36}}sCloseTag(){const c=this.captureNameChars();62===c?this.closeTag():isS(c)?this.state=44:-1!==c&&this.fail("disallowed character in closing tag.")}sCloseTagSawWhite(){switch(this.skipSpaces()){case 62:this.closeTag();break;case-1:break;default:this.fail("disallowed character in closing tag.")}}handleTextInRoot(){let{i:start,forbiddenState:forbiddenState}=this;const{chunk:chunk,textHandler:handler}=this;scanLoop:for(;;)switch(this.getCode()){case 60:if(this.state=15,void 0!==handler){const{text:text}=this,slice=chunk.slice(start,this.prevI);0!==text.length?(handler(text+slice),this.text=""):0!==slice.length&&handler(slice)}forbiddenState=0;break scanLoop;case 38:this.state=14,this.entityReturnState=13,void 0!==handler&&(this.text+=chunk.slice(start,this.prevI)),forbiddenState=0;break scanLoop;case 93:switch(forbiddenState){case 0:forbiddenState=1;break;case 1:forbiddenState=2;break;case 2:break;default:throw new Error("impossible state")}break;case 62:2===forbiddenState&&this.fail('the string "]]>" is disallowed in char data.'),forbiddenState=0;break;case-2:void 0!==handler&&(this.text+=`${chunk.slice(start,this.prevI)}\n`),start=this.i,forbiddenState=0;break;case-1:void 0!==handler&&(this.text+=chunk.slice(start));break scanLoop;default:forbiddenState=0}this.forbiddenState=forbiddenState}handleTextOutsideRoot(){let{i:start}=this;const{chunk:chunk,textHandler:handler}=this;let nonSpace=!1;outRootLoop:for(;;){const code=this.getCode();switch(code){case 60:if(this.state=15,void 0!==handler){const{text:text}=this,slice=chunk.slice(start,this.prevI);0!==text.length?(handler(text+slice),this.text=""):0!==slice.length&&handler(slice)}break outRootLoop;case 38:this.state=14,this.entityReturnState=13,void 0!==handler&&(this.text+=chunk.slice(start,this.prevI)),nonSpace=!0;break outRootLoop;case-2:void 0!==handler&&(this.text+=`${chunk.slice(start,this.prevI)}\n`),start=this.i;break;case-1:void 0!==handler&&(this.text+=chunk.slice(start));break outRootLoop;default:isS(code)||(nonSpace=!0)}}nonSpace&&(this.sawRoot||this.reportedTextBeforeRoot||(this.fail("text data outside of root node."),this.reportedTextBeforeRoot=!0),this.closedRoot&&!this.reportedTextAfterRoot&&(this.fail("text data outside of root node."),this.reportedTextAfterRoot=!0))}pushAttribNS(name,value){var _a;const{prefix:prefix,local:local}=this.qname(name),attr={name:name,prefix:prefix,local:local,value:value};if(this.attribList.push(attr),null===(_a=this.attributeHandler)||void 0===_a||_a.call(this,attr),"xmlns"===prefix){const trimmed=value.trim();"1.0"===this.currentXMLVersion&&""===trimmed&&this.fail("invalid attempt to undefine prefix in XML 1.0"),this.topNS[local]=trimmed,nsPairCheck(this,local,trimmed)}else if("xmlns"===name){const trimmed=value.trim();this.topNS[""]=trimmed,nsPairCheck(this,"",trimmed)}}pushAttribPlain(name,value){var _a;const attr={name:name,value:value};this.attribList.push(attr),null===(_a=this.attributeHandler)||void 0===_a||_a.call(this,attr)}end(){var _a,_b;this.sawRoot||this.fail("document must contain a root element.");const{tags:tags}=this;for(;tags.length>0;){const tag=tags.pop();this.fail(`unclosed tag: ${tag.name}`)}0!==this.state&&13!==this.state&&this.fail("unexpected end.");const{text:text}=this;return 0!==text.length&&(null===(_a=this.textHandler)||void 0===_a||_a.call(this,text),this.text=""),this._closed=!0,null===(_b=this.endHandler)||void 0===_b||_b.call(this),this._init(),this}resolve(prefix){var _a,_b;let uri=this.topNS[prefix];if(void 0!==uri)return uri;const{tags:tags}=this;for(let index=tags.length-1;index>=0;index--)if(uri=tags[index].ns[prefix],void 0!==uri)return uri;return uri=this.ns[prefix],void 0!==uri?uri:null===(_b=(_a=this.opt).resolvePrefix)||void 0===_b?void 0:_b.call(_a,prefix)}qname(name){const colon=name.indexOf(":");if(-1===colon)return{prefix:"",local:name};const local=name.slice(colon+1),prefix=name.slice(0,colon);return(""===prefix||""===local||local.includes(":"))&&this.fail(`malformed name: ${name}.`),{prefix:prefix,local:local}}processAttribsNS(){var _a;const{attribList:attribList}=this,tag=this.tag;{const{prefix:prefix,local:local}=this.qname(tag.name);tag.prefix=prefix,tag.local=local;const uri=tag.uri=null!==(_a=this.resolve(prefix))&&void 0!==_a?_a:"";""!==prefix&&("xmlns"===prefix&&this.fail('tags may not have "xmlns" as prefix.'),""===uri&&(this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`),tag.uri=prefix))}if(0===attribList.length)return;const{attributes:attributes}=tag,seen=new Set;for(const attr of attribList){const{name:name,prefix:prefix,local:local}=attr;let uri,eqname;""===prefix?(uri="xmlns"===name?XMLNS_NAMESPACE:"",eqname=name):(uri=this.resolve(prefix),void 0===uri&&(this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`),uri=prefix),eqname=`{${uri}}${local}`),seen.has(eqname)&&this.fail(`duplicate attribute: ${eqname}.`),seen.add(eqname),attr.uri=uri,attributes[name]=attr}this.attribList=[]}processAttribsPlain(){const{attribList:attribList}=this,attributes=this.tag.attributes;for(const{name:name,value:value}of attribList)void 0!==attributes[name]&&this.fail(`duplicate attribute: ${name}.`),attributes[name]=value;this.attribList=[]}openTag(){var _a;this.processAttribs();const{tags:tags}=this,tag=this.tag;tag.isSelfClosing=!1,null===(_a=this.openTagHandler)||void 0===_a||_a.call(this,tag),tags.push(tag),this.state=13,this.name=""}openSelfClosingTag(){var _a,_b,_c;this.processAttribs();const{tags:tags}=this,tag=this.tag;tag.isSelfClosing=!0,null===(_a=this.openTagHandler)||void 0===_a||_a.call(this,tag),null===(_b=this.closeTagHandler)||void 0===_b||_b.call(this,tag);null===(this.tag=null!==(_c=tags[tags.length-1])&&void 0!==_c?_c:null)&&(this.closedRoot=!0),this.state=13,this.name=""}closeTag(){const{tags:tags,name:name}=this;if(this.state=13,this.name="",""===name)return this.fail("weird empty close tag."),void(this.text+="</>");const handler=this.closeTagHandler;let l=tags.length;for(;l-- >0;){const tag=this.tag=tags.pop();if(this.topNS=tag.ns,null==handler||handler(tag),tag.name===name)break;this.fail("unexpected close tag.")}0===l?this.closedRoot=!0:l<0&&(this.fail(`unmatched closing tag: ${name}.`),this.text+=`</${name}>`)}parseEntity(entity){if("#"!==entity[0]){const defined=this.ENTITIES[entity];return void 0!==defined?defined:(this.fail(this.isName(entity)?"undefined entity.":"disallowed character in entity name."),`&${entity};`)}let num=NaN;return"x"===entity[1]&&/^#x[0-9a-f]+$/i.test(entity)?num=parseInt(entity.slice(2),16):/^#[0-9]+$/.test(entity)&&(num=parseInt(entity.slice(1),10)),this.isChar(num)?String.fromCodePoint(num):(this.fail("malformed character entity."),`&${entity};`)}};let x3dLast=null,x3dDefinition=x3dTypes_X3D;const x3dObjects=[],x3dDefs=new Map,x3dMaterials=[],x3dTextures=[],x3dLength={factor:1,name:"meters"},x3dAngle={factor:1,name:"radians"};let x3dObj=null;const nodeToObjectMap={X3D:element=>{const obj={definition:x3dTypes_X3D,objects:[]};return obj},UNIT:element=>{const obj={definition:x3dTypes_UNIT,category:"",name:"",conversionFactor:1};return element.category&&(obj.category=element.category),element.name&&(obj.name=element.name),element.conversionfactor&&(obj.conversionFactor=element.conversionfactor),obj},META:element=>{const obj={definition:x3dTypes_META,content:"",name:""};return element.content&&(obj.content=element.content),element.name&&(obj.name=element.name),obj},SCENE:element=>{const obj={definition:x3dTypes_SCENE,objects:[]};return obj},TRANSFORM:element=>{const obj={definition:x3dTypes_TRANSFORM,center:[0,0,0],rotation:[0,0,1,0],scale:[1,1,1],scaleOrientation:[0,0,1,0],translation:[0,0,0]};if(element.center){const values=element.center.trim().split(/ +/).map((v=>parseFloat(v)));values.length>2&&(obj.center=values)}if(element.rotation){const values=element.rotation.trim().split(/ +/).map((v=>parseFloat(v)));values.length>3&&(obj.rotation=values)}if(element.scale){const values=element.scale.trim().split(/ +/).map((v=>parseFloat(v)));values.length>2&&(obj.scale=values)}if(element.scaleorientation){const values=element.scaleorientation.trim().split(/ +/).map((v=>parseFloat(v)));values.length>3&&(obj.scaleOrientation=values)}if(element.translation){const values=element.translation.trim().split(/ +/).map((v=>parseFloat(v)));values.length>2&&(obj.translation=values)}return obj.objects=[],obj},SHAPE:element=>{const obj={definition:x3dTypes_SHAPE,objects:[]};return obj},GROUP:x3dGroup,STATICGROUP:x3dGroup,BOX:element=>{const obj={definition:x3dTypes_BOX,size:[2,2,2]};if(element.size){const values=element.size.trim().split(/ +/).map((v=>parseFloat(v)));values.length>2&&(obj.size=values)}return obj},CONE:element=>{const obj={definition:x3dTypes_CONE,bottomRadius:1,height:2,subdivision:32,topRadius:1e-5};return element.bottomRadius&&(obj.bottomRadius=Math.max(parseFloat(element.bottomRadius),1e-5)),element.height&&(obj.height=parseFloat(element.height)),element.subdivision&&(obj.subdivision=parseFloat(element.subdivision)),element.topRadius&&(obj.topRadius=Math.max(parseFloat(element.topRadius),1e-5)),obj},CYLINDER:element=>{const obj={definition:x3dTypes_CYLINDER,height:2,radius:1,subdivision:32};return element.height&&(obj.height=parseFloat(element.height)),element.radius&&(obj.radius=parseFloat(element.radius)),element.subdivision&&(obj.subdivision=parseFloat(element.subdivision)),obj},SPHERE:element=>{const obj={definition:x3dTypes_SPHERE,radius:1,subdivision:24};if(element.radius&&(obj.radius=parseFloat(element.radius)),element.subdivision){const values=element.subdivision.trim().split(/ +/).map((v=>parseFloat(v)));values.length>1&&(obj.subdivision=Math.max(...values))}return obj},EXTRUSION:element=>{const obj={definition:x3dTypes_EXTRUSION,ccw:!0,beginCap:!0,endCap:!0,crossSection:[[1,1],[1,-1],[-1,-1],[-1,1],[1,1]],orientations:[[0,0,1,0]],scales:[[1,1]],spine:[[0,0,0],[0,1,0]]};if(element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.beginCap&&(obj.beginCap=element.beginCap.includes("TRUE")||element.beginCap.includes("true")),element.endCap&&(obj.endCap=element.endCap.includes("TRUE")||element.endCap.includes("true")),element.crossSection){const values=element.crossSection.trim().split(/ +/).map((v=>parseFloat(v))),numpoints=Math.trunc(values.length/2),points=[];for(let i=0;i<numpoints;i++){const vi=2*i;points.push([values[vi],values[vi+1]])}obj.ccw=index$3.measureArea(index$3.create(points))<0,obj.crossSection=points}if(element.orientation){const values=element.orientation.trim().split(/ +/).map((v=>parseFloat(v))),numpoints=Math.trunc(values.length/4),points=[];for(let i=0;i<numpoints;i++){const vi=4*i;points.push([values[vi],values[vi+1],values[vi+2],values[vi+3]])}obj.orientations=points}if(element.scale){const values=element.scale.trim().split(/ +/).map((v=>parseFloat(v))),numpoints=Math.trunc(values.length/2),points=[];for(let i=0;i<numpoints;i++){const vi=2*i;0===values[vi]&&(values[vi]=1e-6),0===values[vi+1]&&(values[vi+1]=1e-6),points.push([values[vi],values[vi+1]])}obj.scales=points}if(element.spine){const values=element.spine.trim().split(/ +/).map((v=>parseFloat(v))),numpoints=Math.trunc(values.length/3),points=[];for(let i=0;i<numpoints;i++){const vi=3*i;points.push([values[vi],values[vi+1],values[vi+2]])}obj.spine=points}return obj},ARC2D:element=>{const obj={definition:x3dTypes_ARC2D,endAngle:Math.PI/2,radius:1,startAngle:0,subdivision:32};return element.endAngle&&(obj.endAngle=parseFloat(element.endAngle)),element.radius&&(obj.radius=parseFloat(element.radius)),element.startAngle&&(obj.startAngle=parseFloat(element.startAngle)),element.subdivision&&(obj.subdivision=parseFloat(element.subdivision)),obj},ARCCLOSE2D:element=>{const obj={definition:x3dTypes_ARCCLOSE2D,closureType:"PIE",endAngle:Math.PI/2,radius:1,startAngle:0,subdivision:32};return element.closureType&&(obj.closureType=element.closureType),element.endAngle&&(obj.endAngle=parseFloat(element.endAngle)),element.radius&&(obj.radius=parseFloat(element.radius)),element.startAngle&&(obj.startAngle=parseFloat(element.startAngle)),element.subdivision&&(obj.subdivision=parseFloat(element.subdivision)),obj},CIRCLE2D:element=>{const obj={definition:x3dTypes_CIRCLE2D,radius:1,subdivision:32};return element.radius&&(obj.radius=parseFloat(element.radius)),element.subdivision&&(obj.subdivision=parseFloat(element.subdivision)),obj},DISK2D:element=>{const obj={definition:x3dTypes_DISK2D,innerRadius:0,outerRadius:1,subdivision:32};return element.innerRadius&&(obj.innerRadius=parseFloat(element.innerRadius)),element.outerRadius&&(obj.outerRadius=parseFloat(element.outerRadius)),element.subdivision&&(obj.subdivision=parseFloat(element.subdivision)),obj},POLYLINE2D:element=>{const obj={definition:x3dTypes_POLYLINE2D,lineSegments:[]};if(element.lineSegments){const values=element.lineSegments.trim().split(/ +/).map((v=>parseFloat(v)));for(let i=0;i<values.length;i+=2){const point=[values[i],values[i+1]];obj.lineSegments.push(point)}}return obj},RECTANGLE2D:element=>{const obj={definition:x3dTypes_RECTANGLE2D,size:[2,2]};if(element.size){const values=element.size.trim().split(/ +/).map((v=>parseFloat(v)));values.length>1&&(obj.size=values)}return obj},TRIANGLESET2D:element=>{const obj={definition:x3dTypes_TRIANGLESET2D,vertices:[]};if(element.vertices){const values=element.vertices.trim().split(/ +/).map((v=>parseFloat(v)));for(let i=0;i<values.length;i+=2){const point=[values[i],values[i+1]];obj.vertices.push(point)}}return obj},COLOR:element=>{const obj={definition:x3dTypes_COLOR,colors:[]};if(element.color){const values=element.color.trim().split(/ +/).map((v=>parseFloat(v))),numvalues=values.length,numcolors=Math.trunc(numvalues/3);for(let i=0;i<numcolors;i++){const vi=3*i;obj.colors.push([values[vi],values[vi+1],values[vi+2]])}}return obj},COORDINATE:element=>{const obj={definition:x3dTypes_COORDINATE,points:[]};if(element.point){const values=element.point.trim().split(/ +/).map((v=>parseFloat(v))),numvalues=values.length,numpoints=Math.trunc(numvalues/3);for(let i=0;i<numpoints;i++){const vi=3*i;obj.points.push([values[vi],values[vi+1],values[vi+2]])}}return obj},TRIANGLESET:element=>{const obj={definition:x3dTypes_TRIANGLESET,ccw:!0,colorPerVertex:!0};return element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),obj.objects=[],obj},TRIANGLEFANSET:element=>{const obj={definition:x3dTypes_TRIANGLEFANSET,ccw:!0,fanCount:[],colorPerVertex:!0};return element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.fanCount&&(obj.fanCount=element.fanCount.trim().split(/ +/).map((v=>parseFloat(v)))),obj.objects=[],obj},TRIANGLESTRIPSET:element=>{const obj={definition:x3dTypes_TRIANGLESTRIPSET,ccw:!0,stripCount:[],colorPerVertex:!0};return element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.stripCount&&(obj.stripCount=element.stripCount.trim().split(/ +/).map((v=>parseFloat(v)))),obj.objects=[],obj},QUADSET:element=>{const obj={definition:x3dTypes_QUADSET,ccw:!0,colorPerVertex:!0};return element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),obj.objects=[],obj},INDEXEDTRIANGLESET:element=>{const obj={definition:x3dTypes_INDEXEDTRIANGLESET,ccw:!0,index:[],colorPerVertex:!0};return element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.index&&(obj.index=element.index.trim().split(/ +/).map((v=>parseFloat(v)))),obj.objects=[],obj},INDEXEDTRIANGLEFANSET:element=>{const obj={definition:x3dTypes_INDEXEDTRIANGLEFANSET,ccw:!0,fans:[],colorPerVertex:!0};if(element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.index){const indexes=element.index.trim().split(/ -1/);obj.fans=indexes.map((index=>index.trim().split(/ +/).map((v=>parseFloat(v))))).filter((index=>index.length>2))}return obj.objects=[],obj},INDEXEDTRIANGLESTRIPSET:element=>{const obj={definition:x3dTypes_INDEXEDTRIANGLESTRIPSET,ccw:!0,strips:[],colorPerVertex:!0,objects:[]};if(element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.index){const indexes=element.index.trim().split(/ -1/);obj.strips=indexes.map((index=>index.trim().split(/ +/).map((v=>parseFloat(v))))).filter((index=>index.length>2))}return obj},INDEXEDQUADSET:element=>{const obj={definition:x3dTypes_INDEXEDQUADSET,ccw:!0,index:[],colorPerVertex:!0};return element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.index&&(obj.index=element.index.trim().split(/ +/).map((v=>parseFloat(v)))),obj.objects=[],obj},INDEXEDFACESET:element=>{const obj={definition:x3dTypes_INDEXEDFACESET,ccw:!0,convex:!0,faces:[],colorPerVertex:!0,colorIndex:null};if(element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.convex&&(obj.convex=element.convex.includes("TRUE")||element.convex.includes("true")),element.coordIndex){const indexes=element.coordIndex.trim().split(/ -1/);obj.faces=indexes.map((index=>index.trim().split(/ +/).map((v=>parseFloat(v))))).filter((index=>index.length>2))}if(element.colorPerVertex&&(obj.colorPerVertex=element.colorPerVertex.includes("TRUE")||element.colorPerVertex.includes("true")),element.colorIndex)if(obj.colorPerVertex){const indexes=element.colorIndex.trim().split(/ -1/);obj.colorIndex=indexes.map((index=>index.trim().split(/ +/).map((v=>parseFloat(v))))).filter((index=>index.length>2))}else obj.colorIndex=element.colorIndex.trim().split(/ +/).map((v=>parseFloat(v)));else obj.colorIndex=obj.faces;return obj.objects=[],obj},ELEVATIONGRID:element=>{const obj={definition:x3dTypes_ELEVATIONGRID,xDimension:2,zDimension:2,xSpacing:1,zSpacing:1,height:[0,0,0,0],ccw:!0,solid:!1,colorPerVertex:!0};return element.xDimension&&(obj.xDimension=parseFloat(element.xDimension)),element.zDimension&&(obj.zDimension=parseFloat(element.zDimension)),element.xSpacing&&(obj.xSpacing=parseFloat(element.xSpacing)),element.zSpacing&&(obj.zSpacing=parseFloat(element.zSpacing)),element.height&&(obj.height=element.height.trim().split(/ +/).map((v=>parseFloat(v)))),element.ccw&&(obj.ccw=element.ccw.includes("TRUE")||element.ccw.includes("true")),element.solid&&(obj.solid=element.solid.includes("TRUE")||element.solid.includes("true")),element.colorPerVertex&&(obj.colorPerVertex=element.colorPerVertex.includes("TRUE")||element.colorPerVertex.includes("true")),obj.objects=[],obj},LINESET:element=>{const obj={definition:x3dTypes_LINESET,vertexCount:[],colorPerVertex:!0};return element.vertexCount&&(obj.vertexCount=element.vertexCount.trim().split(/ +/).map((v=>parseFloat(v)))),element.colorPerVertex&&(obj.colorPerVertex=element.colorPerVertex.includes("TRUE")||element.colorPerVertex.includes("true")),obj.objects=[],obj},INDEXEDLINESET:element=>{const obj={definition:x3dTypes_INDEXEDLINESET,indexes:[],colorPerVertex:!0};if(element.coordIndex){const indexes=element.coordIndex.trim().split(/ -1/);obj.indexes=indexes.map((index=>index.trim().split(/ +/).map((v=>parseFloat(v))))),obj.indexes=obj.indexes.filter((index=>index.length>1))}return element.colorPerVertex&&(obj.colorPerVertex=element.colorPerVertex.includes("TRUE")||element.colorPerVertex.includes("true")),obj.objects=[],obj},APPEARANCE:element=>{const obj={definition:x3dTypes_APPEARANCE,objects:[]};return obj},MATERIAL:element=>{const obj={definition:x3dTypes_MATERIAL,color:[.8,.8,.8,1]};let alpha=1;if(element.transparency&&(alpha=1-element.transparency),element.diffuseColor){const values=element.diffuseColor.trim().split(/ +/).map((v=>parseFloat(v)));values.length>2&&(values.length<4&&values.push(alpha),obj.color=values)}if(element.emissiveColor){const values=element.emissiveColor.trim().split(/ +/).map((v=>parseFloat(v)));values.length>2&&(values.length<4&&values.push(alpha),obj.color=values)}return obj}};let objectId=1;const createX3DParser=src=>{const parser=new SaxesParser_1;parser.on("error",(e=>{console.log(`error: line ${e.line}, column ${e.column}, bad character [${e.c}]`)})),parser.on("opentag",(node=>{const elementname=node.name.toUpperCase();let obj=nodeToObjectMap[elementname]?nodeToObjectMap[elementname](node.attributes,{x3dObjects:x3dObjects}):null;if(obj){if(obj.id=("0000"+objectId++).slice(-4),node.attributes.USE){const objectname=node.attributes.USE;if(x3dDefs.has(objectname)){const def=x3dDefs.get(objectname);def.definition!==obj.definition&&console.log(`WARNING: using a definition "${objectname}" of a different type; ${obj.definition} vs ${def.definition}`),obj=def}else console.log(`WARNING: definition "${objectname}" does not exist, using default for ${obj.definition}`)}else if(node.attributes.DEF){const objectname=node.attributes.DEF;x3dDefs.has(objectname)?console.log(`WARNING: redefintion of ${objectname} has been ignored`):x3dDefs.set(objectname,obj)}switch(obj.definition){case x3dTypes_SCENE:case x3dTypes_TRANSFORM:case x3dTypes_SHAPE:case x3dTypes_APPEARANCE:case x3dTypes_TRIANGLESET:case x3dTypes_TRIANGLEFANSET:case x3dTypes_TRIANGLESTRIPSET:case x3dTypes_QUADSET:case x3dTypes_INDEXEDTRIANGLESET:case x3dTypes_INDEXEDTRIANGLEFANSET:case x3dTypes_INDEXEDTRIANGLESTRIPSET:case x3dTypes_INDEXEDQUADSET:case x3dTypes_INDEXEDFACESET:case x3dTypes_ELEVATIONGRID:case x3dTypes_LINESET:case x3dTypes_INDEXEDLINESET:case x3dTypes_GROUP:x3dDefinition=obj.definition}switch(x3dDefinition){case x3dTypes_X3D:"objects"in obj&&x3dObjects.push(obj),obj.definition===x3dTypes_UNIT&&("length"===obj.category&&(x3dLength.factor=obj.conversionFactor,x3dLength.name=obj.name),"angle"===obj.category&&(x3dAngle.factor=obj.conversionFactor,x3dAngle.name=obj.name));break;case x3dTypes_SCENE:case x3dTypes_TRANSFORM:case x3dTypes_SHAPE:case x3dTypes_GROUP:case x3dTypes_APPEARANCE:case x3dTypes_TRIANGLESET:case x3dTypes_TRIANGLEFANSET:case x3dTypes_TRIANGLESTRIPSET:case x3dTypes_QUADSET:case x3dTypes_INDEXEDTRIANGLESET:case x3dTypes_INDEXEDTRIANGLEFANSET:case x3dTypes_INDEXEDTRIANGLESTRIPSET:case x3dTypes_INDEXEDQUADSET:case x3dTypes_INDEXEDFACESET:case x3dTypes_ELEVATIONGRID:case x3dTypes_LINESET:case x3dTypes_INDEXEDLINESET:if(x3dObjects.length>0){const group=x3dObjects.pop();"objects"in group&&group.objects.push(obj),x3dObjects.push(group),"objects"in obj&&x3dObjects.push(obj)}break;default:console.log("WARNING: invalid X3D definition")}x3dLast=obj}})),parser.on("closetag",(node=>{switch(node.name.toUpperCase()){case"X3D":case"SCENE":case"TRANSFORM":case"SHAPE":case"GROUP":case"STATICGROUP":case"APPEARANCE":case"TRIANGLESET":case"TRIANGLEFANSET":case"TRIANGLESTRIPSET":case"QUADSET":case"INDEXEDTRIANGLESET":case"INDEXEDTRIANGLEFANSET":case"INDEXEDTRIANGLESTRIPSET":case"INDEXEDQUADSET":case"INDEXEDFACESET":case"ELEVATIONGRID":case"LINESET":case"INDEXEDLINESET":break;default:return}const popDefinition=()=>{x3dObjects.length>0&&(x3dDefinition=x3dObjects[x3dObjects.length-1].definition)};let obj=null;switch(x3dDefinition){case x3dTypes_X3D:x3dObjects.length>0&&(obj=x3dObjects.pop(),popDefinition()),0===x3dObjects.length&&(obj.length=x3dLength,obj.angle=x3dAngle,x3dObj=obj);break;case x3dTypes_SCENE:case x3dTypes_TRANSFORM:case x3dTypes_SHAPE:case x3dTypes_GROUP:case x3dTypes_APPEARANCE:case x3dTypes_TRIANGLESET:case x3dTypes_TRIANGLEFANSET:case x3dTypes_TRIANGLESTRIPSET:case x3dTypes_QUADSET:case x3dTypes_INDEXEDTRIANGLESET:case x3dTypes_INDEXEDTRIANGLEFANSET:case x3dTypes_INDEXEDTRIANGLESTRIPSET:case x3dTypes_INDEXEDQUADSET:case x3dTypes_INDEXEDFACESET:case x3dTypes_ELEVATIONGRID:case x3dTypes_LINESET:case x3dTypes_INDEXEDLINESET:x3dObjects.length>0&&(obj=x3dObjects.pop(),popDefinition());break;default:console.log("WARNING: unhandled definition",x3dDefinition)}})),parser.on("text",(value=>{null!==value&&(value=value.trim()).length>0&&x3dLast&&0!==x3dDefinition&&(x3dLast.value=value)})),parser.on("end",(()=>{})),parser.write(src).close()},parse=src=>(createX3DParser(src),{x3dObj:x3dObj,x3dMaterials:x3dMaterials,x3dTextures:x3dTextures}),codify=(x3d,data)=>{if(x3d.definition!==x3dTypes_X3D||!x3d.objects)throw new Error("X3D malformed");if(x3d.objects.length<1||x3d.objects[0].definition!==x3dTypes_SCENE)throw new Error("X3D did not define a SCENE");const objects=x3d.objects[0].objects,length=x3d.length,angle=x3d.angle;let code="";code=`// Objects : ${objects.length}\n// Units : ${length.name} (${length.factor})\n// Angles : ${angle.name} (${angle.factor})\n\nimport * from '@jscad/modeling'\n\nexport const main = () => {\n let options = {}\n let objects = []\n`;for(let i=0;i<objects.length;i++){code+=` objects.push(...createObjects${objects[i].id}(options))\n`}return code+=" return objects\n}\n",code+=translateDefinitions({},objects),code},flatten=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val)),[]),instantiatePrimitive=(options,objects)=>{let geometry,object=findNode(x3dTypes_BOX,objects);if(object)return geometry=(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)})))})({size:object.size}),geometry;if(object=findNode(x3dTypes_CONE,objects),object)return geometry=rotateX(-Math.PI/2,cylinderElliptic({startRadius:[object.bottomRadius,object.bottomRadius],height:object.height,segments:object.subdivision,endRadius:[object.topRadius,object.topRadius]})),geometry;if(object=findNode(x3dTypes_CYLINDER,objects),object)return geometry=rotateX(-Math.PI/2,(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})})({radius:object.radius,height:object.height,segments:object.subdivision})),geometry;if(object=findNode(x3dTypes_SPHERE,objects),object)return geometry=sphere({radius:object.radius,segments:object.subdivision}),geometry;if(object=findNode(x3dTypes_EXTRUSION,objects),object)return geometry=extrudeX3D(object),geometry;if(object=findNode(x3dTypes_ARC2D,objects),object)return geometry=arc({radius:object.radius,startAngle:object.startAngle,endAngle:object.endAngle,segments:object.subdivision}),geometry;if(object=findNode(x3dTypes_ARCCLOSE2D,objects),object)return geometry="PIE"===object.closureType?circle({radius:object.radius,startAngle:object.startAngle,endAngle:object.endAngle,segments:object.subdivision}):index$a.create([index$5.toPoints(index$5.close(arc({radius:object.radius,startAngle:object.startAngle,endAngle:object.endAngle,segments:object.subdivision})))]),geometry;if(object=findNode(x3dTypes_CIRCLE2D,objects),object)return geometry=arc({radius:object.radius,segments:object.subdivision}),geometry;if(object=findNode(x3dTypes_DISK2D,objects),object)return geometry=object.innerRadius===object.outerRadius?arc({radius:object.outerRadius,segments:object.subdivision}):0===object.innerRadius?circle({radius:object.outerRadius,segments:object.subdivision}):subtract(circle({radius:object.outerRadius,segments:object.subdivision}),circle({radius:object.innerRadius,segments:object.subdivision})),geometry;if(object=findNode(x3dTypes_POLYLINE2D,objects),object)return geometry=line([object.lineSegments]),geometry;if(object=findNode(x3dTypes_RECTANGLE2D,objects),object)return geometry=(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])})({size:object.size}),geometry;if(object=findNode(x3dTypes_TRIANGLESET2D,objects),object){const vertices=object.vertices,numpoints=vertices.length,numfaces=Math.trunc(numpoints/3);geometry=[];for(let i=0;i<numfaces;i+=3)geometry.push(index$a.create([[vertices[i],vertices[i+1],vertices[i+2]]]));return geometry}return geometry},instantiatedList=new Map,instantiateTransform=(options,object)=>{const geometries=object.objects.map((object=>instantiateDefinition(options,object))).filter((g=>null!=g));if(0===geometries.length)return null;const matrix=createTransform(object.center,object.rotation,object.scale,object.scaleOrientation,object.translation);return geometries.map((geometry=>{const color=geometry.color;return geometry=((matrix,...objects)=>{if(0===(objects=flatten$1(objects)).length)throw new Error("wrong number of arguments");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):object));return 1===results.length?results[0]:results})(matrix,geometry),color&&(geometry.color=color),geometry}))},instantiateShape=(options,object)=>{const objects=object.objects,color=findColor(objects);let geometry=instantiatePrimitive(0,objects);return geometry||(geometry=instantiateMesh(0,objects)),geometry||(geometry=((options,objects)=>{let geometry;const components=convertLine(0,objects);if(components){const{pointsSet:pointsSet,segColors:segColors}=components;geometry=pointsSet.map(((points,i)=>{let l;return l=segColors?colorize(segColors[i],line(points)):line(points),l}))}return geometry})(0,objects)),geometry||(geometry=null),geometry&&color&&(geometry=colorize(color,geometry)),geometry},instantiateDefinition=(options,object)=>{let geometry;switch(object.definition){case x3dTypes_TRANSFORM:geometry=instantiateTransform(options,object);break;case x3dTypes_SHAPE:geometry=instantiateShape(0,object);break;case x3dTypes_GROUP:geometry=((options,object)=>{const geometries=object.objects.map((object=>instantiateDefinition(options,object))).filter((g=>null!=g));return 0===geometries.length?null:geometries})(options,object);break;default:console.log("WARNING: unknown definition: "+object.definition)}return geometry},instantiate=(options,src)=>{(options=Object.assign({},{},options))&&options.statusCallback&&options.statusCallback({progress:0});const{x3dObj:x3dObj}=parse(src);if(x3dObj.definition!==x3dTypes_X3D||!x3dObj.objects)throw new Error("X3D malformed");if(x3dObj.objects.length<1||x3dObj.objects[0].definition!==x3dTypes_SCENE)throw new Error("X3D did not define a SCENE");options&&options.statusCallback&&options.statusCallback({progress:50});let geometries=((options,objects)=>{const geometries=objects.map((object=>instantiateDefinition(options,object))).filter((g=>null!=g));return instantiatedList.clear(),geometries})(options,x3dObj.objects[0].objects);return options.flatten&&(geometries=flatten(geometries)),options&&options.statusCallback&&options.statusCallback({progress:100}),geometries},deserialize=(options,input)=>{const defaults={filename:"x3d",output:"script",version:"3.0.0-alpha.0",flatten:!0,addMetaData:!0};return"script"===(options=Object.assign({},defaults,options)).output?((options,src)=>{options=Object.assign({},{},options);const{version:version,addMetaData:addMetaData,filename:filename}=options;options&&options.statusCallback&&options.statusCallback({progress:0});const{x3dObj:x3dObj,x3dMaterials:x3dMaterials,x3dTextures:x3dTextures}=parse(src);let code=addMetaData?`//\n// Produced by JSCAD IO Library : X3D Deserializer (${version})\n// date: ${new Date}\n// source: ${filename}\n//\n`:"";if(!x3dObj)throw new Error("X3D parsing failed, no valid X3D data retrieved");return options&&options.statusCallback&&options.statusCallback({progress:50}),code+=codify(x3dObj),options&&options.statusCallback&&options.statusCallback({progress:100}),code})(options,input):instantiate(options,input)},mimeType="model/x3d+xml";export{deserialize,mimeType};