revisited my 1st turtle... here made out of one single path (just pen up/down for hidden lines)
(and its only brick if "nth" is uneven)
Log in to post a comment.
// created by florian berger (flockaroo) - 2025 // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. // one-liner brick torus Canvas.setpenopacity(.5); const turtle = new Turtle(); const nth=33; //min=4, max=100, step=.2 const nph=84; //min=4, max=200, step=.2 const Th=1.; //min=0., max=3.2, step=.01 var pa,pp,ppp=pp=pa=[0,0,0]; function walk(i) { var i2=Math.floor(i/2); var x=i%2, s=i2%2-.5; if(s>0) x=1-x; ppp=pp; pp=pa; pa=rotX(Th,mix3(getTorusPoint(i2, 50,20,nph,nth), getTorusPoint(i2+nth*x,50,20,nph,nth),.9),pa); turtle.goto(project(ppp)); turtle.pendown(); if( cross3(sub3(ppp,pa),sub3(ppp,pp))[2] * s < 0.0 ) turtle.penup(); if(i<2) turtle.penup(); // only after ppp is filled return i < nph*nth*2+2; } function getTorusPoint(i,R,r,nph,nth) { cst=CS(th=i/nth*Math.PI*2.0); csp=CS(th/nph); return[ (R+r*cst[0])*csp[0], (R+r*cst[0])*csp[1], r*cst[1] ]; } function project(p) { p[2]+=180; return [p[0]/p[2]*180.,p[1]/p[2]*180.,p[2]]; } function CS(x) { return [Math.cos(x),Math.sin(x)]; } function sub3(a,b) { return [a[0]-b[0],a[1]-b[1],a[2]-b[2]]; } function mix3(a,b,f) { for(i=0;i<3;i++) a[i]=a[i]*(1.-f)+b[i]*f; return a; } function cross3(a,b) { return [ a[1]*b[2]-b[1]*a[2], a[2]*b[0]-b[2]*a[0], a[0]*b[1]-b[0]*a[1] ]; } function rotX(ph,v) { cs=CS(ph); return [ v[0],v[1]*cs[0]+v[2]*cs[1], v[2]*cs[0]-v[1]*cs[1] ]; }