Crop Circles
I was inspired by crop circles for my clock. Each node is one hour in a day. The crops in the background grow with the mouse.
sketch
/* Evan Stuhlfire
** estuhlfi@andrew.cmu.edu, section B
** Project 06: Abstract Clock */
var r = 90; // radius of center circle, noon
var deg = 360; // degrees in a circle
var nodeCount = 24; // 24 hours, each node is one hour
var c = []; // color array
var x = []; // x position of circle
var theta = []; //angle
var size = []; // diam of the circles
var defaultColor;
var tempSize = 0; // allows the nodes to grow with time
var pSize = 25;
function setup() {
createCanvas(480, 480);
background(127, 198, 164);
fillArray(); // fill arrays with start values
}
function draw() {
var thetaRotate = 40; // canvas rotation
background(127, 198, 164);
drawCrops();
// build color array
buildColorArray();
stroke(93, 115, 126);
// settings to draw circles (nodes)
push(); // save settings
translate(width/2, height/2); // reset origin to center
rotate(radians(thetaRotate)); // rotate canvas to draw at an angle
// call function to draw the nodes
drawNodes();
pop(); // restore settings
// make crops reactive to mouse location and time
pSize = mouseX/hour();
}
function drawCrops() {
var rows = width/30;
var cols = height/30;
var incr = width/16;
var s1 = width/16;
var s2 = height/16;
var len = pSize;
var a = len/4;
// loop over double for loop to add colums and rows of crops
for(var i = 0; i < rows; i++) {
for(var j = 0; j < cols; j++) {
push();
translate(s1/2, s2/2);
drawOne(len, a);
pop();
s2 += 2 * incr;
}
s1 += 2 * incr;
s2 = incr;
}
}
function drawOne(len, a) {
// function to draw on plant for crops
stroke(93, 115, 126, 60);
line(0, -a, 0, len);
line(-a, -a, 0, len/2);
line(a, -a, 0, len/2);
}
function buildColorArray() {
// set the default color
defaultColor = color(242, 245, 234);
// fill array with colors
for(var i = 0; i < x.length; i++){
if(i < 3) {
c[i] = color(93, 115, 126);
} else if(i < 6) {
c[i] = color(118, 129, 179);
} else if(i < 9) {
c[i] = color(214, 248, 214);
} else if(i < 11) {
c[i] = color(163, 213, 255);
} else if(i < 14) {
c[i] = color(250, 243, 62);
} else if (i < 16) {
c[i] = color(163, 213, 255);
} else if (i < 19) {
c[i] = color(214, 248, 214);
} else if (i < 22) {
c[i] = color(118, 129, 179);
} else if (i < 25) {
c[i] = color(93, 115, 126)
}
}
}
function fillArray() {
var angle = 30; // nodes are positioned 30 degrees apart
var angle2 = 150; // starting point for second set of nodes
var dist = 65; // nodes begin at dist from center
var offset = 1.2 // distance offset
var offset2 = .8
var minSize = 15; // can be no smaller than minSize
// fill arrays with start values
x.push((-deg/2) + 10);
theta.push(180);
size.push(r * offset2); // 80% size of center
// fill array with first 12 nodes
for(var i = 1; i < nodeCount/2; i++) {
x[i] = dist;
theta[i] = angle * i;
size[i] = max(r * i/18, minSize);
dist = dist + i * offset;
}
// push center circle into array
x.push(deg/2 - 10);
theta.push(0);
size.push(r);
dist = dist - i * offset; // undo last dist calc
// fill array with last 12 nodes
// loop backward so that decreasing i can be used to decrease size
for(i = x.length; i > 2; i--) {
x.push(dist);
theta.push(angle2);
size.push(max(r * i/22, minSize));
dist = dist - i * offset2;
angle2 -= angle;
}
// push last circle into array, midnight
x.push(0);
theta.push(0);
size.push(r * offset2); // 80% size of center
}
function drawNodes() {
var h = hour();
stroke(93, 115, 126);
// draw line behind center node so that it is behind
line(0, 0, deg/2, 0);
// draw the satellite nodes
push();
translate(x[0], 0); // reset origin to top circle
loopAndDraw(0, x.length/2, h);
// draw top midnight circle
fill(c[0]);
circle(0, 0, r * .8);
pop();
push();
translate((deg/2) -10, 0);
loopAndDraw(int(x.length/2) + 1, x.length, h);
pop();
}
function loopAndDraw(start, end, h) {
var dx;
var dy;
var current = false; // identify the current node
// iterate over arrays
for(var i = start; i < end; i++) {
dx = x[i] * cos(radians(theta[i]));
dy = x[i] * sin(radians(theta[i]));
// midnight
if(h == 0) {
h = 24;
}
// if the hour has passed or is the current hour use fill
if(i < h){
fill(c[i]);
} else if (i == h) {
current = true;
fill(c[i]);
} else {
fill(defaultColor);
}
stroke(93, 115, 126);
line(0, 0, dx, dy);
circle(dx, dy, size[i]);
if(current) {
currentHour(i, dx, dy);
}
current = false;
}
}
function currentHour(i, dx, dy) {
// add time elements to nodes to track time
// subtract to adjust for rotation of canvas
var s = second() * 6 - 140;
var m = minute() * 6 - 140;
var h = hour() * 30 + minute()/2 - 140;
fill(c[i]); // use the color stored in the array
push();
translate(dx, dy);
// make current circle bigger
tempSize = size[i] * 1.32;
circle(0, 0, tempSize);
// have a second hand orbit the current hour
if(i > 3 & i < 23) {
fill(c[i - 3]); //use previous color.
} else {
fill(defaultColor);
}
// mark hours
var hx = size[i] * .6 * cos(radians(h));
var hy = size[i] * .6 * sin(radians(h));
circle(hx, hy, tempSize * .25);
// mark minutes
var mx = size[i] * .3 * cos(radians(m));
var my = size[i] * .3 * sin(radians(m));
circle(mx, my, tempSize * .2);
// mark seconds
var armX = size[i] * .55 * cos(radians(s));
var armY = size[i] * .55 * sin(radians(s));
strokeWeight(1);
circle(armX, armY, tempSize * .15);
pop();
}