// LineFollow2D // dxjones @ gmail.com class Vector { float x, y; Vector(float _x, float _y) { x = _x; y = _y; } void set(float _x, float _y) { x = _x; y = _y; } } final int N = 120; Vector[] p = new Vector[N]; Vector[] v = new Vector[N]; void setup() { size(600,400); frameRate(60); smooth(); p = new Vector[N]; v = new Vector[N]; initialize(); } void initialize() { int i; for (i = 0 ; i < N ; ++i) { p[i] = new Vector(random(0,width), random(0,height)); v[i] = new Vector(random(-1,1), random(-1,1)); } } void randomize() { int i; for (i = 0 ; i < N ; ++i) { p[i].set(random(0,width), random(0,height)); v[i].set(random(-1,1), random(-1,1)); } } void mousePressed() { randomize(); } void normalize() { int i; float mx, my; mx = 0; my = 0; for (i = 0 ; i < N ; ++i) { mx += p[i].x; my += p[i].y; } mx /= (float) N; my /= (float) N; for (i = 0 ; i < N ; ++i) { p[i].x -= mx; p[i].y -= my; } mx = 0; my = 0; for (i = 0 ; i < N ; ++i) { if (abs(p[i].x) > mx) { mx = abs(p[i].x); } if (abs(p[i].y) > my) { my = abs(p[i].y); } } mx = 0.95 * (width/2) / mx; my = 0.95 * (height/2) / my; for (i = 0 ; i < N ; ++i) { p[i].x = width/2 + mx * p[i].x; p[i].y = height/2 + my * p[i].y; } } void draw() { int i, j; background(0); normalize(); for (i = 0 ; i < N ; ++i) { j = (i+1) % N; v[i].x = 0.83 * v[i].x + 0.0125 * (p[j].x - p[i].x); v[i].y = 0.83 * v[i].y + 0.0125 * (p[j].y - p[i].y); } for (i = 0 ; i < N ; ++i) { j = (i+1) % N; p[i].x += v[i].x; p[i].y += v[i].y; } strokeWeight(4); stroke(255,0,0); noFill(); for (i = 0 ; i < N ; ++i) { j = (i+1) % N; line(p[i].x,p[i].y, p[j].x,p[j].y); } noStroke(); fill(255); for (i = 0 ; i < N ; ++i) { ellipse(p[i].x,p[i].y,12,12); } }