@jscad/3mf-serializer 2.1.9 → 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.
- package/CHANGELOG.md +8 -35
- package/README.md +2 -0
- package/dist/jscad-3mf-serializer.es.js +7 -0
- package/dist/jscad-3mf-serializer.min.js +7 -0
- package/package.json +22 -11
- package/rollup.config.js +27 -0
- package/src/index.js +19 -42
- package/tests/serialize.test.js +21 -21
package/CHANGELOG.md
CHANGED
|
@@ -3,81 +3,54 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
6
|
+
# [3.0.0-alpha.0](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.6...@jscad/3mf-serializer@3.0.0-alpha.0) (2023-10-09)
|
|
9
7
|
|
|
8
|
+
### Bug Fixes
|
|
10
9
|
|
|
10
|
+
* **io:** fix io after V3 refactoring ([7a12bbd](https://github.com/jscad/OpenJSCAD.org/commit/7a12bbdb7b4b3df792a4c5b3c8b30a6a985a48f0))
|
|
11
11
|
|
|
12
|
+
### Features
|
|
12
13
|
|
|
14
|
+
* **modeling:** reworked exports to expose a flattened API ([8235238](https://github.com/jscad/OpenJSCAD.org/commit/8235238ad63d063f1e501478cae1208deb130a9c))
|
|
13
15
|
|
|
14
|
-
## [2.1.
|
|
16
|
+
## [2.1.9](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.8...@jscad/3mf-serializer@2.1.9) (2023-06-27)
|
|
15
17
|
|
|
16
18
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
17
19
|
|
|
20
|
+
## [2.1.8](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.7...@jscad/3mf-serializer@2.1.8) (2023-04-30)
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
21
23
|
|
|
22
24
|
## [2.1.7](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.6...@jscad/3mf-serializer@2.1.7) (2022-11-26)
|
|
23
25
|
|
|
24
26
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
28
|
## [2.1.6](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.5...@jscad/3mf-serializer@2.1.6) (2022-08-21)
|
|
31
29
|
|
|
32
30
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
32
|
## [2.1.5](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.4...@jscad/3mf-serializer@2.1.5) (2022-07-17)
|
|
39
33
|
|
|
40
34
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
36
|
## [2.1.4](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.3...@jscad/3mf-serializer@2.1.4) (2022-06-12)
|
|
47
37
|
|
|
48
38
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
49
39
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
40
|
## [2.1.3](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.2...@jscad/3mf-serializer@2.1.3) (2022-05-15)
|
|
55
41
|
|
|
56
42
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
57
43
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
44
|
## [2.1.2](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.1...@jscad/3mf-serializer@2.1.2) (2022-04-24)
|
|
63
45
|
|
|
64
46
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
65
47
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
48
|
## [2.1.1](https://github.com/jscad/OpenJSCAD.org/compare/@jscad/3mf-serializer@2.1.0...@jscad/3mf-serializer@2.1.1) (2022-04-03)
|
|
71
49
|
|
|
72
50
|
**Note:** Version bump only for package @jscad/3mf-serializer
|
|
73
51
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
52
|
# 2.1.0 (2022-04-03)
|
|
79
53
|
|
|
80
|
-
|
|
81
54
|
### Features
|
|
82
55
|
|
|
83
56
|
* **3mf-serializer:** new serializer from JSCAD geometry to 3MF packages ([6b51aed](https://github.com/jscad/OpenJSCAD.org/commit/6b51aed63ee40674822a04ced773564552689763))
|
package/README.md
CHANGED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3MF serializer for JSCAD project
|
|
3
|
+
* @module @jscad/3mf-serializer
|
|
4
|
+
* @version 3.0.0-alpha.0
|
|
5
|
+
* @license MIT
|
|
6
|
+
*/
|
|
7
|
+
var u8=Uint8Array,u16=Uint16Array,u32=Uint32Array,fleb=new u8([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),fdeb=new u8([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),clim=new u8([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),freb=function(eb,start){for(var b=new u16(31),i=0;i<31;++i)b[i]=start+=1<<eb[i-1];var r=new u32(b[30]);for(i=1;i<30;++i)for(var j=b[i];j<b[i+1];++j)r[j]=j-b[i]<<5|i;return[b,r]},_a=freb(fleb,2),fl=_a[0],revfl=_a[1];fl[28]=258,revfl[258]=28;for(var revfd=freb(fdeb,0)[1],rev=new u16(32768),i=0;i<32768;++i){var x=(43690&i)>>>1|(21845&i)<<1;x=(61680&(x=(52428&x)>>>2|(13107&x)<<2))>>>4|(3855&x)<<4,rev[i]=((65280&x)>>>8|(255&x)<<8)>>>1}var hMap=function(cd,mb,r){for(var s=cd.length,i=0,l=new u16(mb);i<s;++i)cd[i]&&++l[cd[i]-1];var co,le=new u16(mb);for(i=0;i<mb;++i)le[i]=le[i-1]+l[i-1]<<1;if(r){co=new u16(1<<mb);var rvb=15-mb;for(i=0;i<s;++i)if(cd[i])for(var sv=i<<4|cd[i],r_1=mb-cd[i],v=le[cd[i]-1]++<<r_1,m=v|(1<<r_1)-1;v<=m;++v)co[rev[v]>>>rvb]=sv}else for(co=new u16(s),i=0;i<s;++i)cd[i]&&(co[i]=rev[le[cd[i]-1]++]>>>15-cd[i]);return co},flt=new u8(288);for(i=0;i<144;++i)flt[i]=8;for(i=144;i<256;++i)flt[i]=9;for(i=256;i<280;++i)flt[i]=7;for(i=280;i<288;++i)flt[i]=8;var fdt=new u8(32);for(i=0;i<32;++i)fdt[i]=5;var flm=hMap(flt,9,0),fdm=hMap(fdt,5,0),shft=function(p){return(p+7)/8|0},slc=function(v,s,e){(null==s||s<0)&&(s=0),(null==e||e>v.length)&&(e=v.length);var n=new(2==v.BYTES_PER_ELEMENT?u16:4==v.BYTES_PER_ELEMENT?u32:u8)(e-s);return n.set(v.subarray(s,e)),n},ec=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],err=function(ind,msg,nt){var e=new Error(msg||ec[ind]);if(e.code=ind,Error.captureStackTrace&&Error.captureStackTrace(e,err),!nt)throw e;return e},wbits=function(d,p,v){v<<=7&p;var o=p/8|0;d[o]|=v,d[o+1]|=v>>>8},wbits16=function(d,p,v){v<<=7&p;var o=p/8|0;d[o]|=v,d[o+1]|=v>>>8,d[o+2]|=v>>>16},hTree=function(d,mb){for(var t=[],i=0;i<d.length;++i)d[i]&&t.push({s:i,f:d[i]});var s=t.length,t2=t.slice();if(!s)return[et,0];if(1==s){var v=new u8(t[0].s+1);return v[t[0].s]=1,[v,1]}t.sort((function(a,b){return a.f-b.f})),t.push({s:-1,f:25001});var l=t[0],r=t[1],i0=0,i1=1,i2=2;for(t[0]={s:-1,f:l.f+r.f,l:l,r:r};i1!=s-1;)l=t[t[i0].f<t[i2].f?i0++:i2++],r=t[i0!=i1&&t[i0].f<t[i2].f?i0++:i2++],t[i1++]={s:-1,f:l.f+r.f,l:l,r:r};var maxSym=t2[0].s;for(i=1;i<s;++i)t2[i].s>maxSym&&(maxSym=t2[i].s);var tr=new u16(maxSym+1),mbt=ln(t[i1-1],tr,0);if(mbt>mb){i=0;var dt=0,lft=mbt-mb,cst=1<<lft;for(t2.sort((function(a,b){return tr[b.s]-tr[a.s]||a.f-b.f}));i<s;++i){var i2_1=t2[i].s;if(!(tr[i2_1]>mb))break;dt+=cst-(1<<mbt-tr[i2_1]),tr[i2_1]=mb}for(dt>>>=lft;dt>0;){var i2_2=t2[i].s;tr[i2_2]<mb?dt-=1<<mb-tr[i2_2]++-1:++i}for(;i>=0&&dt;--i){var i2_3=t2[i].s;tr[i2_3]==mb&&(--tr[i2_3],++dt)}mbt=mb}return[new u8(tr),mbt]},ln=function(n,l,d){return-1==n.s?Math.max(ln(n.l,l,d+1),ln(n.r,l,d+1)):l[n.s]=d},lc=function(c){for(var s=c.length;s&&!c[--s];);for(var cl=new u16(++s),cli=0,cln=c[0],cls=1,w=function(v){cl[cli++]=v},i=1;i<=s;++i)if(c[i]==cln&&i!=s)++cls;else{if(!cln&&cls>2){for(;cls>138;cls-=138)w(32754);cls>2&&(w(cls>10?cls-11<<5|28690:cls-3<<5|12305),cls=0)}else if(cls>3){for(w(cln),--cls;cls>6;cls-=6)w(8304);cls>2&&(w(cls-3<<5|8208),cls=0)}for(;cls--;)w(cln);cls=1,cln=c[i]}return[cl.subarray(0,cli),s]},clen=function(cf,cl){for(var l=0,i=0;i<cl.length;++i)l+=cf[i]*cl[i];return l},wfblk=function(out,pos,dat){var s=dat.length,o=shft(pos+2);out[o]=255&s,out[o+1]=s>>>8,out[o+2]=255^out[o],out[o+3]=255^out[o+1];for(var i=0;i<s;++i)out[o+i+4]=dat[i];return 8*(o+4+s)},wblk=function(dat,out,final,syms,lf,df,eb,li,bs,bl,p){wbits(out,p++,final),++lf[256];for(var _a=hTree(lf,15),dlt=_a[0],mlb=_a[1],_b=hTree(df,15),ddt=_b[0],mdb=_b[1],_c=lc(dlt),lclt=_c[0],nlc=_c[1],_d=lc(ddt),lcdt=_d[0],ndc=_d[1],lcfreq=new u16(19),i=0;i<lclt.length;++i)lcfreq[31&lclt[i]]++;for(i=0;i<lcdt.length;++i)lcfreq[31&lcdt[i]]++;for(var _e=hTree(lcfreq,7),lct=_e[0],mlcb=_e[1],nlcc=19;nlcc>4&&!lct[clim[nlcc-1]];--nlcc);var lm,ll,dm,dl,flen=bl+5<<3,ftlen=clen(lf,flt)+clen(df,fdt)+eb,dtlen=clen(lf,dlt)+clen(df,ddt)+eb+14+3*nlcc+clen(lcfreq,lct)+(2*lcfreq[16]+3*lcfreq[17]+7*lcfreq[18]);if(flen<=ftlen&&flen<=dtlen)return wfblk(out,p,dat.subarray(bs,bs+bl));if(wbits(out,p,1+(dtlen<ftlen)),p+=2,dtlen<ftlen){lm=hMap(dlt,mlb,0),ll=dlt,dm=hMap(ddt,mdb,0),dl=ddt;var llm=hMap(lct,mlcb,0);wbits(out,p,nlc-257),wbits(out,p+5,ndc-1),wbits(out,p+10,nlcc-4),p+=14;for(i=0;i<nlcc;++i)wbits(out,p+3*i,lct[clim[i]]);p+=3*nlcc;for(var lcts=[lclt,lcdt],it=0;it<2;++it){var clct=lcts[it];for(i=0;i<clct.length;++i){var len=31&clct[i];wbits(out,p,llm[len]),p+=lct[len],len>15&&(wbits(out,p,clct[i]>>>5&127),p+=clct[i]>>>12)}}}else lm=flm,ll=flt,dm=fdm,dl=fdt;for(i=0;i<li;++i)if(syms[i]>255){len=syms[i]>>>18&31;wbits16(out,p,lm[len+257]),p+=ll[len+257],len>7&&(wbits(out,p,syms[i]>>>23&31),p+=fleb[len]);var dst=31&syms[i];wbits16(out,p,dm[dst]),p+=dl[dst],dst>3&&(wbits16(out,p,syms[i]>>>5&8191),p+=fdeb[dst])}else wbits16(out,p,lm[syms[i]]),p+=ll[syms[i]];return wbits16(out,p,lm[256]),p+ll[256]},deo=new u32([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),et=new u8(0),crct=function(){for(var t=new Int32Array(256),i=0;i<256;++i){for(var c=i,k=9;--k;)c=(1&c&&-306674912)^c>>>1;t[i]=c}return t}(),crc=function(){var c=-1;return{p:function(d){for(var cr=c,i=0;i<d.length;++i)cr=crct[255&cr^d[i]]^cr>>>8;c=cr},d:function(){return~c}}},dopt=function(dat,opt,pre,post,st){return function(dat,lvl,plvl,pre,post,lst){var s=dat.length,o=new u8(pre+s+5*(1+Math.ceil(s/7e3))+post),w=o.subarray(pre,o.length-post),pos=0;if(!lvl||s<8)for(var i=0;i<=s;i+=65535){var e=i+65535;e>=s&&(w[pos>>3]=lst),pos=wfblk(w,pos+1,dat.subarray(i,e))}else{for(var opt=deo[lvl-1],n=opt>>>13,c=8191&opt,msk_1=(1<<plvl)-1,prev=new u16(32768),head=new u16(msk_1+1),bs1_1=Math.ceil(plvl/3),bs2_1=2*bs1_1,hsh=function(i){return(dat[i]^dat[i+1]<<bs1_1^dat[i+2]<<bs2_1)&msk_1},syms=new u32(25e3),lf=new u16(288),df=new u16(32),lc_1=0,eb=0,li=(i=0,0),wi=0,bs=0;i<s;++i){var hv=hsh(i),imod=32767&i,pimod=head[hv];if(prev[imod]=pimod,head[hv]=imod,wi<=i){var rem=s-i;if((lc_1>7e3||li>24576)&&rem>423){pos=wblk(dat,w,0,syms,lf,df,eb,li,bs,i-bs,pos),li=lc_1=eb=0,bs=i;for(var j=0;j<286;++j)lf[j]=0;for(j=0;j<30;++j)df[j]=0}var l=2,d=0,ch_1=c,dif=imod-pimod&32767;if(rem>2&&hv==hsh(i-dif))for(var maxn=Math.min(n,rem)-1,maxd=Math.min(32767,i),ml=Math.min(258,rem);dif<=maxd&&--ch_1&&imod!=pimod;){if(dat[i+l]==dat[i+l-dif]){for(var nl=0;nl<ml&&dat[i+nl]==dat[i+nl-dif];++nl);if(nl>l){if(l=nl,d=dif,nl>maxn)break;var mmd=Math.min(dif,nl-2),md=0;for(j=0;j<mmd;++j){var ti=i-dif+j+32768&32767,cd=ti-prev[ti]+32768&32767;cd>md&&(md=cd,pimod=ti)}}}dif+=(imod=pimod)-(pimod=prev[imod])+32768&32767}if(d){syms[li++]=268435456|revfl[l]<<18|revfd[d];var lin=31&revfl[l],din=31&revfd[d];eb+=fleb[lin]+fdeb[din],++lf[257+lin],++df[din],wi=i+l,++lc_1}else syms[li++]=dat[i],++lf[dat[i]]}}pos=wblk(dat,w,lst,syms,lf,df,eb,li,bs,i-bs,pos),!lst&&7&pos&&(pos=wfblk(w,pos+1,et))}return slc(o,0,pre+shft(pos)+post)}(dat,null==opt.level?6:opt.level,null==opt.mem?Math.ceil(1.5*Math.max(8,Math.min(13,Math.log(dat.length)))):12+opt.mem,pre,post,!st)},mrg=function(a,b){var o={};for(var k in a)o[k]=a[k];for(var k in b)o[k]=b[k];return o},wbytes=function(d,b,v){for(;v;++b)d[b]=v,v>>>=8};function deflateSync(data,opts){return dopt(data,opts||{},0,0)}var fltn=function(d,p,t,o){for(var k in d){var val=d[k],n=p+k,op=o;Array.isArray(val)&&(op=mrg(o,val[1]),val=val[0]),val instanceof u8?t[n]=[val,op]:(t[n+="/"]=[new u8(0),op],fltn(val,n,t,o))}},te="undefined"!=typeof TextEncoder&&new TextEncoder,td="undefined"!=typeof TextDecoder&&new TextDecoder;try{td.decode(et,{stream:!0}),1}catch(e){}function strToU8(str,latin1){if(latin1){for(var ar_1=new u8(str.length),i=0;i<str.length;++i)ar_1[i]=str.charCodeAt(i);return ar_1}if(te)return te.encode(str);var l=str.length,ar=new u8(str.length+(str.length>>1)),ai=0,w=function(v){ar[ai++]=v};for(i=0;i<l;++i){if(ai+5>ar.length){var n=new u8(ai+8+(l-i<<1));n.set(ar),ar=n}var c=str.charCodeAt(i);c<128||latin1?w(c):c<2048?(w(192|c>>6),w(128|63&c)):c>55295&&c<57344?(w(240|(c=65536+(1047552&c)|1023&str.charCodeAt(++i))>>18),w(128|c>>12&63),w(128|c>>6&63),w(128|63&c)):(w(224|c>>12),w(128|c>>6&63),w(128|63&c))}return slc(ar,0,ai)}var exfl=function(ex){var le=0;if(ex)for(var k in ex){var l=ex[k].length;l>65535&&err(9),le+=l+4}return le},wzh=function(d,b,f,fn,u,c,ce,co){var fl=fn.length,ex=f.extra,col=co&&co.length,exl=exfl(ex);wbytes(d,b,null!=ce?33639248:67324752),b+=4,null!=ce&&(d[b++]=20,d[b++]=f.os),d[b]=20,b+=2,d[b++]=f.flag<<1|(null==c&&8),d[b++]=u&&8,d[b++]=255&f.compression,d[b++]=f.compression>>8;var dt=new Date(null==f.mtime?Date.now():f.mtime),y=dt.getFullYear()-1980;if((y<0||y>119)&&err(10),wbytes(d,b,y<<25|dt.getMonth()+1<<21|dt.getDate()<<16|dt.getHours()<<11|dt.getMinutes()<<5|dt.getSeconds()>>>1),b+=4,null!=c&&(wbytes(d,b,f.crc),wbytes(d,b+4,c),wbytes(d,b+8,f.size)),wbytes(d,b+12,fl),wbytes(d,b+14,exl),b+=16,null!=ce&&(wbytes(d,b,col),wbytes(d,b+6,f.attrs),wbytes(d,b+10,ce),b+=14),d.set(fn,b),b+=fl,exl)for(var k in ex){var exf=ex[k],l=exf.length;wbytes(d,b,+k),wbytes(d,b+2,l),d.set(exf,b+4),b+=4+l}return col&&(d.set(co,b),b+=col),b};function zipSync(data,opts){opts||(opts={});var r={},files=[];fltn(data,"",r,opts);var o=0,tot=0;for(var fn in r){var _a=r[fn],file=_a[0],p=_a[1],compression=0==p.level?0:8,s=(f=strToU8(fn)).length,com=p.comment,m=com&&strToU8(com),ms=m&&m.length,exl=exfl(p.extra);s>65535&&err(11);var d=compression?deflateSync(file,p):file,l=d.length,c=crc();c.p(file),files.push(mrg(p,{size:file.length,crc:c.d(),c:d,f:f,m:m,u:s!=fn.length||m&&com.length!=ms,o:o,compression:compression})),o+=30+s+exl+l,tot+=76+2*(s+exl)+(ms||0)+l}for(var out=new u8(tot+22),oe=o,cdl=tot-o,i=0;i<files.length;++i){var f=files[i];wzh(out,f.o,f,f.f,f.u,f.c.length);var badd=30+f.f.length+exfl(f.extra);out.set(f.c,f.o+badd),wzh(out,o,f,f.f,f.u,f.c.length,f.o,f.m),o+=16+badd+(f.m?f.m.length:0)}return function(o,b,c,d,e){wbytes(o,b,101010256),wbytes(o,b+8,c),wbytes(o,b+10,c),wbytes(o,b+12,d),wbytes(o,b+16,e)}(out,o,files.length,cdl,oe),out}const stringify=(a,indentation)=>{const cr=indentation>0?"\n":"",indent=(indentation=>{if(!(indentation>0))return txt=>txt;const space=" ".repeat(indentation);return txt=>{if("string"!=typeof txt)return txt;const arr=txt.split("\n");return 1===arr.length?space+txt:arr.map((e=>""===e.trim()?e:space+e)).join("\n")}})(indentation),rec=a=>{let res,body="",isFlat=!0;const isEmpty=a.some(((e,i,arr)=>{if(0===i)return res="<"+e,1===arr.length;if(1===i){if((o=e)&&"[object Object]"===Object.prototype.toString.call(o))return Object.keys(e).forEach((key=>{let val=e[key];Array.isArray(val)&&(val=val.join(" ")),res+=" "+key+'="'+val+'"'})),2===arr.length||(res+=">",!1);res+=">"}var o;switch(typeof e){case"string":case"number":case"boolean":case"undefined":return body+=e+cr,!1}return isFlat=!1,body+=rec(e),!1}));return isEmpty?res+"/>"+cr:isFlat?res+body.split("\n").filter((e=>""!==e.trim())).join("\n")+"</"+a[0]+">"+cr:res+cr+indent(body)+"</"+a[0]+">"+cr};return rec(a)},flatten$1=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten$1(val)):acc.concat(val)),[]),clone$a=matrix=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},copy$5=(out,matrix)=>(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out),EPS=1e-5,TAU=2*Math.PI,rezero=n=>Math.abs(n)<1e-13?0:n,sin=radians=>rezero(Math.sin(radians)),cos=radians=>rezero(Math.cos(radians)),identity=out=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromRotation=(out,rad,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return identity(out);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(rad),c=cos(rad),t=1-c;return out[0]=x*x*t+c,out[1]=y*x*t+z*s,out[2]=z*x*t-y*s,out[3]=0,out[4]=x*y*t-z*s,out[5]=y*y*t+c,out[6]=z*y*t+x*s,out[7]=0,out[8]=x*z*t+y*s,out[9]=y*z*t-x*s,out[10]=z*z*t+c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},abs$1=(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out[2]=Math.abs(vector[2]),out),add$1=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out),dot$2=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2],clone$9=vector=>{const out=[0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out},copy$4=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out),cross$1=(out,a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];return out[0]=ay*bz-az*by,out[1]=az*bx-ax*bz,out[2]=ax*by-ay*bx,out},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),snap$2=(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out[2]=Math.round(vector[2]/epsilon)*epsilon+0,out),squaredDistance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return x*x+y*y+z*z},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};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:snap$2,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};Object.freeze({__proto__:null,add:(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out[3]=a[3]+b[3],out[4]=a[4]+b[4],out[5]=a[5]+b[5],out[6]=a[6]+b[6],out[7]=a[7]+b[7],out[8]=a[8]+b[8],out[9]=a[9]+b[9],out[10]=a[10]+b[10],out[11]=a[11]+b[11],out[12]=a[12]+b[12],out[13]=a[13]+b[13],out[14]=a[14]+b[14],out[15]=a[15]+b[15],out),clone:clone$a,copy:copy$5,create:()=>[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],equals:(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15],fromRotation:fromRotation,fromScaling:(out,vector)=>(out[0]=vector[0],out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=vector[1],out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=vector[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromTaitBryanRotation:(out,yaw,pitch,roll)=>{const sy=sin(yaw),cy=cos(yaw),sp=sin(pitch),cp=cos(pitch),sr=sin(roll),cr=cos(roll);return out[0]=cp*cy,out[1]=cp*sy,out[2]=-sp,out[3]=0,out[4]=sr*sp*cy-cr*sy,out[5]=cr*cy+sr*sp*sy,out[6]=sr*cp,out[7]=0,out[8]=sr*sy+cr*sp*cy,out[9]=cr*sp*sy-sr*cy,out[10]=cr*cp,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromTranslation:(out,vector)=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=vector[0],out[13]=vector[1],out[14]=vector[2],out[15]=1,out),fromValues:(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33)=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=m00,out[1]=m01,out[2]=m02,out[3]=m03,out[4]=m10,out[5]=m11,out[6]=m12,out[7]=m13,out[8]=m20,out[9]=m21,out[10]=m22,out[11]=m23,out[12]=m30,out[13]=m31,out[14]=m32,out[15]=m33,out},fromVectorRotation:(out,source,target)=>{const sourceNormal=normalize$1([0,0,0],source),targetNormal=normalize$1([0,0,0],target),axis=cross$1([0,0,0],targetNormal,sourceNormal),cosA=dot$2(targetNormal,sourceNormal);if(-1===cosA)return fromRotation(out,Math.PI,orthogonal(axis,sourceNormal));const k=1/(1+cosA);return out[0]=axis[0]*axis[0]*k+cosA,out[1]=axis[1]*axis[0]*k-axis[2],out[2]=axis[2]*axis[0]*k+axis[1],out[3]=0,out[4]=axis[0]*axis[1]*k+axis[2],out[5]=axis[1]*axis[1]*k+cosA,out[6]=axis[2]*axis[1]*k-axis[0],out[7]=0,out[8]=axis[0]*axis[2]*k-axis[1],out[9]=axis[1]*axis[2]*k+axis[0],out[10]=axis[2]*axis[2]*k+cosA,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromXRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=c,out[6]=s,out[7]=0,out[8]=0,out[9]=-s,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromYRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=0,out[2]=-s,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=s,out[9]=0,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=s,out[2]=0,out[3]=0,out[4]=-s,out[5]=c,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},identity:identity,invert:(out,matrix)=>{const a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],a30=matrix[12],a31=matrix[13],a32=matrix[14],a33=matrix[15],b00=a00*a11-a01*a10,b01=a00*a12-a02*a10,b02=a00*a13-a03*a10,b03=a01*a12-a02*a11,b04=a01*a13-a03*a11,b05=a02*a13-a03*a12,b06=a20*a31-a21*a30,b07=a20*a32-a22*a30,b08=a20*a33-a23*a30,b09=a21*a32-a22*a31,b10=a21*a33-a23*a31,b11=a22*a33-a23*a32;let det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;return det?(det=1/det,out[0]=(a11*b11-a12*b10+a13*b09)*det,out[1]=(a02*b10-a01*b11-a03*b09)*det,out[2]=(a31*b05-a32*b04+a33*b03)*det,out[3]=(a22*b04-a21*b05-a23*b03)*det,out[4]=(a12*b08-a10*b11-a13*b07)*det,out[5]=(a00*b11-a02*b08+a03*b07)*det,out[6]=(a32*b02-a30*b05-a33*b01)*det,out[7]=(a20*b05-a22*b02+a23*b01)*det,out[8]=(a10*b10-a11*b08+a13*b06)*det,out[9]=(a01*b08-a00*b10-a03*b06)*det,out[10]=(a30*b04-a31*b02+a33*b00)*det,out[11]=(a21*b02-a20*b04-a23*b00)*det,out[12]=(a11*b07-a10*b09-a12*b06)*det,out[13]=(a00*b09-a01*b07+a02*b06)*det,out[14]=(a31*b01-a30*b03-a32*b00)*det,out[15]=(a20*b03-a21*b01+a22*b00)*det,out):null},isIdentity:isIdentity,isMirroring:isMirroring,isOnlyTransformScale:matrix=>isZero(matrix[1])&&isZero(matrix[2])&&isZero(matrix[3])&&isZero(matrix[4])&&isZero(matrix[6])&&isZero(matrix[7])&&isZero(matrix[8])&&isZero(matrix[9])&&isZero(matrix[11])&&1===matrix[15],mirrorByPlane:(out,plane)=>{const[nx,ny,nz,w]=plane;return out[0]=1-2*nx*nx,out[1]=-2*ny*nx,out[2]=-2*nz*nx,out[3]=0,out[4]=-2*nx*ny,out[5]=1-2*ny*ny,out[6]=-2*nz*ny,out[7]=0,out[8]=-2*nx*nz,out[9]=-2*ny*nz,out[10]=1-2*nz*nz,out[11]=0,out[12]=2*nx*w,out[13]=2*ny*w,out[14]=2*nz*w,out[15]=1,out},multiply:multiply$1,rotate:(out,matrix,radians,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return copy$5(out,matrix);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(radians),c=cos(radians),t=1-c,a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],b00=x*x*t+c,b01=y*x*t+z*s,b02=z*x*t-y*s,b10=x*y*t-z*s,b11=y*y*t+c,b12=z*y*t+x*s,b20=x*z*t+y*s,b21=y*z*t-x*s,b22=z*z*t+c;return out[0]=a00*b00+a10*b01+a20*b02,out[1]=a01*b00+a11*b01+a21*b02,out[2]=a02*b00+a12*b01+a22*b02,out[3]=a03*b00+a13*b01+a23*b02,out[4]=a00*b10+a10*b11+a20*b12,out[5]=a01*b10+a11*b11+a21*b12,out[6]=a02*b10+a12*b11+a22*b12,out[7]=a03*b10+a13*b11+a23*b12,out[8]=a00*b20+a10*b21+a20*b22,out[9]=a01*b20+a11*b21+a21*b22,out[10]=a02*b20+a12*b21+a22*b22,out[11]=a03*b20+a13*b21+a23*b22,matrix!==out&&(out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out},rotateX:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[4]=a10*c+a20*s,out[5]=a11*c+a21*s,out[6]=a12*c+a22*s,out[7]=a13*c+a23*s,out[8]=a20*c-a10*s,out[9]=a21*c-a11*s,out[10]=a22*c-a12*s,out[11]=a23*c-a13*s,out},rotateY:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c-a20*s,out[1]=a01*c-a21*s,out[2]=a02*c-a22*s,out[3]=a03*c-a23*s,out[8]=a00*s+a20*c,out[9]=a01*s+a21*c,out[10]=a02*s+a22*c,out[11]=a03*s+a23*c,out},rotateZ:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7];return matrix!==out&&(out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c+a10*s,out[1]=a01*c+a11*s,out[2]=a02*c+a12*s,out[3]=a03*c+a13*s,out[4]=a10*c-a00*s,out[5]=a11*c-a01*s,out[6]=a12*c-a02*s,out[7]=a13*c-a03*s,out},scale:(out,matrix,dimensions)=>{const x=dimensions[0],y=dimensions[1],z=dimensions[2];return out[0]=matrix[0]*x,out[1]=matrix[1]*x,out[2]=matrix[2]*x,out[3]=matrix[3]*x,out[4]=matrix[4]*y,out[5]=matrix[5]*y,out[6]=matrix[6]*y,out[7]=matrix[7]*y,out[8]=matrix[8]*z,out[9]=matrix[9]*z,out[10]=matrix[10]*z,out[11]=matrix[11]*z,out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},subtract:(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out[3]=a[3]-b[3],out[4]=a[4]-b[4],out[5]=a[5]-b[5],out[6]=a[6]-b[6],out[7]=a[7]-b[7],out[8]=a[8]-b[8],out[9]=a[9]-b[9],out[10]=a[10]-b[10],out[11]=a[11]-b[11],out[12]=a[12]-b[12],out[13]=a[13]-b[13],out[14]=a[14]-b[14],out[15]=a[15]-b[15],out),toString:mat=>mat.map((n=>n.toFixed(7))).toString(),translate:(out,matrix,offsets)=>{const x=offsets[0],y=offsets[1],z=offsets[2];let a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23;return matrix===out?(out[12]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12],out[13]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13],out[14]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14],out[15]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]):(a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],out[0]=a00,out[1]=a01,out[2]=a02,out[3]=a03,out[4]=a10,out[5]=a11,out[6]=a12,out[7]=a13,out[8]=a20,out[9]=a21,out[10]=a22,out[11]=a23,out[12]=a00*x+a10*y+a20*z+matrix[12],out[13]=a01*x+a11*y+a21*z+matrix[13],out[14]=a02*x+a12*y+a22*z+matrix[14],out[15]=a03*x+a13*y+a23*z+matrix[15]),out}});const create$a=(outlines=[])=>({outlines:outlines,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),add=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out),angleRadians=vector=>Math.atan2(vector[1],vector[0]),angleDegrees=vector=>57.29577951308232*angleRadians(vector),clone$8=vector=>{const out=[0,0];return out[0]=vector[0],out[1]=vector[1],out},cross=(out,a,b)=>(out[0]=0,out[1]=0,out[2]=a[0]*b[1]-a[1]*b[0],out),distance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)},dot$1=(a,b)=>a[0]*b[0]+a[1]*b[1],equals$6=(a,b)=>a[0]===b[0]&&a[1]===b[1],fromAngleRadians=(out,radians)=>(out[0]=cos(radians),out[1]=sin(radians),out),fromValues$2=(x,y)=>{const out=[0,0];return out[0]=x,out[1]=y,out},max$1=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out),min$1=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out),negate=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out),rotate$1=(out,vector,origin,radians)=>{const x=vector[0]-origin[0],y=vector[1]-origin[1],c=Math.cos(radians),s=Math.sin(radians);return out[0]=x*c-y*s+origin[0],out[1]=x*s+y*c+origin[1],out},normal=(out,vector)=>rotate$1(out,vector,[0,0],TAU/4),normalize=(out,vector)=>{const x=vector[0],y=vector[1];let len=x*x+y*y;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out},scale$1=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out),subtract$1=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out),toString$9=vector=>`[${vector[0].toFixed(7)}, ${vector[1].toFixed(7)}]`,transform$b=(out,vector,matrix)=>{const x=vector[0],y=vector[1];return out[0]=matrix[0]*x+matrix[4]*y+matrix[12],out[1]=matrix[1]*x+matrix[5]*y+matrix[13],out};Object.freeze({__proto__:null,abs:(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out),add:add,angle:angleRadians,angleDegrees:angleDegrees,angleRadians:angleRadians,clone:clone$8,copy:(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out),create:()=>[0,0],cross:cross,distance:distance,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out),dot:dot$1,equals:equals$6,fromAngleDegrees:(out,degrees)=>fromAngleRadians(out,.017453292519943295*degrees),fromAngleRadians:fromAngleRadians,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out),fromValues:fromValues$2,length:vector=>Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]),lerp:(out,a,b,t)=>{const ax=a[0],ay=a[1];return out[0]=ax+t*(b[0]-ax),out[1]=ay+t*(b[1]-ay),out},max:max$1,min:min$1,multiply:(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out),negate:negate,normal:normal,normalize:normalize,rotate:rotate$1,scale:scale$1,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out),squaredDistance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y},squaredLength:vector=>{const x=vector[0],y=vector[1];return x*x+y*y},subtract:subtract$1,toString:toString$9,transform:transform$b});const popNextSide=(startSide,nextSides)=>{if(1===nextSides.length)return nextSides.pop();const v0=[0,0],startAngle=angleDegrees(subtract$1(v0,startSide[1],startSide[0]));let bestAngle,bestIndex;nextSides.forEach(((nextSide,index)=>{let angle=angleDegrees(subtract$1(v0,nextSide[1],nextSide[0]))-startAngle;angle<-180&&(angle+=360),angle>=180&&(angle-=360),(void 0===bestIndex||angle>bestAngle)&&(bestIndex=index,bestAngle=angle)}));const nextSide=nextSides[bestIndex];return nextSides.splice(bestIndex,1),nextSide},isA$5=object=>!!(object&&"object"==typeof object&&"outlines"in object&&"transforms"in object&&Array.isArray(object.outlines)&&"length"in object.transforms),toOutlines=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.outlines=geometry.outlines.map((outline=>outline.map((point=>transform$b([0,0],point,geometry.transforms))))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).outlines,toPoints$3=geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},intersect$1=(p1,p2,p3,p4,endpointTouch=!0)=>{if(p1[0]===p2[0]&&p1[1]===p2[1]||p3[0]===p4[0]&&p3[1]===p4[1])return;const denominator=(p4[1]-p3[1])*(p2[0]-p1[0])-(p4[0]-p3[0])*(p2[1]-p1[1]);if(Math.abs(denominator)<Number.MIN_VALUE)return;const ua=((p4[0]-p3[0])*(p1[1]-p3[1])-(p4[1]-p3[1])*(p1[0]-p3[0]))/denominator,ub=((p2[0]-p1[0])*(p1[1]-p3[1])-(p2[1]-p1[1])*(p1[0]-p3[0]))/denominator;return ua<0||ua>1||ub<0||ub>1||!(endpointTouch||0!==ua&&1!==ua&&0!==ub&&1!==ub)?void 0:[p1[0]+ua*(p2[0]-p1[0]),p1[1]+ua*(p2[1]-p1[1])]};Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$a,fromSides:sides=>{const pointMap=(sides=>{const pointMap=new Map,edges=(sides=>{const unique=new Map,getUniquePoint=point=>{const key=point.toString();return unique.has(key)?unique.get(key):(unique.set(key,point),point)};return sides.map((side=>side.map(getUniquePoint)))})(sides);return edges.forEach((edge=>{pointMap.has(edge[0])?pointMap.get(edge[0]).push(edge):pointMap.set(edge[0],[edge])})),pointMap})(sides),outlines=[];for(;;){let startSide;for(const[point,edges]of pointMap){if(startSide=edges.shift(),startSide)break;pointMap.delete(point)}if(void 0===startSide)break;const connectedPoints=[],startPoint=startSide[0];for(;;){connectedPoints.push(startSide[0]);const nextPoint=startSide[1];if(nextPoint===startPoint)break;const nextPossibleSides=pointMap.get(nextPoint);if(!nextPossibleSides)throw new Error(`geometry is not closed at point ${nextPoint}`);const nextSide=popNextSide(startSide,nextPossibleSides);0===nextPossibleSides.length&&pointMap.delete(nextPoint),startSide=nextSide}connectedPoints.length>0&&connectedPoints.push(connectedPoints.shift()),outlines.push(connectedPoints)}return pointMap.clear(),create$a(outlines)},fromCompactBinary:data=>{if(0!==data[0])throw new Error("invalid compact binary data");const created=create$a();created.transforms=clone$a(data.slice(1,17));for(let i=21;i<data.length;){const length=data[i++];if(length<0||i+2*length>data.length)throw new Error("invalid compact binary data");const outline=[];for(let j=0;j<length;j++){const x=data[i+2*j],y=data[i+2*j+1];outline.push(fromValues$2(x,y))}created.outlines.push(outline),i+=2*length}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},isA:isA$5,reverse: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:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$5(object))throw new Error("invalid geom2 structure");if(object.outlines.forEach(((outline,i)=>{if(outline.length<3)throw new Error(`geom2 outline ${i} must contain at least 3 points`);for(let i=0;i<outline.length;i++){const j=(i+1)%outline.length;if(equals$6(outline[i],outline[j]))throw new Error(`geom2 outline ${i} has duplicate point ${outline[i]}`)}})),toOutlines(object).forEach(((outline,i)=>{for(let a1=0;a1<outline.length;a1++){const a2=(a1+1)%outline.length;for(let b1=0;b1<outline.length;b1++){const b2=(b1+1)%outline.length;if(a1!==b1){const int=intersect$1(outline[a1],outline[a2],outline[b1],outline[b2],!1);if(int)throw new Error(`geom2 outline ${i} self intersection at ${int}`)}}}})),!object.transforms.every(Number.isFinite))throw new Error(`geom2 invalid transforms ${object.transforms}`)}});const create$8=polygons=>(void 0===polygons&&(polygons=[]),{polygons:polygons,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),create$7=vertices=>((void 0===vertices||vertices.length<3)&&(vertices=[]),{vertices:vertices}),fromVerticesAndPlane=(vertices,plane)=>{const poly=create$7(vertices);return poly.plane=plane,poly},create$6=()=>[0,0,0,0],clone$5=vector=>{const out=[0,0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out},copy$2=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out),equals$5=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3],flip=(out,plane)=>(out[0]=-plane[0],out[1]=-plane[1],out[2]=-plane[2],out[3]=-plane[3],out),fromValues$1=(x,y,z,w)=>{const out=[0,0,0,0];return out[0]=x,out[1]=y,out[2]=z,out[3]=w,out},fromPoints$4=(out,...vertices)=>{const len=vertices.length,ba=[0,0,0],ca=[0,0,0],vertexNormal=index=>{const a=vertices[index],b=vertices[(index+1)%len],c=vertices[(index+2)%len];return subtract$3(ba,b,a),subtract$3(ca,c,a),cross$1(ba,ba,ca),normalize$1(ba,ba),ba};return out[0]=0,out[1]=0,out[2]=0,3===len?copy$4(out,vertexNormal(0)):(vertices.forEach(((v,i)=>{add$1(out,out,vertexNormal(i))})),normalize$1(out,out)),out[3]=dot$2(out,vertices[0]),out},signedDistanceToPoint=(plane,point)=>dot$2(plane,point)-plane[3],toString$7=vec=>`(${vec[0].toFixed(9)}, ${vec[1].toFixed(9)}, ${vec[2].toFixed(9)}, ${vec[3].toFixed(9)})`;Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,equals:equals$5,flip:flip,fromNormalAndPoint:(out,normal,point)=>{const u=normalize$1([0,0,0],normal),w=dot$2(point,u);return out[0]=u[0],out[1]=u[1],out[2]=u[2],out[3]=w,out},fromValues:fromValues$1,fromPoints:fromPoints$4,fromPointsRandom:(out,a,b,c)=>{let ba=subtract$3([0,0,0],b,a),ca=subtract$3([0,0,0],c,a);length$2(ba)<EPS&&(ba=orthogonal(ba,ca)),length$2(ca)<EPS&&(ca=orthogonal(ca,ba));let normal=cross$1([0,0,0],ba,ca);length$2(normal)<EPS&&(ca=orthogonal(ca,ba),normal=cross$1(normal,ba,ca)),normal=normalize$1(normal,normal);const w=dot$2(normal,a);return out[0]=normal[0],out[1]=normal[1],out[2]=normal[2],out[3]=w,out},projectionOfPoint:(plane,point)=>{const a=point[0]*plane[0]+point[1]*plane[1]+point[2]*plane[2]-plane[3],x=point[0]-a*plane[0],y=point[1]-a*plane[1],z=point[2]-a*plane[2];return fromValues$3(x,y,z)},signedDistanceToPoint:signedDistanceToPoint,toString:toString$7,transform:(out,plane,matrix)=>{const isMirror=isMirroring(matrix),r=orthogonal([0,0,0],plane),u=cross$1(r,plane,r),v=cross$1([0,0,0],plane,u);let point1=fromScalar$2([0,0,0],plane[3]);multiply$2(point1,point1,plane);let point2=add$1([0,0,0],point1,u),point3=add$1([0,0,0],point1,v);return point1=transform$c(point1,point1,matrix),point2=transform$c(point2,point2,matrix),point3=transform$c(point3,point3,matrix),fromPoints$4(out,point1,point2,point3),isMirror&&flip(out,out),out}});const invert$1=polygon=>{const vertices=polygon.vertices.slice().reverse(),inverted=create$7(vertices);return polygon.plane&&(inverted.plane=flip([0,0,0,0],polygon.plane)),inverted},isA$4=object=>!!(object&&"object"==typeof object&&"vertices"in object&&Array.isArray(object.vertices)),isConvex$1=polygon=>areVerticesConvex(polygon.vertices),areVerticesConvex=vertices=>{const numVertices=vertices.length;if(numVertices>2){const normal=fromPoints$4([0,0,0,0],...vertices);let prevPrevPos=vertices[numVertices-2],prevPos=vertices[numVertices-1];for(let i=0;i<numVertices;i++){const pos=vertices[i];if(!isConvexVertex(prevPrevPos,prevPos,pos,normal))return!1;prevPrevPos=prevPos,prevPos=pos}}return!0},isConvexVertex=(prevVertex,vertex,nextVertex,normal)=>{const crossProduct=cross$1([0,0,0],subtract$3([0,0,0],vertex,prevVertex),subtract$3([0,0,0],nextVertex,vertex));return dot$2(crossProduct,normal)>=0},plane=polygon=>(polygon.plane||(polygon.plane=fromPoints$4([0,0,0,0],...polygon.vertices)),polygon.plane),measureArea$2=polygon=>{const n=polygon.vertices.length;if(n<3)return 0;const vertices=polygon.vertices,normal=plane(polygon),ax=Math.abs(normal[0]),ay=Math.abs(normal[1]),az=Math.abs(normal[2]);if(ax+ay+az===0)return 0;let coord=3;ax>ay&&ax>az?coord=1:ay>az&&(coord=2);let area=0,h=0,i=1,j=2;switch(coord){case 1:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][1]*(vertices[j][2]-vertices[h][2]);area+=vertices[0][1]*(vertices[1][2]-vertices[n-1][2]),area/=2*normal[0];break;case 2:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][2]*(vertices[j][0]-vertices[h][0]);area+=vertices[0][2]*(vertices[1][0]-vertices[n-1][0]),area/=2*normal[1];break;default:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][0]*(vertices[j][1]-vertices[h][1]);area+=vertices[0][0]*(vertices[1][1]-vertices[n-1][1]),area/=2*normal[2]}return area};Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,dot:(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],equals:equals$5,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out[3]=scalar,out),fromValues:fromValues$1,toString:toString$7,transform:(out,vector,matrix)=>{const[x,y,z,w]=vector;return out[0]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12]*w,out[1]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13]*w,out[2]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14]*w,out[3]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]*w,out}});const cache$4=new WeakMap,toVertices$1=polygon=>polygon.vertices,toString$6=polygon=>`poly3: [${polygon.vertices.map(toString$b).join(", ")}]`,transform$7=(matrix,polygon)=>{const vertices=polygon.vertices.map((vertex=>transform$c([0,0,0],vertex,matrix)));return isMirroring(matrix)&&vertices.reverse(),create$7(vertices)},validate$4=object=>{if(!isA$4(object))throw new Error("invalid poly3 structure");if(object.vertices.length<3)throw new Error(`poly3 not enough vertices ${object.vertices.length}`);if(measureArea$2(object)<=0)throw new Error("poly3 area must be greater than zero");for(let i=0;i<object.vertices.length;i++)if(equals$7(object.vertices[i],object.vertices[(i+1)%object.vertices.length]))throw new Error(`poly3 has duplicate vertex ${object.vertices[i]}`);if(!isConvex$1(object))throw new Error("poly3 must be convex");if(object.vertices.forEach((vertex=>{if(!vertex.every(Number.isFinite))throw new Error(`poly3 invalid vertex ${vertex}`)})),object.vertices.length>3){const normal=plane(object);object.vertices.forEach((vertex=>{const dist=Math.abs(signedDistanceToPoint(normal,vertex));if(dist>1e-13)throw new Error(`poly3 must be coplanar: vertex ${vertex} distance ${dist}`)}))}};Object.freeze({__proto__:null,clone:(...params)=>{let out,poly3;return 1===params.length?(out=create$7(),poly3=params[0]):(out=params[0],poly3=params[1]),out.vertices=poly3.vertices.map((vec=>clone$9(vec))),out},create:create$7,fromVerticesAndPlane:fromVerticesAndPlane,invert:invert$1,isA:isA$4,isConvex:isConvex$1,measureArea:measureArea$2,measureBoundingBox:polygon=>{const vertices=polygon.vertices,numVertices=vertices.length,min=0===numVertices?[0,0,0]:clone$9(vertices[0]),max=clone$9(min);for(let i=1;i<numVertices;i++)min$2(min,min,vertices[i]),max$2(max,max,vertices[i]);return[min,max]},measureBoundingSphere:polygon=>{const boundingSphere=cache$4.get(polygon);if(boundingSphere)return boundingSphere;const vertices=polygon.vertices,out=[0,0,0,0];if(0===vertices.length)return out[0]=0,out[1]=0,out[2]=0,out[3]=0,out;let minx=vertices[0],miny=minx,minz=minx,maxx=minx,maxy=minx,maxz=minx;vertices.forEach((v=>{minx[0]>v[0]&&(minx=v),miny[1]>v[1]&&(miny=v),minz[2]>v[2]&&(minz=v),maxx[0]<v[0]&&(maxx=v),maxy[1]<v[1]&&(maxy=v),maxz[2]<v[2]&&(maxz=v)})),out[0]=.5*(minx[0]+maxx[0]),out[1]=.5*(miny[1]+maxy[1]),out[2]=.5*(minz[2]+maxz[2]);const x=out[0]-maxx[0],y=out[1]-maxy[1],z=out[2]-maxz[2];return out[3]=Math.sqrt(x*x+y*y+z*z),cache$4.set(polygon,out),out},measureSignedVolume:polygon=>{let signedVolume=0;const vertices=polygon.vertices,cross=[0,0,0];for(let i=0;i<vertices.length-2;i++)cross$1(cross,vertices[i+1],vertices[i+2]),signedVolume+=dot$2(vertices[0],cross);return signedVolume/=6,signedVolume},plane:plane,toVertices:toVertices$1,toString:toString$6,transform:transform$7,validate:validate$4});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);var index$6=Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$8,fromPoints:listOfLists=>{if(!Array.isArray(listOfLists))throw new Error("the given vertices must be an array");return create$8(listOfLists.map(create$7))},fromCompactBinary:data=>{if(1!==data[0])throw new Error("invalid compact binary data");const created=create$8();created.transforms=clone$a(data.slice(1,17));const numberOfVertices=data[21];let ci=22,vi=data.length-3*numberOfVertices;for(;vi<data.length;){const verticesPerPolygon=data[ci];ci++;const vertices=[];for(let i=0;i<verticesPerPolygon;i++)vertices.push(fromValues$3(data[vi],data[vi+1],data[vi+2])),vi+=3;created.polygons.push(create$7(vertices))}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},invert:geometry=>{const newPolygons=toPolygons$1(geometry).map((polygon=>invert$1(polygon)));return create$8(newPolygons)},isA:isA$3,toPoints:geometry=>toPolygons$1(geometry).map((polygon=>toVertices$1(polygon))),toPolygons:toPolygons$1,toString:geometry=>{const polygons=toPolygons$1(geometry);let result="geom3 ("+polygons.length+" polygons):\n";return polygons.forEach((polygon=>{result+=" "+toString$6(polygon)+"\n"})),result},toCompactBinary:geometry=>{const polygons=geometry.polygons,transforms=geometry.transforms,numberOfPolygons=polygons.length,numberOfVertices=polygons.reduce(((count,polygon)=>count+polygon.vertices.length),0);let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+numberOfPolygons+3*numberOfVertices);compacted[0]=1,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3],compacted[21]=numberOfVertices;let ci=22,vi=ci+numberOfPolygons;return polygons.forEach((polygon=>{const vertices=toVertices$1(polygon);compacted[ci]=vertices.length,ci++;for(let i=0;i<vertices.length;i++){const vertex=vertices[i];compacted[vi+0]=vertex[0],compacted[vi+1]=vertex[1],compacted[vi+2]=vertex[2],vi+=3}})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$3(object))throw new Error("invalid geom3 structure");if(object.polygons.forEach(validate$4),(object=>{const edgeCount=new Map;object.polygons.forEach((({vertices:vertices})=>{vertices.forEach(((v,i)=>{const edge=`${v}/${vertices[(i+1)%vertices.length]}`,count=edgeCount.has(edge)?edgeCount.get(edge):0;edgeCount.set(edge,count+1)}))}));const nonManifold=[];if(edgeCount.forEach(((count,edge)=>{const complementEdge=edge.split("/").reverse().join("/");count!==edgeCount.get(complementEdge)&&nonManifold.push(edge.replace("/"," -> "))})),nonManifold.length>0)throw new Error(`non-manifold edges ${nonManifold.length}\n${nonManifold.join("\n")}`)})(object),!object.transforms.every(Number.isFinite))throw new Error(`geom3 invalid transforms ${object.transforms}`)}});const clone$4=geometry=>Object.assign({},geometry),close=geometry=>{if(geometry.isClosed)return geometry;const cloned=clone$4(geometry);if(cloned.isClosed=!0,cloned.points.length>1){const points=cloned.points,p0=points[0];let pn=points[points.length-1];for(;distance(p0,pn)<EPS*EPS&&(points.pop(),1!==points.length);)pn=points[points.length-1]}return cloned},create$5=points=>(void 0===points&&(points=[]),{points:points,isClosed:!1,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),fromPoints$2=(options,points)=>{let{closed:closed}=Object.assign({},{closed:!1},options),created=create$5();if(created.points=points.map((point=>clone$8(point))),created.points.length>1){const p0=created.points[0],pn=created.points[created.points.length-1];distance(p0,pn)<EPS*EPS&&(closed=!0)}return!0===closed&&(created=close(created)),created},toPoints$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.points=geometry.points.map((point=>transform$b([0,0],point,geometry.transforms))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).points,concat=(...paths)=>{let isClosed=!1,newPoints=[];return paths.forEach(((path,i)=>{const tmp=toPoints$1(path).slice();if(newPoints.length>0&&tmp.length>0&&equals$6(tmp[0],newPoints[newPoints.length-1])&&tmp.shift(),tmp.length>0&&isClosed)throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`);isClosed=path.isClosed,newPoints=newPoints.concat(tmp)})),fromPoints$2({closed:isClosed},newPoints)},appendPoints=(points,geometry)=>concat(geometry,create$5(points)),isA$2=object=>!!(object&&"object"==typeof object&&"points"in object&&"transforms"in object&&"isClosed"in object&&Array.isArray(object.points)&&"length"in object.transforms);Object.freeze({__proto__:null,appendArc:(options,geometry)=>{let{endpoint:endpoint,radius:radius,xaxisRotation:xaxisRotation,clockwise:clockwise,large:large,segments:segments}=Object.assign({},{radius:[0,0],xaxisRotation:0,clockwise:!1,large:!1,segments:16},options);if(!Array.isArray(endpoint))throw new Error("endpoint must be an array of X and Y values");if(endpoint.length<2)throw new Error("endpoint must contain X and Y values");if(endpoint=clone$8(endpoint),!Array.isArray(radius))throw new Error("radius must be an array of X and Y values");if(radius.length<2)throw new Error("radius must contain X and Y values");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given path cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the arc)");let xRadius=radius[0],yRadius=radius[1];const startpoint=points[points.length-1];xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5,endpoint=fromValues$2(Math.round(1e5*endpoint[0])/1e5,Math.round(1e5*endpoint[1])/1e5);const sweepFlag=!clockwise;let newPoints=[];if(0===xRadius||0===yRadius)newPoints.push(endpoint);else{xRadius=Math.abs(xRadius),yRadius=Math.abs(yRadius);const phi=xaxisRotation,cosPhi=Math.cos(phi),sinPhi=Math.sin(phi),minusHalfDistance=subtract$1([0,0],startpoint,endpoint);scale$1(minusHalfDistance,minusHalfDistance,.5);const x=Math.round(1e5*(cosPhi*minusHalfDistance[0]+sinPhi*minusHalfDistance[1]))/1e5,y=Math.round(1e5*(-sinPhi*minusHalfDistance[0]+cosPhi*minusHalfDistance[1]))/1e5,startTranslated=fromValues$2(x,y),bigLambda=startTranslated[0]*startTranslated[0]/(xRadius*xRadius)+startTranslated[1]*startTranslated[1]/(yRadius*yRadius);if(bigLambda>1){const sqrtBigLambda=Math.sqrt(bigLambda);xRadius*=sqrtBigLambda,yRadius*=sqrtBigLambda,xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5}let multiplier1=Math.sqrt((xRadius*xRadius*yRadius*yRadius-xRadius*xRadius*startTranslated[1]*startTranslated[1]-yRadius*yRadius*startTranslated[0]*startTranslated[0])/(xRadius*xRadius*startTranslated[1]*startTranslated[1]+yRadius*yRadius*startTranslated[0]*startTranslated[0]));sweepFlag===large&&(multiplier1=-multiplier1);const centerTranslated=fromValues$2(xRadius*startTranslated[1]/yRadius,-yRadius*startTranslated[0]/xRadius);scale$1(centerTranslated,centerTranslated,multiplier1);let center=fromValues$2(cosPhi*centerTranslated[0]-sinPhi*centerTranslated[1],sinPhi*centerTranslated[0]+cosPhi*centerTranslated[1]);center=add(center,center,scale$1([0,0],add([0,0],startpoint,endpoint),.5));const vector1=fromValues$2((startTranslated[0]-centerTranslated[0])/xRadius,(startTranslated[1]-centerTranslated[1])/yRadius),vector2=fromValues$2((-startTranslated[0]-centerTranslated[0])/xRadius,(-startTranslated[1]-centerTranslated[1])/yRadius),theta1=angleRadians(vector1);let deltatheta=angleRadians(vector2)-theta1;deltatheta%=TAU,!sweepFlag&&deltatheta>0?deltatheta-=TAU:sweepFlag&&deltatheta<0&&(deltatheta+=TAU);let numSteps=Math.ceil(Math.abs(deltatheta)/TAU*segments)+1;numSteps<1&&(numSteps=1);for(let step=1;step<numSteps;step++){const theta=theta1+step/numSteps*deltatheta,cosTheta=Math.cos(theta),sinTheta=Math.sin(theta),point=fromValues$2(cosPhi*xRadius*cosTheta-sinPhi*yRadius*sinTheta,sinPhi*xRadius*cosTheta+cosPhi*yRadius*sinTheta);add(point,point,center),newPoints.push(point)}numSteps&&newPoints.push(options.endpoint)}return newPoints=points.concat(newPoints),fromPoints$2({},newPoints)},appendBezier:(options,geometry)=>{let{controlPoints:controlPoints,segments:segments}=Object.assign({},{segments:16},options);if(!Array.isArray(controlPoints))throw new Error("controlPoints must be an array of one or more points");if(controlPoints.length<1)throw new Error("controlPoints must be an array of one or more points");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given geometry cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the bezier curve)");if(controlPoints=controlPoints.slice(),null===controlPoints[0]){if(controlPoints.length<2)throw new Error("a null control point must be passed with one more control points");let lastBezierControlPoint=points[points.length-2];if("lastBezierControlPoint"in geometry&&(lastBezierControlPoint=geometry.lastBezierControlPoint),!Array.isArray(lastBezierControlPoint))throw new Error("the given path must contain TWO or more points if given a null control point");const controlPoint=scale$1([0,0],points[points.length-1],2);subtract$1(controlPoint,controlPoint,lastBezierControlPoint),controlPoints[0]=controlPoint}controlPoints.unshift(points[points.length-1]);const bezierOrder=controlPoints.length-1,factorials=[];let fact=1;for(let i=0;i<=bezierOrder;++i)i>0&&(fact*=i),factorials.push(fact);const binomials=[];for(let i=0;i<=bezierOrder;++i){const binomial=factorials[bezierOrder]/(factorials[i]*factorials[bezierOrder-i]);binomials.push(binomial)}const v0=[0,0],v1=[0,0],v3=[0,0,0],getPointForT=t=>{let tk=1,oneMinusTNMinusK=Math.pow(1-t,bezierOrder);const invOneMinusT=1!==t?1/(1-t):1,point=[0,0];for(let k=0;k<=bezierOrder;++k){k===bezierOrder&&(oneMinusTNMinusK=1);const bernsteinCoefficient=binomials[k]*tk*oneMinusTNMinusK,derivativePoint=scale$1(v0,controlPoints[k],bernsteinCoefficient);add(point,point,derivativePoint),tk*=t,oneMinusTNMinusK*=invOneMinusT}return point},newPoints=[],newPointsT=[],numSteps=bezierOrder+1;for(let i=0;i<numSteps;++i){const t=i/(numSteps-1),point=getPointForT(t);newPoints.push(point),newPointsT.push(t)}let subdivideBase=1;const maxAngle=TAU/segments,maxSinAngle=Math.sin(maxAngle);for(;subdivideBase<newPoints.length-1;){const dir1=subtract$1(v0,newPoints[subdivideBase],newPoints[subdivideBase-1]);normalize(dir1,dir1);const dir2=subtract$1(v1,newPoints[subdivideBase+1],newPoints[subdivideBase]);normalize(dir2,dir2);const sinAngle=cross(v3,dir1,dir2);if(Math.abs(sinAngle[2])>maxSinAngle){const t0=newPointsT[subdivideBase-1],t1=newPointsT[subdivideBase+1],newt0=t0+1*(t1-t0)/3,newt1=t0+2*(t1-t0)/3,point0=getPointForT(newt0),point1=getPointForT(newt1);newPoints.splice(subdivideBase,1,point0,point1),newPointsT.splice(subdivideBase,1,newt0,newt1),subdivideBase--,subdivideBase<1&&(subdivideBase=1)}else++subdivideBase}newPoints.shift();const result=appendPoints(newPoints,geometry);return result.lastBezierControlPoint=controlPoints[controlPoints.length-2],result},appendPoints:appendPoints,clone:clone$4,close:close,concat:concat,create:create$5,equals:(a,b)=>{if(a.isClosed!==b.isClosed)return!1;if(a.points.length!==b.points.length)return!1;const aPoints=toPoints$1(a),bPoints=toPoints$1(b),length=aPoints.length;let offset=0;do{let unequal=!1;for(let i=0;i<length;i++)if(!equals$6(aPoints[i],bPoints[(i+offset)%length])){unequal=!0;break}if(!1===unequal)return!0;if(!a.isClosed)return!1}while(++offset<length);return!1},fromPoints:fromPoints$2,fromCompactBinary:data=>{if(2!==data[0])throw new Error("invalid compact binary data");const created=create$5();created.transforms=clone$a(data.slice(1,17)),created.isClosed=!!data[17];for(let i=22;i<data.length;i+=2){const point=fromValues$2(data[i],data[i+1]);created.points.push(point)}return data[18]>=0&&(created.color=[data[18],data[19],data[20],data[21]]),created},isA:isA$2,reverse:geometry=>{const cloned=clone$4(geometry);return cloned.points=geometry.points.slice().reverse(),cloned},toPoints:toPoints$1,toString:geometry=>{const points=toPoints$1(geometry);let result="path ("+points.length+" points, "+geometry.isClosed+"):\n[\n";return points.forEach((point=>{result+=" "+toString$9(point)+",\n"})),result+="]\n",result},toCompactBinary:geometry=>{const points=geometry.points,transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+2*points.length);compacted[0]=2,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=geometry.isClosed?1:0,compacted[18]=color[0],compacted[19]=color[1],compacted[20]=color[2],compacted[21]=color[3];for(let j=0;j<points.length;j++){const ci=2*j+22,point=points[j];compacted[ci]=point[0],compacted[ci+1]=point[1]}return compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$2(object))throw new Error("invalid path2 structure");if(object.points.length>1)for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`path2 has duplicate point ${object.points[i]}`);if(object.points.forEach((point=>{if(!point.every(Number.isFinite))throw new Error(`path2 invalid point ${point}`)})),!object.transforms.every(Number.isFinite))throw new Error(`path2 invalid transforms ${object.transforms}`)}});const rgbToHex=(...values)=>{if((values=flatten$1(values)).length<3)throw new Error("values must contain R, G and B values");const r=255*values[0],g=255*values[1],b=255*values[2];let s=`#${Number(16777216+65536*r+256*g+b).toString(16).substring(1,7)}`;return values.length>3&&(s+=Number(255*values[3]).toString(16)),s},getPermutations=function(c){const permutations=[];for(let i=0;i<=c;i++)permutations.push(factorial(c)/(factorial(i)*factorial(c-i)));return permutations},factorial=function(b){let out=1;for(let i=2;i<=b;i++)out*=i;return out},valueAt=(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier valueAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierFunction(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierFunction(bezier,singleDimensionPoints,t))}return result}},bezierFunction=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<=n;i++)result+=bezier.permutations[i]*Math.pow(1-t,n-i)*Math.pow(t,i)*p[i];return result},bezierTangent=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<n;i++){const q=n*(p[i+1]-p[i]);result+=bezier.tangentPermutations[i]*Math.pow(1-t,n-1-i)*Math.pow(t,i)*q}return result},lengths=(segments,bezier)=>{let sum=0;const lengths=[0];let previous=valueAt(0,bezier);for(let index=1;index<=segments;index++){const current=valueAt(index/segments,bezier);sum+=distanceBetween(current,previous),lengths.push(sum),previous=current}return lengths},distanceBetween=(a,b)=>{if(Number.isFinite(a)&&Number.isFinite(b))return Math.abs(a-b);if(Array.isArray(a)&&Array.isArray(b)){if(a.length!==b.length)throw new Error("The operands must have the same number of dimensions.");let sum=0;for(let i=0;i<a.length;i++)sum+=(b[i]-a[i])*(b[i]-a[i]);return Math.sqrt(sum)}throw new Error("The operands must be of the same type, either number or array.")};Object.freeze({__proto__:null,create:points=>{if(!Array.isArray(points))throw new Error("Bezier points must be a valid array/");if(points.length<2)throw new Error("Bezier points must contain at least 2 values.");const pointType=function(points){let firstPointType=null;return points.forEach((point=>{let pType="";if(Number.isFinite(point))pType="float_single";else{if(!Array.isArray(point))throw new Error("Bezier points must all be numbers or arrays of number.");point.forEach((val=>{if(!Number.isFinite(val))throw new Error("Bezier point values must all be numbers.")})),pType="float_"+point.length}if(null==firstPointType)firstPointType=pType;else if(firstPointType!==pType)throw new Error("Bezier points must be either all numbers or all arrays of numbers of the same size.")})),firstPointType}(points);return{points:points,pointType:pointType,dimensions:"float_single"===pointType?0:points[0].length,permutations:getPermutations(points.length-1),tangentPermutations:getPermutations(points.length-2)}},valueAt:valueAt,tangentAt:(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier tangentAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierTangent(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierTangent(bezier,singleDimensionPoints,t))}return result}},lengths:lengths,length:(segments,bezier)=>lengths(segments,bezier)[segments],arcLengthToT:(options,bezier)=>{const{distance:distance,segments:segments}=Object.assign({},{distance:0,segments:100},options),arcLengths=lengths(segments,bezier);let startIndex=0,endIndex=segments;for(;startIndex<=endIndex;){const middleIndex=Math.floor(startIndex+(endIndex-startIndex)/2),diff=arcLengths[middleIndex]-distance;if(diff<0)startIndex=middleIndex+1;else{if(!(diff>0)){endIndex=middleIndex;break}endIndex=middleIndex-1}}const targetIndex=endIndex;if(arcLengths[targetIndex]===distance)return targetIndex/segments;const lengthBefore=arcLengths[targetIndex];return(targetIndex+(distance-lengthBefore)/(arcLengths[targetIndex+1]-lengthBefore))/segments}});const area$1=points=>{let area=0;for(let i=0;i<points.length;i++){const j=(i+1)%points.length;area+=points[i][0]*points[j][1],area-=points[j][0]*points[i][1]}return area/2},measureArea$1=polygon=>area$1(polygon.points),create$3=points=>((void 0===points||points.length<3)&&(points=[]),{points:points}),reverse$3=polygon=>{const points=polygon.points.slice().reverse();return create$3(points)},arePointsInside=(points,polygon)=>0===points.length||polygon.points.length<3?0:(measureArea$1(polygon)<0&&(polygon=reverse$3(polygon)),points.reduce(((acc,point)=>acc+isPointInside(point,polygon.points)),0)===points.length?1:0),isPointInside=(point,polygon)=>{const numPoints=polygon.length,tx=point[0],ty=point[1];let vtx0=polygon[numPoints-1],vtx1=polygon[0],yFlag0=vtx0[1]>ty,insideFlag=0,i=0;for(let j=numPoints+1;--j;){const yFlag1=vtx1[1]>ty;if(yFlag0!==yFlag1){const xFlag0=vtx0[0]>tx,xFlag1=vtx1[0]>tx;(xFlag0&&xFlag1||vtx1[0]-(vtx1[1]-ty)*(vtx0[0]-vtx1[0])/(vtx0[1]-vtx1[1])>=tx)&&(insideFlag=!insideFlag)}yFlag0=yFlag1,vtx0=vtx1,vtx1=polygon[++i]}return insideFlag},isA$1=object=>!!(object&&"object"==typeof object&&"points"in object&&Array.isArray(object.points)),crossBetweenSegments=(p1,p2,p3)=>{const X1=p2[0]-p1[0],Y1=p2[1]-p1[1],X2=p3[0]-p1[0];return X1*(p3[1]-p1[1])-Y1*X2};Object.freeze({__proto__:null,arePointsInside:arePointsInside,clone:polygon=>Object.assign({},polygon),create:create$3,isA:isA$1,isConvex:polygon=>{const numPoints=polygon.points.length;if(numPoints>2){const points=polygon.points;let prev=0,curr=0;for(let i=0;i<numPoints;i++)if(curr=crossBetweenSegments(points[i],points[(i+1)%numPoints],points[(i+2)%numPoints]),0!==curr){if(curr*prev<0)return!1;prev=curr}}return!0},isSimple:polygon=>{const numPoints=polygon.points.length;if(numPoints<3)return!1;if(3===numPoints)return!0;const points=polygon.points,found=new Set;if(points.forEach((v=>found.add(v.toString()))),found.size!==numPoints)return!1;for(let i=0;i<numPoints;i++)for(let j=i+2;j<numPoints;j++){const k=(j+1)%numPoints;if(i!==k){const s0=points[i],s1=points[(i+1)%numPoints],z0=points[j],z1=points[k];if(intersect$1(s0,s1,z0,z1))return!1}}return!0},measureArea:measureArea$1,measureBoundingBox:polygon=>{const points=polygon.points,numPoints=points.length,min=0===numPoints?[0,0]:clone$8(points[0]),max=clone$8(min);for(let i=1;i<numPoints;i++)min$1(min,min,points[i]),max$1(max,max,points[i]);return[min,max]},reverse:reverse$3,toPoints:polygon=>polygon.points,toString:polygon=>`poly2: [${polygon.points.map(toString$9).join(", ")}]`,transform:(matrix,polygon)=>{const points=polygon.points.map((point=>transform$b([0,0],point,matrix)));return isMirroring(matrix)&&points.reverse(),create$3(points)},validate:object=>{if(!isA$1(object))throw new Error("invalid poly2 structure");if(object.points.length<3)throw new Error(`poly2 not enough points ${object.points.length}`);if(measureArea$1(object)<=0)throw new Error("poly2 area must be greater than zero");for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`poly2 duplicate point at ${i}: [${object.points[i]}]`);object.points.forEach((point=>{if(2!==point.length)throw new Error(`poly2 invalid point ${point}`);if(!point.every(Number.isFinite))throw new Error(`poly2 invalid point ${point}`)}))}});const calculatePlane=slice=>{if(slice.contours.length<1)throw new Error("slices must have at least one contour to calculate a plane");const middle=[0,0,0];let n=0;slice.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(middle,middle,vertex),n++}))})),scale$3(middle,middle,1/n);let farthestBefore,farthestVertex,farthestAfter,farthestContour=[],distance=0;slice.contours.forEach((contour=>{let prev=contour[contour.length-1];contour.forEach((vertex=>{if(!equals$7(prev,vertex)){const d=squaredDistance$1(middle,vertex);d>distance&&(farthestContour=contour,farthestBefore=prev,farthestVertex=vertex,distance=d)}prev=vertex}))}));let prev=farthestContour[farthestContour.length-1];for(let i=0;i<farthestContour.length;i++){const vertex=farthestContour[i];if(!equals$7(prev,vertex)&&equals$7(prev,farthestVertex)){farthestAfter=vertex;break}prev=vertex}return fromPoints$4([0,0,0,0],farthestBefore,farthestVertex,farthestAfter)},create$2=(contours=[])=>({contours:contours}),isA=object=>!!(object&&"object"==typeof object&&"contours"in object&&Array.isArray(object.contours));class Node$2{constructor(i,x,y){this.i=i,this.x=x,this.y=y,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}}const insertNode=(i,x,y,last)=>{const p=new Node$2(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p},removeNode=p=>{p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)},pointInTriangle=(ax,ay,bx,by,cx,cy,px,py)=>(cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0,area=(p,q,r)=>(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y),linkedPolygon=(data,start,end,dim,clockwise)=>{let last;if(clockwise===signedArea$1(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);return last&&equals$2(last,last.next)&&(removeNode(last),last=last.next),last},filterPoints=(start,end)=>{if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals$2(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end},cureLocalIntersections=(start,triangles,dim)=>{let p=start;do{const a=p.prev,b=p.next.next;!equals$2(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i/dim),triangles.push(p.i/dim),triangles.push(b.i/dim),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)},locallyInside=(a,b)=>area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0,splitPolygon=(a,b)=>{const a2=new Node$2(a.i,a.x,a.y),b2=new Node$2(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2},isValidDiagonal=(a,b)=>a.next.i!==b.i&&a.prev.i!==b.i&&!((a,b)=>{let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1})(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&((a,b)=>{let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside})(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals$2(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0),intersects=(p1,q1,p2,q2)=>{const o1=Math.sign(area(p1,q1,p2)),o2=Math.sign(area(p1,q1,q2)),o3=Math.sign(area(p2,q2,p1)),o4=Math.sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||!(0!==o1||!onSegment(p1,p2,q1))||!(0!==o2||!onSegment(p1,q2,q1))||!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2))},onSegment=(p,q,r)=>q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y),signedArea$1=(data,start,end,dim)=>{let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum},equals$2=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y,eliminateHole=(hole,outerNode)=>{const bridge=findHoleBridge(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole),filteredBridge=filterPoints(bridge,bridge.next);return filterPoints(bridgeReverse,bridgeReverse.next),outerNode===bridge?filteredBridge:outerNode},findHoleBridge=(hole,outerNode)=>{let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){if(qx=x,x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next}m=p.x<p.next.x?p:p.next}}p=p.next}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&§orContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m},sectorContainsSector=(m,p)=>area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0,getLeftmost=start=>{let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost},earcutLinked=(ear,triangles,dim,minX,minY,invSize,pass)=>{if(!ear)return;!pass&&invSize&&indexCurve(ear,minX,minY,invSize);let prev,next,stop=ear;for(;ear.prev!==ear.next;)if(prev=ear.prev,next=ear.next,invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i/dim),triangles.push(ear.i/dim),triangles.push(next.i/dim),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?(ear=cureLocalIntersections(filterPoints(ear),triangles,dim),earcutLinked(ear,triangles,dim,minX,minY,invSize,2)):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}},isEar=ear=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;let p=ear.next.next;for(;p!==ear.prev;){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0},isEarHashed=(ear,minX,minY,invSize)=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y,minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0},splitEarcut=(start,triangles,dim,minX,minY,invSize)=>{let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize),void earcutLinked(c,triangles,dim,minX,minY,invSize)}b=b.next}a=a.next}while(a!==start)},indexCurve=(start,minX,minY,invSize)=>{let p=start;do{null===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,((list,fn)=>{let i,p,q,e,numMerges,inSize=1;do{p=list,list=null;let tail=null;for(numMerges=0;p;){numMerges++,q=p;let pSize=0;for(i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||fn(p)<=fn(q))?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1)})(p,(p=>p.z))},zOrder=(x,y,minX,minY,invSize)=>(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=32767*(x-minX)*invSize)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=32767*(y-minY)*invSize)|y<<8))|y<<4))|y<<2))|y<<1))<<1;class PolygonHierarchy{constructor(slice){this.plane=calculatePlane(slice);const rightVector=orthogonal([0,0,0],this.plane),perp=cross$1([0,0,0],this.plane,rightVector);this.v=normalize$1(perp,perp),this.u=cross$1([0,0,0],this.v,this.plane),this.basisMap=new Map;const projected=slice.contours.map((part=>part.map((v=>this.to2D(v))))),geometry=create$a(projected);this.roots=(geometry=>{const outlines=toOutlines(geometry),solids=[],holes=[];outlines.forEach(((outline,i)=>{const a=area$1(outline);a<0?holes.push(i):a>0&&solids.push(i)}));const children=[],parents=[];return solids.forEach(((s,i)=>{const solid=outlines[s];children[i]=[],holes.forEach(((h,j)=>{const hole=outlines[h];arePointsInside([hole[0]],create$3(solid))&&(children[i].push(h),parents[j]||(parents[j]=[]),parents[j].push(i))}))})),holes.forEach(((h,j)=>{if(parents[j]&&parents[j].length>1){const directParent=((list,score)=>{let bestIndex,best;return list.forEach(((item,index)=>{const value=score(item);(void 0===best||value<best)&&(bestIndex=index,best=value)})),bestIndex})(parents[j],(p=>children[p].length));parents[j].forEach(((p,i)=>{i!==directParent&&(children[p]=children[p].filter((c=>c!==h)))}))}})),children.map(((holes,i)=>({solid:outlines[solids[i]],holes:holes.map((h=>outlines[h]))})))})(geometry)}to2D(vector3){const vector2=fromValues$2(dot$2(vector3,this.u),dot$2(vector3,this.v));return this.basisMap.set(vector2,vector3),vector2}to3D(vector2){const original=this.basisMap.get(vector2);if(original)return original;{console.log("Warning: point not in original slice");const v1=scale$3([0,0,0],this.u,vector2[0]),v2=scale$3([0,0,0],this.v,vector2[1]),planeOrigin=scale$3([0,0,0],this.plane,this.plane[3]),v3=add$1(v1,v1,planeOrigin);return add$1(v2,v2,v3)}}}Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:(a,b)=>{if(a.contours.length!==b.contours.length)return!1;const len=a.contours.length;for(let i=0;i<len;i++){const aVertex=a.contours[i];for(let j=0;j<len;j++){const bVertex=b.contours[j];if(!equals$7(aVertex,bVertex))return!1}}return!0},fromGeom2:geometry=>{const contours=toOutlines(geometry).map((outline=>outline.map((point=>fromVec2([0,0,0],point)))));return create$2(contours)},fromVertices:vertices=>{if(!Array.isArray(vertices))throw new Error("the given vertices must be an array");if(vertices.length<3)throw new Error("the given vertices must contain THREE or more vertices");const cloned=vertices.map((vertex=>3===vertex.length?vertex:fromVec2([0,0,0],vertex)));return create$2([cloned])},isA:isA,reverse:slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},toEdges:slice=>{const edges=[];return slice.contours.forEach((contour=>{contour.forEach(((vertex,i)=>{const next=contour[(i+1)%contour.length];edges.push([vertex,next])}))})),edges},toVertices:slice=>{const vertices=[];return slice.contours.forEach((contour=>{contour.forEach((vertex=>{vertices.push(vertex)}))})),vertices},toPolygons:slice=>{const hierarchy=new PolygonHierarchy(slice),polygons=[];return hierarchy.roots.forEach((({solid:solid,holes:holes})=>{let index=solid.length;const holesIndex=[];holes.forEach(((hole,i)=>{holesIndex.push(index),index+=hole.length}));const vertices=[solid,...holes].flat(),getVertex=i=>hierarchy.to3D(vertices[i]),indices=((data,holeIndices,dim=2)=>{const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedPolygon(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,maxX,maxY,invSize;if(hasHoles&&(outerNode=((data,holeIndices,outerNode,dim)=>{const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const start=holeIndices[i]*dim,end=i<len-1?holeIndices[i+1]*dim:data.length,list=linkedPolygon(data,start,end,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(((a,b)=>a.x-b.x));for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode),outerNode=filterPoints(outerNode,outerNode.next);return outerNode})(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=maxX=data[0],minY=maxY=data[1];for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?1/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize),triangles})(vertices.flat(),holesIndex);for(let i=0;i<indices.length;i+=3){const tri=indices.slice(i,i+3).map(getVertex);polygons.push(fromVerticesAndPlane(tri,hierarchy.plane))}})),polygons},toString:slice=>{let result="slice ("+slice.contours.length+" contours):\n[\n";return slice.contours.forEach((contour=>{result+=" ["+contour.map(toString$b).join()+"],\n"})),result+="]\n",result},transform:(matrix,slice)=>{const contours=slice.contours.map((contour=>contour.map((vertex=>transform$c([0,0,0],vertex,matrix)))));return create$2(contours)},validate:object=>{if(!isA(object))throw new Error("invalid slice structure");const slicePlane=calculatePlane(object);object.contours.forEach(((contour,i)=>{if(contour.length<3)throw new Error(`slice contour ${i} must contain at least 3 vertices`);const contourPlane=plane(create$7(contour));if(!equals$5(slicePlane,contourPlane))throw new Error("slice contours must be coplanar");for(let i=0;i<contour.length;i++){if(!contour[i].every(Number.isFinite))throw new Error(`slice contour ${i} must contain finite vertices`);const j=(i+1)%contour.length;if(equals$7(contour[i],contour[j]))throw new Error(`slice contour ${i} has duplicate vertex ${contour[i]}`)}}))}});const direction$1=line=>{const vector=normal([0,0],line);return negate(vector,vector),vector},origin$1=line=>scale$1([0,0],line,line[2]),copy$1=(out,line)=>(out[0]=line[0],out[1]=line[1],out[2]=line[2],out),fromPoints$1=(out,point1,point2)=>{const vector=subtract$1([0,0],point2,point1);normal(vector,vector),normalize(vector,vector);const distance=dot$1(point1,vector);return out[0]=vector[0],out[1]=vector[1],out[2]=distance,out},fromValues=(x,y,d)=>{const out=[0,1,0];return out[0]=x,out[1]=y,out[2]=d,out},solve2Linear=(a,b,c,d,u,v)=>{const invdet=1/(a*d-b*c);let x=u*d-b*v,y=-u*c+a*v;return x*=invdet,y*=invdet,[x,y]};Object.freeze({__proto__:null,clone:line=>{const out=[0,1,0];return out[0]=line[0],out[1]=line[1],out[2]=line[2],out},closestPoint:(line,point)=>{const orig=origin$1(line),dir=direction$1(line),v=subtract$1([0,0],point,orig),dist=dot$1(v,dir);return scale$1(v,dir,dist),add(v,v,orig),v},copy:copy$1,create:()=>[0,1,0],direction:direction$1,distanceToPoint:(line,point)=>{let distance=dot$1(point,line);return distance=Math.abs(distance-line[2]),distance},equals:(line1,line2)=>line1[0]===line2[0]&&line1[1]===line2[1]&&line1[2]===line2[2],fromPoints:fromPoints$1,fromValues:fromValues,intersectPointOfLines:(line1,line2)=>{const point=solve2Linear(line1[0],line1[1],line2[0],line2[1],line1[2],line2[2]);return clone$8(point)},origin:origin$1,reverse:(out,line)=>{const normal=negate([0,0],line),distance=-line[2];return copy$1(out,fromValues(normal[0],normal[1],distance))},toString:line=>`line2: (${line[0].toFixed(7)}, ${line[1].toFixed(7)}, ${line[2].toFixed(7)})`,transform:(out,line,matrix)=>{const org=origin$1(line),dir=direction$1(line);return transform$b(org,org,matrix),transform$b(dir,dir,matrix),fromPoints$1(out,org,dir)},xAtY:(line,y)=>{let x=(line[2]-line[1]*y)/line[0];return Number.isNaN(x)&&(x=origin$1(line)[0]),x}});const create=()=>[fromValues$3(0,0,0),fromValues$3(0,0,1)],closestPoint=(line,point)=>{const lPoint=line[0],lDirection=line[1],a=dot$2(subtract$3([0,0,0],point,lPoint),lDirection),b=dot$2(lDirection,lDirection),closestPoint=scale$3([0,0,0],lDirection,a/b);return add$1(closestPoint,closestPoint,lPoint),closestPoint},fromPointAndDirection=(out,point,direction)=>{const unit=normalize$1([0,0,0],direction);return copy$4(out[0],point),copy$4(out[1],unit),out};Object.freeze({__proto__:null,clone:line=>{const out=create();return copy$4(out[0],line[0]),copy$4(out[1],line[1]),out},closestPoint:closestPoint,copy:(out,line)=>(copy$4(out[0],line[0]),copy$4(out[1],line[1]),out),create:create,direction:line=>line[1],distanceToPoint:(line,point)=>{const closest=closestPoint(line,point),distanceVector=subtract$3([0,0,0],point,closest);return length$2(distanceVector)},equals:(line1,line2)=>!!equals$7(line1[1],line2[1])&&!!equals$7(line1[0],line2[0]),fromPlanes:(out,plane1,plane2)=>{let direction=cross$1([0,0,0],plane1,plane2),length=length$2(direction);if(length<EPS)throw new Error("parallel planes do not intersect");length=1/length,direction=scale$3(direction,direction,length);const absX=Math.abs(direction[0]),absY=Math.abs(direction[1]),absZ=Math.abs(direction[2]);let origin,r;return absX>=absY&&absX>=absZ?(r=solve2Linear(plane1[1],plane1[2],plane2[1],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(0,r[0],r[1])):absY>=absX&&absY>=absZ?(r=solve2Linear(plane1[0],plane1[2],plane2[0],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(r[0],0,r[1])):(r=solve2Linear(plane1[0],plane1[1],plane2[0],plane2[1],plane1[3],plane2[3]),origin=fromValues$3(r[0],r[1],0)),fromPointAndDirection(out,origin,direction)},fromPointAndDirection:fromPointAndDirection,fromPoints:(out,point1,point2)=>{const direction=subtract$3([0,0,0],point2,point1);return fromPointAndDirection(out,point1,direction)},intersectPointOfLineAndPlane:(line,plane)=>{const pNormal=plane,pw=plane[3],lPoint=line[0],lDirection=line[1],labda=(pw-dot$2(pNormal,lPoint))/dot$2(pNormal,lDirection);return add$1([0,0,0],lPoint,scale$3([0,0,0],lDirection,labda))},origin:line=>line[0],reverse:(out,line)=>{const point=clone$9(line[0]),direction=negate$1([0,0,0],line[1]);return fromPointAndDirection(out,point,direction)},toString:line=>{const point=line[0],direction=line[1];return`line3: point: (${point[0].toFixed(7)}, ${point[1].toFixed(7)}, ${point[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`},transform:(out,line,matrix)=>{const point=line[0],direction=line[1],pointPlusDirection=add$1([0,0,0],point,direction),newPoint=transform$c([0,0,0],point,matrix),newPointPlusDirection=transform$c(pointPlusDirection,pointPlusDirection,matrix),newDirection=subtract$3(newPointPlusDirection,newPointPlusDirection,newPoint);return fromPointAndDirection(out,newPoint,newDirection)}});const 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},calculateEpsilonFromBounds=(bounds,dimensions)=>{let total=0;for(let i=0;i<dimensions;i++)total+=bounds[1][i]-bounds[0][i];return EPS*total/dimensions},createEdges=polygon=>{const vertices=toVertices$1(polygon),edges=[];for(let i=0;i<vertices.length;i++){const j=(i+1)%vertices.length,edge={v1:vertices[i],v2:vertices[j]};edges.push(edge)}for(let i=0;i<edges.length;i++){const j=(i+1)%vertices.length;edges[i].next=edges[j],edges[j].prev=edges[i]}return edges},insertEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.set(key,edge)},deleteEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.delete(key)},findOppositeEdge=(edges,edge)=>{const key=`${edge.v2}:${edge.v1}`;return edges.get(key)},calculateAnglesBetween=(current,opposite,normal)=>{let v0=current.prev.v1,v1=current.prev.v2,v2=opposite.next.v2;const angle1=calculateAngle(v0,v1,v2,normal);return v0=opposite.prev.v1,v1=opposite.prev.v2,v2=current.next.v2,[angle1,calculateAngle(v0,v1,v2,normal)]},v1=[0,0,0],v2=[0,0,0],calculateAngle=(prevVertex,midVertex,nextVertex,normal)=>{const d0=subtract$3(v1,midVertex,prevVertex),d1=subtract$3(v2,nextVertex,midVertex);return cross$1(d0,d0,d1),dot$2(d0,normal)},mergePolygons=(epsilon,polygons)=>{const polygonsPerPlane=[];polygons.forEach((polygon=>{const mapping=polygonsPerPlane.find((element=>{return plane1=element[0],plane2=plane(polygon),Math.abs(plane1[3]-plane2[3])<15e-8&&(a=plane1,b=plane2,Math.abs(a[0]-b[0])<=1e-13&&Math.abs(a[1]-b[1])<=1e-13&&Math.abs(a[2]-b[2])<=1e-13);var a,b,plane1,plane2}));mapping?mapping[1].push(polygon):polygonsPerPlane.push([plane(polygon),[polygon]])}));let destPolygons=[];return polygonsPerPlane.forEach((mapping=>{const retesselatedPolygons=(sourcePolygons=>{if(sourcePolygons.length<2)return sourcePolygons;const normal=sourcePolygons[0].plane,polygons=sourcePolygons.slice(),edgeList=new Map;for(;polygons.length>0;){const polygon=polygons.shift(),edges=createEdges(polygon);for(let i=0;i<edges.length;i++){const current=edges[i],opposite=findOppositeEdge(edgeList,current);if(opposite){const angles=calculateAnglesBetween(current,opposite,normal);if(angles[0]>=0&&angles[1]>=0){const edge1=opposite.next,edge2=current.next;current.prev.next=opposite.next,current.next.prev=opposite.prev,opposite.prev.next=current.next,opposite.next.prev=current.prev,current.v1=null,current.v2=null,current.next=null,current.prev=null,deleteEdge(edgeList,opposite),opposite.v1=null,opposite.v2=null,opposite.next=null,opposite.prev=null;const mergeEdges=(list,e1,e2)=>{const newEdge={v1:e2.v1,v2:e1.v2,next:e1.next,prev:e2.prev};e2.prev.next=newEdge,e1.next.prev=newEdge,deleteEdge(list,e1),e1.v1=null,e1.v2=null,e1.next=null,e1.prev=null,deleteEdge(list,e2),e2.v1=null,e2.v2=null,e2.next=null,e2.prev=null};0===angles[0]&&mergeEdges(edgeList,edge1,edge1.prev),0===angles[1]&&mergeEdges(edgeList,edge2,edge2.prev)}}else current.next&&insertEdge(edgeList,current)}}const destPolygons=[];return edgeList.forEach((edge=>{const polygon=(edge=>{let polygon;const vertices=[];for(;edge.next;){const next=edge.next;vertices.push(edge.v1),edge.v1=null,edge.v2=null,edge.next=null,edge.prev=null,edge=next}return vertices.length>0&&(polygon=create$7(vertices)),polygon})(edge);polygon&&destPolygons.push(polygon)})),edgeList.clear(),destPolygons})(mapping[1]);destPolygons=destPolygons.concat(retesselatedPolygons)})),destPolygons},getTag=vertex=>`${vertex}`,addSide=(sideMap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),newSideTag=`${startTag}/${endTag}`,reverseSideTag=`${endTag}/${startTag}`;if(sideMap.has(reverseSideTag))return deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,vertex1,vertex0,null),null;const newSideObj={vertex0:vertex0,vertex1:vertex1,polygonIndex:polygonIndex};return sideMap.has(newSideTag)?sideMap.get(newSideTag).push(newSideObj):sideMap.set(newSideTag,[newSideObj]),vertextag2sidestart.has(startTag)?vertextag2sidestart.get(startTag).push(newSideTag):vertextag2sidestart.set(startTag,[newSideTag]),vertextag2sideend.has(endTag)?vertextag2sideend.get(endTag).push(newSideTag):vertextag2sideend.set(endTag,[newSideTag]),newSideTag},deleteSide=(sidemap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),sideTag=`${startTag}/${endTag}`;let idx=-1;const sideObjs=sidemap.get(sideTag);for(let i=0;i<sideObjs.length;i++){const sideObj=sideObjs[i];let sideTag=getTag(sideObj.vertex0);if(sideTag===startTag&&(sideTag=getTag(sideObj.vertex1),sideTag===endTag&&(null===polygonIndex||sideObj.polygonIndex===polygonIndex))){idx=i;break}}sideObjs.splice(idx,1),0===sideObjs.length&&sidemap.delete(sideTag),idx=vertextag2sidestart.get(startTag).indexOf(sideTag),vertextag2sidestart.get(startTag).splice(idx,1),0===vertextag2sidestart.get(startTag).length&&vertextag2sidestart.delete(startTag),idx=vertextag2sideend.get(endTag).indexOf(sideTag),vertextag2sideend.get(endTag).splice(idx,1),0===vertextag2sideend.get(endTag).length&&vertextag2sideend.delete(endTag)},generalizeGeom3=(options,geometry)=>{const{snap:snap,simplify:simplify,triangulate:triangulate}=Object.assign({},{snap:!1,simplify:!1,triangulate:!1},options),epsilon=((...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>isA$2(geometry)||isA$5(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),2):isA$3(geometry)||isA(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),3):0));return 1===results.length?results[0]:results})(geometry);let polygons=toPolygons$1(geometry);snap&&(polygons=((epsilon,polygons)=>{let newPolygons=polygons.map((polygon=>{const snapVertices=polygon.vertices.map((vertex=>snap$2([0,0,0],vertex,epsilon))),newVertices=[];for(let i=0;i<snapVertices.length;i++){const j=(i+1)%snapVertices.length;equals$7(snapVertices[i],snapVertices[j])||newVertices.push(snapVertices[i])}const newPolygon=create$7(newVertices);return polygon.color&&(newPolygon.color=polygon.color),newPolygon}));const epsilonArea=epsilon*epsilon*Math.sqrt(3)/4;return newPolygons=newPolygons.filter((polygon=>((epsilon,polygon)=>{const area=Math.abs(measureArea$2(polygon));return Number.isFinite(area)&&area>epsilon})(epsilonArea,polygon))),newPolygons})(epsilon,polygons)),simplify&&(polygons=mergePolygons(0,polygons)),triangulate&&(polygons=(polygons=>{const sideMap=new Map;for(let polygonIndex=0;polygonIndex<polygons.length;polygonIndex++){const polygon=polygons[polygonIndex],numVertices=polygon.vertices.length;if(numVertices>=3){let vertex=polygon.vertices[0],vertexTag=getTag(vertex);for(let vertexIndex=0;vertexIndex<numVertices;vertexIndex++){let nextVertexIndex=vertexIndex+1;nextVertexIndex===numVertices&&(nextVertexIndex=0);const nextVertex=polygon.vertices[nextVertexIndex],nextVertexTag=getTag(nextVertex),sideTag=`${vertexTag}/${nextVertexTag}`,reverseSideTag=`${nextVertexTag}/${vertexTag}`;if(sideMap.has(reverseSideTag)){const ar=sideMap.get(reverseSideTag);ar.splice(-1,1),0===ar.length&&sideMap.delete(reverseSideTag)}else{const sideobj={vertex0:vertex,vertex1:nextVertex,polygonIndex:polygonIndex};sideMap.has(sideTag)?sideMap.get(sideTag).push(sideobj):sideMap.set(sideTag,[sideobj])}vertex=nextVertex,vertexTag=nextVertexTag}}else console.warn("warning: invalid polygon found during insertTjunctions")}if(sideMap.size>0){const vertextag2sidestart=new Map,vertextag2sideend=new Map,sidesToCheck=new Map;for(const[sidetag,sideObjs]of sideMap)sidesToCheck.set(sidetag,!0),sideObjs.forEach((sideObj=>{const starttag=getTag(sideObj.vertex0),endtag=getTag(sideObj.vertex1);vertextag2sidestart.has(starttag)?vertextag2sidestart.get(starttag).push(sidetag):vertextag2sidestart.set(starttag,[sidetag]),vertextag2sideend.has(endtag)?vertextag2sideend.get(endtag).push(sidetag):vertextag2sideend.set(endtag,[sidetag])}));const newPolygons=polygons.slice(0);for(;0!==sideMap.size;){for(const sideTag of sideMap.keys())sidesToCheck.set(sideTag,!0);let doneSomething=!1;for(;;){const sideTags=Array.from(sidesToCheck.keys());if(0===sideTags.length)break;const sideTagToCheck=sideTags[0];let doneWithSide=!0;if(sideMap.has(sideTagToCheck)){const sideObj=sideMap.get(sideTagToCheck)[0];for(let directionIndex=0;directionIndex<2;directionIndex++){const startVertex=0===directionIndex?sideObj.vertex0:sideObj.vertex1,endVertex=0===directionIndex?sideObj.vertex1:sideObj.vertex0,startVertexTag=getTag(startVertex),endVertexTag=getTag(endVertex);let matchingSides=[];0===directionIndex?vertextag2sideend.has(startVertexTag)&&(matchingSides=vertextag2sideend.get(startVertexTag)):vertextag2sidestart.has(startVertexTag)&&(matchingSides=vertextag2sidestart.get(startVertexTag));for(let matchingSideIndex=0;matchingSideIndex<matchingSides.length;matchingSideIndex++){const matchingSideTag=matchingSides[matchingSideIndex],matchingSide=sideMap.get(matchingSideTag)[0],matchingSideStartVertex=0===directionIndex?matchingSide.vertex0:matchingSide.vertex1;if(0===directionIndex?matchingSide.vertex1:matchingSide.vertex0,getTag(matchingSideStartVertex)===endVertexTag){deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,startVertex,endVertex,null),deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,startVertex,null),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}{const startPos=startVertex,endPos=endVertex,direction=subtract$3([0,0,0],matchingSideStartVertex,startPos),t=dot$2(subtract$3([0,0,0],endPos,startPos),direction)/dot$2(direction,direction);if(t>0&&t<1){const closestVertex=scale$3([0,0,0],direction,t);if(add$1(closestVertex,closestVertex,startPos),squaredDistance$1(closestVertex,endPos)<EPS*EPS){const polygonIndex=matchingSide.polygonIndex,polygon=newPolygons[polygonIndex],insertionVertexTag=getTag(matchingSide.vertex1);let insertionVertexTagIndex=-1;for(let i=0;i<polygon.vertices.length;i++)if(getTag(polygon.vertices[i])===insertionVertexTag){insertionVertexTagIndex=i;break}const newVertices=polygon.vertices.slice(0);newVertices.splice(insertionVertexTagIndex,0,endVertex);const newPolygon=create$7(newVertices);newPolygons[polygonIndex]=newPolygon,deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,matchingSide.vertex1,polygonIndex);const newSideTag1=addSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,endVertex,polygonIndex),newSideTag2=addSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,matchingSide.vertex1,polygonIndex);null!==newSideTag1&&sidesToCheck.set(newSideTag1,!0),null!==newSideTag2&&sidesToCheck.set(newSideTag2,!0),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}}}}}}doneWithSide&&sidesToCheck.delete(sideTagToCheck)}if(!doneSomething)break}polygons=newPolygons}return sideMap.clear(),polygons})(polygons),polygons=((epsilon,polygons)=>{const triangles=[];return polygons.forEach((polygon=>{((epsilon,polygon,triangles)=>{const nv=polygon.vertices.length;if(nv>3){if(nv>4){const midpoint=[0,0,0];polygon.vertices.forEach((vertex=>add$1(midpoint,midpoint,vertex))),snap$2(midpoint,divide$1(midpoint,midpoint,[nv,nv,nv]),epsilon);for(let i=0;i<nv;i++){const poly=create$7([midpoint,polygon.vertices[i],polygon.vertices[(i+1)%nv]]);polygon.color&&(poly.color=polygon.color),triangles.push(poly)}return}const poly0=create$7([polygon.vertices[0],polygon.vertices[1],polygon.vertices[2]]),poly1=create$7([polygon.vertices[0],polygon.vertices[2],polygon.vertices[3]]);return polygon.color&&(poly0.color=polygon.color,poly1.color=polygon.color),void triangles.push(poly0,poly1)}triangles.push(polygon)})(epsilon,polygon,triangles)})),triangles})(epsilon,polygons));const clone=Object.assign({},geometry);return clone.polygons=polygons,clone},flatten=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val)),[]),mimeType="model/3mf",serialize=(options,...objects)=>{options=Object.assign({},{unit:"millimeter",metadata:!0,defaultcolor:[1,160/255,0,1],compress:!0},options);const objects3d=(objects=flatten(objects)).filter((object=>index$6.isA(object)));if(0===objects3d.length)throw new Error("only 3D geometries can be serialized to 3MF");var array;objects.length!==objects3d.length&&console.warn("some objects could not be serialized to 3MF"),array=((options,...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>{if(isA$2(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$5(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$3(geometry))return generalizeGeom3(options,geometry);throw new Error("invalid geometry")}));return 1===results.length?results[0]:results})({snap:!0,triangulate:!0},objects3d),objects=Array.isArray(array)?array:null==array?[]:[array];const body=["model",{unit:options.unit,"xml:lang":"und"},["metadata",{name:"Application"},"JSCAD"]];options.metadata&&body.push(["metadata",{name:"CreationDate"},(new Date).toISOString()]),body.push(translateResources(objects,options)),body.push(translateBuild(objects));const xml=`<?xml version="1.0" encoding="UTF-8"?>\n${stringify(body,2)}`;if(options.compress){return[zipSync({"3D":{"3dmodel.model":strToU8(xml)},_rels:{".rels":strToU8(rels)},"[Content_Types].xml":strToU8(contenttype)},{comment:"created by JSCAD"}).buffer]}return[xml]},contenttype='<?xml version="1.0" encoding="UTF-8" ?>\n<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">\n <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml">\n </Default>\n <Default Extension="model" ContentType="application/vnd.ms-package.3dmanufacturing-3dmodel+xml">\n </Default>\n</Types>',rels='<?xml version="1.0" encoding="UTF-8" ?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n <Relationship Target="/3D/3dmodel.model" Id="rel0" Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel">\n </Relationship>\n</Relationships>',translateResources=(objects,options)=>{let resources=["resources",{},translateMaterials(objects,options)];return resources=resources.concat(translateObjects(objects,options)),resources},translateMaterials=(objects,options)=>{let basematerials=["basematerials",{id:"0"}];const materials=[];return objects.forEach(((object,i)=>{let srgb=rgbToHex(options.defaultcolor).toUpperCase();object.color&&(srgb=rgbToHex(object.color).toUpperCase()),materials.push(["base",{name:`mat${i}`,displaycolor:srgb}])})),basematerials=basematerials.concat(materials),basematerials},translateObjects=(objects,options)=>{const contents=[];return objects.forEach(((object,i)=>{if(index$6.isA(object)){index$6.toPolygons(object).length>0&&(options.id=i,contents.push(convertToObject(object,options)))}})),contents},translateBuild=(objects,options)=>{let build=["build",{}];const items=[];return objects.forEach(((object,i)=>{items.push(["item",{objectid:`${i+1}`}])})),build=build.concat(items),build},convertToObject=(object,options)=>{const name=object.name?object.name:`Part ${options.id}`;return["object",{id:`${options.id+1}`,type:"model",pid:"0",pindex:`${options.id}`,name:name},convertToMesh(object)]},convertToMesh=(object,options)=>["mesh",{},convertToVertices(object),convertToVolumes(object)],convertToVertices=(object,options)=>{const vertices=[];return index$6.toPolygons(object).forEach((polygon=>{for(let i=0;i<polygon.vertices.length;i++)vertices.push(convertToVertex(polygon.vertices[i]))})),["vertices",{}].concat(vertices)},convertToVertex=(vertex,options)=>["vertex",{x:vertex[0],y:vertex[1],z:vertex[2]}],convertToVolumes=(object,options)=>{let n=0;const polygons=index$6.toPolygons(object);let contents=["triangles",{}];return polygons.forEach((polygon=>{if(polygon.vertices.length<3)return;const triangles=convertToTriangles(polygon,n);contents=contents.concat(triangles),n+=polygon.vertices.length})),contents},convertToTriangles=(polygon,index)=>{const contents=[];for(let i=0;i<polygon.vertices.length-2;i++){const triangle=["triangle",{v1:index,v2:index+i+1,v3:index+i+2}];contents.push(triangle)}return contents};export{mimeType,serialize};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 3MF serializer for JSCAD project
|
|
3
|
+
* @module @jscad/3mf-serializer
|
|
4
|
+
* @version 3.0.0-alpha.0
|
|
5
|
+
* @license MIT
|
|
6
|
+
*/
|
|
7
|
+
var global,factory;global=this,factory=function(exports){var u8=Uint8Array,u16=Uint16Array,u32=Uint32Array,fleb=new u8([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),fdeb=new u8([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),clim=new u8([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),freb=function(eb,start){for(var b=new u16(31),i=0;i<31;++i)b[i]=start+=1<<eb[i-1];var r=new u32(b[30]);for(i=1;i<30;++i)for(var j=b[i];j<b[i+1];++j)r[j]=j-b[i]<<5|i;return[b,r]},_a=freb(fleb,2),fl=_a[0],revfl=_a[1];fl[28]=258,revfl[258]=28;for(var revfd=freb(fdeb,0)[1],rev=new u16(32768),i=0;i<32768;++i){var x=(43690&i)>>>1|(21845&i)<<1;x=(61680&(x=(52428&x)>>>2|(13107&x)<<2))>>>4|(3855&x)<<4,rev[i]=((65280&x)>>>8|(255&x)<<8)>>>1}var hMap=function(cd,mb,r){for(var s=cd.length,i=0,l=new u16(mb);i<s;++i)cd[i]&&++l[cd[i]-1];var co,le=new u16(mb);for(i=0;i<mb;++i)le[i]=le[i-1]+l[i-1]<<1;if(r){co=new u16(1<<mb);var rvb=15-mb;for(i=0;i<s;++i)if(cd[i])for(var sv=i<<4|cd[i],r_1=mb-cd[i],v=le[cd[i]-1]++<<r_1,m=v|(1<<r_1)-1;v<=m;++v)co[rev[v]>>>rvb]=sv}else for(co=new u16(s),i=0;i<s;++i)cd[i]&&(co[i]=rev[le[cd[i]-1]++]>>>15-cd[i]);return co},flt=new u8(288);for(i=0;i<144;++i)flt[i]=8;for(i=144;i<256;++i)flt[i]=9;for(i=256;i<280;++i)flt[i]=7;for(i=280;i<288;++i)flt[i]=8;var fdt=new u8(32);for(i=0;i<32;++i)fdt[i]=5;var flm=hMap(flt,9,0),fdm=hMap(fdt,5,0),shft=function(p){return(p+7)/8|0},slc=function(v,s,e){(null==s||s<0)&&(s=0),(null==e||e>v.length)&&(e=v.length);var n=new(2==v.BYTES_PER_ELEMENT?u16:4==v.BYTES_PER_ELEMENT?u32:u8)(e-s);return n.set(v.subarray(s,e)),n},ec=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],err=function(ind,msg,nt){var e=new Error(msg||ec[ind]);if(e.code=ind,Error.captureStackTrace&&Error.captureStackTrace(e,err),!nt)throw e;return e},wbits=function(d,p,v){v<<=7&p;var o=p/8|0;d[o]|=v,d[o+1]|=v>>>8},wbits16=function(d,p,v){v<<=7&p;var o=p/8|0;d[o]|=v,d[o+1]|=v>>>8,d[o+2]|=v>>>16},hTree=function(d,mb){for(var t=[],i=0;i<d.length;++i)d[i]&&t.push({s:i,f:d[i]});var s=t.length,t2=t.slice();if(!s)return[et,0];if(1==s){var v=new u8(t[0].s+1);return v[t[0].s]=1,[v,1]}t.sort((function(a,b){return a.f-b.f})),t.push({s:-1,f:25001});var l=t[0],r=t[1],i0=0,i1=1,i2=2;for(t[0]={s:-1,f:l.f+r.f,l:l,r:r};i1!=s-1;)l=t[t[i0].f<t[i2].f?i0++:i2++],r=t[i0!=i1&&t[i0].f<t[i2].f?i0++:i2++],t[i1++]={s:-1,f:l.f+r.f,l:l,r:r};var maxSym=t2[0].s;for(i=1;i<s;++i)t2[i].s>maxSym&&(maxSym=t2[i].s);var tr=new u16(maxSym+1),mbt=ln(t[i1-1],tr,0);if(mbt>mb){i=0;var dt=0,lft=mbt-mb,cst=1<<lft;for(t2.sort((function(a,b){return tr[b.s]-tr[a.s]||a.f-b.f}));i<s;++i){var i2_1=t2[i].s;if(!(tr[i2_1]>mb))break;dt+=cst-(1<<mbt-tr[i2_1]),tr[i2_1]=mb}for(dt>>>=lft;dt>0;){var i2_2=t2[i].s;tr[i2_2]<mb?dt-=1<<mb-tr[i2_2]++-1:++i}for(;i>=0&&dt;--i){var i2_3=t2[i].s;tr[i2_3]==mb&&(--tr[i2_3],++dt)}mbt=mb}return[new u8(tr),mbt]},ln=function(n,l,d){return-1==n.s?Math.max(ln(n.l,l,d+1),ln(n.r,l,d+1)):l[n.s]=d},lc=function(c){for(var s=c.length;s&&!c[--s];);for(var cl=new u16(++s),cli=0,cln=c[0],cls=1,w=function(v){cl[cli++]=v},i=1;i<=s;++i)if(c[i]==cln&&i!=s)++cls;else{if(!cln&&cls>2){for(;cls>138;cls-=138)w(32754);cls>2&&(w(cls>10?cls-11<<5|28690:cls-3<<5|12305),cls=0)}else if(cls>3){for(w(cln),--cls;cls>6;cls-=6)w(8304);cls>2&&(w(cls-3<<5|8208),cls=0)}for(;cls--;)w(cln);cls=1,cln=c[i]}return[cl.subarray(0,cli),s]},clen=function(cf,cl){for(var l=0,i=0;i<cl.length;++i)l+=cf[i]*cl[i];return l},wfblk=function(out,pos,dat){var s=dat.length,o=shft(pos+2);out[o]=255&s,out[o+1]=s>>>8,out[o+2]=255^out[o],out[o+3]=255^out[o+1];for(var i=0;i<s;++i)out[o+i+4]=dat[i];return 8*(o+4+s)},wblk=function(dat,out,final,syms,lf,df,eb,li,bs,bl,p){wbits(out,p++,final),++lf[256];for(var _a=hTree(lf,15),dlt=_a[0],mlb=_a[1],_b=hTree(df,15),ddt=_b[0],mdb=_b[1],_c=lc(dlt),lclt=_c[0],nlc=_c[1],_d=lc(ddt),lcdt=_d[0],ndc=_d[1],lcfreq=new u16(19),i=0;i<lclt.length;++i)lcfreq[31&lclt[i]]++;for(i=0;i<lcdt.length;++i)lcfreq[31&lcdt[i]]++;for(var _e=hTree(lcfreq,7),lct=_e[0],mlcb=_e[1],nlcc=19;nlcc>4&&!lct[clim[nlcc-1]];--nlcc);var lm,ll,dm,dl,flen=bl+5<<3,ftlen=clen(lf,flt)+clen(df,fdt)+eb,dtlen=clen(lf,dlt)+clen(df,ddt)+eb+14+3*nlcc+clen(lcfreq,lct)+(2*lcfreq[16]+3*lcfreq[17]+7*lcfreq[18]);if(flen<=ftlen&&flen<=dtlen)return wfblk(out,p,dat.subarray(bs,bs+bl));if(wbits(out,p,1+(dtlen<ftlen)),p+=2,dtlen<ftlen){lm=hMap(dlt,mlb,0),ll=dlt,dm=hMap(ddt,mdb,0),dl=ddt;var llm=hMap(lct,mlcb,0);for(wbits(out,p,nlc-257),wbits(out,p+5,ndc-1),wbits(out,p+10,nlcc-4),p+=14,i=0;i<nlcc;++i)wbits(out,p+3*i,lct[clim[i]]);p+=3*nlcc;for(var lcts=[lclt,lcdt],it=0;it<2;++it){var clct=lcts[it];for(i=0;i<clct.length;++i){var len=31&clct[i];wbits(out,p,llm[len]),p+=lct[len],len>15&&(wbits(out,p,clct[i]>>>5&127),p+=clct[i]>>>12)}}}else lm=flm,ll=flt,dm=fdm,dl=fdt;for(i=0;i<li;++i)if(syms[i]>255){len=syms[i]>>>18&31,wbits16(out,p,lm[len+257]),p+=ll[len+257],len>7&&(wbits(out,p,syms[i]>>>23&31),p+=fleb[len]);var dst=31&syms[i];wbits16(out,p,dm[dst]),p+=dl[dst],dst>3&&(wbits16(out,p,syms[i]>>>5&8191),p+=fdeb[dst])}else wbits16(out,p,lm[syms[i]]),p+=ll[syms[i]];return wbits16(out,p,lm[256]),p+ll[256]},deo=new u32([65540,131080,131088,131104,262176,1048704,1048832,2114560,2117632]),et=new u8(0),crct=function(){for(var t=new Int32Array(256),i=0;i<256;++i){for(var c=i,k=9;--k;)c=(1&c&&-306674912)^c>>>1;t[i]=c}return t}(),crc=function(){var c=-1;return{p:function(d){for(var cr=c,i=0;i<d.length;++i)cr=crct[255&cr^d[i]]^cr>>>8;c=cr},d:function(){return~c}}},dopt=function(dat,opt,pre,post,st){return function(dat,lvl,plvl,pre,post,lst){var s=dat.length,o=new u8(pre+s+5*(1+Math.ceil(s/7e3))+post),w=o.subarray(pre,o.length-post),pos=0;if(!lvl||s<8)for(var i=0;i<=s;i+=65535){var e=i+65535;e>=s&&(w[pos>>3]=lst),pos=wfblk(w,pos+1,dat.subarray(i,e))}else{for(var opt=deo[lvl-1],n=opt>>>13,c=8191&opt,msk_1=(1<<plvl)-1,prev=new u16(32768),head=new u16(msk_1+1),bs1_1=Math.ceil(plvl/3),bs2_1=2*bs1_1,hsh=function(i){return(dat[i]^dat[i+1]<<bs1_1^dat[i+2]<<bs2_1)&msk_1},syms=new u32(25e3),lf=new u16(288),df=new u16(32),lc_1=0,eb=0,li=(i=0,0),wi=0,bs=0;i<s;++i){var hv=hsh(i),imod=32767&i,pimod=head[hv];if(prev[imod]=pimod,head[hv]=imod,wi<=i){var rem=s-i;if((lc_1>7e3||li>24576)&&rem>423){pos=wblk(dat,w,0,syms,lf,df,eb,li,bs,i-bs,pos),li=lc_1=eb=0,bs=i;for(var j=0;j<286;++j)lf[j]=0;for(j=0;j<30;++j)df[j]=0}var l=2,d=0,ch_1=c,dif=imod-pimod&32767;if(rem>2&&hv==hsh(i-dif))for(var maxn=Math.min(n,rem)-1,maxd=Math.min(32767,i),ml=Math.min(258,rem);dif<=maxd&&--ch_1&&imod!=pimod;){if(dat[i+l]==dat[i+l-dif]){for(var nl=0;nl<ml&&dat[i+nl]==dat[i+nl-dif];++nl);if(nl>l){if(l=nl,d=dif,nl>maxn)break;var mmd=Math.min(dif,nl-2),md=0;for(j=0;j<mmd;++j){var ti=i-dif+j+32768&32767,cd=ti-prev[ti]+32768&32767;cd>md&&(md=cd,pimod=ti)}}}dif+=(imod=pimod)-(pimod=prev[imod])+32768&32767}if(d){syms[li++]=268435456|revfl[l]<<18|revfd[d];var lin=31&revfl[l],din=31&revfd[d];eb+=fleb[lin]+fdeb[din],++lf[257+lin],++df[din],wi=i+l,++lc_1}else syms[li++]=dat[i],++lf[dat[i]]}}pos=wblk(dat,w,lst,syms,lf,df,eb,li,bs,i-bs,pos),!lst&&7&pos&&(pos=wfblk(w,pos+1,et))}return slc(o,0,pre+shft(pos)+post)}(dat,null==opt.level?6:opt.level,null==opt.mem?Math.ceil(1.5*Math.max(8,Math.min(13,Math.log(dat.length)))):12+opt.mem,pre,post,!st)},mrg=function(a,b){var o={};for(var k in a)o[k]=a[k];for(var k in b)o[k]=b[k];return o},wbytes=function(d,b,v){for(;v;++b)d[b]=v,v>>>=8};function deflateSync(data,opts){return dopt(data,opts||{},0,0)}var fltn=function(d,p,t,o){for(var k in d){var val=d[k],n=p+k,op=o;Array.isArray(val)&&(op=mrg(o,val[1]),val=val[0]),val instanceof u8?t[n]=[val,op]:(t[n+="/"]=[new u8(0),op],fltn(val,n,t,o))}},te="undefined"!=typeof TextEncoder&&new TextEncoder,td="undefined"!=typeof TextDecoder&&new TextDecoder;try{td.decode(et,{stream:!0})}catch(e){}function strToU8(str,latin1){if(latin1){for(var ar_1=new u8(str.length),i=0;i<str.length;++i)ar_1[i]=str.charCodeAt(i);return ar_1}if(te)return te.encode(str);var l=str.length,ar=new u8(str.length+(str.length>>1)),ai=0,w=function(v){ar[ai++]=v};for(i=0;i<l;++i){if(ai+5>ar.length){var n=new u8(ai+8+(l-i<<1));n.set(ar),ar=n}var c=str.charCodeAt(i);c<128||latin1?w(c):c<2048?(w(192|c>>6),w(128|63&c)):c>55295&&c<57344?(w(240|(c=65536+(1047552&c)|1023&str.charCodeAt(++i))>>18),w(128|c>>12&63),w(128|c>>6&63),w(128|63&c)):(w(224|c>>12),w(128|c>>6&63),w(128|63&c))}return slc(ar,0,ai)}var exfl=function(ex){var le=0;if(ex)for(var k in ex){var l=ex[k].length;l>65535&&err(9),le+=l+4}return le},wzh=function(d,b,f,fn,u,c,ce,co){var fl=fn.length,ex=f.extra,col=co&&co.length,exl=exfl(ex);wbytes(d,b,null!=ce?33639248:67324752),b+=4,null!=ce&&(d[b++]=20,d[b++]=f.os),d[b]=20,b+=2,d[b++]=f.flag<<1|(null==c&&8),d[b++]=u&&8,d[b++]=255&f.compression,d[b++]=f.compression>>8;var dt=new Date(null==f.mtime?Date.now():f.mtime),y=dt.getFullYear()-1980;if((y<0||y>119)&&err(10),wbytes(d,b,y<<25|dt.getMonth()+1<<21|dt.getDate()<<16|dt.getHours()<<11|dt.getMinutes()<<5|dt.getSeconds()>>>1),b+=4,null!=c&&(wbytes(d,b,f.crc),wbytes(d,b+4,c),wbytes(d,b+8,f.size)),wbytes(d,b+12,fl),wbytes(d,b+14,exl),b+=16,null!=ce&&(wbytes(d,b,col),wbytes(d,b+6,f.attrs),wbytes(d,b+10,ce),b+=14),d.set(fn,b),b+=fl,exl)for(var k in ex){var exf=ex[k],l=exf.length;wbytes(d,b,+k),wbytes(d,b+2,l),d.set(exf,b+4),b+=4+l}return col&&(d.set(co,b),b+=col),b};function zipSync(data,opts){opts||(opts={});var r={},files=[];fltn(data,"",r,opts);var o=0,tot=0;for(var fn in r){var _a=r[fn],file=_a[0],p=_a[1],compression=0==p.level?0:8,s=(f=strToU8(fn)).length,com=p.comment,m=com&&strToU8(com),ms=m&&m.length,exl=exfl(p.extra);s>65535&&err(11);var d=compression?deflateSync(file,p):file,l=d.length,c=crc();c.p(file),files.push(mrg(p,{size:file.length,crc:c.d(),c:d,f:f,m:m,u:s!=fn.length||m&&com.length!=ms,o:o,compression:compression})),o+=30+s+exl+l,tot+=76+2*(s+exl)+(ms||0)+l}for(var out=new u8(tot+22),oe=o,cdl=tot-o,i=0;i<files.length;++i){var f=files[i];wzh(out,f.o,f,f.f,f.u,f.c.length);var badd=30+f.f.length+exfl(f.extra);out.set(f.c,f.o+badd),wzh(out,o,f,f.f,f.u,f.c.length,f.o,f.m),o+=16+badd+(f.m?f.m.length:0)}return function(o,b,c,d,e){wbytes(o,b,101010256),wbytes(o,b+8,c),wbytes(o,b+10,c),wbytes(o,b+12,d),wbytes(o,b+16,e)}(out,o,files.length,cdl,oe),out}const stringify=(a,indentation)=>{const cr=indentation>0?"\n":"",indent=(indentation=>{if(!(indentation>0))return txt=>txt;const space=" ".repeat(indentation);return txt=>{if("string"!=typeof txt)return txt;const arr=txt.split("\n");return 1===arr.length?space+txt:arr.map((e=>""===e.trim()?e:space+e)).join("\n")}})(indentation),rec=a=>{let res,body="",isFlat=!0;const isEmpty=a.some(((e,i,arr)=>{if(0===i)return res="<"+e,1===arr.length;if(1===i){if((o=e)&&"[object Object]"===Object.prototype.toString.call(o))return Object.keys(e).forEach((key=>{let val=e[key];Array.isArray(val)&&(val=val.join(" ")),res+=" "+key+'="'+val+'"'})),2===arr.length||(res+=">",!1);res+=">"}var o;switch(typeof e){case"string":case"number":case"boolean":case"undefined":return body+=e+cr,!1}return isFlat=!1,body+=rec(e),!1}));return isEmpty?res+"/>"+cr:isFlat?res+body.split("\n").filter((e=>""!==e.trim())).join("\n")+"</"+a[0]+">"+cr:res+cr+indent(body)+"</"+a[0]+">"+cr};return rec(a)},flatten$1=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten$1(val)):acc.concat(val)),[]),clone$a=matrix=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},copy$5=(out,matrix)=>(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out),EPS=1e-5,TAU=2*Math.PI,rezero=n=>Math.abs(n)<1e-13?0:n,sin=radians=>rezero(Math.sin(radians)),cos=radians=>rezero(Math.cos(radians)),identity=out=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromRotation=(out,rad,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return identity(out);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(rad),c=cos(rad),t=1-c;return out[0]=x*x*t+c,out[1]=y*x*t+z*s,out[2]=z*x*t-y*s,out[3]=0,out[4]=x*y*t-z*s,out[5]=y*y*t+c,out[6]=z*y*t+x*s,out[7]=0,out[8]=x*z*t+y*s,out[9]=y*z*t-x*s,out[10]=z*z*t+c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},abs$1=(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out[2]=Math.abs(vector[2]),out),add$1=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out),dot$2=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2],clone$9=vector=>{const out=[0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out},copy$4=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out),cross$1=(out,a,b)=>{const ax=a[0],ay=a[1],az=a[2],bx=b[0],by=b[1],bz=b[2];return out[0]=ay*bz-az*by,out[1]=az*bx-ax*bz,out[2]=ax*by-ay*bx,out},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),snap$2=(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out[2]=Math.round(vector[2]/epsilon)*epsilon+0,out),squaredDistance$1=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1],z=b[2]-a[2];return x*x+y*y+z*z},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};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:snap$2,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};Object.freeze({__proto__:null,add:(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out[2]=a[2]+b[2],out[3]=a[3]+b[3],out[4]=a[4]+b[4],out[5]=a[5]+b[5],out[6]=a[6]+b[6],out[7]=a[7]+b[7],out[8]=a[8]+b[8],out[9]=a[9]+b[9],out[10]=a[10]+b[10],out[11]=a[11]+b[11],out[12]=a[12]+b[12],out[13]=a[13]+b[13],out[14]=a[14]+b[14],out[15]=a[15]+b[15],out),clone:clone$a,copy:copy$5,create:()=>[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],equals:(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15],fromRotation:fromRotation,fromScaling:(out,vector)=>(out[0]=vector[0],out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=vector[1],out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=vector[2],out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out),fromTaitBryanRotation:(out,yaw,pitch,roll)=>{const sy=sin(yaw),cy=cos(yaw),sp=sin(pitch),cp=cos(pitch),sr=sin(roll),cr=cos(roll);return out[0]=cp*cy,out[1]=cp*sy,out[2]=-sp,out[3]=0,out[4]=sr*sp*cy-cr*sy,out[5]=cr*cy+sr*sp*sy,out[6]=sr*cp,out[7]=0,out[8]=sr*sy+cr*sp*cy,out[9]=cr*sp*sy-sr*cy,out[10]=cr*cp,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromTranslation:(out,vector)=>(out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=vector[0],out[13]=vector[1],out[14]=vector[2],out[15]=1,out),fromValues:(m00,m01,m02,m03,m10,m11,m12,m13,m20,m21,m22,m23,m30,m31,m32,m33)=>{const out=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];return out[0]=m00,out[1]=m01,out[2]=m02,out[3]=m03,out[4]=m10,out[5]=m11,out[6]=m12,out[7]=m13,out[8]=m20,out[9]=m21,out[10]=m22,out[11]=m23,out[12]=m30,out[13]=m31,out[14]=m32,out[15]=m33,out},fromVectorRotation:(out,source,target)=>{const sourceNormal=normalize$1([0,0,0],source),targetNormal=normalize$1([0,0,0],target),axis=cross$1([0,0,0],targetNormal,sourceNormal),cosA=dot$2(targetNormal,sourceNormal);if(-1===cosA)return fromRotation(out,Math.PI,orthogonal(axis,sourceNormal));const k=1/(1+cosA);return out[0]=axis[0]*axis[0]*k+cosA,out[1]=axis[1]*axis[0]*k-axis[2],out[2]=axis[2]*axis[0]*k+axis[1],out[3]=0,out[4]=axis[0]*axis[1]*k+axis[2],out[5]=axis[1]*axis[1]*k+cosA,out[6]=axis[2]*axis[1]*k-axis[0],out[7]=0,out[8]=axis[0]*axis[2]*k-axis[1],out[9]=axis[1]*axis[2]*k+axis[0],out[10]=axis[2]*axis[2]*k+cosA,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromXRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=1,out[1]=0,out[2]=0,out[3]=0,out[4]=0,out[5]=c,out[6]=s,out[7]=0,out[8]=0,out[9]=-s,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromYRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=0,out[2]=-s,out[3]=0,out[4]=0,out[5]=1,out[6]=0,out[7]=0,out[8]=s,out[9]=0,out[10]=c,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},fromZRotation:(out,radians)=>{const s=sin(radians),c=cos(radians);return out[0]=c,out[1]=s,out[2]=0,out[3]=0,out[4]=-s,out[5]=c,out[6]=0,out[7]=0,out[8]=0,out[9]=0,out[10]=1,out[11]=0,out[12]=0,out[13]=0,out[14]=0,out[15]=1,out},identity:identity,invert:(out,matrix)=>{const a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],a30=matrix[12],a31=matrix[13],a32=matrix[14],a33=matrix[15],b00=a00*a11-a01*a10,b01=a00*a12-a02*a10,b02=a00*a13-a03*a10,b03=a01*a12-a02*a11,b04=a01*a13-a03*a11,b05=a02*a13-a03*a12,b06=a20*a31-a21*a30,b07=a20*a32-a22*a30,b08=a20*a33-a23*a30,b09=a21*a32-a22*a31,b10=a21*a33-a23*a31,b11=a22*a33-a23*a32;let det=b00*b11-b01*b10+b02*b09+b03*b08-b04*b07+b05*b06;return det?(det=1/det,out[0]=(a11*b11-a12*b10+a13*b09)*det,out[1]=(a02*b10-a01*b11-a03*b09)*det,out[2]=(a31*b05-a32*b04+a33*b03)*det,out[3]=(a22*b04-a21*b05-a23*b03)*det,out[4]=(a12*b08-a10*b11-a13*b07)*det,out[5]=(a00*b11-a02*b08+a03*b07)*det,out[6]=(a32*b02-a30*b05-a33*b01)*det,out[7]=(a20*b05-a22*b02+a23*b01)*det,out[8]=(a10*b10-a11*b08+a13*b06)*det,out[9]=(a01*b08-a00*b10-a03*b06)*det,out[10]=(a30*b04-a31*b02+a33*b00)*det,out[11]=(a21*b02-a20*b04-a23*b00)*det,out[12]=(a11*b07-a10*b09-a12*b06)*det,out[13]=(a00*b09-a01*b07+a02*b06)*det,out[14]=(a31*b01-a30*b03-a32*b00)*det,out[15]=(a20*b03-a21*b01+a22*b00)*det,out):null},isIdentity:isIdentity,isMirroring:isMirroring,isOnlyTransformScale:matrix=>isZero(matrix[1])&&isZero(matrix[2])&&isZero(matrix[3])&&isZero(matrix[4])&&isZero(matrix[6])&&isZero(matrix[7])&&isZero(matrix[8])&&isZero(matrix[9])&&isZero(matrix[11])&&1===matrix[15],mirrorByPlane:(out,plane)=>{const[nx,ny,nz,w]=plane;return out[0]=1-2*nx*nx,out[1]=-2*ny*nx,out[2]=-2*nz*nx,out[3]=0,out[4]=-2*nx*ny,out[5]=1-2*ny*ny,out[6]=-2*nz*ny,out[7]=0,out[8]=-2*nx*nz,out[9]=-2*ny*nz,out[10]=1-2*nz*nz,out[11]=0,out[12]=2*nx*w,out[13]=2*ny*w,out[14]=2*nz*w,out[15]=1,out},multiply:multiply$1,rotate:(out,matrix,radians,axis)=>{let[x,y,z]=axis;const lengthSquared=x*x+y*y+z*z;if(Math.abs(lengthSquared)<EPS)return copy$5(out,matrix);const len=1/Math.sqrt(lengthSquared);x*=len,y*=len,z*=len;const s=sin(radians),c=cos(radians),t=1-c,a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],b00=x*x*t+c,b01=y*x*t+z*s,b02=z*x*t-y*s,b10=x*y*t-z*s,b11=y*y*t+c,b12=z*y*t+x*s,b20=x*z*t+y*s,b21=y*z*t-x*s,b22=z*z*t+c;return out[0]=a00*b00+a10*b01+a20*b02,out[1]=a01*b00+a11*b01+a21*b02,out[2]=a02*b00+a12*b01+a22*b02,out[3]=a03*b00+a13*b01+a23*b02,out[4]=a00*b10+a10*b11+a20*b12,out[5]=a01*b10+a11*b11+a21*b12,out[6]=a02*b10+a12*b11+a22*b12,out[7]=a03*b10+a13*b11+a23*b12,out[8]=a00*b20+a10*b21+a20*b22,out[9]=a01*b20+a11*b21+a21*b22,out[10]=a02*b20+a12*b21+a22*b22,out[11]=a03*b20+a13*b21+a23*b22,matrix!==out&&(out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out},rotateX:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[0]=matrix[0],out[1]=matrix[1],out[2]=matrix[2],out[3]=matrix[3],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[4]=a10*c+a20*s,out[5]=a11*c+a21*s,out[6]=a12*c+a22*s,out[7]=a13*c+a23*s,out[8]=a20*c-a10*s,out[9]=a21*c-a11*s,out[10]=a22*c-a12*s,out[11]=a23*c-a13*s,out},rotateY:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11];return matrix!==out&&(out[4]=matrix[4],out[5]=matrix[5],out[6]=matrix[6],out[7]=matrix[7],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c-a20*s,out[1]=a01*c-a21*s,out[2]=a02*c-a22*s,out[3]=a03*c-a23*s,out[8]=a00*s+a20*c,out[9]=a01*s+a21*c,out[10]=a02*s+a22*c,out[11]=a03*s+a23*c,out},rotateZ:(out,matrix,radians)=>{const s=sin(radians),c=cos(radians),a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7];return matrix!==out&&(out[8]=matrix[8],out[9]=matrix[9],out[10]=matrix[10],out[11]=matrix[11],out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15]),out[0]=a00*c+a10*s,out[1]=a01*c+a11*s,out[2]=a02*c+a12*s,out[3]=a03*c+a13*s,out[4]=a10*c-a00*s,out[5]=a11*c-a01*s,out[6]=a12*c-a02*s,out[7]=a13*c-a03*s,out},scale:(out,matrix,dimensions)=>{const x=dimensions[0],y=dimensions[1],z=dimensions[2];return out[0]=matrix[0]*x,out[1]=matrix[1]*x,out[2]=matrix[2]*x,out[3]=matrix[3]*x,out[4]=matrix[4]*y,out[5]=matrix[5]*y,out[6]=matrix[6]*y,out[7]=matrix[7]*y,out[8]=matrix[8]*z,out[9]=matrix[9]*z,out[10]=matrix[10]*z,out[11]=matrix[11]*z,out[12]=matrix[12],out[13]=matrix[13],out[14]=matrix[14],out[15]=matrix[15],out},subtract:(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out[2]=a[2]-b[2],out[3]=a[3]-b[3],out[4]=a[4]-b[4],out[5]=a[5]-b[5],out[6]=a[6]-b[6],out[7]=a[7]-b[7],out[8]=a[8]-b[8],out[9]=a[9]-b[9],out[10]=a[10]-b[10],out[11]=a[11]-b[11],out[12]=a[12]-b[12],out[13]=a[13]-b[13],out[14]=a[14]-b[14],out[15]=a[15]-b[15],out),toString:mat=>mat.map((n=>n.toFixed(7))).toString(),translate:(out,matrix,offsets)=>{const x=offsets[0],y=offsets[1],z=offsets[2];let a00,a01,a02,a03,a10,a11,a12,a13,a20,a21,a22,a23;return matrix===out?(out[12]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12],out[13]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13],out[14]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14],out[15]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]):(a00=matrix[0],a01=matrix[1],a02=matrix[2],a03=matrix[3],a10=matrix[4],a11=matrix[5],a12=matrix[6],a13=matrix[7],a20=matrix[8],a21=matrix[9],a22=matrix[10],a23=matrix[11],out[0]=a00,out[1]=a01,out[2]=a02,out[3]=a03,out[4]=a10,out[5]=a11,out[6]=a12,out[7]=a13,out[8]=a20,out[9]=a21,out[10]=a22,out[11]=a23,out[12]=a00*x+a10*y+a20*z+matrix[12],out[13]=a01*x+a11*y+a21*z+matrix[13],out[14]=a02*x+a12*y+a22*z+matrix[14],out[15]=a03*x+a13*y+a23*z+matrix[15]),out}});const create$a=(outlines=[])=>({outlines:outlines,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),add=(out,a,b)=>(out[0]=a[0]+b[0],out[1]=a[1]+b[1],out),angleRadians=vector=>Math.atan2(vector[1],vector[0]),angleDegrees=vector=>57.29577951308232*angleRadians(vector),clone$8=vector=>{const out=[0,0];return out[0]=vector[0],out[1]=vector[1],out},cross=(out,a,b)=>(out[0]=0,out[1]=0,out[2]=a[0]*b[1]-a[1]*b[0],out),distance=(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return Math.sqrt(x*x+y*y)},dot$1=(a,b)=>a[0]*b[0]+a[1]*b[1],equals$6=(a,b)=>a[0]===b[0]&&a[1]===b[1],fromAngleRadians=(out,radians)=>(out[0]=cos(radians),out[1]=sin(radians),out),fromValues$2=(x,y)=>{const out=[0,0];return out[0]=x,out[1]=y,out},max$1=(out,a,b)=>(out[0]=Math.max(a[0],b[0]),out[1]=Math.max(a[1],b[1]),out),min$1=(out,a,b)=>(out[0]=Math.min(a[0],b[0]),out[1]=Math.min(a[1],b[1]),out),negate=(out,vector)=>(out[0]=-vector[0],out[1]=-vector[1],out),rotate$1=(out,vector,origin,radians)=>{const x=vector[0]-origin[0],y=vector[1]-origin[1],c=Math.cos(radians),s=Math.sin(radians);return out[0]=x*c-y*s+origin[0],out[1]=x*s+y*c+origin[1],out},normal=(out,vector)=>rotate$1(out,vector,[0,0],TAU/4),normalize=(out,vector)=>{const x=vector[0],y=vector[1];let len=x*x+y*y;return len>0&&(len=1/Math.sqrt(len)),out[0]=x*len,out[1]=y*len,out},scale$1=(out,vector,amount)=>(out[0]=vector[0]*amount,out[1]=vector[1]*amount,out),subtract$1=(out,a,b)=>(out[0]=a[0]-b[0],out[1]=a[1]-b[1],out),toString$9=vector=>`[${vector[0].toFixed(7)}, ${vector[1].toFixed(7)}]`,transform$b=(out,vector,matrix)=>{const x=vector[0],y=vector[1];return out[0]=matrix[0]*x+matrix[4]*y+matrix[12],out[1]=matrix[1]*x+matrix[5]*y+matrix[13],out};Object.freeze({__proto__:null,abs:(out,vector)=>(out[0]=Math.abs(vector[0]),out[1]=Math.abs(vector[1]),out),add:add,angle:angleRadians,angleDegrees:angleDegrees,angleRadians:angleRadians,clone:clone$8,copy:(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out),create:()=>[0,0],cross:cross,distance:distance,divide:(out,a,b)=>(out[0]=a[0]/b[0],out[1]=a[1]/b[1],out),dot:dot$1,equals:equals$6,fromAngleDegrees:(out,degrees)=>fromAngleRadians(out,.017453292519943295*degrees),fromAngleRadians:fromAngleRadians,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out),fromValues:fromValues$2,length:vector=>Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]),lerp:(out,a,b,t)=>{const ax=a[0],ay=a[1];return out[0]=ax+t*(b[0]-ax),out[1]=ay+t*(b[1]-ay),out},max:max$1,min:min$1,multiply:(out,a,b)=>(out[0]=a[0]*b[0],out[1]=a[1]*b[1],out),negate:negate,normal:normal,normalize:normalize,rotate:rotate$1,scale:scale$1,snap:(out,vector,epsilon)=>(out[0]=Math.round(vector[0]/epsilon)*epsilon+0,out[1]=Math.round(vector[1]/epsilon)*epsilon+0,out),squaredDistance:(a,b)=>{const x=b[0]-a[0],y=b[1]-a[1];return x*x+y*y},squaredLength:vector=>{const x=vector[0],y=vector[1];return x*x+y*y},subtract:subtract$1,toString:toString$9,transform:transform$b});const popNextSide=(startSide,nextSides)=>{if(1===nextSides.length)return nextSides.pop();const v0=[0,0],startAngle=angleDegrees(subtract$1(v0,startSide[1],startSide[0]));let bestAngle,bestIndex;nextSides.forEach(((nextSide,index)=>{let angle=angleDegrees(subtract$1(v0,nextSide[1],nextSide[0]))-startAngle;angle<-180&&(angle+=360),angle>=180&&(angle-=360),(void 0===bestIndex||angle>bestAngle)&&(bestIndex=index,bestAngle=angle)}));const nextSide=nextSides[bestIndex];return nextSides.splice(bestIndex,1),nextSide},isA$5=object=>!!(object&&"object"==typeof object&&"outlines"in object&&"transforms"in object&&Array.isArray(object.outlines)&&"length"in object.transforms),toOutlines=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.outlines=geometry.outlines.map((outline=>outline.map((point=>transform$b([0,0],point,geometry.transforms))))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).outlines,toPoints$3=geometry=>{const points=[];return toOutlines(geometry).forEach((outline=>{outline.forEach((point=>{points.push(point)}))})),points},intersect$1=(p1,p2,p3,p4,endpointTouch=!0)=>{if(p1[0]===p2[0]&&p1[1]===p2[1]||p3[0]===p4[0]&&p3[1]===p4[1])return;const denominator=(p4[1]-p3[1])*(p2[0]-p1[0])-(p4[0]-p3[0])*(p2[1]-p1[1]);if(Math.abs(denominator)<Number.MIN_VALUE)return;const ua=((p4[0]-p3[0])*(p1[1]-p3[1])-(p4[1]-p3[1])*(p1[0]-p3[0]))/denominator,ub=((p2[0]-p1[0])*(p1[1]-p3[1])-(p2[1]-p1[1])*(p1[0]-p3[0]))/denominator;return ua<0||ua>1||ub<0||ub>1||!(endpointTouch||0!==ua&&1!==ua&&0!==ub&&1!==ub)?void 0:[p1[0]+ua*(p2[0]-p1[0]),p1[1]+ua*(p2[1]-p1[1])]};Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$a,fromSides:sides=>{const pointMap=(sides=>{const pointMap=new Map,edges=(sides=>{const unique=new Map,getUniquePoint=point=>{const key=point.toString();return unique.has(key)?unique.get(key):(unique.set(key,point),point)};return sides.map((side=>side.map(getUniquePoint)))})(sides);return edges.forEach((edge=>{pointMap.has(edge[0])?pointMap.get(edge[0]).push(edge):pointMap.set(edge[0],[edge])})),pointMap})(sides),outlines=[];for(;;){let startSide;for(const[point,edges]of pointMap){if(startSide=edges.shift(),startSide)break;pointMap.delete(point)}if(void 0===startSide)break;const connectedPoints=[],startPoint=startSide[0];for(;;){connectedPoints.push(startSide[0]);const nextPoint=startSide[1];if(nextPoint===startPoint)break;const nextPossibleSides=pointMap.get(nextPoint);if(!nextPossibleSides)throw new Error(`geometry is not closed at point ${nextPoint}`);const nextSide=popNextSide(startSide,nextPossibleSides);0===nextPossibleSides.length&&pointMap.delete(nextPoint),startSide=nextSide}connectedPoints.length>0&&connectedPoints.push(connectedPoints.shift()),outlines.push(connectedPoints)}return pointMap.clear(),create$a(outlines)},fromCompactBinary:data=>{if(0!==data[0])throw new Error("invalid compact binary data");const created=create$a();created.transforms=clone$a(data.slice(1,17));for(let i=21;i<data.length;){const length=data[i++];if(length<0||i+2*length>data.length)throw new Error("invalid compact binary data");const outline=[];for(let j=0;j<length;j++){const x=data[i+2*j],y=data[i+2*j+1];outline.push(fromValues$2(x,y))}created.outlines.push(outline),i+=2*length}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},isA:isA$5,reverse: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:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$5(object))throw new Error("invalid geom2 structure");if(object.outlines.forEach(((outline,i)=>{if(outline.length<3)throw new Error(`geom2 outline ${i} must contain at least 3 points`);for(let i=0;i<outline.length;i++){const j=(i+1)%outline.length;if(equals$6(outline[i],outline[j]))throw new Error(`geom2 outline ${i} has duplicate point ${outline[i]}`)}})),toOutlines(object).forEach(((outline,i)=>{for(let a1=0;a1<outline.length;a1++){const a2=(a1+1)%outline.length;for(let b1=0;b1<outline.length;b1++){const b2=(b1+1)%outline.length;if(a1!==b1){const int=intersect$1(outline[a1],outline[a2],outline[b1],outline[b2],!1);if(int)throw new Error(`geom2 outline ${i} self intersection at ${int}`)}}}})),!object.transforms.every(Number.isFinite))throw new Error(`geom2 invalid transforms ${object.transforms}`)}});const create$8=polygons=>(void 0===polygons&&(polygons=[]),{polygons:polygons,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),create$7=vertices=>((void 0===vertices||vertices.length<3)&&(vertices=[]),{vertices:vertices}),fromVerticesAndPlane=(vertices,plane)=>{const poly=create$7(vertices);return poly.plane=plane,poly},create$6=()=>[0,0,0,0],clone$5=vector=>{const out=[0,0,0,0];return out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out},copy$2=(out,vector)=>(out[0]=vector[0],out[1]=vector[1],out[2]=vector[2],out[3]=vector[3],out),equals$5=(a,b)=>a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3],flip=(out,plane)=>(out[0]=-plane[0],out[1]=-plane[1],out[2]=-plane[2],out[3]=-plane[3],out),fromValues$1=(x,y,z,w)=>{const out=[0,0,0,0];return out[0]=x,out[1]=y,out[2]=z,out[3]=w,out},fromPoints$4=(out,...vertices)=>{const len=vertices.length,ba=[0,0,0],ca=[0,0,0],vertexNormal=index=>{const a=vertices[index],b=vertices[(index+1)%len],c=vertices[(index+2)%len];return subtract$3(ba,b,a),subtract$3(ca,c,a),cross$1(ba,ba,ca),normalize$1(ba,ba),ba};return out[0]=0,out[1]=0,out[2]=0,3===len?copy$4(out,vertexNormal(0)):(vertices.forEach(((v,i)=>{add$1(out,out,vertexNormal(i))})),normalize$1(out,out)),out[3]=dot$2(out,vertices[0]),out},signedDistanceToPoint=(plane,point)=>dot$2(plane,point)-plane[3],toString$7=vec=>`(${vec[0].toFixed(9)}, ${vec[1].toFixed(9)}, ${vec[2].toFixed(9)}, ${vec[3].toFixed(9)})`;Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,equals:equals$5,flip:flip,fromNormalAndPoint:(out,normal,point)=>{const u=normalize$1([0,0,0],normal),w=dot$2(point,u);return out[0]=u[0],out[1]=u[1],out[2]=u[2],out[3]=w,out},fromValues:fromValues$1,fromPoints:fromPoints$4,fromPointsRandom:(out,a,b,c)=>{let ba=subtract$3([0,0,0],b,a),ca=subtract$3([0,0,0],c,a);length$2(ba)<EPS&&(ba=orthogonal(ba,ca)),length$2(ca)<EPS&&(ca=orthogonal(ca,ba));let normal=cross$1([0,0,0],ba,ca);length$2(normal)<EPS&&(ca=orthogonal(ca,ba),normal=cross$1(normal,ba,ca)),normal=normalize$1(normal,normal);const w=dot$2(normal,a);return out[0]=normal[0],out[1]=normal[1],out[2]=normal[2],out[3]=w,out},projectionOfPoint:(plane,point)=>{const a=point[0]*plane[0]+point[1]*plane[1]+point[2]*plane[2]-plane[3],x=point[0]-a*plane[0],y=point[1]-a*plane[1],z=point[2]-a*plane[2];return fromValues$3(x,y,z)},signedDistanceToPoint:signedDistanceToPoint,toString:toString$7,transform:(out,plane,matrix)=>{const isMirror=isMirroring(matrix),r=orthogonal([0,0,0],plane),u=cross$1(r,plane,r),v=cross$1([0,0,0],plane,u);let point1=fromScalar$2([0,0,0],plane[3]);multiply$2(point1,point1,plane);let point2=add$1([0,0,0],point1,u),point3=add$1([0,0,0],point1,v);return point1=transform$c(point1,point1,matrix),point2=transform$c(point2,point2,matrix),point3=transform$c(point3,point3,matrix),fromPoints$4(out,point1,point2,point3),isMirror&&flip(out,out),out}});const invert$1=polygon=>{const vertices=polygon.vertices.slice().reverse(),inverted=create$7(vertices);return polygon.plane&&(inverted.plane=flip([0,0,0,0],polygon.plane)),inverted},isA$4=object=>!!(object&&"object"==typeof object&&"vertices"in object&&Array.isArray(object.vertices)),isConvex$1=polygon=>areVerticesConvex(polygon.vertices),areVerticesConvex=vertices=>{const numVertices=vertices.length;if(numVertices>2){const normal=fromPoints$4([0,0,0,0],...vertices);let prevPrevPos=vertices[numVertices-2],prevPos=vertices[numVertices-1];for(let i=0;i<numVertices;i++){const pos=vertices[i];if(!isConvexVertex(prevPrevPos,prevPos,pos,normal))return!1;prevPrevPos=prevPos,prevPos=pos}}return!0},isConvexVertex=(prevVertex,vertex,nextVertex,normal)=>{const crossProduct=cross$1([0,0,0],subtract$3([0,0,0],vertex,prevVertex),subtract$3([0,0,0],nextVertex,vertex));return dot$2(crossProduct,normal)>=0},plane=polygon=>(polygon.plane||(polygon.plane=fromPoints$4([0,0,0,0],...polygon.vertices)),polygon.plane),measureArea$2=polygon=>{const n=polygon.vertices.length;if(n<3)return 0;const vertices=polygon.vertices,normal=plane(polygon),ax=Math.abs(normal[0]),ay=Math.abs(normal[1]),az=Math.abs(normal[2]);if(ax+ay+az===0)return 0;let coord=3;ax>ay&&ax>az?coord=1:ay>az&&(coord=2);let area=0,h=0,i=1,j=2;switch(coord){case 1:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][1]*(vertices[j][2]-vertices[h][2]);area+=vertices[0][1]*(vertices[1][2]-vertices[n-1][2]),area/=2*normal[0];break;case 2:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][2]*(vertices[j][0]-vertices[h][0]);area+=vertices[0][2]*(vertices[1][0]-vertices[n-1][0]),area/=2*normal[1];break;default:for(i=1;i<n;i++)h=i-1,j=(i+1)%n,area+=vertices[i][0]*(vertices[j][1]-vertices[h][1]);area+=vertices[0][0]*(vertices[1][1]-vertices[n-1][1]),area/=2*normal[2]}return area};Object.freeze({__proto__:null,clone:clone$5,copy:copy$2,create:create$6,dot:(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],equals:equals$5,fromScalar:(out,scalar)=>(out[0]=scalar,out[1]=scalar,out[2]=scalar,out[3]=scalar,out),fromValues:fromValues$1,toString:toString$7,transform:(out,vector,matrix)=>{const[x,y,z,w]=vector;return out[0]=matrix[0]*x+matrix[4]*y+matrix[8]*z+matrix[12]*w,out[1]=matrix[1]*x+matrix[5]*y+matrix[9]*z+matrix[13]*w,out[2]=matrix[2]*x+matrix[6]*y+matrix[10]*z+matrix[14]*w,out[3]=matrix[3]*x+matrix[7]*y+matrix[11]*z+matrix[15]*w,out}});const cache$4=new WeakMap,toVertices$1=polygon=>polygon.vertices,toString$6=polygon=>`poly3: [${polygon.vertices.map(toString$b).join(", ")}]`,transform$7=(matrix,polygon)=>{const vertices=polygon.vertices.map((vertex=>transform$c([0,0,0],vertex,matrix)));return isMirroring(matrix)&&vertices.reverse(),create$7(vertices)},validate$4=object=>{if(!isA$4(object))throw new Error("invalid poly3 structure");if(object.vertices.length<3)throw new Error(`poly3 not enough vertices ${object.vertices.length}`);if(measureArea$2(object)<=0)throw new Error("poly3 area must be greater than zero");for(let i=0;i<object.vertices.length;i++)if(equals$7(object.vertices[i],object.vertices[(i+1)%object.vertices.length]))throw new Error(`poly3 has duplicate vertex ${object.vertices[i]}`);if(!isConvex$1(object))throw new Error("poly3 must be convex");if(object.vertices.forEach((vertex=>{if(!vertex.every(Number.isFinite))throw new Error(`poly3 invalid vertex ${vertex}`)})),object.vertices.length>3){const normal=plane(object);object.vertices.forEach((vertex=>{const dist=Math.abs(signedDistanceToPoint(normal,vertex));if(dist>1e-13)throw new Error(`poly3 must be coplanar: vertex ${vertex} distance ${dist}`)}))}};Object.freeze({__proto__:null,clone:(...params)=>{let out,poly3;return 1===params.length?(out=create$7(),poly3=params[0]):(out=params[0],poly3=params[1]),out.vertices=poly3.vertices.map((vec=>clone$9(vec))),out},create:create$7,fromVerticesAndPlane:fromVerticesAndPlane,invert:invert$1,isA:isA$4,isConvex:isConvex$1,measureArea:measureArea$2,measureBoundingBox:polygon=>{const vertices=polygon.vertices,numVertices=vertices.length,min=0===numVertices?[0,0,0]:clone$9(vertices[0]),max=clone$9(min);for(let i=1;i<numVertices;i++)min$2(min,min,vertices[i]),max$2(max,max,vertices[i]);return[min,max]},measureBoundingSphere:polygon=>{const boundingSphere=cache$4.get(polygon);if(boundingSphere)return boundingSphere;const vertices=polygon.vertices,out=[0,0,0,0];if(0===vertices.length)return out[0]=0,out[1]=0,out[2]=0,out[3]=0,out;let minx=vertices[0],miny=minx,minz=minx,maxx=minx,maxy=minx,maxz=minx;vertices.forEach((v=>{minx[0]>v[0]&&(minx=v),miny[1]>v[1]&&(miny=v),minz[2]>v[2]&&(minz=v),maxx[0]<v[0]&&(maxx=v),maxy[1]<v[1]&&(maxy=v),maxz[2]<v[2]&&(maxz=v)})),out[0]=.5*(minx[0]+maxx[0]),out[1]=.5*(miny[1]+maxy[1]),out[2]=.5*(minz[2]+maxz[2]);const x=out[0]-maxx[0],y=out[1]-maxy[1],z=out[2]-maxz[2];return out[3]=Math.sqrt(x*x+y*y+z*z),cache$4.set(polygon,out),out},measureSignedVolume:polygon=>{let signedVolume=0;const vertices=polygon.vertices,cross=[0,0,0];for(let i=0;i<vertices.length-2;i++)cross$1(cross,vertices[i+1],vertices[i+2]),signedVolume+=dot$2(vertices[0],cross);return signedVolume/=6,signedVolume},plane:plane,toVertices:toVertices$1,toString:toString$6,transform:transform$7,validate:validate$4});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);var index$6=Object.freeze({__proto__:null,clone:geometry=>Object.assign({},geometry),create:create$8,fromPoints:listOfLists=>{if(!Array.isArray(listOfLists))throw new Error("the given vertices must be an array");return create$8(listOfLists.map(create$7))},fromCompactBinary:data=>{if(1!==data[0])throw new Error("invalid compact binary data");const created=create$8();created.transforms=clone$a(data.slice(1,17));const numberOfVertices=data[21];let ci=22,vi=data.length-3*numberOfVertices;for(;vi<data.length;){const verticesPerPolygon=data[ci];ci++;const vertices=[];for(let i=0;i<verticesPerPolygon;i++)vertices.push(fromValues$3(data[vi],data[vi+1],data[vi+2])),vi+=3;created.polygons.push(create$7(vertices))}return data[17]>=0&&(created.color=[data[17],data[18],data[19],data[20]]),created},invert:geometry=>{const newPolygons=toPolygons$1(geometry).map((polygon=>invert$1(polygon)));return create$8(newPolygons)},isA:isA$3,toPoints:geometry=>toPolygons$1(geometry).map((polygon=>toVertices$1(polygon))),toPolygons:toPolygons$1,toString:geometry=>{const polygons=toPolygons$1(geometry);let result="geom3 ("+polygons.length+" polygons):\n";return polygons.forEach((polygon=>{result+=" "+toString$6(polygon)+"\n"})),result},toCompactBinary:geometry=>{const polygons=geometry.polygons,transforms=geometry.transforms,numberOfPolygons=polygons.length,numberOfVertices=polygons.reduce(((count,polygon)=>count+polygon.vertices.length),0);let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+numberOfPolygons+3*numberOfVertices);compacted[0]=1,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=color[0],compacted[18]=color[1],compacted[19]=color[2],compacted[20]=color[3],compacted[21]=numberOfVertices;let ci=22,vi=ci+numberOfPolygons;return polygons.forEach((polygon=>{const vertices=toVertices$1(polygon);compacted[ci]=vertices.length,ci++;for(let i=0;i<vertices.length;i++){const vertex=vertices[i];compacted[vi+0]=vertex[0],compacted[vi+1]=vertex[1],compacted[vi+2]=vertex[2],vi+=3}})),compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$3(object))throw new Error("invalid geom3 structure");if(object.polygons.forEach(validate$4),(object=>{const edgeCount=new Map;object.polygons.forEach((({vertices:vertices})=>{vertices.forEach(((v,i)=>{const edge=`${v}/${vertices[(i+1)%vertices.length]}`,count=edgeCount.has(edge)?edgeCount.get(edge):0;edgeCount.set(edge,count+1)}))}));const nonManifold=[];if(edgeCount.forEach(((count,edge)=>{const complementEdge=edge.split("/").reverse().join("/");count!==edgeCount.get(complementEdge)&&nonManifold.push(edge.replace("/"," -> "))})),nonManifold.length>0)throw new Error(`non-manifold edges ${nonManifold.length}\n${nonManifold.join("\n")}`)})(object),!object.transforms.every(Number.isFinite))throw new Error(`geom3 invalid transforms ${object.transforms}`)}});const clone$4=geometry=>Object.assign({},geometry),close=geometry=>{if(geometry.isClosed)return geometry;const cloned=clone$4(geometry);if(cloned.isClosed=!0,cloned.points.length>1){const points=cloned.points,p0=points[0];let pn=points[points.length-1];for(;distance(p0,pn)<EPS*EPS&&(points.pop(),1!==points.length);)pn=points[points.length-1]}return cloned},create$5=points=>(void 0===points&&(points=[]),{points:points,isClosed:!1,transforms:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]}),fromPoints$2=(options,points)=>{let{closed:closed}=Object.assign({},{closed:!1},options),created=create$5();if(created.points=points.map((point=>clone$8(point))),created.points.length>1){const p0=created.points[0],pn=created.points[created.points.length-1];distance(p0,pn)<EPS*EPS&&(closed=!0)}return!0===closed&&(created=close(created)),created},toPoints$1=geometry=>(geometry=>(isIdentity(geometry.transforms)||(geometry.points=geometry.points.map((point=>transform$b([0,0],point,geometry.transforms))),geometry.transforms=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),geometry))(geometry).points,concat=(...paths)=>{let isClosed=!1,newPoints=[];return paths.forEach(((path,i)=>{const tmp=toPoints$1(path).slice();if(newPoints.length>0&&tmp.length>0&&equals$6(tmp[0],newPoints[newPoints.length-1])&&tmp.shift(),tmp.length>0&&isClosed)throw new Error(`Cannot concatenate to a closed path; check the ${i}th path`);isClosed=path.isClosed,newPoints=newPoints.concat(tmp)})),fromPoints$2({closed:isClosed},newPoints)},appendPoints=(points,geometry)=>concat(geometry,create$5(points)),isA$2=object=>!!(object&&"object"==typeof object&&"points"in object&&"transforms"in object&&"isClosed"in object&&Array.isArray(object.points)&&"length"in object.transforms);Object.freeze({__proto__:null,appendArc:(options,geometry)=>{let{endpoint:endpoint,radius:radius,xaxisRotation:xaxisRotation,clockwise:clockwise,large:large,segments:segments}=Object.assign({},{radius:[0,0],xaxisRotation:0,clockwise:!1,large:!1,segments:16},options);if(!Array.isArray(endpoint))throw new Error("endpoint must be an array of X and Y values");if(endpoint.length<2)throw new Error("endpoint must contain X and Y values");if(endpoint=clone$8(endpoint),!Array.isArray(radius))throw new Error("radius must be an array of X and Y values");if(radius.length<2)throw new Error("radius must contain X and Y values");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given path cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the arc)");let xRadius=radius[0],yRadius=radius[1];const startpoint=points[points.length-1];xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5,endpoint=fromValues$2(Math.round(1e5*endpoint[0])/1e5,Math.round(1e5*endpoint[1])/1e5);const sweepFlag=!clockwise;let newPoints=[];if(0===xRadius||0===yRadius)newPoints.push(endpoint);else{xRadius=Math.abs(xRadius),yRadius=Math.abs(yRadius);const phi=xaxisRotation,cosPhi=Math.cos(phi),sinPhi=Math.sin(phi),minusHalfDistance=subtract$1([0,0],startpoint,endpoint);scale$1(minusHalfDistance,minusHalfDistance,.5);const x=Math.round(1e5*(cosPhi*minusHalfDistance[0]+sinPhi*minusHalfDistance[1]))/1e5,y=Math.round(1e5*(-sinPhi*minusHalfDistance[0]+cosPhi*minusHalfDistance[1]))/1e5,startTranslated=fromValues$2(x,y),bigLambda=startTranslated[0]*startTranslated[0]/(xRadius*xRadius)+startTranslated[1]*startTranslated[1]/(yRadius*yRadius);if(bigLambda>1){const sqrtBigLambda=Math.sqrt(bigLambda);xRadius*=sqrtBigLambda,yRadius*=sqrtBigLambda,xRadius=Math.round(1e5*xRadius)/1e5,yRadius=Math.round(1e5*yRadius)/1e5}let multiplier1=Math.sqrt((xRadius*xRadius*yRadius*yRadius-xRadius*xRadius*startTranslated[1]*startTranslated[1]-yRadius*yRadius*startTranslated[0]*startTranslated[0])/(xRadius*xRadius*startTranslated[1]*startTranslated[1]+yRadius*yRadius*startTranslated[0]*startTranslated[0]));sweepFlag===large&&(multiplier1=-multiplier1);const centerTranslated=fromValues$2(xRadius*startTranslated[1]/yRadius,-yRadius*startTranslated[0]/xRadius);scale$1(centerTranslated,centerTranslated,multiplier1);let center=fromValues$2(cosPhi*centerTranslated[0]-sinPhi*centerTranslated[1],sinPhi*centerTranslated[0]+cosPhi*centerTranslated[1]);center=add(center,center,scale$1([0,0],add([0,0],startpoint,endpoint),.5));const vector1=fromValues$2((startTranslated[0]-centerTranslated[0])/xRadius,(startTranslated[1]-centerTranslated[1])/yRadius),vector2=fromValues$2((-startTranslated[0]-centerTranslated[0])/xRadius,(-startTranslated[1]-centerTranslated[1])/yRadius),theta1=angleRadians(vector1);let deltatheta=angleRadians(vector2)-theta1;deltatheta%=TAU,!sweepFlag&&deltatheta>0?deltatheta-=TAU:sweepFlag&&deltatheta<0&&(deltatheta+=TAU);let numSteps=Math.ceil(Math.abs(deltatheta)/TAU*segments)+1;numSteps<1&&(numSteps=1);for(let step=1;step<numSteps;step++){const theta=theta1+step/numSteps*deltatheta,cosTheta=Math.cos(theta),sinTheta=Math.sin(theta),point=fromValues$2(cosPhi*xRadius*cosTheta-sinPhi*yRadius*sinTheta,sinPhi*xRadius*cosTheta+cosPhi*yRadius*sinTheta);add(point,point,center),newPoints.push(point)}numSteps&&newPoints.push(options.endpoint)}return newPoints=points.concat(newPoints),fromPoints$2({},newPoints)},appendBezier:(options,geometry)=>{let{controlPoints:controlPoints,segments:segments}=Object.assign({},{segments:16},options);if(!Array.isArray(controlPoints))throw new Error("controlPoints must be an array of one or more points");if(controlPoints.length<1)throw new Error("controlPoints must be an array of one or more points");if(segments<4)throw new Error("segments must be four or more");if(geometry.isClosed)throw new Error("the given geometry cannot be closed");const points=toPoints$1(geometry);if(points.length<1)throw new Error("the given path must contain one or more points (as the starting point for the bezier curve)");if(controlPoints=controlPoints.slice(),null===controlPoints[0]){if(controlPoints.length<2)throw new Error("a null control point must be passed with one more control points");let lastBezierControlPoint=points[points.length-2];if("lastBezierControlPoint"in geometry&&(lastBezierControlPoint=geometry.lastBezierControlPoint),!Array.isArray(lastBezierControlPoint))throw new Error("the given path must contain TWO or more points if given a null control point");const controlPoint=scale$1([0,0],points[points.length-1],2);subtract$1(controlPoint,controlPoint,lastBezierControlPoint),controlPoints[0]=controlPoint}controlPoints.unshift(points[points.length-1]);const bezierOrder=controlPoints.length-1,factorials=[];let fact=1;for(let i=0;i<=bezierOrder;++i)i>0&&(fact*=i),factorials.push(fact);const binomials=[];for(let i=0;i<=bezierOrder;++i){const binomial=factorials[bezierOrder]/(factorials[i]*factorials[bezierOrder-i]);binomials.push(binomial)}const v0=[0,0],v1=[0,0],v3=[0,0,0],getPointForT=t=>{let tk=1,oneMinusTNMinusK=Math.pow(1-t,bezierOrder);const invOneMinusT=1!==t?1/(1-t):1,point=[0,0];for(let k=0;k<=bezierOrder;++k){k===bezierOrder&&(oneMinusTNMinusK=1);const bernsteinCoefficient=binomials[k]*tk*oneMinusTNMinusK,derivativePoint=scale$1(v0,controlPoints[k],bernsteinCoefficient);add(point,point,derivativePoint),tk*=t,oneMinusTNMinusK*=invOneMinusT}return point},newPoints=[],newPointsT=[],numSteps=bezierOrder+1;for(let i=0;i<numSteps;++i){const t=i/(numSteps-1),point=getPointForT(t);newPoints.push(point),newPointsT.push(t)}let subdivideBase=1;const maxAngle=TAU/segments,maxSinAngle=Math.sin(maxAngle);for(;subdivideBase<newPoints.length-1;){const dir1=subtract$1(v0,newPoints[subdivideBase],newPoints[subdivideBase-1]);normalize(dir1,dir1);const dir2=subtract$1(v1,newPoints[subdivideBase+1],newPoints[subdivideBase]);normalize(dir2,dir2);const sinAngle=cross(v3,dir1,dir2);if(Math.abs(sinAngle[2])>maxSinAngle){const t0=newPointsT[subdivideBase-1],t1=newPointsT[subdivideBase+1],newt0=t0+1*(t1-t0)/3,newt1=t0+2*(t1-t0)/3,point0=getPointForT(newt0),point1=getPointForT(newt1);newPoints.splice(subdivideBase,1,point0,point1),newPointsT.splice(subdivideBase,1,newt0,newt1),subdivideBase--,subdivideBase<1&&(subdivideBase=1)}else++subdivideBase}newPoints.shift();const result=appendPoints(newPoints,geometry);return result.lastBezierControlPoint=controlPoints[controlPoints.length-2],result},appendPoints:appendPoints,clone:clone$4,close:close,concat:concat,create:create$5,equals:(a,b)=>{if(a.isClosed!==b.isClosed)return!1;if(a.points.length!==b.points.length)return!1;const aPoints=toPoints$1(a),bPoints=toPoints$1(b),length=aPoints.length;let offset=0;do{let unequal=!1;for(let i=0;i<length;i++)if(!equals$6(aPoints[i],bPoints[(i+offset)%length])){unequal=!0;break}if(!1===unequal)return!0;if(!a.isClosed)return!1}while(++offset<length);return!1},fromPoints:fromPoints$2,fromCompactBinary:data=>{if(2!==data[0])throw new Error("invalid compact binary data");const created=create$5();created.transforms=clone$a(data.slice(1,17)),created.isClosed=!!data[17];for(let i=22;i<data.length;i+=2){const point=fromValues$2(data[i],data[i+1]);created.points.push(point)}return data[18]>=0&&(created.color=[data[18],data[19],data[20],data[21]]),created},isA:isA$2,reverse:geometry=>{const cloned=clone$4(geometry);return cloned.points=geometry.points.slice().reverse(),cloned},toPoints:toPoints$1,toString:geometry=>{const points=toPoints$1(geometry);let result="path ("+points.length+" points, "+geometry.isClosed+"):\n[\n";return points.forEach((point=>{result+=" "+toString$9(point)+",\n"})),result+="]\n",result},toCompactBinary:geometry=>{const points=geometry.points,transforms=geometry.transforms;let color=[-1,-1,-1,-1];geometry.color&&(color=geometry.color);const compacted=new Float32Array(22+2*points.length);compacted[0]=2,compacted[1]=transforms[0],compacted[2]=transforms[1],compacted[3]=transforms[2],compacted[4]=transforms[3],compacted[5]=transforms[4],compacted[6]=transforms[5],compacted[7]=transforms[6],compacted[8]=transforms[7],compacted[9]=transforms[8],compacted[10]=transforms[9],compacted[11]=transforms[10],compacted[12]=transforms[11],compacted[13]=transforms[12],compacted[14]=transforms[13],compacted[15]=transforms[14],compacted[16]=transforms[15],compacted[17]=geometry.isClosed?1:0,compacted[18]=color[0],compacted[19]=color[1],compacted[20]=color[2],compacted[21]=color[3];for(let j=0;j<points.length;j++){const ci=2*j+22,point=points[j];compacted[ci]=point[0],compacted[ci+1]=point[1]}return compacted},transform:(matrix,geometry)=>{const transforms=multiply$1([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],matrix,geometry.transforms);return Object.assign({},geometry,{transforms:transforms})},validate:object=>{if(!isA$2(object))throw new Error("invalid path2 structure");if(object.points.length>1)for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`path2 has duplicate point ${object.points[i]}`);if(object.points.forEach((point=>{if(!point.every(Number.isFinite))throw new Error(`path2 invalid point ${point}`)})),!object.transforms.every(Number.isFinite))throw new Error(`path2 invalid transforms ${object.transforms}`)}});const rgbToHex=(...values)=>{if((values=flatten$1(values)).length<3)throw new Error("values must contain R, G and B values");const r=255*values[0],g=255*values[1],b=255*values[2];let s=`#${Number(16777216+65536*r+256*g+b).toString(16).substring(1,7)}`;return values.length>3&&(s+=Number(255*values[3]).toString(16)),s},getPermutations=function(c){const permutations=[];for(let i=0;i<=c;i++)permutations.push(factorial(c)/(factorial(i)*factorial(c-i)));return permutations},factorial=function(b){let out=1;for(let i=2;i<=b;i++)out*=i;return out},valueAt=(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier valueAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierFunction(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierFunction(bezier,singleDimensionPoints,t))}return result}},bezierFunction=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<=n;i++)result+=bezier.permutations[i]*Math.pow(1-t,n-i)*Math.pow(t,i)*p[i];return result},bezierTangent=function(bezier,p,t){const n=p.length-1;let result=0;for(let i=0;i<n;i++){const q=n*(p[i+1]-p[i]);result+=bezier.tangentPermutations[i]*Math.pow(1-t,n-1-i)*Math.pow(t,i)*q}return result},lengths=(segments,bezier)=>{let sum=0;const lengths=[0];let previous=valueAt(0,bezier);for(let index=1;index<=segments;index++){const current=valueAt(index/segments,bezier);sum+=distanceBetween(current,previous),lengths.push(sum),previous=current}return lengths},distanceBetween=(a,b)=>{if(Number.isFinite(a)&&Number.isFinite(b))return Math.abs(a-b);if(Array.isArray(a)&&Array.isArray(b)){if(a.length!==b.length)throw new Error("The operands must have the same number of dimensions.");let sum=0;for(let i=0;i<a.length;i++)sum+=(b[i]-a[i])*(b[i]-a[i]);return Math.sqrt(sum)}throw new Error("The operands must be of the same type, either number or array.")};Object.freeze({__proto__:null,create:points=>{if(!Array.isArray(points))throw new Error("Bezier points must be a valid array/");if(points.length<2)throw new Error("Bezier points must contain at least 2 values.");const pointType=function(points){let firstPointType=null;return points.forEach((point=>{let pType="";if(Number.isFinite(point))pType="float_single";else{if(!Array.isArray(point))throw new Error("Bezier points must all be numbers or arrays of number.");point.forEach((val=>{if(!Number.isFinite(val))throw new Error("Bezier point values must all be numbers.")})),pType="float_"+point.length}if(null==firstPointType)firstPointType=pType;else if(firstPointType!==pType)throw new Error("Bezier points must be either all numbers or all arrays of numbers of the same size.")})),firstPointType}(points);return{points:points,pointType:pointType,dimensions:"float_single"===pointType?0:points[0].length,permutations:getPermutations(points.length-1),tangentPermutations:getPermutations(points.length-2)}},valueAt:valueAt,tangentAt:(t,bezier)=>{if(t<0||t>1)throw new Error("Bezier tangentAt() input must be between 0 and 1");if("float_single"===bezier.pointType)return bezierTangent(bezier,bezier.points,t);{const result=[];for(let i=0;i<bezier.dimensions;i++){const singleDimensionPoints=[];for(let j=0;j<bezier.points.length;j++)singleDimensionPoints.push(bezier.points[j][i]);result.push(bezierTangent(bezier,singleDimensionPoints,t))}return result}},lengths:lengths,length:(segments,bezier)=>lengths(segments,bezier)[segments],arcLengthToT:(options,bezier)=>{const{distance:distance,segments:segments}=Object.assign({},{distance:0,segments:100},options),arcLengths=lengths(segments,bezier);let startIndex=0,endIndex=segments;for(;startIndex<=endIndex;){const middleIndex=Math.floor(startIndex+(endIndex-startIndex)/2),diff=arcLengths[middleIndex]-distance;if(diff<0)startIndex=middleIndex+1;else{if(!(diff>0)){endIndex=middleIndex;break}endIndex=middleIndex-1}}const targetIndex=endIndex;if(arcLengths[targetIndex]===distance)return targetIndex/segments;const lengthBefore=arcLengths[targetIndex];return(targetIndex+(distance-lengthBefore)/(arcLengths[targetIndex+1]-lengthBefore))/segments}});const area$1=points=>{let area=0;for(let i=0;i<points.length;i++){const j=(i+1)%points.length;area+=points[i][0]*points[j][1],area-=points[j][0]*points[i][1]}return area/2},measureArea$1=polygon=>area$1(polygon.points),create$3=points=>((void 0===points||points.length<3)&&(points=[]),{points:points}),reverse$3=polygon=>{const points=polygon.points.slice().reverse();return create$3(points)},arePointsInside=(points,polygon)=>0===points.length||polygon.points.length<3?0:(measureArea$1(polygon)<0&&(polygon=reverse$3(polygon)),points.reduce(((acc,point)=>acc+isPointInside(point,polygon.points)),0)===points.length?1:0),isPointInside=(point,polygon)=>{const numPoints=polygon.length,tx=point[0],ty=point[1];let vtx0=polygon[numPoints-1],vtx1=polygon[0],yFlag0=vtx0[1]>ty,insideFlag=0,i=0;for(let j=numPoints+1;--j;){const yFlag1=vtx1[1]>ty;if(yFlag0!==yFlag1){const xFlag0=vtx0[0]>tx,xFlag1=vtx1[0]>tx;(xFlag0&&xFlag1||vtx1[0]-(vtx1[1]-ty)*(vtx0[0]-vtx1[0])/(vtx0[1]-vtx1[1])>=tx)&&(insideFlag=!insideFlag)}yFlag0=yFlag1,vtx0=vtx1,vtx1=polygon[++i]}return insideFlag},isA$1=object=>!!(object&&"object"==typeof object&&"points"in object&&Array.isArray(object.points)),crossBetweenSegments=(p1,p2,p3)=>{const X1=p2[0]-p1[0],Y1=p2[1]-p1[1],X2=p3[0]-p1[0];return X1*(p3[1]-p1[1])-Y1*X2};Object.freeze({__proto__:null,arePointsInside:arePointsInside,clone:polygon=>Object.assign({},polygon),create:create$3,isA:isA$1,isConvex:polygon=>{const numPoints=polygon.points.length;if(numPoints>2){const points=polygon.points;let prev=0,curr=0;for(let i=0;i<numPoints;i++)if(curr=crossBetweenSegments(points[i],points[(i+1)%numPoints],points[(i+2)%numPoints]),0!==curr){if(curr*prev<0)return!1;prev=curr}}return!0},isSimple:polygon=>{const numPoints=polygon.points.length;if(numPoints<3)return!1;if(3===numPoints)return!0;const points=polygon.points,found=new Set;if(points.forEach((v=>found.add(v.toString()))),found.size!==numPoints)return!1;for(let i=0;i<numPoints;i++)for(let j=i+2;j<numPoints;j++){const k=(j+1)%numPoints;if(i!==k){const s0=points[i],s1=points[(i+1)%numPoints],z0=points[j],z1=points[k];if(intersect$1(s0,s1,z0,z1))return!1}}return!0},measureArea:measureArea$1,measureBoundingBox:polygon=>{const points=polygon.points,numPoints=points.length,min=0===numPoints?[0,0]:clone$8(points[0]),max=clone$8(min);for(let i=1;i<numPoints;i++)min$1(min,min,points[i]),max$1(max,max,points[i]);return[min,max]},reverse:reverse$3,toPoints:polygon=>polygon.points,toString:polygon=>`poly2: [${polygon.points.map(toString$9).join(", ")}]`,transform:(matrix,polygon)=>{const points=polygon.points.map((point=>transform$b([0,0],point,matrix)));return isMirroring(matrix)&&points.reverse(),create$3(points)},validate:object=>{if(!isA$1(object))throw new Error("invalid poly2 structure");if(object.points.length<3)throw new Error(`poly2 not enough points ${object.points.length}`);if(measureArea$1(object)<=0)throw new Error("poly2 area must be greater than zero");for(let i=0;i<object.points.length;i++)if(equals$6(object.points[i],object.points[(i+1)%object.points.length]))throw new Error(`poly2 duplicate point at ${i}: [${object.points[i]}]`);object.points.forEach((point=>{if(2!==point.length)throw new Error(`poly2 invalid point ${point}`);if(!point.every(Number.isFinite))throw new Error(`poly2 invalid point ${point}`)}))}});const calculatePlane=slice=>{if(slice.contours.length<1)throw new Error("slices must have at least one contour to calculate a plane");const middle=[0,0,0];let n=0;slice.contours.forEach((contour=>{contour.forEach((vertex=>{add$1(middle,middle,vertex),n++}))})),scale$3(middle,middle,1/n);let farthestBefore,farthestVertex,farthestAfter,farthestContour=[],distance=0;slice.contours.forEach((contour=>{let prev=contour[contour.length-1];contour.forEach((vertex=>{if(!equals$7(prev,vertex)){const d=squaredDistance$1(middle,vertex);d>distance&&(farthestContour=contour,farthestBefore=prev,farthestVertex=vertex,distance=d)}prev=vertex}))}));let prev=farthestContour[farthestContour.length-1];for(let i=0;i<farthestContour.length;i++){const vertex=farthestContour[i];if(!equals$7(prev,vertex)&&equals$7(prev,farthestVertex)){farthestAfter=vertex;break}prev=vertex}return fromPoints$4([0,0,0,0],farthestBefore,farthestVertex,farthestAfter)},create$2=(contours=[])=>({contours:contours}),isA=object=>!!(object&&"object"==typeof object&&"contours"in object&&Array.isArray(object.contours));class Node$2{constructor(i,x,y){this.i=i,this.x=x,this.y=y,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}}const insertNode=(i,x,y,last)=>{const p=new Node$2(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p},removeNode=p=>{p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)},pointInTriangle=(ax,ay,bx,by,cx,cy,px,py)=>(cx-px)*(ay-py)-(ax-px)*(cy-py)>=0&&(ax-px)*(by-py)-(bx-px)*(ay-py)>=0&&(bx-px)*(cy-py)-(cx-px)*(by-py)>=0,area=(p,q,r)=>(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y),linkedPolygon=(data,start,end,dim,clockwise)=>{let last;if(clockwise===signedArea$1(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i,data[i],data[i+1],last);return last&&equals$2(last,last.next)&&(removeNode(last),last=last.next),last},filterPoints=(start,end)=>{if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals$2(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end},cureLocalIntersections=(start,triangles,dim)=>{let p=start;do{const a=p.prev,b=p.next.next;!equals$2(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i/dim),triangles.push(p.i/dim),triangles.push(b.i/dim),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)},locallyInside=(a,b)=>area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0,splitPolygon=(a,b)=>{const a2=new Node$2(a.i,a.x,a.y),b2=new Node$2(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2},isValidDiagonal=(a,b)=>a.next.i!==b.i&&a.prev.i!==b.i&&!((a,b)=>{let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1})(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&((a,b)=>{let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside})(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals$2(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0),intersects=(p1,q1,p2,q2)=>{const o1=Math.sign(area(p1,q1,p2)),o2=Math.sign(area(p1,q1,q2)),o3=Math.sign(area(p2,q2,p1)),o4=Math.sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||!(0!==o1||!onSegment(p1,p2,q1))||!(0!==o2||!onSegment(p1,q2,q1))||!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2))},onSegment=(p,q,r)=>q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y),signedArea$1=(data,start,end,dim)=>{let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum},equals$2=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y,eliminateHole=(hole,outerNode)=>{const bridge=findHoleBridge(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole),filteredBridge=filterPoints(bridge,bridge.next);return filterPoints(bridgeReverse,bridgeReverse.next),outerNode===bridge?filteredBridge:outerNode},findHoleBridge=(hole,outerNode)=>{let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;do{if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx){if(qx=x,x===hx){if(hy===p.y)return p;if(hy===p.next.y)return p.next}m=p.x<p.next.x?p:p.next}}p=p.next}while(p!==outerNode);if(!m)return null;if(hx===qx)return m;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&§orContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m},sectorContainsSector=(m,p)=>area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0,getLeftmost=start=>{let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost},earcutLinked=(ear,triangles,dim,minX,minY,invSize,pass)=>{if(!ear)return;!pass&&invSize&&indexCurve(ear,minX,minY,invSize);let prev,next,stop=ear;for(;ear.prev!==ear.next;)if(prev=ear.prev,next=ear.next,invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i/dim),triangles.push(ear.i/dim),triangles.push(next.i/dim),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?(ear=cureLocalIntersections(filterPoints(ear),triangles,dim),earcutLinked(ear,triangles,dim,minX,minY,invSize,2)):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}},isEar=ear=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;let p=ear.next.next;for(;p!==ear.prev;){if(pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0},isEarHashed=(ear,minX,minY,invSize)=>{const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const minTX=a.x<b.x?a.x<c.x?a.x:c.x:b.x<c.x?b.x:c.x,minTY=a.y<b.y?a.y<c.y?a.y:c.y:b.y<c.y?b.y:c.y,maxTX=a.x>b.x?a.x>c.x?a.x:c.x:b.x>c.x?b.x:c.x,maxTY=a.y>b.y?a.y>c.y?a.y:c.y:b.y>c.y?b.y:c.y,minZ=zOrder(minTX,minTY,minX,minY,invSize),maxZ=zOrder(maxTX,maxTY,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p!==ear.prev&&p!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n!==ear.prev&&n!==ear.next&&pointInTriangle(a.x,a.y,b.x,b.y,c.x,c.y,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0},splitEarcut=(start,triangles,dim,minX,minY,invSize)=>{let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize),void earcutLinked(c,triangles,dim,minX,minY,invSize)}b=b.next}a=a.next}while(a!==start)},indexCurve=(start,minX,minY,invSize)=>{let p=start;do{null===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,((list,fn)=>{let i,p,q,e,numMerges,inSize=1;do{p=list,list=null;let tail=null;for(numMerges=0;p;){numMerges++,q=p;let pSize=0;for(i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||fn(p)<=fn(q))?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1)})(p,(p=>p.z))},zOrder=(x,y,minX,minY,invSize)=>(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=32767*(x-minX)*invSize)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=32767*(y-minY)*invSize)|y<<8))|y<<4))|y<<2))|y<<1))<<1;class PolygonHierarchy{constructor(slice){this.plane=calculatePlane(slice);const rightVector=orthogonal([0,0,0],this.plane),perp=cross$1([0,0,0],this.plane,rightVector);this.v=normalize$1(perp,perp),this.u=cross$1([0,0,0],this.v,this.plane),this.basisMap=new Map;const projected=slice.contours.map((part=>part.map((v=>this.to2D(v))))),geometry=create$a(projected);this.roots=(geometry=>{const outlines=toOutlines(geometry),solids=[],holes=[];outlines.forEach(((outline,i)=>{const a=area$1(outline);a<0?holes.push(i):a>0&&solids.push(i)}));const children=[],parents=[];return solids.forEach(((s,i)=>{const solid=outlines[s];children[i]=[],holes.forEach(((h,j)=>{const hole=outlines[h];arePointsInside([hole[0]],create$3(solid))&&(children[i].push(h),parents[j]||(parents[j]=[]),parents[j].push(i))}))})),holes.forEach(((h,j)=>{if(parents[j]&&parents[j].length>1){const directParent=((list,score)=>{let bestIndex,best;return list.forEach(((item,index)=>{const value=score(item);(void 0===best||value<best)&&(bestIndex=index,best=value)})),bestIndex})(parents[j],(p=>children[p].length));parents[j].forEach(((p,i)=>{i!==directParent&&(children[p]=children[p].filter((c=>c!==h)))}))}})),children.map(((holes,i)=>({solid:outlines[solids[i]],holes:holes.map((h=>outlines[h]))})))})(geometry)}to2D(vector3){const vector2=fromValues$2(dot$2(vector3,this.u),dot$2(vector3,this.v));return this.basisMap.set(vector2,vector3),vector2}to3D(vector2){const original=this.basisMap.get(vector2);if(original)return original;{console.log("Warning: point not in original slice");const v1=scale$3([0,0,0],this.u,vector2[0]),v2=scale$3([0,0,0],this.v,vector2[1]),planeOrigin=scale$3([0,0,0],this.plane,this.plane[3]),v3=add$1(v1,v1,planeOrigin);return add$1(v2,v2,v3)}}}Object.freeze({__proto__:null,calculatePlane:calculatePlane,clone:slice=>Object.assign({},slice),create:create$2,equals:(a,b)=>{if(a.contours.length!==b.contours.length)return!1;const len=a.contours.length;for(let i=0;i<len;i++){const aVertex=a.contours[i];for(let j=0;j<len;j++){const bVertex=b.contours[j];if(!equals$7(aVertex,bVertex))return!1}}return!0},fromGeom2:geometry=>{const contours=toOutlines(geometry).map((outline=>outline.map((point=>fromVec2([0,0,0],point)))));return create$2(contours)},fromVertices:vertices=>{if(!Array.isArray(vertices))throw new Error("the given vertices must be an array");if(vertices.length<3)throw new Error("the given vertices must contain THREE or more vertices");const cloned=vertices.map((vertex=>3===vertex.length?vertex:fromVec2([0,0,0],vertex)));return create$2([cloned])},isA:isA,reverse:slice=>{const contours=slice.contours.map((contour=>contour.slice().reverse()));return create$2(contours)},toEdges:slice=>{const edges=[];return slice.contours.forEach((contour=>{contour.forEach(((vertex,i)=>{const next=contour[(i+1)%contour.length];edges.push([vertex,next])}))})),edges},toVertices:slice=>{const vertices=[];return slice.contours.forEach((contour=>{contour.forEach((vertex=>{vertices.push(vertex)}))})),vertices},toPolygons:slice=>{const hierarchy=new PolygonHierarchy(slice),polygons=[];return hierarchy.roots.forEach((({solid:solid,holes:holes})=>{let index=solid.length;const holesIndex=[];holes.forEach(((hole,i)=>{holesIndex.push(index),index+=hole.length}));const vertices=[solid,...holes].flat(),getVertex=i=>hierarchy.to3D(vertices[i]),indices=((data,holeIndices,dim=2)=>{const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedPolygon(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,maxX,maxY,invSize;if(hasHoles&&(outerNode=((data,holeIndices,outerNode,dim)=>{const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const start=holeIndices[i]*dim,end=i<len-1?holeIndices[i+1]*dim:data.length,list=linkedPolygon(data,start,end,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(((a,b)=>a.x-b.x));for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode),outerNode=filterPoints(outerNode,outerNode.next);return outerNode})(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=maxX=data[0],minY=maxY=data[1];for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?1/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize),triangles})(vertices.flat(),holesIndex);for(let i=0;i<indices.length;i+=3){const tri=indices.slice(i,i+3).map(getVertex);polygons.push(fromVerticesAndPlane(tri,hierarchy.plane))}})),polygons},toString:slice=>{let result="slice ("+slice.contours.length+" contours):\n[\n";return slice.contours.forEach((contour=>{result+=" ["+contour.map(toString$b).join()+"],\n"})),result+="]\n",result},transform:(matrix,slice)=>{const contours=slice.contours.map((contour=>contour.map((vertex=>transform$c([0,0,0],vertex,matrix)))));return create$2(contours)},validate:object=>{if(!isA(object))throw new Error("invalid slice structure");const slicePlane=calculatePlane(object);object.contours.forEach(((contour,i)=>{if(contour.length<3)throw new Error(`slice contour ${i} must contain at least 3 vertices`);const contourPlane=plane(create$7(contour));if(!equals$5(slicePlane,contourPlane))throw new Error("slice contours must be coplanar");for(let i=0;i<contour.length;i++){if(!contour[i].every(Number.isFinite))throw new Error(`slice contour ${i} must contain finite vertices`);const j=(i+1)%contour.length;if(equals$7(contour[i],contour[j]))throw new Error(`slice contour ${i} has duplicate vertex ${contour[i]}`)}}))}});const direction$1=line=>{const vector=normal([0,0],line);return negate(vector,vector),vector},origin$1=line=>scale$1([0,0],line,line[2]),copy$1=(out,line)=>(out[0]=line[0],out[1]=line[1],out[2]=line[2],out),fromPoints$1=(out,point1,point2)=>{const vector=subtract$1([0,0],point2,point1);normal(vector,vector),normalize(vector,vector);const distance=dot$1(point1,vector);return out[0]=vector[0],out[1]=vector[1],out[2]=distance,out},fromValues=(x,y,d)=>{const out=[0,1,0];return out[0]=x,out[1]=y,out[2]=d,out},solve2Linear=(a,b,c,d,u,v)=>{const invdet=1/(a*d-b*c);let x=u*d-b*v,y=-u*c+a*v;return x*=invdet,y*=invdet,[x,y]};Object.freeze({__proto__:null,clone:line=>{const out=[0,1,0];return out[0]=line[0],out[1]=line[1],out[2]=line[2],out},closestPoint:(line,point)=>{const orig=origin$1(line),dir=direction$1(line),v=subtract$1([0,0],point,orig),dist=dot$1(v,dir);return scale$1(v,dir,dist),add(v,v,orig),v},copy:copy$1,create:()=>[0,1,0],direction:direction$1,distanceToPoint:(line,point)=>{let distance=dot$1(point,line);return distance=Math.abs(distance-line[2]),distance},equals:(line1,line2)=>line1[0]===line2[0]&&line1[1]===line2[1]&&line1[2]===line2[2],fromPoints:fromPoints$1,fromValues:fromValues,intersectPointOfLines:(line1,line2)=>{const point=solve2Linear(line1[0],line1[1],line2[0],line2[1],line1[2],line2[2]);return clone$8(point)},origin:origin$1,reverse:(out,line)=>{const normal=negate([0,0],line),distance=-line[2];return copy$1(out,fromValues(normal[0],normal[1],distance))},toString:line=>`line2: (${line[0].toFixed(7)}, ${line[1].toFixed(7)}, ${line[2].toFixed(7)})`,transform:(out,line,matrix)=>{const org=origin$1(line),dir=direction$1(line);return transform$b(org,org,matrix),transform$b(dir,dir,matrix),fromPoints$1(out,org,dir)},xAtY:(line,y)=>{let x=(line[2]-line[1]*y)/line[0];return Number.isNaN(x)&&(x=origin$1(line)[0]),x}});const create=()=>[fromValues$3(0,0,0),fromValues$3(0,0,1)],closestPoint=(line,point)=>{const lPoint=line[0],lDirection=line[1],a=dot$2(subtract$3([0,0,0],point,lPoint),lDirection),b=dot$2(lDirection,lDirection),closestPoint=scale$3([0,0,0],lDirection,a/b);return add$1(closestPoint,closestPoint,lPoint),closestPoint},fromPointAndDirection=(out,point,direction)=>{const unit=normalize$1([0,0,0],direction);return copy$4(out[0],point),copy$4(out[1],unit),out};Object.freeze({__proto__:null,clone:line=>{const out=create();return copy$4(out[0],line[0]),copy$4(out[1],line[1]),out},closestPoint:closestPoint,copy:(out,line)=>(copy$4(out[0],line[0]),copy$4(out[1],line[1]),out),create:create,direction:line=>line[1],distanceToPoint:(line,point)=>{const closest=closestPoint(line,point),distanceVector=subtract$3([0,0,0],point,closest);return length$2(distanceVector)},equals:(line1,line2)=>!!equals$7(line1[1],line2[1])&&!!equals$7(line1[0],line2[0]),fromPlanes:(out,plane1,plane2)=>{let direction=cross$1([0,0,0],plane1,plane2),length=length$2(direction);if(length<EPS)throw new Error("parallel planes do not intersect");length=1/length,direction=scale$3(direction,direction,length);const absX=Math.abs(direction[0]),absY=Math.abs(direction[1]),absZ=Math.abs(direction[2]);let origin,r;return absX>=absY&&absX>=absZ?(r=solve2Linear(plane1[1],plane1[2],plane2[1],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(0,r[0],r[1])):absY>=absX&&absY>=absZ?(r=solve2Linear(plane1[0],plane1[2],plane2[0],plane2[2],plane1[3],plane2[3]),origin=fromValues$3(r[0],0,r[1])):(r=solve2Linear(plane1[0],plane1[1],plane2[0],plane2[1],plane1[3],plane2[3]),origin=fromValues$3(r[0],r[1],0)),fromPointAndDirection(out,origin,direction)},fromPointAndDirection:fromPointAndDirection,fromPoints:(out,point1,point2)=>{const direction=subtract$3([0,0,0],point2,point1);return fromPointAndDirection(out,point1,direction)},intersectPointOfLineAndPlane:(line,plane)=>{const pNormal=plane,pw=plane[3],lPoint=line[0],lDirection=line[1],labda=(pw-dot$2(pNormal,lPoint))/dot$2(pNormal,lDirection);return add$1([0,0,0],lPoint,scale$3([0,0,0],lDirection,labda))},origin:line=>line[0],reverse:(out,line)=>{const point=clone$9(line[0]),direction=negate$1([0,0,0],line[1]);return fromPointAndDirection(out,point,direction)},toString:line=>{const point=line[0],direction=line[1];return`line3: point: (${point[0].toFixed(7)}, ${point[1].toFixed(7)}, ${point[2].toFixed(7)}) direction: (${direction[0].toFixed(7)}, ${direction[1].toFixed(7)}, ${direction[2].toFixed(7)})`},transform:(out,line,matrix)=>{const point=line[0],direction=line[1],pointPlusDirection=add$1([0,0,0],point,direction),newPoint=transform$c([0,0,0],point,matrix),newPointPlusDirection=transform$c(pointPlusDirection,pointPlusDirection,matrix),newDirection=subtract$3(newPointPlusDirection,newPointPlusDirection,newPoint);return fromPointAndDirection(out,newPoint,newDirection)}});const 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},calculateEpsilonFromBounds=(bounds,dimensions)=>{let total=0;for(let i=0;i<dimensions;i++)total+=bounds[1][i]-bounds[0][i];return EPS*total/dimensions},createEdges=polygon=>{const vertices=toVertices$1(polygon),edges=[];for(let i=0;i<vertices.length;i++){const j=(i+1)%vertices.length,edge={v1:vertices[i],v2:vertices[j]};edges.push(edge)}for(let i=0;i<edges.length;i++){const j=(i+1)%vertices.length;edges[i].next=edges[j],edges[j].prev=edges[i]}return edges},insertEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.set(key,edge)},deleteEdge=(edges,edge)=>{const key=`${edge.v1}:${edge.v2}`;edges.delete(key)},findOppositeEdge=(edges,edge)=>{const key=`${edge.v2}:${edge.v1}`;return edges.get(key)},calculateAnglesBetween=(current,opposite,normal)=>{let v0=current.prev.v1,v1=current.prev.v2,v2=opposite.next.v2;const angle1=calculateAngle(v0,v1,v2,normal);return v0=opposite.prev.v1,v1=opposite.prev.v2,v2=current.next.v2,[angle1,calculateAngle(v0,v1,v2,normal)]},v1=[0,0,0],v2=[0,0,0],calculateAngle=(prevVertex,midVertex,nextVertex,normal)=>{const d0=subtract$3(v1,midVertex,prevVertex),d1=subtract$3(v2,nextVertex,midVertex);return cross$1(d0,d0,d1),dot$2(d0,normal)},mergePolygons=(epsilon,polygons)=>{const polygonsPerPlane=[];polygons.forEach((polygon=>{const mapping=polygonsPerPlane.find((element=>{return plane1=element[0],plane2=plane(polygon),Math.abs(plane1[3]-plane2[3])<15e-8&&(a=plane1,b=plane2,Math.abs(a[0]-b[0])<=1e-13&&Math.abs(a[1]-b[1])<=1e-13&&Math.abs(a[2]-b[2])<=1e-13);var a,b,plane1,plane2}));mapping?mapping[1].push(polygon):polygonsPerPlane.push([plane(polygon),[polygon]])}));let destPolygons=[];return polygonsPerPlane.forEach((mapping=>{const retesselatedPolygons=(sourcePolygons=>{if(sourcePolygons.length<2)return sourcePolygons;const normal=sourcePolygons[0].plane,polygons=sourcePolygons.slice(),edgeList=new Map;for(;polygons.length>0;){const polygon=polygons.shift(),edges=createEdges(polygon);for(let i=0;i<edges.length;i++){const current=edges[i],opposite=findOppositeEdge(edgeList,current);if(opposite){const angles=calculateAnglesBetween(current,opposite,normal);if(angles[0]>=0&&angles[1]>=0){const edge1=opposite.next,edge2=current.next;current.prev.next=opposite.next,current.next.prev=opposite.prev,opposite.prev.next=current.next,opposite.next.prev=current.prev,current.v1=null,current.v2=null,current.next=null,current.prev=null,deleteEdge(edgeList,opposite),opposite.v1=null,opposite.v2=null,opposite.next=null,opposite.prev=null;const mergeEdges=(list,e1,e2)=>{const newEdge={v1:e2.v1,v2:e1.v2,next:e1.next,prev:e2.prev};e2.prev.next=newEdge,e1.next.prev=newEdge,deleteEdge(list,e1),e1.v1=null,e1.v2=null,e1.next=null,e1.prev=null,deleteEdge(list,e2),e2.v1=null,e2.v2=null,e2.next=null,e2.prev=null};0===angles[0]&&mergeEdges(edgeList,edge1,edge1.prev),0===angles[1]&&mergeEdges(edgeList,edge2,edge2.prev)}}else current.next&&insertEdge(edgeList,current)}}const destPolygons=[];return edgeList.forEach((edge=>{const polygon=(edge=>{let polygon;const vertices=[];for(;edge.next;){const next=edge.next;vertices.push(edge.v1),edge.v1=null,edge.v2=null,edge.next=null,edge.prev=null,edge=next}return vertices.length>0&&(polygon=create$7(vertices)),polygon})(edge);polygon&&destPolygons.push(polygon)})),edgeList.clear(),destPolygons})(mapping[1]);destPolygons=destPolygons.concat(retesselatedPolygons)})),destPolygons},getTag=vertex=>`${vertex}`,addSide=(sideMap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),newSideTag=`${startTag}/${endTag}`,reverseSideTag=`${endTag}/${startTag}`;if(sideMap.has(reverseSideTag))return deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,vertex1,vertex0,null),null;const newSideObj={vertex0:vertex0,vertex1:vertex1,polygonIndex:polygonIndex};return sideMap.has(newSideTag)?sideMap.get(newSideTag).push(newSideObj):sideMap.set(newSideTag,[newSideObj]),vertextag2sidestart.has(startTag)?vertextag2sidestart.get(startTag).push(newSideTag):vertextag2sidestart.set(startTag,[newSideTag]),vertextag2sideend.has(endTag)?vertextag2sideend.get(endTag).push(newSideTag):vertextag2sideend.set(endTag,[newSideTag]),newSideTag},deleteSide=(sidemap,vertextag2sidestart,vertextag2sideend,vertex0,vertex1,polygonIndex)=>{const startTag=getTag(vertex0),endTag=getTag(vertex1),sideTag=`${startTag}/${endTag}`;let idx=-1;const sideObjs=sidemap.get(sideTag);for(let i=0;i<sideObjs.length;i++){const sideObj=sideObjs[i];let sideTag=getTag(sideObj.vertex0);if(sideTag===startTag&&(sideTag=getTag(sideObj.vertex1),sideTag===endTag&&(null===polygonIndex||sideObj.polygonIndex===polygonIndex))){idx=i;break}}sideObjs.splice(idx,1),0===sideObjs.length&&sidemap.delete(sideTag),idx=vertextag2sidestart.get(startTag).indexOf(sideTag),vertextag2sidestart.get(startTag).splice(idx,1),0===vertextag2sidestart.get(startTag).length&&vertextag2sidestart.delete(startTag),idx=vertextag2sideend.get(endTag).indexOf(sideTag),vertextag2sideend.get(endTag).splice(idx,1),0===vertextag2sideend.get(endTag).length&&vertextag2sideend.delete(endTag)},generalizeGeom3=(options,geometry)=>{const{snap:snap,simplify:simplify,triangulate:triangulate}=Object.assign({},{snap:!1,simplify:!1,triangulate:!1},options),epsilon=((...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>isA$2(geometry)||isA$5(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),2):isA$3(geometry)||isA(geometry)?calculateEpsilonFromBounds(measureBoundingBox(geometry),3):0));return 1===results.length?results[0]:results})(geometry);let polygons=toPolygons$1(geometry);snap&&(polygons=((epsilon,polygons)=>{let newPolygons=polygons.map((polygon=>{const snapVertices=polygon.vertices.map((vertex=>snap$2([0,0,0],vertex,epsilon))),newVertices=[];for(let i=0;i<snapVertices.length;i++){const j=(i+1)%snapVertices.length;equals$7(snapVertices[i],snapVertices[j])||newVertices.push(snapVertices[i])}const newPolygon=create$7(newVertices);return polygon.color&&(newPolygon.color=polygon.color),newPolygon}));const epsilonArea=epsilon*epsilon*Math.sqrt(3)/4;return newPolygons=newPolygons.filter((polygon=>((epsilon,polygon)=>{const area=Math.abs(measureArea$2(polygon));return Number.isFinite(area)&&area>epsilon})(epsilonArea,polygon))),newPolygons})(epsilon,polygons)),simplify&&(polygons=mergePolygons(0,polygons)),triangulate&&(polygons=(polygons=>{const sideMap=new Map;for(let polygonIndex=0;polygonIndex<polygons.length;polygonIndex++){const polygon=polygons[polygonIndex],numVertices=polygon.vertices.length;if(numVertices>=3){let vertex=polygon.vertices[0],vertexTag=getTag(vertex);for(let vertexIndex=0;vertexIndex<numVertices;vertexIndex++){let nextVertexIndex=vertexIndex+1;nextVertexIndex===numVertices&&(nextVertexIndex=0);const nextVertex=polygon.vertices[nextVertexIndex],nextVertexTag=getTag(nextVertex),sideTag=`${vertexTag}/${nextVertexTag}`,reverseSideTag=`${nextVertexTag}/${vertexTag}`;if(sideMap.has(reverseSideTag)){const ar=sideMap.get(reverseSideTag);ar.splice(-1,1),0===ar.length&&sideMap.delete(reverseSideTag)}else{const sideobj={vertex0:vertex,vertex1:nextVertex,polygonIndex:polygonIndex};sideMap.has(sideTag)?sideMap.get(sideTag).push(sideobj):sideMap.set(sideTag,[sideobj])}vertex=nextVertex,vertexTag=nextVertexTag}}else console.warn("warning: invalid polygon found during insertTjunctions")}if(sideMap.size>0){const vertextag2sidestart=new Map,vertextag2sideend=new Map,sidesToCheck=new Map;for(const[sidetag,sideObjs]of sideMap)sidesToCheck.set(sidetag,!0),sideObjs.forEach((sideObj=>{const starttag=getTag(sideObj.vertex0),endtag=getTag(sideObj.vertex1);vertextag2sidestart.has(starttag)?vertextag2sidestart.get(starttag).push(sidetag):vertextag2sidestart.set(starttag,[sidetag]),vertextag2sideend.has(endtag)?vertextag2sideend.get(endtag).push(sidetag):vertextag2sideend.set(endtag,[sidetag])}));const newPolygons=polygons.slice(0);for(;0!==sideMap.size;){for(const sideTag of sideMap.keys())sidesToCheck.set(sideTag,!0);let doneSomething=!1;for(;;){const sideTags=Array.from(sidesToCheck.keys());if(0===sideTags.length)break;const sideTagToCheck=sideTags[0];let doneWithSide=!0;if(sideMap.has(sideTagToCheck)){const sideObj=sideMap.get(sideTagToCheck)[0];for(let directionIndex=0;directionIndex<2;directionIndex++){const startVertex=0===directionIndex?sideObj.vertex0:sideObj.vertex1,endVertex=0===directionIndex?sideObj.vertex1:sideObj.vertex0,startVertexTag=getTag(startVertex),endVertexTag=getTag(endVertex);let matchingSides=[];0===directionIndex?vertextag2sideend.has(startVertexTag)&&(matchingSides=vertextag2sideend.get(startVertexTag)):vertextag2sidestart.has(startVertexTag)&&(matchingSides=vertextag2sidestart.get(startVertexTag));for(let matchingSideIndex=0;matchingSideIndex<matchingSides.length;matchingSideIndex++){const matchingSideTag=matchingSides[matchingSideIndex],matchingSide=sideMap.get(matchingSideTag)[0],matchingSideStartVertex=0===directionIndex?matchingSide.vertex0:matchingSide.vertex1;if(0===directionIndex?matchingSide.vertex1:matchingSide.vertex0,getTag(matchingSideStartVertex)===endVertexTag){deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,startVertex,endVertex,null),deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,startVertex,null),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}{const startPos=startVertex,endPos=endVertex,direction=subtract$3([0,0,0],matchingSideStartVertex,startPos),t=dot$2(subtract$3([0,0,0],endPos,startPos),direction)/dot$2(direction,direction);if(t>0&&t<1){const closestVertex=scale$3([0,0,0],direction,t);if(add$1(closestVertex,closestVertex,startPos),squaredDistance$1(closestVertex,endPos)<EPS*EPS){const polygonIndex=matchingSide.polygonIndex,polygon=newPolygons[polygonIndex],insertionVertexTag=getTag(matchingSide.vertex1);let insertionVertexTagIndex=-1;for(let i=0;i<polygon.vertices.length;i++)if(getTag(polygon.vertices[i])===insertionVertexTag){insertionVertexTagIndex=i;break}const newVertices=polygon.vertices.slice(0);newVertices.splice(insertionVertexTagIndex,0,endVertex);const newPolygon=create$7(newVertices);newPolygons[polygonIndex]=newPolygon,deleteSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,matchingSide.vertex1,polygonIndex);const newSideTag1=addSide(sideMap,vertextag2sidestart,vertextag2sideend,matchingSide.vertex0,endVertex,polygonIndex),newSideTag2=addSide(sideMap,vertextag2sidestart,vertextag2sideend,endVertex,matchingSide.vertex1,polygonIndex);null!==newSideTag1&&sidesToCheck.set(newSideTag1,!0),null!==newSideTag2&&sidesToCheck.set(newSideTag2,!0),doneWithSide=!1,directionIndex=2,doneSomething=!0;break}}}}}}doneWithSide&&sidesToCheck.delete(sideTagToCheck)}if(!doneSomething)break}polygons=newPolygons}return sideMap.clear(),polygons})(polygons),polygons=((epsilon,polygons)=>{const triangles=[];return polygons.forEach((polygon=>{((epsilon,polygon,triangles)=>{const nv=polygon.vertices.length;if(nv>3){if(nv>4){const midpoint=[0,0,0];polygon.vertices.forEach((vertex=>add$1(midpoint,midpoint,vertex))),snap$2(midpoint,divide$1(midpoint,midpoint,[nv,nv,nv]),epsilon);for(let i=0;i<nv;i++){const poly=create$7([midpoint,polygon.vertices[i],polygon.vertices[(i+1)%nv]]);polygon.color&&(poly.color=polygon.color),triangles.push(poly)}return}const poly0=create$7([polygon.vertices[0],polygon.vertices[1],polygon.vertices[2]]),poly1=create$7([polygon.vertices[0],polygon.vertices[2],polygon.vertices[3]]);return polygon.color&&(poly0.color=polygon.color,poly1.color=polygon.color),void triangles.push(poly0,poly1)}triangles.push(polygon)})(epsilon,polygon,triangles)})),triangles})(epsilon,polygons));const clone=Object.assign({},geometry);return clone.polygons=polygons,clone},flatten=arr=>arr.reduce(((acc,val)=>Array.isArray(val)?acc.concat(flatten(val)):acc.concat(val)),[]),contenttype='<?xml version="1.0" encoding="UTF-8" ?>\n<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">\n <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml">\n </Default>\n <Default Extension="model" ContentType="application/vnd.ms-package.3dmanufacturing-3dmodel+xml">\n </Default>\n</Types>',rels='<?xml version="1.0" encoding="UTF-8" ?>\n<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">\n <Relationship Target="/3D/3dmodel.model" Id="rel0" Type="http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel">\n </Relationship>\n</Relationships>',translateResources=(objects,options)=>{let resources=["resources",{},translateMaterials(objects,options)];return resources=resources.concat(translateObjects(objects,options)),resources},translateMaterials=(objects,options)=>{let basematerials=["basematerials",{id:"0"}];const materials=[];return objects.forEach(((object,i)=>{let srgb=rgbToHex(options.defaultcolor).toUpperCase();object.color&&(srgb=rgbToHex(object.color).toUpperCase()),materials.push(["base",{name:`mat${i}`,displaycolor:srgb}])})),basematerials=basematerials.concat(materials),basematerials},translateObjects=(objects,options)=>{const contents=[];return objects.forEach(((object,i)=>{index$6.isA(object)&&index$6.toPolygons(object).length>0&&(options.id=i,contents.push(convertToObject(object,options)))})),contents},translateBuild=(objects,options)=>{let build=["build",{}];const items=[];return objects.forEach(((object,i)=>{items.push(["item",{objectid:`${i+1}`}])})),build=build.concat(items),build},convertToObject=(object,options)=>{const name=object.name?object.name:`Part ${options.id}`;return["object",{id:`${options.id+1}`,type:"model",pid:"0",pindex:`${options.id}`,name:name},convertToMesh(object)]},convertToMesh=(object,options)=>["mesh",{},convertToVertices(object),convertToVolumes(object)],convertToVertices=(object,options)=>{const vertices=[];return index$6.toPolygons(object).forEach((polygon=>{for(let i=0;i<polygon.vertices.length;i++)vertices.push(convertToVertex(polygon.vertices[i]))})),["vertices",{}].concat(vertices)},convertToVertex=(vertex,options)=>["vertex",{x:vertex[0],y:vertex[1],z:vertex[2]}],convertToVolumes=(object,options)=>{let n=0;const polygons=index$6.toPolygons(object);let contents=["triangles",{}];return polygons.forEach((polygon=>{if(polygon.vertices.length<3)return;const triangles=convertToTriangles(polygon,n);contents=contents.concat(triangles),n+=polygon.vertices.length})),contents},convertToTriangles=(polygon,index)=>{const contents=[];for(let i=0;i<polygon.vertices.length-2;i++){const triangle=["triangle",{v1:index,v2:index+i+1,v3:index+i+2}];contents.push(triangle)}return contents};exports.mimeType="model/3mf",exports.serialize=(options,...objects)=>{options=Object.assign({},{unit:"millimeter",metadata:!0,defaultcolor:[1,160/255,0,1],compress:!0},options);const objects3d=(objects=flatten(objects)).filter((object=>index$6.isA(object)));if(0===objects3d.length)throw new Error("only 3D geometries can be serialized to 3MF");var array;objects.length!==objects3d.length&&console.warn("some objects could not be serialized to 3MF"),array=((options,...geometries)=>{if(0===(geometries=flatten$1(geometries)).length)throw new Error("wrong number of arguments");const results=geometries.map((geometry=>{if(isA$2(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$5(geometry))return((options,geometry)=>geometry)(0,geometry);if(isA$3(geometry))return generalizeGeom3(options,geometry);throw new Error("invalid geometry")}));return 1===results.length?results[0]:results})({snap:!0,triangulate:!0},objects3d),objects=Array.isArray(array)?array:null==array?[]:[array];const body=["model",{unit:options.unit,"xml:lang":"und"},["metadata",{name:"Application"},"JSCAD"]];options.metadata&&body.push(["metadata",{name:"CreationDate"},(new Date).toISOString()]),body.push(translateResources(objects,options)),body.push(translateBuild(objects));const xml=`<?xml version="1.0" encoding="UTF-8"?>\n${stringify(body,2)}`;return options.compress?[zipSync({"3D":{"3dmodel.model":strToU8(xml)},_rels:{".rels":strToU8(rels)},"[Content_Types].xml":strToU8(contenttype)},{comment:"created by JSCAD"}).buffer]:[xml]},Object.defineProperty(exports,"__esModule",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).jscad3mfSerializer={});
|
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/3mf-serializer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.0",
|
|
4
4
|
"description": "3MF serializer for JSCAD project",
|
|
5
5
|
"homepage": "https://openjscad.xyz/",
|
|
6
6
|
"repository": "https://github.com/jscad/OpenJSCAD.org",
|
|
7
|
+
"type": "module",
|
|
7
8
|
"main": "src/index.js",
|
|
9
|
+
"unpkg": "dist/jscad-3mf-serializer.min.js",
|
|
10
|
+
"module": "dist/jscad-3mf-serializer.es.js",
|
|
8
11
|
"scripts": {
|
|
9
|
-
"
|
|
10
|
-
"
|
|
12
|
+
"build": "rollup --config",
|
|
13
|
+
"coverage": "c8 --reporter=html --reporter=text pnpm test",
|
|
14
|
+
"test": "ava --concurrency 3 --verbose --timeout 40000 './tests/*.test.js'",
|
|
15
|
+
"version": "pnpm run build && git add dist"
|
|
11
16
|
},
|
|
12
17
|
"contributors": [
|
|
13
18
|
{
|
|
14
19
|
"name": "z3dev",
|
|
15
|
-
"url": "
|
|
20
|
+
"url": "https://github.com/z3dev"
|
|
16
21
|
}
|
|
17
22
|
],
|
|
18
23
|
"keywords": [
|
|
@@ -27,14 +32,20 @@
|
|
|
27
32
|
"access": "public"
|
|
28
33
|
},
|
|
29
34
|
"dependencies": {
|
|
30
|
-
"@jscad/array-utils": "
|
|
31
|
-
"@jscad/
|
|
32
|
-
"
|
|
33
|
-
"
|
|
35
|
+
"@jscad/array-utils": "3.0.0-alpha.0",
|
|
36
|
+
"@jscad/io-utils": "^3.0.0-alpha.0",
|
|
37
|
+
"@jscad/modeling": "3.0.0-alpha.0",
|
|
38
|
+
"fflate": "^0.7.3",
|
|
39
|
+
"onml": "^1.2.0"
|
|
34
40
|
},
|
|
35
41
|
"devDependencies": {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
42
|
+
"@rollup/plugin-commonjs": "^23.0.4",
|
|
43
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
44
|
+
"@rollup/plugin-terser": "^0.4.3",
|
|
45
|
+
"ava": "^4.3.3",
|
|
46
|
+
"c8": "^8.0.0",
|
|
47
|
+
"rollup": "^2.79.1",
|
|
48
|
+
"rollup-plugin-banner": "^0.2.1"
|
|
38
49
|
},
|
|
39
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "3656d36ed9cd738ab884e86aae5a2ce08d52adf7"
|
|
40
51
|
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import banner from 'rollup-plugin-banner'
|
|
2
|
+
import commonjs from '@rollup/plugin-commonjs'
|
|
3
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
|
4
|
+
import terser from '@rollup/plugin-terser'
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
input: 'src/index.js',
|
|
8
|
+
|
|
9
|
+
output: [
|
|
10
|
+
{
|
|
11
|
+
file: 'dist/jscad-3mf-serializer.min.js',
|
|
12
|
+
format: 'umd',
|
|
13
|
+
name: 'jscad3mfSerializer'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
file: 'dist/jscad-3mf-serializer.es.js',
|
|
17
|
+
format: 'es'
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
|
|
21
|
+
plugins: [
|
|
22
|
+
commonjs(),
|
|
23
|
+
nodeResolve(),
|
|
24
|
+
banner('<%= pkg.description %>\n@module <%= pkg.name %>\n@version <%= pkg.version %>\n@license <%= pkg.license %>'),
|
|
25
|
+
terser({ compress: { module: true }, mangle: false, format: { comments: 'some'} })
|
|
26
|
+
]
|
|
27
|
+
}
|
package/src/index.js
CHANGED
|
@@ -1,21 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
JSCAD Object to 3MF (XML) Format Serialization
|
|
3
|
-
|
|
4
|
-
## License
|
|
5
|
-
|
|
6
|
-
Copyright (c) 2022 JSCAD Organization https://github.com/jscad
|
|
7
|
-
|
|
8
|
-
All code released under MIT license
|
|
9
|
-
|
|
10
|
-
Notes:
|
|
11
|
-
1) geom2 conversion to:
|
|
12
|
-
none
|
|
13
|
-
2) geom3 conversion to:
|
|
14
|
-
mesh
|
|
15
|
-
3) path2 conversion to:
|
|
16
|
-
none
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
1
|
/**
|
|
20
2
|
* Serializer of JSCAD geometries to 3D manufacturing format (XML)
|
|
21
3
|
*
|
|
@@ -30,38 +12,34 @@ Notes:
|
|
|
30
12
|
* const { serializer, mimeType } = require('@jscad/3mf-serializer')
|
|
31
13
|
*/
|
|
32
14
|
|
|
15
|
+
import { zipSync, strToU8 } from 'fflate'
|
|
33
16
|
|
|
34
|
-
|
|
35
|
-
const strToU8 = require('fflate').strToU8
|
|
36
|
-
|
|
37
|
-
const stringify = require('onml/lib/stringify')
|
|
38
|
-
|
|
39
|
-
const { colors, geometries, modifiers } = require('@jscad/modeling')
|
|
40
|
-
const { flatten, toArray } = require('@jscad/array-utils')
|
|
17
|
+
import { stringify } from '@jscad/io-utils'
|
|
41
18
|
|
|
19
|
+
import { geom3, rgbToHex, generalize } from '@jscad/modeling'
|
|
20
|
+
import { flatten, toArray } from '@jscad/array-utils'
|
|
42
21
|
|
|
43
22
|
const mimeType = 'model/3mf'
|
|
44
|
-
const fileExtension = '3mf'
|
|
45
23
|
|
|
46
24
|
/**
|
|
47
25
|
* Serialize the give objects to 3MF contents (XML) or 3MF packaging (OPC).
|
|
48
26
|
* @see https://3mf.io/specification/
|
|
49
27
|
* @param {Object} [options] - options for serialization
|
|
50
|
-
* @param {String} [options.unit='millimeter'] - unit of design; millimeter, inch, feet, meter or micrometer
|
|
28
|
+
* @param {String} [options.unit='millimeter'] - unit of design; micron, millimeter, inch, feet, meter or micrometer
|
|
51
29
|
* @param {Boolean} [options.metadata=true] - add metadata to 3MF contents, such at CreationDate
|
|
52
30
|
* @param {Array} [options.defaultcolor=[0,0,0,1]] - default color for objects
|
|
53
31
|
* @param {Boolean} [options.compress=true] - package and compress the contents
|
|
54
32
|
* @param {Object|Array} objects - objects to serialize into 3D manufacturing format
|
|
55
33
|
* @returns {Array} serialized contents, 3MF contents (XML) or 3MF packaging (ZIP)
|
|
56
34
|
* @example
|
|
57
|
-
* const geometry =
|
|
35
|
+
* const geometry = cube()
|
|
58
36
|
* const package = serializer({unit: 'meter'}, geometry) // 3MF package, ZIP format
|
|
59
37
|
*/
|
|
60
38
|
const serialize = (options, ...objects) => {
|
|
61
39
|
const defaults = {
|
|
62
|
-
unit: 'millimeter',
|
|
40
|
+
unit: 'millimeter',
|
|
63
41
|
metadata: true,
|
|
64
|
-
defaultcolor: [255/255, 160/255, 0, 1], // JSCAD
|
|
42
|
+
defaultcolor: [255 / 255, 160 / 255, 0, 1], // JSCAD orange
|
|
65
43
|
compress: true
|
|
66
44
|
}
|
|
67
45
|
options = Object.assign({}, defaults, options)
|
|
@@ -69,13 +47,13 @@ const serialize = (options, ...objects) => {
|
|
|
69
47
|
objects = flatten(objects)
|
|
70
48
|
|
|
71
49
|
// convert only 3D geometries
|
|
72
|
-
|
|
50
|
+
const objects3d = objects.filter((object) => geom3.isA(object))
|
|
73
51
|
|
|
74
52
|
if (objects3d.length === 0) throw new Error('only 3D geometries can be serialized to 3MF')
|
|
75
53
|
if (objects.length !== objects3d.length) console.warn('some objects could not be serialized to 3MF')
|
|
76
54
|
|
|
77
55
|
// convert to triangles
|
|
78
|
-
objects = toArray(
|
|
56
|
+
objects = toArray(generalize({ snap: true, triangulate: true }, objects3d))
|
|
79
57
|
|
|
80
58
|
// construct the contents of the 3MF 'model'
|
|
81
59
|
const body = ['model',
|
|
@@ -101,7 +79,7 @@ ${stringify(body, 2)}`
|
|
|
101
79
|
'3D': {
|
|
102
80
|
'3dmodel.model': strToU8(xml)
|
|
103
81
|
},
|
|
104
|
-
|
|
82
|
+
_rels: {
|
|
105
83
|
'.rels': strToU8(rels)
|
|
106
84
|
},
|
|
107
85
|
'[Content_Types].xml': strToU8(contenttype)
|
|
@@ -140,9 +118,9 @@ const translateMaterials = (objects, options) => {
|
|
|
140
118
|
|
|
141
119
|
const materials = []
|
|
142
120
|
objects.forEach((object, i) => {
|
|
143
|
-
let srgb =
|
|
121
|
+
let srgb = rgbToHex(options.defaultcolor).toUpperCase()
|
|
144
122
|
if (object.color) {
|
|
145
|
-
srgb =
|
|
123
|
+
srgb = rgbToHex(object.color).toUpperCase()
|
|
146
124
|
}
|
|
147
125
|
materials.push(['base', { name: `mat${i}`, displaycolor: srgb }])
|
|
148
126
|
})
|
|
@@ -154,8 +132,8 @@ const translateMaterials = (objects, options) => {
|
|
|
154
132
|
const translateObjects = (objects, options) => {
|
|
155
133
|
const contents = []
|
|
156
134
|
objects.forEach((object, i) => {
|
|
157
|
-
if (
|
|
158
|
-
const polygons =
|
|
135
|
+
if (geom3.isA(object)) {
|
|
136
|
+
const polygons = geom3.toPolygons(object)
|
|
159
137
|
if (polygons.length > 0) {
|
|
160
138
|
options.id = i
|
|
161
139
|
contents.push(convertToObject(object, options))
|
|
@@ -200,7 +178,7 @@ const convertToVertices = (object, options) => {
|
|
|
200
178
|
const contents = ['vertices', {}]
|
|
201
179
|
|
|
202
180
|
const vertices = []
|
|
203
|
-
const polygons =
|
|
181
|
+
const polygons = geom3.toPolygons(object)
|
|
204
182
|
polygons.forEach((polygon) => {
|
|
205
183
|
for (let i = 0; i < polygon.vertices.length; i++) {
|
|
206
184
|
vertices.push(convertToVertex(polygon.vertices[i], options))
|
|
@@ -221,7 +199,7 @@ const convertToVertex = (vertex, options) => {
|
|
|
221
199
|
|
|
222
200
|
const convertToVolumes = (object, options) => {
|
|
223
201
|
let n = 0
|
|
224
|
-
const polygons =
|
|
202
|
+
const polygons = geom3.toPolygons(object)
|
|
225
203
|
|
|
226
204
|
let contents = ['triangles', {}]
|
|
227
205
|
polygons.forEach((polygon) => {
|
|
@@ -249,8 +227,7 @@ const convertToTriangles = (polygon, index) => {
|
|
|
249
227
|
return contents
|
|
250
228
|
}
|
|
251
229
|
|
|
252
|
-
|
|
253
|
-
serialize,
|
|
230
|
+
export {
|
|
254
231
|
mimeType,
|
|
255
|
-
|
|
232
|
+
serialize
|
|
256
233
|
}
|
package/tests/serialize.test.js
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
import test from 'ava'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { colorize, cube, cuboid, geom3 } from '@jscad/modeling'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
import { serialize } from '../src/index.js'
|
|
6
6
|
|
|
7
7
|
test('serialize (empty)', (t) => {
|
|
8
|
-
const emptyShape =
|
|
9
|
-
const buffer =
|
|
8
|
+
const emptyShape = geom3.create()
|
|
9
|
+
const buffer = serialize({ metadata: false, compress: false }, emptyShape)
|
|
10
10
|
t.deepEqual(buffer, expected1)
|
|
11
11
|
})
|
|
12
12
|
|
|
13
13
|
test('serialize (single)', (t) => {
|
|
14
|
-
const cube1 =
|
|
15
|
-
const buffer =
|
|
14
|
+
const cube1 = cube()
|
|
15
|
+
const buffer = serialize({ metadata: false, compress: false }, cube1)
|
|
16
16
|
t.deepEqual(buffer, expected2)
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
test('serialize (single, color)', (t) => {
|
|
20
|
-
let cube1 =
|
|
21
|
-
cube1 =
|
|
22
|
-
const buffer =
|
|
20
|
+
let cube1 = cube()
|
|
21
|
+
cube1 = colorize([1.0, 0.0, 0.5, 0.8], cube1)
|
|
22
|
+
const buffer = serialize({ metadata: false, compress: false, unit: 'inch' }, cube1)
|
|
23
23
|
t.deepEqual(buffer, expected3)
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
test('serialize (multiple, color)', (t) => {
|
|
27
|
-
let cube1 =
|
|
28
|
-
cube1 =
|
|
29
|
-
cube1.name =
|
|
30
|
-
const cube2 =
|
|
31
|
-
cube2.name =
|
|
32
|
-
const buffer =
|
|
27
|
+
let cube1 = cuboid({ size: [4, 5, 6], center: [5, 5, 5] })
|
|
28
|
+
cube1 = colorize([0.0, 0.0, 1.0, 0.8], cube1)
|
|
29
|
+
cube1.name = 'CUBE A'
|
|
30
|
+
const cube2 = cube()
|
|
31
|
+
cube2.name = 'CUBE B'
|
|
32
|
+
const buffer = serialize({ metadata: false, compress: false, defaultcolor: [1, 0, 0, 1] }, cube1, cube2)
|
|
33
33
|
t.deepEqual(buffer, expected4)
|
|
34
34
|
})
|
|
35
35
|
|
|
36
36
|
test('serialize (multiple, compress)', (t) => {
|
|
37
|
-
const cube1 =
|
|
38
|
-
cube1.name =
|
|
39
|
-
const cube2 =
|
|
40
|
-
cube2.name =
|
|
37
|
+
const cube1 = colorize([1.0, 0.0, 0.5, 0.8], cube())
|
|
38
|
+
cube1.name = 'CUBE A'
|
|
39
|
+
const cube2 = cuboid({ size: [4, 5, 6], center: [5, 5, 5] })
|
|
40
|
+
cube2.name = 'CUBE B'
|
|
41
41
|
|
|
42
|
-
const results =
|
|
42
|
+
const results = serialize({ compress: true }, cube1, cube2)
|
|
43
43
|
t.is(results.length, 1)
|
|
44
44
|
const len = results[0].byteLength
|
|
45
45
|
t.true(len > 1600)
|