0xa319…7f9c

All memos sent from and to 0xa319…7f9c.

Field Recordings is a collection of observations. Each observation depicts an intangible entity and hints at the greater environment which spawned it. Each token is accompanied by a signed physical plot which can be claimed for the price of shipping. Details can be found on the project website.
Field Recordings is a collection of observations. Each observation depicts an intangible entity and hints at the greater environment which spawned it. Each token is accompanied by a unique signed physical plot which can be claimed for the price of shipping. Details can be found on the project website.
p5.disableFriendlyErrors=!0;class Random{constructor(){this.useA=!1;let $=function($){let e=parseInt($.substr(0,8),16),r=parseInt($.substr(8,8),16),n=parseInt($.substr(16,8),16),l=parseInt($.substr(24,8),16);return function(){n|=0;let $=((e|=0)+(r|=0)|0)+(l|=0)|0;return l=l+1|0,e=r^r>>>9,r=n+(n<<3)|0,n=(n=n<<21|n>>>11)+$|0,($>>>0)/4294967296}};this.prngA=new $(tokenData.hash.substr(2,32)),this.prngB=new $(tokenData.hash.substr(34,32));for(let e=0;e<1e6;e+=2)this.prngA(),this.prngB()}rd(){return this.useA=!this.useA,this.useA?this.prngA():this.prngB()}}function setup(){aspect=420/297,unit=1200,noiseSeed(floor(1e9*R.rd())),noLoop(),gen_pts=[],pts1=[],pts2=[],pr=R.rd(),pr2=(6*R.rd()/7+floor(7*pr)/7+1/7)%1,pts1=fitPts(pts1=pr<1/7?linePts(8e3):pr<2/7?spiralPts(8e3):pr<3/7?walkPts(8e3):pr<4/7?sinePts(8e3):pr<5/7?polyPts(8e3):pr<6/7?directedPts(8e3):flowPts(8e3)),pts2=fitPts(pts2=pr2<1/7?linePts(8e3):pr2<2/7?spiralPts(8e3):pr2<3/7?walkPts(8e3):pr2<4/7?sinePts(8e3):pr2<5/7?polyPts(8e3):pr2<6/7?directedPts(8e3):flowPts(8e3)),gen_pts=[];for(let $=0;$<pts1.length;$++)x=.6*pts1[$][0]+.4*pts2[$][0],y=.6*pts1[$][1]+.4*pts2[$][1],gen_pts.push([x,y]);gen_pts=fitPts(gen_pts)}function linePts($){out_pts=[],num_lines=12,line_counts=[],sum=0,exp_weight=.18+.04*R.rd();for(let e=0;e<num_lines;e++)line_counts[e]=exp(e*exp_weight),sum+=exp(e*exp_weight);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;for(let n=0;n<num_lines;n++){x=R.rd();for(let l=0;l<line_counts[n];l++)y=map(l,0,line_counts[n]-1,0,aspect),out_pts.push([x,y])}return out_pts}function spiralPts($){out_pts=[],num_lines=3,line_counts=[],sum=0;for(let e=0;e<num_lines;e++)line_counts[e]=exp(e),sum+=exp(e);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;for(let n=0;n<num_lines;n++){cx=map(R.rd(),0,1,.3,.7),cy=map(R.rd(),0,1,.3,aspect-.3),th=R.rd()*TWO_PI,th_max=map(R.rd(),0,1,16,32)*PI,r_max=.3+.2*R.rd();for(let l=0;l<line_counts[n];l++)x=cx+(rad=map(l,0,line_counts[n]-1,0,r_max))*cos(theta=map(l,0,line_counts[n],th,th+th_max)),y=cy+rad*sin(theta),out_pts.push([x,y])}return out_pts}function sinePts($){out_pts=[],num_lines=8,line_counts=[],sum=0,exp_weight=.28+.04*R.rd();for(let e=0;e<num_lines;e++)line_counts[e]=exp(e*exp_weight),sum+=exp(e*exp_weight);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;for(let n=0;n<num_lines;n++){sine_mag=.2+.2*R.rd(),sine_freq=TWO_PI*(2*R.rd()+1),right=.5>R.rd(),cy=map(R.rd(),0,1,sine_mag,aspect-sine_mag);for(let l=0;l<line_counts[n];l++)y=cy+sine_mag*sin(sine_freq*(x=right?map(l,0,line_counts[n]-1,0,1):map(l,0,line_counts[n]-1,1,0))),out_pts.push([x,y])}return out_pts}function walkPts($){out_pts=[],num_lines=20,line_counts=[],sum=0;for(let e=0;e<num_lines;e++)line_counts[e]=exp(.1*e),sum+=exp(.1*e);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;cx=R.rd(),cy=R.rd()*aspect;for(let n=0;n<num_lines;n++){cx2=R.rd(),cy2=R.rd()*aspect;for(let l=0;l<line_counts[n];l++)x=map(l,0,line_counts[n]-1,cx,cx2),y=map(l,0,line_counts[n]-1,cy,cy2),out_pts.push([x,y]);cx=cx2,cy=cy2}return out_pts}function polyPts($){out_pts=[],num_lines=8,line_counts=[],sum=0;for(let e=0;e<num_lines;e++)line_counts[e]=exp(.3*e),sum+=exp(.3*e);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;for(let n=0;n<num_lines;n++){rad=.3*R.rd()+.2,cx=map(R.rd(),0,1,rad,1-rad),cy=map(R.rd(),0,1,rad,aspect-rad),num_sides=floor(6*R.rd()+3),vertices=[],ctheta=R.rd()*TWO_PI;for(let l=0;l<num_sides;l++)x=cx+rad*cos((theta=map(l,0,num_sides,0,TWO_PI))+ctheta),y=cy+rad*sin(theta+ctheta),vertices.push([x,y]);for(let _=0;_<line_counts[n];_++)index=map(_,0,line_counts[n]-1,0,num_sides),x1=vertices[floor(index)%num_sides][0],y1=vertices[floor(index)%num_sides][1],x2=vertices[ceil(index)%num_sides][0],y2=vertices[ceil(index)%num_sides][1],x=(w=index-floor(index))*x2+(1-w)*x1,y=w*y2+(1-w)*y1,out_pts.push([x,y])}return out_pts}function directedPts($){out_pts=[],num_lines=6,line_counts=[],sum=0;for(let e=0;e<num_lines;e++)line_counts[e]=exp(.4*e),sum+=exp(.4*e);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;t=1e7*R.rd();for(let n=0;n<num_lines;n++){x=map(R.rd(),0,1,.4,.6),y=map(R.rd(),0,1,.4*aspect,.6*aspect),theta=R.rd()*TWO_PI,v=.001*$/line_counts[n];for(let l=0;l<line_counts[n];l++)theta+=5*v*(noise(60,t)-.5),x+=v*cos(theta),y+=v*sin(theta),out_pts.push([x,y,0]),t+=10*v}return out_pts}function flowPts($){out_pts=[],num_lines=8,line_counts=[],sum=0;for(let e=0;e<num_lines;e++)line_counts[e]=exp(.3*e),sum+=exp(.3*e);count=0;for(let r=0;r<num_lines;r++)count+=floor(line_counts[r]/sum*$),line_counts[r]=floor(line_counts[r]/sum*$);for(;count<$;)line_counts[floor(R.rd()*line_counts.length)]++,count++;for(let n=0;n<num_lines;n++){x=map(R.rd(),0,1,.1,.9),y=map(R.rd(),0,1,.1*aspect,.9*aspect),v=.001*$/line_counts[n],offset=1e6*R.rd();for(let l=0;l<line_counts[n];l++)vx=v*(noise(3*x,3*y,offset)-.5),vy=v*(noise(3*x,3*y,offset+10)-.5),x+=vx,y+=vy,out_pts.push([x,y,0])}return out_pts}function fitPts($){out_pts=[],min_x=$[0][0],max_x=$[0][0],min_y=$[0][1],max_y=$[0][1];for(let e=0;e<$.length;e++)$[e][0]<min_x&&(min_x=$[e][0]),$[e][0]>max_x&&(max_x=$[e][0]),$[e][1]<min_y&&(min_y=$[e][1]),$[e][1]>max_y&&(max_y=$[e][1]),out_pts[e]=[];for(let r=0;r<$.length;r++)x=map($[r][0],min_x,max_x,0,1),y=map($[r][1],min_y,max_y,0,aspect),out_pts[r][0]=x,out_pts[r][1]=y;return out_pts}function genPoly3($,e){let r=[];num_pts=100,t_max=100,v=.02,nls=5,line1=[];let n=$,l=e;n_scale=1;for(let _=0;_<t_max;_++)line1.push([n,l]),nx=n_scale*(noise(nls*n,nls*l,0)-.5),ny=n_scale*(noise(nls*n,nls*l,10)-.5),nnx=n_scale*(noise(nls*nx,nls*nx,40)-.5),nny=n_scale*(noise(nls*nx,nls*nx,50)-.5),n+=v*nx,l+=v*ny;line2=[],n=$,l=e,n_scale=1;for(let o=0;o<t_max;o++)line2.push([n,l]),nx=n_scale*(noise(nls*n,nls*l,20)-.5),ny=n_scale*(noise(nls*n,nls*l,30)-.5),nnx=n_scale*(noise(nls*nx,nls*nx,60)-.5),nny=n_scale*(noise(nls*nx,nls*nx,70)-.5),n+=v*nx,l+=v*ny;for(let s=0;s<num_pts;s++)l1=.5+.5*cos(theta=map(s,0,num_pts-1,0,TWO_PI)),l2=.5+.5*sin(theta),i1=floor((line1.length-2)*l1),w1=1-((line1.length-2)*l1-floor((line1.length-2)*l1)),i2=floor((line2.length-2)*l2),w2=1-((line2.length-2)*l2-floor((line2.length-2)*l2)),n=(line1[i1][0]*w1+line1[i1+1][0]*(1-w1)+line2[i2][0]*w2+line2[i2+1][0]*(1-w2))/2,r.push([n,l=(line1[i1][1]*w1+line1[i1+1][1]*(1-w1)+line2[i2][1]*w2+line2[i2+1][1]*(1-w2))/2]);return r}function on_segment($,e,r,n,l,_){return!!(r<=max($,l)&&r>=min($,l)&&n<=max(e,_)&&n>=min(e,_))}function orient($,e,r,n,l,_){let o=(n-e)*(l-r)-(r-$)*(_-n);return o>0?1:o<0?2:0}function intersect($,e,r,n,l,_,o,s){return($!=l||e!=_)&&($!=o||e!=s)&&(r!=l||n!=_)&&(r!=o||n!=s)&&(o1=orient($,e,r,n,l,_),o2=orient($,e,r,n,o,s),o3=orient(l,_,o,s,$,e),o4=orient(l,_,o,s,r,n),!!(o1!=o2&&o3!=o4||0==o1&&on_segment($,e,l,_,r,n)||0==o2&&on_segment($,e,o,s,r,n)||0==o3&&on_segment(l,_,$,e,o,s)||0==o4&&on_segment(l,_,r,n,o,s)))}function intersect_pt($,e,r,n,l,_,o,s){let f=r-$,h=n-e,i=o-l,u=s-_,d;return[(d=0==i?(l-$)/(r-$):(_-e+($-l)*u/i)/(h-f*u/i))*f+$,d*h+e]}function draw(){poly_list=[],poly_limits=[],count=0,count2=0,p=[color(0),color(0),color(0)],layer_size=[3e3,3e3,3e3],weights=[.5,.5,.5],max_intersections=1,edge_dict={},dict_size=200,x1=margin=.03,x2=1-margin,y1=margin,xgmin=floor(x1*dict_size),xgmax=floor(x2*dict_size),yg=floor(y1*dict_size);let $=1/.3,e=297*$,r=420*$,n="http://www.w3.org/2000/svg",l=document.createElementNS(n,"svg");l.setAttribute("width","100vw"),l.setAttribute("height","100vh"),l.setAttribute("viewBox","0 0 "+e+" "+r),l.setAttribute("style","background-color:white;");let _=document.createElementNS(n,"path");_.setAttribute("d",`M 0 0 M ${e} ${r}`),l.appendChild(_);let o=document.createElementNS(n,"g");o.setAttribute("id","1000000layer"),o.setAttribute("style","fill:none;stroke-width:1;stroke:rgb(0%,0%,0%);");for(let s=0;s<gen_pts.length;s++){let f;poly=genPoly3(gen_pts[s][0],gen_pts[s][1]),start_index=62,final_poly=[poly[start_index]],has_intersections=!1,num_intersections=0;for(let h=0;h<poly.length&&!has_intersections;h++){x1=poly[(h+start_index)%poly.length][0],y1=poly[(h+start_index)%poly.length][1],x2=poly[(h+start_index+1)%poly.length][0],y2=poly[(h+start_index+1)%poly.length][1],xg=floor(x1*dict_size),yg=floor(y1*dict_size),xg2=floor(x2*dict_size),yg2=floor(y2*dict_size);for(let i=min(xg,xg2);i<=max(xg,xg2);i++)for(let u=min(yg,yg2);u<=max(yg,yg2);u++)if([i,u]in edge_dict)for(let d=0;d<edge_dict[[i,u]].length;d++)intersect(x1,y1,x2,y2,edge_dict[[i,u]][d][0],edge_dict[[i,u]][d][1],edge_dict[[i,u]][d][2],edge_dict[[i,u]][d][3])&&(count++,++num_intersections==max_intersections&&(final_poly.push(intersect_pt(x1,y1,x2,y2,edge_dict[[i,u]][d][0],edge_dict[[i,u]][d][1],edge_dict[[i,u]][d][2],edge_dict[[i,u]][d][3])),has_intersections=!0));has_intersections||final_poly.push([x2,y2])}if(has_intersections){has_intersections=!1,num_intersections=0;for(let g=0;g<poly.length&&!has_intersections;g++){x1=poly[(-g+start_index+2*poly.length)%poly.length][0],y1=poly[(-g+start_index+2*poly.length)%poly.length][1],x2=poly[(-g+start_index+2*poly.length-1)%poly.length][0],y2=poly[(-g+start_index+2*poly.length-1)%poly.length][1],xg=floor(x1*dict_size),yg=floor(y1*dict_size),xg2=floor(x2*dict_size),yg2=floor(y2*dict_size);for(let c=min(xg,xg2);c<=max(xg,xg2);c++)for(let P=min(yg,yg2);P<=max(yg,yg2);P++)if([c,P]in edge_dict)for(let a=0;a<edge_dict[[c,P]].length;a++)intersect(x1,y1,x2,y2,edge_dict[[c,P]][a][0],edge_dict[[c,P]][a][1],edge_dict[[c,P]][a][2],edge_dict[[c,P]][a][3])&&++num_intersections==max_intersections&&(final_poly.splice(0,0,intersect_pt(x1,y1,x2,y2,edge_dict[[c,P]][a][0],edge_dict[[c,P]][a][1],edge_dict[[c,P]][a][2],edge_dict[[c,P]][a][3])),has_intersections=!0);has_intersections||final_poly.splice(0,0,[x2,y2])}}for(let b=0;b<final_poly.length-1;b++){x1=final_poly[b][0],y1=final_poly[b][1],x2=final_poly[b+1][0],y2=final_poly[b+1][1],xg=floor(x1*dict_size),yg=floor(y1*dict_size),xg2=floor(x2*dict_size),yg2=floor(y2*dict_size);for(let A=min(xg,xg2);A<=max(xg,xg2);A++)for(let m=min(yg,yg2);m<=max(yg,yg2);m++)[A,m]in edge_dict?edge_dict[[A,m]].push([x1,y1,x2,y2]):edge_dict[[A,m]]=[[x1,y1,x2,y2]]}poly_list.push(final_poly)}min_x=poly_list[0][0][0],max_x=poly_list[0][0][0],min_y=poly_list[0][0][1],max_y=poly_list[0][0][1],mean_x=0,mean_y=0,mean_x2=0,mean_y2=0,count=0;for(let k=0;k<poly_list.length;k++)for(let E=0;E<poly_list[k].length;E++)mean_x+=poly_list[k][E][0],mean_x2+=poly_list[k][E][0]**2,mean_y+=poly_list[k][E][1],mean_y2+=poly_list[k][E][1]**2,count++,poly_list[k][E][0]<min_x&&(min_x=poly_list[k][E][0]),poly_list[k][E][0]>max_x&&(max_x=poly_list[k][E][0]),poly_list[k][E][1]<min_y&&(min_y=poly_list[k][E][1]),poly_list[k][E][1]>max_y&&(max_y=poly_list[k][E][1]);mean_x/=count,mean_y/=count,mean_x2/=count,mean_y2/=count,std_x=sqrt(mean_x2-mean_x**2),std_y=sqrt(mean_y2-mean_y**2),scale_factor=1,(scale_ratio=(max_y-min_y)/(max_x-min_x))>aspect?(min_x=-(scale_factor=(max_y-min_y)/aspect)/2+(avg_x=(max_x+min_x)/2),max_x=scale_factor/2+avg_x):(min_y=-(scale_factor=max_x-min_x)*aspect/2+(avg_y=(max_y+min_y)/2),max_y=scale_factor*aspect/2+avg_y);for(let B=0;B<poly_list.length;B++)for(let C=0;C<poly_list[B].length;C++)poly_list[B][C][0]=map(poly_list[B][C][0],min_x,max_x,margin,1-margin),poly_list[B][C][1]=map(poly_list[B][C][1],min_y,max_y,margin,aspect-margin);margin=.03;for(let N=0;N<poly_list.length;N++){path_string=`M ${poly_list[N][0][0]*e} ${poly_list[N][0][1]*e}`,nonNumber=!1;for(let S=1;S<poly_list[N].length;S++)path_string+=` L ${poly_list[N][S][0]*e} ${poly_list[N][S][1]*e}`,(isNaN(poly_list[N][S][0])||isNaN(poly_list[N][S][1]))&&(nonNumber=!0);if(!nonNumber){let M=document.createElementNS(n,"path");M.setAttribute("d",path_string),o.appendChild(M)}}l.appendChild(o),noCanvas(),document.body.appendChild(l),print(tokenData.hash)}R=new Random;
S=Uint32Array.from([0,1,s=t=2,3].map(t=>parseInt(tokenData.hash.substr(8*t+2,8),16))),R=i=>(t=S[3],S[3]=S[2],S[2]=S[1],S[1]=s=S[0],t^=t<<11,S[0]^=t^t>>>8^s>>>19,S[0]/2**32);let sd=parseInt(tokenData.hash.slice(0,16),16),rnd=function(t,s){var i,h=R();return void 0===t?h:void 0===s?t instanceof Array?t[Math.floor(h*t.length)]:h*t:(s<t&&(i=t,t=s,s=i),h*(s-t)+t)},st,fm,bbs=[],cps={},pT,iP=!1,iE=!1,sW=900,sH=1200;function setup(){var t;noiseSeed(sd),tokenData.plot?(width=sW,height=sH,noCanvas(),noLoop(),gs(),t=cS(),doc.body.appendChild(t),(t=doc.ce("style")).appendChild(doc.createTextNode(".plot{width:100vw;height:100vh;}")),doc.head.appendChild(t)):(createCanvas(3*windowHeight/4,windowHeight),frameRate(120),strokeWeight(1.5*width/1080),gs(),pT=millis())}function gs(){st=new St,fm=new F,zz()}function zz(){for(let t=0;t<st.cs.length;t++)cps[st.cs[t]]=new Path2D;for(let s=0;s<st.nX;s++){var i=st.cX*s+st.cX/2;for(let t=0;t<st.nY;t++){var h=st.cF(s,t),e=new P(i,st.cY*t+st.cY/2,PI/4,st.cX/1.5,4,h);cps[h].addPath(e.gp()),bbs.push(e)}}}function draw(){if(!(tokenData.plot||iP||iE)){var t,s=millis();background(st.bC),Object.keys(cps).forEach(t=>{drawingContext.save();var s=cps[t];drawingContext.clip(s),background(st.bC),stroke(t),fm.sh(),drawingContext.restore()});for(let t=0;t<bbs.length;t++)bbs[t].sb();500<s&&(t=max(map(s,500,2e3,1e3,100),100),fm.sp((s-pT)/t)),pT=s}}function dCS(s){var i=[];for(let t=0;t<s.length;t++){var h=s[t].copy();i.push(h)}return i}class F{constructor(){this.x=width/2,this.y=height/2,this.r1=width/rnd(40,15),this.r2=width/rnd(4,8),this.rF=20*rnd([1,2,4,8]),this.rO=rnd(1.5,4),this.x1=rnd(0,width/12),this.x2=width/rnd(4,2),this.y1=rnd(0,height/12),this.y2=height/rnd(4,2),this.d=rnd([-1,1]),this.sD=rnd([-1,1]),this.p=.01,this.sO=0,this.nS=rnd([3,4,5,6]),this.sP(),this.sM=rnd(-5,5),this.pD=rnd([76,100,200])}sP(){this.ps=[];let s=this.p;for(let t=this.sO;t<=st.nS+this.sO;t++){var i=map(t-this.sO,0,st.nS,this.r2,width/120),i=map(sin(t/this.rF),-1,1,this.r1,i)+i*noise(cos(t/st.nS))/2,h=map(t-this.sO,0,st.nS,this.x1,this.x2),e=map(t-this.sO,0,st.nS,this.y1,this.y2),n=h*cos(s)-e*sin(s)+this.x,e=e*cos(s)+h*sin(s)+this.y;this.ps.push(new P(n,e,s,i,this.nS,this.clr)),s+=2*this.rO*PI/st.nS*this.d}}sp(t=1){this.sO+=t*this.sM,this.p+=t/this.pD*this.sD,this.sP()}sh(){this.ps.forEach(t=>t.sh())}}function cl(i){for(let s=0;s<i.length;s++)for(let t=s+1;t<i.length;t++)rHL(i[s],i[t])}function rHL(t,s){if(t.iN(s)){var i=t.ls,h=s.ls;for(let t=0;t<i.length;t++){var e=i[t];if(s.cP(e.p1)&&s.cP(e.p2))i.splice(t,1),t--;else{var n=[];for(let t=0;t<h.length;t++){var r=h[t].gI(e);r&&n.push(r)}1===n.length?s.cP(e.p1)?i.splice(t,1,new L(n[0],e.p2)):i.splice(t,1,new L(n[0],e.p1)):2===n.length&&(p5.Vector.dist(e.p1,n[0])<p5.Vector.dist(e.p1,n[1])?i.splice(t,1,new L(n[0],e.p1),new L(n[1],e.p2)):i.splice(t,1,new L(n[0],e.p2),new L(n[1],e.p1)),t++)}}}}class St{constructor(){this.cF=this.gCF(),this.nX=3*floor(rnd(1,4)),this.nY=floor(height/width*this.nX),this.cX=width/this.nX,this.cY=height/this.nY,this.nS=rnd(300,400)}gCF(){this.bC="#f9f9fa";const i=[];for(var t=Object.keys(clrMap),s=floor(rnd(1,6));i.length<s;){var h=floor(rnd(t.length));i.push(t[h]),t.splice(h,1)}this.cs=i;var e=[(t,s)=>i[t%i.length],(t,s)=>i[s%i.length],(t,s)=>i[(t+s)%i.length]];clrMap["#eae6de"]="White",clrMap["#383131"]="Black";let n="#eae6de",r="#383131";return rnd()<.18?rnd()<.5?(this.bC=n,this.cs=[r],()=>r):(this.bC=r,this.cs=[n],()=>n):rnd(e)}}clrMap={"#ba4796":"Rose","#e0142c":"Red","#ffa038":"Orange","#12a691":"Green","#0972c4":"Blue","#842eae":"Purple","#a14725":"Brown","#00275f":"Blue Black","#85031b":"Burgundy","#67bd4f":"Fresh Green"};class P{constructor(s,i,h,t,e,n){this.x=s,this.y=i,this.c=createVector(s,i),this.p=h,this.r=t,this.nP=e,this.clr=n,this.points=[];for(let t=0;t<this.nP;t++){var r=this.p+TWO_PI*t/this.nP;const s=this.x+sin(r)*this.r,i=this.y+cos(r)*this.r;this.points.push(createVector(s,i))}this.x1=1/0,this.x2=-1/0,this.y1=1/0,this.y2=-1/0;for(let t=0;t<this.points.length;t++){const h=this.points[t];this.x1=min(this.x1,h.x),this.x2=max(this.x2,h.x),this.y1=min(this.y1,h.y),this.y2=max(this.y2,h.y)}this.ls=[];for(let t=0;t<this.points.length;t++)this.ls.push(new L(this.points[t],this.points[(t+1)%this.points.length]))}copy(){var s=new P(this.x,this.y,this.p,this.r,this.nP,this.clr);s.x1=this.x1,s.x2=this.x2,s.y1=this.y1,s.y2=this.y2,s.ls=[];for(let t=0;t<this.ls.length;t++)s.ls.push(this.ls[t].copy());return s}cP(t){if(t.x<this.x1||t.x>this.x2||t.y<this.y1||t.y>this.y2)return!1;let s=0;var i=new L(t,createVector(2*width,height+width));for(let t=0;t<this.ls.length;t++)this.ls[t].gI(i)&&s++;return s%2==1}cn(s){for(let t=0;t<this.ls.length;t++){var i=this.ls[t],h=s.cP(i.p1),e=s.cP(i.p2),n=[];for(let t=0;t<s.ls.length;t++){var r=s.ls[t].gI(i);r&&n.push(r)}0===n.length?h||e||(this.ls.splice(t,1),t--):1===n.length?h?this.ls[t].p2=n[0]:e&&(this.ls[t].p1=n[0]):2===n.length&&(this.ls[t]=new L(n[0],n[1]))}}iN(t){return p5.Vector.dist(this.c,t.c)<this.r+t.r}sh(){push(),fill(st.bC),beginShape(),this.points.forEach(t=>{vertex(t.x,t.y)}),endShape(CLOSE),pop()}sb(){push(),strokeWeight(2*width/1080),noFill(),stroke(this.clr),beginShape(),this.points.forEach(t=>{vertex(t.x,t.y)}),endShape(CLOSE),pop()}gsp(){let s="",i;for(let t=0;t<this.ls.length;t++){var h=this.ls[t],e=new L(h.p1.copy().mult(sW/width),h.p2.copy().mult(sW/width));i&&i.p2.equals(h.p1)?s+=`L ${e.p2.x} `+e.p2.y:s+=`M ${e.p1.x} ${e.p1.y} L ${e.p2.x} ${e.p2.y} `,i=h}return s}gp(){var s=new Path2D;s.moveTo(this.points[0].x,this.points[0].y);for(let t=0;t<this.points.length;t++){var i=this.points[(t+1)%this.points.length];s.lineTo(i.x,i.y)}return s}}class L{constructor(t,s){this.p1=t,this.p2=s,this.m=(s.y-t.y)/(s.x-t.x),999999999999<this.m&&(this.m=1/0),this.m<-999999999999&&(this.m=-1/0),this.b=t.y-this.m*t.x}gI(t){let s,i;i=this.m===1/0||this.m===-1/0?(s=this.p1.x,t.m*s+t.b):t.m===1/0||t.m===-1/0?(s=t.p1.x,this.m*s*this.b):(s=(t.b-this.b)/(this.m-t.m),this.m*s+this.b);var h=createVector(s,i);return this.hP(h)&&t.hP(h)?h:null}hP(t){var s=(t.y-this.p1.a)*(this.p1.x-this.p2.x)-(t.x-this.p1.x)*(this.p2.y-this.p1.y);return!(abs(s)>Number.EPSILON||(s=(t.x-this.p1.x)*(this.p2.x-this.p1.x)+(t.y-this.p1.y)*(this.p2.y-this.p1.y))<0||(this.p2.x-this.p1.x)*(this.p2.x-this.p1.x)+(this.p2.y-this.p1.y)*(this.p2.y-this.p1.y)<s)}copy(){return new L(this.p1.copy(),this.p2.copy())}}function eS(){var t=cS(),s=doc.ce("a"),t=new Blob([t.outerHTML],{type:"text/plain"});s.href=URL.createObjectURL(t),s.download=`framed_${tokenData.tokenId}.svg`,s.click(),URL.revokeObjectURL(s.href)}(doc=document).cen=doc.createElementNS,doc.ce=doc.createElement;let ns="http://www.w3.org/2000/svg";function cS(){var s=doc.cen(ns,"svg"),i=(s.sA=s.setAttribute,s.sA("class","plot"),s.sA("width",sW+"px"),s.sA("height",sH+"px"),s.sA("viewBox","0 0 "+sW+" "+sH),s.sA("xmlns","http://www.w3.org/2000/svg"),s.sA("xmlns:inkscape","http://www.inkscape.org/namespaces/inkscape"),s.sA("style",`background-color:${st.bC};stroke-linecap:round`),gSL());for(let t=0;t<i.length;t++)s.appendChild(i[t]);return s}function gSL(){var s={},i={};for(let t=0;t<st.cs.length;t++){var h=st.cs[t];i[h]=s[h]=""}for(let t=0;t<bbs.length;t++){var e=bbs[t],n=(i[e.clr]+=e.gsp(),dCS(fm.ps,fm.clr));cl(n);for(let t=0;t<n.length;t++){n[t].cn(e);var r=n[t].gsp();r&&r.length&&(s[e.clr]+=r)}}var p=[];let l=1;var o=Object.keys(i);for(let t=0;t<st.cs.length;t++){var c=st.cs[t],c=cL(l,"Form",c,s[c],1.5*sW/1080);c&&(p.push(c),l++)}for(let t=0;t<o.length;t++){var a=o[t],a=cL(l,"Frame",a,i[a],2*sW/1080);a&&(p.push(a),l++)}return p}function cL(t,s,i,h,e){var n;return""===h?null:((n=doc.cen(ns,"g")).sA=n.setAttribute,t=t+` - ${s} - `+clrMap[i],n.sA("id",t),n.sA("inkscape:groupmode","layer"),n.sA("inkscape:label",t),n.sA("style",`fill:none;stroke-width:${e};stroke:`+i),(s=doc.cen(ns,"path")).setAttribute("d",h),n.appendChild(s),n)}function keyPressed(t){"p"===t.key?(iP=!iP,pT=millis()):"i"===t.key?(iE=!0,save(`framed_${tokenData.tokenId}.png`),pT=millis(),iE=!1):"s"===t.key&&(iE=!0,eS(),pT=millis(),iE=!1)}
function setup(){let S=Uint32Array.from([0,1,ss=tt=2,3].map((tt=>parseInt(tokenData.hash.substr(8*tt+2,8),16))));function RC(q){return q[Math.floor(R()*q.length)]}function RR(q,n){return q+R()*(n-q)}R=q=>(tt=S[3],S[3]=S[2],S[2]=S[1],S[1]=ss=S[0],tt^=tt<<11,S[0]^=tt^tt>>>8^ss>>>19,S[0]/2**32);noCanvas(),noLoop();let e=parseInt(tokenData.hash.slice(0,16),16);randomSeed(e);console.log("e=",e);let o=1100;for(function(){points=[],col=[],SHOWSIDE=[],STWdt=[],La=Lb=[3,5,7,11,13,17,19,23,27,39,51,59,69,77,101,81,89,95],Lc=Ld=[2].concat(La),M=1,a=b=c=d=0;for(;1==(a==b||a==c||a==d||b==c||b==d||c==d)||a+b+c+d<=29||a+b==5||a+b>39||abs(a-b)>17||a+b+c+d>=72;)a=RC(La),b=RC(Lb),c=RC(Lc),d=RC(Ld),d=RC(Ld),colorMode(HSB,1);alph=a,beta=b,gamm=c}(),ThreeFaced=RC([0,0,0,0,0,0,0,0,0,1]),DASHEDLINE=RC([0,0,0,0,0,0,1,2]),INDECISIVE=R()>.8,TINTEDPAPER=R()>.5,BGBW=R()>.65,1==ThreeFaced?BWLines=R()>.6:BWLines=R()>.9,1==ThreeFaced&&1!=BWLines&&(BGBW=R()>.3,console.log(BGBW)),AltPalette=R()>.5,1==BWLines&&(AltPalette=0),SC=1.5,OVERLAPFACES=R()>0.9,OVERLAPFACES==1?(Over6=-1.0125,TINTEDPAPER=0,ThreeFaced=0):Over6=1,t=0,dt=.001,1==INDECISIVE?(r=.01*M,r2=0*M):(r=0,r2=0),angleX=-(25+.5*RR(-10,15))/180*PI,angleY=-(40+.5*RR(-35,35))/180*PI,angleZ=0,distance=1.5*RR(2,10),ScalFactor=100*RR(.95,1.41)*distance*2,distance=6,ScalFactor=1300,abs(180*angleY/PI+45)<2&&(angleY=-.25*PI+(3+RR(0,3))/180*PI),R()>.8&&(CuratedMode=RC([0,1,2,3,4,5]),function(){switch(CuratedMode){case 0:angleX=-.25*PI,angleY=-30/180*PI,angleZ=0*PI;break;case 1:angleX=-30/180*PI,angleY=-.25*PI,angleZ=0*PI;break;case 2:angleX=-.25*PI,angleY=-.25*PI,angleZ=0*PI;break;case 3:angleX=-30/180*PI,angleY=-30/180*PI,angleZ=0*PI;break;case 4:angleX=-.125*PI,angleY=-.25*PI,angleZ=0*PI;break;case 5:angleX=-35/180*PI,angleY=-.25*PI,angleZ=0*PI}}()),i=0;i<6;i++)points[i]=[];for(t=0,it=0;t<TAU;t+=dt,it++)x=M*RR(-r,r)+M*cos(t*alph),y=M*RR(-r,r)+M*sin(t*beta),points[0][it]=createVector(x+RR(-r2,r2),y+RR(-r2,r2),-M*Over6),points[3][it]=createVector(M,y+RR(-r2,r2),x+RR(-r2,r2)),points[5][it]=createVector(x+RR(-r2,r2),y+RR(-r2,r2),M),points[1][it]=createVector(-M*Over6,y+RR(-r2,r2),x+RR(-r2,r2)),points[2][it]=createVector(y+RR(-r2,r2),M*Over6,x+RR(-r2,r2)),points[4][it]=createVector(y+RR(-r2,r2),-M,x+RR(-r2,r2));gr=color(.33,1,1),oran=color(32/360,1,1),pur=color(.8,.81,1),cyn=color(.49,.95,.95),Colours=[gr,"blue","red","yellow",cyn,"magenta"],colorNames=["Green","Blue","Red","Yellow","Cyan","Magenta"],1==AltPalette&&(Colours=[gr,oran,pur,"blue","yellow","red"],colorNames=["Green","Orange","Purple","Blue","Yellow","Red"]),TFM=RR([1,2,3,4]),1==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red","blue",gr,"yellow"],colorNames=["Green","Blue","Red","Blue","Green","Yellow"]),2==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red",gr,cyn,"yellow"],colorNames=["Green","Blue","Red","Green","Cyan","Yellow"]),3==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red","blue",pur,"red"],colorNames=["Green","Blue","Red","Blue","Purple","Red"]),4==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red",color([.073,.91,1]),color([.9,.71,1]),color([1/6,.71,1])],colorNames=["Green","Blue","Red","Orange","Pink","Yellow"]),1==TINTEDPAPER?ConCol3=[R(),.05,1]:ConCol3=[.1,.025,1],1==ThreeFaced?SHOWSIDE=[1,1,1,0,0,0]:SHOWSIDE=[0,0,0,0,0,0],1==BGBW?1==TINTEDPAPER?ConCol3=[RC([,.15,.4,.45,.5,.6,.7,.8,.9]),.81,.01]:ConCol3=[0,0,.05]:ConCol3=ConCol3,1==BGBW&&1==BWLines&&(Colours=["white","white","white","white","white","white"]),0==BGBW&&1==BWLines&&(Colours=["black","black","black","black","black","black"]), OVERLAPFACES==1?(Colours = ["yellow", "blue", "magenta", gr, cyn, "red"], colorNames = ["Yellow", "Blue", "Magenta", "Green", "Cyan", "Red"]):0, noFill();let n="http://www.w3.org/2000/svg",l=document.createElementNS(n,"svg");l.setAttribute("width","100vw"),l.setAttribute("height","100vh"),l.setAttribute("viewBox","0 0 850 "+o),l.setAttribute("style","background-color:white;");let s=document.createElementNS(n,"path");s.setAttribute("d","M 0 0 M 850 1100"),l.appendChild(s);let u=1/0,m=-1/0,g=[];for(let e=0;e<6;e++){let t=C(points[e],e,0);g.push(t.projected),u=min(u,t.minX),m=max(m,t.maxX)}let h=-((u+m)/2);for(let e=0;e<6;e++)for(let t=0;t<g[e].length;t++)g[e][t].x+=h;let I=function(e,t,r){let o=r*t,n=o*(1-Math.abs(6*e%2-1)),l=r-o,[a,d,c]=[0,0,0];0<=6*e&&6*e<1?[a,d,c]=[o,n,0]:1<=6*e&&6*e<2?[a,d,c]=[n,o,0]:2<=6*e&&6*e<3?[a,d,c]=[0,o,n]:3<=6*e&&6*e<4?[a,d,c]=[0,n,o]:4<=6*e&&6*e<5?[a,d,c]=[n,0,o]:5<=6*e&&6*e<6&&([a,d,c]=[o,0,n]);return a=Math.round(255*(a+l)),d=Math.round(255*(d+l)),c=Math.round(255*(c+l)),`rgb(${a}, ${d}, ${c})`}(ConCol3[0],ConCol3[1],ConCol3[2]);for(l.setAttribute("style",`background-color:${I};`),i=0;i<6;i++){let e=g[i],t=document.createElementNS(n,"g");t.setAttribute("id",colorNames[i]);let r=SC*M*1,o=1==SHOWSIDE[i]?"none":Colours[i];if(0===DASHEDLINE&&0==SHOWSIDE[i]){let l=document.createElementNS(n,"path");l.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`);let a="M "+(e[0].x+425)+" "+(e[0].y+550);for(let t=1;t<e.length;t++){let r=e[t];a+=" L "+(r.x+425)+" "+(r.y+550)}l.setAttribute("d",a),t.appendChild(l)}if(2===DASHEDLINE&&0==SHOWSIDE[i])for(let l=0;l<e.length-1;l++){let a=e[l],d=e[l+1],c=document.createElementNS(n,"path");c.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`),c.setAttribute("d",`M ${a.x+425} ${a.y+550} L ${d.x+425} ${d.y+550}`),t.appendChild(c)}if(1===DASHEDLINE&&0==SHOWSIDE[i])for(let l=0;l<e.length-1;l++){let a=e[l],d=e[l+1];if(l%2==0){let e=document.createElementNS(n,"path");e.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`),e.setAttribute("d",`M ${a.x+425} ${a.y+550} L ${d.x+425} ${d.y+550}`),t.appendChild(e)}}l.appendChild(t)}function C(e,t,r){const o=[[cos(angleZ),-sin(angleZ),0],[sin(angleZ),cos(angleZ),0],[0,0,1]],n=[[1,0,0],[0,cos(angleX),-sin(angleX)],[0,sin(angleX),cos(angleX)]],l=[[cos(angleY),0,sin(angleY)],[0,1,0],[-sin(angleY),0,cos(angleY)]];let a=[];for(let t=0;t<e.length;t++){let r=P(l,e[t]);r=P(n,r),r=P(o,r);let d=1/(distance-r.z);let c=P([[d,0,0],[0,d,0]],r);c.mult(ScalFactor),a[t]=c}let d=1/0,c=-1/0;for(let e=0;e<a.length;e++)d=min(d,a[e].x),c=max(c,a[e].x);return{projected:a,minX:d,maxX:c}}function p(e,t){return function(e){return createVector(e[0][0],e[1][0],e.length>2?e[2][0]:0)}(P(e,function(e){let t=[];for(let e=0;e<3;e++)t[e]=[];return t[0][0]=e.x,t[1][0]=e.y,t[2][0]=e.z,t}(t)))}function P(e,t){if(t instanceof p5.Vector)return p(e,t);let r=e[0].length,o=e.length,n=t[0].length;if(r!==t.length)return null;result=[];for(let l=0;l<o;l++){result[l]=[];for(let o=0;o<n;o++){let n=0;for(let a=0;a<r;a++)n+=e[l][a]*t[a][o];result[l][o]=n}}return result}document.body.appendChild(l)}
function setup(){noCanvas(),noLoop();let e=parseInt(tokenData.hash.slice(0,16),16);randomSeed(e);let o=1100;for(function(){points=[],col=[],SHOWSIDE=[],STWdt=[],La=Lb=[3,5,7,11,13,17,19,23,27,39,51,59,69,77,101,81,89,95],Lc=Ld=[2].concat(La),M=1,a=b=c=d=0;for(;1==(a==b||a==c||a==d||b==c||b==d||c==d)||a+b+c+d<=29||a+b==5||a+b>39||abs(a-b)>17||a+b+c+d>=72;)a=random(La),b=random(Lb),c=random(Lc),d=random(Ld),colorMode(HSB,1);alph=a,beta=b,gamm=c}(),ThreeFaced=random([0,0,0,0,0,0,0,0,0,1]),DASHEDLINE=random([0,0,0,0,0,0,1,2]),INDECISIVE=random()>.8,TINTEDPAPER=random()>.5,BGBW=random()>.65,1==ThreeFaced?BWLines=random()>.6:BWLines=random()>.9,1==ThreeFaced&&1!=BWLines&&(BGBW=random()>.3,console.log(BGBW)),AltPalette=random()>.5,1==BWLines&&(AltPalette=0),SC=1.5,OVERLAPFACES=random()>0.9,OVERLAPFACES==1?(Over6=-1.03,TINTEDPAPER=0,ThreeFaced=0):Over6=1,t=0,dt=.001,1==INDECISIVE?(r=.01*M,r2=0*M):(r=0,r2=0),angleX=-(25+.5*random(-10,15))/180*PI,angleY=-(40+.5*random(-35,35))/180*PI,angleZ=0,distance=1.5*random(2,10),ScalFactor=100*random(.95,1.41)*distance*2,distance=6,ScalFactor=1300,abs(180*angleY/PI+45)<2&&(angleY=-.25*PI+(3+random(0,3))/180*PI),random()>.8&&(CuratedMode=random([0,1,2,3,4,5]),function(){switch(CuratedMode){case 0:angleX=-.25*PI,angleY=-30/180*PI,angleZ=0*PI;break;case 1:angleX=-30/180*PI,angleY=-.25*PI,angleZ=0*PI;break;case 2:angleX=-.25*PI,angleY=-.25*PI,angleZ=0*PI;break;case 3:angleX=-30/180*PI,angleY=-30/180*PI,angleZ=0*PI;break;case 4:angleX=-.125*PI,angleY=-.25*PI,angleZ=0*PI;break;case 5:angleX=-35/180*PI,angleY=-.25*PI,angleZ=0*PI}}()),i=0;i<6;i++)points[i]=[];for(t=0,it=0;t<TAU;t+=dt,it++)x=M*random(-r,r)+M*cos(t*alph),y=M*random(-r,r)+M*sin(t*beta),points[0][it]=createVector(x+random(-r2,r2),y+random(-r2,r2),-M*Over6),points[3][it]=createVector(M,y+random(-r2,r2),x+random(-r2,r2)),points[5][it]=createVector(x+random(-r2,r2),y+random(-r2,r2),M),points[1][it]=createVector(-M*Over6,y+random(-r2,r2),x+random(-r2,r2)),points[2][it]=createVector(y+random(-r2,r2),M*Over6,x+random(-r2,r2)),points[4][it]=createVector(y+random(-r2,r2),-M,x+random(-r2,r2));gr=color(.33,1,1),oran=color(32/360,1,1),pur=color(.8,.81,1),cyn=color(.49,.95,.95),Colours=[gr,"blue","red","yellow",cyn,"magenta"],colorNames=["Green","Blue","Red","Yellow","Cyan","Magenta"],1==AltPalette&&(Colours=[gr,oran,pur,"blue","yellow","red"],colorNames=["Green","Orange","Purple","Blue","Yellow","Red"]),TFM=random([1,2,3,4]),1==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red","blue",gr,"yellow"],colorNames=["Green","Blue","Red","Blue","Green","Yellow"]),2==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red",gr,cyn,"yellow"],colorNames=["Green","Blue","Red","Green","Cyan","Yellow"]),3==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red","blue",pur,"red"],colorNames=["Green","Blue","Red","Blue","Purple","Red"]),4==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red",color([.073,.91,1]),color([.9,.71,1]),color([1/6,.71,1])],colorNames=["Green","Blue","Red","Orange","Pink","Yellow"]),1==TINTEDPAPER?ConCol3=[random(),.05,1]:ConCol3=[.1,.025,1],1==ThreeFaced?SHOWSIDE=[1,1,1,0,0,0]:SHOWSIDE=[0,0,0,0,0,0],1==BGBW?1==TINTEDPAPER?ConCol3=[random([,.15,.4,.45,.5,.6,.7,.8,.9]),.81,.01]:ConCol3=[0,0,.05]:ConCol3=ConCol3,1==BGBW&&1==BWLines&&(Colours=["white","white","white","white","white","white"]),0==BGBW&&1==BWLines&&(Colours=["black","black","black","black","black","black"]), OVERLAPFACES==1?(Colours = ["yellow", "blue", "magenta", gr, cyn, "red"], colorNames = ["Yellow", "Blue", "Magenta", "Green", "Cyan", "Red"]):0, noFill();let n="http://www.w3.org/2000/svg",l=document.createElementNS(n,"svg");l.setAttribute("width","100vw"),l.setAttribute("height","100vh"),l.setAttribute("viewBox","0 0 850 "+o),l.setAttribute("style","background-color:white;");let s=document.createElementNS(n,"path");s.setAttribute("d","M 0 0 M 850 1100"),l.appendChild(s);let u=1/0,m=-1/0,g=[];for(let e=0;e<6;e++){let t=C(points[e],e,0);g.push(t.projected),u=min(u,t.minX),m=max(m,t.maxX)}let h=-((u+m)/2);for(let e=0;e<6;e++)for(let t=0;t<g[e].length;t++)g[e][t].x+=h;let I=function(e,t,r){let o=r*t,n=o*(1-Math.abs(6*e%2-1)),l=r-o,[a,d,c]=[0,0,0];0<=6*e&&6*e<1?[a,d,c]=[o,n,0]:1<=6*e&&6*e<2?[a,d,c]=[n,o,0]:2<=6*e&&6*e<3?[a,d,c]=[0,o,n]:3<=6*e&&6*e<4?[a,d,c]=[0,n,o]:4<=6*e&&6*e<5?[a,d,c]=[n,0,o]:5<=6*e&&6*e<6&&([a,d,c]=[o,0,n]);return a=Math.round(255*(a+l)),d=Math.round(255*(d+l)),c=Math.round(255*(c+l)),`rgb(${a}, ${d}, ${c})`}(ConCol3[0],ConCol3[1],ConCol3[2]);for(l.setAttribute("style",`background-color:${I};`),i=0;i<6;i++){let e=g[i],t=document.createElementNS(n,"g");t.setAttribute("id",colorNames[i]);let r=SC*M*1,o=1==SHOWSIDE[i]?"none":Colours[i];if(0===DASHEDLINE&&0==SHOWSIDE[i]){let l=document.createElementNS(n,"path");l.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`);let a="M "+(e[0].x+425)+" "+(e[0].y+550);for(let t=1;t<e.length;t++){let r=e[t];a+=" L "+(r.x+425)+" "+(r.y+550)}l.setAttribute("d",a),t.appendChild(l)}if(2===DASHEDLINE&&0==SHOWSIDE[i])for(let l=0;l<e.length-1;l++){let a=e[l],d=e[l+1],c=document.createElementNS(n,"path");c.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`),c.setAttribute("d",`M ${a.x+425} ${a.y+550} L ${d.x+425} ${d.y+550}`),t.appendChild(c)}if(1===DASHEDLINE&&0==SHOWSIDE[i])for(let l=0;l<e.length-1;l++){let a=e[l],d=e[l+1];if(l%2==0){let e=document.createElementNS(n,"path");e.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`),e.setAttribute("d",`M ${a.x+425} ${a.y+550} L ${d.x+425} ${d.y+550}`),t.appendChild(e)}}l.appendChild(t)}function C(e,t,r){const o=[[cos(angleZ),-sin(angleZ),0],[sin(angleZ),cos(angleZ),0],[0,0,1]],n=[[1,0,0],[0,cos(angleX),-sin(angleX)],[0,sin(angleX),cos(angleX)]],l=[[cos(angleY),0,sin(angleY)],[0,1,0],[-sin(angleY),0,cos(angleY)]];let a=[];for(let t=0;t<e.length;t++){let r=P(l,e[t]);r=P(n,r),r=P(o,r);let d=1/(distance-r.z);let c=P([[d,0,0],[0,d,0]],r);c.mult(ScalFactor),a[t]=c}let d=1/0,c=-1/0;for(let e=0;e<a.length;e++)d=min(d,a[e].x),c=max(c,a[e].x);return{projected:a,minX:d,maxX:c}}function p(e,t){return function(e){return createVector(e[0][0],e[1][0],e.length>2?e[2][0]:0)}(P(e,function(e){let t=[];for(let e=0;e<3;e++)t[e]=[];return t[0][0]=e.x,t[1][0]=e.y,t[2][0]=e.z,t}(t)))}function P(e,t){if(t instanceof p5.Vector)return p(e,t);let r=e[0].length,o=e.length,n=t[0].length;if(r!==t.length)return null;result=[];for(let l=0;l<o;l++){result[l]=[];for(let o=0;o<n;o++){let n=0;for(let a=0;a<r;a++)n+=e[l][a]*t[a][o];result[l][o]=n}}return result}document.body.appendChild(l)}
Since first encountering Lissajous curves on an oscilloscope in the mid-2000s, I have been fascinated by the intricate patterns and structures that emerge from one of the most fundamental curves in mathematics, the sine curve. Lissajous curves are a family of complex, looping shapes formed by the intersection of two sine waves. This fascination inspired me to create this generative art project entitled "Lissajous," where I have experimented extensively with these curves as primitive shapes to craft a diverse range of images showcasing their beauty and complexity. By adjusting the frequency, phase shift, and amplitude of the parametric equations, it is possible to create unique and mesmerizing patterns. Over the years, I have explored various ways to bring these images to life. Some have been transformed into physical prints, utilizing techniques such as intaglio printing, cyanotypes, and various other printmaking methods, while others have been realized as digital monoprints. This iteration of the project features carefully curated color palettes and themes designed specifically with the AxiDraw plotter in mind. Each piece in the collection allows for customization, providing the opportunity to choose from different base colors and select the pen and paper that best fits the holder's individual taste. #### Suggestions for Plotting - Paper and Pens **Black paper:** - Fabriano Black Pad, 11.75" x 16.5" **Best pens for black paper:** - SAKURA - Gelly Roll - Posca PC-1MR Metallic Pink Colour Paint Marker (Archival) **White Paper:** - BFK Rives Blanc - Somerset Satin Soft White **Pens for white paper:** - Triplus Fineliner Superfine - WHSmith Drawing Pens Pigment Ink (Archival) - STABILO point 88 Fineliner - BIC Cristal Any of the pens suggested for black paper will also work on the white paper, but the black paper requires pens with opaque inks. #### Prints Signed prints will be available to any token holder interested in purchasing one. Please reach out to me on Discord or Twitter, I will be happy to take into account any customizations or requests before plotting the piece with my AxiDraw.
function setup(){noCanvas(),noLoop();let e=parseInt(tokenData.hash.slice(0,16),16);randomSeed(e);let o=1100;for(function(){points=[],col=[],SHOWSIDE=[],STWdt=[],La=Lb=[3,5,7,11,13,17,19,23,27,39,51,59,69,77,101,81,89,95],Lc=Ld=[2].concat(La),M=1,a=b=c=d=0;for(;1==(a==b||a==c||a==d||b==c||b==d||c==d)||a+b+c+d<=29||a+b==5||a+b>39||abs(a-b)>17||a+b+c+d>=72;)a=random(La),b=random(Lb),c=random(Lc),d=random(Ld),colorMode(HSB,1);alph=a,beta=b,gamm=c}(),ThreeFaced=random([0,0,0,0,0,0,0,0,0,1]),DASHEDLINE=random([0,0,0,0,0,0,1,2]),INDECISIVE=random()>.8,TINTEDPAPER=random()>.5,BGBW=random()>.65,1==ThreeFaced?BWLines=random()>.6:BWLines=random()>.9,1==ThreeFaced&&1!=BWLines&&(BGBW=random()>.3,console.log(BGBW)),AltPalette=random()>.5,1==BWLines&&(AltPalette=0),SC=1.5,OVERLAPFACES=random()>0.95,OVERLAPFACES==1?(Over6=-1.01,TINTEDPAPER=0,ThreeFaced=0):Over6=1,t=0,dt=.001,1==INDECISIVE?(r=.01*M,r2=0*M):(r=0,r2=0),angleX=-(25+.5*random(-10,15))/180*PI,angleY=-(40+.5*random(-35,35))/180*PI,angleZ=0,distance=1.5*random(2,10),ScalFactor=100*random(.95,1.41)*distance*2,distance=6,ScalFactor=1300,abs(180*angleY/PI+45)<2&&(angleY=-.25*PI+(3+random(0,3))/180*PI),random()>.8&&(CuratedMode=random([0,1,2,3,4,5]),function(){switch(CuratedMode){case 0:angleX=-.25*PI,angleY=-30/180*PI,angleZ=0*PI;break;case 1:angleX=-30/180*PI,angleY=-.25*PI,angleZ=0*PI;break;case 2:angleX=-.25*PI,angleY=-.25*PI,angleZ=0*PI;break;case 3:angleX=-30/180*PI,angleY=-30/180*PI,angleZ=0*PI;break;case 4:angleX=-.125*PI,angleY=-.25*PI,angleZ=0*PI;break;case 5:angleX=-35/180*PI,angleY=-.25*PI,angleZ=0*PI}}()),i=0;i<6;i++)points[i]=[];for(t=0,it=0;t<TAU;t+=dt,it++)x=M*random(-r,r)+M*cos(t*alph),y=M*random(-r,r)+M*sin(t*beta),points[0][it]=createVector(x+random(-r2,r2),y+random(-r2,r2),-M*Over6),points[3][it]=createVector(M,y+random(-r2,r2),x+random(-r2,r2)),points[5][it]=createVector(x+random(-r2,r2),y+random(-r2,r2),M),points[1][it]=createVector(-M*Over6,y+random(-r2,r2),x+random(-r2,r2)),points[2][it]=createVector(y+random(-r2,r2),M*Over6,x+random(-r2,r2)),points[4][it]=createVector(y+random(-r2,r2),-M,x+random(-r2,r2));gr=color(.33,1,1),oran=color(32/360,1,1),pur=color(.8,.81,1),cyn=color(.49,.95,.95),Colours=[gr,"blue","red","yellow",cyn,"magenta"],colorNames=["Green","Blue","Red","Yellow","Cyan","Magenta"],1==AltPalette&&(Colours=[gr,oran,pur,"blue","yellow","red"],colorNames=["Green","Orange","Purple","Blue","Yellow","Red"]),TFM=random([1,2,3,4]),1==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red","blue",gr,"yellow"],colorNames=["Green","Blue","Red","Blue","Green","Yellow"]),2==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red",gr,cyn,"yellow"],colorNames=["Green","Blue","Red","Green","Cyan","Yellow"]),3==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red","blue",pur,"red"],colorNames=["Green","Blue","Red","Blue","Purple","Red"]),4==TFM&&1==ThreeFaced&&(Colours=[gr,"blue","red",color([.073,.91,1]),color([.9,.71,1]),color([1/6,.71,1])],colorNames=["Green","Blue","Red","Orange","Pink","Yellow"]),1==TINTEDPAPER?ConCol3=[random(),.05,1]:ConCol3=[.1,.025,1],1==ThreeFaced?SHOWSIDE=[1,1,1,0,0,0]:SHOWSIDE=[0,0,0,0,0,0],1==BGBW?1==TINTEDPAPER?ConCol3=[random([,.15,.4,.45,.5,.6,.7,.8,.9]),.81,.01]:ConCol3=[0,0,.05]:ConCol3=ConCol3,1==BGBW&&1==BWLines&&(Colours=["white","white","white","white","white","white"]),0==BGBW&&1==BWLines&&(Colours=["black","black","black","black","black","black"]), OVERLAPFACES==1?(Colours = ["yellow", "blue", "magenta", gr, cyn, "red"], colorNames = ["Yellow", "Blue", "Magenta", "Green", "Cyan", "Red"]):0, noFill();let n="http://www.w3.org/2000/svg",l=document.createElementNS(n,"svg");l.setAttribute("width","100vw"),l.setAttribute("height","100vh"),l.setAttribute("viewBox","0 0 850 "+o),l.setAttribute("style","background-color:white;");let s=document.createElementNS(n,"path");s.setAttribute("d","M 0 0 M 850 1100"),l.appendChild(s);let u=1/0,m=-1/0,g=[];for(let e=0;e<6;e++){let t=C(points[e],e,0);g.push(t.projected),u=min(u,t.minX),m=max(m,t.maxX)}let h=-((u+m)/2);for(let e=0;e<6;e++)for(let t=0;t<g[e].length;t++)g[e][t].x+=h;let I=function(e,t,r){let o=r*t,n=o*(1-Math.abs(6*e%2-1)),l=r-o,[a,d,c]=[0,0,0];0<=6*e&&6*e<1?[a,d,c]=[o,n,0]:1<=6*e&&6*e<2?[a,d,c]=[n,o,0]:2<=6*e&&6*e<3?[a,d,c]=[0,o,n]:3<=6*e&&6*e<4?[a,d,c]=[0,n,o]:4<=6*e&&6*e<5?[a,d,c]=[n,0,o]:5<=6*e&&6*e<6&&([a,d,c]=[o,0,n]);return a=Math.round(255*(a+l)),d=Math.round(255*(d+l)),c=Math.round(255*(c+l)),`rgb(${a}, ${d}, ${c})`}(ConCol3[0],ConCol3[1],ConCol3[2]);for(l.setAttribute("style",`background-color:${I};`),i=0;i<6;i++){let e=g[i],t=document.createElementNS(n,"g");t.setAttribute("id",colorNames[i]);let r=SC*M*1,o=1==SHOWSIDE[i]?"none":Colours[i];if(0===DASHEDLINE&&0==SHOWSIDE[i]){let l=document.createElementNS(n,"path");l.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`);let a="M "+(e[0].x+425)+" "+(e[0].y+550);for(let t=1;t<e.length;t++){let r=e[t];a+=" L "+(r.x+425)+" "+(r.y+550)}l.setAttribute("d",a),t.appendChild(l)}if(2===DASHEDLINE&&0==SHOWSIDE[i])for(let l=0;l<e.length-1;l++){let a=e[l],d=e[l+1],c=document.createElementNS(n,"path");c.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`),c.setAttribute("d",`M ${a.x+425} ${a.y+550} L ${d.x+425} ${d.y+550}`),t.appendChild(c)}if(1===DASHEDLINE&&0==SHOWSIDE[i])for(let l=0;l<e.length-1;l++){let a=e[l],d=e[l+1];if(l%2==0){let e=document.createElementNS(n,"path");e.setAttribute("style",`fill:none;stroke-width:${r};stroke:${o}`),e.setAttribute("d",`M ${a.x+425} ${a.y+550} L ${d.x+425} ${d.y+550}`),t.appendChild(e)}}l.appendChild(t)}function C(e,t,r){const o=[[cos(angleZ),-sin(angleZ),0],[sin(angleZ),cos(angleZ),0],[0,0,1]],n=[[1,0,0],[0,cos(angleX),-sin(angleX)],[0,sin(angleX),cos(angleX)]],l=[[cos(angleY),0,sin(angleY)],[0,1,0],[-sin(angleY),0,cos(angleY)]];let a=[];for(let t=0;t<e.length;t++){let r=P(l,e[t]);r=P(n,r),r=P(o,r);let d=1/(distance-r.z);let c=P([[d,0,0],[0,d,0]],r);c.mult(ScalFactor),a[t]=c}let d=1/0,c=-1/0;for(let e=0;e<a.length;e++)d=min(d,a[e].x),c=max(c,a[e].x);return{projected:a,minX:d,maxX:c}}function p(e,t){return function(e){return createVector(e[0][0],e[1][0],e.length>2?e[2][0]:0)}(P(e,function(e){let t=[];for(let e=0;e<3;e++)t[e]=[];return t[0][0]=e.x,t[1][0]=e.y,t[2][0]=e.z,t}(t)))}function P(e,t){if(t instanceof p5.Vector)return p(e,t);let r=e[0].length,o=e.length,n=t[0].length;if(r!==t.length)return null;result=[];for(let l=0;l<o;l++){result[l]=[];for(let o=0;o<n;o++){let n=0;for(let a=0;a<r;a++)n+=e[l][a]*t[a][o];result[l][o]=n}}return result}document.body.appendChild(l)}
let seed="",A_R=1.25,D_S=1600,DIM=Math.min(window.innerWidth,window.innerHeight/A_R),S=DIM/D_S;function presetup(){canvas=createCanvas(1600*S,1600*A_R*S),setupUseful()}function keyPressed(){"s"===key&&save("pattern"),"d"===key&&generateEmbroiderySVG(5.5/A_R*10*2.5)}let P,LP,pa={},N_B=24;function setupParams(e={}){e.notreset||(rays=[]),pa.n=e.n??rnd([2,4,7,20]),pa.NC=e.NC??100;for(let t=0;t<pa.NC;t++){let t=vec(W/2,H/2);pa.NC>1&&(t=rndvec(0,W,0,H)),pa.O=e.O??rnd(TAU);for(let e=0;e<TAU;e+=TAU/pa.n){let A=new Poly([t],0,0,1,0,0);A.dir=vec(cos(e+pa.O),sin(e+pa.O)),rays.push(A)}}pa.SR=e.SR??1,pa.A=e.A??rnd([0,1,2,3,4]),pa.SM=e.SM??rnd([0,1]),pa.i=e.i??5e3,pa.B=e.B??[];let t=Poly.rect(W/2,H/2,W,H);t.S.push(t.S[0].copy()),pa.B.push(t),pa.DD=0,pa.DDS=e.DDS??1,pa.BBA=0;let A=color,r=A(121,23,44),s=A(26,46,35),n=A(142,120,82),i=A(12,22,32),l=A(34,34,35),o=A(52,54,51),a=A(247,175,41),g=A(225),w=A(240);pa.c=pa.c??rnd([{bg:g,BBL:l,BBS:l,BBF:w,LBS:l,LBF:-1,LBH:rnd([A(0),A(0),A(0),A(0),a,r,n,s]),TF:l},{bg:l,BBL:w,BBS:A(255),BBF:i,LBS:w,LBF:-1,LBH:rnd([A(255),A(255),A(255),A(255),a,s,o]),TF:g},{bg:s,BBL:r,BBS:a,BBF:r,LBS:a,LBF:-1,LBH:a,TF:a}]),pa.B=[];let p=[{s:"AToncwQgBZ+A5P89+wOf/O9wOAE6/wjgBV/weAAB/wTgDI/gIQDM/g+/+5/gjAOaAAAADgAgLgvjAQAAAe/QRvGF/Q8v/Q/gtf/N/QaP+R/QEP9E/Q5P6k/QAv6t/AlwRV/Qlwd3/AOAGMAgjgBWAAxgA4AAhwgbAQbgNIAAcgAqAAOADGAAOAHwBQjgAIBATwAZBAIgDgAwAADgAwwP9wAgqf+KAQj/+sAQTPSW4wtAtqHA7//qOg5PwAAA8v843AYwEDAAnf79/wBQCZ9AWQECAAp/7+/wCAB99AVgEBAAqv7//wAQCs/g//9UAQyv0BAANgL//w+P+DCw0v0CAALgL+/w+/9nCw1/0DAAKQL9/wDgDIIwHAMAAA/v/cCA4/+pAAj/9xAAue8AAAJvWP/wHQCS/A1wF50wAAyQAAx//N+Qc/R1/wxv8uBg8/rK/wVADM+Q8wQ8AA"},{y:2050,s:"t1VSiQNwA73wCwBg7AAwCQ+w1P8N/Qov9I/gov/S/gP/9w/g+v57/g+f4n/wRv4K/wAf5r/w8vhS/wdf8n+w5wUZAAYAHu/wxgHH/w8QGH/wxgFL/w7QBU/w1QD8/glgCp/gLgCv/gCADf/g1/+A/grf8j/gvP0d9wlP4g+Q+goUAgLgL0/w7wAJAAjgAjAATQAlAASgBoAAHwDFAA+QAtBgZwCGAwPQBaBAEQCfAw4v8XBAgv9lAws/8QAQkv+GAQx/TH4gOQs5HQkv+oAwaf/FPw8/+9AA3P8wAAyv8VAAcv8KAA5fXq/w"},{s:"iBV1Bwpg6Z+A6ATKCQYAR5BwoQLfAw1wM7BQKQVsBgJQYTBwqv+yAAuP8QAQBgBRAQPQBpAQnwAGAgKwF/AwogCDAgbADKAg/v/gAQu/+pAQZv97AQE/9hAQ3P4YAQoP7QAAvv5wAAu/45AA5v4CAAMv7Z/wg/2W/wqf/f/wkf92/wgP1r/Abv02/Avfqp9wo/xB+gs/la9A+fwp+g2fdz7w"},{s:"TAkeDAwvbhBwSgcrCAXAGeAQnwO+BAmwNRBQMAMXBQDgNKBQ0wGYAwbAOABg6QD6/g2wBK/wQQFI/wSwFx/wogGl/wEQIDAAtQFFAADQKaAAfgHHAAFwJ0AQawQpAw8fzl+Q0f7h/QkP2k+wQ/2/+wk/w3+wHvwK+wRfmy9wc/vQ+glPr6+QivsA+w"},{s:"wQ6OSgHgTp/QZwSm/QCgM9/gEQEe/w/wCqAAZAGAAA7gFGAApwMAAAcgD4CAAABXHwAADUEQAAAwKw2eoAAAAACR/AVQFA1wqgAr7wHAB59wj/9f9QxgCq/w5P8g/Quf+u/AgP90/AZf8l/QK/9u/Q"},{s:"cUOrJQbwet/w8P8g/gBAAK/gzP8r/A9P9Y/gJACo/gFgDr/gRQC9/gBwHG/QDwBz/w3/+n/wt/+p/w/P1C/gJPu1BAsf8qAAF//5AAt//LAAy//eAA9f8tAQ+P9WAQIQDqAwOgCdBA"},{s:"NiiKXwBAEcAAUAEdAAcAHj/wcQG+/weQFg/wSwE5/wIwEW/wMQF1/gOQCiEA/gEEPQm/CNAAGwK+yQOQCV+AOABZ+wVQAj+A"},{y:2050,s:"8EztwAAAAf/QXvVX/gHQDEAghQrGAQ"},{y:2050,s:"jkUXtQAADN+Qge9W/wq/8XBg1BDGAA"},{s:"DVlOFglfjgBAOAFTAgjQCqAAegAvAA2gDf/wKgHI/wzwHV/wygEdAAqQJxAASQI4AAqgsAAAVAK6/whQKd/wEgLj/wxAE5AALAE5AAqwAAAAcQDH/wqQEf/Qefgg+wO/2pAQnv21AAEP4vAAjfcAAAwv2a/wLv5Y/wdP2B/g"},{s:"x1e7IA4wD/AQjQAcAA6QABAA+gAbAARRIAAA/wDk/w4wAAAAcQDk/w4wAB/gOv4cAAyvwAAAAf8dAARPMAAA5f7j/w5vwAAAHv7k/w"}];pa.LL=[],LP=p.map((e=>{let t=new Poly(DP(e.s),90*S,350*S,3.5*S);return t.MW(),t=new Poly(t.S,0,e.y?e.y*S:0,.9,e.r),t})),pa.LL=p.map(((e,t)=>{let A=new Poly(LP[t].S,0,0,.9);return LP[t].LS=A,A})),pa.LL.map((e=>{let t=new Poly(e.S.map((e=>vec(W-e.x,e.y))));t.MW(),e.setColor(pa.c.BBL,pa.c.bg),t.setColor(pa.c.BBL,pa.c.bg),pa.LL.push(t)}))}function placeAll(){patterns=LP;let e=[];do{print("LAYOUT ATTEMPT"),e=[],patterns=[...shuffle(patterns.slice(0,4)),...shuffle(patterns.slice(4,9)),...shuffle(patterns.slice(9))],e.push(new Poly([vec(W/2-1*S,H/2),vec(W/2,H/2)])),patterns.map(((t,A)=>{if(patterns.length-A+e.length<N_B/2)return;let r=[];e.map((e=>{r.push(...e.HCPD())}));let s=t.TWR(e,r);s&&(s.highCurvePreselected=t.highCurvePreselected,s.LS=t.LS,e.push(s))}))}while(e.length<N_B/2);pa.B=[];let t={bbr:0,bbt:H,bbb:0};e.map((e=>{let A=new Poly(e.S,0,0,.9);A.LS=e.LS,A.bbr>t.bbr&&(t.bbr=A.bbr),A.bbb>t.bbb&&(t.bbb=A.bbb),A.bbt<t.bbt&&(t.bbt=A.bbt),pa.B.push(A)}));let A=pa.B.length;for(let e=0;e<A;e++){let A=pa.B[e];A.translate(-t.bbr+W/2,-t.bbt+(t.bbt+(H-t.bbb))/2-40*S);let r=new Poly(A.S.map((e=>vec(W-e.x,e.y))));r.MW(),pa.B.push(r)}pa.B=shuffle(pa.B);let r=pa.B.filter((e=>17==e.S.length)),s=pa.B.filter((e=>28==e.S.length));r[0].LS||(r[0].LS=new Poly(r[1].LS.S.map((e=>vec(W-e.x,e.y)))),r[0].LS.MW()),s[0].LS||(s[0].LS=new Poly(s[1].LS.S.map((e=>vec(W-e.x,e.y)))),s[0].LS.MW()),pa.B.splice(pa.B.indexOf(r[1]),1),pa.B.splice(pa.B.indexOf(s[1]),1);let n="pBCQBgAAD0/Auv9g/wdP9g/wwP4k/wNP4u/wmP6m/wbP3O/wqP1aAAev6WAA6P6qAA+P3qAQyv4wAgiP/CAQ4v/mAAAADwAAKABAAQRgAEAQ0gDWAQVAGuAQVAEYAQ4AHwAAaAFkAAaAEoAAXgEAAAVAHY/wkAGS/wzAEu/wSgEa/wUACw/wRgCc/wHgCc/wAADy/gAAA+/gFAB+/wFACw/wMgCc/wPACw/wWgCw/wRvsAAAWgBGAARgBkAAMgBuAAHgCMAACgCAAg9v9uAAxP+gAAnP9uAA/P6+AABv9uAAjv5aAA3v4AAAwP66/wyv5g/w/P4G/wTP/y/gVv+Y/gfv8M/g2P+E/gHgCO/geAD4/QqgCE/gqgDe/g0gAu/wNgFC/w5gCm/w3ADi/w3AAAAAGAEoAALAFkAAGAGWAAIgHmAA0gDmAAvgDwAAtABAAQ",i="kCmAAgAAAACg2P/mAAdP8iAQQv/IAA8v6gAA3v5kAAjv48AAwP72/w1P7E/w6P6c/wTP+I/wav90/wfv9M/wpv8u/w2P8Q/w9v84/wAADm9gMgAk/wUAB+/wbgCS/wbvsAAAWgBaAAbgCqAAHgDwAAAADUCACgAsAQHgCWAAjABeAQ8AAiAQLAHSAAQAGCAAVAFaAAQAEoAAVAEAAASgHO/w+gDE/wIgGS/wGAFg/wtABq/wqgAk/wZAAu/wMgAk/wFABM/wAAAy9gCgCw/wHgCI/wMgCc/wUACm/wRgDE/wTv0AAAUABGAARgBQAAKABGAAHgBkAA",l="JEWGBgiP/8/gav8Q/wGv/e/gwP7U/ghP4u/wZv6I/wov7i/w1P4oAAov6WAAGv++AALv/6AAfv/mAAnP/mAApv8YAQxP8EAQ4v8sAQCgBKAQMgBUAQKAC+AAeABKAQ0gB8AQlgC0AAyACgAAyAB4AA5gBQAABAEoAA3AD2/wvgDi/wDgG6/w3ACm/wLAFM/wIgEk/w8AAG/wqgAa/wjADy/gPACI/wkv80Aw9v8oAAxP9uAAsP9aAAEP++AA1P6qAAmP6MAAZv5aAAcP4oAArP7s/wcP66/w8v6c/wQv+w/wyv44/wLv9M/wav9W/wJP/e/gfv/8/gnP/o/guv+O/gAACi/gHgDo/gUADU/geADU/goADo/goAAu/waAG2/gNgFC/w+gCS/w0gC6/wIgHO/wLAHi/wpAEUAADgEoAAIgFQAANgGCAANgG0AAIgHwAAUACgAACgBQAA",o="zm2KAgAAC8DAAACgAAFACMAAMgCCAAZACCAAMgAyAAjPsAAAZACc/wRgCI/wMgBq/wAABg/wAADC8g4v9+/wxP9+/wnP+S/w2P/Y/wkgQAAAkv9kAAuv9kAA4v9aAA7P9QAA";n=DP(n),i=DP(i),l=DP(l),o=DP(o),pa.G=[];let a=[n,i,l,o];a=a.map((e=>new Poly(e,0,0,.8*S))),a.map((e=>e.S.map((e=>e.add(vec(.43*W,.93*H)))))),a.push(new Poly(a[2].S,55*S)),a.map((e=>{e.setColor(pa.c.BBF,pa.c.BBS),pa.G.push(e)})),redraw()}let vec,rndvec,canvas,W,H,rnd,sn,q=[],rays=[];function setup(){presetup(),strokeWeight(2*S);P=rnd([{n:20,NC:250,A:0,i:5e3,SM:0,DDS:.05},{n:2,NC:200,A:2,i:1e4,DDS:.11},{n:2,NC:5e3,A:4,i:2e4,SM:0,DDS:.05},{n:2,NC:100,SR:1,A:0,i:3e4,DDS:.06}]),setupParams(P),background(pa.c.bg),noFill(),strokeJoin(BEVEL),textFont("Georgia");if(background(pa.c.bg),push(),noStroke(),fill(pa.c.TF),textAlign(CENTER,CENTER),textSize(20*S),text("LOADING",W/2,120*S),pop(),pa.LL.map((e=>{e.draw()})),placeAll(),!pa.RR){let e,t;for(pa.LL.map((e=>e.draw())),e=rays,t=rays.slice(0),iters=0;t.length&&iters<pa.i;){iters++;let A=t.shift(),r=[...pa.B];pa.SR&&(r=[...r,...e]);let s=A.rayIntersect(r,A.dir);if(s){A.addPoint(s.point);let e=reflect(A.dir,s,0);e&&(A.dir=e,t.push(A))}}strokeWeight(1*S),pa.RR=[],pa.SM?e.map((e=>{pa.B.reduce(((t,A)=>t+A.contains(e.S[0])),0)>0&&(e.S.splice(0,0,e.S[0].copy()),pa.RR.push(e))})):e.map(((e,t)=>{pa.B.reduce(((t,A)=>t+A.contains(e.S[0])),0)>0&&pa.RR.push(e)})),pa.RR.map((e=>{e.setColor(pa.c.LBF,pa.c.LBS),rnd()<.05&&e.setColor(pa.c.LBF,pa.c.LBH)})),print("RENDERED")}for(let e=0;e<pa.B.length;e++){let t=pa.B[e];if(t.setColor(pa.c.BBF,pa.c.BBS),!t.stitches&&e<N_B){t.stitches=[];let e=t.outline(1.1).stepnodes(10*S),A=!1;for(let r=0;r<e.length-1;r+=2){(!A&&rnd()<.008||A&&rnd()<.02)&&(A=!A);let s=e[r],n=e[r+1];if(A){let e=new Poly([s,n]);e.setColor(-1,pa.c.BBS),lin2=e.copy().reflect([0],vec(W/2,H/2),1,1),t.stitches.push(e,lin2)}}}if(!t.CP&&e<N_B&&(t.CP=t.HCPD().map((e=>e[0])).filter((()=>rnd()<.1)),t.registration=t.HCPD(0).filter(((e,t)=>!(t%8))).filter((e=>!t.contains(p5.Vector.add(e[0],e[1]))))),!t.labels){t.labels=[];for(let e=0;e<3;e++){let e=draw.toString().replace(/\s+/g,""),A=floor(rnd(e.length-10)),r=t.label(e.substring(A,A+floor(rnd(5,10))));if(!r)continue;let s=100*S;r.p.overlapsCount(pa.B)<=1&&r.p.onCanvas(s,W-s,s,H-s)&&t.labels.push(r)}}}}function draw(){if(!(frameCount<100)){randomSeed(seed),blendMode(BLEND),background(pa.c.bg),loop();for(let e=0;e<pa.B.length;e++){strokeWeight(2*S);let t=pa.B[e];if(pa.BBA<1)return pa.BBA+=.003,void pa.B.map(((e,t)=>{if(!e.LS)return;let A=1-(cos(PI*(1-pa.BBA))+1)/2,r=e.morph([[e.S[0],e.S[1]]],[[e.LS.S[0],e.LS.S[1]]],A),s=r.copy().reflect([PI/2],vec(W/2,H/2),1,1),n=lerpColor(color(pa.c.bg),color(pa.c.BBS),1-A),i=lerpColor(color(pa.c.BBL),color(pa.c.BBF),1-A);r.setColor(i,n),s.setColor(i,n),17!=e.S.length&&28!=e.S.length&&s.draw(),r.draw()}));strokeWeight(S),pa.G.map((e=>{e.draw()})),t.stitches&&t.stitches.map((e=>e.draw())),push(),strokeWeight(2*S),t.draw(),pop(),t.CP&&t.CP.map((e=>circle(e.x,e.y,10*S))),t.registration&&t.registration.map((e=>{let t=e[0],A=e[1];push(),stroke(pa.c.BBS),line(t.x,t.y,20*A.x*S+t.x,20*A.y*S+t.y),pop()})),t.labels.map((e=>{push(),textAlign(CENTER,CENTER),noStroke(),fill(pa.c.TF),textSize(W/80),e.p.setColor(-1,pa.c.LBS),e.p.draw(),text(e.text,e.pt.x,e.pt.y),pop()}))}strokeWeight(1*S),pa.DD+=pa.DDS,pa.RR.map(((e,t)=>{e.drawPercent(pa.DD,pa.SM)})),push(),erase(),Poly.rect(W/2,H/2,W-80*S,H-80*S).draw(),noErase(),pop()}}function reflect(e,t,A=0){let r=t.dir,s=r.copy(),n=r.copy().rotate(PI/2),i=e.copy().reflect(n),l=e.copy();if(abs(abs(s.angleBetween(l))-PI/2)<1e-6)return;let o=A*(p5.Vector.cross(e,r).z<0?1:-1),a=-(p5.Vector.cross(e,i).z<0?-1:1);return 2==pa.A?e.rotate(-(PI/2+.01)*a).rotate(o):3==pa.A?e.rotate(2*PI/3+.01).rotate(o):4==pa.A?e.rotate(PI-.1).rotate(o):i.rotate(o)}function setupUseful(){setupRandom(),W=width,H=height,vec=createVector,rndvec=(e=0,t=W,A=0,r=H)=>vec(rnd(e,t),rnd(A,r))}function setupRandom(){seedRNG(seed),rnd=random,sn=noise}function seedRNG(){""==seed&&(seed=str(floor(random(1e10))),txt=seed),console.log(seed);let e=0;for(let t=0;t<seed.length;t++){e=(e<<5)-e+seed.charCodeAt(t),e|=0}randomSeed(e),noiseSeed(e)}function generateEmbroiderySVG(e,t){let A=(e*=3.77953)/W,r=[...pa.B,...pa.G,...pa.RR].map((e=>e.copy())),s=8/e*W;if(r=r.map((e=>{let t=e.c??color(0),r=e.sc??color(0);return e.setColor(t,r),e.reseed(s),e.S=e.S.map((e=>vec(e.x*A,e.y*A))),e.findBBox(),e})),new Set(r.map((e=>e.sc.toString("#rrggbb")))).size>MAX_THREAD_NUMBER)throw"too many colors";return saveSVGElement(createSVGCanvas(r,e,e*A_R),`${`${`${(new Date).toLocaleDateString()} @ ${(new Date).toLocaleTimeString()}`} -- ${seed}`}.svg`).outerHTML}function saveSVGElement(e,t){e.setAttribute("xmlns","http://www.w3.org/2000/svg");var A=e.outerHTML,r=new Blob(['<?xml version="1.0" standalone="no"?>\r\n',A],{type:"image/svg+xml;charset=utf-8"}),s=URL.createObjectURL(r),n=document.createElement("a");return n.href=s,n.download=t,document.body.appendChild(n),n.click(),document.body.removeChild(n),document.body.appendChild(e),e}function createSVGCanvas(e,t,A){ns="http://www.w3.org/2000/svg",svg=document.createElementNS(ns,"svg"),groups=[],svg.setAttribute("width","100vw"),svg.setAttribute("height","100vh"),svg.setAttribute("viewBox","0 0 "+t+" "+A),pa.c.bg&&svg.setAttribute("style",`background-color:rgb(${red(pa.c.bg)/2.55}%,${green(pa.c.bg)/2.55}%,${blue(pa.c.bg)/2.55}%);`);let r={};return e.map((e=>{let A,s=e.sc.toString("#rrggbb");r.hasOwnProperty(s)?A=r[s]:(A=document.createElementNS(ns,"g"),A.setAttribute("id",s),A.setAttribute("style",`stroke-linejoin=bevel; stroke-linecap:round; fill:none; stroke-width:${t/800}; stroke:rgb(${red(e.sc)/2.55}%,${green(e.sc)/2.55}%,${blue(e.sc)/2.55}%); `),svg.appendChild(A),r[s]=A);let n=e.S;if(!n||!n.length)return;let i=document.createElementNS(ns,"path"),l=`M ${n[0].x} ${n[0].y} `;for(let e=1;e<n.length;e++)l+=`L ${n[e].x.toPrecision(6)} ${n[e].y.toPrecision(6)} `;i.setAttribute("d",l),A.appendChild(i)})),svg}p5.disableFriendlyErrors=!0,MAX_THREAD_NUMBER=12;class Vec{constructor(e,t){this.x=e,this.y=t}add(e){return new Vec(this.x+e.x,this.y+e.y)}sub(e){return new Vec(this.x-e.x,this.y-e.y)}mult(e){return new Vec(this.x*e,this.y*e)}div(e){return new Vec(this.x/e,this.y/e)}dot(e){return this.x*e.x+this.y*e.y}len(){return dist(0,0,this.x,this.y)}norm(){return this.div(this.len())}perp(){return new Vec(this.y,-this.x)}}class Poly{constructor(e,t=0,A=0,r=1,s=0,n=!0,i=undefined,l=undefined){this.S=e.map((e=>{let n=e.copy();return n.rotate(s),vec(t+n.x*r,A+n.y*r)}));let o=this.S[this.S.length-1];!n||this.S[0].x==o.x&&this.S[0].y==o.y||this.S.push(this.S[0].copy()),this.closed=0,this.inactive=[],this.inactive.length=this.S.length,this.findBBox(),this.tex=null,this.c=i,this.sc=l}MW(e=1){return(e&&this.getArea()<0||!e&&this.getArea()>0)&&(this.S=this.S.reverse()),this.findBBox(),this}morph(e,t,A=1,r=!1){if(r){let A=[],r=[];for(let s=0;s<e.length;s+=2)A.push([e[s],e[s+1]]),r.push([t[s],t[s+1]]);e=A,t=r}let s=[];for(let r=0;r<e.length;r++){let n=p5.Vector.lerp(e[r][0],t[r][0],A),i=p5.Vector.lerp(e[r][1],t[r][1],A);s.push([n,i])}let n=((e,t,A)=>{if(t.length!=A.length)throw"correspondences dont align";let r=[];for(let s=0;s<e.length;s++){let n=new Vec(0,0),i=0,l=new Vec(e[s].x,e[s].y);for(let e=0;e<t.length;e++){let r=new Vec(t[e][0].x,t[e][0].y),s=new Vec(t[e][1].x,t[e][1].y),o=new Vec(A[e][0].x,A[e][0].y),a=new Vec(A[e][1].x,A[e][1].y);const g=l.sub(r).dot(s.sub(r))/s.sub(r).len()**2,w=l.sub(r).dot(s.sub(r).perp())/s.sub(r).len(),p=o.add(a.sub(o).mult(g)).add(a.sub(o).perp().mult(w).div(a.sub(o).len())).sub(l);let h;h=g<0?l.sub(r).len():g<1?Math.abs(w):l.sub(s).len();const c=(o.sub(a).len()**.5/(.01+h))**2;n=n.add(p.mult(c)),i+=c}const o=l.add(n.div(i));r.push(vec(o.x,o.y))}return r})(this.S,e,s);return new Poly(n)}outline(e){let t=new Poly(this.S,0,0,e),A=this.centerOfMass(),r=t.centerOfMass();return t.translate(A.x-r.x,A.y-r.y),t}label(e){let t=vec(rnd(this.bbl,this.bbr),rnd(this.bbt,this.bbb));if(!this.contains(t))return;let A=this.centerOfMass(),r=p5.Vector.sub(t,A).heading(),s=round(r/(PI/2))*(PI/2);s+=rnd([PI/2,0,-PI/2]);let n=rnd(W/8,W/4),i=vec(1,0).rotate(s).setMag(n),l=p5.Vector.add(t,i);return this.contains(l)?void 0:{p:new Poly([t,l]),text:e,pt:p5.Vector.add(t,i.copy().setMag(n+30*S))}}TWR(e,t,A=.2){t=shuffle(t);let r=this.HCPD();r=shuffle(r);for(let[s,n]of r)for(let[r,i]of t){let t=rnd(TAU);for(let l=t;l<TAU+t;l+=A){let t=new Poly(this.S,-s.x,-s.y);if(t.rotate(l,vec(0,0)),n.setMag(1),t.translate(-n.x,-n.y),t.translate(r.x+i.x,r.y+i.y),!t.overlapsAny([...e,Poly.rect(3*W/4,H/2,W/2,H)],1,1)){let e=new Poly(this.S,-s.x,-s.y);return e.rotate(l,vec(0,0)),n.setMag(1),e.translate(-n.x,-n.y),e.translate(r.x+i.x,r.y+i.y),e}}}}HCPD(e=.5){let t=[];for(let A=0;A<this.S.length-1;A++){let r=(A+1)%this.S.length,s=(A+2)%this.S.length,n=this.S[A],i=this.S[r],l=this.S[s],o=p5.Vector.sub(i,n),a=p5.Vector.sub(l,i),g=o.copy().normalize(),w=a.copy().normalize(),p=p5.Vector.add(g,w);if(p.rotate(-PI/2),p.normalize(),abs(o.angleBetween(a))>e){if(this.highCurvePreselected&&!this.highCurvePreselected.includes(A))continue;t.push([i,p])}}return t}translate(e,t){return this.S=this.S.map((A=>vec(A.x+e,A.y+t))),this.findBBox(),this}rotate(e,t=undefined){return t=t??this.centerOfMass(),this.S=this.S.map((A=>{let r=p5.Vector.sub(A,t);return r.rotate(e),vec(r.x,r.y)})),this.findBBox(),this}static rect(e,t,A,r){let s=1e-6,n=[vec(e-(A/=2),t-(r/=2)),vec(e+A,t-r),vec(e+A+s,t+r),vec(e-A-s,t+r)];return new Poly(n)}addPoint(e){this.S.push(e),this.findBBox()}rayIntersect(e,t,A=1){let r=this.S[this.S.length-1],s=p5.Vector.add(r,t),n=[];if(e.map((e=>{for(let t=0;t<e.S.length-1;t++){let A=e.S[t],i=e.S[(t+1)%e.S.length],l=this.rayToLineSegmentIntersection(r,s,A,i);l&&n.push(l)}})),n.sort(((e,t)=>e.t-t.t)),n.length&&n[0].t>A)return n[0]}rayToLineSegmentIntersection(e,t,A,r){let s=t.x-e.x,n=t.y-e.y,i=r.x-A.x,l=r.y-A.y,o=l*s-i*n,a=i*(e.y-A.y)-l*(e.x-A.x),g=s*(e.y-A.y)-n*(e.x-A.x);if(0==o)return void 0;let w=a/o,p=g/o,h=1e-6;return w>=h&&p>=h&&p<=1-h?{point:createVector(e.x+w*s,e.y+w*n),t:w,dir:p5.Vector.sub(r,A)}:void 0}stepnodes(e=10,t=undefined){if(t>e)throw"r > gap";this.reseed(e),t&&(t*=t);let A=[],r=0;for(let s=0;s<this.S.length;s++){let n=(s+1)%this.S.length,i=this.S[s],l=this.S[n],o=p5.Vector.dist(i,l),a=(e-r)/o;if(a>1){r+=o;continue}let g=p5.Vector.lerp(i,l,a);t&&A.reduce(((e,A)=>e||p5.Vector.sub(A,g).magSq()<t),!1)||(A.push(g),r=(1-a)*o)}return A}reflect(e,t=undefined,A=!1,r=!1){t=t??this.centerOfMass();let s=this.S;for(let n=0;n<e.length;n++){let i,l=e[n],o=[],a=vec(1,0).rotate(l);if(a.setMag(39e3),r)o=s;else for(let e=0;e<s.length;e++){let A=s[e];p5.Vector.sub(A,t).cross(a).z>0?o.push(A):i=i??e}a.rotate(PI/2),o=o.concat(o.splice(0,i));let g=o.length;for(let e=g-1;e>=0;e--){let A=vec(o[e].x,o[e].y);A.sub(t);let r=A.reflect(a);r.add(t),o.push(r)}s=o,A&&s.splice(0,g)}return this.S=s,this.MW(),this.findBBox(),this}copy(e=undefined,t=undefined,A=1,r=undefined,s=undefined){return e=e??0,t=t??0,A=A??1,r=r??this.c,s=s??this.sc,new Poly(this.S,e,t,A,0,this.closed,r,s)}setColor(e=undefined,t=undefined){return this.c=e,this.sc=t,this}onCanvas(e=0,t=width,A=0,r=height){return this.bbl>e&&this.bbr<t&&this.bbt>A&&this.bbb<r}static intersect(e,t,A,r){let s=(e,t,A)=>{let r=p5.Vector.sub(e,t),s=p5.Vector.sub(A,t);return r.angleBetween(s)<0};if(s(e,t,A)!=s(e,t,r)){return s(A,r,e)!=s(A,r,t)}return!1}findBBox(){this.bbl=999999,this.bbr=-999999,this.bbt=999999,this.bbb=-999999;for(let e of this.S)e.x<this.bbl&&(this.bbl=e.x),e.x>this.bbr&&(this.bbr=e.x),e.y<this.bbt&&(this.bbt=e.y),e.y>this.bbb&&(this.bbb=e.y)}BBoxOverlap(e){return this.bbr>e.bbl&&this.bbb>e.bbt&&this.bbr>e.bbl&&this.bbt<e.bbb&&this.bbl<e.bbr&&this.bbb>e.bbt&&this.bbl<e.bbr&&this.bbt<e.bbb}getArea(){let e=this.S;for(var t=0,A=0,r=e.length;A<r;A++){t+=e[A].x*e[A==e.length-1?0:A+1].y*.5,t-=e[A==e.length-1?0:A+1].x*e[A].y*.5}return t}getPerimeter(e=!0){if(!e&&this.perimeter)return this.perimeter;{let e=this.S.reduce(((e,t,A)=>{let r=(A+1)%this.S.length;return e+p5.Vector.sub(t,this.S[r]).mag()}),0);return this.perimeter=e,this.perimeter}}contains(e){if(e.x<this.bbl||e.x>this.bbr||e.y<this.bbt||e.y>this.bbb)return!1;let t=vec(999999,e.y),A=0;return this.S.map(((r,s)=>{let n=(s+1)%this.S.length;A+=Poly.intersect(e,t,this.S[s],this.S[n])})),!(A%2==0)}overlaps(e,t=!1){if(!this.BBoxOverlap(e))return!1;let A=this.S;for(let t=0;t<A.length;t++){let r=(t+1)%A.length;for(let s=0;s<e.S.length;s++){let n=(s+1)%e.S.length;if(Poly.intersect(A[t],A[r],e.S[s],e.S[n]))return!0}}return!!t&&(e.contains(A[0])||this.contains(e.S[0]))}overlapsAny(e,t=!0,A=!1){if(t&&!this.onCanvas())return!0;for(let t of e)if(this.overlaps(t,A))return!0}overlapsCount(e,t=!1){let A=0;for(let r of e)this.overlaps(r,t)&&A++;return A}reseed(e=5){let t=[];for(let A=0;A<this.S.length-!this.closed;A++){let r=(A+1)%this.S.length,s=this.S[A],n=this.S[r],i=e/p5.Vector.dist(s,n);if(t.push(s),i<1)if(i>.5)t.push(p5.Vector.lerp(s,n,.5));else for(let e=i;e<1;e+=i)t.push(p5.Vector.lerp(s,n,e))}return t.push(this.S[this.S.length-1].copy()),this.S=t,this}centerOfMass(){return p5.Vector.div(this.S.reduce(((e,t)=>(e.add(t),e)),vec(0,0)),this.S.length)}drawPercent(e,t=!1){let A=Math.sqrt(this.getPerimeter(!1))*e;this.drawDistance(A,t)}drawDistance(e=1e3,t=!1){null!=this.c&&(-1==this.c?noFill():fill(this.c)),null!=this.sc&&(-1==this.sc?noStroke():stroke(this.sc));let A=!1,r=0;beginShape(),this.S.map(((s,n)=>{if(A)return;if(t?curveVertex(s.x,s.y):vertex(s.x,s.y),n>=this.S.length-1)return;let i=this.S[n+1],l=p5.Vector.dist(s,i);if(r+l>e){let n=p5.Vector.lerp(s,i,constrain((e-r)/l,0,1));t?(curveVertex(n.x,n.y),curveVertex(n.x,n.y)):vertex(n.x,n.y),A=!0}r+=l})),endShape()}draw(e=!0,t=!1,A=!1){return push(),null!=this.c&&(-1==this.c?noFill():fill(this.c)),null!=this.sc&&(-1==this.sc?noStroke():stroke(this.sc)),e&&(beginShape(),this.S.map(((e,t)=>{this.inactive[t]?(endShape(),beginShape()):A?curveVertex(e.x,e.y):vertex(e.x,e.y)})),endShape()),pop(),this}}function EP(e){let t=0,A=0,r="";for(let s of e){let e=Math.round((s.x-t)*Math.pow(10,2)),n=Math.round((s.y-A)*Math.pow(10,2)),i=new ArrayBuffer(4);new DataView(i).setInt16(0,e,!0),new DataView(i).setInt16(2,n,!0),r+=btoa(String.fromCharCode(...new Uint8Array(i))),t=s.x,A=s.y}encodednoequals="";for(let e=6;e<r.length;e+=8)encodednoequals+=r.substring(e-6,e);return r=encodednoequals,r}function DP(e){encodedequals="";for(let t=6;t<e.length;t+=6)encodedequals+=e.substring(t-6,t),encodedequals+="==";e=encodedequals;let t=[],A=0,r=0;for(let s=0;s<e.length;s+=8){let n=Uint8Array.from(atob(e.substring(s,s+8)),(e=>e.charCodeAt(0))).buffer,i=new DataView(n).getInt16(0,!0),l=new DataView(n).getInt16(2,!0);i=i/Math.pow(10,2)+A,l=l/Math.pow(10,2)+r,t.push(vec(i,l)),A=i,r=l}return t}
Stroomlijn holds a special place for me. While focused on creating a plottable project, I neglected my creative enjoyment. As a result, I ended up with many unfinished projects that were okay but didn't feel like something I could proudly call my own. Everything clicked when I released those limitations and pursued something I truly enjoyed, only transforming it into a plottable work after the visuals were how I wanted them to be. My studio is cluttered with various test plots and different directions I initially had for this project. I took a lot of inspiration from artists like Mario Nigro and Peter Struycken, who use bold rectangular patterns in their work. I studied their art and learned how to create dark and thick shapes using just lines. Once I mastered that technique, I incorporated it into my own personal style, with Stroomlijn being the final result. For this project, it's best to use Pigma Micron 05 fineliners when plotting. If you're plotting a white on black design, go for a white Sakura Gelly Roll 08 pen. When it comes to paper, choose Bristol Smooth for white background plots. Use Fabriano Black Black for black background plots. For the other options use smooth thick (160g+) paper in light grey or cream (Mi-Teintes for example). To reduce the chance of mistakes, set your plotter settings to a slow speed. If you wish to experiment with a thinner pen, you can add ‘?density=$“ to the URL of the live view. Replace ‘$’ with 2 or 3 to increase the amount of lines that are drawn. 1 is the default value. You can also use decimal numbers but those can result in different patterns. Press spacebar to download the new SVG file.
let t,e,o,n,l,s={};const i=(i=!1,r=!1,h=!1)=>{let c=window.innerWidth/window.innerHeight,a=h||1;s.b=1e3,s.h=window.innerHeight,s.r=a,c>a?s.w=a*s.h:(s.w=window.innerWidth,s.h=s.w/a),i&&(s.w=i),r&&(s.h=r),s.s=Math.min(s.w,s.h),s.m=s.s/s.b,[t,e,o,n,l]=[s.w,s.h,s.m,.1*s.w,s.b]},r=(t,e,o,n,l)=>n+(t-e)/(o-e)*(l-n),h=(t,e,o)=>{let{size:n,name:l,download:s,hideCanvas:i,removeSVG:r}=e||{},h=document.querySelector(".stroomlijn-svg");h&&h.remove();let a=2970,y=4200,u="http://www.w3.org/2000/svg",p=document.createElementNS(u,"svg");console.log("Generating SVG using backgroundColor: "+o),e.download||tokenData.plot?(p.setAttribute("width","29.7cm"),p.setAttribute("height","42cm")):(p.setAttribute("width","100vw"),p.setAttribute("height","100vh")),p.setAttribute("viewBox","0 0 2970 4200"),p.setAttribute("style",`background: ${o};`),p.setAttribute("xml:space","preserve"),p.setAttribute("xmlns:inkscape","http://www.inkscape.org/namespaces/inkscape"),p.setAttribute("xmlns","http://www.w3.org/2000/svg"),p.setAttribute("class","stroomlijn-svg"),t.forEach((t,o)=>{const n=t.path;if(n.length>0){const o=p.getElementById(""+t.colName);let l;if(null===o){l=document.createElementNS(u,"g"),l.setAttribute("id",""+t.colName),l.setAttribute("inkscape:groupmode","layer");const e=p.querySelectorAll("g").length+1;l.setAttribute("inkscape:label",`${e} - ${t.colName}`)}else l=o;let s=document.createElementNS(u,"path");s.setAttribute("d",`M ${n[0].x*a} ${n[0].y*y}`),s.setAttribute("stroke",t.col),s.setAttribute("stroke-width","5"),s.setAttribute("stroke-linejoin","bevel"),"outline"===t.type||"outline-hatch"===t.type||e.hideFill?s.setAttribute("fill","none"):s.setAttribute("fill",t.col),n.forEach(t=>{let e=s.getAttribute("d");s.setAttribute("d",`${e} L ${t.x*a} ${t.y*y} `)}),l.appendChild(s),p.appendChild(l)}}),document.body.appendChild(p),s&&c(p,l)},c=(t,e)=>{const o=(new XMLSerializer).serializeToString(t),n=document.createElement("a");n.setAttribute("download",tokenData.tokenId+".svg"),n.style.display="none",document.body.appendChild(n),n.setAttribute("href",window.URL.createObjectURL(new Blob([o],{type:"text/plain;charset=utf-8"}))),document.body.removeChild(n),n.click()},a=(o,n)=>({x:r(o,0,t,0,1),y:r(n,0,e,0,1)}),y=Uint32Array.from([0,0,0,0].map((t,e)=>parseInt(tokenData.hash.substr(8*e+2,8),16))),u=()=>{let t,e=y[3];return y[3]=y[2],y[2]=y[1],y[1]=t=y[0],e^=e<<11,e^=e>>>8,y[0]=e^t^t>>>19,y[0]/4294967296},p=(t,e)=>t+(e-t)*u(),x=t=>t[Math.floor(u()*t.length)];let d=function(t){this.p=[...Array(256)].map(e=>f(256*t())),this.pm=[...this.p,...this.p]};const{floor:f,sqrt:g}=Math,w=(t,e,o)=>t[0]*e+t[1]*o,b=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]];d.prototype.noise=function(t,e){const o=this.pm;let n,l,s,i,r,h=(t+e)*(.5*(g(3)-1)),c=f(t+h),a=f(e+h),y=(3-g(3))/6,u=(c+a)*y,p=t-(c-u),x=e-(a-u);p>x?(i=1,r=0):(i=0,r=1);let d=p-i+y,m=x-r+y,F=p-1+2*y,M=x-1+2*y,A=255&c,v=255&a,k=o[A+o[v]]%12,S=o[A+i+o[v+r]]%12,E=o[A+1+o[v+1]]%12,N=.5-p*p-x*x;N<0?n=0:(N*=N,n=N*N*w(b[k],p,x));let B=.5-d*d-m*m;B<0?l=0:(B*=B,l=B*B*w(b[S],d,m));let C=.5-F*F-M*M;return C<0?s=0:(C*=C,s=C*C*w(b[E],F,M)),70*(n+l+s)};const m=(t,e)=>{const o=e.x-t.x,n=e.y-t.y;return Math.atan2(n,o)*(180/Math.PI)},F=t=>{let e=0,o=0;for(let n=0;n<t.length;n++)e+=t[n].x,o+=t[n].y;return e/=t.length,o/=t.length,[e,o]},M=t=>{const e=[];for(let o=0;o<t.length;o++){let n=t[o],l=o===t.length-1?0:o+1,s=t[l];const i=Math.round(m(n,s));[-270,-180,-90,0,90,180,270].includes(i)&&e.push([o,l])}return e},A=(t,e)=>t.filter(t=>E(t,e)),v=(t,e)=>{const o=[];for(let n=0;n<t.length-1;n++){const l=[t[n],t[n+1]];for(let t=0;t<e.length-1;t++){const n=[e[t],e[t+1]];if(S(l,n)){const{x:t,y:e}=k(l,n);o.push({x:t,y:e})}}}return o},k=([t,e],[o,n])=>{const l=(t.x-e.x)*(o.y-n.y)-(t.y-e.y)*(o.x-n.x);return{x:((t.x*e.y-t.y*e.x)*(o.x-n.x)-(t.x-e.x)*(o.x*n.y-o.y*n.x))/l,y:((t.x*e.y-t.y*e.x)*(o.y-n.y)-(t.y-e.y)*(o.x*n.y-o.y*n.x))/l}},S=([t,e],[o,n])=>{const l=(e.x-t.x)*(n.y-o.y)-(n.x-o.x)*(e.y-t.y);if(0===l)return!1;const s=((n.y-o.y)*(n.x-t.x)+(o.x-n.x)*(n.y-t.y))/l,i=((t.y-e.y)*(n.x-t.x)+(e.x-t.x)*(n.y-t.y))/l;return 0<s&&s<1&&0<i&&i<1},E=(t,e)=>{let o=!1,n=t.x,l=t.y;for(let t=0,s=e.length-1;t<e.length;s=t++){let[i,r]=[e[t].x,e[t].y],[h,c]=[e[s].x,e[s].y];r>l!=c>l&&n<(h-i)*(l-r)/(c-r)+i&&(o=!o)}return o},N=t=>t.filter((e,o)=>t.findIndex(t=>t.x===e.x&&t.y===e.y)===o),B=t=>{let[e,o]=F(t);return t.sort((function(t,n){return Math.atan2(t.y-o,t.x-e)-Math.atan2(n.y-o,n.x-e)})),t};let C,$,q,H=[{bg:"#000000",colors:["#FFFFFF"]},{bg:"#FFFBF0",colors:["#0058b9"]},{bg:"#FFFBF0",colors:["#F00"]},{bg:"#FFFBF0",colors:["#F00","#0058b9"]},{bg:"#F6F5F4",colors:["#023c19"]},{bg:"#F6F5F4",colors:["#880018"]},{bg:"#FFFFFF",colors:["#000"]}],I=[[0,10],[1,10],[2,10],[3,3],[4,6],[5,6],[6,12]],L=[],j=0,D=0;const G=[[0,.65],[-.2,.6],[.1,.6]],z=[[-.1,.42,.57,.6],[-.3,.25,.42,.62],[-.2,.35,.45,.52]];let R,U,P=[],V=1*o,W=1,O={},T=new d(u),X={active:!0,size:"A3",name:tokenData.hash,download:!1,hideCanvas:!0,removeSVG:!1,hideFill:!1};const J=()=>{(t=>{console.log("Stroomlijn - Bart Simons - 2023");let{width:e,height:o,ratio:n}=t||{};i(e,o,n)})({width:707.56302521,height:1e3,ratio:.70756302521}),ct();const o=r(e,0,1e3,0,1);D=.1*t,X.height=e,X.width=t,V?V*=o:V=1*o},K=()=>{P=[],L=[],j=0;const t=Q();Y(t),Z(),_(),tt(),ht()},Q=()=>{const t=707.56302521/U,e=[],o=O.fullSelection?x(z):x(G);for(let n=-353.781512605;n<1061.344537815;n+=t){let l=-250;for(;l<1250;){const s=C.noise1,i=C.noise2,h=C.noiseHeight1,c=C.noiseHeight2,a=T.noise(n*s,l*i),y=T.noise(n*h,l*c),u=r(y,-1,1,10,150),p=r(a,-1,1,.5*t,.7*t);let x={x:n+t/2-p/2,y:l+u/2,w:p,h:u};l+u>1250&&(x.h=1250-l);const d=T.noise(a,y);if(O.fullSelection){const t=O.broken?o[3]:1;d>-1&&d<o[0]?x.type="filled":d>o[0]&&d<o[1]?x.type="outlined":d>o[1]&&d<o[2]?x.type="barred":d>o[2]&&d<t?x.type="angled":x.type="empty"}else{const t=O.broken?o[1]:1;d>-1&&d<o[0]?x.type="outlined":d>o[0]&&d<t?x.type="filled":x.type="empty"}e.push(x),l+=10+u}}return e},Y=t=>{t.forEach((t,e)=>{const o=x(q);"filled"===t.type?st(t.x,t.y,t.w,t.h,o):"outlined"===t.type?lt(t.x,t.y,t.w,t.h,"outline",o):"barred"===t.type?rt(t.x,t.y,t.w,t.h,o):"angled"===t.type&&it(t.x,t.y,t.w,t.h,o)})},Z=()=>{P.forEach(o=>{o.path.forEach(o=>{o.x-=t/2,o.y-=e/2;const n=o.x*Math.cos(C.rotation)-o.y*Math.sin(C.rotation),l=o.x*Math.sin(C.rotation)+o.y*Math.cos(C.rotation);o.x=n+t/2,o.y=l+e/2})})},_=()=>{let o=D,n=t-D,l=e-D,s=D;const i=[];for(let t=0;t<P.length;t++){let e=!0;const[r,h]=[P[t].path,P[t].type];for(let t=0;t<r.length;t++){const i=r[t];if(i.x>=s&&i.x<=n&&i.y>=o&&i.y<=l){e=!1;break}}e&&(i.push(t),"filled-outline"===h&&i.push(t+1))}const r=[...new Set(i)];for(let t=r.length-1;t>=0;t--)P.splice(r[t],1)},tt=()=>{let o=t-D,n=e-D,l=[{x:D,y:D},{x:o,y:D},{x:o,y:n},{x:D,y:n},{x:D,y:D}];for(let o=0;o<P.length;o++){const n=P[o];let s=n.path,i=.1*D,r=[{x:i,y:i},{x:t-i,y:i},{x:t-i,y:e-i},{x:i,y:e-i},{x:i,y:i}],h=!0;if(s.forEach(o=>{(o.x<D||o.x>t-D||o.y<D||o.y>e-D)&&(h=!1)}),!h)if("outline"===n.type){const t=nt(s,l);if(P[o].path=t[0],t.length>1){const e={path:t[1],type:"outline"};P.splice(o+1,0,e)}}else if("filled"===n.type){R||(r=l);const t=ot(s,r,R,l);P[o].path=t}else if("filled-hatch"===n.type){const t=ot(s,l);P[o].path=t}else if("outline-hatch"===n.type){const t=et(s,l);P[o].path=t}else if("filled-outline"===n.type)if(R){let t=!0;if(s.forEach(e=>{E(e,r)||(t=!1)}),!t){const t=[];P[o].path=t}}else{const t=et(s,l);P[o].path=t}}},et=(t,e)=>{let o=[];const n=v(t,e),l=[];n.forEach(t=>{l.push({...t})});const s=A(t,e);if(o.push(...s,...n),l.forEach(t=>{t.x=Math.floor(t.x),t.y=Math.floor(t.y)}),n.length<2)o.push(n[0]);else if(l[0].x===l[1].x||l[0].y===l[1].y||4===n.length);else{const[t,n]=F(o),l=((t,e,o)=>{const[n,l,s,i]=o,r=Math.sqrt((t-n.x)**2+(e-n.y)**2),h=Math.sqrt((t-l.x)**2+(e-l.y)**2),c=Math.sqrt((t-s.x)**2+(e-s.y)**2),a=Math.sqrt((t-i.x)**2+(e-i.y)**2),y=Math.min(r,h,c,a);return y===r?n:y===h?l:y===c?s:y===a?i:null})(t,n,e);o.push(l)}return o=N(o),o=B(o),o.push(o[0]),o},ot=(t,e,o=!1,n)=>{let l=[];if(o)for(let o=0;o<t.length;o++){const l=t[o];if(!E(l,e))return void nt(t,n)}for(let o=0;o<t.length;o++){const n=t[o],s=t[o+1]||t[0],i=v([n,s],e);E(n,e)?l.push(n):i.length>0&&(t[o]=i[0],l.push(...i))}return l},nt=(t,e)=>{let o=[];const n=v(t,e),l=A(t,e);if(o.push(...l,...n),o=N(o),o=B(o),n.length>2)o=(t=>{let e=[],o=[[],[]];e=M(t);let[n,l,s,i]=[e[0][1],e[1][0],e[1][1],e[0][0]];const r=t.slice(s).concat(t.slice(0,s));e=M(r),[n,l,s,i]=[e[0][1],e[1][0],e[1][1],e[0][0]];for(let t=0;t<r.length;t++)t>=n&&t<=l&&o[0].push(r[t]),s<i?t>=s&&t<=i&&o[1].push(r[t]):(t>=s||t<=i)&&o[1].push(r[t]);return o})(o);else if(2===n.length)for(let t=0;t<o.length;t++){let e=t===o.length-1?0:t+1;if(o[t]==n[1]&&o[e]==n[0]||o[t]==n[0]&&o[e]==n[1]){const e=o.slice(0,t+1),n=o.slice(t+1);n.push(...e),o=n}}return[o]},lt=(t,e,o,n,l="outline",s="#000000")=>{let i=[];i.push({x:t,y:e-n/2}),i.push({x:t+o,y:e-n/2}),i.push({x:t+o,y:e+n/2}),i.push({x:t,y:e+n/2}),i.push({x:t,y:e-n/2}),P.push({path:i,type:l,col:s})},st=(t,e,o,n,l="#000000")=>{const s=[];for(let l=e-n/2;l<e+n/2;l+=V)s.push({x:t,y:l}),s.push({x:t+o,y:l});lt(t,e,o,n,"filled-outline",l),P.push({path:s,type:"filled",col:l})},it=(t,e,n,l,s="#000000")=>{const i=[[]],r=[{x:t,y:e-l/2},{x:t+n,y:e-l/2},{x:t+n,y:e+l/2},{x:t,y:e+l/2},{x:t,y:e-l/2}];let h=0;for(let s=e-2*l,c=0;s<e+2*l;s+=V){let e={x:t-n,y:s+50*o},l={x:t+2*n,y:s};const a=v([e,l],r);0===a.length?(l={},e={}):1===a.length?l=a[0]:2===a.length&&([e,l]=a),i[c].push(e),i[c].push(l),h++,h===Math.round(4*W)&&(s+=5*V*W,h=0,c++,i.push([]))}for(let t=0;t<i.length-1;t++)P.push({path:i[t],type:"filled-hatch",col:s});lt(t,e,n,l,"outline-hatch",s)},rt=(t,e,o,n,l="#000000")=>{const s=[[]];let i=0;for(let l=e-n/2,r=0;l<e+n/2;l+=V)s[r].push({x:t,y:l}),s[r].push({x:t+o,y:l}),i++,i===Math.round(6*W)&&(l+=4*V*W,i=0,r++,s.push([]));for(let t=0;t<s.length;t++)P.push({path:s[t],type:"filled-hatch",col:l});lt(t,e,o,n,"outline-hatch",l)},ht=()=>{P.forEach(t=>{const e=t.path,o=t.type,n=t.col;if(X.active&&void 0!==e&&e.length>0){const t=at(n);L.push({path:[],col:n,colName:t,type:o});for(let t=0;t<e.length;t++){const o=a(e[t].x,e[t].y);isNaN(o.x)||isNaN(o.y)||L[j].path.push(a(e[t].x,e[t].y))}j++}})},ct=()=>{var t,e;C={rotation:p(0,2*Math.PI),noise1:p(1e-5,5e-4),noise2:.001,noiseHeight1:.001,noiseHeight2:.001,scale:(t=15,e=40,Math.floor(p(t,e))),overlapAllowed:u()<.5};const o=(t=>{let e=[];for(let o in t)e=e.concat(new Array(t[o][1]).fill(t[o][0]));return x(e)})(I),n=H[o];$=n.bg,q=n.colors,R=u()<.64,U=C.scale;const l=Math.round(r(U,15,39,0,2));O.breakout=R,O.scale=["Small","Medium","Large"][l],O.broken=u()<.6,O.fullSelection=u()<.73;const s=window.location.search,i=new URLSearchParams(s),h=Number(i.get("density"));0!==h&&(W=h),W&&W>1&&W<3.01&&(V=1/W)},at=t=>"#FFFFFF"===t?"White/Silver":"#0058b9"===t?"Micron Blue":"#F00"===t?"Micron Red":"#023c19"===t?"Micron Hunter Green":"#880018"===t?"Micron Burgundy":"#000"===t?"Micron Black":void 0;window.onkeypress=t=>{32==t.which&&(X.download=!0,X.hideFill=!0,h(L,X,$))},tokenData.plot?(J(),K(),X.hideFill=!0,h(L,X,$)):(J(),K(),h(L,X,$))
console.log("Scratch v5.5 © Matto"); console.log(`TOKEN ENTROPY: ${tokenData.hash}`); const tokenId = tokenData.tokenId; const attributes = {}; let seed = makeSeed(tokenData.hash); let nonce = 0; let showcncPreview = false; let showSignature = true; let enso = false; const allRadii = [0]; const brushCounts = [0,0,0]; const ringQTY = selectByProbs([5,4,3,2,1], RR()); const brushTypeList = []; const m = (R(0, 200) / 100) - 1; const sizeStrings = ["Small", "Medium", "Large"]; const sizeColors = ["red", "green", "blue"]; let focusMode, orbitMode, pointMode, metal, finish, bkg, metalColor; let proxLim = 1000 / 5; RR() < .80 ? metal = "Al" : metal = "Cu"; metal == "Cu" ? metalColor = "#b87333" : metalColor = "grey"; RR() < .80 ? finish = "Brushed" : finish = "Polished"; let dark = selectByProbs([false, true], RR()); if (!tokenData.plot) { dark ? bkg = 32 : bkg = 224; } for (i = 0; i < ringQTY; i++) { brushTypeList[i] = selectByProbs([0,1,2], RR()); brushCounts[brushTypeList[i]]++; } RR() > .75 ? focusMode = true : focusMode = false; RR() > .50 ? pointMode = true : pointMode = false; RR() > .50 && pointMode == true ? orbitMode = true : orbitMode = false; if (pointMode == false) { if (ringQTY == 1 && focusMode == false || ringQTY == 2 && focusMode == true) { enso = true; } } addAttribute("FOCUS", focusMode); addAttribute("Enso", enso); addAttribute("Point Mode", pointMode); addAttribute("Orbits", orbitMode); addAttribute("Ring Count", ringQTY.toString()); addAttribute("Small Disc Rings", brushCounts[0].toString()); addAttribute("Medium Disc Rings", brushCounts[1].toString()); addAttribute("Large Disc Rings", brushCounts[2].toString()); addAttribute("Metal", metal); addAttribute("Finish", finish); addAttribute("Dark", dark); console.log("Attributes:"); console.log(attributes); const svgStart = `<?xml version="1.0" encoding="utf-8"?><svg viewBox="0 0 1000 1000" style="background-color:rgb(${bkg},${bkg},${bkg})" xmlns="http://www.w3.org/2000/svg">`; let svg = ""; let sig = ""; let cncPreview = ""; const cncSVG = []; for (let i=0; i < 4; i++) { cncSVG[i] = ""; if (i != 3) { cncSVG[i] += `<desc>Sand the ${sizeColors[i]} paths with a disk that is ${i + 1}/24th the artwork size.</desc><g id="padsize-${i + 1}" style="stroke:${sizeColors[i]}; stroke-width: 1px; stroke-opacity:1; fill-opacity:0">`; } else { cncSVG[i] += `<desc>Carve the black paths with an end mill. For a 24 x 24 inch plate, use a 1/16-inch bit.</desc>`; } } function setup() { noCanvas(); noLoop(); } function draw() { let bkg = `<g id="background" style="stroke:${metalColor}; stroke-width: ${1000/1000}px; stroke-opacity:1; fill-opacity:0">`; let bMod; finish == "Brushed" ? bMod = 0 : bMod = R(100, 200); for (let b = -2000; b < 2000; b += (10/3) + Math.sin(b) * (10/4) + bMod) { const x0 = Math.max(0, -b / m); const x1 = Math.min(1000, (1000 - b) / m); const y0 = b + x0 * m; const y1 = b + x1 * m; const clipped = getClippedLine(x0, y0, x1, y1); if (clipped) { bkg += lineWithGaps(clipped.x0,clipped.y0,clipped.x1,clipped.y1); } } svg = svgStart + bkg + "</g>"; for (let p = 0; p < ringQTY; p++) { let plotString = ""; let cncString = ""; const brushType = brushTypeList[p]; let radius, newStrings; const padding = 100 + (brushType + 1) * (1000 / 48); if (p == 0 && focusMode) { radius = (brushType + 1) * (2000 / 24); allRadii.push(radius); newStrings = addPoint(500, 500, brushType); } else { radius = randRad(padding); newStrings = addCircle(500, 500, radius, brushType); } plotString += newStrings.plot; cncString += newStrings.cnc; cncSVG[brushType] += newStrings.cnc; svg += `<g id="ring-${p}" style="stroke:${metalColor}; stroke-width: 1px; stroke-opacity:1; fill-opacity:0"><desc>Ring Radius: ${radius}, Disc Size: ${sizeStrings[brushType]}</desc>` + plotString + "</g>"; cncPreview += `<g id="cnc-${p}" style="stroke:purple; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0">` + cncString + "</g>"; } sig += `<polyline points="924,956 920,956 920,860 940,872 960,860 960,956 956,956" />`; sig += `<polyline points="928,902 940,872 952,902" stroke-linejoin="bevel" />`; sig += `<line x1="934" y1="888" x2="946" y2="888" />`; sig += `<line x1="920" y1="902" x2="960" y2="902" />`; sig += `<line x1="932" y1="902" x2="932" y2="928" />`; sig += `<line x1="948" y1="902" x2="948" y2="928" />`; sig += `<circle cx="940" cy="940" r="15" />`; let sigCNCStart = `<g id="cnc-signature" style="stroke:black; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0">`; cncPreview += sigCNCStart + sig + "</g>"; cncSVG[3] += sigCNCStart + sig; sig = `<g id="signature" style="stroke:${metalColor}; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0"><desc>Suggested Pen Thickness: 2.6x</desc>` + sig + "</g>"; for (let i = 0; i < 4; i++) { cncSVG[i] += "</g>"; } document.body.insertAdjacentHTML('beforeend', svg + sig + "</svg>"); console.log("CNC SVG:"); console.log(compilecncSVG()); } function addAttribute(trait_type, value) { attributes[trait_type] = value; } function makeSeed(input) { let s = 1; for (let i = 0; i < (input.length - 2) / 2; i++) { let v = parseInt(input.slice(2 + i * 2, 4 + i * 2), 16); s = ((s * v) % 999999999999) + 1 } return s; } function R(min, max) { const range = max - min + 1; const v = (seed % range) + min; newSeed(); return Math.floor(v); } function RR() { return R(1,100)/100; } function newSeed() { nonce++; seed = ((seed * 35932678341237) + nonce) % 999999999999 + 1 } function keyPressed() { if (tokenData.plot != true) { const k = key.toUpperCase(); if (k === "S") { saveStrings([svg + sig + "</svg>"], `SCRATCH-${tokenId}`, "svg"); } else if (k === "C") { showcncPreview = !showcncPreview; updateSVG(); } else if (k === "H") { showSignature = !showSignature; updateSVG() } else if (k === "E") { saveStrings([compilecncSVG()], `SCRATCH-${tokenId}-CNC`, "svg"); } } return false; } function updateSVG() { let comp = svg; if (showSignature) { comp += sig; } if (showcncPreview) { comp += cncPreview; } document.body.innerHTML = ''; document.body.insertAdjacentHTML('beforeend', comp + "</svg>"); } function randRad(padding) { const radius = R(allRadii[0], (500) - padding); let tooClose = false; for (let i = 0; i < allRadii.length; i++) { if (Math.abs(radius - allRadii[i]) < proxLim) { tooClose = true; proxLim -= 1; break; } } if (!tooClose) { allRadii.push(radius); proxLim = 1000 / 5; return radius; } else { return randRad(padding); } } function selectByProbs(list, randomValue) { const totalWeight = list.reduce(function(acc, item, index) { return acc + (1 / (index + 2)); }, 0); const threshold = totalWeight * randomValue; let currentSum = 0; for (let i = 0; i < list.length; i++) { currentSum += 1 / (i + 2); if (currentSum >= threshold) { return list[i]; } } return list[list.length - 1]; } function compilecncSVG() { let list = svgStart; list += `<desc>The grey border is a visual guide. Please scale the vectors appropriately.</desc><rect x="0" y="0" width="1000" height="1000" style="stroke:grey; stroke-width: 1px; stroke-opacity:1; fill-opacity:0" />` for (let i = 0; i < 4; i++) { if (cncSVG[i].length > 180) { list += cncSVG[i]; } } return list + "</svg>"; } function addPoint(x,y, brushType) { let plotString = ""; const cncString = `<circle cx="${x}" cy="${y}" r="4" />`; for (let i = 0; i < R(5,7); i++) { plotString += concentrics(x, y, (brushType + 1) * (1000 / 24), 1); } return {plot: plotString, cnc: cncString}; } function getY(x0, y0, x1, y1, x) { const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const y = m * x + b; return y; } function getX(x0, y0, x1, y1, y) { const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const x = (y - b) / m; return x; } function lineWithGaps(x0, y0, x1, y1) { let xT, yT; if(x0 > x1) { xT = x0; yT = y0; x0 = x1; y0 = y1; x1 = xT; y1 = yT; } let xS = x0; let yS = y0; let yE, xE; let str = ""; let lfg = true; while (lfg) { let dS; let dnm = [[60,4,48,12],[80,12,40,8]]; finish == "Brushed" ? dS = 0 : dS = 1; let lSeg = R((1000 / dnm[dS][0]), (1000 / dnm[dS][1])); let gSeg = R((1000 / dnm[dS][2]), (1000 / dnm[dS][3])); xS + lSeg > x1 ? xE = x1 : xE = xS + lSeg; yE = getY(x0, y0, x1, y1, xE); str += `<line x1="${xS}" y1="${yS}" x2="${xE}" y2="${yE}" />` xE + gSeg > x1 ? lfg = false : xS = xE + gSeg; xS = xE + gSeg; yS = getY(x0, y0, x1, y1, xS); } return str; } function addCircle(x,y, cr, brushType) { const r = (brushType + 1) * (1000 / 24); const orbitLocs = R(2,6); let locs; const pad = (1000 / 15) + (brushType + 1) * (1000 / 48); let plotString = ""; let cncString = ""; if (pointMode) { locs = R(2,20); } else { locs = Math.floor((2 * PI * cr) / 10); cncString = `<circle cx="${x}" cy="${y}" r="${cr}" />`; } const angleStep = 2 * PI / locs; for (let i = 0; i < locs; i++) { const angle = i * angleStep; const xC = x + cr * Math.cos(angle); const yC = y + cr * Math.sin(angle); if (pointMode) { const newStrings = addPoint(xC, yC, brushType); plotString += newStrings.plot; cncString += newStrings.cnc; if (orbitMode && cr > 200) { const closestEdgeDist = Math.min(Math.min(Math.abs(1000 - xC), xC), Math.min(Math.abs(1000 - yC), yC)); if (closestEdgeDist > pad + 2 * r) { const newStringsOrbit = addOrbit(xC, yC, 2 * r, brushType, orbitLocs); plotString += newStringsOrbit.plot; cncString += newStringsOrbit.cnc; } } } else { plotString += concentrics(xC, yC, r, 0); } } return {plot: plotString, cnc: cncString}; } function addOrbit(x, y, cr, brushType, locs) { const r = (brushType + 1) * (1000 / 24); let plotString = ""; let cncString = ""; const angleStep = 2 * PI / locs; for (let i = 0; i < locs; i++) { const angle = i * angleStep; const xC = x + cr * Math.cos(angle); const yC = y + cr * Math.sin(angle); const newStrings = addPoint(xC, yC, brushType); plotString += newStrings.plot; cncString += newStrings.cnc; } return {plot: plotString, cnc: cncString}; } function concentrics(x,y,r,f) { r /= 2; let arcs = ""; if (f == 1) { x = x + R(-4, 4); y = y + R(-4, 4); } for (let i = 10; i < r; i += R(r/25, r/8) ) { arcs += randomArcSVG(x,y,i); } return arcs; } function randomArcSVG(x, y, radius) { const getRandomAngle = () => R(0,628) / 100; const startAngle = getRandomAngle(); const endAngle = getRandomAngle(); let sweepAngle = endAngle - startAngle; if (sweepAngle < 0) { sweepAngle += 2 * Math.PI; } const startX = x + radius * Math.cos(startAngle); const startY = y + radius * Math.sin(startAngle); const endX = x + radius * Math.cos(endAngle); const endY = y + radius * Math.sin(endAngle); const largeArcFlag = sweepAngle > Math.PI ? 1 : 0; const sweepFlag = 1; const d = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${endX} ${endY}`; return `<path d="${d}" />`; } function getClippedLine(x0, y0, x1, y1) { const xmin = R((100 / 24),(1000 / 48)); const ymin = R((100 / 24),(1000 / 48)); const xmax = 1000-R((100 / 24),(1000 / 48)); const ymax = 1000-R((100 / 24),(1000 / 48)); const inside = (x, y) => x >= xmin && x <= xmax && y >= ymin && y <= ymax; if (inside(x0, y0) && inside(x1, y1)) { return { x0, y0, x1, y1 }; } const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const xLeft = xmin; const yLeft = m * xLeft + b; const xRight = xmax; const yRight = m * xRight + b; const yTop = ymin; const xTop = (yTop - b) / m; const yBottom = ymax; const xBottom = (yBottom - b) / m; const intersections = [ { x: xLeft, y: yLeft }, { x: xRight, y: yRight }, { x: xTop, y: yTop }, { x: xBottom, y: yBottom } ]; const validIntersections = intersections.filter(p => inside(p.x, p.y)); if (validIntersections.length >= 2) { return { x0: validIntersections[0].x, y0: validIntersections[0].y, x1: validIntersections[1].x, y1: validIntersections[1].y }; } return null; }
Scratch is a Zen-inspired generative art project that explores the captivating patterns that sanding discs create on metal surfaces. The digital artworks can be pen-plotted at any scale, and an alternate physical output can be created on sheets of metal using CNC machines. Interactivity: 'S' saves the SVG. 'C' previews the CNC paths. 'E' exports the CNC paths. 'H' hides the signature stamp. Plotter Notes: To replicate the density of the digital image, choose a pen for the main area of a Scratch that is 1/1000th the length of the sides of the plottable area. For the signature, a pen that is 2.6 times thicker than the one used for the main area is suggested. For instance, for a 10" square plot, a 0.25mm pen for the main image and a 0.65mm pen for the signature will closely mimic the density of the digital output. While bolder pens can create more visually striking images, denser Scratches plotted with thicker pens might require a heavier paper stock. CNC Notes: Experienced CNC technicians can faithfully execute the outputs on 24" x 24" sheets of metal by using 1", 2", and 3" sanding discs and a 1/16" end mill. The choice of material and finish should be based on the specific characteristics of the Scratch output. If the Scratch output includes the 'Dark' feature, anodized aluminum or copper with a patina can be used. Clear coat the piece after machining to prevent tarnishing.
Scratch is a Zen-inspired generative art project that explores the captivating patterns that sanding discs create on metal surfaces. The digital artworks can be pen-plotted at any scale, and an alternate physical output can be created on sheets of metal using CNC machines. Interactivity: 'S' saves the SVG. 'C' previews the CNC paths. 'E' exports the CNC paths. 'H' hides the signature stamp. Plotter Notes: To replicate the density of the digital image, choose a pen for the main area of a Scratch that is 1/1000th the length of the sides of the plottable area. For the signature, a pen that is 2.6 times thicker than the one used for the main area is suggested. For instance, for a 10" square plot, a 0.25mm pen for the main image and a 0.65mm pen for the signature will closely mimic the density of the digital output. While bolder pens can create more visually striking images, denser Scratches plotted with thicker pens might require a heavier paper stock. CNC Notes: Experienced CNC technicians can faithfully execute the outputs on 24" x 24" sheets of metal by using 1", 2", and 3" sanding discs and a 1/16" end mill. The choice of aluminum or copper as a material should be based on the specific characteristics of the Scratch output. If the Scratch output includes the 'Dark' feature, anodized aluminum or a copper with a patina can be used. Clear coat the piece after machining to prevent tarnishing.
console.log("Scratch v5.4 © Matto"); console.log(`TOKEN ENTROPY: ${tokenData.hash}`); const tokenId = tokenData.tokenId; const attributes = {}; let seed = makeSeed(tokenData.hash); let nonce = 0; let showcncPreview = false; let showSignature = true; const allRadii = [0]; const brushCounts = [0,0,0]; const ringQTY = selectByProbs([5,4,3,2,1], RR()); const brushTypeList = []; const m = (R(0, 200) / 100) - 1; const sizeStrings = ["Small", "Medium", "Large"]; const sizeColors = ["red", "green", "blue"]; let focusMode, orbitMode, pointMode, metal, finish, bkg, metalColor; let proxLim = 1000 / 5; RR() < .80 ? metal = "Al" : metal = "Cu"; metal == "Cu" ? metalColor = "#b87333" : metalColor = "grey"; RR() < .80 ? finish = "Brushed" : finish = "Polished"; let dark = selectByProbs([false, true], RR()); if (!tokenData.plot) { dark ? bkg = 32 : bkg = 224; } for (i = 0; i < ringQTY; i++) { brushTypeList[i] = selectByProbs([0,1,2], RR()); brushCounts[brushTypeList[i]]++; } RR() > .75 ? focusMode = true : focusMode = false; RR() > .50 ? pointMode = true : pointMode = false; RR() > .50 && pointMode == true ? orbitMode = true : orbitMode = false; addAttribute("FOCUS", focusMode); addAttribute("Point Mode", pointMode); addAttribute("Orbits", orbitMode); addAttribute("Ring Count", ringQTY.toString()); addAttribute("Small Disc Rings", brushCounts[0].toString()); addAttribute("Medium Disc Rings", brushCounts[1].toString()); addAttribute("Large Disc Rings", brushCounts[2].toString()); addAttribute("Metal", metal); addAttribute("Finish", finish); addAttribute("Dark", dark); console.log("Attributes:"); console.log(attributes); const svgStart = `<?xml version="1.0" encoding="utf-8"?><svg viewBox="0 0 1000 1000" style="background-color:rgb(${bkg},${bkg},${bkg})" xmlns="http://www.w3.org/2000/svg">`; let svg = ""; let sig = ""; let cncPreview = ""; const cncSVG = []; for (let i=0; i < 4; i++) { cncSVG[i] = ""; if (i != 3) { cncSVG[i] += `<desc>Sand the ${sizeColors[i]} paths with a disk that is ${i + 1}/24th the artwork size.</desc><g id="padsize-${i + 1}" style="stroke:${sizeColors[i]}; stroke-width: 1px; stroke-opacity:1; fill-opacity:0">`; } else { cncSVG[i] += `<desc>Carve the black paths with an end mill. For a 24 x 24 inch plate, use a 1/16-inch bit.</desc>`; } } function setup() { noCanvas(); noLoop(); } function draw() { let bkg = `<g id="background" style="stroke:${metalColor}; stroke-width: ${1000/1000}px; stroke-opacity:1; fill-opacity:0">`; let bMod; finish == "Brushed" ? bMod = 0 : bMod = R(100, 200); for (let b = -2000; b < 2000; b += (10/3) + Math.sin(b) * (10/4) + bMod) { const x0 = Math.max(0, -b / m); const x1 = Math.min(1000, (1000 - b) / m); const y0 = b + x0 * m; const y1 = b + x1 * m; const clipped = getClippedLine(x0, y0, x1, y1); if (clipped) { bkg += lineWithGaps(clipped.x0,clipped.y0,clipped.x1,clipped.y1); } } svg = svgStart + bkg + "</g>"; for (let p = 0; p < ringQTY; p++) { let plotString = ""; let cncString = ""; const brushType = brushTypeList[p]; let radius, newStrings; const padding = 100 + (brushType + 1) * (1000 / 48); if (p == 0 && focusMode) { radius = (brushType + 1) * (2000 / 24); allRadii.push(radius); newStrings = addPoint(500, 500, brushType); } else { radius = randRad(padding); newStrings = addCircle(500, 500, radius, brushType); } plotString += newStrings.plot; cncString += newStrings.cnc; cncSVG[brushType] += newStrings.cnc; svg += `<g id="ring-${p}" style="stroke:${metalColor}; stroke-width: 1px; stroke-opacity:1; fill-opacity:0"><desc>Ring Radius: ${radius}, Disc Size: ${sizeStrings[brushType]}</desc>` + plotString + "</g>"; cncPreview += `<g id="cnc-${p}" style="stroke:purple; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0">` + cncString + "</g>"; } sig += `<polyline points="924,956 920,956 920,860 940,872 960,860 960,956 956,956" />`; sig += `<polyline points="928,902 940,872 952,902" stroke-linejoin="bevel" />`; sig += `<line x1="934" y1="888" x2="946" y2="888" />`; sig += `<line x1="920" y1="902" x2="960" y2="902" />`; sig += `<line x1="932" y1="902" x2="932" y2="928" />`; sig += `<line x1="948" y1="902" x2="948" y2="928" />`; sig += `<circle cx="940" cy="940" r="15" />`; let sigCNCStart = `<g id="cnc-signature" style="stroke:black; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0">`; cncPreview += sigCNCStart + sig + "</g>"; cncSVG[3] += sigCNCStart + sig; sig = `<g id="signature" style="stroke:${metalColor}; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0"><desc>Suggested Pen Thickness: 2.6x</desc>` + sig + "</g>"; for (let i = 0; i < 4; i++) { cncSVG[i] += "</g>"; } document.body.insertAdjacentHTML('beforeend', svg + sig + "</svg>"); console.log("CNC SVG:"); console.log(compilecncSVG()); } function addAttribute(trait_type, value) { attributes[trait_type] = value; } function makeSeed(input) { let s = 1; for (let i = 0; i < (input.length - 2) / 2; i++) { let v = parseInt(input.slice(2 + i * 2, 4 + i * 2), 16); s = ((s * v) % 999999999999) + 1 } return s; } function R(min, max) { const range = max - min + 1; const v = (seed % range) + min; newSeed(); return Math.floor(v); } function RR() { return R(1,100)/100; } function newSeed() { nonce++; seed = ((seed * 35932678341237) + nonce) % 999999999999 + 1 } function keyPressed() { if (tokenData.plot != true) { const k = key.toUpperCase(); if (k === "S") { saveStrings([svg + sig + "</svg>"], `SCRATCH-${tokenId}`, "svg"); } else if (k === "C") { showcncPreview = !showcncPreview; updateSVG(); } else if (k === "H") { showSignature = !showSignature; updateSVG() } else if (k === "E") { saveStrings([compilecncSVG()], `SCRATCH-${tokenId}-CNC`, "svg"); } } return false; } function updateSVG() { let comp = svg; if (showSignature) { comp += sig; } if (showcncPreview) { comp += cncPreview; } document.body.innerHTML = ''; document.body.insertAdjacentHTML('beforeend', comp + "</svg>"); } function randRad(padding) { const radius = R(allRadii[0], (500) - padding); let tooClose = false; for (let i = 0; i < allRadii.length; i++) { if (Math.abs(radius - allRadii[i]) < proxLim) { tooClose = true; proxLim -= 1; break; } } if (!tooClose) { allRadii.push(radius); proxLim = 1000 / 5; return radius; } else { return randRad(padding); } } function selectByProbs(list, randomValue) { const totalWeight = list.reduce(function(acc, item, index) { return acc + (1 / (index + 2)); }, 0); const threshold = totalWeight * randomValue; let currentSum = 0; for (let i = 0; i < list.length; i++) { currentSum += 1 / (i + 2); if (currentSum >= threshold) { return list[i]; } } return list[list.length - 1]; } function compilecncSVG() { let list = svgStart; list += `<desc>The grey border is a visual guide. Please scale the vectors appropriately.</desc><rect x="0" y="0" width="1000" height="1000" style="stroke:grey; stroke-width: 1px; stroke-opacity:1; fill-opacity:0" />` for (let i = 0; i < 4; i++) { if (cncSVG[i].length > 180) { list += cncSVG[i]; } } return list + "</svg>"; } function addPoint(x,y, brushType) { let plotString = ""; const cncString = `<circle cx="${x}" cy="${y}" r="4" />`; for (let i = 0; i < R(5,7); i++) { plotString += concentrics(x, y, (brushType + 1) * (1000 / 24), 1); } return {plot: plotString, cnc: cncString}; } function getY(x0, y0, x1, y1, x) { const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const y = m * x + b; return y; } function getX(x0, y0, x1, y1, y) { const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const x = (y - b) / m; return x; } function lineWithGaps(x0, y0, x1, y1) { let xT, yT; if(x0 > x1) { xT = x0; yT = y0; x0 = x1; y0 = y1; x1 = xT; y1 = yT; } let xS = x0; let yS = y0; let yE, xE; let str = ""; let lfg = true; while (lfg) { let dS; let dnm = [[60,4,48,12],[80,12,40,8]]; finish == "Brushed" ? dS = 0 : dS = 1; let lSeg = R((1000 / dnm[dS][0]), (1000 / dnm[dS][1])); let gSeg = R((1000 / dnm[dS][2]), (1000 / dnm[dS][3])); xS + lSeg > x1 ? xE = x1 : xE = xS + lSeg; yE = getY(x0, y0, x1, y1, xE); str += `<line x1="${xS}" y1="${yS}" x2="${xE}" y2="${yE}" />` xE + gSeg > x1 ? lfg = false : xS = xE + gSeg; xS = xE + gSeg; yS = getY(x0, y0, x1, y1, xS); } return str; } function addCircle(x,y, cr, brushType) { const r = (brushType + 1) * (1000 / 24); const orbitLocs = R(2,6); let locs; const pad = (1000 / 15) + (brushType + 1) * (1000 / 48); let plotString = ""; let cncString = ""; if (pointMode) { locs = R(2,20); } else { locs = Math.floor((2 * PI * cr) / 10); cncString = `<circle cx="${x}" cy="${y}" r="${cr}" />`; } const angleStep = 2 * PI / locs; for (let i = 0; i < locs; i++) { const angle = i * angleStep; const xC = x + cr * Math.cos(angle); const yC = y + cr * Math.sin(angle); if (pointMode) { const newStrings = addPoint(xC, yC, brushType); plotString += newStrings.plot; cncString += newStrings.cnc; if (orbitMode && cr > 200) { const closestEdgeDist = Math.min(Math.min(Math.abs(1000 - xC), xC), Math.min(Math.abs(1000 - yC), yC)); if (closestEdgeDist > pad + 2 * r) { const newStringsOrbit = addOrbit(xC, yC, 2 * r, brushType, orbitLocs); plotString += newStringsOrbit.plot; cncString += newStringsOrbit.cnc; } } } else { plotString += concentrics(xC, yC, r, 0); } } return {plot: plotString, cnc: cncString}; } function addOrbit(x, y, cr, brushType, locs) { const r = (brushType + 1) * (1000 / 24); let plotString = ""; let cncString = ""; const angleStep = 2 * PI / locs; for (let i = 0; i < locs; i++) { const angle = i * angleStep; const xC = x + cr * Math.cos(angle); const yC = y + cr * Math.sin(angle); const newStrings = addPoint(xC, yC, brushType); plotString += newStrings.plot; cncString += newStrings.cnc; } return {plot: plotString, cnc: cncString}; } function concentrics(x,y,r,f) { r /= 2; let arcs = ""; if (f == 1) { x = x + R(-4, 4); y = y + R(-4, 4); } for (let i = 10; i < r; i += R(r/25, r/8) ) { arcs += randomArcSVG(x,y,i); } return arcs; } function randomArcSVG(x, y, radius) { const getRandomAngle = () => R(0,628) / 100; const startAngle = getRandomAngle(); const endAngle = getRandomAngle(); let sweepAngle = endAngle - startAngle; if (sweepAngle < 0) { sweepAngle += 2 * Math.PI; } const startX = x + radius * Math.cos(startAngle); const startY = y + radius * Math.sin(startAngle); const endX = x + radius * Math.cos(endAngle); const endY = y + radius * Math.sin(endAngle); const largeArcFlag = sweepAngle > Math.PI ? 1 : 0; const sweepFlag = 1; const d = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${endX} ${endY}`; return `<path d="${d}" />`; } function getClippedLine(x0, y0, x1, y1) { const xmin = R((100 / 24),(1000 / 48)); const ymin = R((100 / 24),(1000 / 48)); const xmax = 1000-R((100 / 24),(1000 / 48)); const ymax = 1000-R((100 / 24),(1000 / 48)); const inside = (x, y) => x >= xmin && x <= xmax && y >= ymin && y <= ymax; if (inside(x0, y0) && inside(x1, y1)) { return { x0, y0, x1, y1 }; } const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const xLeft = xmin; const yLeft = m * xLeft + b; const xRight = xmax; const yRight = m * xRight + b; const yTop = ymin; const xTop = (yTop - b) / m; const yBottom = ymax; const xBottom = (yBottom - b) / m; const intersections = [ { x: xLeft, y: yLeft }, { x: xRight, y: yRight }, { x: xTop, y: yTop }, { x: xBottom, y: yBottom } ]; const validIntersections = intersections.filter(p => inside(p.x, p.y)); if (validIntersections.length >= 2) { return { x0: validIntersections[0].x, y0: validIntersections[0].y, x1: validIntersections[1].x, y1: validIntersections[1].y }; } return null; }
Scratch is a Zen-inspired generative art project that explores the captivating patterns that sanding discs create on metal surfaces. The digital artworks can be pen-plotted at any scale, and they can be recreated on 24" x 24" sheets of metal using CNC machines. Interactivity: 'S' saves the SVG. 'C' previews the CNC paths. 'E' exports the CNC paths. 'H' hides the signature stamp. Plotter Notes: To replicate the density of the digital image, choose a pen for the main area of a Scratch that is 1/1000th the length of the sides of the plottable area. For the signature, a pen that is 2.6 times thicker than the one used for the main area is suggested. For instance, for a 10" square plot, a 0.25mm pen for the main image and a 0.65mm pen for the signature will closely mimic the density of the digital output. While bolder pens can create more visually striking images, denser Scratches plotted with thicker pens might require a heavier paper stock. CNC Notes: Experienced CNC technicians can faithfully execute the outputs on 24" x 24" sheets of metal by using 1", 2", and 3" diameter sanding discs and a 1/16" end mill. The choice of aluminum or copper as a material should be based on the specific characteristics of the Scratch output. If the Scratch output includes the 'Dark' feature, anodized aluminum or a copper with a patina can be used. Clear coat the piece after machining.
Scratch is a Zen-inspired generative art project that explores the captivating patterns that sanding discs create on metal surfaces. The digital artworks can be pen-plotted at any scale, and they can be recreated on 24" x 24" sheets of metal using CNC machines. Interactivity: 'S' saves the SVG. 'C' previews the CNC paths. 'E' exports the CNC paths. 'H' hides the signature stamp. Plotter Notes: To replicate the density of the digital image, choose a pen for the main area of a Scratch that is 1/1000th the length of the sides of the plottable area. For the signature, a pen that is 2.6 times thicker than the one used for the main area is suggested. For instance, for a 10" square plot, a 0.25mm pen for the main image and a 0.65mm pen for the signature will closely mimic the density of the digital output. While bolder pens can create more visually striking images, denser Scratches plotted with thicker pens might require a heavier paper stock. CNC Notes: Experienced CNC technicians can faithfully reproduce the digital outputs on 24" x 24" sheets of metal by using 1", 2", and 3" diameter sanding discs. The choice of aluminum or copper as a material should be based on the specific characteristics of the Scratch output. If the Scratch output includes the 'Dark' feature, both aluminum and copper sheets can be darkened with common chemicals before the machining process.
console.log("Scratch v5.1 © Matto"); console.log(`TOKEN ENTROPY: ${tokenData.hash}`); const tokenId = tokenData.tokenId; const attributes = []; let seed = makeSeed(tokenData.hash); let nonce = 0; let showcncPreview = false; let showSignature = true; const allRadii = [0]; const brushCounts = [0,0,0]; const ringQTY = selectByProbs([5,4,3,2,1], RR()); const brushTypeList = []; const m = (R(0, 200) / 100) - 1; const sizeStrings = ["Small", "Medium", "Large"]; let focusMode, orbitMode, pointMode, metal, finish, bkg, metalColor; let proxLim = 1000 / 5; RR() < .80 ? metal = "Al" : metal = "Cu"; metal == "Cu" ? metalColor = "#b87333" : metalColor = "grey"; RR() < .80 ? finish = "Brushed" : finish = "Polished"; let dark = selectByProbs([false, true], RR()); if (!tokenData.plot) { dark ? bkg = 32 : bkg = 224; } for (i = 0; i < ringQTY; i++) { brushTypeList[i] = selectByProbs([0,1,2], RR()); brushCounts[brushTypeList[i]]++; } RR() > .75 ? focusMode = true : focusMode = false; RR() > .50 ? pointMode = true : pointMode = false; RR() > .50 && pointMode == true ? orbitMode = true : orbitMode = false; addAttribute("FOCUS", focusMode); addAttribute("Point Mode", pointMode); addAttribute("Orbits", orbitMode); addAttribute("Ring Count", ringQTY.toString()); addAttribute("Small Disc Rings", brushCounts[0].toString()); addAttribute("Medium Disc Rings", brushCounts[1].toString()); addAttribute("Large Disc Rings", brushCounts[2].toString()); addAttribute("Metal", metal); addAttribute("Finish", finish); addAttribute("Dark", dark); // sessionStorage.setItem("attributes", JSON.stringify(attributes)); console.log("Attributes:"); console.log(attributes); const svgStart = `<?xml version="1.0" encoding="utf-8"?><svg viewBox="0 0 1000 1000" style="background-color:rgb(${bkg},${bkg},${bkg})" xmlns="http://www.w3.org/2000/svg">`; let svg = ""; let sig = ""; let cncPreview = ""; const cncSVG = []; for (let i=0; i < 4; i++) { cncSVG[i] = svgStart; if (i != 3) { cncSVG[i] += `<desc>Scratch with a ${i + 1}-inch pad onto 24 x 24 inch plate.</desc><g id="padsize-${i + 1}" style="stroke:black; stroke-width: 1px; stroke-opacity:1; fill-opacity:0">`; } else { cncSVG[i] += `<desc>Carve with a 1/16-inch end mill onto 24 x 24 inch plate.</desc>`; } } function setup() { noCanvas(); noLoop(); } function draw() { let bkg = `<g id="background" style="stroke:${metalColor}; stroke-width: ${1000/1000}px; stroke-opacity:1; fill-opacity:0">`; let bMod; finish == "Brushed" ? bMod = 0 : bMod = R(100, 200); for (let b = -2000; b < 2000; b += (10/3) + Math.sin(b) * (10/4) + bMod) { const x0 = Math.max(0, -b / m); const x1 = Math.min(1000, (1000 - b) / m); const y0 = b + x0 * m; const y1 = b + x1 * m; const clipped = getClippedLine(x0, y0, x1, y1); if (clipped) { bkg += lineWithGaps(clipped.x0,clipped.y0,clipped.x1,clipped.y1); } } svg = svgStart + bkg + "</g>"; for (let p = 0; p < ringQTY; p++) { let plotString = ""; let cncString = ""; const brushType = brushTypeList[p]; let radius, newStrings; const padding = 100 + (brushType + 1) * (1000 / 48); if (p == 0 && focusMode) { radius = (brushType + 1) * (2000 / 24); allRadii.push(radius); newStrings = addPoint(500, 500, brushType); } else { radius = randRad(padding); newStrings = addCircle(500, 500, radius, brushType); } plotString += newStrings.plot; cncString += newStrings.cnc; cncSVG[brushType] += newStrings.cnc; svg += `<g id="ring-${p}" style="stroke:${metalColor}; stroke-width: 1px; stroke-opacity:1; fill-opacity:0"><desc>Ring Radius: ${radius}, Disc Size: ${sizeStrings[brushType]}</desc>` + plotString + "</g>"; cncPreview += `<g id="cnc-${p}" style="stroke:blue; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0">` + cncString + "</g>"; } sig += `<polyline points="924,956 920,956 920,860 940,872 960,860 960,956 956,956" />`; sig += `<polyline points="928,902 940,872 952,902" stroke-linejoin="bevel" />`; sig += `<line x1="934" y1="888" x2="946" y2="888" />`; sig += `<line x1="920" y1="902" x2="960" y2="902" />`; sig += `<line x1="932" y1="902" x2="932" y2="928" />`; sig += `<line x1="948" y1="902" x2="948" y2="928" />`; sig += `<circle cx="940" cy="940" r="15" />`; let sigCNCStart = `<g id="cnc-signature" style="stroke:blue; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0">`; cncPreview += sigCNCStart + sig + "</g>"; cncSVG[3] += sigCNCStart + sig; sig = `<g id="signature" style="stroke:${metalColor}; stroke-width: 2.6px; stroke-opacity:1; fill-opacity:0"><desc>Suggested Pen Thickness: 2.6x</desc>` + sig + "</g>"; for (let i = 0; i < 4; i++) { cncSVG[i] += "</g></svg>"; } document.body.insertAdjacentHTML('beforeend', svg + sig + "</svg>"); console.log("CNC SVGs:"); console.log(compilecncSVG()); } function addAttribute(trait_type, value) { if (typeof value == "boolean") { value = value.toString(); } attributes.push({ trait_type, value }); } function makeSeed(input) { let s = 1; for (let i = 0; i < (input.length - 2) / 2; i++) { let v = parseInt(input.slice(2 + i * 2, 4 + i * 2), 16); s = ((s * v) % 999999999999) + 1 } return s; } function R(min, max) { const range = max - min + 1; const v = (seed % range) + min; newSeed(); return Math.floor(v); } function RR() { return R(1,100)/100; } function newSeed() { nonce++; seed = ((seed * 35932678341237) + nonce) % 999999999999 + 1 } function keyPressed() { if (tokenData.plot != true) { const k = key.toUpperCase(); if (k === "S") { saveStrings([svg], `SCRATCH-${tokenId}-SVG.txt`); } else if (k === "C") { showcncPreview = !showcncPreview; updateSVG(); } else if (k === "H") { showSignature = !showSignature; updateSVG() } else if (k === "E") { saveStrings(compilecncSVG(), `SCRATCH-${tokenId}-CNC-SVG.txt`); } } return false; } function updateSVG() { let comp = svg; if (showSignature) { comp += sig; } if (showcncPreview) { comp += cncPreview; } document.body.innerHTML = ''; document.body.insertAdjacentHTML('beforeend', comp + "</svg>"); } function randRad(padding) { const radius = R(allRadii[0], (500) - padding); let tooClose = false; for (let i = 0; i < allRadii.length; i++) { if (Math.abs(radius - allRadii[i]) < proxLim) { tooClose = true; proxLim -= 1; break; } } if (!tooClose) { allRadii.push(radius); proxLim = 1000 / 5; return radius; } else { return randRad(padding); } } function selectByProbs(list, randomValue) { const totalWeight = list.reduce(function(acc, item, index) { return acc + (1 / (index + 2)); }, 0); const threshold = totalWeight * randomValue; let currentSum = 0; for (let i = 0; i < list.length; i++) { currentSum += 1 / (i + 2); if (currentSum >= threshold) { return list[i]; } } return list[list.length - 1]; } function compilecncSVG() { let list = []; for (let i = 0; i < 3; i++) { if (cncSVG[i].length > 270) { list.push(cncSVG[i]); } } list.push(cncSVG[3]); return list; } function addPoint(x,y, brushType) { let plotString = ""; const cncString = `<circle cx="${x}" cy="${y}" r="4" />`; for (let i = 0; i < R(5,7); i++) { plotString += concentrics(x, y, (brushType + 1) * (1000 / 24), 1); //1 = randomized center mode } return {plot: plotString, cnc: cncString}; } function getY(x0, y0, x1, y1, x) { const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const y = m * x + b; return y; } function getX(x0, y0, x1, y1, y) { const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const x = (y - b) / m; return x; } function lineWithGaps(x0, y0, x1, y1) { let xT, yT; if(x0 > x1) { xT = x0; yT = y0; x0 = x1; y0 = y1; x1 = xT; y1 = yT; } let xS = x0; let yS = y0; let yE, xE; let str = ""; let lfg = true; while (lfg) { let dS; let dnm = [[60,4,48,12],[80,12,40,8]]; finish == "Brushed" ? dS = 0 : dS = 1; let lSeg = R((1000 / dnm[dS][0]), (1000 / dnm[dS][1])); let gSeg = R((1000 / dnm[dS][2]), (1000 / dnm[dS][3])); xS + lSeg > x1 ? xE = x1 : xE = xS + lSeg; yE = getY(x0, y0, x1, y1, xE); str += `<line x1="${xS}" y1="${yS}" x2="${xE}" y2="${yE}" />` xE + gSeg > x1 ? lfg = false : xS = xE + gSeg; xS = xE + gSeg; yS = getY(x0, y0, x1, y1, xS); } return str; } function addCircle(x,y, cr, brushType) { const r = (brushType + 1) * (1000 / 24); const orbitLocs = R(2,6); let locs; const pad = (1000 / 15) + (brushType + 1) * (1000 / 48); let plotString = ""; let cncString = ""; if (pointMode) { locs = R(2,20); } else { locs = Math.floor((2 * PI * cr) / 10); cncString = `<circle cx="${x}" cy="${y}" r="${cr}" />`; } const angleStep = 2 * PI / locs; for (let i = 0; i < locs; i++) { const angle = i * angleStep; const xC = x + cr * Math.cos(angle); const yC = y + cr * Math.sin(angle); if (pointMode) { const newStrings = addPoint(xC, yC, brushType); plotString += newStrings.plot; cncString += newStrings.cnc; if (orbitMode && cr > 200) { const closestEdgeDist = Math.min(Math.min(Math.abs(1000 - xC), xC), Math.min(Math.abs(1000 - yC), yC)); if (closestEdgeDist > pad + 2 * r) { const newStringsOrbit = addOrbit(xC, yC, 2 * r, brushType, orbitLocs); plotString += newStringsOrbit.plot; cncString += newStringsOrbit.cnc; } } } else { plotString += concentrics(xC, yC, r, 0); } } return {plot: plotString, cnc: cncString}; } function addOrbit(x, y, cr, brushType, locs) { const r = (brushType + 1) * (1000 / 24); let plotString = ""; let cncString = ""; const angleStep = 2 * PI / locs; for (let i = 0; i < locs; i++) { const angle = i * angleStep; const xC = x + cr * Math.cos(angle); const yC = y + cr * Math.sin(angle); const newStrings = addPoint(xC, yC, brushType); plotString += newStrings.plot; cncString += newStrings.cnc; } return {plot: plotString, cnc: cncString}; } function concentrics(x,y,r,f) { r /= 2; let arcs = ""; if (f == 1) { x = x + R(-4, 4); y = y + R(-4, 4); } for (let i = 10; i < r; i += R(r/25, r/8) ) { arcs += randomArcSVG(x,y,i); } return arcs; } function randomArcSVG(x, y, radius) { const getRandomAngle = () => R(0,628) / 100; const startAngle = getRandomAngle(); const endAngle = getRandomAngle(); let sweepAngle = endAngle - startAngle; if (sweepAngle < 0) { sweepAngle += 2 * Math.PI; } const startX = x + radius * Math.cos(startAngle); const startY = y + radius * Math.sin(startAngle); const endX = x + radius * Math.cos(endAngle); const endY = y + radius * Math.sin(endAngle); const largeArcFlag = sweepAngle > Math.PI ? 1 : 0; const sweepFlag = 1; const d = `M ${startX} ${startY} A ${radius} ${radius} 0 ${largeArcFlag} ${sweepFlag} ${endX} ${endY}`; return `<path d="${d}" />`; } function getClippedLine(x0, y0, x1, y1) { const xmin = R((100 / 24),(1000 / 48)); const ymin = R((100 / 24),(1000 / 48)); const xmax = 1000-R((100 / 24),(1000 / 48)); const ymax = 1000-R((100 / 24),(1000 / 48)); const inside = (x, y) => x >= xmin && x <= xmax && y >= ymin && y <= ymax; if (inside(x0, y0) && inside(x1, y1)) { return { x0, y0, x1, y1 }; } const m = (y1 - y0) / (x1 - x0); const b = y0 - m * x0; const xLeft = xmin; const yLeft = m * xLeft + b; const xRight = xmax; const yRight = m * xRight + b; const yTop = ymin; const xTop = (yTop - b) / m; const yBottom = ymax; const xBottom = (yBottom - b) / m; const intersections = [ { x: xLeft, y: yLeft }, { x: xRight, y: yRight }, { x: xTop, y: yTop }, { x: xBottom, y: yBottom } ]; const validIntersections = intersections.filter(p => inside(p.x, p.y)); if (validIntersections.length >= 2) { return { x0: validIntersections[0].x, y0: validIntersections[0].y, x1: validIntersections[1].x, y1: validIntersections[1].y }; } return null; }
Scratch is a Zen-inspired generative art project that explores the captivating patterns that sanding discs create on metal surfaces. The digital artworks can be pen-plotted at any scale, and they can be recreated on 24" x 24" sheets of metal using CNC machines. Interactivity: 'S' saves the SVG. 'C' previews the CNC paths. 'E' exports the CNC paths. 'H' hides the signature stamp. Plotter Notes: To replicate the density of the digital image, choose a pen for the main area of a Scratch that is 1/1000th the length of the sides of the plottable area. For the signature, a pen that is 2.6 times thicker than the one used for the main area is suggested. For instance, for a 10" square plot, a 0.25mm pen for the main image and a 0.65mm pen for the signature will closely mimic the density of the digital output. While bolder pens can create more visually striking images, denser Scratches plotted with thicker pens might require a heavier paper stock. CNC Notes: Experienced CNC technicians can faithfully reproduce the digital output on 24" x 24" sheets of metal by using standard sanding disc sizes of 1", 2", and 3". The choice of aluminum or copper as a material should be based on the specific characteristics of the Scratch output. If the Scratch output includes the 'Dark' feature, both aluminum and copper sheets can be darkened with common chemicals before the machining process.
Generative Alchemy is a versatile utility NFT collection that provides a toolset for divination, spell-casting, meditation, sacrifice, spirit worship (benign or otherwise), hedonism, pacifism, inter-dimensional travel, cryptozoological investigation, seance, prayer, banishing, chaos magic, clairvoyance, chromotherapy, evocation, dowsing, exorcism, fortune-telling, literomancy, necromancy, shapeshifting, and other esoteric (or mainstream) ritual (including entertainment). Collectors, devotees, rationalists, pirates, and all others alike are encouraged to leverage the designs pursuant to their own subjective belief system (whether sincere or imaginary) to address any and all desires (emotional or material). Generative Alchemy is provided as-is without explicit documentation, but here are some hypotheticals to get you started: Suffering from unrequited love? Plot it on a photo of your crush. Desire riches behind your wildest dreams? Plot it on your paystub. Want fame? Plot it on a magazine cover. Want to change your past? Plot it on a childhood picture. In too much of a hurry to plot? Click to activate the sequence.
Generative Alchemy is a versatile utility NFT collection that provides a toolset for divination, spell-casting, meditation, sacrifice, spirit worship (benign or otherwise), hedonism, prayer, pacifism, inter-dimensional travel, cryptozoological investigation, seance, prayer, banishing, chaos magic, clairvoyance, chromotherapy, evocation, dowsing, exorcism, fortune-telling, literomancy, necromancy, shapeshifting, and other esoteric (or mainstream) ritual (including entertainment). Collectors, devotees, rationalists, pirates, and others alike are encouraged to leverage the designs pursuant to their own subjective belief system (whether sincere or imaginary) to address any and all desires (emotional or material). Generative Alchemy is provided as-is without explicit documentation, but here are some hypotheticals to get you started: Suffering from unrequited love? Plot it on a photo of your crush. Desire riches behind your wildest dreams? Plot it on your paystub. Want fame? Plot it on a magazine cover. Want to change your past? Plot it on a childhood picture. In too much of a hurry to plot? Click to activate the sequence.
SS=tokenData.hash,S=Uint32Array.from([0,1,s=t=2,3].map($=>parseInt(SS.substr(8*$+2,8),16))),R=$=>(t=S[3],S[3]=S[2],S[2]=S[1],S[1]=s=S[0],t^=t<<11,S[0]^=t^t>>>8^s>>>19,S[0]/4294967296),setAttributes(Svg=document.createElementNS("http://www.w3.org/2000/svg","svg"),{viewBox:"0 0 80 100",fill:"black"}),WW=80,HH=100,pAL=["wOL","rOL","gOL","rGL","rNW","bOL","bRD","all"][Math.floor(7*R())];let mnSK;for("bOL"==pAL||"bRD"==pAL||"all"==pAL?mnSK="black"&&dReC(0,0,WW,HH,f="white",c="black"):(dReC(0,0,WW,HH,f="black"),mnSK=["red","gold","white"][Math.floor(3*R())]),sFUl=R()>.9,sPlF=R()>.8,icons={dGGr:"M 0 -42 C 0 -33 -1 -28 -5 -21 C -1 -24 -3 12 -2 23 L -11 23 L -11 26 L -2 26 L -2 48 L 2 48 L 2 26 L 12 26 L 12 23 L 2 23 C 2 8 13 -36 0 -42 M 2 26 L -2 26 L 2 31 L -2 29 L 2 33 L -2 31 L -2 31 L 2 35 L -2 33 L 2 38 L -2 36 L 2 40 L -2 39 L 2 44 L -1 42 L -2 42 L 2 46 L -2 45 L 2 48",dGG2:"M 0 -42 L -5 -12 L -2 25 L -9 25 L -9 28 L -2 28 L -3 46 L 3 46 L 2 28 L 9 28 L 9 25 L 2 25 L 5 -11 L 0 -42",tDNt:"M 0 -39.2 L -4.8 -34.4 L -0.8 -34.4 L -0.8 -6.4 C -14.4 -4.8 -15.2 -17.6 -14.4 -34.4 L -12 -34.4 L -16 -39.2 L -18.4 -34.4 L -16 -34.4 C -16 -16.8 -16 -4 -0.8 -4.8 L -1.6 35.2 L 1.6 35.2 L 0.8 -4.8 C 13.6 -7.2 17.6 -20 16 -34.4 L 19.2 -34.4 L 14.4 -39.2 L 12 -34.4 L 14.4 -34.4 C 16.8 -23.2 12.8 -7.2 0.8 -7.2 L 0.8 -34.4 L 4.8 -34.4 L 0 -39.2 Z",cube:"M -18 -26 L 21 -25 L 21 14 M 21 14 L -18 14 L -18 -26 M -4 -8 L 33 -8 L 33 29 L -3 29 L -4 -8 M -18 -26 L -4 -8 M 21 -25 L 33 -8 M -18 14 L -3 29 M 21 14 L 33 29",kITT:"M -5.6 -14.4 C -20 -4 -24 11.2 -18.4 28 L 18.4 28 C 31.2 16 19.2 -12.8 30.4 -26.4 C 30.4 -30.4 28 -25.6 25.6 -24.8 C 23.2 -24.8 24 8.8 20 21.6 C 19.2 4 20.8 -20 7.2 -13.6 C 12.8 -20 15.2 -28 7.2 -32.8 L 6.4 -37.6 L 4 -33.6 C 0 -34.4 -3.2 -34.4 -7.2 -32.8 L -11.2 -38.4 L -9.6 -30.4 C -13.6 -24 -17.6 -18.4 -5.6 -14.4",yrMi:"M -3 -29 L -31 26 L 17 32 L -3 -29 L 38 16 L 17 32",eye:"M 0 -31.2 C -23.2 -12 -25.6 16.8 0 37.6 C 28 24.8 26.4 -12 0 -31.2 C -16 -11.2 -20 11.2 0 37.6 C 22.4 13.6 18.4 -6.4 0 -31.2 M 0 -10.4 A 0.8 0.8 90 0 0 0 13.6 A 0.8 0.8 90 0 0 0 -10.4 M 0 -1.6 A 0.8 0.8 90 0 0 0 4 A 0.8 0.8 90 0 0 0 -1.6",tHma:"M 0.6949 -29.8125 l 27.9491 47.9734 L -27.2546 -10.2863 L 0.6949 37.6875 l 27.9491 -47.9734 L -27.2546 18.1613 L 0.6949 -29.8125 z",yyNg:"M 0 30.4 a 30.4 30.4 90 0 1 0 -60.8 a 15.2 15.2 90 0 1 0 30.4 a 15.2 15.2 90 0 0 0 30.4 M 0 30.4 A 0.8 0.8 90 0 0 0 -30.4",pTcL:"m -0.75 -32 l 18.5 57 l -48.5 -35.25 h 60 l -48.5 35.25 z m 0 -1.75 a 33.25 33.25 90 1 1 -0.025 0",sxPn:"M 0 -32.8487 L -14.995 32.8487 L 27.0201 -19.8365 L -33.6935 9.4016 L 33.6935 9.4016 L -27.0201 -19.8366 L 14.995 32.8487 L 0 -32.8487 z",ankh:"M 8 -4 L 0 -4 C 16 -16 10 -35 0 -38 C -12 -35 -13 -17 0 -4 L -3 -4 C -14 -10 -26 -37 0 -40 C 24 -35 17 -8 3 -4 L -25 -4 L -25 1 L -2 0 L -4 46 L 4 46 L 2 0 L 29 2 L 29 -5 L 8 -4",moon:"M 0 -34 A 1 1 0 0 0 0 28 C -26 11 -25 -18 0 -34",male:"M 13.0108 -13.0108 A 0.8 0.8 135 0 0 -13.0108 13.0108 A 0.8 0.8 135 0 0 13.0108 -13.0108 L 30.547 -30.547 M 29.9813 -20.9304 L 30.547 -30.547 M 20.9304 -29.9813 L 30.547 -30.547",fMLe:"M 0 -18.4 A 0.8 0.8 90 0 0 0 18.4 A 0.8 0.8 90 0 0 0 -18.4 M 0 18.4 L 0 45.6 M -14.4 32 L 13.6 32",es1:"M 0 -29.6 L -7.2 -23.2 L -2.4 -23.2 L -2.4 -4 L -16.8 -4 L -16.8 -8 L -24 -2.4 L -16.8 3.2 L -16.8 0 L -2.4 0 L -2.4 16 L -14.4 16 C -17.6 28.8 3.2 8 17.6 37.6 C 12.8 29.6 12.8 12 3.2 13.6 L 3.2 0 L 20.8 0 L 20.8 4.8 L 27.2 -3.2 L 20.8 -8.8 L 20.8 -4 L 3.2 -4 L 3.2 -23.2 L 8 -23.2 L 0 -29.6 M 11.2 -20 A 0.8 0.8 90 0 0 11.2 -11.2 A 0.8 0.8 90 0 0 11.2 -20 M -5.6 26.4 A 0.8 0.8 90 0 0 -5.6 34.4 A 0.8 0.8 90 0 0 -5.6 26.4",es2:"M -15.2 -16.8 A 0.8 0.8 90 0 0 -15.2 -5.6 L -15.2 -11.2 L 3.2 -11.2 L -19.2 27.2 L -23.2 24 L -24.8 26.4 L -16 34.4 L -12 28.8 L -15.2 26.4 L -3.2 6.4 C 8.8 3.2 4.8 32.8 16.8 35.2 C 10.4 24.8 25.6 7.2 3.2 0.8 L 30.4 2.4 A 0.8 0.8 90 0 0 29.6 -5.6 C 14.4 -3.2 -4 -16 0 -32 L -15.2 -16.8 M 15.2 -25.6 A 0.8 0.8 90 0 0 27.2 -18.4 L 25.6 -29.6 L 15.2 -25.6 M -4.8 19.2 L -0.8 35.2 L 4 19.2 L -4.8 19.2",yEOp:"M 0 -29 A 1 1 0 0 0 0 35 A 1 1 0 0 0 0 -29 M 0 -21 L -23 18 L 24 18 L 0 -21 M -11 6 C -2 18 4 7 12 4 C 2 -7 -3 2 -11 6 M 0 3 A 1 1 0 0 0 0 7 A 1 1 0 0 0 0 3 M 0 -14 L 0 -5 M 9 9 L 16 14 M -11 11 L -17 16 M 0 13 L 0 15 M 4 -5 L 6 -7 M -4 -5 L -6 -7",atom:"M 0 -33 C -11 -33 -9 38 0 36 C 10 35 9 -34 0 -33 M -30 0 C -30 10 32 9 31 0 C 33 -9 -29 -10 -30 0 M -21 25 C -16 32 30 -19 23 -26 C 17 -32 -27 19 -21 25 M 0 -3 A 1 1 0 0 0 0 3 A 1 1 0 0 0 0 -3",cross:"M 0 -27 L -6.3 -27 L -6.3 -11.7 L -25.2 -11.7 L -25.2 -3.6 L -6.3 -3.6 L -5.4 40.5 L 5.4 40.5 L 5.4 -3.6 L 26.1 -3.6 L 26.1 -11.7 L 5.4 -11.7 L 5.4 -27 L 0 -27 Z",pi:"M -11.664 -11.664 C -14.904 -12.312 -18.144 -13.608 -20.088 -9.72 C -20.736 -22.032 3.24 -14.904 20.088 -17.496 C 21.384 -15.552 20.736 -12.96 19.44 -11.016 L 12.96 -11.664 C 13.176 3.24 9.72 30.456 18.144 30.456 C 1.296 33.048 11.232 2.376 7.776 -11.664 L -7.128 -11.664 L -7.128 29.16 C -8.424 30.456 -10.584 29.16 -12.312 29.16 C -12.096 15.552 -9.72 -1.296 -11.664 -11.664 Z",oro:"M -18.75 -2.25 A 0.75 0.75 90 0 0 23 -9 C 19 -23 1 -28 -7 -20 L -5 -13 L -18 -7.5 L -20.25 -9 L -20 -15 L -20 -25 L -12 -24 C 0 -40 31 -27 30 -3 C 25 28 -24 28.5 -19.5 -8.25 C -19.5 -6 -18.75 -7.5 -19 -3 Z",worm : "M9.68-13.93a14.25 14.25 0 0 1 5.34-1.13C23.81-15.06 31-8.3 31 .05c0 8.32-7.05 15.01-15.84 15.01-5.62 0-10.02-3.05-13.2-6.26 1.08-1.47 3.49-4.95 4.45-6.34 2.22 2.55 5.37 4.93 8.7 4.99 4.58.08 8.22-3.46 8.29-7.38.08-4.39-4.8-8.47-9.95-7.18.59-3.11-1.9-6.23-3.77-6.82Zm-.16 8.66C5.6-2.55 2.96 2.59-.77 7.5c-1.19 1.57-7.04 7.54-14.3 7.54-8.81.01-15.93-6.67-15.93-15s7.1-15 15.89-15c5.66 0 10 3.07 13.19 6.3-.9 1.25-3.3 4.77-4.44 6.35-2.21-2.56-5.46-5.03-8.8-5.03-4.45 0-8.23 3.47-8.23 7.38 0 3.92 3.78 7.42 8.23 7.4 2.37 0 5.77-1 10.21-6.73C-.2-5.41.2-7.72 4.65-11.1c1.74-1.32 4.38-.55 5.57 1.59.63 1.13.4 3-.7 4.24 Z"},bSQc=rColor(),brSM=R()>.9,icon=Object.keys(icons)[Math.floor(Object.keys(icons).length*R())],x=WW/10;x<WW;x+=WW/10)for(y=HH/10;y<HH;y+=HH/10)(x>=WW/10&&y==HH/10||x==WW-WW/10&&y>=HH/10||x>=WW/10&&y==HH-HH/10||x==WW/10&&y<=HH-HH/10||sFUl||sPlF&&R()>.5)&&(brSM||(icon=Object.keys(icons)[Math.floor(Object.keys(icons).length*R())]),R()>.1&&dICo(icons[icon],x,y,.1,f="none",r=!1,c=rColor()),R()>.9&&dReC(x-(R()>.5?0:WW/10),y-(R()>.5?0:HH/10),WW/10,HH/10,f="none",c=bSQc),R()>.5&&dCIC(x,y,WW/10/2,c=rColor()),R()>.3&&dReC(x-WW/10/2,y-HH/10/2,WW/10,HH/10,f="none",c=bSQc),R()>.8&&dCIC(x,y,WW/10,c=rColor()));if(lAYt=["grNi","cRCs","thGY"][Math.floor(3*R())],cnRs=R()>.9,icon=Object.keys(icons)[Math.floor(Object.keys(icons).length*R())],"thGY"!=lAYt||sFUl||sPlF){if("cRCs"!=lAYt||sFUl||sPlF){if("grNi"==lAYt&&!sFUl&&!sPlF)for(x=WW/10+WW/10+WW/10;x<WW-WW/10-WW/10;x+=WW/10)for(y=HH/10+HH/10+HH/10;y<HH-HH/10-HH/10;y+=HH/10)cnRs||(icon=Object.keys(icons)[Math.floor(Object.keys(icons).length*R())]),dICo(icons[icon],x,y,.1,f="none",r=!0,c=rColor()),dReC(x-WW/10/2,y-HH/10/2,WW/10,HH/10,f="none",c=bSQc)}else n=[2,4,6,8,12,16,20,30][Math.floor(8*R())],cPnT(WW/2,HH/2,WW/10,n+=4,o=R()+.5).forEach($=>{dCIC($[0],$[1],10,c=rColor())})}else cPnT(40,50,17,n=10).forEach($=>{dCIC($[0],$[1],5,c=rColor()),cnRs||(icon=Object.keys(icons)[Math.floor(Object.keys(icons).length*R())]),dICo(icons[icon],$[0],$[1],.1,f=rColor(),!0,c=rColor())}),icon=Object.keys(icons)[Math.floor(Object.keys(icons).length*R())],dICo(icons[icon],40,50,.2,f=rColor,r=!0,c=rColor());function rColor(){if("bOL"==pAL)return"black";if("wOL"==pAL)return"white";if("rOL"==pAL)return"red";if("gOL"==pAL)return"gold";if("rGL"==pAL)return["gold","red"][Math.floor(2*R())];else if("rNW"==pAL)return["white","red"][Math.floor(2*R())];else if("bRD"==pAL)return["black","red"][Math.floor(2*R())];else return["white","red","gold"][Math.floor(3*R())]}function cPnT($,_,e,L=5,t=1){let l=[];for(i=0;i<L;i++)l.push([$+e*Math.cos(2*Math.PI*i/L)*t,_+e*Math.sin(2*Math.PI*i/L)*t]);return l}function dICo($,_,e,L,t=!1,l=!0,C="gold"){let a="";Object.getOwnPropertyNames(icons).forEach(_=>{$==icons[_]&&(a=_)}),["yrMi","cube","kITT","eye","tHma","yyNg","pTcL","sxPn","tHma","fMLe","male","yEOp","atom"].includes(a)&&(t="none"),["yrMi","kITT","tHma"].includes(a)&&(l=!1);let s=document.createElementNS("http://www.w3.org/2000/svg","path");setAttributes(s,{d:$,fill:t||"none",stroke:C,transform:`translate(${_}, ${e}) scale(${L}) rotate(${l?360*R():0})`,"stroke-width":2}),Svg.appendChild(s)}function dReC($,_,e,L,t="none",l="gold",C=.1){let a=document.createElementNS("http://www.w3.org/2000/svg","rect");setAttributes(a,{x:$,y:_,width:e,height:L,fill:t,stroke:l,"stroke-width":C}),Svg.appendChild(a)}function dCIC($,_,e,L="gold"){setAttributes(_circle=document.createElementNS("http://www.w3.org/2000/svg","circle"),{cx:$,cy:_,r:e,"fill-opacity":"0",stroke:L,"stroke-width":.1}),Svg.appendChild(_circle)}function setAttributes($,_){for(key in _)$.setAttribute(key,_[key])}document.body.appendChild(Svg);let _nINg=!1,iRVL,mxRe=5*R(),rOLY=R()>.8;function ANLO(){function $($,_,e){return setAttributes(_anim=document.createElementNS("http://www.w3.org/2000/svg","animate"),{attributeType:"xml",attributeName:$,values:_,dur:e,additive:"sum",repeatCount:"indefinite"}),_anim}(_paths=document.querySelectorAll("path")).forEach($=>{setAttributes(_anim=document.createElementNS("http://www.w3.org/2000/svg","animateTransform"),{attributeType:"xml",attributeName:"transform",type:"rotate",from:"360 0 0",to:"0 0 0",dur:"5s",additive:"sum",repeatCount:"indefinite"}),R()>.95&&$.appendChild(_anim),Svg.appendChild($)}),(_rects=document.querySelectorAll("rect")).forEach(_=>{targColor=["gold","red","white","black"][Math.floor(4*R())],_anim=$("fill",`${targColor};none;${targColor}`,`${5*R()+1}s`),R()>.95&&_.appendChild(_anim),_anim2=$("x",`${-(WW*R())};${WW};${-(WW*R())}`,`${10*R()+3}s`),R()>.95&&!rOLY&&_.appendChild(_anim2),_anim3=$("y",`${-(HH*R())};${HH};${-(HH*R())}`,`${10*R()+3}s`),R()>.95&&!rOLY&&_.appendChild(_anim3)}),(_cRCs=document.querySelectorAll("circle")).forEach(_=>{_anim=$("stroke-width",`0;${2*R()};0`,`${5*R()+1}s`),R()>.95&&_.appendChild(_anim)}),(MATI=document.querySelectorAll("animate, animateTransform")).forEach($=>{R()>.85&&$.remove()})}!0!=tokenData.plot&&document.body.addEventListener("click",()=>{(_nINg=!_nINg)?(ANLO(),iRVL=setInterval(ANLO,8e3*R()+2e3)):(clearInterval(iRVL),(MATI=document.querySelectorAll("animate, animateTransform")).forEach($=>{$.remove()}))});document.getElementsByTagName('svg')[0].style="height:"+window.innerHeight;Svg.setAttribute('width', '100vw');Svg.setAttribute('height', '100vh');
function setup(){const a=createVector;noiseSeed(s),noCanvas();var o=900,l=1200;const t=new CC;var i=rnd()<.45,e=60*floor(i?rnd(20,26):rnd(15,20)),n=floor(rnd(2,6)),c=e/n;const p=[],r=[];for(let e=0;e<n;e++){const{v:a,n:$}=t.N(r);r.push(a),p[e]={v:a,n:$,shapes:[]}}const h=gnf();var v=18e4/1080,f=floor(rnd(3,9)),u=o/(i?rnd(48,128):rnd(24,40));for(let r=0;r<n;r++){const A=[];for(let e=0;e<f-1;e++)A[e]=[rnd(2e3),rnd(2e3)];for(let e=0;e<c;e++){var g,w=e<c/2?map(e,0,c/2,0,u):map(e,c/2,c,u,0);let t,n;const N=[];n=i?(g=map(e,0,c-1,0,l),t=a(0,g),a(o,g)):(x=map(e,0,c-1,0,o),t=a(x,0),a(x,l));for(let e=0;e<A.length;e++){const a=p5.Vector.lerp(t,n,(e+1)/f);var[m,y]=A[e];a.x+=map(h(m,a.x/v,a.y/v),0,1,-w,w),a.y+=map(h(y,a.y/v,a.x/v),0,1,-w,w),a.x<0&&(a.x=0),a.y<0&&(a.y=0),a.x>o&&(a.x=o),a.y>l&&(a.y=l),N.push(a)}var x=e%2==0?[t,...N,n]:[n,...N.reverse(),t];p[r].shapes.push(x)}}var S="http://www.w3.org/2000/svg";let C=document.createElementNS(S,"svg");C.sa=C.setAttribute,C.sa("class","plot"),C.sa("width","9in"),C.sa("height","12in"),C.sa("viewBox","0 0 900 "+l),C.sa("style","background-color:white;"),C.sa("xmlns","http://www.w3.org/2000/svg"),C.sa("xmlns:inkscape","http://www.inkscape.org/namespaces/inkscape");for(let e=0;e<p.length;e++){var k=p[e];const E=d.createElementNS(S,"g");var M=`${e+1} - ${k.n}`;E.sa=E.setAttribute,E.sa("id",M),E.sa("inkscape:groupmode","layer"),E.sa("inkscape:label",M);for(let e=0;e<k.shapes.length;e++){var b=k.shapes[e];let t=`M ${b[0].x} ${b[0].y}`;for(let e=1;e<b.length;e++)t+=` L ${b[e].x} ${b[e].y}`;const B=d.createElementNS(S,"path");B.setAttribute("style",`fill:none;stroke-width:1;stroke:${k.v};`),B.setAttribute("d",t),E.appendChild(B)}C.appendChild(E)}d.body.appendChild(C);let R=d.createElement("style");R.appendChild(d.createTextNode(".plot{width:100vw;height:100vh;}")),d.head.appendChild(R)}h=tokenData.hash,S=Uint32Array.from([0,1,s=t=2,3].map(e=>parseInt(h.substr(8*e+2,8),16))),R=e=>(t=S[3],S[3]=S[2],S[2]=S[1],S[1]=s=S[0],t^=t<<11,S[0]^=t^t>>>8^s>>>19,S[0]/2**32),s=parseInt(h.slice(0,16),16),d=document,rnd=(e,t)=>{var n,r=R();return void 0===e?r:void 0===t?e instanceof Array?e[Math.floor(r*e.length)]:r*e:(t<e&&(n=e,e=t,t=n),r*(t-e)+e)};class CC{n=["Micron Rose","Micron Red","Micron Orange","Micron Green","Micron Blue","Micron Purple","Micron Brown"];v=["#df4a82","#f1230a","#f47d3d","#47a858","#0972c4","#842eae","#a14725"];R(){return rnd(this.v)}N(e){let t=this.R();for(;e.includes(t);)t=this.R();var n=this.n[this.v.indexOf(t)];return{v:t,n:n}}}function gnf(){const r=floor(rnd(5,10));return rnd([(e,t,n)=>noise(e,t,n),(e,t,n)=>ceil(noise(e,t,n)*r)/r])}
/* minimizer, 2023. https://minimizer.art/ */ function calculateFeatures(e){t=(e,a)=>{let t=0,n=[o(e),o(a)],r=()=>n[t++%2];return{$R:(e,a)=>r().$R(e,a),$I:(e,a)=>r().$I(e,a),$6:()=>r().$6()}},n=a=>[0,8].map(e=>parseInt(a.slice(2+e,2+e+8),16));let a={j:o=n=>{var t=(e,a)=>{return n=(n=(n^=n<<13)^n>>17)^n<<5,a=a-e+1,(0<(t=n<0?1+~n:n)?t%a:t%a+a)+e;var t},e=(e,a)=>t(1,a)<=e;return{$R:t,$I:e,$6:()=>e(1,2)?1:-1}},$7:e=>{e=n(e);return t(...e)}};r=a=>{var t=e=>e[a.$R(0,e.length-1)],e="he,she,my neighbor,my boss,my trainer,the teacher,the professor,the super,the barista,my therapist",n="lunch,dinner",r="I could really go for,It's been a while since I had",o=r+",I need a new spot for,Where do I get the best",s="I wonder",i=[["I need,I want,I want,It's time for,When can I get","a","coffee,tea,shot,snack,break,day off,new job,new roommate,new house,vacation,promotion,date,boyfriend,girlfriend,partner,babysitter,dog,cat,hug"],["Can't wait for","vacation,happy hour,my birthday,my wedding,my last day,the new year,the holidays,spring,summer,autumn,winter,graduation,retirement,the weekend,better weather,the snow,the beach,bed"],["I should have,I shouldn't have,Wish I'd","had breakfast,said yes,said no,had that last drink,stayed out later,gone to the party,gone for a run,taken a walk,exercised,stretched,worked harder,paid attention,skipped the meeting,eaten that,eaten more,saved more money,gotten high,slept in,napped"],["Did I,I need to,I forgot to","take out the garbage,"+["flight","appointment","meeting","class","reservation"].map(e=>["book that "+e,"cancel that "+e]).flat().join(",")+",cancel that subscription,do laundry,pay the rent,reply to that email,do the dishes"]],s=[[s,"what",e,"thinks of me,does for fun"],[s,"where",e,"shops,goes for vacation"],[s,"if",e,"likes,hates,knows,notices,cares about,is upset with","me"]],e=[[r,"a","bagel,steak,salad,burrito,sandwich,burger,smoothie,juice,wrap,bender,massage,mani-pedi"],[r,"anything healthy,something greasy,spicy food,something sweet,comfort food"],[o,"barbeque,nuggets,cake,donuts,empanadas,fish and chips,fries,hot dogs,ice cream,sushi,noodles,pizza,ramen,seafood,pho,wings"],[o,"Argentinian,Chinese,Cuban,Ethiopian,French,Greek,Indian,Italian,Jamaican,Japanese,Korean,Lebanese,Mediterranean,Mexican,Spanish,Thai,Turkish,vegan,vegetarian","food"]];return t(t([i,i,i,i,i,s,s,s,s,[["I forgot to order,It's going to be leftovers for",n,",again"],["What's for,Did I order,I need ideas for",n]],e,e,e,e])).map(e=>t(e.split(","))).join(" ").trim()};var o,t,n,r;return e=a.$7(e.hash),{"Thinking about":r(e)}}
/* minimizer, 2023. https://minimizer.art/ */ (()=>{let L=Array,i=Math,v=i.trunc,k=i.min,x=i.max,E=parseInt,A={$g:a=i=>{var t=(e,n)=>{return i=(i=(i^=i<<13)^i>>17)^i<<5,n=n-e+1,(0<(t=i<0?1+~i:i)?t%n:t%n+n)+e;var t},e=(e,n)=>t(1,n)<=e;return{G:t,K:e,S:()=>e(1,2)?1:-1}},$p:i=>{n=i;var n,i=[0,8].map(e=>E(n.slice(2+e,2+e+8),16));{var[i,r]=[...i];let e=0,n=[a(i),a(r)],t=()=>n[e++%2];return{G:(e,n)=>t().G(e,n),K:(e,n)=>t().K(e,n),S:()=>t().S()}}}};var a,r,t,n;let $={$7:r=(e,n)=>({x:v(e),y:v(n)}),Y:(e,n)=>((e.x-n.x)**2+(e.y-n.y)**2)**.5,$T:(e,n,t)=>r(e.x+i.sin(n/1e3/180*i.PI)*t,e.y+i.cos(n/1e3/180*i.PI)*t),$6:(e,n,t,i)=>({R:e,O:n,z:t,q:i,w:t-e,h:i-n})},B=({$7:m,Y:p},e)=>(n,t,i,r,a)=>{var o=x,s=v,e=1e3*t.G(0,359),l=[],d=s((n.w+n.h)/2);for(let e=1;e<2*i;e+=2){var u=s(e*n.w/(2*i));for(let e=1;e<2*i;e+=2){var F=s(e*n.h/(2*i)),c=s(d/i*t.G(120,200)/100);l.push({$f:m(u,F),V:c,$e:t.S()*t.G(r,a)})}}return{J:t=>e+l.map(e=>{var n=t;return n=p(t,e.$f),s(o(0,s(e.V-n))*e.$e/e.V)}).reduce((e,n)=>e+n,0)}},W=({Y:s})=>({$H:n=>{var i={},r=[],a=e=>v(e/n),o=(t,i,r)=>{for(let n=a(t.x-i);n<=a(t.x+i);n++)for(let e=a(t.y-i);e<=a(t.y+i);e++)if(r(1e7*n+e))return!0},t=(e,n)=>{var t={X:e,r:n};r.push(t),o(e,n,e=>{i[e]||(i[e]=[]),i[e].push(t)})};return{$2:t,Z:(n,t)=>o(n,t,e=>i[e]&&i[e].some(e=>s(n,e.X)<e.r+t)),$W:(e,n)=>e.$c.map(e=>t(e.X,e.r+n)),$c:r}},$o:(t,i)=>({$2:t.$2,Z:(e,n)=>t.Z(e,n)||i.Z(e,n)})}),M=(t=L.isArray,{$b:(e,...n)=>({$5:e,$M:n.filter(e=>!t(e)).reduce((e,n)=>({...e,...n}),{}),$0:n.filter(e=>t(e)).flat()}),$V:n=e=>"string"==typeof e?e:`<${e.$5}${Object.entries(e.$M).map(([e,n])=>` ${e}="${n}"`).join("")}${0==e.$0.length?"/":""}>`+e.$0.map(n).join("")+(0<e.$0.length?`</${e.$5}>`:"")}),H=({$7:p,Y:g})=>{var h=e=>e.length,x=e=>h(e)-1;return(r,e,n,t,i,a,o)=>{var s=[];let l=0,d,u=2*a;let F=0;var c=()=>h(d),m=e=>[e.x,e.y];return{$m:e=>{var n,t,i,e=e.G;return 0==h(s)?p(e(r.R,r.z),e(r.O,r.q)):(n=(n=s[e(e(0,x(s)),x(s))])[e(0,e(0,x(n)))],i=e(-(t=6*a),t),e=e(-t,t),p(n.x+i,n.y+e))},$J:e=>{return t=r,(n=e).x>t.R&&n.x<t.z&&n.y>t.O&&n.y<t.q&&!((n,t,i)=>{for(let e=h(i)-2;0<=e;e--)if(g(n,i[e])<t)return!0;return!1})(e,u,d)&&!o.Z(e,a);var n,t},$k:()=>d=[],$G:e=>d.push(e),$K:()=>d[x(d)],$L:c,$l:()=>c()>=n,$a:n=>{h(d)>=e?(s.push(d),F+=h(d),d.map(e=>o.$2(e,a+n))):l++},$Z:()=>F>=t||l>=i,$v:()=>s[0][0],N:()=>F,$F:()=>h(s),$Y:()=>s.map(r=>["M",m(r[0]),...(h(r)<=2?[]:r.map((e,n,t)=>{return 0==n?[]:["Q",m(r[n-1]),m((i=r[n-1],n=r[n],p((i.x+n.x)/2,(i.y+n.y)/2)))];var i})).flat(),"L",m(r[x(r)])]).flat().join(" ")}}},T=({Y:p})=>{var g=(e,n)=>({$9:e,K:n}),o=(e,n)=>{var t,i=n.map(e=>e.K).reduce((e,n)=>e+n),r=e.G(1,i);let a=0;for(t of n)if(r<=(a+=t.K))return t},h=(e,n)=>o(e,n).$9,r=(n,t,i)=>{var r=[];for(let e=0;e<t;e++){var a=o(n,i);r.push(a.$9),i=i.filter(e=>e!==a)}return r},x=(e,n,t,i,r,a)=>g({$N:i,$s:r,$B:((e,t,i)=>{var r=[];for(let n=0;n<=t;n+=e)for(let e=-1;e<=i;e+=2)r.push({J:1e3*n,$j:e});return r})(e,n,t)},a),f=(e,n)=>n(e),a=(e,n)=>f(e.split(","),e=>e[n.G(0,e.length-1)]);return(t,e,i)=>{var n;return{$P:r(n=t,e,[g("000,1B1212,301934",20),g("4169E1,1E90FF,0437F2,1F51FF,0096FF,008080",4),g("228B22,006400,008000",4),g("DC143C,B22222,E30B5C,C21E56,E0115F,FF2400,FF3131,D2042D",4),g("4B0082,663399,8B008B,5D3FD3",3),g("FF7518,FF5F15,FFA500,E49B0F,DA70D6,4CBB17,40B5AD",4),g("2F4F4F,483248,51414F,36454F,483C32",2)]).map(e=>a(e,n)).map((e,n)=>({...((e,n)=>{var{G:t,K:i,S:r}=e,a=t(t(t(2,7),7),10),o=2**a,s=t(1,k(o,5)),l=i(1,2)?15*t(1,3)*1e3:0,d=i(3,10)?2e3*t(1,t(1,12)):0,a=a<=7&&i(2,10)?7e3*t(1,7):0,u=(e,n,t)=>(n+e)*t,F=(e,n,t)=>e+n*t,c=(e,n)=>e,m=(e,n)=>0,F=h(e,[x(15,180,1,u,m,3),x(15,180,1,F,m,3),x(15,360,-1,u,m,1),x(15,360,-1,F,m,1),x(90,180,1,u,c,1),x(90,180,1,F,c,1),x(90,360,-1,u,c,2),x(1,0,-1,u,m,3)]),c={$U:n,$i:s,$h:o,$u:l,$I:d,$E:a,$8:0==a&&i(1,4)?{$A:h(e,[g(f(t(1,t(7,12)),t=>(e,n)=>n%t==0),3),g(f(t(2,12),t=>(e,n)=>e.K(1,t)),1)]),J:h(e,[g(f(15*t(2,6)*1e3,t=>(e,n)=>t*e.S()),1),g(f(15*t(2,10)*1e3,t=>(e,n)=>t*(n.$r*=-1)),2),g(f(15*t(2,4)*1e3*r(),t=>(e,n)=>t),2)])}:{$A:()=>!1},$3:F},u=1==F.$B.length?7:8,m=v(t(u,t(u,2+u))/20*n);return{N:7e4,$d:7500,U:c,V:m,$_:h(e,[g((e,n)=>n.G(-1,n.G(-1,10))/10,2),g((e,n)=>n.G(0,15)/5,2),g((e,n)=>e.$F()%5/2,3),g((e,n)=>k(1.5,(e.N()/7e4)**2*10),6),g((e,n)=>0==e.$F()||0==e.$L()?0:p(e.$v(),e.$K())/875,4)]),$1:{$n:t(0,5),$D:1e3*t(45,360)},$X:t(0,1)*t(1,4)*3*m}})(t,i),$4:e,id:n+1+"-"+e})),$O:{$C:a("F0FFF0,F0F8FF,F5F5F5,F8F8FF,FFFFF0,FFFAF0,FFFAFA,FFF8DC,FFEFD5,FFF5EE,FAF0E6,F0FFFF,FFF0F5,E6E6FA,EADDCA,ECFFDC,F5F5DC",e=t),$S:e.G(5,16),$R:e.G(5,8)/4,$Q:500*e.G(2,6)}}}},I=({$T:d},p)=>{var g=(e,n,t,i)=>{var r,a,o=e.$K(),s=n.J(o);for({J:r,$j:a}of i.$3.$B){var l=s+i.$3.$N(t,r,a),l=d(o,l,i.$U);if(e.$J(l))return{X:l,J:i.$3.$s(r,a)}}return!1},h=(e,n,t,i)=>{var r=0==e.$I?0:n.G(0,e.$I),i=e.$8.$A(n,t)?e.$8.J(n,i):0,t=0==e.$E?0:(5<=t%10?-1:1)*n.G(0,e.$E);return x(-1e5,k(1e5,r+i+t))};return{$t:(e,n,t,i,r)=>{for(var a=p(n,e.U.$i,e.U.$h,e.N,e.$d,e.V,r),o={$r:-1};!a.$Z();){m=c=void 0;var s=e,l=a,d=t,u=i,F=o,c=(l.$k(),l.$m(u));if(l.$J(c)){l.$G(c);let e=u.G(0,s.U.$u);for(;!l.$l();){e+=h(s.U,u,l.$L(),F);var m=g(l,d,e,s.U);if(!m)break;l.$G(m.X),e+=m.J}}l.$a(s.$_(l,u)*s.V)}return a}}};var e=({tokenId:e,hash:n})=>{var t,i=A,r=$,a=B(r),{$b:o,$V:s}=M,l=H(r),d=W(r),u=I(r,l),l=T(r),F=r.$6(0,0,7500,1e4),c=r.$6(500,500,7e3,9500),m=i.$p(n),{$P:p,$O:g}=l(m,5,18),h=d.$H(150);for(t of p)t.$=0,t.j=[];for(let e=1;e<=15;e++){var x=p.slice().sort((e,n)=>e.$-n.$)[0];let n,t;for(let e=0;e<20;e++){var f=d.$H(150),v=d.$o(f,h),k=a(F,m,x.$1.$n,.1*x.$1.$D,x.$1.$D),k=u.$t(x,c,k,i.$g(m.G(1,2e6)),v),v=k.N();if((!n||v>n.N())&&(n=k,t=f,1e3<v))break}300<n.N()&&(x.j.push({n:e,$q:n}),x.$+=n.N(),h.$W(t,x.$X))}var P=`piece_${e%1e6}_`,y=(e,n,...t)=>o(e,{id:P+n},...t),D=(e,...n)=>o("use",{href:"#"+P+e},...n),r=e=>`url(#${P}${e})`,w=e=>({stroke:"#"+e,"stroke-linecap":"round",fill:"none"}),b=e=>({"stroke-width":e}),C=(e,n)=>({d:[...L(e).keys()].map(n).join(" ")}),n=(e,n)=>o("path",w((E(g.$C,16)-e*g.$S).toString(16)),b(g.$R),C(n,()=>`M ${m.G(1,99)} ${m.G(1,99)} l 0 0`));return s(o("svg",{xmlns:"http://www.w3.org/2000/svg","xmlns:inkscape":"http://www.inkscape.org/namespaces/inkscape",viewBox:`${F.R} ${F.O} ${F.w} `+F.h,width:"100vw",height:"100vh"},[o("defs",[y("rect","frame",{x:F.R,y:F.O,width:F.w,height:F.h}),y("marker","dots",{viewBox:"0 0 100 100",refX:50,refY:50,markerWidth:100,markerHeight:100,orient:"auto"},[n(65793,160),n(131586,80)]),y("path","back",C(g.$Q,e=>`${0<e?"L":"M"} ${m.G(F.R,F.z)} `+m.G(F.O,F.q))),y("clipPath","clip",[D("frame")])]),D("frame",{stroke:"none",fill:"#"+g.$C},[o("title",["Scribbled Daydreams #"+e%1e6])]),D("back",w("none"),b(10),{"marker-mid":r("dots"),"clip-path":r("clip")}),...p.map(e=>y("g",e.id,{"inkscape:groupmode":"layer","inkscape:label":e.id},w(e.$4),b(15),e.j.map(e=>y("path",e.n,{d:e.$q.$Y()})))),...p.map(n=>n.j.map(e=>D(e.n,w(n.$4),b(21),{"stroke-opacity":"50%"}))).flat()]))},o=document.createElement("template");o.innerHTML=e(tokenData),document.body.append(o.content.firstChild)})();
You're sitting with pen in hand, intent on paying attention and taking notes. However, your mind quickly drifts off to other thoughts, and your hand decides to take charge and start drawing. After some time you look down to see what these unsupervised doodles have curiously grown into. This piece takes inspiration from the beautiful artworks we've all unconsciously created. Recommended to plot on 9"x12" paper using 0.45mm or 0.5mm pens. Feel free to try different pen and paper combinations!
(i+r)/e,u=n-t;return I.map(s,0,1,t+o*u,t+c*u)}}r.forEach((function(r){const s=r.length();l?(o.push(r.scale(x(t,e,a,h,s))),u.push(r.scale(x(-n,-i,a,h,s)))):(o.push(r.scale(t)),u.push(r.scale(-n))),h+=s})),u=u.map((function(t){return c=t.points,c[3]?t.points=[c[3],c[2],c[1],c[0]]:t.points=[c[2],c[1],c[0]],t})).reverse();const f=o[0].points[0],y=o[s-1].points[o[s-1].points.length-1],p=u[s-1].points[u[s-1].points.length-1],d=u[0].points[0],m=I.makeline(p,f),g=I.makeline(y,d),b=[m].concat(o).concat([g]).concat(u);return new O(b)}outlineshapes(t,n,e){n=n||t;const i=this.outline(t,n).curves,r=[];for(let t=1,n=i.length;t<n/2;t++){const s=I.makeshape(i[t],i[n-t],e);s.startcap.virtual=t>1,s.endcap.virtual=t<n/2-1,r.push(s)}return r}intersects(t,n){return t?t.p1&&t.p2?this.lineIntersects(t):(t instanceof q&&(t=t.reduce()),this.curveintersects(this.reduce(),t,n)):this.selfintersects(n)}lineIntersects(t){const n=j(t.p1.x,t.p2.x),e=j(t.p1.y,t.p2.y),i=T(t.p1.x,t.p2.x),r=T(t.p1.y,t.p2.y);return I.roots(this.points,t).filter((t=>{var s=this.get(t);return I.between(s.x,n,i)&&I.between(s.y,e,r)}))}selfintersects(t){const n=this.reduce(),e=n.length-2,i=[];for(let r,s,o,c=0;c<e;c++)s=n.slice(c,c+1),o=n.slice(c+2),r=this.curveintersects(s,o,t),i.push(...r);return i}curveintersects(t,n,e){const i=[];t.forEach((function(t){n.forEach((function(n){t.overlaps(n)&&i.push({left:t,right:n})}))}));let r=[];return i.forEach((function(t){const n=I.pairiteration(t.left,t.right,e);n.length>0&&(r=r.concat(n))})),r}arcs(t){return t=t||.5,this._iterate(t,[])}_error(t,n,e,i){const r=(i-e)/4,s=this.get(e+r),o=this.get(i-r),c=I.dist(t,n),u=I.dist(t,s),h=I.dist(t,o);return C(u-c)+C(h-c)}_iterate(t,n){let e,i=0,r=1;do{e=0,r=1;let s,o,c,u,h,a=this.get(i),l=!1,x=!1,f=r,y=1,p=0;do{if(x=l,u=c,f=(i+r)/2,p++,s=this.get(f),o=this.get(r),c=I.getccenter(a,s,o),c.interval={start:i,end:r},l=this._error(c,a,i,r)<=t,h=x&&!l,h||(y=r),l){if(r>=1){if(c.interval.end=y=1,u=c,r>1){let t={x:c.x+c.r*$(c.e),y:c.y+c.r*B(c.e)};c.e+=I.angle({x:c.x,y:c.y},t,this.get(1))}break}r+=(r-i)/2}else r=f}while(!h&&e++<100);if(e>=100)break;u=u||c,n.push(u),i=y}while(r<1);return n}}function L(t,n){var e=n%t.points.length;return e<0&&(e=t.points.length+e),t.points[e]}function U(t,n){const e=[];return function(t,n){for(var e=0;e<t.points.length&&!1!==n.call(t,L(t,e-1),L(t,e),L(t,e+1),e);e++);}({points:t.points.reverse()},(function(t,i,r,s){const o=i.subtract(t,!0).normalize(),c=i.subtract(r,!0).normalize();let u=Math.sin(Math.acos(o.dot(c))/2);u=0==u?1:u;var h=n/u,a=o.add(c,!0).normalize().multiply(h,!0),l=o.perpDot(c)<0?i.add(a,!0):i.subtract(a,!0);e.push(l)})),{points:e}}const R=q.getUtils();q.prototype.bboxIntersections=function(t,n){const e=[{p1:{x:t.x.min,y:t.y.min},p2:{x:t.x.max,y:t.y.min}},{p1:{x:t.x.max,y:t.y.min},p2:{x:t.x.max,y:t.y.max}},{p1:{x:t.x.max,y:t.y.max},p2:{x:t.x.min,y:t.y.max}},{p1:{x:t.x.min,y:t.y.max},p2:{x:t.x.min,y:t.y.min}}].map((t=>this.lineIntersects(t))).reduce(((t,n)=>t.concat(n)),[]);return e.sort(),e},q.prototype.vec2=function(){return this.points.map((t=>new(a())(t.x,t.y)))};class V{constructor(t){if(t instanceof Array){const n=t[0],e=t[1];this.x={min:n.x,mid:(e.x-n.x)/2,max:e.x,size:e.x-n.x},this.y={min:n.y,mid:(e.y-n.y)/2,max:e.y,size:e.y-n.y}}else this.x=t.x,this.y=t.y,this.z=t.z}inside(t){return t.x>=this.x.min&&t.x<=this.x.max&&t.y>=this.y.min&&t.y<=this.y.max}}class J extends Array{constructor(){super(...arguments),this.addBezier=this.push}bbox(){let t=this[0].bbox();for(let n=1;n<this.length;n++){const e=this[n].bbox();R.expandbox(t,e)}return t}scale(t){const n=this.bbox(),e=((t,n)=>e=>e.subtract(n,!0).multiply(t).add(n))(t,new(a())(n.x.mid,n.y.mid)),i=this.map((t=>{const n=t.vec2().map(e);return new q(n)}));this.update(i)}draw(t){const n=this,e=x(t);for(let t=0;t<n.length;t++)y(e,n[t].toSVG());return e}update(t){this.splice(0,this.length,...t)}crop(t,n){const e=this,i=[];for(let r=e.length-1;r>=0;r--){const s=e[r],o=s.bboxIntersections(t,n);o.splice(0,0,0),o.push(1),o.forEach(((n,e)=>{if(e<o.length-1){const r=o[e+1],c=(n+r)/2,u=s.get(c);if(t.inside(u)){const t=s.split(n,r);i.push(t)}}}))}this.update(i)}}const G=[[13,93,43,10,50,10,80,93],[26,55,67,55]],W=[[21,92,21,8,52,8,65,12,70,20,70,33,60,49,25,49,60,49,70,55,73,60,73,84,68,90,58,92,21,92]],X=[[74,18,74,85,60,93,12,93,12,10,60,10,74,18]],H=[[75,92,25,92,25,8,75,8],[66,56,25,56]],Q=[[57,50,82,50,82,86,70,93,40,93,27,86,27,18,40,10,70,10,82,18]],K=[[45,90,45,10,42,10]],Y=[[64,93,19,93,19,9]],Z=[[8,88,8,10,73,88,73,64,73,10]],tt=[[13,93,13,10,50,10,61,18,61,55,47,63,20,63]],nt=[[71,18,57,12,30,12,23,24,23,42,27,50,62,55,71,67,68,86,57,92,35,92,23,86]],et=[[45,14,45,93],[11,10,73,10]],it=[[74,10,74,85,60,93,23,93,12,85,12,10]],rt=[[39,23,34,70],[11,39,49,37],[50,52,11,54],[19,70,23,24]],st=[[70,13,17,90]],ot=[[42,93,47,93]],ct=[[[9,79,15,88,28,88,42,88,47,79,47,18,44,9,28,9,14,9,10,17,9,79]],[[25,27,45,12,45,88]],[[49,88,5,88,5,65,13,57,26,53,35,51,39,50,46,40,46,14,40,7,27,4,11,7,5,14,4,19]],[[5,78,11,84,25,86,40,85,46,78,47,57,40,45,20,45,46,8,5,8]],[[27,9,11,61,52,60],[42,21,42,90]],[[9,79,15,85,29,88,44,85,50,79,49,53,45,46,28,44,18,45,11,52,12,11,51,11]],[[15,56,32,47,44,49,52,58,49,79,34,87,21,86,13,77,10,53,15,33,28,20,48,11]],[[23,90,51,9,7,10]],[[12,37,15,42,31,45,46,42,50,36,50,18,45,12,31,10,17,12,12,17,12,37],[10,79,16,85,31,88,45,86,52,79,51,54,47,48,31,45,15,48,10,54,10,79]],[[37,88,41,80,45,69,50,46,51,20,45,14,31,12,17,14,12,19,11,39,17,49,31,52,43,50,48,45]]];function ut(t,n,e,i,r=i/111){n.forEach(((n,s)=>{let o=n.map((t=>t*i/100)).map(((t,n)=>n%2==0?t+e.x:t+e.y)).map((t=>u(t,r)));!function(t,n,e){const i=document.createElementNS(l,"path");f(i,{d:`M ${n.slice(0,2).join(" ")} L ${n.slice(2).join(" ")}`}),f(i,void 0),t.appendChild(i)}(t,o)}))}const ht=(t,n,e=n)=>{const i=u(t.x,n),r=u(t.y,e);return new(a())(i,r)};!function(t){r=!1;let i=function(t){let n=parseInt(t.substring(0,8),16),e=parseInt(t.substring(8,16),16),i=parseInt(t.substring(16,24),16),r=parseInt(t.substring(24,32),16);return()=>{n|=0,e|=0,i|=0,r|=0;let t=(n+e|0)+r|0;return r=r+1|0,n=e^e>>>9,e=i+(i<<3)|0,i=i<<21|i>>>11,i=i+t|0,(t>>>0)/4294967296}};n=i(t.hash.substring(2,34)),e=i(t.hash.substring(34,66));for(let t=0;t<1e6;t+=2)n(),e()}(tokenData),console.log(`token.id: ${tokenData.tokenId}`),console.log(`token.hash: ${tokenData.hash}`);const at=2*Math.PI,lt=11/14;let xt={dx:550,dy:Math.ceil(700),ar:lt};const ft=xt.dx,yt=xt.dy,pt=.0025*ft,dt=[{n:"blue",c:"#5C7799",prob:.4},{n:"grey",c:"#696974",prob:.4},{n:"tan",c:"#E8E0C4",prob:.2}];var mt;function gt(t,n,e){if(!tokenData.plot){const i=.8*Math.pow(n/e,1),r=Math.min(1,i+.3),s="4s",o={attributeName:"stroke-width",values:`1;60;60;${pt};${pt}`,keyTimes:`0;${i};${i};${r};1`,calcMode:"linear",dur:s};p(t,{attributeName:"opacity",values:"0;0;0.4;1",keyTimes:`0;${i};${i};1`,calcMode:"linear",dur:s}),p(t,o)}}function bt(t,n){const e=new J;for(let i=0;i<t.points.length;i++){const r=t.points[i],s=t.points[(i+1)%t.points.length],o=t.points[(i+2)%t.points.length],c=r.subtract(s,!0).normalize(),u=o.subtract(s,!0).normalize(),h=(c.add(u,!0).normalize(),c.angleTo(u)),a=Math.min(r.distance(s),o.distance(s))/2*Math.abs(Math.sin(h/2)),l=Math.min(n,a),x=Math.abs(l/Math.sin(h/2)),f=s.add(c.multiply(x,!0),!0),y=s.add(u.multiply(x,!0),!0),p=.5523,d=f.subtract(c.multiply(2*l*p,!0),!0),m=y.subtract(u.multiply(2*l*p,!0),!0),g=new q(f,d,m,y);e.addBezier(g)}const i=new J,r=e;for(let t=0;t<r.length;t++){const n=r[t],e=r[(t+1)%r.length];i.addBezier(n);const c=n.point(3),u=e.point(0);if(o=u,(s=c).x.toFixed(5)!=o.x.toFixed(5)||s.y.toFixed(5)!=o.y.toFixed(5)){const t=new q(c,c,u,u);i.addBezier(t)}}var s,o;return i}mt=()=>{console.log("drawing..."),function(){let t="11in",n="14in";if(!tokenData.plot){let e=function(){let t=window.innerWidth,n=window.innerHeight;const e=lt;return{dx:n*e>=t?t:Math.ceil(n*e),dy:t/e>=n?n:Math.ceil(t/e),ar:e}}();console.log("using window dimensions",e),t="100vw",n="100vh"}const e=function(){const t=document.createElementNS(l,"svg");return f(t,{xmlns:"http://www.w3.org/2000/svg",version:"1.1","xmlns:xlink":"http://www.w3.org/1999/xlink"}),t}();f(e,{width:t,height:n,viewBox:`0 0 ${ft+0} ${yt+0}`});const i=(t=>{const n=t.reduce(((t,n)=>t+n.prob),0),e=[];let i=0;for(let n=0;n<t.length;n++)i+=t[n].prob,e.push(i);const r=s(0,n);let o=e.findIndex((c=r,t=>c<=t));var c;return-1==o&&(o=t.length-1),t[o]})(dt);console.log("paper",i.n);const r=x(e);f(r,{id:`0 paper ${i.n}`,fill:i.c,"stroke-width":1,stroke:"none"});const h=x(e);f(h,{id:"1 black",fill:"none","stroke-width":pt,"stroke-linecap":"round",stroke:"black"});const y=x(e);f(y,{id:"2 white",fill:"none","stroke-width":pt,"stroke-linecap":"round",stroke:"white"});const p=x(e);f(p,{id:"3 title",fill:"none","stroke-width":.5,"stroke-linecap":"round","stroke-linejoin":"round",stroke:"darkgrey"});const d=x(e);f(d,{id:"4 titleFR",fill:"none","stroke-width":.5,"stroke-linecap":"round","stroke-linejoin":"round",stroke:"none"});const m=new V({x:{min:0,mid:ft/2,max:ft,size:ft},y:{min:0,mid:yt/2,max:yt,size:yt}}),g=.0682*ft,b=new(a())(g,g),v=new(a())(ft-g,yt-g),z=new V([b,v]);!function(t,n,e,i){const r=document.createElementNS(l,"rect");f(r,{width:n,height:e}),f(r,i),t.appendChild(r)}(r,ft,yt,{"stroke-width":0,fill:i.c});const w=ft*yt,_=s(.1*ft,.9*ft),k=s(.1*yt,.9*yt),E=new(a())(_,k),M=s(.3*ft),S=function(){const t=Math.floor(u(4.4,3)),n=o(3,6),e=o(3,9);let i=t;return t<3?i=n:t>=9&&(i=e),i}();console.log("summits",S);const N=function(t,n,e){const i=[];let r=0;const s=at/e;for(let o=0;o<e;o++){let e=u(r,.2*s);const o=t.x+Math.cos(e)*n,c=t.y+Math.sin(e)*n,h=ht(new(a())(o,c),.1*n);i.push(h),r+=s}return{points:i}}(E,M,S),A=(bt(N,2e-4*function(t){let n=0;const e=t.points[0];return t.points.forEach(((t,i,r)=>{if(i<2)return;const s=e.subtract(t,!0),o=r[i-1],c=e.subtract(o,!0);n+=s.x*c.y-s.y*c.x})),n/2}(N)),s()*s());console.log("chunkiness",Math.round(100*A));const I=2e-5*w;let O=N;const C=o(21,33);console.log(`eggs: ${C} `);for(let t=1;t<=C;t++)try{const n=I+t*t*s(1.1,1.7)*S/3;let e=N;c(A)&&(e=O);const i=U(e,n);O=i;const r=n*n*2,o=bt(i,r);if(c(.9)?(o.crop(z),gt(o.draw(h),t,C)):(o.crop(m),gt(o.draw(y),t,C)),c(.3))try{const n=bt(U(i,5),r);n.scale(.08),n.crop(m),gt(n.draw(y),t,C)}catch(v){console.log("oops",v)}}catch(v){console.log("oops",v)}if(tokenData.plot){const t=tokenData.tokenId.substring(tokenData.tokenId.length-4),n=new(a())(g,yt-.37*g),e="0000"==t?"0":t.replace(/^0+/,"");console.log("editionNumber",e),function(t,n,e,i){let r=[W,H,Q,K,Z,Z,K,Z,Q,nt,,G,st,tt];if("A/P"!=n){r=[W,H,Q,K,Z,Z,K,Z,Q,nt,,rt];for(let t=0;t<n.length;t++){const e=n[t],i=parseInt(e,10),s=ct[i];r.push(s)}}for(let n=0;n<2;n++){const i=0,s=.85*9;r.forEach(((r,o)=>{const c=e.x+s*o,u=e.y-9-i,h=new(a())(c,u);ut(t,r,h,9,9*n*.02)}))}}(p,e,n),function(t,n,e,i){let r=[Y,H,nt,,X,H,W,it,et,nt,,H,ot,G,ot];if("A/P"!=n){r=[Y,H,nt,,X,H,W,it,et,nt,rt];for(let t=0;t<n.length;t++){const e=n[t],i=parseInt(e,10),s=ct[i];r.push(s)}}for(let n=0;n<2;n++){const i=0,s=.85*9;r.forEach(((r,o)=>{const c=e.x+s*o,u=e.y-9-i,h=new(a())(c,u);ut(t,r,h,9,9*n*.02)}))}}(d,e,n)}document.body.appendChild(e)}()},"complete"===document.readyState||"interactive"===document.readyState?mt():document.addEventListener("DOMContentLoaded",(t=>{mt()}))})()})();
(()=>{var n={490:t=>{!function n(e,i,r){var s=function(t){return"[object Array]"===Object.prototype.toString.call(t)};function o(t,n){if(!(this instanceof o))return new o(t,n);s(t)?(n=t[1],t=t[0]):"object"==typeof t&&t&&(n=t.y,t=t.x),this.x=o.clean(t||0),this.y=o.clean(n||0)}o.prototype={change:function(t){if("function"==typeof t)this.observers?this.observers.push(t):this.observers=[t];else if(this.observers&&this.observers.length)for(var n=this.observers.length-1;n>=0;n--)this.observers[n](this,t);return this},ignore:function(t){if(this.observers)if(t)for(var n=this.observers,e=n.length;e--;)n[e]===t&&n.splice(e,1);else this.observers=[];return this},set:function(t,n,e){if("number"!=typeof t&&(e=n,n=t.y,t=t.x),this.x===t&&this.y===n)return this;var i=null;return!1!==e&&this.observers&&this.observers.length&&(i=this.clone()),this.x=o.clean(t),this.y=o.clean(n),!1!==e?this.change(i):void 0},zero:function(){return this.set(0,0)},clone:function(){return new this.constructor(this.x,this.y)},negate:function(t){return t?new this.constructor(-this.x,-this.y):this.set(-this.x,-this.y)},add:function(t,n,e){return"number"!=typeof t&&(e=n,s(t)?(n=t[1],t=t[0]):(n=t.y,t=t.x)),t+=this.x,n+=this.y,e?new this.constructor(t,n):this.set(t,n)},subtract:function(t,n,e){return"number"!=typeof t&&(e=n,s(t)?(n=t[1],t=t[0]):(n=t.y,t=t.x)),t=this.x-t,n=this.y-n,e?new this.constructor(t,n):this.set(t,n)},multiply:function(t,n,e){return"number"!=typeof t?(e=n,s(t)?(n=t[1],t=t[0]):(n=t.y,t=t.x)):"number"!=typeof n&&(e=n,n=t),t*=this.x,n*=this.y,e?new this.constructor(t,n):this.set(t,n)},rotate:function(t,n,e){var i,r,s=this.x,o=this.y,c=Math.cos(t),u=Math.sin(t);return i=c*s-(n=n?-1:1)*u*o,r=n*u*s+c*o,e?new this.constructor(i,r):this.set(i,r)},length:function(){var t=this.x,n=this.y;return Math.sqrt(t*t+n*n)},lengthSquared:function(){var t=this.x,n=this.y;return t*t+n*n},distance:function(t){var n=this.x-t.x,e=this.y-t.y;return Math.sqrt(n*n+e*e)},nearest:function(t){for(var n,e=Number.MAX_VALUE,i=null,r=t.length-1;r>=0;r--)(n=this.distance(t[r]))<=e&&(e=n,i=t[r]);return i},normalize:function(t){var n=this.length(),e=n<Number.MIN_VALUE?0:1/n;return t?new this.constructor(this.x*e,this.y*e):this.set(this.x*e,this.y*e)},equal:function(t,n){return"number"!=typeof t&&(s(t)?(n=t[1],t=t[0]):(n=t.y,t=t.x)),o.clean(t)===this.x&&o.clean(n)===this.y},abs:function(t){var n=Math.abs(this.x),e=Math.abs(this.y);return t?new this.constructor(n,e):this.set(n,e)},min:function(t,n){var e=this.x,i=this.y,r=t.x,s=t.y,o=e<r?e:r,c=i<s?i:s;return n?new this.constructor(o,c):this.set(o,c)},max:function(t,n){var e=this.x,i=this.y,r=t.x,s=t.y,o=e>r?e:r,c=i>s?i:s;return n?new this.constructor(o,c):this.set(o,c)},clamp:function(t,n,e){var i=this.min(n,!0).max(t);return e?i:this.set(i.x,i.y)},lerp:function(t,n,e){return this.add(t.subtract(this,!0).multiply(n),e)},skew:function(t){return t?new this.constructor(-this.y,this.x):this.set(-this.y,this.x)},dot:function(t){return o.clean(this.x*t.x+t.y*this.y)},perpDot:function(t){return o.clean(this.x*t.y-this.y*t.x)},angleTo:function(t){return Math.atan2(this.perpDot(t),this.dot(t))},divide:function(t,n,e){if("number"!=typeof t?(e=n,s(t)?(n=t[1],t=t[0]):(n=t.y,t=t.x)):"number"!=typeof n&&(e=n,n=t),0===t||0===n)throw new Error("division by zero");if(isNaN(t)||isNaN(n))throw new Error("NaN detected");return e?new this.constructor(this.x/t,this.y/n):this.set(this.x/t,this.y/n)},isPointOnLine:function(t,n){return(t.y-this.y)*(t.x-n.x)==(t.y-n.y)*(t.x-this.x)},toArray:function(){return[this.x,this.y]},fromArray:function(t){return this.set(t[0],t[1])},toJSON:function(){return{x:this.x,y:this.y}},toString:function(){return"("+this.x+", "+this.y+")"},constructor:o},o.fromArray=function(t,n){return new(n||o)(t[0],t[1])},o.precision=i||8;var c=Math.pow(10,o.precision);return o.clean=e||function(t){if(isNaN(t))throw new Error("NaN detected");if(!isFinite(t))throw new Error("Infinity detected");return Math.round(t)===t?t:Math.round(t*c)/c},o.inject=n,e||(o.fast=n((function(t){return t})),"object"==typeof t.exports?t.exports=o:window.Vec2=window.Vec2||o),o}()}},e={};function i(t){var r=e[t];if(void 0!==r)return r.exports;var s=e[t]={exports:{}};return n[t](s,s.exports,i),s.exports}i.n=t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return i.d(n,{a:n}),n},i.d=(t,n)=>{for(var e in n)i.o(n,e)&&!i.o(t,e)&&Object.defineProperty(t,e,{enumerable:!0,get:n[e]})},i.o=(t,n)=>Object.prototype.hasOwnProperty.call(t,n),(()=>{"use strict";let n,e,r=!1;function s(t=0,i=1){return t+(i-t)*(r=!r,r?n():e())}function o(t,n){return Math.floor(s(t,n+1))}function c(t=.5){return s()<t}const u=(t=0,n=1)=>{const e=1-s(),i=s();return t+Math.sqrt(-2*Math.log(e))*Math.cos(2*Math.PI*i)*n};var h=i(490),a=i.n(h);const l="http://www.w3.org/2000/svg";function x(t){const n=document.createElementNS(l,"g");return t.appendChild(n),n}function f(t,n){for(let e in n)n.hasOwnProperty(e)&&t.setAttribute(e,n[e])}function y(t,n,e){const i=document.createElementNS(l,"path");return f(i,{d:n}),f(i,e),t.appendChild(i),i}function p(t,n){const e=document.createElementNS(l,"animate");f(e,n),t.appendChild(e)}const{abs:d,cos:m,sin:g,acos:b,atan2:v,sqrt:z,pow:w}=Math;function _(t){return t<0?-w(-t,1/3):w(t,1/3)}const k=Math.PI,E=2*k,M=k/2,S=Number.MAX_SAFE_INTEGER||9007199254740991,N=Number.MIN_SAFE_INTEGER||-9007199254740991,A={x:0,y:0,z:0},I={Tvalues:[-.06405689286260563,.06405689286260563,-.1911188674736163,.1911188674736163,-.3150426796961634,.3150426796961634,-.4337935076260451,.4337935076260451,-.5454214713888396,.5454214713888396,-.6480936519369755,.6480936519369755,-.7401241915785544,.7401241915785544,-.820001985973903,.820001985973903,-.8864155270044011,.8864155270044011,-.9382745520027328,.9382745520027328,-.9747285559713095,.9747285559713095,-.9951872199970213,.9951872199970213],Cvalues:[.12793819534675216,.12793819534675216,.1258374563468283,.1258374563468283,.12167047292780339,.12167047292780339,.1155056680537256,.1155056680537256,.10744427011596563,.10744427011596563,.09761865210411388,.09761865210411388,.08619016153195327,.08619016153195327,.0733464814110803,.0733464814110803,.05929858491543678,.05929858491543678,.04427743881741981,.04427743881741981,.028531388628933663,.028531388628933663,.0123412297999872,.0123412297999872],arcfn:function(t,n){const e=n(t);let i=e.x*e.x+e.y*e.y;return void 0!==e.z&&(i+=e.z*e.z),z(i)},compute:function(t,n,e){if(0===t)return n[0].t=0,n[0];const i=n.length-1;if(1===t)return n[i].t=1,n[i];const r=1-t;let s=n;if(0===i)return n[0].t=t,n[0];if(1===i){const n={x:r*s[0].x+t*s[1].x,y:r*s[0].y+t*s[1].y,t};return e&&(n.z=r*s[0].z+t*s[1].z),n}if(i<4){let n,o,c,u=r*r,h=t*t,a=0;2===i?(s=[s[0],s[1],s[2],A],n=u,o=r*t*2,c=h):3===i&&(n=u*r,o=u*t*3,c=r*h*3,a=t*h);const l={x:n*s[0].x+o*s[1].x+c*s[2].x+a*s[3].x,y:n*s[0].y+o*s[1].y+c*s[2].y+a*s[3].y,t};return e&&(l.z=n*s[0].z+o*s[1].z+c*s[2].z+a*s[3].z),l}const o=JSON.parse(JSON.stringify(n));for(;o.length>1;){for(let n=0;n<o.length-1;n++)o[n]={x:o[n].x+(o[n+1].x-o[n].x)*t,y:o[n].y+(o[n+1].y-o[n].y)*t},void 0!==o[n].z&&(o[n]=o[n].z+(o[n+1].z-o[n].z)*t);o.splice(o.length-1,1)}return o[0].t=t,o[0]},computeWithRatios:function(t,n,e,i){const r=1-t,s=e,o=n;let c,u=s[0],h=s[1],a=s[2],l=s[3];return u*=r,h*=t,2===o.length?(c=u+h,{x:(u*o[0].x+h*o[1].x)/c,y:(u*o[0].y+h*o[1].y)/c,z:!!i&&(u*o[0].z+h*o[1].z)/c,t}):(u*=r,h*=2*r,a*=t*t,3===o.length?(c=u+h+a,{x:(u*o[0].x+h*o[1].x+a*o[2].x)/c,y:(u*o[0].y+h*o[1].y+a*o[2].y)/c,z:!!i&&(u*o[0].z+h*o[1].z+a*o[2].z)/c,t}):(u*=r,h*=1.5*r,a*=3*r,l*=t*t*t,4===o.length?(c=u+h+a+l,{x:(u*o[0].x+h*o[1].x+a*o[2].x+l*o[3].x)/c,y:(u*o[0].y+h*o[1].y+a*o[2].y+l*o[3].y)/c,z:!!i&&(u*o[0].z+h*o[1].z+a*o[2].z+l*o[3].z)/c,t}):void 0))},derive:function(t,n){const e=[];for(let i=t,r=i.length,s=r-1;r>1;r--,s--){const t=[];for(let e,r=0;r<s;r++)e={x:s*(i[r+1].x-i[r].x),y:s*(i[r+1].y-i[r].y)},n&&(e.z=s*(i[r+1].z-i[r].z)),t.push(e);e.push(t),i=t}return e},between:function(t,n,e){return n<=t&&t<=e||I.approximately(t,n)||I.approximately(t,e)},approximately:function(t,n,e){return d(t-n)<=(e||1e-6)},length:function(t){const n=I.Tvalues.length;let e=0;for(let i,r=0;r<n;r++)i=.5*I.Tvalues[r]+.5,e+=I.Cvalues[r]*I.arcfn(i,t);return.5*e},map:function(t,n,e,i,r){return i+(t-n)/(e-n)*(r-i)},lerp:function(t,n,e){const i={x:n.x+t*(e.x-n.x),y:n.y+t*(e.y-n.y)};return void 0!==n.z&&void 0!==e.z&&(i.z=n.z+t*(e.z-n.z)),i},pointToString:function(t){let n=t.x+"/"+t.y;return void 0!==t.z&&(n+="/"+t.z),n},pointsToString:function(t){return"["+t.map(I.pointToString).join(", ")+"]"},copy:function(t){return JSON.parse(JSON.stringify(t))},angle:function(t,n,e){const i=n.x-t.x,r=n.y-t.y,s=e.x-t.x,o=e.y-t.y;return v(i*o-r*s,i*s+r*o)},round:function(t,n){const e=""+t,i=e.indexOf(".");return parseFloat(e.substring(0,i+1+n))},dist:function(t,n){const e=t.x-n.x,i=t.y-n.y;return z(e*e+i*i)},closest:function(t,n){let e,i,r=w(2,63);return t.forEach((function(t,s){i=I.dist(n,t),i<r&&(r=i,e=s)})),{mdist:r,mpos:e}},abcratio:function(t,n){if(2!==n&&3!==n)return!1;if(void 0===t)t=.5;else if(0===t||1===t)return t;const e=w(t,n)+w(1-t,n);return d((e-1)/e)},projectionratio:function(t,n){if(2!==n&&3!==n)return!1;if(void 0===t)t=.5;else if(0===t||1===t)return t;const e=w(1-t,n);return e/(w(t,n)+e)},lli8:function(t,n,e,i,r,s,o,c){const u=(t-e)*(s-c)-(n-i)*(r-o);return 0!=u&&{x:((t*i-n*e)*(r-o)-(t-e)*(r*c-s*o))/u,y:((t*i-n*e)*(s-c)-(n-i)*(r*c-s*o))/u}},lli4:function(t,n,e,i){const r=t.x,s=t.y,o=n.x,c=n.y,u=e.x,h=e.y,a=i.x,l=i.y;return I.lli8(r,s,o,c,u,h,a,l)},lli:function(t,n){return I.lli4(t,t.c,n,n.c)},makeline:function(t,n){return new q(t.x,t.y,(t.x+n.x)/2,(t.y+n.y)/2,n.x,n.y)},findbbox:function(t){let n=S,e=S,i=N,r=N;return t.forEach((function(t){const s=t.bbox();n>s.x.min&&(n=s.x.min),e>s.y.min&&(e=s.y.min),i<s.x.max&&(i=s.x.max),r<s.y.max&&(r=s.y.max)})),{x:{min:n,mid:(n+i)/2,max:i,size:i-n},y:{min:e,mid:(e+r)/2,max:r,size:r-e}}},shapeintersections:function(t,n,e,i,r){if(!I.bboxoverlap(n,i))return[];const s=[],o=[t.startcap,t.forward,t.back,t.endcap],c=[e.startcap,e.forward,e.back,e.endcap];return o.forEach((function(n){n.virtual||c.forEach((function(i){if(i.virtual)return;const o=n.intersects(i,r);o.length>0&&(o.c1=n,o.c2=i,o.s1=t,o.s2=e,s.push(o))}))})),s},makeshape:function(t,n,e){const i=n.points.length,r=t.points.length,s=I.makeline(n.points[i-1],t.points[0]),o=I.makeline(t.points[r-1],n.points[0]),c={startcap:s,forward:t,back:n,endcap:o,bbox:I.findbbox([s,t,n,o]),intersections:function(t){return I.shapeintersections(c,c.bbox,t,t.bbox,e)}};return c},getminmax:function(t,n,e){if(!e)return{min:0,max:0};let i,r,s=S,o=N;-1===e.indexOf(0)&&(e=[0].concat(e)),-1===e.indexOf(1)&&e.push(1);for(let c=0,u=e.length;c<u;c++)i=e[c],r=t.get(i),r[n]<s&&(s=r[n]),r[n]>o&&(o=r[n]);return{min:s,mid:(s+o)/2,max:o,size:o-s}},align:function(t,n){const e=n.p1.x,i=n.p1.y,r=-v(n.p2.y-i,n.p2.x-e);return t.map((function(t){return{x:(t.x-e)*m(r)-(t.y-i)*g(r),y:(t.x-e)*g(r)+(t.y-i)*m(r)}}))},roots:function(t,n){n=n||{p1:{x:0,y:0},p2:{x:1,y:0}};const e=t.length-1,i=I.align(t,n),r=function(t){return 0<=t&&t<=1};if(2===e){const t=i[0].y,n=i[1].y,e=i[2].y,s=t-2*n+e;if(0!==s){const i=-z(n*n-t*e),o=-t+n;return[-(i+o)/s,-(-i+o)/s].filter(r)}return n!==e&&0===s?[(2*n-e)/(2*n-2*e)].filter(r):[]}const s=i[0].y,o=i[1].y,c=i[2].y;let u=3*o-s-3*c+i[3].y,h=3*s-6*o+3*c,a=-3*s+3*o,l=s;if(I.approximately(u,0)){if(I.approximately(h,0))return I.approximately(a,0)?[]:[-l/a].filter(r);const t=z(a*a-4*h*l),n=2*h;return[(t-a)/n,(-a-t)/n].filter(r)}h/=u,a/=u,l/=u;const x=(3*a-h*h)/3,f=x/3,y=(2*h*h*h-9*h*a+27*l)/27,p=y/2,d=p*p+f*f*f;let g,v,w,k,M;if(d<0){const t=-x/3,n=z(t*t*t),e=-y/(2*n),i=b(e<-1?-1:e>1?1:e),s=2*_(n);return w=s*m(i/3)-h/3,k=s*m((i+E)/3)-h/3,M=s*m((i+2*E)/3)-h/3,[w,k,M].filter(r)}if(0===d)return g=p<0?_(-p):-_(p),w=2*g-h/3,k=-g-h/3,[w,k].filter(r);{const t=z(d);return g=_(-p+t),v=_(p+t),[g-v-h/3].filter(r)}},droots:function(t){if(3===t.length){const n=t[0],e=t[1],i=t[2],r=n-2*e+i;if(0!==r){const t=-z(e*e-n*i),s=-n+e;return[-(t+s)/r,-(-t+s)/r]}return e!==i&&0===r?[(2*e-i)/(2*(e-i))]:[]}if(2===t.length){const n=t[0],e=t[1];return n!==e?[n/(n-e)]:[]}return[]},curvature:function(t,n,e,i,r){let s,o,c,u,h=0,a=0;const l=I.compute(t,n),x=I.compute(t,e),f=l.x*l.x+l.y*l.y;if(i?(s=z(w(l.y*x.z-x.y*l.z,2)+w(l.z*x.x-x.z*l.x,2)+w(l.x*x.y-x.x*l.y,2)),o=w(f+l.z*l.z,1.5)):(s=l.x*x.y-l.y*x.x,o=w(f,1.5)),0===s||0===o)return{k:0,r:0};if(h=s/o,a=o/s,!r){const r=I.curvature(t-.001,n,e,i,!0).k,s=I.curvature(t+.001,n,e,i,!0).k;u=(s-h+(h-r))/2,c=(d(s-h)+d(h-r))/2}return{k:h,r:a,dk:u,adk:c}},inflections:function(t){if(t.length<4)return[];const n=I.align(t,{p1:t[0],p2:t.slice(-1)[0]}),e=n[2].x*n[1].y,i=n[3].x*n[1].y,r=n[1].x*n[2].y,s=18*(-3*e+2*i+3*r-n[3].x*n[2].y),o=18*(3*e-i-3*r),c=18*(r-e);if(I.approximately(s,0)){if(!I.approximately(o,0)){let t=-c/o;if(0<=t&&t<=1)return[t]}return[]}const u=2*s;if(I.approximately(u,0))return[];const h=o*o-4*s*c;if(h<0)return[];const a=Math.sqrt(h);return[(a-o)/u,-(o+a)/u].filter((function(t){return 0<=t&&t<=1}))},bboxoverlap:function(t,n){const e=["x","y"],i=e.length;for(let r,s,o,c,u=0;u<i;u++)if(r=e[u],s=t[r].mid,o=n[r].mid,c=(t[r].size+n[r].size)/2,d(s-o)>=c)return!1;return!0},expandbox:function(t,n){n.x.min<t.x.min&&(t.x.min=n.x.min),n.y.min<t.y.min&&(t.y.min=n.y.min),n.z&&n.z.min<t.z.min&&(t.z.min=n.z.min),n.x.max>t.x.max&&(t.x.max=n.x.max),n.y.max>t.y.max&&(t.y.max=n.y.max),n.z&&n.z.max>t.z.max&&(t.z.max=n.z.max),t.x.mid=(t.x.min+t.x.max)/2,t.y.mid=(t.y.min+t.y.max)/2,t.z&&(t.z.mid=(t.z.min+t.z.max)/2),t.x.size=t.x.max-t.x.min,t.y.size=t.y.max-t.y.min,t.z&&(t.z.size=t.z.max-t.z.min)},pairiteration:function(t,n,e){const i=t.bbox(),r=n.bbox(),s=1e5,o=e||.5;if(i.x.size+i.y.size<o&&r.x.size+r.y.size<o)return[(s*(t._t1+t._t2)/2|0)/s+"/"+(s*(n._t1+n._t2)/2|0)/s];let c=t.split(.5),u=n.split(.5),h=[{left:c.left,right:u.left},{left:c.left,right:u.right},{left:c.right,right:u.right},{left:c.right,right:u.left}];h=h.filter((function(t){return I.bboxoverlap(t.left.bbox(),t.right.bbox())}));let a=[];return 0===h.length||(h.forEach((function(t){a=a.concat(I.pairiteration(t.left,t.right,o))})),a=a.filter((function(t,n){return a.indexOf(t)===n}))),a},getccenter:function(t,n,e){const i=n.x-t.x,r=n.y-t.y,s=e.x-n.x,o=e.y-n.y,c=i*m(M)-r*g(M),u=i*g(M)+r*m(M),h=s*m(M)-o*g(M),a=s*g(M)+o*m(M),l=(t.x+n.x)/2,x=(t.y+n.y)/2,f=(n.x+e.x)/2,y=(n.y+e.y)/2,p=l+c,d=x+u,b=f+h,z=y+a,w=I.lli8(l,x,p,d,f,y,b,z),_=I.dist(w,t);let k,S=v(t.y-w.y,t.x-w.x),N=v(n.y-w.y,n.x-w.x),A=v(e.y-w.y,e.x-w.x);return S<A?((S>N||N>A)&&(S+=E),S>A&&(k=A,A=S,S=k)):A<N&&N<S?(k=A,A=S,S=k):A+=E,w.s=S,w.e=A,w.r=_,w},numberSort:function(t,n){return t-n}};class O{constructor(t){this.curves=[],this._3d=!1,t&&(this.curves=t,this._3d=this.curves[0]._3d)}valueOf(){return this.toString()}toString(){return"["+this.curves.map((function(t){return I.pointsToString(t.points)})).join(", ")+"]"}addCurve(t){this.curves.push(t),this._3d=this._3d||t._3d}length(){return this.curves.map((function(t){return t.length()})).reduce((function(t,n){return t+n}))}curve(t){return this.curves[t]}bbox(){const t=this.curves;for(var n=t[0].bbox(),e=1;e<t.length;e++)I.expandbox(n,t[e].bbox());return n}offset(t){const n=[];return this.curves.forEach((function(e){n.push(...e.offset(t))})),new O(n)}}const{abs:C,min:j,max:T,cos:$,sin:B,acos:D,sqrt:P}=Math,F=Math.PI;class q{constructor(t){let n=t&&t.forEach?t:Array.from(arguments).slice(),e=!1;if("object"==typeof n[0]){e=n.length;const t=[];n.forEach((function(n){["x","y","z"].forEach((function(e){void 0!==n[e]&&t.push(n[e])}))})),n=t}let i=!1;const r=n.length;if(e){if(e>4){if(1!==arguments.length)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");i=!0}}else if(6!==r&&8!==r&&9!==r&&12!==r&&1!==arguments.length)throw new Error("Only new Bezier(point[]) is accepted for 4th and higher order curves");const s=this._3d=!i&&(9===r||12===r)||t&&t[0]&&void 0!==t[0].z,o=this.points=[];for(let t=0,e=s?3:2;t<r;t+=e){var c={x:n[t],y:n[t+1]};s&&(c.z=n[t+2]),o.push(c)}const u=this.order=o.length-1,h=this.dims=["x","y"];s&&h.push("z"),this.dimlen=h.length;const a=I.align(o,{p1:o[0],p2:o[u]}),l=I.dist(o[0],o[u]);this._linear=a.reduce(((t,n)=>t+C(n.y)),0)<l/50,this._lut=[],this._t1=0,this._t2=1,this.update()}static quadraticFromPoints(t,n,e,i){if(void 0===i&&(i=.5),0===i)return new q(n,n,e);if(1===i)return new q(t,n,n);const r=q.getABC(2,t,n,e,i);return new q(t,r.A,e)}static cubicFromPoints(t,n,e,i,r){void 0===i&&(i=.5);const s=q.getABC(3,t,n,e,i);void 0===r&&(r=I.dist(n,s.C));const o=r*(1-i)/i,c=I.dist(t,e),u=(e.x-t.x)/c,h=(e.y-t.y)/c,a=r*u,l=r*h,x=o*u,f=o*h,y=n.x-a,p=n.y-l,d=n.x+x,m=n.y+f,g=s.A,b=g.x+(y-g.x)/(1-i),v=g.y+(p-g.y)/(1-i),z=g.x+(d-g.x)/i,w=g.y+(m-g.y)/i,_={x:t.x+(b-t.x)/i,y:t.y+(v-t.y)/i},k={x:e.x+(z-e.x)/(1-i),y:e.y+(w-e.y)/(1-i)};return new q(t,_,k,e)}static getUtils(){return I}getUtils(){return q.getUtils()}static get PolyBezier(){return O}valueOf(){return this.toString()}toString(){return I.pointsToString(this.points)}toSVG(){if(this._3d)return!1;const t=this.points,n=["M",t[0].x,t[0].y,2===this.order?"Q":"C"];for(let e=1,i=t.length;e<i;e++)n.push(t[e].x),n.push(t[e].y);return n.join(" ")}setRatios(t){if(t.length!==this.points.length)throw new Error("incorrect number of ratio values");this.ratios=t,this._lut=[]}verify(){const t=this.coordDigest();t!==this._print&&(this._print=t,this.update())}coordDigest(){return this.points.map((function(t,n){return""+n+t.x+t.y+(t.z?t.z:0)})).join("")}update(){this._lut=[],this.dpoints=I.derive(this.points,this._3d),this.computedirection()}computedirection(){const t=this.points,n=I.angle(t[0],t[this.order],t[1]);this.clockwise=n>0}length(){return I.length(this.derivative.bind(this))}static getABC(t=2,n,e,i,r=.5){const s=I.projectionratio(r,t),o=1-s,c={x:s*n.x+o*i.x,y:s*n.y+o*i.y},u=I.abcratio(r,t);return{A:{x:e.x+(e.x-c.x)/u,y:e.y+(e.y-c.y)/u},B:e,C:c,S:n,E:i}}getABC(t,n){n=n||this.get(t);let e=this.points[0],i=this.points[this.order];return q.getABC(this.order,e,n,i,t)}getLUT(t){if(this.verify(),t=t||100,this._lut.length===t)return this._lut;this._lut=[],t++,this._lut=[];for(let n,e,i=0;i<t;i++)e=i/(t-1),n=this.compute(e),n.t=e,this._lut.push(n);return this._lut}on(n,e){e=e||5;const i=this.getLUT(),r=[];for(let t,s=0,o=0;s<i.length;s++)t=i[s],I.dist(t,n)<e&&(r.push(t),o+=s/i.length);return!!r.length&&(t/=r.length)}project(t){const n=this.getLUT(),e=n.length-1,i=I.closest(n,t),r=i.mpos,s=(r-1)/e,o=(r+1)/e,c=.1/e;let u,h,a=i.mdist,l=s,x=l;for(a+=1;l<o+c;l+=c)u=this.compute(l),h=I.dist(t,u),h<a&&(a=h,x=l);return x=x<0?0:x>1?1:x,u=this.compute(x),u.t=x,u.d=a,u}get(t){return this.compute(t)}point(t){return this.points[t]}compute(t){return this.ratios?I.computeWithRatios(t,this.points,this.ratios,this._3d):I.compute(t,this.points,this._3d,this.ratios)}raise(){const t=this.points,n=[t[0]],e=t.length;for(let i,r,s=1;s<e;s++)i=t[s],r=t[s-1],n[s]={x:(e-s)/e*i.x+s/e*r.x,y:(e-s)/e*i.y+s/e*r.y};return n[e]=t[e-1],new q(n)}derivative(t){return I.compute(t,this.dpoints[0],this._3d)}dderivative(t){return I.compute(t,this.dpoints[1],this._3d)}align(){let t=this.points;return new q(I.align(t,{p1:t[0],p2:t[t.length-1]}))}curvature(t){return I.curvature(t,this.dpoints[0],this.dpoints[1],this._3d)}inflections(){return I.inflections(this.points)}normal(t){return this._3d?this.__normal3(t):this.__normal2(t)}__normal2(t){const n=this.derivative(t),e=P(n.x*n.x+n.y*n.y);return{t,x:-n.y/e,y:n.x/e}}__normal3(t){const n=this.derivative(t),e=this.derivative(t+.01),i=P(n.x*n.x+n.y*n.y+n.z*n.z),r=P(e.x*e.x+e.y*e.y+e.z*e.z);n.x/=i,n.y/=i,n.z/=i,e.x/=r,e.y/=r,e.z/=r;const s={x:e.y*n.z-e.z*n.y,y:e.z*n.x-e.x*n.z,z:e.x*n.y-e.y*n.x},o=P(s.x*s.x+s.y*s.y+s.z*s.z);s.x/=o,s.y/=o,s.z/=o;const c=[s.x*s.x,s.x*s.y-s.z,s.x*s.z+s.y,s.x*s.y+s.z,s.y*s.y,s.y*s.z-s.x,s.x*s.z-s.y,s.y*s.z+s.x,s.z*s.z];return{t,x:c[0]*n.x+c[1]*n.y+c[2]*n.z,y:c[3]*n.x+c[4]*n.y+c[5]*n.z,z:c[6]*n.x+c[7]*n.y+c[8]*n.z}}hull(t){let n=this.points,e=[],i=[],r=0;for(i[r++]=n[0],i[r++]=n[1],i[r++]=n[2],3===this.order&&(i[r++]=n[3]);n.length>1;){e=[];for(let s,o=0,c=n.length-1;o<c;o++)s=I.lerp(t,n[o],n[o+1]),i[r++]=s,e.push(s);n=e}return i}split(t,n){if(0===t&&n)return this.split(n).left;if(1===n)return this.split(t).right;const e=this.hull(t),i={left:2===this.order?new q([e[0],e[3],e[5]]):new q([e[0],e[4],e[7],e[9]]),right:2===this.order?new q([e[5],e[4],e[2]]):new q([e[9],e[8],e[6],e[3]]),span:e};return i.left._t1=I.map(0,0,1,this._t1,this._t2),i.left._t2=I.map(t,0,1,this._t1,this._t2),i.right._t1=I.map(t,0,1,this._t1,this._t2),i.right._t2=I.map(1,0,1,this._t1,this._t2),n?(n=I.map(n,t,1,0,1),i.right.split(n).left):i}extrema(){const t={};let n=[];return this.dims.forEach(function(e){let i=function(t){return t[e]},r=this.dpoints[0].map(i);t[e]=I.droots(r),3===this.order&&(r=this.dpoints[1].map(i),t[e]=t[e].concat(I.droots(r))),t[e]=t[e].filter((function(t){return t>=0&&t<=1})),n=n.concat(t[e].sort(I.numberSort))}.bind(this)),t.values=n.sort(I.numberSort).filter((function(t,e){return n.indexOf(t)===e})),t}bbox(){const t=this.extrema(),n={};return this.dims.forEach(function(e){n[e]=I.getminmax(this,e,t[e])}.bind(this)),n}overlaps(t){const n=this.bbox(),e=t.bbox();return I.bboxoverlap(n,e)}offset(t,n){if(void 0!==n){const e=this.get(t),i=this.normal(t),r={c:e,n:i,x:e.x+i.x*n,y:e.y+i.y*n};return this._3d&&(r.z=e.z+i.z*n),r}if(this._linear){const n=this.normal(0),e=this.points.map((function(e){const i={x:e.x+t*n.x,y:e.y+t*n.y};return e.z&&n.z&&(i.z=e.z+t*n.z),i}));return[new q(e)]}return this.reduce().map((function(n){return n._linear?n.offset(t)[0]:n.scale(t)}))}simple(){if(3===this.order){const t=I.angle(this.points[0],this.points[3],this.points[1]),n=I.angle(this.points[0],this.points[3],this.points[2]);if(t>0&&n<0||t<0&&n>0)return!1}const t=this.normal(0),n=this.normal(1);let e=t.x*n.x+t.y*n.y;return this._3d&&(e+=t.z*n.z),C(D(e))<F/3}reduce(){let t,n,e=0,i=0,r=.01,s=[],o=[],c=this.extrema().values;for(-1===c.indexOf(0)&&(c=[0].concat(c)),-1===c.indexOf(1)&&c.push(1),e=c[0],t=1;t<c.length;t++)i=c[t],n=this.split(e,i),n._t1=e,n._t2=i,s.push(n),e=i;return s.forEach((function(t){for(e=0,i=0;i<=1;)for(i=e+r;i<=1.01;i+=r)if(n=t.split(e,i),!n.simple()){if(i-=r,C(e-i)<r)return[];n=t.split(e,i),n._t1=I.map(e,0,1,t._t1,t._t2),n._t2=I.map(i,0,1,t._t1,t._t2),o.push(n),e=i;break}e<1&&(n=t.split(e,1),n._t1=I.map(e,0,1,t._t1,t._t2),n._t2=t._t2,o.push(n))})),o}translate(t,n,e){e="number"==typeof e?e:n;const i=this.order;let r=this.points.map(((t,r)=>(1-r/i)*n+r/i*e));return new q(this.points.map(((n,e)=>({x:n.x+t.x*r[e],y:n.y+t.y*r[e]}))))}scale(t){const n=this.order;let e=!1;if("function"==typeof t&&(e=t),e&&2===n)return this.raise().scale(e);const i=this.clockwise,r=this.points;if(this._linear)return this.translate(this.normal(0),e?e(0):t,e?e(1):t);const s=e?e(0):t,o=e?e(1):t,c=[this.offset(0,10),this.offset(1,10)],u=[],h=I.lli4(c[0],c[0].c,c[1],c[1].c);if(!h)throw new Error("cannot scale this curve. Try reducing it first.");return[0,1].forEach((function(t){const e=u[t*n]=I.copy(r[t*n]);e.x+=(t?o:s)*c[t].n.x,e.y+=(t?o:s)*c[t].n.y})),e?([0,1].forEach((function(s){if(2!==n||!s){var o=r[s+1],c={x:o.x-h.x,y:o.y-h.y},a=e?e((s+1)/n):t;e&&!i&&(a=-a);var l=P(c.x*c.x+c.y*c.y);c.x/=l,c.y/=l,u[s+1]={x:o.x+a*c.x,y:o.y+a*c.y}}})),new q(u)):([0,1].forEach((t=>{if(2===n&&t)return;const e=u[t*n],i=this.derivative(t),s={x:e.x+i.x,y:e.y+i.y};u[t+1]=I.lli4(e,s,h,r[t+1])})),new q(u))}outline(t,n,e,i){if(n=void 0===n?t:n,this._linear){const r=this.normal(0),s=this.points[0],o=this.points[this.points.length-1];let c,u,h;void 0===e&&(e=t,i=n),c={x:s.x+r.x*t,y:s.y+r.y*t},h={x:o.x+r.x*e,y:o.y+r.y*e},u={x:(c.x+h.x)/2,y:(c.y+h.y)/2};const a=[c,u,h];c={x:s.x-r.x*n,y:s.y-r.y*n},h={x:o.x-r.x*i,y:o.y-r.y*i},u={x:(c.x+h.x)/2,y:(c.y+h.y)/2};const l=[h,u,c],x=I.makeline(l[2],a[0]),f=I.makeline(a[2],l[0]),y=[x,new q(a),f,new q(l)];return new O(y)}const r=this.reduce(),s=r.length,o=[];let c,u=[],h=0,a=this.length();const l=void 0!==e&&void 0!==i;function x(t,n,e,i,r){return function(s){const o=i/e,c=
1-50 of 148