GarrettRauck-Project-6

sketch

//Garrett Rauck
//Section C
//grauck@andrew.cmu.edu
//Project-06-Abstract Clock

//In this clock, the hour is represented by the greyscale tone of the background,
//the minute is represented by the rotation of the line, and the second is
//represented by the inflection of the line which is a 6-bit binary representation
//of the integer value of the second.

/////////////////////////////////
// GLOBAL VARS
/////////////////////////////////
//canvas
var canvasWidth, canvasHeight;
//time
var h, m, s;
//geometry
var x = []; //x pts of line
var y = []; //y pts of line
var nBits, ptsPerBit, nPts, ptSpacing;
var bitVal, bit0Amplitude, bit1Amplitude;
var rotationAngle;
var seeTime;
var mBallSize, sBallSize, cBallSize;
//color
var cBackground, cStroke;

/////////////////////////////////
// HELPER FNS
/////////////////////////////////
function drawWave() {
    for (var i = 0; i < x.length-1; i++) {
        stroke(cStroke);
        push(); //rotation for minute
            translate(canvasWidth/2, canvasHeight/2); //translate to origin
            rotate(rotationAngle); //rotate based on current minute
            translate(-canvasWidth/2, -canvasHeight/2); //translate back to position.
            line(x[i], y[i], x[i+1], y[i+1]); //draw line
        pop();
    }
}

function drawSBall() {
    var armLength = canvasWidth/4-sBallSize/2;
    var theta = s*(TWO_PI/60) - HALF_PI;
    var cx = canvasWidth/2 + armLength*cos(theta);
    var cy = canvasHeight/2 + armLength*sin(theta);
    stroke(0);
    noFill();
    ellipse(cx, cy, sBallSize);
}

function drawMBall() {
    var armLength = canvasWidth/2-mBallSize/2;
    var theta = rotationAngle;
    var cx = canvasWidth/2 + armLength*cos(theta);
    var cy = canvasHeight/2 + armLength*sin(theta);
    noStroke();
    fill(0);
    ellipse(cx, cy, mBallSize);
}

function drawCBall() {
    noStroke();
    fill(0);
    ellipse(canvasWidth/2, canvasHeight/2, cBallSize);
}

function drawTime() {
    var h = hour()%12;
    var m = minute();
    var s = second();
    noStroke();
    fill(cStroke);
    text("" + nf(h,2,0) + ":" + nf(m,2,0) + ":" + nf(s,2,0), canvasWidth/2, 3*canvasHeight/4);
}

//adapted from fernandosavio's function on Stack Overflow
//http://stackoverflow.com/questions/9939760/how-do-i-convert-an-integer-to-binary-in-javascript
function getBinString(n){
    //return binary string for input number with specified number of digits
    return nf((n >>> 0).toString(2), nBits); 
}

function updateTime() {
    h = hour();
    m = minute();
    s = second();
}

function updatePts() {
    //clean pts lists
    x = [];
    y = [];
    //get binary string for seconds count
    binString = getBinString(s); //convert second to binary, return string
    //get x and y values for pts
    for (i = 0; i < nBits; i++) { //for each bit
        bitVal = int(binString[i]);
        for (j = 0; j < ptsPerBit; j++) { //for each pt in bit
            x.push(i*ptsPerBit*ptSpacing+j*ptSpacing); //x value
            if (bitVal == 0) {
                yMax = bit0Amplitude;
                yMin = -bit0Amplitude;
            }
            else {
                yMax = bit1Amplitude;
                yMin = -bit1Amplitude;
            }
            y.push(canvasHeight/2 + random(yMax, yMin)) //y value
        }
    }
}

function updateRotation() {
    rotationAngle = m*(TWO_PI/60) + HALF_PI;
}

function updateColors() {
    cStroke = color(h*(255/24)); // greyscale tone, hr0 = 0, hr24 = 255
    cBackground = color(255-h*(255/24)); //greyscale tone, hr0 = 255, hr24 = 0
}

function updateModel() {
    updateTime();
    updatePts();
    updateRotation();
    updateColors();
}

/////////////////////////////////
// EVENTS
/////////////////////////////////
function keyPressed() {
    if (seeTime == false) seeTime = true;
    else seeTime = false;
}
/////////////////////////////////
// RUN
/////////////////////////////////
function setup() {
    // INIT VARS
    //canvas
    canvasWidth = canvasHeight = 400;
    //time
    h = hour();
    m = minute();
    s = second();
    //geometry
    nBits = 6; //max second count will be 59, which is 111011 in binary, 6 bits
    ptsPerBit = 25; //density of "bits" represented graphically
    nPts = nBits*ptsPerBit;
    ptSpacing = canvasWidth/nPts;
    bit0Amplitude = 5;
    bit1Amplitude = 50;
    seeTime = false;
    mBallSize = 15;
    sBallSize = 8;
    cBallSize = 5;
    
    //canvas setup
    createCanvas(canvasWidth, canvasHeight);
    ellipseMode(CENTER);

    //initial list setup
    // rotateMinuteHand();
    updateModel();
}

function draw() {
    //update model
    updateModel();
    //draw background
    background(cBackground);
    //draw wave
    drawWave();
    //draw minute ball
    drawMBall();
    //draw minute ball
    drawSBall();
    //draw center ball
    // drawCBall();
    //draw actual time
    if (seeTime == true) {
        drawTime();
    }
}

The aesthetic of this clock was inspired by an exhibit by Martin Messier, which I had the chance to experience at Pittsburgh’s Wood Street Galleries over the summer. I wanted to explore creating a visual drama through the activation of a single line. I used randomness to generate “noise” in the line to give a sense of constant movement, time passing. The “bands” that form within the line change every second and are a 6-bit binary representation of the second count, from 0 to 59; the bands with the larger amplitude represent 1’s, while the bands with the smaller amplitude represent 0’s. The minute is complete when the line returns to flat, then the binary counting begins again. The minute is represented by the rotation of the line and the ball at the end, while the hour is represented by the grey-scale tone change throughout the 24-hour period–white at 00:00, black at 23:00.

Leave a Reply