Computational Media Project Proposals

Project 1: Google and Me

 Heat map of locations I have visited

Heat map of locations I have visited

My first ICM final project idea has to do with Google’s location data that has been collected from me for the past two years. Every month I receive an email from them listing out the places I have been that month along with other location based information.

The idea for my project is to take this data and create a narrative from my personal data. The narrative could be counterfactual or more game like but I would like it to be thought provoking in in the way people look at their digital selves vs. their physical selves.

Conceptually, I’m not totally sure of the direction to take this idea and whether to make it purely data based or add other levels of interactivity and visuality. I think that adding a video element to this piece could add an interesting effect.

A few pieces of inspiration for this idea are this map by Vincze Istvan tracing places visited and this article about reading Google’s Location JSON files.

Project 2: Prison Reform and Post-Release Visualizations

My second ICM final project proposal is to create an interactive map to highlight key statistics about Prisoners and recently released inmates in The USA. Inspiration for this project was largely taken from ITP Graduate, Rebecca Ricks’s project dealing with Internet Freedom in the Arab World.

Having worked in the Prison Reform Industry, I would like to explore the efforts the industry have made and whether the impact has been as effective as expected.

A few concerns I have with this project are a lack of available data relevant to the thesis of the piece. After some research it seems that a majority of the available data does not go in depth enough to make this project accurate. The larger concern is that with the time available and the amount of research I must do I’m not sure that I could become fluent enough or knowledgable enough about the details and dynamics of this topic to make a fair case and avoid ignorant mistakes.

Pulsating Mirror

Idea:

For this week’s Computational Media assignment I iterated through multiple ideas before deciding to create a mirror that pulsates and changes color with the bass from a song. I wanted to combine both video and sound elements into this project and thought that it would be interesting to see how the live video would respond to sound. I had watched more than a few Coding Train videos about video and sound and began working off of the projects created in the videos.

A lot of the inspiration for the program came from Daniel Shiffman and his coding train videos. The main part being the use of pixel arrays, using vScale, and mapping the pixels. Initially I had planned on using the audio input function of p5’s sound library but decided to switch it to a preloaded sound. Below is a short video of the program.

After doing this initial program I feel like this would work well modified for a live music input and being projected in a club setting. As for an initial piece I think it was a success and would like to expand on it to see what other visually appealing modifications I can make to it.

Click here to try it for yourself(turn your sound on!).

And click here to the full song.

Code:

/*
ICM Homework 10/29/18, Morgan Mueller

This project takes a live video and performs image manipulations 
on it to give a few different results depending on the music being
played.

The first result is that a grayscaled video appears with minorly 
pulsating rectangles. The second is that a colored video appears
with pulsating circles.

The slider at the bottom of the screen increases the size of the 
pixels in the video

*/
let video;

let vScaleSlider1;
let vScaleSlider2;
let vScale = 16;

//load sound info
// FYI for ICM class I called this boring because the DJ's name 
//is DJ Boring
let boring;
let fft;

let slideText;

function preload() {

  // import the song
  boring = loadSound('assets/icmFinal.mp3');

}

function setup() {

  createCanvas(640, 480);
  pixelDensity(1);

  //instantiate sliders
  
  vScaleSlider1 = createSlider(0, 50, 0);
  vScaleSlider1.position(10, 500);
  
  stroke(255);
  let tempText = createElement('p','Pulsation Intensity');
    tempText.position(150, 480);

  video = createCapture(VIDEO);
  video.size(width / vScale, height / vScale);
  video.hide();

  //begin the FFT operations
  fft = new p5.FFT();
  boring.amp(0.7);
  boring.play();

  frameRate(30);

}

function draw() {
  background(51);

  //load the video's pixels
  video.loadPixels();
  loadPixels();

  //analyze the sound 
  let fftSpectrum = fft.analyze();
    //get the energy from the bass
  let boringBass = fft.getEnergy("bass");
    //map the energy from the bass 
  let bassMapped = map(boringBass, 0, 255, 0, vScale + vScaleSlider1.value());
 // console.log(boringMid);

  //iterate through the video in both x and y 
  for (let y = 0; y < video.height; y++) {
    for (let x = 0; x < video.width; x++) {
      //calculation to index through the video's size 
      let index = (video.width - x - 1 + (y * video.width)) * 4;

      //create variables to store pixel values in the video
      let r = video.pixels[index + 0];
      let g = video.pixels[index + 1];
      let b = video.pixels[index + 2];
    
      //average grayscale value of the video
      let bright = (r + g + b) / 3

      //map the brightness 
      let w = map(bright, 0, 255, 0, vScale);
            noStroke();
      
      //if the bass from the song is less than 125 use grayscale
      if (boringBass < 125) {
        fill(bright);
        rectMode(CENTER);
        rect(x * vScale, y * vScale, bassMapped , bassMapped);

        //otherwise set color
      } else {
        fill(r, g, b, random(100, 255));
        ellipseMode(CENTER);
        ellipse(x * vScale, y * vScale, bassMapped , bassMapped );

        slideText;
      }
    }
  }
  
}

Data Visualization and External APIs

The goal of week seven’s assignment was for students to use an external data source and build a sketch implementing the data.

I began thinking about possibilities for this assignment and my thoughts went directly to comparing novels by two of my favorite authors, Ernest Hemingway and Jack Kerouac. After spending some time trying to find the right API I realized that the task might be too large. So I decided to use the NYT API and see what I could find out about one of the authors then work from there. There were many more articles written by and aboutHemingway than Kerouac so I decided to create a visualization based on his writings with the NYT.

Screen Shot 2018-10-23 at 9.39.14 AM.png

Overall I found the NYT API easy to navigate and use. That along with the help of Dan Schiffman’s series 10 videos I was able to import the data I wanted and begin to analyze.

Where I ran into issues was when I realized that I couldn’t actually access the whole article in the NYT API just the main headlines. This along with the limit of 10 articles began to limit my options.

Finally, I decided to visualize the most used words in his article’s headlines as a sort of proof of concept for my larger idea. I was able to get all of the words into a dictionary and then perform the manipulations on the words to cut out unnecessary characters. Where I ran into trouble was when I tried to visualize the words I could’t figure out a way to access the dictionary to pull the most used words from. Below is the final visualization I was able to create with the words.

Screen Shot 2018-10-23 at 9.46.18 AM.png

I am planning on continuing to work on this project but due to time constraints at the moment I had to call it at creating this basic animation using words that I had to input myself.

See the Program here.

Code:

let urlOne = 'https://api.nytimes.com/svc/search/v2/articlesearch.json?q=ernest%20hemingway&begin_date=19361231&end_date=19371231';
let apiKey = '8be8b3ad946d476aafdcc023aec18d47';

let webURLOne = urlOne + '&api-key=' + apiKey;
let wordHolder;

//global array for Hemingway data
let hem = [];
//let headlines = [];
let hemWordCounts = {};

function setup() {
  createCanvas(400, 400);

  title = createElement('h1', 'Ernest Hemingway and His Most Used Words in His Written Articles').style('text-align', 'center');

  //load json files
  loadJSON(webURLOne, gotData);
  ellipseMode(CENTER);

}

function draw() {

  let mod = 0;
  background(255);
  textSize(10);
  fill(0);

  // loop through the array and create the shapes based on the
  //use of words in hemingways titles.
  for (let i = 0; i < hem.length; i++) {
    for (let j = 0; j < hem[i].length; j++) {

      if (hem[i][j] === "Madrid") {
        fill(random(hemWordCounts.hemingway));
        ellipse(random(hemWordCounts.hemingway) + 250, random(hemWordCounts.hemingway) + 100, 10 * mod, 10 * mod);
        mod++;
      } else if (hem[i][j] === "Writer") {

        fill(random(hemWordCounts.ernest), 40, hemWordCounts.war);
        rect(random(hemWordCounts.ernest) + 100, random(hemWordCounts.ernest) + 200, 10 * mod, 10 * mod);
        mod++;
      } else if (hem[i][j] === "Spain") {
        fill(random(hemWordCounts.spain), hemWordCounts.spain, 100);
        ellipse(random(hemWordCounts.spain) + 30, random(hemWordCounts.spain) + 300, 10 * mod, 10 * mod);
        mod++;
      } else if (hem[i][j] === "War") {
        fill(random(hemWordCounts.war), hemWordCounts.war * 40, random(hemWordCounts.war));
        ellipse(random(hemWordCounts.war) + 350, random(hemWordCounts.war) + 350, 10 * mod, 10 * mod);
        mod++;
      }


    }
  }

}

/*
This function goes through each value in the hem array and checks for 
the frequency of each word, assigning that word a value in the hemWordCounts object

*/
function stringCompare() {


  //console.log(hemWordCounts);

  for (i = 0; i < hem.length; i++) {
    for (j = 0; j < hem[i].length; j++) {


      wordHolder = hem[i][j].toLowerCase().trim(' ');
      // console.log(wordHolder);

      // if this word is not already a property of the wordCounts object, create it with the value of 1
      if (!hemWordCounts[wordHolder]) {
        hemWordCounts[wordHolder] = 1;
        // console.log("Added : " + wordHolder);
      } else {
        // if this word IS already a property of wordCounts, then increase its count value
        hemWordCounts[wordHolder]++;
        //print(hemWordCounts);
      }
    }

  }
  //iterates over all the values in the dictionary
  let value;
  // console.log(hemWordCounts)
  Object.keys(hemWordCounts).forEach(function(key) {
    value = hemWordCounts[key];
    //console.log(key + " : " + value);
  });

}

function gotData(data) {
  print('ready');
  let articleInfo = data.response.docs;

  //loop thrrugh the articles and assign them to array
  for (i = 0; i < articleInfo.length; i++) {

    createP(articleInfo[i].headline.main);
    //let headline = articleInfo[i].headline;
    let hemArray = articleInfo[i].headline.main.split(' ');
    //headlines.push(headline);
    hem.push(hemArray);
  }
  stringCompare();
  print(hem);
  print(hemWordCounts.spain);
}

The DOM and Style Elements

Week 6 required students to either create their own webpage using HTML, CSS, and Javascript elements. After some thought I wanted to attempt to make a page similar to the 90s type informational pages. Basically, something similar to this. I wanted to keep with the use of generative and parabolic art so I figured making an informational page about the artists that I enjoy and have some graphics I have created on there.

Planning and scheduling time to work on this assignment was a failure on my part this week so when it came to actually working with the CSS and HTML portion later on I realized that I was over my head for the time remaining. This being so I scaled back to a basic functionality project.

Here is a screenshot of the final piece:

Screen Shot 2018-10-16 at 8.37.13 AM.png

The piece ended up having two main DOM elements. The first being the checkbox on the left hand portion. This checkbox was used in the previous homework involving this graphic as well. The other was the button to invert the graphic on the right side. Full functionality of this button was not achieved.

Implementing basic CSS and HTML elements was more fairly simple and satisfying. Most of this involved using <div> classes and ids for the text. I worked within the javascript file itself to edit the DOM elements and use callbacks to get them to function properly.

Overall, I need to spend more time going over the DOM and the proper syntax for CSS and HTML. My time management skills were lacking on this project and it showed in the final product. It is easy to see the power of the DOM and all its elements and that it is something I am going to need to work on to understand better.

Here is a link to the final piece to try for yourself: link.

CODE:

Main Javascript Sketch Code including DOM creation:
/*
ICM Homework 6, 10/15/18
This weeks ICM Homework took inspiration on computer art from 
John Whitney. 
-As the user scrolls their mouse across the 
screen, the number of lines being created from the moving 
objects increases.

-When the user clicks the screen the shapes invert

-Finally, the checkbox at the top left of the screen the shape
changes from a line to a rectangle.

*/
let t = 0;
let divOne;
let divTwo;
let divThree;
let button;
//object to translate the start point of the lines 
//and set basic functionality

let trans = {
  numLines: 25,
  x: 2,
  y: 2,
};

function setup() {
  createCanvas(500, 500);
  background(0);

  button = createButton("Invert");
  button.style("float", "right");
  button.style("background-color", "pink")

  button.style("padding", "10px");
  //button.style("border","10px");
  button.mousePressed(mouseIsPressed);

  //create a checkbox for changing the shape to rectangles
  rectCheckbox = createCheckbox('rectangles', false);
  rectCheckbox.changed(parabolicEffect);
  rectCheckbox.style("float", "left");
  rectCheckbox.style("background-color", "pink")
  rectCheckbox.style("color", "black")

  divOne = select("#divOne");
  divOne.html("Geometric Poetry and Similar Inspiration");
  divTwo = select("#divTwo");
  divTwo.html("Artists Eusebio Sempere and John Whitney were pioneers of two different kinds of generated art.");
  divThree = select("#divThree");
  divThree.html("This piece was inspired by John Whitney and is the first in a series of generated graphic works I will be doing");
}

function draw() {
  background(0, 0, 0);

  strokeWeight(4);
  //move parabolic shape to center of screen
  translate(width / trans.x, height / trans.y);
  //call to parabolic effect function
  parabolicEffect();
  // increase the value being pushed into the function  
  t += .3;
}

function invert(t) {
  return true;

}

//parabolic function x
function x(t) {
  if (mouseIsPressed) {
    return -sin(t / 10) * 100 + -sin(t / 10) * 100;
  } else {

    return sin(t / 10) * 100 + sin(t / 10) * 100;
  }
}
//parabolic function y
function y(t) {
  if (mouseIsPressed) {
    for (let i = 0; i < 20; i++) {
      return cos(t / 10) * i;
    }
  } else {
    return -cos(t / 10) * 20;
  }
}

//parabolic function x1
function x1(t) {

  if (mouseIsPressed) {
    return -sin(t / 10) * 100 + -cos(t / 10) * 100;
  } else {
    return sin(t / 10) * 100 + cos(t / 10) * 100;
  }
}

//parabolic function y1
function y1(t) {
  if (mouseIsPressed) {
    return cos(t / 20) * 200 + sin(t / 10) * 100;
  } else {
    return -cos(t / 20) * 200 + -sin(t / 10) * 100;
  }
}

/*
The parabolicEffect function creates the shapes at different 
points mapped to the various parabolic functions.
There is an offset of i or j added to each shape that 
give speed and tracing effects

*/
function parabolicEffect() {

  //map the cursor movement to the number of lines on screen
  let deltaX = map(mouseX, 0, width, 0, trans.numLines);

  //check to see if the rectangle checkbox is true or not
  if (rectCheckbox.checked()) {

    //create the rectangle shape and add in the offset of i 
    for (let i = 0; i < deltaX; i++) {
      noFill();
      stroke(111, 195, 223, 50 + (i * 4));
      rect(x(t + i), y(t + i), x1(t + i), y1(t + i));
      rect(x1(t + i), y(t + i), x(t + i), y1(t + i));

    }
    //create the rectangle shape and add in the offset of j
    for (let j = 5; j < deltaX * 2; j++) {
      stroke(218, 112, 214, 50 + (j * 4));
      rect(x(t - j), y(t - j), x1(t - j), y1(t - j));
      rect(x(t - j), y1(t - j), x1(t - j), y(t - j));

    }
  } else {

    //create the lines and add in the offset of i
    for (let i = 0; i < deltaX; i++) {
      noFill();
      stroke(111, 195, 223, 50 + (i * 4));
      line(x(t + i), y(t + i), x1(t + i), y1(t + i));
      line(x1(t + i), y(t + i), x(t + i), y1(t + i));
    }

    //create the lines and add in the offset of j
    for (let j = 5; j < deltaX * 2; j++) {
            noFill();
      stroke(218, 112, 214, 50 + (j * 4));
      line(x(t - j), y(t - j), x1(t - j), y1(t - j));
      line(x(t - j), y1(t - j), x1(t - j), y(t - j));

    }
  }
}

HTML Code:
<!DOCTYPE html>
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.dom.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js"></script>
  <link rel="stylesheet" type="text/css" href="style.css">
  <meta charset="utf-8" />

</head>

<body>
  <script src="parabolicEffects.js"></script>
  <script src="sketch.js"></script>
  <div id="divOne">Header text</div>
  <div class="theDiv">
  <par id="divTwo">Subtext</par>
  <par id="divThree">Subtext</par>
  </div>
  <br>
</body>
</html>

CSS Code:
html, body {
  margin: 0;
  padding-bottom: 0;
}
    #divOne {
  text-align: center;
  color: white;
  background-color:gray;
  padding: 5px;
  font-size: 30px;
}
    .theDiv {
  text-align: left;
  color: turquoise;
  padding: 5px;
  font-size: 20px;
}

More Animation Fun

This week, I wasn’t really sure what I felt like making for my Computational Media assignment. I spent hours watching coding train videos about everything from flow to genetic algorithms but nothing felt right. I began doing some more research for inspiration and came across this animation. I decided to use this animation as a possibility for my final outcome.

Thinking about how the person created the concaving lines, it seemed that they used a series of points that acted as lines and then used sinusoidal functions to have them converge in the middle of each line. I spent some time trying to work this out for myself but realized that I had not begun to code anything. This being so I decided to just start programming and see where it went.

 Initial animation

Initial animation

After working from this initial animation I decided to try to work with the circle pattern I created in the center. The point of this homework assignment was to work with arrays, classes, and objects so I knew that I had to keep those constraints in mind. I moved the lines being created into a new class and began restructuring the rest of my program around it.

Below are two videos of the final version of the assignment.

The first video shows the animation show the rotation around -pi/8 while the second shows the rotation around pi/4. This change is triggered when the mouse is pressed.

This program was a lot more playing around with numbers and angles than having a set plan for the program. I plan to work on this type of animation further on and work to move past my own limitations in terms of my understanding classes and array management.

You can see the final sketch here: sketch

CODE

/*
ICM HW 5 - Morgan Mueller
This homework takes  the basic idea of last weeks assignment and works 
//with sinusoids again. Using arrays, a class, and objects I created 
//an animation that takes a set of lines and rotates them around 
//an axis in a motion that is somewhat hypnotic
*/


let lines = [];
let t = 0;

function setup() {
  createCanvas(400, 400);

  //create 25 line objecs and add them to the arrya
  for (i = 0; i < 25; i++) {
    lines[i] = new Lines(i);
  }
}

function draw() {
  background(0, 10);
  translate(width / 2, height / 2);
  stroke(255, 20);
  //create the effect on all objects in the array
  for (i = 1; i < 25; i++) {
    lines[i].effect(t);
  }

  //increment the speed 
  t += 0.05;
}

class Lines {

  //constructor function
  constructor(numLines, speed, angRotate) {
    this.numLines = numLines;
    this.speed = speed;
    this.angRotate = angRotate;
  }

  //run function
  run() {

    this.effect();

  }

  // The effect function contains the code for drawing the lines and 
  //performing the calculations on rotate 
  effect(speed) {

    //sets the rotation depening on if the mouse is pressed
    if (mouseIsPressed) {
      this.angRotate = PI / 4;
    } else {
      this.angRotate = -PI / 8;

    }

    //draws the lines and rotates the positions.
    line(this.x(speed * this.numLines), this.y(speed * this.numLines), 0, height / 2);

    //not totally sure why this function causes the randomness that it does
    rotate(this.angRotate * cos(speed * 0.1) + this.angRotate);

    line(this.x1(speed * this.numLines), this.y1(speed * this.numLines), 0, height / 2);

  }


  /*
  this group of functions
  */

  x(t) {

    return sin(t / 30) * 100;

  }

  y(t) {

    return cos(t / 30) * 100;

  }

  x1(t) {

    return sin(t / 50) * 50;

  }

  y1(t) {

    return cos(t / 50) * 50;

  }

}

Reimagining John Whitney

The Idea:

I have enjoyed minimalist animation and fractal art for a long time. For this week’s Computational Media assignment I wanted to try and meet the assignment parameters and implement some form of fractal or simplistic generative art.

I began by trying a couple different fractal patterns that incorporated circles but was not happy with any of the results achieved. After some research I discovered the works of John Whitney Sr. One movie of his, in particular, inspired me to try to work with his style of graphics in P5.js.

Beyond how great the visuals are in this video, it’s even more interesting to learn how the people creating the graphics were able to do so with the technology available at the time.

I began to mess around with parametric equations and researching methods of creating this type of graphic generatively. After some time I found a piece of code by Alexander Miller that helped me to work out some of the problems with my process.

From there I played around, for an ungodly amount of time, with sin and cos functions to get a shape I thought was worth working with. Below are a few clips of the sketch running.

I don’t consider this piece finished but the extra functionality and animation I want to add to it is out of the scope for what this assignment required.

The Code for the project largely involved playing around with sinusoidal functions and trying to figure out ways to make the sketch more interactive. I think that I could have done some things more efficiently but overall I think the project turned out well. You can see the code below.

Link to completed sketch: Here

Code:

/*

ICM Homework 4, 10/01/18

This weeks ICM Homework took inspiration on computer art from 
John Whitney. 

-As the user scrolls their mouse across the 
screen, the number of lines being created from the moving 
objects increases.

-When the user clicks the screen the shapes invert

-Finally, the checkbox at the top left of the screen the shape
changes from a line to a rectangle.

*/


let t = 0;

//object to translate the start point of the lines 
//and set basic functionality

let trans = {
  numLines: 25,
  x: 2,
  y: 2,
};

function setup() {
  createCanvas(600, 600);
  background(0);


  //create a checkbox for changing the shape to rectangles
  rectCheckbox = createCheckbox('rectangles', false);
  rectCheckbox.changed(parabolicEffect);
  rectCheckbox.position(10, 20);


}

function draw() {
  background(0, 0, 0);

  strokeWeight(4);


  //move parabolic shape to center of screen
  translate(width / trans.x, height / trans.y);

  //text for checkbox
  textSize(12);
  fill(255);
  text('Rectangles', -290, -280);

  //call to parabolic effect function
  parabolicEffect();

  // increase the value being pushed into the function  
  t += .3;


}



//parabolic function x
function x(t) {
  if (mouseIsPressed) {
    return -sin(t / 10) * 100 + -sin(t / 10) * 100;
  } else {

    return sin(t / 10) * 100 + sin(t / 10) * 100;
  }
}


//parabolic function y
function y(t) {
  if (mouseIsPressed) {
    for (let i = 0; i < 20; i++) {
      return cos(t / 10) * i;
    }
  } else {
    return -cos(t / 10) * 20;

  }
}

//parabolic function x1
function x1(t) {

  if (mouseIsPressed) {
    return -sin(t / 10) * 100 + -cos(t / 10) * 100;
  } else {
    return sin(t / 10) * 100 + cos(t / 10) * 100;

  }
}

//parabolic function y1
function y1(t) {
  if (mouseIsPressed) {
    return cos(t / 20) * 200 + sin(t / 10) * 100;
  } else {
    return -cos(t / 20) * 200 + -sin(t / 10) * 100;

  }


}
/*
The parabolicEffect function creates the shapes at different 
points mapped to the various parabolic functions.
There is an offset of i or j added to each shape that 
give speed and tracing effects

*/
function parabolicEffect() {


  //map the cursor movement to the number of lines on screen
  let deltaX = map(mouseX, 0, width, 0, trans.numLines);

  //check to see if the rectangle checkbox is true or not
  if (rectCheckbox.checked()) {

    //create the rectangle shape and add in the offset of i 
    for (let i = 0; i < deltaX; i++) {
      noFill();
      stroke(111, 195, 223, 50 + (i * 4));
      rect(x(t + i), y(t + i), x1(t + i), y1(t + i));
      rect(x1(t + i), y(t + i), x(t + i), y1(t + i));

    }
    //create the rectangle shape and add in the offset of j
    for (let j = 5; j < deltaX * 2; j++) {
      stroke(218, 112, 214, 50 + (j * 4));
      rect(x(t - j), y(t - j), x1(t - j), y1(t - j));
      rect(x(t - j), y1(t - j), x1(t - j), y(t - j));

    }
  } else {

    //create the lines and add in the offset of i
    for (let i = 0; i < deltaX; i++) {
      noFill();
      stroke(111, 195, 223, 50 + (i * 4));
      line(x(t + i), y(t + i), x1(t + i), y1(t + i));
      line(x1(t + i), y(t + i), x(t + i), y1(t + i));

    }

    //create the lines and add in the offset of j
    for (let j = 5; j < deltaX * 2; j++) {
      //  fill(218, 112, 214, 50);
      stroke(218, 112, 214, 50 + (j * 4));
      line(x(t - j), y(t - j), x1(t - j), y1(t - j));
      line(x(t - j), y1(t - j), x1(t - j), y(t - j));

    }
  }
}

Vegas Lights

Trial of Errors

After binge watching videos about Reaction Diffusion and Perlin Noise I started to brainstorm ideas for implementing one or the other in the third ICM Homework. I spent more time than I care to admit trying to figure out ways to use them within the realm of my abilities. I finally scaled back my efforts to using bezier curves to make swooping fan patterns controlled by a slider, like the rough sketch below.

 Initial fanning idea.

Initial fanning idea.

Again, I spent way too long trying to get the bezier curves to act in a manner that would be algorithmically scalable. Lack of time and patience caused me to, again, abandon this idea and move on to just using straight lines. Having one set on the top of the frame and another on the bottom. I then began having difficulties making the lines fan out in the way I wanted. The screenshot below is one of the patterns created.

Finally, I decided to switch up my thinking again and make use of the bottom two fanned out sections but then to add more interactivity to the project. The gif below shows the final outcome of my multiple failed attempts at making something I liked.

The final project included a few different elements of algorithmic design, including the shapes and expanding lines. I was able to create the slider with the help of Veronica Alfaro. The Elvis face was added at the end because it felt like the graphic wasn’t quite finished without something in the center portion and all of the rainbow colors felt very Vegas-esqe to me. This homework was a challenge for me in terms of accepting that my programming skills are more limited than I thought they were and that it is necessary for me to spend time analyzing and really understanding the algorithms behind the generative art I enjoy.

Code

/*
ICM Homework 3 
Vegas Lights 
9/24/18
*/
let padding = 50;
let slider;
let img;

//preload function to import the image
function preload() {

  img = loadImage('images/elv.png');
}

function setup() {
  createCanvas(400, 400);
  slider = padding;
  rectMode(CENTER);
}

function draw() {
  background(255);
  noFill();
  
  //create the slider object
  sliderPos = map(slider, padding, width - padding, 0, 20);

  fill(255);
  
  //nested for loops to draw the cirlces and squares in the background
  for (let j = 0; j <= width; j += 20) {
    for (let k = 0; k <= height; k += 20) {
      //let x = random(10) * 100;

      if (sliderPos < 20) {

        ellipse(j, k, 10, 10);
        rect(j + 10, k + 10, 5, 5);
      }
    }

    //make elvis appear as the slider is dragged
    if (sliderPos < 20 && sliderPos > 1) {
     image(img, width / 2 - img.width / 4, height / 2 - img.height / 2,      (sliderPos * 6), (sliderPos * 6));
    }

    //draw fanning lines at the bottom of scree
    for (let i = 0; i <= 50; i++) {
      stroke(random(255), random(255), random(255));
      if (sliderPos <= 20) {

        line(width / 2, height, 0, sliderPos / 2 * i);
        line(width / 2, height, width, sliderPos / 2 * i);
      }

    }


    // if the slider is < 50% then the lines begin to 
    //converge on each other, when > 50% they expand to this point
    
    //code to draw slider at bottom of screen
    fill(255);
    line(padding, height - padding, width - padding, height - padding);
    ellipse(CENTER);
    ellipse(slider, height - padding, 20, 20);

    //set the slider to the mouseX position as long as it is
    //within the correct set of bounds.
    if (mouseIsPressed && mouseY >= height - padding - 10 &&
      mouseY <= height - padding + 10) {
      if (mouseX >= padding && mouseX <= width - padding) {
        slider = mouseX;
      }
    }

  }
}

Trippy Solar System

Ideation

For the second Computational Media homework we were tasked with either reconfiguring our first homework to add more degrees of functionality; i.e. animated elements, less hardcoded numbers, and elements that change over time. We could also choose to do something completely different.

I chose to make a solar system with different interactive elements. I decided to do this in part because I had been thinking about the talk Carter Emmart had given to the applications class the week before.

The initial idea for the project was to have the planets in the solar system revolve around the sun with their own, different, gravitational pulls. I also wanted to have asteroids randomly shoot around the screen and have some other effects in place. Implementing some of these ideas was more time consuming than I had initially thought they would be. The most difficult part was creating the different gravitational pulls on the planets. So after a lot of trial and error I decided to go for a less realistic galaxy system and make a trippy one.

Below you can see the end product:

As shown above, the solar system has planets that rotate around the sun. Each planet has a random starting angle and orbit so that they start in different positions and rotate on a slightly different axis each time the program is run. After deciding against using different gravitational pulls I researched best practices for rotation around a set point. This piece of code on open processing helped in my decision to use basic sinusoidal functions to create the rotation. I decided to not show the rings immediately but rather give the user the option of showing the rings if they wanted to, by using a checkbox.

The most spastic part of the program is the “asteroids” flashing around and the “flares” being emitted in a circular pattern from the Sun. I spent some time trying different methods of creating asteroids that would shoot around the screen but after playing around with translation and push()/pop() I found that I enjoyed the way the ring looked when it expanded and shrank around the sun. After adding some effects to change the shape and color randomly it seemed appropriate to call them solar flares. Finally, I added a little space ship that follows

After the Fact

I thought the homework was a good introduction to various p5.js fundamentals, including push(), pop(), translate, and preset variables. This homework also brought to light some limitations I have right now with my thought process and programming abilities and fundamentals that I need to refresh or get better at. Given more time and patience I would have tried harder to implement the gravitational pull and added some extra cosmic type effects. Overall, I thought was enjoyable to play with the code and make something that was interesting; even if the outcome was different than I had imagined it would be.

Code:

    /*
  * Morgan Mueller 
  * ICM Homework 2
  * 09/17/18
  *Trippy Solar System
  */

    let sunX,sunY,sunW,sunH;//sun 
    let ringX,ringY;
    let  planetX,planetY;
    let asteroidX, asteroidY;
    let asteroidLocX, asteroidLocY;
    //spaceship variables
    let spaceShipX = 0;
  let spaceShipY = 0;
    //let changeX, changeY;
    let easing = .05;
  //let mouseLocX, mouseLocY;
    let angle1, angle2, angle3, angle4, angle5;
    let speed = .01; //speed of planets
    let asteroidSpeed = 1;
    let c = 250; //center constant
    let radius = 50;
    let mercOrbit, venOrbit, earOrbit, marOrbit, jupOrbit; //each    planet's orbit
    let ringCheckbox;
    let sunR;

    function setup() {
  createCanvas(500, 500);
  ellipseMode(CENTER);
    sunX=width/2;
  sunY=height/2;
  //planet's orbit is a random number between 0 and 10
  mercOrbit=random(8);
  venOrbit=random(15),
  earOrbit=random(18), 
  marOrbit=random(20), 
  jupOrbit=random(25);
    
  //
  asteroidLocX=random(width / 2);
  asteroidLocY=random(height / 2);
    asteroidX = random(5, 10);
  asteroidY = random(5, 10);
    
    //Checkbox to display the orbital rings when clicked
  fill(255);
  ringCheckbox =createCheckbox('rings',false);
  ringCheckbox.changed(showRings);
  ringCheckbox.position(10,20);
  
  //dictates the starting point of each planet
  angle1 = random(-2,3);
  angle2 = random(-5.6,0.6);
  angle3 = (-0.2,0.9);
  angle4 = (-3.14,3.14);
    angle5 = (0,6.28);

  //random r value for sun bursts  
  sunR = random(220,255);  

}

 //planet rings
  function showRings(){
    if (ringCheckbox.checked()){
    stroke(255);
    noFill();
    ellipse(sunX,sunY,ringX,ringY);
    ellipse(sunX,sunY,ringX*1.75,ringY*1.75);
    ellipse(sunX,sunY,ringX*2.5,ringY*2.5);
      ellipse(sunX,sunY,ringX*3.25,ringY*3.25);
      ellipse(sunX,sunY,ringX*4,ringY*4);
  }
  else{

  }
}

//sun size
sunW=60;
sunH=60;

//planet size
ringX=100;
ringY=100;

function draw() {
      background(0);

  //display rings function called
  showRings();
  
  /*
  drawPlanet function.
  This function creates a planet at a base location
  with an initial speed and angle.
  When called the user can modify the location and orbit rotation.
  */
  function drawPlanet(cx,orbit,angle,radius,speed1,ringW,ringH){
  planetX = c + mercOrbit  + sin(angle) * radius;
  planetY = c + mercOrbit + cos(angle) * radius;
  angle = angle+speed;
  ellipse(planetX,planetY,ringW*1.75,ringH*1.75);

  }
  

  //sun and sun spots
  noStroke();
  fill(253, 184, 19);
  ellipse(sunX,sunY,sunW,sunH);
  fill(255, 153, 0);
  ellipse(sunX  +10,sunY + 5,10,10);
  fill(255, 0, 0);
  ellipse(sunX - 10,sunY - 10,12,12);
  fill(0);
  ellipse(sunX - 10,sunY - 10, 7,7);



  //mercury
  fill(213, 210, 209);
  stroke(0);
  drawPlanet(250,mercOrbit,angle1,radius,speed,11,11);
  angle1=angle1+speed;
  
  //Venus
  fill(139,160,130);
  stroke(0);
  drawPlanet(250,venOrbit,angle2,radius*1.5,speed,14,14);
    angle2=angle2+speed;

  //Earth
  fill(125,68,29);
  drawPlanet(250,venOrbit,angle3,radius*2.3,speed,17,17);
  angle3=angle3+speed;
  
  //Mars
  fill(193,68,14);
  drawPlanet(250,venOrbit,angle4,radius*3.25,speed,15,15);
  angle4=angle4+speed;
  
  //Jupiter
    fill(216,202,157);
  drawPlanet(250,venOrbit,angle5,radius*4.3,speed,20,20);
  angle5=angle5+speed;
  
   //sun flare
    fill(sunR,random(255),random(255));
    noStroke();
  asteroidLocX = asteroidLocX + asteroidSpeed;
  asteroidLocY = asteroidLocY + asteroidSpeed;
  
  //reset asteroid speed if its off screen
  if(asteroidLocX > width || asteroidLocX < 0 || asteroidLocY > height || asteroidLocY < 0){
    asteroidSpeed = random(-5,5);
    
  }
  
  if(asteroidLocX > width || asteroidLocX < 0){
    asteroidLocX = width / 2;  
  }
  
  if(asteroidLocY > height || asteroidLocY < 0){
    asteroidLocY = height / 2;  
  }
  
  //creates the ring of solar flares
  push();
  translate(width / 2, height / 2);
  for(let i = 0; i < 500; i++){
    push();
    rotate(i * -10);
    let randX = random(2,10);
    let randY = random(2,10);
    ellipse(asteroidLocX,asteroidLocY,randX,randY);
    pop();
   }
   pop();
  
  //spaceship
 let mouseLocX = mouseX;
 let mouseLocY = mouseY;

 let  changeX = mouseLocX - spaceShipX;
 let  changeY   = mouseLocY - spaceShipY;
  spaceShipX = spaceShipX + changeX * easing;
  spaceShipY = spaceShipY + changeY * easing;
     fill(255,165,0);
   rect(spaceShipX-7,spaceShipY+9,16,3);
   rect(spaceShipX-7,spaceShipY+3,16,3);

     fill(255, 0, 0);
     rect(spaceShipX-5,spaceShipY+2,15,5);
   rect(spaceShipX-5,spaceShipY+8,15,5);
    fill(0,0,255);
        rect(spaceShipX,spaceShipY,50,15,0,100,100,0);
    
    //spaceship name
    fill(255);
    text("Enterprise",spaceShipX+3,spaceShipY+10);
  

  
  //for loop that makes asteroids appear
    for(j = 20; j<25; j++){
        fill(255);
    ellipse(random(width),random(height),10,10);
  }
  
  //text for rings
  textSize(10);
  fill(255);
  text('Display Rings',12,20);

 }

My Interest in Computation

For me, computation relates to my interest in a variety of ways. Having worked with Non profits and Mission Driven organizations I believe that computation can help to make a positive impact on the world. I also believe that computation can help people become more aware of injustice going on in the world on both global and local scales. On a different note my love of visual media and art has brought me to learn about the seemingly endless possibilities of art and media that will cause people to think differently and more progressively.

This term I hope to make projects that push my own creativity but also help me to think about the ways media and computing can be used to positively affect people.

A few projects I love that ended up being integral in me ending up at ITP:

The first is by Jer Thorpe, in which he developed the algorithm used to place the names on the 9/11 Memorial using processing. After reading about the algorithm and the reasoning behind it, I realized that I had no idea that computation could be used in design like that.

https://www.scientificamerican.com/article/september-11-memorial/

Another project that showed me how creative computing could produce social change, or at least help people think differently and be more aware of how technology can be used was by a few ITP alumni. The project called “The Outrage Machine” was an examination of mass surveillance. The piece was just as much performance art and political statement as it was computation which made me begin to think of work I could create in a similar vein.

ICM Homework 1 (Sudo-Portrait)

The first Computational Media assignment began with the decision to attempt to draw a portrait of a classmate. My expose to programming is expansive but coming from a background based around firmware and more low level programming I knew that flexing my creative coding muscles was going to be tedious. Along with that drawing abilities are minimal at best so I knew that sketching out the portrait by hand first wouldn’t be the best way to go about the process. Instead I used illustrator to attempt to make a trace for the portrait to get an idea of the shapes to use in p5. Unfortunately I had difficulty getting the trace work fully as well (My Illustrator skills could use a tune up).

 Attempted Image Trace for Portrait

Attempted Image Trace for Portrait

After the initial sketch and tracing portion I decided that it would be best to dive into the p5 drawing. I used coolors to decide what color scheme would be best for my vision. I also realized midway through that I liked a less realistic portrait and then go for my own interpretation of the subject.

 Sudo-Portrait of a Classmate

Sudo-Portrait of a Classmate

This assignment ended up being a great refresher on basic spacial functions. Many of the mistakes I made while going through the drawing process could have been avoidable if I had done more planning and sketching before just diving into the coding. Overall, though, I am happy with the way the project turned out.

Below you can find my code for the assignment:

function setup() {
 createCanvas(600, 600);
 background(32,178,170);
}
function draw() {
 //shirt and body
smooth();
stroke(123,45,38);
fill(123,45,38);
triangle(270,270,300,320,240,300);
triangle(300,320,360,290,380,340);
//shoulders and arms
quad(250,250,160,290, 120, 470, 210,470,240,300);
//line(420,260, 505, 320); ,380,320
quad(210,470,320,470,380,340,240,300); //cuts off part of collar
//fixed part of shirt
strokeJoin(MITER);
 quad(315, 350,370,260,420,290);
triangle(420,290, 450,308, 315,350);
quad(452,312, 460,470, 320,470);
 quad(452,312, 320,330, 320,455,400,460);
triangle(297,320,370,261,370,305);
rect(325,450,10,15);
stroke(194,197,198);
fill(194,197,198);
triangle(320,300,360,320,370,261); //left shirt collar
 triangle(270,270,240,300,255,250); // right shirt collar
//shirt details
stroke(0,0,0);
strokeWeight(2.5);
line(295,317, 290,470);
 line(310,317, 305,470);
//buttons
ellipse(302, 330, 5,5);
 ellipse(301, 360, 5,5);
 ellipse(300, 390, 5,5);
 ellipse(299, 420, 5,5);
 ellipse(298, 450, 5,5);
//face
stroke(234,199,169);
fill(234,199,169);
triangle(255,249,368,260,300,320);
quad(255,249,368,260,340,210,280,210);
 ellipse(310,160, 110, 170,60);
//Hair(beard)
fill(183,72,42);
stroke(183,72,42);
quad(250,170,250,190,280,250,315,250,300,190);
quad(370,170,370,190,340,250,305,250,330,190);
triangle(250,169,370,169,305,250);
//Hair(top of head)
ellipse(310,83,40,20);
triangle(290,80, 260,110,290,100);
 triangle(300,75, 260,100,320,100);
 triangle(335,75, 290,110,350,100);
//Face details
stroke(234,199,169);
fill(234,199,169);
quad(265,160,260,185,265,195,340,195);
quad(350,160,355,185,350,195,265,160);
triangle(265,195, 300,195,280,215);
triangle(320,195,350,195,335,215);
rect(320,175, 30,20);
fill(249,158,144);
ellipse(310,220,25,5);
//freckles
fill(249,101,14);
stroke(249,101,14);
ellipse(275,195,1,1);
ellipse(285,195,1,1);
ellipse(280,185,1,1);
ellipse(330,195,1,1);
ellipse(340,195,1,1);
ellipse(335,185,1,1);
//ears
fill(234,199,169);
stroke(249,158,144);
arc(250,160,20,37,-90,PI,CHORD);
arc(370,160,20,37,-90,PI,CHORD);
fill(109,111,112);
stroke(109,111,112);
ellipse(252,164,8,12);
ellipse(369,164,8,12);
//eyes and nose
 fill(255);
stroke(255);
rect(275, 155, 20, 10, 50,50,0,0);
rect(320, 155, 20, 10, 50,50,0,0);
fill(11,122,117);
stroke(11,122,117);
ellipse(280,160,7,7);
stroke(194,197,198);
fill(194,197,198);
ellipse(280,160,2,2);
 stroke(11,122,117);
 ellipse(325,160,7,7);
 stroke(194,197,198);
 fill(194,197,198);
 ellipse(325,160,2,2);
fill(25,83,95);
stroke(249,158,144);
strokeWeight(2.5);
line(303,170,302,190);
line(314,170,315,190);
strokeWeight(4);
line(295,255,285,290);
line(315,255,320,275);
//glasses
strokeWeight(2.5);
noFill();
stroke(0);
ellipse(285,160,33,28);
ellipse(331,160,33,28);
line(269,160,250,140);
line(347,160,365,140);
line(300,160,315,160);
//eyebrows
fill(183,72,42);
stroke(183,72,42);
rect(271, 138, 25, 5, 20,20,20,20);
rect(320, 138, 25, 5, 20,20,20,20);
}