Set 05 (Due 10/1)

The readings, assignments, and projects below constitute the Week 05 Deliverables and are due by 11:59pm EDT on Thursday, October 1st.

There are five parts: a Looking Outwards, 3 Autolab Assignments, and 1 Project.

In addition, please read Chapter 11 (Arrays) in GSWp5.js.


Looking Outwards 05: 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 KoblinAmanda CoxBen Fry & FathomFernanda Viegas, Giorgia Lupi, Ingrid BurringtonJen LoweJer ThorpJonathan Harris, Kim ReesLev ManovichLisa JevbrattMarcos WeskampMartin WattenbergMoritz StefanerNicholas FeltonRachel BinxStamen Design, Santiago OrtizStephan Thiel & Nand.ioStephanie PosavecWes 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 100-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 (if available).
  • Label your blog post with the Category, LookingOutwards-05.
  • Label your blog post with the Category referring to your section (e.g.GolanSectionRogerSectionARogerSectionBRogerSectionD, or RogerSectionE).

Assignment 05-A: Pie Chart 1.

This Assignment is to be submitted through Autolab. Its purpose is to practice your skills with graphics and introductory information visualization. 

The code below declares four variables, which are assumed to be globally declared. In this Assignment, you will use p5.js code to generate a pie chart which displays these values using filled arc() primitives:

var val0 = 0.30;
var val1 = 0.45;
var val2 = 0.15;
var val3 = 0.10;

Your pie chart should look something like the screenshot below. The black arc represents val0 (30% of the pie), the dark gray arc represents val1 (45% of the pie), etcetera.

You can define the colors for the pie pieces however you please, but you’ll need some solution for coloring the pieces differently. I colored each wedge with a grayscale level proportional to its start-angle. Another solution might color each wedge proportional to its index (0,1,2) if you were to count them. Another solution might color the wedges with an array of custom-selected colors.

pie-chart-simple

Now introduce the following mousePressed() code to the bottom of your program. Your pie chart should accommodate the changes automatically — so that when the user clicks the mouse, the pie chart adjusts to the new values of the four variables.

function mousePressed() {
    val0 = random(0.1, 0.3);
    val1 = random(0.1, 0.3);
    val2 = random(0.1, 0.3);
    val3 = 1.0-(val0+val1+val2);
}

Then, as per usual for all Assignments uploaded to Autolab:

  • Put the following information into comments at the top of your code: Your name; Your class section or time; Your email address, including @andrew.cmu.edu; and Assignment-05-A
  • Name your project UserID-05-a. For example, if your Andrew ID is placebo, then your project name should be placebo-05-a.
  • Zip and upload your code to Autolab, using the provided instructions. Zip your entire sketch folder. (Since you’re using our lightweight sketch template, there will be no libraries subdirectory to include.)

Assignment 05-B: Pie Chart 2.

This Assignment is to be submitted through Autolab. Its purpose is to practice your skills with graphics, introductory information visualization, and arrays. 

In this Assignment you will modify the Pie Chart you created in the previous section. At the top of your code, begin with the following two global variables: vals, which is an array of 4 numbers, and nVals, which is a number that stores the number of elements in that array (in this case, 4, clearly), which is obtained automatically using the .length property of the array. These variables replace the ones you had before (val0, val1, val2, etcetera).

var vals = [0.30, 0.45, 0.15,0.10];
var nVals = vals.length;

Now that you’ve got that working, include the following mousePressed() function in your program. DON’T WORRY about the gory details of what’s going on in this voodoo. What you do have to know is that the following code will randomize this array whenever the user clicks. It also populates the array with a random number of elements (somewhere between 3 and 8, roughly), and reassigns the nVals variable appropriately. Your Pie Chart must accommodate.

function mousePressed() {
  vals = [];
  var sum = 0;
  while (sum < 1.0) {
    var v = random(0.08, 0.38);
    sum += v = ((1.0 - (sum + v)) < 0.05) ? (1.0 - sum) : min(v, 1.0 - sum);
    vals.push(v);
  }
  nVals = vals.length;
}

Here’s what it will look like when the user clicks:

pie-anim

 

Then, as per usual for all Assignments uploaded to Autolab:

  • Put the following information into comments at the top of your code: Your name; Your class section or time; Your email address, including @andrew.cmu.edu; and Assignment-05-B
  • Name your project UserID-05-b. For example, if your Andrew ID is placebo, then your project name should be placebo-05-b.
  • Zip and upload your code to Autolab, using the provided instructions. Zip your entire sketch folder. (Since you’re using our lightweight sketch template, there will be no libraries subdirectory to include.)

Assignment 05-C: Bar Chart

This Assignment is to be submitted through Autolab. Its purpose is to practice your skills with arrays, iteration, and introductory information visualization. 

Below is a (longish) line of p5.js code. It creates a variable called presidentHeights that stores an array of 44 numbers. These numbers represent the heights of the US Presidents, in centimeters, using data from Wikipedia. (*Note that Grover Cleveland is represented twice, as the 22nd and 24th President.)

var presidentHeights = [188, 170, 189, 163, 183, 171, 185, 168, 
173, 183, 173, 173, 175, 178, 183, 193, 178, 173, 174, 183, 188, 
180, 168, 180, 170, 178, 182, 180, 183, 178, 182, 188, 175, 179, 
183, 192, 182, 183, 177, 185, 188, 188, 182, 185];

Write a p5.js program that uses a for() loop and array-access techniques to plot these numbers as a bar chart. An example of how this bar chart might appear is below.

presidents

Then, as per usual for all Assignments uploaded to Autolab:

  • Put the following information into comments at the top of your code: Your name; Your class section or time; Your email address, including @andrew.cmu.edu; and Assignment-05-C
  • Name your project UserID-05-c. For example, if your Andrew ID is placebo, then your project name should be placebo-05-c.
  • Zip and upload your code to Autolab, using the provided instructions. Zip your entire sketch folder. (Since you’re using our lightweight sketch template, there will be no libraries subdirectory to include.)

For a small BONUS, add some additional code which searches through the array for the tallest president. Render the tallest president’s bar with a differently-colored fill.


Project 05: Composition with Curves

spirograph

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 800 x 800 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 bel0w) we highly recommend you use the p5.js map() and constrain() functions.
  • When you’re done, embed your p5.js sketch in a WordPress blog post on this site, using the (usual) instructions here.
  • Ensure that your p5.js code is visible and attractively formatted in the post.
  • In your blog post, write a paragraph or two (~100-150 words) reflecting on your process and product.
  • Document your work by embedding a screenshot or two of your project in different states.
  • Label your project’s blog post with the Category Project-05-Curves.
  • Label your project’s blog post with the Category referring to your section (e.g. GolanSection, RogerSectionARogerSectionBRogerSectionD, or RogerSectionE).
  • Your code should adhere to our style guidelines.

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

polar-curves

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);
}

//--------------------------------------------------
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!

sketch

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

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();


}