Week 7 (due Oct 15)

The readings, assignments, and projects below constitute the Week 7 Deliverables and are due before 11:59pm EDT on Saturday, October 15th:

  1. Technical Readings
  2. Looking Outwards 07 [Autolab & Blog]
  3. Assignment-07-A (Planting the Flag) [Autolab]
  4. Project-07: (Composition with Curves) [Autolab]
  5. Handin Instructions


1. Technical Readings


2. Looking Outwards 07: Information Visualization

Our Looking Outwards topic for this week is computational information visualization. We ask you to select a project in which an artist, designer or other researcher has created custom software in order to collect and/or visualize a dataset.

We particularly recommend the work of Aaron Koblin, Amanda Cox, Ben Fry & Fathom, Fernanda Viegas, Ingrid Burrington, Jen Lowe, Jer Thorp, Jonathan Harris, Kim Rees, Lev Manovich, Lisa Jevbratt, Martin Wattenberg, Moritz Stefaner, Nicholas Felton, Rachel Binx, Stamen Design, Santiago Ortiz, Nand.io, Stephanie Posavec, Wes Grubbs, or CMU’s own Chris Harrison, among others. (Many of these people also have given stimulating lecture presentations at the Eyeo Festival, which are available online.)

There are also a number of prominent blogs specifically devoted to documenting computational and interactive information visualization, including:

Identify a particular project or work which you find intriguing or inspirational. In a blog post of about 150-200 words,

  • Please discuss the project. What do you admire about it, and why do you admire these aspects of it?
  • What do you know (or what do you suppose) about the algorithms that generated the work?
  • It what ways are the creator’s artistic sensibilities manifest in the final form?
  • Link (if possible) to the work. To the best of your abilities, be sure to provide the creator’s name, title of the work, and year of creation.
  • Embed an image and/or a YouTube/Vimeo video of the project.
  • Create a descriptive caption for each image or video.
  • Label your blog post with the Categories LookingOutwards-07 and your section, e.g. SectionB.
  • REMEMBER: Also include your blog paragraph in your Autolab submission for full credit.


3. Assignment-07: Planting the Flag

In this Assignment, which should be uploaded to Autolab, you will create a random, scrolling terrain with flags at each peak. Study the stock market example from lab 7 on Tuesday since there are some similarities between that example and this assignment.

Your job is to write code which automatically plants small flags on the hills of this landscape. Here’s an example of what your flags (or trees, street signs, cell towers, etc.) might look like:

terrain

For this Assignment, how your flags look is entirely up to you. However, what is crucially important is where they are placed. You must ensure that your flags are placed at the tops of the terrain’s hills.

Here are some guidelines for your assignment:

  • You should use the noise() function to create an array of vertical coordinates that will make up the terrain. The coordinates will be spaced 5 pixels at a time across the canvas horizontally, just like the stock market example.
  • Instead of drawing a series of lines across the canvas like in the stock market example, you will need to create a green shape made up of all of the points along with (width, height) and (0, height). (HINT: Use beginShape(), vertex() calls and endShape() to create the terrain.)
  • After you draw the terrain, you should iterate (loop) through the array of coordinates, and place a flag on top of each peak. Think about what condition must be true in order to see a peak on the canvas. You do not need to test for a peak on the edges of the canvas.
  • You should write a separate function to draw the flag. You should pass into this function as arguments the x, y position of the base of the flag.
  • Once you have the terrain and flags drawn, remove the first coordinate from the array and append a new random coordinate at the end of the array. Thus, when the draw function repeats, the terrain will appear to scroll, just like the stock market tracker did.
  • Make sure that your code accesses correct indices for the array. Javascript doesn’t crash if you access an invalid location, but we will look at your code to make sure you don’t have invalid array accesses.
  • Don’t forget to comment your code, and please give attention to code style.

4. Project-07: Composition with Curves

spirograph-640x480
The Spirograph was a toy with pens and gears for drawing curve patterns.

Mathematical curves allow for unique, expressive and surprising ways of generating and controlling graphics. This open-ended Project invites you to you experiment and play with the aesthetics of curves.

  • Browse the Mathworld curves site.
  • Select a curve from the site. In a canvas no larger than 480 x 480 pixels, develop an interactive composition using this curve. Feel free to use any graphical primitives, colors, and visual strategies you wish. You can layer the curve with other elements if you wish. Play.
  • Please note that not every Mathworld curve comes with a helpful diagram or an easy-to-implement equation. We recommend selecting curves whose equations take one of the following standard forms:
    • the standard explicit form y = f(x),
    • or curves which take the parametric form y = f(t), x = g(t).
    • or curves with the polar form r = f(theta). For some easy starters, check out the Spirograph-like roulette curves.
  • View the examples below for some sample code that deals with polar and parametric curves.
  • Create a simple interaction in which the mouseX and mouseY are used to continuously govern at least one (and preferably at least two) parameters of the curve. For this purpose (see the example below) we highly recommend you use the p5.js map() and constrain() functions.
  • Your code should adhere to our style guidelines.
  • Remember to submit your code to Autolab. You do not have to submit a blog post of your code although you can if you wish.

Try clicking in the example below, to switch between an epitrochoid and a cranioid:

polar

var nPoints = 100;
var EPITROCHOID = 0; // Cartesian Parametric Form  [x=f(t), y=g(t)]
var CRANIOID = 1; // Polar explicit form   [r =f(t)]

var titles = ["1. Epitrochoid", "2. Cranioid"];
var curveMode = EPITROCHOID;


function setup() {
    createCanvas(400, 400);
    frameRate(10);
}


function draw() {
    background(255);
    
    // draw the frame
    fill(0); 
    noStroke();
    text(titles[curveMode], 20, 40);
    stroke(0);
    noFill(); 
    rect(0, 0, width-1, height-1); 
    
    // draw the curve
    push();
    translate(width / 2, height / 2);
    switch (curveMode) {
    case EPITROCHOID:
        drawEpitrochoidCurve();
        break;
    case CRANIOID:
        drawCranioidCurve();
        break;
    }
    pop();
}

//--------------------------------------------------
function drawEpitrochoidCurve() {
    // Epicycloid:
    // http://mathworld.wolfram.com/Epicycloid.html
    
    var x;
    var y;
    
    var a = 80.0;
    var b = a / 2.0;
    var h = constrain(mouseY / 8.0, 0, b);
    var ph = mouseX / 50.0;
    
    fill(255, 200, 200);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var t = map(i, 0, nPoints, 0, TWO_PI);
        
        x = (a + b) * cos(t) - h * cos(ph + t * (a + b) / b);
        y = (a + b) * sin(t) - h * sin(ph + t * (a + b) / b);
        vertex(x, y);
    }
    endShape(CLOSE);
    
}

//--------------------------------------------------
function drawCranioidCurve() {
    // http://mathworld.wolfram.com/Cranioid.html
    
    // NOTE: given a curve in the polar form  r = f(theta),
    // 1. sweep theta from 0...TWO_PI,
    // 2. then compute r as a function of theta,
    // 3. then compute x and y using the circular identity:
    //    x = r * cos(theta);
    //    y = r * sin(theta);
    
    var x;
    var y;
    var r;
    var a = 40.0;
    var b = 10.0;
    var c = 100.0;
    
    var p = constrain((mouseX / width), 0.0, 1.0);
    var q = constrain((mouseY / height), 0.0, 1.0);
    
    fill(200, 200, 255);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var t = map(i, 0, nPoints, 0, TWO_PI);
        
        // cranioid:
        r =
            a * sin(t) +
            b * sqrt(1.0 - p * sq(cos(t))) +
            c * sqrt(1.0 - q * sq(cos(t)));
        
        x = r * cos(t);
        y = r * sin(t);
        vertex(x, y);
    }
    endShape(CLOSE);
}

//--------------------------------------------------
function mousePressed() {
    curveMode = 1 - curveMode;
}

Please note that there are an infinity of different ways that you can render your curve(s)! For example, below are five different ways of rendering a circle. Also, please note that many curves on MathWorld are “open” (such as spirals and parabolas), and can’t be “closed” (like a circle); those curves are totally great and just fine too!

circles

function setup() {
    createCanvas(750, 200);
    frameRate(10);
}

function draw() {
    background(255, 200, 200);
    fill(255, 255, 255, 64);
    var nPoints = 20;
    var radius = 50;
    var separation = 125;
    
    // draw the circle normally
    push();
    translate(1*separation, height / 2);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var theta = map(i, 0, nPoints, 0, TWO_PI);
        var px = radius * cos(theta);
        var py = radius * sin(theta);
        vertex(px,py); 
        ellipse(px, py, 3,3);
    }
    endShape(CLOSE);
    pop();
    
    // draw the circle as a sequence of little elements
    push();
    translate(2*separation, height / 2);
    for (var i = 0; i < nPoints; i++) {
        var theta = map(i, 0, nPoints, 0, TWO_PI);
        var px = radius * cos(theta);
        var py = radius * sin(theta);
        rect(px - 5, py - 5, 10, 10);
    }
    pop();
    
    // draw the circle as a starburst
    push();
    translate(3 * separation, height / 2);
    for (var i = 0; i < nPoints; i++) {
        var theta = map(i, 0, nPoints, 0, TWO_PI);
        var px = radius * cos(theta);
        var py = radius * sin(theta);
        line(0, 0, px, py);
    }
    pop();
    
    // draw the circle as a wiggly circle
    push();
    
    translate(4*separation, height / 2);
    beginShape();
    for (var i = 0; i < nPoints; i++) {
        var theta = map(i, 0, nPoints, 0, TWO_PI);
        var px = radius * cos(theta);
        var py = radius * sin(theta);
        vertex(px + random(-5, 5), py + random(-5, 5));
    }
    endShape(CLOSE);
    pop();
    
    
    // draw the circle as a dotted line
    push();
    translate(5*separation, height / 2);
    var qx = 0;
    var qy = 0;
    for (var i = 0; i <= nPoints; i++) {
        var theta = map(i, 0, nPoints, 0, TWO_PI);
        var px = radius * cos(theta);
        var py = radius * sin(theta);
        if ((i % 2 == 0) & (i > 1)) {
            line(qx, qy, px, py);
        }
        qx = px;
        qy = py;
    }
    pop();
}


5. Handin and Post Your Work

  • Zip (compress) your handin-07 folder, which should contain folders containing your blog essay, assignment and project, and upload your zip file to Autolab. Be sure to use the conventional names for your folders inside the handin-07 folder: userID-07-blog, userID-07-assignment, userID-07-project.
  • Remember to post your blog on the WordPress course website with appropriate category labels so we (and students) can find your work easily.

Your zip file handin on Autolab must be submitted before Saturday, October 15th by 11:59PM EDT to be considered on time. Your blog and project posted on WordPress should be the same or similar to what you submitted in Autolab and should also be posted by the due date. (You may make minor corrections on WordPress for formatting issues.)