memoscan
← all memos

Memo 0xbf656262…e19cfe on Ethereum

///6 //SVG EXPORT const SVG_WIDTH_MM=210; const SVG_HEIGHT_MM=297; function makeSVG(){let e=SVG_WIDTH_MM/BDM,t=["LINE","LOOP","DASH","TRUSS","WHEEL","STAR","TREE","URCHIN","CENTI","BALL","MEMBRANE","OFFSETS"],n=getSVGDocumentHeader();n+='<g id="main_ink_layer" ',n+='fill="none" stroke="black" stroke-linecap="round" stroke-width="0.38"> \n';for(let l=0;l<mySs.length;l++){let S=mySs[l],o=S.getContours(),r=S.type;if(n+=' <g id="structure_',n+=t[S.type],n+="_"+l+'"> \n',r==ST12){let t=mySs[l].renderLetterForSVG();for(let l=0;l<t.length;l++){let S=t[l];if(2==S.length){n+=getLineSegmentSVG(S,e)}}}resetRnd(CHASH);for(let t=0;t<o.length;t++){let l=o[t],s=l.thickness;r==ST11&&(s=W0);let g=1,i=0;s<=W0?(g=1,i=0):s<=W1?(g=3,i=.38):s<=W2?(g=4,i=.76):(g=8,i=1.52);for(let o=0;o<g;o++){let s="",h=l.verts,a=l.bClosed,c=l.bSmooth,d=l.bIsDot,V=l.dashGap,G=l.dashLen,y=[];if(g>1){let e=map(o,0,g,0,PI2),t=i*cos(e),n=i*sin(e);for(let e=0;e<h.length;e++){let l=h[e].x+t,S=h[e].y+n;y[e]=CV(l,S)}}else y=h;d?s=getCircSVG(y,e,.095):V>0?(r==ST10&&4==S.STID&&(StSh.bOrientationSensitiveDashedContours=T),s=getDashedPolycurveSVG(y,e,t,a,V,G),StSh.bOrientationSensitiveDashedContours=F):a?l.strokeStyle!=STR_NO&&(s=getClosedPolycurveSVG(y,e,t)):s=2==y.length?getLineSegmentSVG(y,e):c?getOpenPolycurveSVG(y,e,t):getPolylineSVG(y,e,t,F),n+=s}}n+=" </g>\n"}let l=getContoursForHatchedShapes();if(l.length>0){n+=' <g id="hatch_lines"> \n';for(let t=0;t<l.length;t++){let S=l[t].verts;if(2==S.length){n+=getLineSegmentSVG(S,e)}}n+=" </g>\n\n"}n+=getEncircledSiteBlobsSVG(e),n+=getParticlesSVG(e),n+=getSelectVoronoiCellsSVG(e),n+="</g>\n\n",n+="</svg>";let S="cytographia_"+CHASH+"_"+myFrmCnt;saveStrings([n],S,"svg")} function getSVGDocumentHeader(){ let currDateAndTime=new Date(); let aDocStr=""; aDocStr+='<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'; aDocStr+='<!-- SVG generated using Cytographia by Golan Levin (CC BY-NC-ND 4.0,2023) -->\n'; aDocStr+='<!-- '+currDateAndTime+' -->\n\n'; aDocStr+='<!-- NOTE: This SVG has been specifically designed for execution by a computer-controlled plotter, -->\n'; aDocStr+='<!-- such as an EMSL AxiDraw V3. In particular, it has been designed to be plotted on A4-size paper -->\n'; aDocStr+='<!-- using a very thin black pen, such as the the Pilot G2 Ultra Fine Point (0.38 mm) Gel Ink Pen. -->\n'; aDocStr+='<!-- Note that the plotted version may differ in certain respects from its on-screen appearance. -->\n\n'; aDocStr+='<svg\n'; aDocStr+=' width="'+SVG_WIDTH_MM+'mm"\n'; aDocStr+=' height="'+SVG_HEIGHT_MM+'mm"\n'; aDocStr+=' viewBox="0 0 '+SVG_WIDTH_MM+" "+SVG_HEIGHT_MM+'"\n'; aDocStr+=' version="1.1"\n\n'; aDocStr+=' xmlns="http://www.w3.org/2000/svg"\n'; aDocStr+=' xmlns:svg="http://www.w3.org/2000/svg"\n'; aDocStr+=' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"\n'; aDocStr+=' xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"\n'; aDocStr+=' xmlns:cc="http://creativecommons.org/ns#"\n'; aDocStr+=' xmlns:dc="http://purl.org/dc/elements/1.1/">\n\n'; aDocStr+=' <title>Cytographia: '+CHASH+':'+myFrmCnt+' (SVG)</title>\n'; aDocStr+=' <metadata>\n'; aDocStr+=' <rdf:RDF>\n'; aDocStr+=' <cc:Work rdf:about="http://www.flong.com/"> \n'; aDocStr+=' <dc:title>Cytographia: '+CHASH+':'+myFrmCnt+' (SVG)</dc:title>\n'; aDocStr+=' <dc:date>2023</dc:date>\n'; aDocStr+=' <dc:identifier>'+CHASH+'</dc:identifier>\n'; aDocStr+=' <dc:creator>\n'; aDocStr+=' <cc:Agent>\n'; aDocStr+=' <dc:title>Golan Levin</dc:title>\n'; aDocStr+=' </cc:Agent>\n'; aDocStr+=' </dc:creator>\n'; aDocStr+=' <dc:publisher>\n'; aDocStr+=' <cc:Agent>\n'; aDocStr+=' <dc:title>ArtBlocks</dc:title>\n'; aDocStr+=' </cc:Agent>\n'; aDocStr+=' </dc:publisher>\n'; aDocStr+=' <dc:description>A computationally generated diagram of an imaginary microorganism.</dc:description>\n\n'; aDocStr+=' <dc:rights>\n'; aDocStr+=' <cc:Agent>\n'; aDocStr+=' <dc:title>Levin, Golan. This SVG design is released under CC BY-NC-ND 4.0.</dc:title>\n'; aDocStr+=' </cc:Agent>\n'; aDocStr+=' </dc:rights>\n'; aDocStr+=' <cc:license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/4.0/"/>\n'; aDocStr+=' <dc:coverage>International</dc:coverage>\n\n'; aDocStr+=' <dc:contributor>\n'; aDocStr+=' <cc:Agent>\n'; aDocStr+=' <dc:title>Developed with p5.js, d3.js, and additional libraries.</dc:title>\n'; aDocStr+=' </cc:Agent>\n'; aDocStr+=' </dc:contributor>\n\n'; aDocStr+=' <dc:subject>\n'; aDocStr+=' <rdf:Bag>\n'; aDocStr+=' <rdf:li>cell</rdf:li>\n'; aDocStr+=' <rdf:li>diagram</rdf:li>\n'; aDocStr+=' <rdf:li>illustration</rdf:li>\n'; aDocStr+=' <rdf:li>incunabula</rdf:li>\n'; aDocStr+=' <rdf:li>cytology</rdf:li>\n'; aDocStr+=' <rdf:li>generative art</rdf:li>\n'; aDocStr+=' <rdf:li>interactive art</rdf:li>\n'; aDocStr+=' <rdf:li>asemic writing</rdf:li>\n'; aDocStr+=' <rdf:li>skeuomorphism</rdf:li>\n'; aDocStr+=' <rdf:li>xenobiology</rdf:li>\n'; aDocStr+=' </rdf:Bag>\n'; aDocStr+=' </dc:subject>\n'; aDocStr+=' </cc:Work>\n\n'; aDocStr+=' <cc:License rdf:about="http://creativecommons.org/licenses/by-nc-nd/4.0/">\n'; aDocStr+=' </cc:License>\n'; aDocStr+=' </rdf:RDF>\n'; aDocStr+=' </metadata>\n\n'; return aDocStr;} function getDashedPolycurveSVG(e,t,i,n,s,l){let h=e.length,o="",r=0;if(n){let n=h+1,u=~~myRAB(0,h/10),S=StSh.orientationSensitiveOmitDashAngle,f=StSh.orientationSensitiveDashNotchWidth,y=cos(S),p=sin(S);for(;r<h;){let S=2+round(myRAB(1,l)),a=h-r;if(a<=1)break;2==a?S=1:a<S&&(S=a-1);let m=[];if(StSh.bOrientationSensitiveDashedContours){let t=myRA(f),i=F;for(let s=0;s<S;s++){let l=(r+u-1+h)%h,o=(r+u)%h;if(r<n){let n=e[o].x-e[l].x,h=e[o].y-e[l].y,r=sqrt(n*n+h*h);t<abs(n/r*p-h/r*y)&&!i?(m.push(e[o]),0!=s&&s!=S-1||m.push(e[o])):i=T}r++}}else{let t=(r+u)%h;m.push(e[t]);for(let i=0;i<S;i++)t=(r+u)%h,r<n&&m.push(e[t]),r++;m.push(e[t])}if(m.length>0){o+=getOpenPolycurveSVG(m,t,i+"_"+r)}r+=~~myRAB(1,s)-1}}else{let n=h-1;for(;r<h;){let h=1+~~myRAB(1,l),u=[],S=min(r,n);u.push(e[S]);for(let t=0;t<h;t++)S=min(r,n),u.push(e[S]),r++;u.push(e[S]),o+=getOpenPolycurveSVG(u,t,i+"_"+r),r+=~~myRAB(1,s)-1}}return o} function getLineSegmentSVG(n,e){let f=n[0].x*e,t=n[0].y*e,x=n[1].x*e,y=n[1].y*e,i=' <line x1="'+nf(f,1,3);return i+='" y1="'+nf(t,1,3),i+='" x2="'+nf(x,1,3),i+='" y2="'+nf(y,1,3),i+='" /> \n',i} function getPolylineSVG(n,t,e,l){let f=" <path\n";f+=' id="path'+e+'"\n',f+=' d="';for(let e=0;e<n.length;e++){f+=0==e?"M ":" L ";let l=n[e].x*t,h=n[e].y*t;f+=nf(l,1,3)+",",f+=nf(h,1,3)}return l&&(f+=" Z"),f+='"/>\n',f} function getParticlesSVG(e){let t="";if(StSh.bDrawPs){let s=0;for(let e=nMaskPoints;e<myPs.length;e++)myPs[e].isFree&&s++;if(s>0){t=' <g id="free_particles"> \n';for(let s=nMaskPoints;s<myPs.length;s++)if(myPs[s].isFree){let i=[myPs[s].p];t+=getCircSVG(i,e,W0)}t+=" </g>\n"}}return t} function getCircSVG(n,e,t){let c="";for(let r=0;r<n.length;r++){let f=n[r].x*e,l=n[r].y*e,i=t*e;c+=" <circle ",c+='cx="'+nf(f,1,3)+'" ',c+='cy="'+nf(l,1,3)+'" ',c+='r="'+nf(i,1,3)+'"',c+="/>\n"}return c} function getClosedPolycurveSVG(n,N,l){let t="",e=1/3,x=getVxPV(n,0,0,e),f=T;if((null==x||isNaN(x.x)||isNaN(x.y))&&(f=F),f){t=" <path \n",t+=' id="path'+l+'"\n',t+=' d="',t+="M ",t+=nf(x.x*N,1,3)+",",t+=nf(x.y*N,1,3);for(let l=0;l<n.length;l++){let x=getVxPV(n,l+0,1,e),f=getVxPV(n,l+1,-1,e),i=getVxPV(n,l+1,0,e);null!=x&&null!=f&&null!=i&&(isNaN(x.x)||isNaN(f.x)||isNaN(i.x)||isNaN(x.y)||isNaN(f.y)||isNaN(i.y)||(t+=" C ",t+=nf(x.x*N,1,3)+",",t+=nf(x.y*N,1,3)+" ",t+=nf(f.x*N,1,3)+",",t+=nf(f.y*N,1,3)+" ",t+=nf(i.x*N,1,3)+",",t+=nf(i.y*N,1,3)))}t+=' Z"/>\n'}return t} function getSelectVoronoiCellsSVG(e){let l="";if(StSh.bDrawVs){let t=mySs.length,o=0;for(let e=0;e<t;e++)mySs[e].bShoVorCls&&o++;if(o>0){let t,o,s,i=T;t=d3Voronoi.cellPolygons(),o=t.next(),s=0,l+=' <g id="voronoi_cells"> \n';let n=StSh.nVoronoiSubdivs;for(;!o.done;){if(i){let t=myPs[s].isInStrc;if(t>0&&mySs[t].bShoVorCls){let t=o.value,i=t.length-1,r=[];if(n>1){for(let e=0;e<i;e++)for(let l=0;l<n;l++){let l=t[e][0],o=t[e][1];r.push(CV(l,o))}let e=r.length;for(let l=0;l<e;l++){let t=(l-1+e)%e,o=(l+1)%e;r[l].x=(r[t].x+r[l].x+r[o].x)/3,r[l].y=(r[t].y+r[l].y+r[o].y)/3}for(let l=e-1;l>=0;l--){let t=(l-1+e)%e,o=(l+1)%e;r[l].x=(r[t].x+r[l].x+r[o].x)/3,r[l].y=(r[t].y+r[l].y+r[o].y)/3}}else for(let e=0;e<i;e++){let l=t[e][0],o=t[e][1];r.push(CV(l,o))}l+=getPolylineSVG(r,e,"cell"+s,T),r=null}}if(StSh.bDrawClippedVoronoiCellsOnInteriorStructureBoundaries){let t=myPs[s].isOfStrc;if(t>0){let i=mySs[t];if(i.bShoVorCls&&i.bShoVorEdgs&&i.type==ST4){let n=i.pIs,r=n.length,y=-1;for(let e=0;e<r;e++)n[e]==s&&(y=e);if(y>=0&&y%2==0){let s=y,i=(y+2)%r,S=n[(y-2+r)%r],f=n[s],u=n[i],V=myPs[S].p.x,g=myPs[S].p.y,p=myPs[f].p.x,h=myPs[f].p.y,m=myPs[u].p.x,x=myPs[u].p.y,c=o.value,C=c.length-1,P=3;for(let o=0;o<C;o++){let s=c[o][0],i=c[o][1],n=c[o+1][0],r=c[o+1][1];if(mySs[t].pointInside(s,i)){if((s-p)*(g-h)-(i-h)*(V-p)>0)if((n-m)*(h-x)-(r-x)*(p-m)>0){let t=[];t.push(CV(s,i)),t.push(CV(n,r)),l+=getLineSegmentSVG(t,e),t=null}else{let t=(x-g)*(n-s)-(m-V)*(r-i);if(abs(t)>0){let o=((m-V)*(i-g)-(x-g)*(s-V))/t,y=((n-s)*(i-g)-(r-i)*(s-V))/t;if(abs(o)<P&&abs(y)<P){let t=s+o*(n-s),y=i+o*(r-i),S=[];S.push(CV(s,i)),S.push(CV(t,y)),l+=getLineSegmentSVG(S,e),S=null}}}}}}}}}o=t.next(),s++}for(l+=" </g>\n",t=d3Voronoi.cellPolygons(),o=t.next(),s=0,l+=' <g id="voronoi_nuclei"> \n';!o.done;){let i=myPs[s].isInStrc;if(i>0&&mySs[i].bShoVorNuc){let t=[myPs[s].p];l+=getCircSVG(t,e,W1),l+=getCircSVG(t,e,W0)}o=t.next(),s++}l+=" </g>\n"}}return l} function getEncircledSiteBlobsSVG(e){let t="\n",l=0;if(StSh.bDrawBs){let s=d3Voronoi.cellPolygons(),i=s.next(),n=0;for(;!i.done;){if(myPs[n].bDrawSiteBlob&&!myPs[n].bNoShoAsBlb){let s=myPs[n].bIsABoundarySite,o=!(-1==myPs[n].isOfStrc);if(!s&&!o){let s=i.value,o=s.length-1,r=myPs[n].c.x,b=myPs[n].c.y;t+=getSiteBlobSVG(s,o,r,b,n,e),l++}}i=s.next(),n++}}return l>0&&(t=' <g id="site_blobs"> \n'+t,t+=" </g>\n"),t} function getSiteBlobSVG(t,e,r,n,l,N){let i=[],f="";for(let r=0;r<e;r++){let e=r+1,n=t[r][0],l=t[r][1],N=(n+t[e][0])/2,f=(l+t[e][1])/2;i[r]=[N,f]}let g,s,a,V,o=StSh.siteBlobScale,A=StSh.siteBlobTightness,P=T;g=getVPtArr(i,0,0,A),(isNaN(g[0])||isNaN(g[1]))&&(P=F);for(let t=0;t<i.length;t++)s=getVPtArr(i,t,1,A),a=getVPtArr(i,t+1,-1,A),V=getVPtArr(i,t+1,0,A),(isNaN(s[0])||isNaN(s[1]))&&(P=F),(isNaN(a[0])||isNaN(a[1]))&&(P=F),(isNaN(V[0])||isNaN(V[1]))&&(P=F);if(P){f=" <path \n",f+=' id="blob'+l+'"\n',f+=' d="',g=getVPtArr(i,0,0,A);let t=r+o*(g[0]-r),e=n+o*(g[1]-n);f+="M ",f+=nf(t*N,1,3)+",",f+=nf(e*N,1,3);for(let t=0;t<i.length;t++){s=getVPtArr(i,t,1,A),a=getVPtArr(i,t+1,-1,A),V=getVPtArr(i,t+1,0,A);let e=r+o*(s[0]-r),l=n+o*(s[1]-n),g=r+o*(a[0]-r),P=n+o*(a[1]-n),S=r+o*(V[0]-r),h=n+o*(V[1]-n);f+=" C ",f+=nf(e*N,1,3)+",",f+=nf(l*N,1,3)+" ",f+=nf(g*N,1,3)+",",f+=nf(P*N,1,3)+" ",f+=nf(S*N,1,3)+",",f+=nf(h*N,1,3)}f+=' Z"/>\n'}return i=null,f} function getVxPV(e,r,t,o){let l=e.length;if(0===t)return e[r%l];{let n=e[r%l],c=e[(r+l-1)%l],a=e[(r+l+1)%l],u=Sb(c,n),m=Sb(a,n),p=u.copy().normalize(),V=m.copy().normalize(),i=0,g=Ad(p,V);if(g.mag()>0){g.normalize();let e=CV(g.y,0-g.x),r=p5.Vector.cross(p,V);return i=o,1===t?(i*=m.mag(),i*=r.z>0?-1:1):(i*=u.mag(),i*=r.z<0?-1:1),n.copy().add(e.mult(i))}return null}} function getOpenPolycurveSVG(n,e,t){let f=[],l=0;for(let e=0;e<n.length;e++)f[l++]=n[e].x,f[l++]=n[e].y;let r=F,i=catmullRom2bezier(f,r),o=T;for(let n=0;n<i.length;n++)(isNaN(i[n][0])||isNaN(i[n][1]))&&(o=F);let a="";if(o){a=" <path \n",a+=' id="path'+t+'"\n',a+=' d="',a+="M ",a+=nf(n[0].x*e,1,3)+",",a+=nf(n[0].y*e,1,3);for(let n=0;n<i.length;n++){let t=i[n];a+=" C ",a+=nf(t[0]*e,1,3)+",",a+=nf(t[1]*e,1,3)+" ",a+=nf(t[2]*e,1,3)+",",a+=nf(t[3]*e,1,3)+" ",a+=nf(t[4]*e,1,3)+",",a+=nf(t[5]*e,1,3)}a+='"/>\n'}return a} function catmullRom2bezier(x,y){let e=[];for(let t=0,l=x.length;l-2*!y>t;t+=2){let n=[{x:x[t-2],y:x[t-1]},{x:x[t+0],y:x[t+1]},{x:x[t+2],y:x[t+3]},{x:x[t+4],y:x[t+5]}];y?t?l-4===t?n[3]={x:x[0],y:x[1]}:l-2===t&&(n[2]={x:x[0],y:x[1]},n[3]={x:x[2],y:x[3]}):n[0]={x:x[l-2],y:x[l-1]}:l-4===t?n[3]=n[2]:t||(n[0]={x:x[t],y:x[t+1]}),e.push([(-n[0].x+6*n[1].x+n[2].x)/6,(-n[0].y+6*n[1].y+n[2].y)/6,(n[1].x+6*n[2].x-n[3].x)/6,(n[1].y+6*n[2].y-n[3].y)/6,n[2].x,n[2].y])}return e} //PARTICLE let Particle=function Particle(){ this.mass=1.;this.tMinv=TMP/this.mass;this.damping=DAMPING; this.bIsABoundarySite=F;this.bConstrainToMask=T; this.isOfStrc=-1;this.isInStrc=-1; this.isFree=T;this.bFixed=F; this.bDrawSiteBlob=F;this.nSpringsAttachedTo=0; this.bContributesToImplicitBlob=F; this.bNoShoAsBlb=(myR01()<StSh.blobDrpPct); this.bNoShoAsVorNuc=(myR01()<StSh.nucDropPct); this.p=CV(),this.v=CV(),this.c=CV(),this.p0=CV(),this.v0=CV(),this.pE=CV(),this.v1=CV(),this.pC=CV(),this.pH=CV(); this.set=function(s,t,i=1){this.p.set(s,t),this.v.set(0,0),this.p0.set(s,t),this.pE.set(s,t),this.pC.set(s,t),this.pH.set(s,t),this.v0.set(0,0),this.v1.set(0,0),i&&(this.mass=i,this.tMinv=TMP/this.mass)}; this.setTemperatureOverMass=function(){this.tMinv=TMP/this.mass},this.setIsPartOfStructure=function(t){this.isOfStrc=t}; this.setBConstrainToMask=function(t){this.bConstrainToMask=t}; this.clearForcesAndVelocities=function(){this.v.set(0,0),this.v0.set(0,0),this.v1.set(0,0)}; this.addF=function(t,s,i){const n=t*this.tMinv,h=s*this.tMinv;1==i?(this.v0.x+=n,this.v0.y+=h):(this.v1.x+=n,this.v1.y+=h)}; this.update=function(i){if(this.bFixed||this.bIsABoundarySite)this.p0.x=this.p.x,this.p0.y=this.p.y,this.pE.x=this.p.x,this.pE.y=this.p.y,this.pC.x=this.p.x,this.pC.y=this.p.y,this.pH.x=this.p.x,this.pH.y=this.p.y,this.v.x=this.v.y=0,this.v0.x=this.v0.y=0,this.v1.x=this.v1.y=0;else if(1==i)this.pE.x=this.p0.x+this.v0.x,this.pE.y=this.p0.y+this.v0.y,this.v1.x=this.v0.x,this.v1.y=this.v0.y;else if(2==i){this.pC.x=this.p0.x+this.v1.x,this.pC.y=this.p0.y+this.v1.y,this.pH.x=(this.pE.x+this.pC.x)/2,this.pH.y=(this.pE.y+this.pC.y)/2,this.p.x=this.p0.x=this.pH.x,this.p.y=this.p0.y=this.pH.y,this.v.x=this.damping*(this.v0.x+this.v1.x)/2,this.v.y=this.damping*(this.v0.y+this.v1.y)/2;const i=this.v.x*this.v.x+this.v.y*this.v.y;if(i>MAXSP2){const t=Math.sqrt(i);this.v.x=MAXSP*this.v.x/t,this.v.y=MAXSP*this.v.y/t}this.v0.x=this.v.x,this.v0.y=this.v.y}}; this.updateAndConstrainToMask=function(t){let i=F;if(this.bFixed||this.bIsABoundarySite)this.p0.x=this.p.x,this.p0.y=this.p.y,this.pE.x=this.p.x,this.pE.y=this.p.y,this.pC.x=this.p.x,this.pC.y=this.p.y,this.pH.x=this.p.x,this.pH.y=this.p.y,this.v.x=this.v.y=0,this.v0.x=this.v0.y=0,this.v1.x=this.v1.y=0;else if(1==t)this.pE.x=this.p0.x+this.v0.x,this.pE.y=this.p0.y+this.v0.y,this.v1.x=this.v0.x,this.v1.y=this.v0.y;else{this.pC.x=this.p0.x+this.v1.x,this.pC.y=this.p0.y+this.v1.y,this.pH.x=(this.pE.x+this.pC.x)/2,this.pH.y=(this.pE.y+this.pC.y)/2,this.p.x=this.p0.x=this.pH.x,this.p.y=this.p0.y=this.pH.y,i=this.constrainToMask(),this.v.x=this.damping*(this.v0.x+this.v1.x)/2,this.v.y=this.damping*(this.v0.y+this.v1.y)/2;const t=this.v.x*this.v.x+this.v.y*this.v.y;if(t>MAXSP2){const i=Math.sqrt(t);this.v.x=MAXSP*this.v.x/i,this.v.y=MAXSP*this.v.y/i}this.v0.x=this.v.x,this.v0.y=this.v.y}return i}; this.constrainToMask=function(){let t=F;if(!pointInPolygon(this.p.x,this.p.y,myPs,nMaskPoints)){let s=getClosestPointOnPolygonNaive(this.p.x,this.p.y,myPs,nMaskPoints);null!=s&&(this.set(s.x,s.y),t=T)}return t}; }; //SPRING let Spring=function Spring (tpa){ let ip;let iq;let baseLength;let restLength;let distention;let springConstant;let PArr=tpa; this.getP=function(){return PArr[ip];};this.getQ=function(){return PArr[iq];}; this.getIP=function(){return ip;};this.getIQ=function(){return iq;}; this.setIP=function(iip){ip=iip;};this.setIQ=function(iiq){iq=iiq;}; this.getRestL=function(){return restLength;};this.getBaseL=function(){return baseLength;}; this.setRestL=function(L){restLength=L;} this.setBaseL=function(L){baseLength=L;} this.getDistention=function(){return distention;} this.setParticleIndicesAndRestLength=function(t,n,s,i){ip=t,iq=n,restLength=s,baseLength=restLength,springConstant=i}, this.setAndComputeRestLength=function(t,n,s){ip=t,iq=n;let i=PArr[ip],e=PArr[iq];restLength=i.p0.dist(e.p0),baseLength=restLength,springConstant=s}, this.updatePass1=function(){const t=PArr[ip],n=PArr[iq],s=t.p0.x-n.p0.x,i=t.p0.y-n.p0.y,e=Math.sqrt(s*s+i*i);if(e>MINSPRD){distention=e-restLength;const p=springConstant*(distention/e),r=s*p,d=i*p;t.addF(-r,-d,1),n.addF(r,d,1)}}, this.updatePass2=function(){const t=PArr[ip],n=PArr[iq],s=t.pE.x-n.pE.x,i=t.pE.y-n.pE.y,e=Math.sqrt(s*s+i*i);if(e>MINSPRD){distention=e-restLength;const p=springConstant*(distention/e),r=s*p,d=i*p;t.addF(-r,-d,2),n.addF(r,d,2)}}, this.update=function(t){let n=PArr[ip],s=PArr[iq],i=0,e=0,p=0;if(1==t?(i=n.p0.x-s.p0.x,e=n.p0.y-s.p0.y,p=Math.sqrt(i*i+e*e)):(i=n.pE.x-s.pE.x,e=n.pE.y-s.pE.y,p=Math.sqrt(i*i+e*e)),p>MINSPRD){distention=p-restLength;const r=springConstant*(distention/p),d=i*r,a=e*r;n.addF(-d,-a,t),s.addF(d,a,t)}}; }; //CELLWALL function initContour(){imper=new ImplicitBlobmaker(255),prevZeroLocation=CV(BDM/2,0),bFirstTimeForMask=T,zeroOffsetIndex=myFrmCnt=centralSiteId=fadeInPhysics=0,X0=.2*BDM,X1=.8*BDM,Y0=.2*BDM,Y1=.8*BDM,CX=BDM/2,CY=BDM/2,sitePVecs=[],springPairings=[],sitePs=[],siteSprings=[],dlnyTris=[],uniqDlnyEs=[],niceSiteIds=[],radialTipIndices=[],CONT_MODE==CONT_MODE_IMPLICIT_SPINES?(rawBlobPVectorArrayContainer=new ImplicitPolygon,resampledBlobPolyline=new ofPolyline,resampNoiBlobPolyl=new ofPolyline,setImplicitContourProperties(),initSitePVecs_1(),delaunayTriangulate(sitePVecs),computeUniqueEdgesFromTriangulation(),subdivideOverlongDelaunayEdges(),initImplicitSpringPairings_2(),initImplicitSiteParticles_3(T,T),initImplicitSiteSprings_4(),identifyImplicitSpecialSites(),regularizeImplicitConfiguration(),checkImplicitContourBounds()):CONT_MODE==CONT_MODE_IMPLICIT_RADIAL&&(rawBlobPVectorArrayContainer=new ImplicitPolygon,resampledBlobPolyline=new ofPolyline,resampNoiBlobPolyl=new ofPolyline,setImplicitContourPropertiesRadial(),initSitePVecs_Radial(),delaunayTriangulate(sitePVecs),computeUniqueEdgesFromTriangulation(),subdivideOverlongDelaunayEdges(),initImplicitSpringPairings_Radial(),initImplicitSiteParticles_Radial(),initImplicitSiteSprings_4(),regularizeImplicitConfigurationRadial())} function checkImplicitContourBounds(){let o=1e5,e=-1e5,l=1e5,t=-1e5;if(resampNoiBlobPolyl.points.length>180)for(let i=0;i<resampNoiBlobPolyl.points.length;i++){let n=resampNoiBlobPolyl.points[i];n.x<o&&(o=n.x),n.x>e&&(e=n.x),n.y<l&&(l=n.y),n.y>t&&(t=n.y)}let i=o/BDM,n=e/BDM,B=l/BDM,r=t/BDM;(i<.1||n>.9||B<.1||r>.9)&&recoverFromBadHash()} function setImplicitContourProperties(){let t=4;StSh.cachedFieldGamma>2&&(t=5),nSpineSites=int(Cs(round(myRGauss(5.4,1)),t,7)),nSitePairs=int(Cs(round(myRGauss(3.3,1)),1,5)),centralSiteId=~~(nSpineSites/2),nSubdivsToDo=20,closenessThreshForSprings=38/128,blobContourSpringK=25/128,blobContourDamping=102/128,twist=myRGauss(0,StSh.impContourTwistStdv),bloat=myRGauss(.5,StSh.impContourBloatStdv),bendx=myRGauss(0,StSh.impContourBendxStdv),bendy=myR01()*StSh.impContourBendy,202==SHMA&&(twist=getSGauss(-.5,.5,.75,0),bloat=getSGauss(.3,.7,.9,0),bendx=getSGauss(-.25,.25,.8,0),bendy=getSGauss(0,.2,.8,-.5),myR01()<.6875&&(StSh.bIsSym=F)),unexpectedBlobSiteProbability=.08,rotationalRestoreForce=2.5,StSh.bIsSym&&(unexpectedBlobSiteProbability=0,StSh.massRandomness=0,twist*=.1,bloat=.5,bendx*=.1,bendy*=.1,StSh.edgeNoiseAmp*=.5)} function setImplicitContourPropertiesRadial(){nSpineSites=0,nSitePairs=0,centralSiteId=0,maxBloat=2,minBloat=.7,bloat=minBloat,bendy=Cs(myRGauss(0,.06),-.17,.17),bendx=.005*myRAB(-1,1),StSh.bMakePlatonicRadials&&(bendy*=.2),nSubdivsToDo=StSh.nSubdivsToDo,twist=0,imper.setBaseThresh(.84375),closenessThreshForSprings=38/128,blobContourSpringK=19/128,blobContourDamping=102/128,unexpectedBlobSiteProbability=0,rotationalRestoreForce=0,bRestoreSpineToVertical=F} function initSitePVecs_1(){let e=imper.getMaxAllowableSep();StSh.cachedFieldGamma<2&&(e=205);let t=115/128*e/BDM,s=.5*t,S=1e5;let _=0;for(;S>300&&_<3;){sitePVecs=[];for(let e=0;e<nSpineSites;e++){let t=.5,s=map(e,0,nSpineSites-1,.1,.9),S=SITE_FOR_SPRINGS_AND_BLOB,_=CV(t,s,S);sitePVecs.push(_)}let e=0;for(let S=0;S<nSitePairs;S++){let _=F;for(;!_;){let i=~~myRA(sitePVecs.length);S>0&&myR01()<.5&&(i=~~myRAB(nSpineSites,sitePVecs.length));let R=sitePVecs[i],l=t*myRAB(.75,2.5),P=Rd(myRAB(120,240)),I=R.x+l*cos(P),N=R.y+l*sin(P);if(I>.03&&I<.48&&N>.03&&N<.97){let S=PINF;for(let e=0;e<sitePVecs.length;e++){let t=sitePVecs[e],s=t.x,_=t.y,i=dist(I,N,s,_);i<S&&(S=i)}if(S>s&&S<t)if(202==SHMA||208==SHMA){let t=sqrt(.8),s=myR01()<t,S=myR01()<t;for(;!s&&!S;)s=myR01()<t,S=myR01()<t;let i=s?SITE_FOR_SPRINGS_AND_BLOB:SITE_FOR_SPRINGS_ONLY,R=S?SITE_FOR_SPRINGS_AND_BLOB:SITE_FOR_SPRINGS_ONLY;e<2?i!=SITE_FOR_SPRINGS_ONLY&&R!=SITE_FOR_SPRINGS_ONLY||e++:(i=SITE_FOR_SPRINGS_AND_BLOB,R=SITE_FOR_SPRINGS_AND_BLOB),sitePVecs.push(CV(I,N,i)),sitePVecs.push(CV(1-I,N,R)),_=T}else sitePVecs.push(CV(I,N,SITE_FOR_SPRINGS_AND_BLOB)),sitePVecs.push(CV(1-I,N,SITE_FOR_SPRINGS_AND_BLOB)),_=T}}}let i=0,R=0;for(let e=nSpineSites;e<sitePVecs.length;e++)i+=sitePVecs[e].y-.5,R++;i/=R;let l=0;for(let e=nSpineSites;e<sitePVecs.length;e++){let t=sitePVecs[e].y-.5-i;l+=t*t}l=sqrt(l/R),i=2*abs(i),i=pow(i,1.5),l=max(.001,l),S=i/l,S>10.1&&myR01()<.4&&(S=301),_++}} function initSitePVecs_Radial(){sitePVecs=[];let S=CV(.5,.5,SITE_FOR_SPRINGS_AND_BLOB);sitePVecs.push(S);let e=myR01()<.5?0:PI,a=1,t=0;StSh.nRadialArms%2==0&&(StSh.bDoWarpEvenShapeSpokeModulo&&(4==StSh.nRadialArms?a=2:6==StSh.nRadialArms&&(a=StSh.bOrientEvenShapesDifferently?3:2)),StSh.bOrientEvenShapesDifferently&&(t=PI2/(2*StSh.nRadialArms),e=t));for(let S=1;S<=StSh.nRdR;S++)for(let i=0;i<StSh.nRadialArms;i++){let s=e+HALF_PI+map(i,0,StSh.nRadialArms,0,PI2);s+=StSh.howMuchSpokeAngleWarping*sin(t+a*map(i,0,StSh.nRadialArms,0,PI2)),2==S&&StSh.nRadialArms>5&&(s+=PI2/(2*StSh.nRadialArms));let n=pow(S/StSh.nRdR,bloat),l=map(n,0,1,0,.51),h=.5+l*cos(s),R=.5+l*sin(s);h+=1e-5*myRAB(-1,1),R+=1e-5*myRAB(-1,1);let d=CV(h,R,SITE_FOR_SPRINGS_AND_BLOB);sitePVecs.push(d),S==StSh.nRdR-1&&niceSiteIds.push(sitePVecs.length-1),S==StSh.nRdR&&radialTipIndices.push(sitePVecs.length-1)}} function subdivideOverlongDelaunayEdges(){let e,s,i,t,n,l;if(CONT_MODE==CONT_MODE_IMPLICIT_SPINES&&nSpineSites%2==0){let e=centralSiteId,s=centralSiteId-1;n=(sitePVecs[s].x+sitePVecs[e].x)/2,l=(sitePVecs[s].y+sitePVecs[e].y)/2,sitePVecs.push(CV(n,l,SITE_FOR_SPRINGS_ONLY)),delaunayTriangulate(sitePVecs),computeUniqueEdgesFromTriangulation(),centralSiteId=sitePVecs.length-1}if(uniqDlnyEs.length>8){let c=0;for(let u=0;u<nSubdivsToDo;u++){let u,P,V=0,a=0;for(let n=0;n<uniqDlnyEs.length;n++){u=uniqDlnyEs[n][0],P=uniqDlnyEs[n][1],e=sitePVecs[u].x,s=sitePVecs[u].y,i=sitePVecs[P].x,t=sitePVecs[P].y;let l=dist(e,s,i,t);c+=l,l>a&&(a=l,V=n)}u=uniqDlnyEs[V][0],P=uniqDlnyEs[V][1],n=(sitePVecs[u].x+sitePVecs[P].x)/2,l=(sitePVecs[u].y+sitePVecs[P].y)/2;let S=SITE_FOR_SPRINGS_ONLY;myR01()<unexpectedBlobSiteProbability&&(S=SITE_FOR_SPRINGS_AND_BLOB),sitePVecs.push(CV(n,l,S)),delaunayTriangulate(sitePVecs),computeUniqueEdgesFromTriangulation()}}} function computeUniqueEdgesFromTriangulation(){uniqDlnyEs=[];for(let n=0;n<dlnyTris.length;n+=3){let l=dlnyTris[n+0],s=dlnyTris[n+1],u=dlnyTris[n+2],e=[];e.push(l<s?[l,s]:[s,l]),e.push(s<u?[s,u]:[u,s]),e.push(u<l?[u,l]:[l,u]);for(let n=0;n<e.length;n++){let l=e[n][0],s=e[n][1],u=F;for(let n=0;n<uniqDlnyEs.length;n++){let e=uniqDlnyEs[n],i=e[0],t=e[1];l===i&&s===t&&(u=T)}u||uniqDlnyEs.push([l,s])}}return uniqDlnyEs}