This is an attempt to reproduce an effect from the demo "Intrinsic Gravity" by Still.
The triangles' positions lead your eye towards certain lines while their rotations lead to others.
Log in to post a comment.
// created by Andrew Lamoureux (andrewl) - 2019 // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. Canvas.setpenopacity(1); const turtle = new Turtle(); function walk(i) { nspokes = 22 ndots = 41 spacing = 5 spin_speed = 1.6 tri_rot = .78 ysizer = 7 fbradius = 150 for(spoke=0; spoke<nspokes; ++spoke) { angle = (spoke/nspokes)*2*Math.PI for(ri=3; ri<ndots; ++ri) { r = ri * (fbradius/ndots) /* increase angle as r increases (spiral effect) */ angle_ = angle + spin_speed*r/fbradius*Math.PI var [x,y] = [r*Math.cos(angle_), r*Math.sin(angle_)] trisize = 1 + (r/150)*5 + ysizer*((y+100)/200)**2 triangle(x, y, trisize, tri_rot*angle) } } triangle(0, 0, 10, 0) return false; } /* scan-line polygon fill WARNNG: basic implementation, no optimizations here */ function polyfill(points) { lines = [] scan_start = 100 scan_end = -100 for(i=0; i<points.length; i++) { /* collect lines from points */ p = points[i] q = points[(i+1)%points.length] r = points[(i+2)%points.length] if(p[1] == q[1]) continue /* no horizontals */ m = null /* slope */ if(p[0] != q[0]) m = (1.0*q[1]-p[1])/(q[0]-p[0]) eflag = false /* endpoint flag */ if((q[1]-p[1] > 0) != (q[1]-r[1] >= 0)) eflag = true var [ylo, yhi] = [p[1], q[1]] /* y's span */ if(ylo > yhi) [ylo,yhi]=[yhi,ylo] scan_start = Math.min(scan_start, ylo) scan_end = Math.max(scan_end, yhi) lines.push({'ylo':ylo,'yhi':yhi,'p':p,'q':q,'m':m,'eflag':eflag}) } for(y=scan_start; y<=scan_end; y+=.15) { /* scan */ intersects = [] /* collect intersections */ for(l of lines) { if(y<l['ylo'] || y>l['yhi']) continue x = null if(l['m']==null) x = l['p'][0] else x = (y-l['p'][1])/l['m'] + l['p'][0] if(! (y==l['q'][1] && l['eflag']) ) intersects.push(x) } intersects.sort() /* draw intersections */ for(i=0; i<intersects.length; i+=2) { x0 = intersects[i] x1 = intersects[i+1] line(x0,y,x1,y) } } } function rotate(p, angle) { [x,y] = [p[0], p[1]] //console.log('rotate('+x+','+y+')') return [x*Math.cos(angle) - y*Math.sin(angle), y*Math.cos(angle) + x*Math.sin(angle)] } function shift(point, x, y) { return [point[0]+x, point[1]+y] } function line(x0,y0,x1,y1) { //console.log('line('+x0+','+y0+','+x1+','+y1+')') turtle.penup() turtle.goto(x0,y0) turtle.pendown() turtle.goto(x1,y1) } function triangle(x, y, side, angle) { //console.log('triangle('+x+','+y+')') dx = side/2.0 dya = side * (1/Math.sqrt(3)) dyb = side * (1/(2*Math.sqrt(3))) var p0 = [0, -dya] var p1 = [side/2.0, dyb] var p2 = [-side/2.0, dyb] var [p0,p1,p2] = [rotate(p0,angle), rotate(p1,angle), rotate(p2,angle)] var [p0,p1,p2] = [shift(p0,x,y), shift(p1,x,y), shift(p2,x,y)] polyfill([p0,p1,p2]) }