diff --git a/js/democapsid.min.js b/js/democapsid.min.js index 228b7e6..d32ec87 100644 --- a/js/democapsid.min.js +++ b/js/democapsid.min.js @@ -1,6 +1,6 @@ /*! - * democapsid v2.2.1 - Render viral capsids in the browser and export SVG. + * democapsid v2.2.2 - Render viral capsids in the browser and export SVG. * MIT License * Copyright (c) 2020 - 2024, Daniel Antonio Negrón (dnanto/remaindeer) */ -const t="2.2.1",e=Math.sqrt(3),r=Math.sqrt(5),o=(1+r)/2,a=100,n=1e-15,s=1e-5;function mmul(t,e){const[r,o,a]=[t.length,t[0].length,e[0].length];for(var n=new Array(r),s=0;sArray.from({length:t.length},(()=>[])))),r=0;r[new paper.Path.RegularPolygon({center:t.coor,sides:6,radius:r,data:{mer:1}})],radius:r};else if("trihex"===t)a={basis:[[2*r,0],[r,r*e]],tile:t=>[new paper.Path.RegularPolygon({center:t.coor,sides:6,radius:r,data:{mer:1}}).rotate(30),...Array.from({length:2},((e,a)=>new paper.Path.RegularPolygon({center:t.coor.add([r,-1/3*o]),sides:3,radius:2/3*o,data:{mer:2}}).rotate(180).rotate(60*a,t.coor)))],radius:2*o};else if("snubhex"===t)a={basis:[[2.5*r,o],[.5*r,3*o]],tile:t=>[new paper.Path.RegularPolygon({center:t.coor,sides:6,radius:r,data:{mer:1}}).rotate(30),...Array.from({length:6},((e,r)=>new paper.Path.RegularPolygon({center:t.coor.add([0,-o-1/3*o]),sides:3,radius:2/3*o,data:{mer:2}}).rotate(60*r,t.coor))),new paper.Path.RegularPolygon({center:t.coor.add([1.5*r,-1/3*o]),sides:3,radius:2/3*o,data:{mer:2}}),new paper.Path.RegularPolygon({center:t.coor.add([-1.5*r,2/3*o]),sides:3,radius:2/3*o,data:{mer:2}}).rotate(180)],radius:2*o};else if("rhombitrihex"===t)a={basis:[[r+o+.5*r,.5*r+o],[0,2*o+r]],tile:t=>[new paper.Path.RegularPolygon({center:t.coor,sides:6,radius:r,data:{mer:1}}).rotate(30),...Array.from({length:3},((o,a)=>new paper.Path.RegularPolygon({center:t.coor.add([0,r+r*(e/3)]),sides:3,radius:r/e,data:{mer:2}}).rotate(-60*a-30,t.coor))),...Array.from({length:3},((e,a)=>new paper.Path.RegularPolygon({center:t.coor.add([0,-o-.5*r]),sides:4,radius:Math.sqrt(2*r*r)/2,data:{mer:3}}).rotate(60*a,t.coor)))],radius:Math.sqrt(Math.pow(o+r,2)+Math.pow(r/2,2))};else if("dualhex"===t)a={basis:[[1.5*r,o],[0,2*o]],tile:t=>Array.from({length:6},((a,n)=>new paper.Path.RegularPolygon({center:t.coor.add([0,o-r*e/6]),sides:3,radius:r/e,data:{mer:1}}).rotate(60*n,t.coor))),radius:r};else if("dualtrihex"===t)a={basis:[[2*o,0],[o,e*o]],tile:t=>[...Array.from({length:6},((e,a)=>new paper.Path({segments:[[0,0],[.5*o,-.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)],[o,0],[.5*o,.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)]].map((e=>t.coor.add(e))),closed:!0,data:{mer:1}}).rotate(60*a,t.coor))),...Array.from({length:6},((e,a)=>new paper.Path({segments:[[-.5*o,.5*r+.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)],[0,.5*r],[o-.5*o,.5*r+.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)],[0,.5*r+.25*r*Math.sin(Math.PI/6)*2/Math.cos(Math.PI/3)]].map((e=>t.coor.add(e))),closed:!0,data:{mer:2}}).rotate(60*a,t.coor)))],radius:r};else if("dualsnubhex"===t)a={basis:[[2.5*r,o],[.5*r,2*o+r*e/3*2-r*e/6]],tile:t=>Array.from({length:6},((a,n)=>new paper.Path({segments:[[0,0],[0,o+r*e/6],[.5*r,o+r*e/3],[r,o+r*e/6],[r,r*e/3]].map((e=>t.coor.add(e))),closed:!0,data:{mer:1}}).rotate(60*n,t.coor))),radius:o+r*e/3};else{if("dualrhombitrihex"!==t)throw new Error("incorrect tile mode");a={basis:[[1.5*r,o],[0,2*o]],tile:t=>Array.from({length:6},((a,n)=>new paper.Path({segments:[[0,0],[0,o],[.5*r,o],[e/2*o,.5*o]].map((e=>t.coor.add(e))),closed:!0,data:{mer:1}}).rotate(60*n,t.coor))),radius:r}}return a}function*tile_grid(t,e){const r=t.map((t=>mmul(T(inv2(e)),[t,1].flat().T()).flat())).map((t=>t.map(Math.round))),[o,a,n,s]=[...[0,1].map(((t,e)=>Math.min(...r.map((t=>t[e]))))),...[0,1].map(((t,e)=>Math.max(...r.map((t=>t[e])))))];for(let i=o;ie.sub(t)));return t.add(a.cross(n).mul(s.norm()**2).add(s.cross(a).mul(n.norm()**2)).add(n.cross(s).mul(a.norm()**2)).div(2*det3([a,n,s])))}function body_radius(t){return t[6].sub([0,0,t[6][2]]).norm()}function height(t){return t[0][2]-t[19][2]}function body_height(t){return t[4][2]-t[6][2]}function sd_sphere(t,e){return t.norm()-e}function spherize(t,e,r){return t.uvec().mul(Math.abs(sd_sphere(t,e))*r).add(t)}function cylinderize(t,e,r,o){const[a,n]=[body_radius(e),body_height(e)/2];let s,i;if(5===r)s=[0,0,n-a/2],i=e[0][2]+a/2-n;else if(3===r){const[t,r]=[e[0],e[3]];s=triangle_circumcircle_center(t,r,[r[0],-r[1],r[2]]),i=t.sub(s).norm()}else 2===r&&(p1=e[0],s=tetrahedron_circumsphere_center(p1,...[1,4,5].map((t=>e[t]))),i=p1.sub(s).norm());const[c,l,d,u]=[[0,0,s[2]],[0,0,-s[2]],[0,0,n],[0,0,-n]];if(n[t,e[r]])))}function ico_axis_5(t){const[e,o]=[t[0].norm(),t[1].norm()],a=e*Math.sqrt((5+r)/10),n=[0,0,(1+r)*e/(2*Math.sqrt(5+2*r))],s=[-a,0,0].roro([0,0,1],.3*Math.PI),i=s.add([e,0,0]),c=t[0].angle(t[1]),l=i.add([o,0,0].roro([0,1,0],-Math.PI-c)),d=s.add(l.sub(s).proj(i.sub(s))),u=[d[0],-Math.abs(d[1])*Math.sqrt(a*a*d[1]*d[1]-(d[0]*d[1])**2)/(d[1]*d[1]),0];if(Number.isNaN(u[1]))throw new Error("impossible construction!");const p=u.add([0,0,-Math.sqrt(l[2]*l[2]-(d[1]-u[1])**2)]);return[n,s,i].concat([1,2,3].map((t=>i.roro([0,0,1],2*t/5*Math.PI)))).concat([p]).concat([1,2,3,4].map((t=>p.roro([0,0,1],2*t/5*Math.PI)))).concat([[0,0,p[2]-n[2]]]).map((t=>t.add([0,0,-p[2]/2])))}function ico_axis_3(t,r=a,o=n){const[s,i,c]=[t[0].norm(),t[1].norm(),t[2].sub(t[1]).norm()],l=[0,s*(1/e),0],d=[s/2,-s*(e/6),0],u=[-s/2,-s*(e/6),0],p=[0,-s*(2*e/3),0];function fold(a){let[n,l]=[p.uvec().mul(s*(e/2)),d.sub(u).uvec()];const h=[0,-s*(e/6),0].add(n.roro(l,a)),m=h.roro([0,0,1],2/3*Math.PI);a=t[0].angle(t[1]),[n,l]=[h.sub(d).uvec().mul(i),h.cross(d).uvec()];const _=n.roro(l,a),[g,b]=[d.add(_.proj(n)),d.add(_)];[n,l]=[b.sub(g),d.sub(h).uvec()];const f=t=>c-g.add(n.roro(l,t)).sub(m).norm();brackets(f,0,2*Math.PI,r).next().value;a=bisection(f,...brackets(f,0,2*Math.PI,r).next().value,o,r).slice(-1);const y=g.add(n.roro(l,a));return[h,m,y,Math.abs(h[1])-y.sub([0,0,y[2]]).norm()]}const h=Math.PI/180/10;let m=0;for(let e=0;e*hfold(t).slice(-1)[0];try{m=bisection(obj,...brackets(obj,m,Math.PI/4,r).next().value,o,r).slice(-1)}catch(P){throw new Error("impossible construction!")}const[_,g,b]=fold(m).slice(0,-1);if(Number.isNaN(_[0]))throw new Error("impossible construction!");const y=[0,0,1];m=2*Math.PI/3;const M=b.roro(y,-m),w=M.sub([0,0,M[2]]).roro(y,Math.PI/3).uvec().mul(l[1]).add([0,0,M[2]+_[2]-l[2]]);let v=[l,d,u,_,g.roro(y,m),g,b,M,M.roro(y,-m),w,w.roro(y,-m),w.roro(y,-2*m)];return v.map((t=>t.add([0,0,(v[0][2]-v.slice(-1)[0][2])/2])))}function ico_axis_2(t,e=a,r=n){const[s,i,c]=[t[0].norm(),t[1].norm(),t[2].sub(t[1]).norm()],l=[s/2,0,0],d=[-s/2,0,0],u=[0,-s*o/2,-(s*o-s)/2],p=[0,s*o/2,-(s*o-s)/2];function fold(o){let a=d.add(u).div(2),[n,s]=[a.sub(l),u.sub(d).uvec()];const p=a.add(n.roro(s,o)),h=p.roro([0,0,1],Math.PI);o=t[0].angle(t[1]),[n,s]=[u.sub(l).uvec().mul(i),u.cross(l).uvec()];const m=n.roro(s,o);a=l.add(m.proj(n));const _=l.add(m);[n,s]=[_.sub(a),l.sub(u).uvec()];const f=t=>c-a.add(n.roro(s,t)).sub(h).norm();o=bisection(f,...brackets(f,0,2*Math.PI,e).next().value,r,e).slice(-1);const g=a.add(n.roro(s,o));return[p,h,g,p.sub([0,0,p[2]]).norm()-g.sub([0,0,g[2]]).norm()]}const h=Math.PI/180/10;let m=0;for(let o=0;o*hfold(t).slice(-1)[0];try{m=bisection(obj,...brackets(obj,m,Math.PI/4,e).next().value,r,e).slice(-1)}catch(w){throw new Error("impossible construction!")}const[_,g,b]=fold(m).slice(0,-1);if(Number.isNaN(_[0]))throw new Error("impossible construction!");obj=t=>l.roro([0,0,1],t).add([0,0,b[2]+_[2]]).sub(g).norm()-i;try{m=bisection(obj,...brackets(obj,0,2*Math.PI,e).next().value,r,e).slice(-1)}catch(w){throw new Error("impossible construction!")}const y=l.roro([0,0,1],m).add([0,0,b[2]+_[2]]),M=y.sub([0,0,y[2]]).uvec().roro([0,0,1],Math.PI/2).mul(p[1]).add([0,0,b[2]+_[2]-p[2]]);return coor=[l,d,u,p,_,g,b,b.roro([0,0,1],Math.PI),M,M.roro([0,0,1],Math.PI),y,y.roro([0,0,1],Math.PI)],coor.map((t=>t.add([0,0,(coor[0][2]-coor.slice(-1)[0][2])/2])))}function model_sa_error(t){const e=ck_vectors(calc_tile(t.t,t.R).basis,t.h,t.k,t.H,t.K),r=[[e[3],e[0]],[e[0],e[1]],[e[1],e[2]]],o=["","",ico_axis_2,ico_axis_3,"",ico_axis_5][t.a](e,a,n),s=ico_config(t.a),i=s.t_id.map((t=>parseInt(t[1]))).reduce(((t,e)=>tc[t[1]-1]+=s.t_rep[e]));const l=r.slice(0,i).map(((t,e)=>[...t[0],0].cross([...t[1],0]).norm()/2*c[e])).sum();return(l-s.v_idx.map((t=>t.map((t=>o[t])))).map(((t,e)=>t[1].sub(t[0]).cross(t[2].sub(t[0])).norm()/2*s.t_rep[e])).sum())/l}function lattice_config(t,e,r,o,a,n){const s=calc_tile(n,a),i=ck_vectors(s.basis,t,e,r,o),c=Array.from(tile_grid(i,s.basis)),l=c.map(s.tile),d=c.filter((t=>t.is_vertex)).map((t=>t.coor)).concat([[0,0]]);return l.flat().forEach((t=>{t.data.offset=t.data.mer+(d.some((e=>[t.position.x,t.position.y].sub(e).norm()<=s.radius))?0:3),t.data.centroid=t.segments.map((t=>t.point)).reduce(((t,e)=>t.add(e))).divide(t.segments.length)})),{tile:s,ck:i,lattice:l}}function calc_facets(t,e){const r=[[3,0],[0,1],[1,2]].map((e=>[t.ck[e[0]],t.ck[e[1]]])).map((t=>new paper.Path({segments:[[0,0],...t],closed:!0,data:{vectors:[[0,0],...t]}}))),o=r.map((r=>new paper.Group({children:t.lattice.flatMap((t=>t.map((t=>{const o=t.curves.map((t=>[t.segment1.point,t.segment2.point])),a=t.intersect(r,{insert:!1});return a.data.has_centroid=r.contains(a.data.centroid),a.data.centroid_on_vertex=a.segments.findIndex((t=>t.point.getDistance(a.data.centroid)<1e-5))>-1,a.style.fillColor=e["mer_color_"+a.data.offset]+e["mer_alpha_"+a.data.offset],a.data.strokes=a.curves.map((t=>[t.segment1.point,t.segment2.point])).map(((t,e)=>o.some((e=>[0,1].every((r=>e[0].subtract(t[r]).cross(e[1].subtract(t[r]))<1e-5))&&e[0].subtract(e[1]).isCollinear(t[0].subtract(t[1]))))?e:-1)).split(-1).map((t=>(t.push((t[t.length-1]+1)%a.curves.length),t))),a})))).sort(((t,e)=>t.data.offset-e.data.offset)).filter((t=>t.segments.length>0)),data:r.data})));return r.forEach((t=>t.remove())),o}function draw_lattice(t){const[e,r,o,a,n,s]=["h","k","H","K","R","t"].map((e=>t[e])),i=lattice_config(e,r,o,a,n,s);return i.lattice.flat().forEach((e=>e.style.fillColor=t["mer_color_"+e.data.offset]+t["mer_alpha_"+e.data.offset])),new paper.Group(new paper.Group({children:i.lattice.flat(),position:paper.view.center,style:{strokeColor:t.line_color+t.line_alpha,strokeWidth:t.line_size,strokeCap:"round",strokeJoin:"round"}}))}function draw_facets(t){const[e,r,o,a,n,s]=["h","k","H","K","R","t"].map((e=>t[e])),i=lattice_config(e,r,o,a,n,s),c=new paper.Group({children:calc_facets(i,t),position:paper.view.center});return i.lattice.forEach((t=>t.forEach((t=>t.remove())))),t.facet_toggle?(c.style.strokeColor=t.line_color+t.line_alpha,c.style.strokeWidth=t.line_size,c.style.strokeCap="round",c.style.strokeJoin="round",c):(c.remove(),new paper.Group({children:c.children.map((e=>new paper.Group(e.children.map((e=>{const r=e.segments.map((t=>t.point)),o=new paper.Group(e.data.strokes.map((e=>new paper.Path({segments:e.map((t=>r[t])),closed:!1,style:{strokeColor:t.line_color,strokeWidth:t.line_size}}))));return new paper.Group([e.clone(),o])}))))),style:{strokeCap:"round",strokeJoin:"round"}}))}function draw_net(t){const[e,r,o,a,n,s]=["h","k","H","K","R","t"].map((e=>t[e])),i=lattice_config(e,r,o,a,n,s),c=i.ck,l=calc_facets(i,t);let d;if(5===t.a){const t=new paper.Group(l.slice(0,2)).rotate(-degrees(c[0].angle([1,0]))).scale(-1,1),e=t.clone().rotate(180),r=e.children[1].children.flatMap((t=>t.segments)).map((t=>t.point)).reduce(((t,e)=>t.y{const[a,n]=[t.clone(),e.clone()];return a.position.x+=o*t.children[0].bounds.width,n.position.x+=o*t.children[0].bounds.width,[a,n]})).flatMap((t=>t.children)),position:paper.view.center}),[t,e].forEach((t=>t.remove()))}else if(3===t.a){const t=c[0].angle([1,0]),e=new paper.Group(l).rotate(-degrees(t)).scale(-1,1),r=l[0].clone().rotate(180);r.position.x+=c[0].norm()/2;const o=[r.bounds.topLeft,r.bounds.topRight,r.bounds.bottomCenter].reduce(((t,e)=>t.add(e))).divide(3),a=r.bounds.topRight.add(new paper.Point([1,0].mul(c[1].norm()).rot(-(Math.PI/3-c[1].angle(c[2]))))),n=r.bounds.topRight.add(new paper.Point([1,0].mul(c[2].norm()).rot(-(Math.PI/3-c[1].angle(c[2])+c[1].angle(c[2]))))),s=new paper.Group([...[1,2,3].map(((t,r)=>e.clone().rotate(120*r,o)))]);s.children.slice(0,-1).forEach((t=>t.children[1].remove()));const i=s.clone().rotate(180);i.bounds.left=Math.min(a.x,n.x),i.bounds.bottom=r.bounds.topRight.y,i.position.y-=i.children[1].children[0].bounds.bottom-a.y,i.children.forEach((t=>s.addChild(t.clone()))),s.position=paper.view.center,d=new paper.Group({children:s.children.flatMap((t=>t.children.flat()))}),[r,e,i].forEach((t=>t.remove()))}else{if(2!==t.a)throw new Error("invalid symmetry mode!");{const t=c[0].angle([1,0]),e=new paper.Group(l).rotate(-degrees(t)).rotate(-60).scale(-1,1),r=e.children[1].clone(),o=e.children[0].bounds.topLeft.subtract(e.children[0].bounds.bottomCenter);r.position=r.position.add(o);const a=new paper.Group([e.clone(),e.children[0].clone().rotate(60,e.children[0].bounds.topRight),r.clone()]),n=a.clone().rotate(180,a.children[0].children[0].bounds.topRight);n.position=n.position.add(o.rotate(240));const s=new paper.Group([a,n]),i=s.children[0].children[2].children.filter((t=>1===t.data.offset)).flatMap((t=>t.segments.map((t=>t.point)))).filter((t=>Math.abs(t.getDistance(s.children[0].children[1].bounds.bottomLeft)-c[1].norm())<1e-5)).reduce(((t,e)=>t.yt.children)).flatMap((t=>t.children));d=new paper.Group({children:[...h.filter(((t,e)=>e%3==0)).flatMap((t=>t.children)),...h.filter(((t,e)=>e%3!=0))]}),[2,5,8,11].forEach((t=>d.children[t].remove())),[e,r,a,n,s,u].forEach((t=>t.remove()))}}return d.scale(-1,1),l.forEach((t=>t.remove())),i.lattice.forEach((t=>t.forEach((t=>t.remove())))),t.facet_toggle?(d.style.strokeColor=t.line_color+t.line_alpha,d.style.strokeWidth=t.line_size,d.style.strokeCap="round",d.style.strokeJoin="round",d):(d.remove(),new paper.Group({children:d.children.map((e=>new paper.Group(e.children.map((e=>{const r=e.segments.map((t=>t.point)),o=new paper.Group(e.data.strokes.map((e=>new paper.Path({segments:e.map((t=>r[t])),closed:!1,style:{strokeColor:t.line_color,strokeWidth:t.line_size}}))));return new paper.Group([e.clone(),o])}))))),style:{strokeCap:"round",strokeJoin:"round"}}))}function draw_capsid(t){const[e,r,o,i,c,l]=["h","k","H","K","R","t"].map((e=>t[e])),d=lattice_config(e,r,o,i,c,l),u=calc_facets(d,t),p=ico_config(t.a),h=["","",ico_axis_2,ico_axis_3,"",ico_axis_5][t.a](d.ck,a,n),m=2*Math.PI/t.a,_=e==o&&r==i?e=>spherize(e,h[0].norm(),t.s):e=>cylinderize(e,h,t.a,t.s),g=camera(...[t.θ,t.ψ,t.φ].map(radians));let b=[];for(let a=0,n=0;at.concat(1))))),r=[0,1,2].map((t=>h[p.v_idx[a][t]]));for(let o=0;ot.roro([0,0,1],o*m))),s=mmul(T(a),e),i=t.children.map((t=>{const e=t.segments.map((t=>[t.point.x,t.point.y,1])).map((t=>mmul(s,t.T()).flat())).map((t=>_(t))).map((t=>mmul(g,t.concat(1).T()).flat())),r=mmul(g,_(mmul(s,[t.data.centroid.x,t.data.centroid.y,1].T()).flat()).concat(1).T()).flat();return new paper.Path({segments:e.map((t=>t.slice(0,2))),closed:t.closed,data:Object.assign({},t.data,{id:n,centroid:r,segments_3D:e,normal:e[1].sub(e[0]).cross(e[2].sub(e[0])).uvec()}),style:t.style})}));b=b.concat(new paper.Group({children:i,data:{type:"facet",centroid:mmul(g,_(a.centroid()).concat(1).T()).flat()}}))}}const y=h.map((t=>mmul(g,t.concat(1).T()).flat()));let M=t.penton_fiber_toggle?p.v_con.map((t=>t.map((t=>y[t])).reduce(((t,e)=>t.add(e)),[0,0,0]).uvec())).map(((e,r)=>[y[r],y[r].add(e.mul(t.fiber_length))])):[];M=M.concat(b.flatMap((t=>t.children)).filter((e=>t["mer_toggle_"+e.data.offset]&&e.data.has_centroid)).map((e=>{const r=e.data.centroid;return[r,r.add(e.data.normal.mul(t.fiber_length))]})));let w=[];M.forEach((t=>{let e=0;for(let r of w)t[0].sub(r[0][0]).norm()[t[0][0],t.map((t=>t[1])).reduce(((t,e)=>t.add(e)),[0,0,0]).div(t.length)])).map((t=>new paper.Path.Line({from:t[0],to:t[1],data:{centroid:t[1].mul(2)}})));const v=t.knob_toggle?M.map((e=>new paper.Path.Circle({center:e.segments[1].point,radius:t.knob_size,data:{centroid:e.data.centroid}}))):[];b=b.concat(M).concat(v),b.sort(((t,e)=>t.data.centroid[2]-e.data.centroid[2]));const P=new paper.Group({children:b,position:paper.view.center,style:{strokeWidth:t.line_size,strokeCap:"round",strokeJoin:"round"}});return v.forEach((e=>{e.style.strokeColor=t.line_color+t.line_alpha,e.style.fillColor=t.knob_color+t.knob_alpha})),M.forEach((e=>{e.style.strokeColor=t.fiber_color+t.fiber_alpha,e.style.strokeWidth=t.fiber_size})),u.forEach((t=>t.remove())),d.lattice.forEach((t=>t.forEach((t=>t.remove())))),t.facet_toggle?(P.children.filter((t=>"facet"===t.data.type)).forEach((e=>{e.style.strokeColor=t.line_color+t.line_alpha,e.style.strokeWidth=t.line_size})),P.style.strokeCap="round",P.style.strokeJoin="round",P):(P.remove(),new paper.Group({children:P.children.map((e=>Object.hasOwn(e.data,"type")&&"facet"===e.data.type?new paper.Group(e.children.map((e=>{const r=e.segments.map((t=>t.point)),o=new paper.Group(e.data.strokes.map((e=>new paper.Path({segments:e.map((t=>r[t])),closed:!1,style:{strokeColor:t.line_color+t.line_alpha,strokeWidth:t.line_size}}))));return new paper.Group([e.clone(),o])}))):e)),style:{strokeCap:"round",strokeJoin:"round"}}))}Array.prototype.mul=function(t){return this.map((e=>e*t))},Array.prototype.div=function(t){return this.map((e=>e/t))},Array.prototype.add=function(t){return this.map(((e,r)=>e+t[r]))},Array.prototype.sub=function(t){return this.map(((e,r)=>e-t[r]))},Array.prototype.dot=function(t){return this.map(((e,r)=>e*t[r])).reduce(((t,e)=>t+e))},Array.prototype.sum=function(t=0){return this.reduce(((t,e)=>t+e),t)},Array.prototype.centroid=function(){return this.reduce(((t,e)=>t.add(e))).div(this.length)},Array.prototype.cross=function(t){return[this[1]*t[2]-this[2]*t[1],this[2]*t[0]-this[0]*t[2],this[0]*t[1]-this[1]*t[0]]},Array.prototype.rot=function(t){const[e,r]=[Math.cos(t),Math.sin(t)];return mmul([[e,-r],[r,e]],this.T()).flat()},Array.prototype.roro=function(t,e){return this.mul(Math.cos(e)).add(t.cross(this).mul(Math.sin(e))).add(t.mul(t.dot(this)).mul(1-Math.cos(e)))},Array.prototype.norm=function(){return Math.sqrt(this.map((t=>t*t)).sum())},Array.prototype.uvec=function(){return this.div(this.norm())},Array.prototype.angle=function(t){return Math.acos(this.dot(t)/(this.norm()*t.norm()))},Array.prototype.proj=function(t){return t.mul(this.dot(t)/t.dot(t))},Array.prototype.T=function(){return this.map((t=>[t]))},Array.prototype.distance=function(t){return this.sub(t).norm()},Array.prototype.has=function(t,e=n){return this.some((r=>r.length===t.length&&r.distance(t)t.length))},"undefined"!=typeof exports&&(module.exports={ico_axis_2:ico_axis_2,ico_axis_3:ico_axis_3,ico_axis_5:ico_axis_5}); \ No newline at end of file +const e="2.2.2",t=Math.sqrt(3),r=Math.sqrt(5),o=(1+r)/2,a=100,n=1e-15,s=1e-5;function mmul(e,t){const[r,o,a]=[e.length,e[0].length,t[0].length];for(var n=new Array(r),s=0;sArray.from({length:e.length},(()=>[])))),r=0;r[new paper.Path.RegularPolygon({center:e.coor,sides:6,radius:r,data:{mer:1}})],radius:r};else if("trihex"===e)a={basis:[[2*r,0],[r,r*t]],tile:e=>[new paper.Path.RegularPolygon({center:e.coor,sides:6,radius:r,data:{mer:1}}).rotate(30),...Array.from({length:2},((t,a)=>new paper.Path.RegularPolygon({center:e.coor.add([r,-1/3*o]),sides:3,radius:2/3*o,data:{mer:2}}).rotate(180).rotate(60*a,e.coor)))],radius:2*o};else if("snubhex"===e)a={basis:[[2.5*r,o],[.5*r,3*o]],tile:e=>[new paper.Path.RegularPolygon({center:e.coor,sides:6,radius:r,data:{mer:1}}).rotate(30),...Array.from({length:6},((t,r)=>new paper.Path.RegularPolygon({center:e.coor.add([0,-o-1/3*o]),sides:3,radius:2/3*o,data:{mer:2}}).rotate(60*r,e.coor))),new paper.Path.RegularPolygon({center:e.coor.add([1.5*r,-1/3*o]),sides:3,radius:2/3*o,data:{mer:2}}),new paper.Path.RegularPolygon({center:e.coor.add([-1.5*r,2/3*o]),sides:3,radius:2/3*o,data:{mer:2}}).rotate(180)],radius:2*o};else if("rhombitrihex"===e)a={basis:[[r+o+.5*r,.5*r+o],[0,2*o+r]],tile:e=>[new paper.Path.RegularPolygon({center:e.coor,sides:6,radius:r,data:{mer:1}}).rotate(30),...Array.from({length:3},((o,a)=>new paper.Path.RegularPolygon({center:e.coor.add([0,r+r*(t/3)]),sides:3,radius:r/t,data:{mer:2}}).rotate(-60*a-30,e.coor))),...Array.from({length:3},((t,a)=>new paper.Path.RegularPolygon({center:e.coor.add([0,-o-.5*r]),sides:4,radius:Math.sqrt(2*r*r)/2,data:{mer:3}}).rotate(60*a,e.coor)))],radius:Math.sqrt(Math.pow(o+r,2)+Math.pow(r/2,2))};else if("dualhex"===e)a={basis:[[1.5*r,o],[0,2*o]],tile:e=>Array.from({length:6},((a,n)=>new paper.Path.RegularPolygon({center:e.coor.add([0,o-r*t/6]),sides:3,radius:r/t,data:{mer:1}}).rotate(60*n,e.coor))),radius:r};else if("dualtrihex"===e)a={basis:[[2*o,0],[o,t*o]],tile:e=>[...Array.from({length:6},((t,a)=>new paper.Path({segments:[[0,0],[.5*o,-.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)],[o,0],[.5*o,.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)]].map((t=>e.coor.add(t))),closed:!0,data:{mer:1}}).rotate(60*a,e.coor))),...Array.from({length:6},((t,a)=>new paper.Path({segments:[[-.5*o,.5*r+.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)],[0,.5*r],[o-.5*o,.5*r+.25*r*Math.sin(Math.PI/6)/Math.cos(Math.PI/3)],[0,.5*r+.25*r*Math.sin(Math.PI/6)*2/Math.cos(Math.PI/3)]].map((t=>e.coor.add(t))),closed:!0,data:{mer:2}}).rotate(60*a,e.coor)))],radius:r};else if("dualsnubhex"===e)a={basis:[[2.5*r,o],[.5*r,2*o+r*t/3*2-r*t/6]],tile:e=>Array.from({length:6},((a,n)=>new paper.Path({segments:[[0,0],[0,o+r*t/6],[.5*r,o+r*t/3],[r,o+r*t/6],[r,r*t/3]].map((t=>e.coor.add(t))),closed:!0,data:{mer:1}}).rotate(60*n,e.coor))),radius:o+r*t/3};else if("dualrhombitrihex"===e)a={basis:[[1.5*r,o],[0,2*o]],tile:e=>Array.from({length:6},((a,n)=>new paper.Path({segments:[[0,0],[0,o],[.5*r,o],[t/2*o,.5*o]].map((t=>e.coor.add(t))),closed:!0,data:{mer:1}}).rotate(60*n,e.coor))),radius:r};else if("pinwheel-1"===e)a={basis:[[1.5*o,.75*r],[0,1.5*r]],tile:e=>Array.from({length:6},((t,a)=>new paper.Path({segments:[[0,0],[0,r],[-o/2,.75*r],[-o/2,.25*r]].map((t=>e.coor.add(t))),closed:!0,data:{mer:1}}).rotate(60*a,e.coor))),radius:o};else{if("pinwheel-2"!==e)throw new Error("incorrect tile mode");a={basis:[[1.5*o,.75*r],[0,1.5*r]],tile:e=>Array.from({length:6},((t,a)=>new paper.Path({segments:[[0,0],[0,r],[o/2,.75*r],[o/2,.25*r]].map((t=>e.coor.add(t))),closed:!0,data:{mer:1}}).rotate(60*a,e.coor))),radius:o}}return a}function*tile_grid(e,t){const r=e.map((e=>mmul(T(inv2(t)),[e,1].flat().T()).flat())).map((e=>e.map(Math.round))),[o,a,n,s]=[...[0,1].map(((e,t)=>Math.min(...r.map((e=>e[t]))))),...[0,1].map(((e,t)=>Math.max(...r.map((e=>e[t])))))];for(let c=o;ct.sub(e)));return e.add(a.cross(n).mul(s.norm()**2).add(s.cross(a).mul(n.norm()**2)).add(n.cross(s).mul(a.norm()**2)).div(2*det3([a,n,s])))}function body_radius(e){return e[6].sub([0,0,e[6][2]]).norm()}function height(e){return e[0][2]-e[19][2]}function body_height(e){return e[4][2]-e[6][2]}function sd_sphere(e,t){return e.norm()-t}function spherize(e,t,r){return e.uvec().mul(Math.abs(sd_sphere(e,t))*r).add(e)}function cylinderize(e,t,r,o){const[a,n]=[body_radius(t),body_height(t)/2];let s,c;if(5===r)s=[0,0,n-a/2],c=t[0][2]+a/2-n;else if(3===r){const[e,r]=[t[0],t[3]];s=triangle_circumcircle_center(e,r,[r[0],-r[1],r[2]]),c=e.sub(s).norm()}else 2===r&&(p1=t[0],s=tetrahedron_circumsphere_center(p1,...[1,4,5].map((e=>t[e]))),c=p1.sub(s).norm());const[i,l,d,u]=[[0,0,s[2]],[0,0,-s[2]],[0,0,n],[0,0,-n]];if(n[e,t[r]])))}function ico_axis_5(e){const[t,o]=[e[0].norm(),e[1].norm()],a=t*Math.sqrt((5+r)/10),n=[0,0,(1+r)*t/(2*Math.sqrt(5+2*r))],s=[-a,0,0].roro([0,0,1],.3*Math.PI),c=s.add([t,0,0]),i=e[0].angle(e[1]),l=c.add([o,0,0].roro([0,1,0],-Math.PI-i)),d=s.add(l.sub(s).proj(c.sub(s))),u=[d[0],-Math.abs(d[1])*Math.sqrt(a*a*d[1]*d[1]-(d[0]*d[1])**2)/(d[1]*d[1]),0];if(Number.isNaN(u[1]))throw new Error("impossible construction!");const p=u.add([0,0,-Math.sqrt(l[2]*l[2]-(d[1]-u[1])**2)]);return[n,s,c].concat([1,2,3].map((e=>c.roro([0,0,1],2*e/5*Math.PI)))).concat([p]).concat([1,2,3,4].map((e=>p.roro([0,0,1],2*e/5*Math.PI)))).concat([[0,0,p[2]-n[2]]]).map((e=>e.add([0,0,-p[2]/2])))}function ico_axis_3(e,r=a,o=n){const[s,c,i]=[e[0].norm(),e[1].norm(),e[2].sub(e[1]).norm()],l=[0,s*(1/t),0],d=[s/2,-s*(t/6),0],u=[-s/2,-s*(t/6),0],p=[0,-s*(2*t/3),0];function fold(a){let[n,l]=[p.uvec().mul(s*(t/2)),d.sub(u).uvec()];const m=[0,-s*(t/6),0].add(n.roro(l,a)),h=m.roro([0,0,1],2/3*Math.PI);a=e[0].angle(e[1]),[n,l]=[m.sub(d).uvec().mul(c),m.cross(d).uvec()];const _=n.roro(l,a),[g,y]=[d.add(_.proj(n)),d.add(_)];[n,l]=[y.sub(g),d.sub(m).uvec()];const f=e=>i-g.add(n.roro(l,e)).sub(h).norm();a=bisection(f,...brackets(f,0,2*Math.PI,r).next().value,o,r).slice(-1);const b=g.add(n.roro(l,a));return[m,h,b,Math.abs(m[1])-b.sub([0,0,b[2]]).norm()]}const m=Math.PI/180/10;let h=0;for(let t=0;t*mfold(e).slice(-1)[0];try{h=bisection(obj,...brackets(obj,h,Math.PI/4,r).next().value,o,r).slice(-1)}catch(P){throw new Error("impossible construction!")}const[_,g,y]=fold(h).slice(0,-1);if(Number.isNaN(_[0]))throw new Error("impossible construction!");const b=[0,0,1];h=2*Math.PI/3;const M=y.roro(b,-h),w=M.sub([0,0,M[2]]).roro(b,Math.PI/3).uvec().mul(l[1]).add([0,0,M[2]+_[2]-l[2]]);let v=[l,d,u,_,g.roro(b,h),g,y,M,M.roro(b,-h),w,w.roro(b,-h),w.roro(b,-2*h)];return v.map((e=>e.add([0,0,(v[0][2]-v.slice(-1)[0][2])/2])))}function ico_axis_2(e,t=a,r=n){const[s,c,i]=[e[0].norm(),e[1].norm(),e[2].sub(e[1]).norm()],l=[s/2,0,0],d=[-s/2,0,0],u=[0,-s*o/2,-(s*o-s)/2],p=[0,s*o/2,-(s*o-s)/2];function fold(o){let a=d.add(u).div(2),[n,s]=[a.sub(l),u.sub(d).uvec()];const p=a.add(n.roro(s,o)),m=p.roro([0,0,1],Math.PI);o=e[0].angle(e[1]),[n,s]=[u.sub(l).uvec().mul(c),u.cross(l).uvec()];const h=n.roro(s,o);a=l.add(h.proj(n));const _=l.add(h);[n,s]=[_.sub(a),l.sub(u).uvec()];const f=e=>i-a.add(n.roro(s,e)).sub(m).norm();o=bisection(f,...brackets(f,0,2*Math.PI,t).next().value,r,t).slice(-1);const g=a.add(n.roro(s,o));return[p,m,g,p.sub([0,0,p[2]]).norm()-g.sub([0,0,g[2]]).norm()]}const m=Math.PI/180/10;let h=0;for(let o=0;o*mfold(e).slice(-1)[0];try{h=bisection(obj,...brackets(obj,h,Math.PI/4,t).next().value,r,t).slice(-1)}catch(w){throw new Error("impossible construction!")}const[_,g,y]=fold(h).slice(0,-1);if(Number.isNaN(_[0]))throw new Error("impossible construction!");obj=e=>l.roro([0,0,1],e).add([0,0,y[2]+_[2]]).sub(g).norm()-c;try{h=bisection(obj,...brackets(obj,0,2*Math.PI,t).next().value,r,t).slice(-1)}catch(w){throw new Error("impossible construction!")}const b=l.roro([0,0,1],h).add([0,0,y[2]+_[2]]),M=b.sub([0,0,b[2]]).uvec().roro([0,0,1],Math.PI/2).mul(p[1]).add([0,0,y[2]+_[2]-p[2]]);return coor=[l,d,u,p,_,g,y,y.roro([0,0,1],Math.PI),M,M.roro([0,0,1],Math.PI),b,b.roro([0,0,1],Math.PI)],coor.map((e=>e.add([0,0,(coor[0][2]-coor.slice(-1)[0][2])/2])))}function model_sa_error(e){try{const t=ck_vectors(calc_tile(e.t,e.R).basis,e.h,e.k,e.H,e.K,e.c),r=[[t[3],t[0]],[t[0],t[1]],[t[1],t[2]]],o=["","",ico_axis_2,ico_axis_3,"",ico_axis_5][e.a](t,a,n),s=ico_config(e.a),c=s.t_id.map((e=>parseInt(e[1]))).reduce(((e,t)=>ei[e[1]-1]+=s.t_rep[t]));const l=r.slice(0,c).map(((e,t)=>[...e[0],0].cross([...e[1],0]).norm()/2*i[t])).sum();return(l-s.v_idx.map((e=>e.map((e=>o[e])))).map(((e,t)=>e[1].sub(e[0]).cross(e[2].sub(e[0])).norm()/2*s.t_rep[t])).sum())/l}catch(t){return NaN}}function lattice_config(e,t,r,o,a,s,c){const i=calc_tile(c,s),l=ck_vectors(i.basis,e,t,r,o,a),d=Array.from(tile_grid(l,i.basis)),u=d.map(i.tile),p=d.filter((e=>e.is_vertex)).map((e=>e.coor)).concat([[0,0]]);return u.flat().forEach((e=>{e.data.offset=e.data.mer+(p.some((t=>[e.position.x,e.position.y].sub(t).norm()-i.radiuse.point)).reduce(((e,t)=>e.add(t))).divide(e.segments.length)})),{tile:i,ck:l,lattice:u}}function calc_facets(e,t){const r=[[3,0],[0,1],[1,2]].map((t=>[e.ck[t[0]],e.ck[t[1]]])).map((e=>new paper.Path({segments:[[0,0],...e],closed:!0,data:{vectors:[[0,0],...e]}}))),o=r.map((r=>new paper.Group({children:e.lattice.flatMap((e=>e.map((e=>{const o=e.curves.map((e=>[e.segment1.point,e.segment2.point])),a=e.intersect(r,{insert:!1});return a.data.has_centroid=r.contains(a.data.centroid),a.data.centroid_on_vertex=a.segments.findIndex((e=>e.point.getDistance(a.data.centroid)<1e-5))>-1,a.style.fillColor=t["mer_color_"+a.data.offset]+t["mer_alpha_"+a.data.offset],a.data.strokes=a.curves.map((e=>[e.segment1.point,e.segment2.point])).map(((e,t)=>o.some((t=>[0,1].every((r=>t[0].subtract(e[r]).cross(t[1].subtract(e[r]))<1e-5))&&t[0].subtract(t[1]).isCollinear(e[0].subtract(e[1]))))?t:-1)).split(-1).map((e=>(e.push((e[e.length-1]+1)%a.curves.length),e))),a})))).sort(((e,t)=>e.data.offset-t.data.offset)).filter((e=>e.segments.length>0)),data:r.data})));return r.forEach((e=>e.remove())),o}function draw_lattice(e){const[t,r,o,a,n,s,c]=["h","k","H","K","c","R","t"].map((t=>e[t])),i=lattice_config(t,r,o,a,n,s,c);return i.lattice.flat().forEach((t=>t.style.fillColor=e["mer_color_"+t.data.offset]+e["mer_alpha_"+t.data.offset])),new paper.Group(new paper.Group({children:i.lattice.flat(),position:paper.view.center,style:{strokeColor:e.line_color+e.line_alpha,strokeWidth:e.line_size,strokeCap:"round",strokeJoin:"round"}})).scale(1,-1)}function draw_facets(e){const[t,r,o,a,n,s,c]=["h","k","H","K","c","R","t"].map((t=>e[t])),i=lattice_config(t,r,o,a,n,s,c),l=new paper.Group({children:calc_facets(i,e),position:paper.view.center}).scale(1,-1);return i.lattice.forEach((e=>e.forEach((e=>e.remove())))),e.facet_toggle?(l.style.strokeColor=e.line_color+e.line_alpha,l.style.strokeWidth=e.line_size,l.style.strokeCap="round",l.style.strokeJoin="round",l):(l.remove(),new paper.Group({children:l.children.map((t=>new paper.Group(t.children.map((t=>{const r=t.segments.map((e=>e.point)),o=new paper.Group(t.data.strokes.map((t=>new paper.Path({segments:t.map((e=>r[e])),closed:!1,style:{strokeColor:e.line_color,strokeWidth:e.line_size}}))));return new paper.Group([t.clone(),o])}))))),style:{strokeCap:"round",strokeJoin:"round"}}))}function draw_net(e){const[t,r,o,a,n,s,c]=["h","k","H","K","c","R","t"].map((t=>e[t])),i=lattice_config(t,r,o,a,n,s,c),l=i.ck,d=calc_facets(i,e);let u;if(5==e.a){const e=new paper.Group(d.slice(0,2).map((e=>e.clone()))),t=e.clone().rotate(180,l[0]).translate(l[1].sub(l[0].mul(2)));u=new paper.Group({children:[e,t].flatMap((e=>Array.from({length:5},((t,r)=>e.clone().translate(l[0].mul(r)))))).flatMap((e=>e.children)),position:paper.view.center}).rotate(-degrees(Math.atan2(l[0].dot([0,1]),1*l[0][0]-0*l[0][1]))),[e,t].forEach((e=>e.remove()))}else if(3==e.a){const e=[[0,0],l[0],l[3]].centroid(),t=new paper.Group(d.slice(0,1).map((e=>e.clone()))),r=new paper.Group(d.slice(0,3).map((e=>e.clone()))).translate(l[0]).rotate(-60,l[0]),o=new paper.Group([t.clone(),...Array.from({length:3},((t,o)=>r.clone().rotate(120*o,e)))]),a=l[0].add(l[1].rot(Math.PI/3).rot(4*Math.PI/3));u=new paper.Group({children:[o.clone(),o.clone().translate(l[0].add(a)).rotate(60,a)].flatMap((e=>e.children)).flatMap((e=>e.children)),position:paper.view.center}).rotate(-degrees(Math.atan2(l[0].dot([0,1]),1*l[0][0]-0*l[0][1]))-30),[t,r,o].forEach((e=>e.remove()))}else if(2==e.a){const e=new paper.Group(d.slice(0,3).map((e=>e.clone()))),t=new paper.Group([...e.clone().children,e.children[0].clone().rotate(60,l[0]),e.children[2].clone().translate(l[0])]),r=new paper.Group([t.clone(),t.clone().rotate(180,l[3]).translate(l[3].mul(-1))]);u=new paper.Group({children:[r.clone(),r.clone().translate(l[1].mul(-1).add(l[0].mul(-2)).add(l[3]))].flatMap((e=>e.children)).flatMap((e=>e.children)),position:paper.view.center}).rotate(-degrees(Math.atan2(l[0].dot([0,1]),1*l[0][0]-0*l[0][1]))-30),[e,t,r].forEach((e=>e.remove()))}return d.forEach((e=>e.remove())),i.lattice.forEach((e=>e.forEach((e=>e.remove())))),e.facet_toggle?(u.style.strokeColor=e.line_color+e.line_alpha,u.style.strokeWidth=e.line_size,u.style.strokeCap="round",u.style.strokeJoin="round",u.scale(1,-1)):(u.remove(),new paper.Group({children:u.children.flatMap((t=>new paper.Group(t.children.map((t=>{const r=t.segments.map((e=>e.point)),o=new paper.Group(t.data.strokes.map((t=>new paper.Path({segments:t.map((e=>r[e])),closed:!1,style:{strokeColor:e.line_color,strokeWidth:e.line_size}}))));return new paper.Group([t.clone(),o])}))))),style:{strokeCap:"round",strokeJoin:"round"}}).scale(1,-1))}function draw_capsid(e){const[t,r,o,c,i,l,d]=["h","k","H","K","c","R","t"].map((t=>e[t])),u=lattice_config(t,r,o,c,i,l,d),p=calc_facets(u,e),m=ico_config(e.a),h=["","",ico_axis_2,ico_axis_3,"",ico_axis_5][e.a](u.ck,a,n),_=2*Math.PI/e.a,g=t==o&&r==c?t=>spherize(t,h[0].norm(),e.s):t=>cylinderize(t,h,e.a,e.s),y=camera(...[e.θ,e.ψ,e.φ].map(radians));let b=[];for(let a=0,n=0;ae.concat(1))))),r=[0,1,2].map((e=>h[m.v_idx[a][e]]));for(let o=0;oe.roro([0,0,1],o*_))),s=mmul(T(a),t),c=e.children.map((e=>{const t=e.segments.map((e=>[e.point.x,e.point.y,1])).map((e=>mmul(s,e.T()).flat())).map((e=>g(e))).map((e=>mmul(y,e.concat(1).T()).flat())),r=mmul(y,g(mmul(s,[e.data.centroid.x,e.data.centroid.y,1].T()).flat()).concat(1).T()).flat();return new paper.Path({segments:t.map((e=>e.slice(0,2))),closed:e.closed,data:Object.assign({},e.data,{id:n,centroid:r,segments_3D:t,normal:t[1].sub(t[0]).cross(t[2].sub(t[0])).uvec()}),style:e.style})}));b=b.concat(new paper.Group({children:c,data:{type:"facet",centroid:mmul(y,g(a.centroid()).concat(1).T()).flat()}}))}}const M=h.map((e=>mmul(y,e.concat(1).T()).flat()));let w=e.penton_fiber_toggle?m.v_con.map((e=>e.map((e=>M[e])).reduce(((e,t)=>e.add(t)),[0,0,0]).uvec())).map(((t,r)=>[M[r],M[r].add(t.mul(e.fiber_length))])):[];w=w.concat(b.flatMap((e=>e.children)).filter((t=>e["mer_toggle_"+t.data.offset]&&t.data.has_centroid)).map((t=>{const r=t.data.centroid;return[r,r.add(t.data.normal.mul(e.fiber_length))]})));let v=[];w.forEach((e=>{let t=0;for(let r of v)e[0].sub(r[0][0]).norm()[e[0][0],e.map((e=>e[1])).reduce(((e,t)=>e.add(t)),[0,0,0]).div(e.length)])).map((e=>new paper.Path.Line({from:e[0],to:e[1],data:{centroid:e[1].mul(2)}})));const P=e.knob_toggle?w.map((t=>new paper.Path.Circle({center:t.segments[1].point,radius:e.knob_size,data:{centroid:t.data.centroid}}))):[];b=b.concat(w).concat(P),b.sort(((e,t)=>e.data.centroid[2]-t.data.centroid[2]));const k=new paper.Group({children:b,position:paper.view.center,style:{strokeWidth:e.line_size,strokeCap:"round",strokeJoin:"round"}});return P.forEach((t=>{t.style.strokeColor=e.line_color+e.line_alpha,t.style.fillColor=e.knob_color+e.knob_alpha})),w.forEach((t=>{t.style.strokeColor=e.fiber_color+e.fiber_alpha,t.style.strokeWidth=e.fiber_size})),p.forEach((e=>e.remove())),u.lattice.forEach((e=>e.forEach((e=>e.remove())))),e.facet_toggle?(k.children.filter((e=>"facet"===e.data.type)).forEach((t=>{t.style.strokeColor=e.line_color+e.line_alpha,t.style.strokeWidth=e.line_size})),k.style.strokeCap="round",k.style.strokeJoin="round",k.scale(-1,1)):(k.remove(),new paper.Group({children:k.children.map((t=>Object.hasOwn(t.data,"type")&&"facet"===t.data.type?new paper.Group(t.children.map((t=>{const r=t.segments.map((e=>e.point)),o=new paper.Group(t.data.strokes.map((t=>new paper.Path({segments:t.map((e=>r[e])),closed:!1,style:{strokeColor:e.line_color+e.line_alpha,strokeWidth:e.line_size}}))));return new paper.Group([t.clone(),o])}))):t)),style:{strokeCap:"round",strokeJoin:"round"}}).scale(-1,1))}Array.prototype.mul=function(e){return this.map((t=>t*e))},Array.prototype.div=function(e){return this.map((t=>t/e))},Array.prototype.add=function(e){return this.map(((t,r)=>t+e[r]))},Array.prototype.sub=function(e){return this.map(((t,r)=>t-e[r]))},Array.prototype.dot=function(e){return this.map(((t,r)=>t*e[r])).reduce(((e,t)=>e+t))},Array.prototype.sum=function(e=0){return this.reduce(((e,t)=>e+t),e)},Array.prototype.centroid=function(){return this.reduce(((e,t)=>e.add(t))).div(this.length)},Array.prototype.cross=function(e){return[this[1]*e[2]-this[2]*e[1],this[2]*e[0]-this[0]*e[2],this[0]*e[1]-this[1]*e[0]]},Array.prototype.rot=function(e){const[t,r]=[Math.cos(e),Math.sin(e)];return mmul([[t,-r],[r,t]],this.T()).flat()},Array.prototype.roro=function(e,t){return this.mul(Math.cos(t)).add(e.cross(this).mul(Math.sin(t))).add(e.mul(e.dot(this)).mul(1-Math.cos(t)))},Array.prototype.norm=function(){return Math.sqrt(this.map((e=>e*e)).sum())},Array.prototype.uvec=function(){return this.div(this.norm())},Array.prototype.angle=function(e){return Math.acos(this.dot(e)/(this.norm()*e.norm()))},Array.prototype.proj=function(e){return e.mul(this.dot(e)/e.dot(e))},Array.prototype.T=function(){return this.map((e=>[e]))},Array.prototype.distance=function(e){return this.sub(e).norm()},Array.prototype.has=function(e,t=n){return this.some((r=>r.length===e.length&&r.distance(e)e.length))},"undefined"!=typeof exports&&(module.exports={ico_axis_2:ico_axis_2,ico_axis_3:ico_axis_3,ico_axis_5:ico_axis_5}); \ No newline at end of file