× Project Code

boolean showTriangles = true, showSpirals = true, showDots = true; Draggables p; Point[] points; float radius = 10; float phi = 1.618034; float angle; int n = 360, red = 229, green = 190, blue = 100; float da = TWO_PI/n; float timer = 0; int maxPoints = 30; void setup() { size(800, 800); points = new Point[2]; points[0] = new Point( width*0.1, height*0.5, color(red, green, blue), radius); points[1] = new Point( width*0.4, height*0.5, color(red, green, blue), radius); p = new Draggables(points, radius); angle = PI/2; } void draw() { background(0); if (showDots) { p.redraw(); } p.update(); if (showTriangles) { stroke(red, green, blue); line(p.getPoint(0).x, p.getPoint(0).y, p.getPoint(1).x, p.getPoint(1).y); } PVector[] t = new PVector[maxPoints]; t[0] = new PVector(p.getPoint(0).x, p.getPoint(0).y); t[1] = new PVector(p.getPoint(1).x, p.getPoint(1).y); float[] di = new float[maxPoints]; di[0] = dist(t[0].x, t[0].y, t[1].x, t[1].y); for (int i = 1; i < maxPoints; i++) { di[i] = di[i-1]/phi; } float[] ang = new float[maxPoints-1]; float deltaAng = atan2(t[1].y-t[0].y, t[1].x-t[0].x); ang[0] = angle; for (int i = 1; i < ang.length; i++) { ang[i] = ang[i-1] + ang[0]-deltaAng; } for (int i = 2; i < maxPoints; i++) { t[i] = new PVector(t[i-1].x + di[i-1]*cos(ang[i-2]-(i-1)*108.0/360*TWO_PI), t[i-1].y + di[i-1]*sin(ang[i-2]-(i-1)*108.0/360*TWO_PI)); } strokeWeight(2); for (int i = 0; i < maxPoints; i++) { if (showTriangles) { drawTriangles(i, t, di, ang); } if (showSpirals) { drawSpirals(i, t, di, ang, deltaAng); } } updateValues(deltaAng); } void mouseReleased() { p.release(); } void keyPressed() { if (key == 't') { showTriangles = !showTriangles; } if (key == 's') { showSpirals = !showSpirals; } if (key == 'd') { showDots = !showDots; } } void drawSpirals(int i, PVector[] q, float[] di, float[] ang, float deltaAng) { if (0 < i && i < maxPoints-3) { float tempAng = atan2(q[i-1].y - q[i+2].y, q[i-1].x - q[i+2].x); float ang108 = 108.0/360*TWO_PI, a; drawArc(q[i+2], di[i+1]*phi, tempAng, ang108); if (deltaAng < 0) { drawArc(q[i+2], di[i+1]*phi, tempAng - ang108, ang108); } else { drawArc(q[i+2], di[i+1]*phi, tempAng - ang108, ang108); } } } void drawTriangles(int i, PVector[] q, float[] di, float[] ang) { if (i > 0) { stroke(red, green, blue); line(q[i-1].x, q[i-1].y, q[i].x, q[i].y); } if (i < maxPoints-2) { fill(red, green, blue, 80); noStroke(); beginShape(); vertex(q[i].x, q[i].y); vertex(q[i+1].x, q[i+1].y); vertex(q[i+2].x, q[i+2].y); endShape(CLOSE); } } void drawArc(PVector mid, float r, float start, float v) { int vMax = 10; float dv = v/(vMax-1); stroke(183, 31, 31); noFill(); beginShape(); curveVertex(mid.x + r*cos(start), mid.y+ r*sin(start)); for (int i = 0; i < vMax; i++) { curveVertex(mid.x + r*cos(start + dv*i), mid.y+ r*sin(start + dv*i)); } curveVertex(mid.x + r*cos(start + v), mid.y+ r*sin(start + v)); endShape(); fill(183, 31, 31, 80); noStroke(); beginShape(); curveVertex(mid.x + r*cos(start), mid.y+ r*sin(start)); for (int i = 0; i < vMax; i++) { curveVertex(mid.x + r*cos(start + dv*i), mid.y+ r*sin(start + dv*i)); } curveVertex(mid.x + r*cos(start + v), mid.y+ r*sin(start + v)); curveVertex(mid.x + r*cos(start + v), mid.y+ r*sin(start + v)); endShape(); } void updateValues(float deltaAng) { int degree = round(((deltaAng+angle)%TWO_PI)*180/PI); if ((degree+36)%72 != 0 ) { angle += da; } else { if (timer == 0) { timer = 1; } else if (timer < 100) { timer ++; } else { timer = 0; angle = (angle + da)% TWO_PI; } } } /**************************************************************************/ /* Class to draw a set of draggable points. When dragging a point, no */ /* other point should be dragged. When point 1 is dragged onto point 2, */ /* point 2 should be partly hidden. Next time the mouse hits the area of */ /* collision, point 1 should be dragged. */ /**************************************************************************/ class Draggables { Point[] draggables; //A stack of indeces. The index of a dragged point is moved to the last position in stack. //Draw points in stack-order, update move in reverse stack-order int[] stack; int draggedPoint = -1; float radius; Draggables(Point[] p, float radius){ draggables = new Point[p.length]; stack = new int[p.length]; for (int i=0; i<p.length; i++) { draggables[i] = new Point(p[i].x, p[i].y, p[i].fColor, p[i].r); stack[i] = i; } this.radius = radius; } float getX(int i) { return draggables[i].x; } float getY(int i) { return draggables[i].y; } Point getPoint(int i) { return draggables[i]; } void setX(float x, int i) { draggables[i].x =x; } void setY(float y, int i) { draggables[i].y =y; } int size() { return draggables.length; } void update() { float mx = mouseX; float my = mouseY; if (mousePressed) { for (int k=(stack.length-1); k>-1; k--) { int i = stack[k]; if (draggedPoint == -1) { if (dist(draggables[i].x, draggables[i].y, mx, my)<=radius) { draggedPoint = i; moveToLast(k); } } else if (mx >0 && my>0 && mx<width && my<(height-38-radius)) { draggables[draggedPoint].x = mx; draggables[draggedPoint].y = my; } } } } void redraw() { for (int i=0; i<draggables.length; i++) { draggables[stack[i]].redraw(); } } void release() { draggedPoint = -1; } //place the dragged index at the last position in the stack of indeces void moveToLast(int i) { int temp = stack[i]; for (int k=i; k<(stack.length-1); k++) { stack[k] = stack[k+1]; } stack[stack.length-1] = temp; } } class Point { float x, y, r; color fColor; Point(float x, float y, color fColor, float r) { this.x = x; this.y = y; this.r = r; this.fColor = fColor; } void redraw() { noStroke(); ellipseMode(RADIUS); fill(this.fColor); ellipse(x, y, r, r); } }