//Selina Lee
//Section C
//selinal@andrew.cmu.edu
//Final Project
var mapPic;//variable for image of map
var backPic; //background picture (collage of running in Pittsburgh)
var skiboStart; //turtle functions at different start poitns
//this one starts in front of skibo
var ovalStart; //this one occurs after reaching the schenley oval
var scaleX = 0.4; //scale down width wise from original canvas which is
// 480 / 1200
var scaleY = 0.6; //scale down height wise from original canvas whic is
// 480 / 800
//arrays containing the points to draw run routes with turtle functions
//route titled beechwood (x and y points placed into arrays)
var beechX = [760, 789, 778, 808, 859, 895, 968, 980, 1014, 984, 1024, 950,
809, 737, 733];
var beechY = [277, 262, 244, 225, 221, 242, 242, 325, 324, 175, 111, 125, 189,
195, 237];
//route titled the point
var pointX = [740, 726, 719, 697, 687, 695, 677, 632, 592, 568, 560, 464, 402,
268, 219, 35, 38, 61, 104, 148, 154, 201, 162, 183, 234, 418, 463, 502, 602,
672, 695, 732, 722, 735, 733, 745];
var pointY = [295, 298, 312, 315, 327, 353, 372, 378, 365, 389, 418, 361, 356,
379, 370, 279, 262, 258, 242, 226, 255, 244, 314, 328, 327, 338, 352, 355, 261,
235, 236, 234, 258, 261, 270, 275];
//route titled trader joe's
var traderX = [760, 789, 778, 808, 859, 859, 968, 1059, 1064, 1062, 1098, 964,
943, 718, 731, 737, 733, 744, 734];
var traderY = [277, 262, 244, 225, 221, 242, 242, 221, 212, 204, 138, 24, 12,
103, 147, 194, 234, 239, 270];
//route titled tranquil
var tranquilX = [760, 789, 778, 808, 859, 895, 968, 980, 1049, 1087, 1089, 1111,
1126, 1138, 1161, 1174, 1169, 1178, 1170, 1178, 1160, 1159, 1139, 1068, 1060,
1059, 1139, 1068, 1060, 1059, 968, 895, 859, 808, 778];
var tranquilY = [277, 262, 244, 225, 221, 242, 242, 325, 324, 338, 345, 343,
354, 346, 362, 350, 339, 322, 301, 287, 260, 234, 217, 191, 208, 218, 245, 242,
221, 225, 244];
//warmup route to work out location titled one-eight
var eightX = [743, 732, 715, 700, 686, 695, 687, 678, 687, 674, 673, 677, 671,
683, 683, 692, 759, 782, 787, 778, 761, 721];
var eightY = [291, 295, 310, 315, 328, 349, 365, 379, 394, 397, 406, 411, 421,
436, 444, 449, 403, 398, 392, 385, 391, 417];
//schenley oval route
var ovalX = [714, 720, 737, 746, 757, 764, 760, 751, 741, 720, 715];
var ovalY = [411, 415, 407, 396, 393, 389, 381, 379, 379, 395, 406];
//regular cool down route from oval
var coolX = [737, 778, 789, 794, 801, 789, 776, 733, 719, 709, 709, 713, 714,
723, 740, 746];
var coolY = [408, 387, 387, 392, 386, 378, 374, 358, 355, 342, 328, 321, 311,
308, 296, 274];
//other cool down route from oval called ten minute
var tenX = [724, 696, 684, 689, 688, 704, 690, 712, 707, 693, 696, 690, 694,
724, 731, 741];
var tenY = [420, 439, 426, 416, 407, 404, 385, 379, 372, 363, 351, 326, 318,
306, 294, 293];
//run titled southside
var southX = [745, 730, 740, 727, 673, 602, 499, 465, 418, 407, 409, 431, 477,
486, 496, 523, 576, 602, 632, 680, 675, 682, 686, 699, 761, 782, 795, 784, 733,
712, 694, 691, 694, 724, 731, 739];
var southY = [274, 271, 235, 233, 236, 262, 352, 354, 335, 417, 454, 460, 472,
463, 455, 477, 437, 460, 469, 460, 443, 435, 448, 448, 400, 395, 382, 376, 357,
350, 340, 323, 315, 304, 293, 293];
var counter = 0;// counter variable to count down differet routes shown
var backColR = 0; //background R value variable
var backColG = 0; //background G value variable
var backColB = 0; //background B value variable
var backColT = 270; //background opacity value
var colorArr = []; //empty array to contain color and placement creations
//see function fillInColorArray
var colors = ["black", "yellow"]; //colors to take
function preload() {
mapPic = loadImage("https://i.imgur.com/zIVTSXM.jpg"); //map preload
backPic = loadImage("https://i.imgur.com/vzuo6YG.jpg"); //background image
//preload
}
function setup() {
createCanvas(480, 480);
image(backPic, 0, 0, map.width, map.height);//drawing map picture
//used early on in project to find array points
/*if(mouseIsPressed) {
print(mouseX, mouseY);
}*/
skiboStart = makeTurtle(747 * scaleX, 274 * scaleY); //draws turtles that
//start and end at Skibo
ovalStart = makeTurtle(712 * scaleX, 410 * scaleY); // turtles that start at
//Schenley Oval
//I missed the criteria to scale the canvas to 480, so I used the scale
//variable to reduce the size of my points
for(var i = 0; i < beechX.length; i++) {
beechX[i] *= scaleX;
beechY[i] *= scaleY;
}
for(var i = 0; i < pointX.length; i++) {
pointX[i] *= scaleX;
pointY[i] *= scaleY;
}
for(var i = 0; i < traderX.length; i++) {
traderX[i] *= scaleX;
traderY[i] *= scaleY;
}
for(var i = 0; i < tranquilX.length; i++) {
tranquilX[i] *= scaleX;
tranquilY[i] *= scaleY;
}
for(var i = 0; i < ovalX.length; i++) {
ovalX[i] *= scaleX;
ovalY[i] *= scaleY;
}
for(var i = 0; i < eightX.length; i++) {
eightX[i] *= scaleX;
eightY[i] *= scaleY;
}
for(var i = 0; i < coolX.length; i++) {
coolX[i] *= scaleX;
coolY[i] *= scaleY;
}
for(var i = 0; i < tenX.length; i++) {
tenX[i] *= scaleX;
tenY[i] *= scaleY;
}
for(var i = 0; i < southX.length; i++) {
southX[i] *= scaleX;
southY[i] *= scaleY;
}
}
function mouseClicked() {
counter++; //when mouse is clicked, create a counter to increment
//every time
backColT = backColT - 20; //with every mouse click, the background
//transparency gets more opaque
}
function draw() {
image(backPic, 0, 0, map.width, map.height);//underlying image to be
//revealed
background(backColR, backColG, backColB, backColT); //background color
//based on variable values
fill(255); //prints directions on how to interact with piece ==>
//continuous clicking reveals the different routes and visuals and black
//and white background
text("Click on the canvas to reveal my running log in Pittsburgh!", 30,
30);
if(mouseIsPressed) {
print(mouseX, mouseY); //helps find position of mouse on map to draw
//turtle before translation
}
translate(-8, 50); //center the marks with these units
//BEECHWOOD ROUTE: 5 MILES
if (counter == 0 || counter >= 9) { //the start of the counter and when
//the mouse clicks through all slides, this will be shown
for(var i = 0; i < beechX.length; i++) { //iterate through route
//arrays to get points. The array length should be the same for
//X and Y because I manually clicked on the screen to get place
//numbers
skiboStart.setColor(color(255, 0, 255)); //magenta turtle
skiboStart.penDown(); //start drawing
skiboStart.goto(beechX[i], beechY[i]); //drawing beechwood route
//based on points in beechX and beechY array
skiboStart.penUp();//stop drawing
noStroke();
fill(150, 0, 255, 80); //light, see-through, purple rectangles
//these rectangles are drawn based on the values of the points
//and the differences of the points on the path
rect(beechX[i - 1], beechY[i - 1], beechX[i - 1] - beechX[i],
beechY[i - 1] - beechY[i]);
rect(beechX[i], beechY[i], beechX[i] - beechX[i],
beechY[i - 1] - beechY[i]);
rect(beechX[i - 1], beechY[i], beechX[i] - beechX[i - 1],
beechY[i] - beechY[i - 1]);
rect(beechX[i], beechY[i], beechX[i] - beechX[i - 1],
beechY[i] - beechY[i - 1]);
}
}
//THE POINT: 9.25 MILES
fillInColorArr(0); //see function fillInColorArr
//this starts the function at place 0
if (counter == 1 || counter >= 9) { //next shown visual from counter
//(all visuals are shown at the end of the list)
for(var i = 0; i < pointX.length; i++) {
backColB = 255; //background will be light blue
backColG = 200;
backColR = 100;
skiboStart.setColor(colorArr[i]); //the color of each
//turtle move is based on fillInColorArr (while it
//iterates, a value is placed into the color function out
//of the colorArr array)
skiboStart.setWeight(5); //thicker line
skiboStart.penDown();
skiboStart.goto(pointX[i], pointY[i]);
skiboStart.penUp();
noFill();
stroke(255, 255, 0); //yellow thin lines
strokeWeight(1);
beginShape(); //curves based off of Pittsburgh bridges
//and the curve vertex control points are based on
//position between selected points so that some
//abstraction is visualized from the data
curveVertex(pointX[i], pointY[i] + 30);
curveVertex(pointX[i], pointY[i] + 30);
curveVertex((pointX[i] + pointX[i - 1]) / 2,
(pointY[i - 1] + pointY[i]) / 4);
curveVertex((pointX[i - 1] + pointX[i]) / 2,
(pointY[i - 1] + pointY[i]) / 4);
curveVertex(pointX[i - 1], pointY[i - 1] + 30);
curveVertex(pointX[i - 1], pointY[i - 1] + 30);
endShape();
}
}
//TRADER JOE'S: 5.5 MILES
if(counter == 2 || counter >= 9) {
for(var i = 0; i < traderX.length; i++) {
backColR = 255; //light purple background
backColG = 120;
backColB = 200;
skiboStart.setColor(color(200, 255, 0)); //green-yellow
skiboStart.setWeight(1)
skiboStart.penDown();
skiboStart.goto(traderX[i], traderY[i]);
skiboStart.penUp();
for(var j = 0; j < 5; j++) { //make 5 of this command
noFill();
strokeWeight(2);
stroke(255, 200, 0); //orange bullseye design at
//each turtle point
ellipse(traderX[i], traderY[i], 10 * j, 10 * j);
}
}
}
//TRANQUIL: 6.3 MILES
if(counter == 3 || counter >= 9) {
for(var i = 0; i < tranquilX.length; i++) {
backColB = 75; //dark blu background
backColG = 0;
backColR = 0;
skiboStart.setColor(color(200, 255, 0)); //green-yellow
skiboStart.setWeight(1);
skiboStart.goto(tranquilX[i], tranquilY[i]);
skiboStart.penUp();
fill(255, 230, 0, 60); //see-through orange-yellow
//circles drawn at each tranquil turtle point
//one on top of the other like an eye
ellipse(tranquilX[i], tranquilY[i], 20, 20);
ellipse(tranquilX[i], tranquilY[i], 8, 8);
fill(150, 255, 100, 100); //see-through green
noStroke();
//these ellipses were drawn towards the top right of the turtle
//route as a conglomeration
ellipse(tranquilX[i] + 60, tranquilY[i] - 20, 50, 50);
fill(100, 255, 220, 100); //see-through blue-green
ellipse(tranquilX[i] + 50, tranquilY[i] - 40, 40, 40);
}
}
//ONE EIGHT- WARMUP ROUTE TO SCHENLEY OVAL VIA THE BRIDAL PATH: 1.8 MILES
if(counter == 4 || counter >= 9) {
for(var i = 0; i < eightX.length; i++) {
backColR = 255; //yellow background
backColG = 255;
backColB = 0;
skiboStart.setColor(color(255, 0, 0)); //red turtle
skiboStart.setWeight(1);
skiboStart.penDown();
skiboStart.goto(eightX[i], eightY[i]);
skiboStart.penUp();
fill(255, 50, 75, 20); //fill transparent red
var maxX = max(eightX); //maximum value in x value array
var minX = min(eightX); //minimum value in x value array
var midX = (maxX + minX) / 2; //average of max and min value in
//x array
var maxY = max(eightY); //maximum value in y array
var minY = min(eightY); //minimum value in y array
var midY = (maxY + minY) / 2; //avverage of max and min value in
//y array
var curveX1; //first control x value point
var curveY1; //first control y value point
var curveX2; //control two x value point
var curveY2; //control two y value point
if(eightX[i] < midX) { //if the turtle point is to the left of the
//"center"
curveX1 = eightX[i] + 10; //if using bezier curve function, the
//first control point goes towards the middle
curveX2 = eightX[i] - 10; //then the second control point goes
//away from the center
} else { //to the right of "center"
curveX1 = eightX[i] - 10; //towards middle
curveX2 = eightX[i] + 10; //away from center
}
if(eightY[i] < midY) { //if the turtle point is to the top of the
//middle of the route loop
curveY1 = eightY[i] + 10; //the first control point goes down
//towards the center
curveY2 = eightY[i] - 10; //second goes away from
} else { //to bottom of route
curveY1 = eightY[i] - 10; //first control point towards middle
curveY2 = eightY[i] + 10; //away from middle
}
stroke(255, 100, 100, 200); //red
strokeWeight(0.5);
//the curves meet at a midpoint
bezier(eightX[i], eightY[i], curveX1, curveY1, curveX2, curveY2,
midX, midY);
bezier(eightX[i], eightY[i], curveX2, curveY2, curveX1, curveY1,
midX, midY);
}
}
//OVAL LOOP = .625 MILES
if(counter == 5 || counter >= 9) {
for(var i = 0; i < ovalX.length; i++) {
stroke(255, 100, 255, 70); //light magenta
strokeWeight(40); //very thick line
//used a line so the turtle function does not get confused
//and hide the movement created visually.
//this line makes the same route as the turtle function
line(ovalX[i], ovalY[i], ovalX[i - 1], ovalY[i - 1]);
stroke(100, 150, 255, 120); //overlapping light blue lines
//on top of oval lap so you can still see the purple underneath
strokeWeight(15);
line(ovalX[i - 1], ovalY[i - 1], ovalX[i], ovalY[i]);
stroke(255, 200, 0); //orange turtle on top of laps
strokeWeight(3);
line(ovalX[i], ovalY[i], ovalX[i - 1], ovalY[i - 1]);
}
}
//COOL DOWN ROUTE FROM SCHENLEY OVAL VIA PANTHER HOLLOW TRAIL: 1.3 MILES
if(counter == 6 || counter >= 9) {
for(var i = 0; i < coolX.length; i++) {
ovalStart.setColor(color(0, 100, 255));
ovalStart.setWeight(1);
ovalStart.penDown();
ovalStart.goto(coolX[i], coolY[i]);
ovalStart.penUp();
fill(100, 150, 255, 30);
var maxX = max(coolX); //maximum value in x value array
var minX = min(coolX); //minimum value in x value array
var midX = (maxX + minX) / 2; //average of max and min value in
//x array
var maxY = max(coolY); //maximum value in y array
var minY = min(coolY); //minimum value in y array
var midY = (maxY + minY) / 2; //avverage of max and min value in
//y array
var curveX1; //first control x value point
var curveY1; //first control y value point
var curveX2; //control two x value point
var curveY2; //control two y value point
if(coolX[i] < midX) { //if the turtle point is to the left of the
//"center"
curveX1 = coolX[i] + 10; //if using bezier curve function, the
//first control point goes towards the middle
curveX2 = coolX[i] - 10; //then the second control point goes
//away from the center
} else { //to the right of "center"
curveX1 = coolX[i] - 10; //towards middle
curveX2 = coolX[i] + 10; //away from center
}
if(coolY[i] < midY) { //if the turtle point is to the top of the
//middle of the route loop
curveY1 = coolY[i] + 10; //the first control point goes down
//towards the center
curveY2 = coolY[i] - 10; //second goes away from
} else { //to bottom of route
curveY1 = coolY[i] - 10; //first control point towards middle
curveY2 = coolY[i] + 10; //away from middle
}
stroke(0, 200, 255, 200);
strokeWeight(.5);
bezier(coolX[i], coolY[i], curveX1, curveY1, curveX2, curveY2, midX,
midY);
bezier(coolX[i], coolY[i], curveX2, curveY2, curveX1, curveY1, midX,
midY);
}
}
//TEN MINUTE COOL DOWN: 1.1 MILES
if(counter == 7 || counter >= 9) {
for(var i = 0; i < tenX.length; i++) {
ovalStart.setColor(color(0, 150, 255));
ovalStart.penDown();
ovalStart.goto(tenX[i], tenY[i]);
ovalStart.penUp();
fill(20, 20, 255, 30);
var maxX = max(tenX); //maximum value in x value array
var minX = min(tenX); //minimum value in x value array
var midX = (maxX + minX) / 2; //average of max and min value in
//x array
var maxY = max(tenY); //maximum value in y array
var minY = min(tenY); //minimum value in y array
var midY = (maxY + minY) / 2; //avverage of max and min value in
//y array
var curveX1; //first control x value point
var curveY1; //first control y value point
var curveX2; //control two x value point
var curveY2; //control two y value point
if(tenX[i] < midX) { //if the turtle point is to the left of the
//"center"
curveX1 = tenX[i] + 10; //if using bezier curve function, the
//first control point goes towards the middle
curveX2 = tenX[i] - 10; //then the second control point goes
//away from the center
} else { //to the right of "center"
curveX1 = tenX[i] - 10; //towards middle
curveX2 = tenX[i] + 10; //away from center
}
if(tenY[i] < midY) { //if the turtle point is to the top of the
//middle of the route loop
curveY1 = tenY[i] + 10; //the first control point goes down
//towards the center
curveY2 = tenY[i] - 10; //second goes away from
} else { //to bottom of route
curveY1 = tenY[i] - 10; //first control point towards middle
curveY2 = tenY[i] + 10; //away from middle
}
stroke(0, 150, 255, 200);
strokeWeight(0.5);
bezier(tenX[i], tenY[i], curveX1, curveY1, curveX2, curveY2, midX,
midY);
bezier(tenX[i], tenY[i], curveX2, curveY2, curveX1, curveY1, midX,
midY);
}
}
//SOUTHSIDE: 6.6 MILES
if(counter == 8 || counter >= 9) {
for(var i = 0; i < southX.length; i++) {
backColG = 255; //green background
backColR = 50;
backColB = 100;
skiboStart.setColor(color(255, 0, 255));
skiboStart.penDown();
skiboStart.goto(southX[i], southY[i]);
skiboStart.penUp();
stroke(255, 50, 100); //red
fill(255, 120, 50, 50); //transparent red orange
//lines drawn to create turtle skeleton
line(southX[i], southY[i], southX[i] * 0.9, southY[i] + 20);
line(southX[i] * 0.9, southY[i] + 20, southX[i - 1] * 0.9,
southY[i - 1] + 20);
line(southX[i - 1] * 0.9, southY[i - 1] + 20, southX[i] * 0.85,
southY[i] - 30);
line(southX[i] * 0.85, southY[i] - 30, southX[i - 1] * 0.85,
southY[i - 1] - 30);
line(southX[i] * 0.85, southY[i] - 30, 180, 330);
noStroke();
//triangles based off of parameters to create line skeleton
triangle(southX[i], southY[i], southX[i] * 0.9, southY[i] + 20,
southX[i - 1] * 0.9, southY[i - 1] + 20);
triangle(southX[i - 1] * 0.9, southY[i - 1] + 20,
southX[i] * 0.85, southY[i] - 30, 180, 330)
}
}
}
function fillInColorArr(filledSoFar) { //recursive function to change color
//every action of the turtle
if(filledSoFar == 0) { //if nothing has been drawn yet, leave the array
colorArr = [];
colorArr.push(colors[0]); //push the colors from colors array into
//colorArr so that they can be used and start from 0 which is "black"
var currentFillNumber = filledSoFar + 1; //counts which property has
//recieved a color to use
fillInColorArr(currentFillNumber); //fill in this area with the color
//corresponding to the placement of the turtle in its start point in
//its array
} else if(filledSoFar >= pointX.length) {
return;
} else { //if the paremeters that have been filled so far do not exceed
//the length of the point array, do the same as if nothing has been
//drawn yet and give the parameter a color to use
colorArr.push(colors[filledSoFar % colors.length]);
var currentFillNumber = filledSoFar + 1;
fillInColorArr(currentFillNumber);
}
}
function turtleLeft(d) {
this.angle -= d;
}
function turtleRight(d) {
this.angle += d;
}
function turtleForward(p) {
var rad = radians(this.angle);
var newx = this.x + cos(rad) * p;
var newy = this.y + sin(rad) * p;
this.goto(newx, newy);
}
function turtleBack(p) {
this.forward(-p);
}
function turtlePenDown() {
this.penIsDown = true;
}
function turtlePenUp() {
this.penIsDown = false;
}
function turtleGoTo(x, y) {
if (this.penIsDown) {
stroke(this.color);
strokeWeight(this.weight);
line(this.x, this.y, x, y);
}
this.x = x;
this.y = y;
}
function turtleDistTo(x, y) {
return sqrt(sq(this.x - x) + sq(this.y - y));
}
function turtleAngleTo(x, y) {
var absAngle = degrees(atan2(y - this.y, x - this.x));
var angle = ((absAngle - this.angle) + 360) % 360.0;
return angle;
}
function turtleTurnToward(x, y, d) {
var angle = this.angleTo(x, y);
if (angle < 180) {
this.angle += d;
} else {
this.angle -= d;
}
}
function turtleSetColor(c) {
this.color = c;
}
function turtleSetWeight(w) {
this.weight = w;
}
function turtleFace(angle) {
this.angle = angle;
}
function makeTurtle(tx, ty) {
var turtle = {x: tx, y: ty,
angle: 0.0,
penIsDown: true,
color: color(128),
weight: 1,
left: turtleLeft, right: turtleRight,
forward: turtleForward, back: turtleBack,
penDown: turtlePenDown, penUp: turtlePenUp,
goto: turtleGoTo, angleto: turtleAngleTo,
turnToward: turtleTurnToward,
distanceTo: turtleDistTo, angleTo: turtleAngleTo,
setColor: turtleSetColor, setWeight: turtleSetWeight,
face: turtleFace};
return turtle;
}
Author: Selina Lee
selinal-Looking-Outwards-12
The World’s Greatest Bar Chat by Roz Dimon
http://www.rozdimon.com/digital-paintings?lightbox=i218wx
Kisses, Kisses by Yael Kanarek
http://www.yaelkanarek.com/netart/kisses-kisses-2016
Both of the pieces are a form of digital paintings or visual generations. What I admire about them is the interactive input in creating a cohesive piece. I am not aware of the algorithms used or the input audience members were allowed to share in forming the interaction, but a subject I think was overlooked was the physicality of these pieces and their linkage to audience members. I think if the interaction was an important part, the documentation of the interaction is also pivotal in display, otherwise it seems like another painting.
selinal-Final-Project-Proposal
Running Drawings
For my final project, I would like to create some data visualizations of the running routes I do in Pittsburgh. These visualizations would be algorithmic drawings documented as a running diary of my daily or weekly runs. What I normally do not notice on a run are the larger gestures I make and the shapes, speed rates, and heart rate variations accompanying the larger gesture of a route. Mapping out these routes, and creating algorithmic drawings from the resulting shapes would not only visualize the “gestures” I am constantly making but unaware of, but also document trends on the routes which can affect my running and the way we look at a route retrospectively. I would be using turtle functions to follow the path, and arrays and for loops to create algorithmic patterns/visuals for a more appealing visualization of how I felt that day.
selinal-Project-11
//Selina Lee
//Section C
//selinal@andrew.cmu.edu
//Project-11
var turt1;
var turt2;
var turt3;
function setup() {
createCanvas(480, 480);
frameRate(10); //best speed for change in turtle function
}
function draw() {
background(40, 255, 215); //aqua backround
turt1 = makeTurtle(mouseX, mouseY); //follows mouse from center
turt1.setColor(color(255, 0, 255)); //magenta
turt1.setWeight(.5); //thin lines
turt2 = makeTurtle(mouseX, mouseY);
turt2.setColor(color(255, 200, 0)); //orange turtles
turt2.setWeight(4);
turt3 = makeTurtle(mouseX, mouseY);
turt3.setColor(color(180, 255, 30)); //yellow turtles
turt3.setWeight(10); //largest stroke weight span
turt4 = makeTurtle(mouseX, mouseY);
turt4.setColor(color(255, 100, 50));
for(var i = 0; i < 12; i++) { //there are about 12 visible iterations of the yellow turtles
turt3.penDown();
turt3.forward(random(30,35)*i); //by multiplying by i, the side lengths increase with each iteration of the turtle shape
turt3.left(60); //constant angle for visual flow
turt3.forward(random(30,35)*i); //larger length sides
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.penUp();
}
for(var i = 0; i < 18; i++) { //iterations of the orange turtles
turt2.penDown();
turt2.forward(random(6,10)*i); //shorter sides
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.penUp();
turt2.left(20);
turt2.forward(5);
}
for(var i = 0; i < 20; i++) { //there are about 20 visible iterations of the magenta turtles
turt1.setWeight(i*.1); //stroke weight increases with side length of the turtle
turt1.penDown();
turt1.back(20*i/3); //medium scale sides scale sides
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.penUp();
turt1.right(noise(.001)*50); //natural movement away from the other circles with noise function
turt1.back(40); //constant for visual appeal
}
for(var i = 0; i < 50; i++) {
turt4.setWeight(i*.04);
turt4.penDown();
turt4.back(10*i/4);
turt4.left(random(70,90));
turt4.back(10*i/4);
turt4.left(random(70,90));
turt4.back(10*i/4);
turt4.left(random(70,90));
turt1.back(10*i/4);
turt1.left(random(70,90));
turt1.back(10*i/4);
turt1.left(random(70,90));
turt1.back(10*i/4);
turt1.penUp();
turt1.right(noise(.001)*50);
turt1.back(80);
}
if(mouseIsPressed) {
noLoop();
}
}
function turtleLeft(d) {
this.angle -= d;
}
function turtleRight(d) {
this.angle += d;
}
function turtleForward(p) {
var rad = radians(this.angle);
var newx = this.x + cos(rad) * p;
var newy = this.y + sin(rad) * p;
this.goto(newx, newy);
}
function turtleBack(p) {
this.forward(-p);
}
function turtlePenDown() {
this.penIsDown = true;
}
function turtlePenUp() {
this.penIsDown = false;
}
function turtleGoTo(x, y) {
if (this.penIsDown) {
stroke(this.color);
strokeWeight(this.weight);
line(this.x, this.y, x, y);
}
this.x = x;
this.y = y;
}
function turtleDistTo(x, y) {
return sqrt(sq(this.x - x) + sq(this.y - y));
}
function turtleAngleTo(x, y) {
var absAngle = degrees(atan2(y - this.y, x - this.x));
var angle = ((absAngle - this.angle) + 360) % 360.0;
return angle;
}
function turtleTurnToward(x, y, d) {
var angle = this.angleTo(x, y);
if (angle < 180) {
this.angle += d;
} else {
this.angle -= d;
}
}
function turtleSetColor(c) {
this.color = c;
}
function turtleSetWeight(w) {
this.weight = w;
}
function turtleFace(angle) {
this.angle = angle;
}
function makeTurtle(tx, ty) {
var turtle = {x: tx, y: ty,
angle: 0.0,
penIsDown: true,
color: color(128),
weight: 1,
left: turtleLeft, right: turtleRight,
forward: turtleForward, back: turtleBack,
penDown: turtlePenDown, penUp: turtlePenUp,
goto: turtleGoTo, angleto: turtleAngleTo,
turnToward: turtleTurnToward,
distanceTo: turtleDistTo, angleTo: turtleAngleTo,
setColor: turtleSetColor, setWeight: turtleSetWeight,
face: turtleFace};
return turtle;
}
My process for this project started with playing around with the abstraction and composition of different polygons and their color. The mouse interaction and randomization were added after.
//Selina Lee
//Section C
//selinal@andrew.cmu.edu
//Project-11
var turt1;
var turt2;
var turt3;
function setup() {
createCanvas(480, 480);
frameRate(10); //best speed for change in turtle function
}
function draw() {
background(40, 255, 215); //aqua backround
turt1 = makeTurtle(mouseX, mouseY); //follows mouse from center
turt1.setColor(color(255, 0, 255)); //magenta
turt1.setWeight(.5); //thin lines
turt2 = makeTurtle(mouseX, mouseY);
turt2.setColor(color(255, 200, 0)); //orange turtles
turt2.setWeight(4);
turt3 = makeTurtle(mouseX, mouseY);
turt3.setColor(color(180, 255, 30)); //yellow turtles
turt3.setWeight(10); //largest stroke weight span
turt4 = makeTurtle(mouseX, mouseY);
turt4.setColor(color(255, 100, 50));
for(var i = 0; i < 12; i++) { //there are about 12 visible iterations of the yellow turtles
turt3.penDown();
turt3.forward(random(30,35)*i); //by multiplying by i, the side lengths increase with each iteration of the turtle shape
turt3.left(60); //constant angle for visual flow
turt3.forward(random(30,35)*i); //larger length sides
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.left(60);
turt3.forward(random(30,35)*i);
turt3.penUp();
}
for(var i = 0; i < 18; i++) { //iterations of the orange turtles
turt2.penDown();
turt2.forward(random(6,10)*i); //shorter sides
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.right(72);
turt2.forward(random(6,10)*i);
turt2.penUp();
turt2.left(20);
turt2.forward(5);
}
for(var i = 0; i < 20; i++) { //there are about 20 visible iterations of the magenta turtles
turt1.setWeight(i*.1); //stroke weight increases with side length of the turtle
turt1.penDown();
turt1.back(20*i/3); //medium scale sides scale sides
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.left(random(50,70));
turt1.back(20*i/3);
turt1.penUp();
turt1.right(noise(.001)*50); //natural movement away from the other circles with noise function
turt1.back(40); //constant for visual appeal
}
for(var i = 0; i < 50; i++) {
turt4.setWeight(i*.04);
turt4.penDown();
turt4.back(10*i/4);
turt4.left(random(70,90));
turt4.back(10*i/4);
turt4.left(random(70,90));
turt4.back(10*i/4);
turt4.left(random(70,90));
turt1.back(10*i/4);
turt1.left(random(70,90));
turt1.back(10*i/4);
turt1.left(random(70,90));
turt1.back(10*i/4);
turt1.penUp();
turt1.right(noise(.001)*50);
turt1.back(80);
}
if(mouseIsPressed) {
noLoop();
}
}
function turtleLeft(d) {
this.angle -= d;
}
function turtleRight(d) {
this.angle += d;
}
function turtleForward(p) {
var rad = radians(this.angle);
var newx = this.x + cos(rad) * p;
var newy = this.y + sin(rad) * p;
this.goto(newx, newy);
}
function turtleBack(p) {
this.forward(-p);
}
function turtlePenDown() {
this.penIsDown = true;
}
function turtlePenUp() {
this.penIsDown = false;
}
function turtleGoTo(x, y) {
if (this.penIsDown) {
stroke(this.color);
strokeWeight(this.weight);
line(this.x, this.y, x, y);
}
this.x = x;
this.y = y;
}
function turtleDistTo(x, y) {
return sqrt(sq(this.x - x) + sq(this.y - y));
}
function turtleAngleTo(x, y) {
var absAngle = degrees(atan2(y - this.y, x - this.x));
var angle = ((absAngle - this.angle) + 360) % 360.0;
return angle;
}
function turtleTurnToward(x, y, d) {
var angle = this.angleTo(x, y);
if (angle < 180) {
this.angle += d;
} else {
this.angle -= d;
}
}
function turtleSetColor(c) {
this.color = c;
}
function turtleSetWeight(w) {
this.weight = w;
}
function turtleFace(angle) {
this.angle = angle;
}
function makeTurtle(tx, ty) {
var turtle = {x: tx, y: ty,
angle: 0.0,
penIsDown: true,
color: color(128),
weight: 1,
left: turtleLeft, right: turtleRight,
forward: turtleForward, back: turtleBack,
penDown: turtlePenDown, penUp: turtlePenUp,
goto: turtleGoTo, angleto: turtleAngleTo,
turnToward: turtleTurnToward,
distanceTo: turtleDistTo, angleTo: turtleAngleTo,
setColor: turtleSetColor, setWeight: turtleSetWeight,
face: turtleFace};
return turtle;
}
selinal-Looking-Outwards-11
Surround Sounds by Christian Marclay
Surround Sounds is an art installation by Christian Marclay which entraps viewers in a room with projections that play “music” through their animation of visual onomatopoeias. The room is actually silent, but by using the animations to take over the space, sound can be envisioned, or felt in an alternative way. This piece shows an interesting connection between sound art and music, because the art under the category of sound art simply does not make sound. I admire this aspect of the piece. I am not sure if many algorithms were used directly in this piece, but Marclay worked with a team of animators in Adobe After Effects.
selinal-Project-10
//Selina Lee
//section C
//selinal@andrew.cmu.edu
//Project-10
var cactus = []; //tall cacti array w/ arms array
var smallCactus = []; //lower, short cacti w/o arms array
function setup() {
createCanvas(640, 240);
// create an initial collection of buildings
for (var i = 0; i < 6; i++){ //there are a max of 6 objects in the array listed
var rx = random(width); //randomized placement of cactus
cactus[i] = makeCactus(rx); //creating cacti from position and read through cactus array
}
for(var i = 0; i < 8; i++) { //there is a max of 8 objects in listed array
var srx = random(width); //second varaiable for randomized placement
smallCactus[i] = makeSmallCactus(srx);
}
frameRate(10); //slower frame rate
}
function draw() {
background(255, 70, 235); //purple background
displayStatusString(); //displays text counting number of each object present in index
displayHorizon(); //shows horizon line and subseding lines underneath
updateAndDisplayCactus(); //updates position number of cactus depending on placement in array and time
removeCactusThatHaveSlippedOutOfView(); //removes cactus out of view
addNewCactusWithSomeRandomProbability(); //adds new object
updateAndDisplaySmallCactus(); //same functions as bigger cactus but representation is different
removeSmallCactusThatHaveSlippedOutOfView();
addNewSmallCactusWithSomeRandomProbability();
}
function updateAndDisplayCactus(){
// Update the building's positions, and display them.
for (var i = 0; i < cactus.length; i++){
cactus[i].move();
cactus[i].display();
}
}
function removeCactusThatHaveSlippedOutOfView(){
// If a building has dropped off the left edge,
// remove it from the array. This is quite tricky, but
// we've seen something like this before with particles.
// The easy part is scanning the array to find buildings
// to remove. The tricky part is if we remove them
// immediately, we'll alter the array, and our plan to
// step through each item in the array might not work.
// Our solution is to just copy all the buildings
// we want to keep into a new array.
var cactusToKeep = [];
for (var i = 0; i < cactus.length; i++){
if (cactus[i].x + cactus[i].breadth > 0) { //pushing objects into array of cacti to keep around based on present
cactusToKeep.push(cactus[i]);
}
}
cactus = cactusToKeep; // remember the surviving buildings
}
function addNewCactusWithSomeRandomProbability() {
// With a very tiny probability, add a new building to the end.
var newCactusLikelihood = 0.007;
if (random(0,1) < newCactusLikelihood) { //random out of 100%
cactus.push(makeCactus(width)); //pushing objects into array of cactus
}
}
// method to update position of building every frame
function cactusMove() {
this.x += this.speed;
}
// draw the building and some windows
function cactusDisplay() {
fill(150, 255, 100); //liget, bright green
stroke(50, 200, 50); //darker green stroke
strokeWeight(1); //normal weight for stroke
push(); //translations only to this object
translate(this.x, height - 40); //places cactus on horison line
beginShape(); //curve to make cactus shape emerging from ground
curveVertex(this.breadth/2 - 10, 0);
curveVertex(this.breadth/2 - 10, 0);
curveVertex(0, -this.cHeight);
curveVertex(this.breadth, -this.cHeight);
curveVertex(this.breadth/2 + 10, 0);
curveVertex(this.breadth/2 + 10, 0);
endShape();
for(var i = 0; i < this.nArmsLeft; i++) { //loop to place randomized number of arms on left side of cactus
beginShape();
curveVertex(this.breadth + 120, -i*30 - 10);
curveVertex(this.breadth/2 - 10, -i*30 - 12);
curveVertex(this.breadth/2 - 35, -i*40 - 50);
curveVertex(this.breadth/2 - 15, -i*40 - 45);
curveVertex(this.breadth/2 - 10, -i*30 - 17);
curveVertex(this.breadth + 60, -i*30 - 15);
endShape();
}
for(var i = 0; i < this.nArmsRight; i++) { //loop to place randomized number of arms on right side of cactus
beginShape();
curveVertex(this.breadth - 120, -i*30 - 10);
curveVertex(this.breadth/2 + 10, -i*30 - 12);
curveVertex(this.breadth/2 + 35, -i*40 - 50);
curveVertex(this.breadth/2 + 15, -i*40 - 45);
curveVertex(this.breadth/2 + 10, -i*30 - 17);
curveVertex(this.breadth - 60, -i*30 - 15);
endShape();
}
pop(); //end of translated parts
}
function makeCactus(birthLocationX) { //make a cactus at given location
var cact = {x: birthLocationX,
breadth: random(20, 50), //width of cactus
speed: -1.0,
cHeight: random(100, 200), //height of cactus
nArmsLeft: round(random(0,5)), // number of arms to display on left
nArmsRight: round(random(0,5)), // number of arms on right
move: cactusMove, //function to move cactus
display: cactusDisplay} //fucntion to draw cactus
return cact;
}
function updateAndDisplaySmallCactus(){ //same as for updateAndDisplayCactus but for smaller cactus
// Update the building's positions, and display them.
for (var i = 0; i < smallCactus.length; i++){
smallCactus[i].move();
smallCactus[i].display();
}
}
function removeSmallCactusThatHaveSlippedOutOfView(){ //similar as above
var smallCactusToKeep = [];
for (var i = 0; i < smallCactus.length; i++){
if (smallCactus[i].x + smallCactus[i].breadth > 0) {
smallCactusToKeep.push(smallCactus[i]);
}
}
smallCactus = smallCactusToKeep; // remember the surviving buildings
}
function addNewSmallCactusWithSomeRandomProbability() {
// With a very tiny probability, add a new building to the end.
var newSmallCactusLikelihood = 0.007; //small cactus array has likelihood of showing up
if (random(0,1) < newSmallCactusLikelihood) {
smallCactus.push(makeSmallCactus(width));
}
}
// method to update position of building every frame
function smallCactusMove() {
this.x += this.speed;
}
function smallCactusDisplay() {
fill(130, 240, 120); //darker, more muted green
stroke(50, 210, 90); //darker outline
strokeWeight(1);
push();
translate(this.x, height - 20); //translates to second horizon line that is lighter than the first
beginShape(); //creates shorter tube shape of cactus emergying from ground
curveVertex(this.breadth/2 - 10, 0);
curveVertex(this.breadth/2 - 10, 0);
curveVertex(0, -this.cHeight);
curveVertex(this.breadth, -this.cHeight);
curveVertex(this.breadth/2 + 10, 0);
curveVertex(this.breadth/2 + 10, 0);
endShape();
pop();
}
function makeSmallCactus(birthLocationX) {
var sCact = {x: birthLocationX,
breadth: random(20, 50), //similar width as cactus
speed: -1.0,
cHeight: random(20, 80), //shorter height
move: smallCactusMove,
display: smallCactusDisplay}
return sCact;
}
function displayHorizon(){
stroke(255, 210, 80); //orange
strokeWeight(20); //thick line
line (0,height-50, width, height-50); //first opaque line
stroke(255, 210, 80, 200);
line(0, height-30, width, height-30); //second transparent line
stroke(255, 210, 80, 140);
line(0, height-10, width, height-10); //third, bottom-most translucent line
}
function displayStatusString(){
noStroke();
fill(0);
var statusString = "# Cactus = " + cactus.length; //text to display along with data available in arrays
var secondString = "# Small Cactus = " + smallCactus.length;
text(statusString, 5,20); //place to display text
text(secondString, 5, 35);
}
//Selina Lee
//section C
//selinal@andrew.cmu.edu
//Project-10
var cactus = []; //tall cacti array w/ arms array
var smallCactus = []; //lower, short cacti w/o arms array
function setup() {
createCanvas(640, 240);
// create an initial collection of buildings
for (var i = 0; i < 6; i++){ //there are a max of 6 objects in the array listed
var rx = random(width); //randomized placement of cactus
cactus[i] = makeCactus(rx); //creating cacti from position and read through cactus array
}
for(var i = 0; i < 8; i++) { //there is a max of 8 objects in listed array
var srx = random(width); //second varaiable for randomized placement
smallCactus[i] = makeSmallCactus(srx);
}
frameRate(10); //slower frame rate
}
function draw() {
background(255, 70, 235); //purple background
displayStatusString(); //displays text counting number of each object present in index
displayHorizon(); //shows horizon line and subseding lines underneath
updateAndDisplayCactus(); //updates position number of cactus depending on placement in array and time
removeCactusThatHaveSlippedOutOfView(); //removes cactus out of view
addNewCactusWithSomeRandomProbability(); //adds new object
updateAndDisplaySmallCactus(); //same functions as bigger cactus but representation is different
removeSmallCactusThatHaveSlippedOutOfView();
addNewSmallCactusWithSomeRandomProbability();
}
function updateAndDisplayCactus(){
// Update the building's positions, and display them.
for (var i = 0; i < cactus.length; i++){
cactus[i].move();
cactus[i].display();
}
}
function removeCactusThatHaveSlippedOutOfView(){
// If a building has dropped off the left edge,
// remove it from the array. This is quite tricky, but
// we've seen something like this before with particles.
// The easy part is scanning the array to find buildings
// to remove. The tricky part is if we remove them
// immediately, we'll alter the array, and our plan to
// step through each item in the array might not work.
// Our solution is to just copy all the buildings
// we want to keep into a new array.
var cactusToKeep = [];
for (var i = 0; i < cactus.length; i++){
if (cactus[i].x + cactus[i].breadth > 0) { //pushing objects into array of cacti to keep around based on present
cactusToKeep.push(cactus[i]);
}
}
cactus = cactusToKeep; // remember the surviving buildings
}
function addNewCactusWithSomeRandomProbability() {
// With a very tiny probability, add a new building to the end.
var newCactusLikelihood = 0.007;
if (random(0,1) < newCactusLikelihood) { //random out of 100%
cactus.push(makeCactus(width)); //pushing objects into array of cactus
}
}
// method to update position of building every frame
function cactusMove() {
this.x += this.speed;
}
// draw the building and some windows
function cactusDisplay() {
fill(150, 255, 100); //liget, bright green
stroke(50, 200, 50); //darker green stroke
strokeWeight(1); //normal weight for stroke
push(); //translations only to this object
translate(this.x, height - 40); //places cactus on horison line
beginShape(); //curve to make cactus shape emerging from ground
curveVertex(this.breadth/2 - 10, 0);
curveVertex(this.breadth/2 - 10, 0);
curveVertex(0, -this.cHeight);
curveVertex(this.breadth, -this.cHeight);
curveVertex(this.breadth/2 + 10, 0);
curveVertex(this.breadth/2 + 10, 0);
endShape();
for(var i = 0; i < this.nArmsLeft; i++) { //loop to place randomized number of arms on left side of cactus
beginShape();
curveVertex(this.breadth + 120, -i*30 - 10);
curveVertex(this.breadth/2 - 10, -i*30 - 12);
curveVertex(this.breadth/2 - 35, -i*40 - 50);
curveVertex(this.breadth/2 - 15, -i*40 - 45);
curveVertex(this.breadth/2 - 10, -i*30 - 17);
curveVertex(this.breadth + 60, -i*30 - 15);
endShape();
}
for(var i = 0; i < this.nArmsRight; i++) { //loop to place randomized number of arms on right side of cactus
beginShape();
curveVertex(this.breadth - 120, -i*30 - 10);
curveVertex(this.breadth/2 + 10, -i*30 - 12);
curveVertex(this.breadth/2 + 35, -i*40 - 50);
curveVertex(this.breadth/2 + 15, -i*40 - 45);
curveVertex(this.breadth/2 + 10, -i*30 - 17);
curveVertex(this.breadth - 60, -i*30 - 15);
endShape();
}
pop(); //end of translated parts
}
function makeCactus(birthLocationX) { //make a cactus at given location
var cact = {x: birthLocationX,
breadth: random(20, 50), //width of cactus
speed: -1.0,
cHeight: random(100, 200), //height of cactus
nArmsLeft: round(random(0,5)), // number of arms to display on left
nArmsRight: round(random(0,5)), // number of arms on right
move: cactusMove, //function to move cactus
display: cactusDisplay} //fucntion to draw cactus
return cact;
}
function updateAndDisplaySmallCactus(){ //same as for updateAndDisplayCactus but for smaller cactus
// Update the building's positions, and display them.
for (var i = 0; i < smallCactus.length; i++){
smallCactus[i].move();
smallCactus[i].display();
}
}
function removeSmallCactusThatHaveSlippedOutOfView(){ //similar as above
var smallCactusToKeep = [];
for (var i = 0; i < smallCactus.length; i++){
if (smallCactus[i].x + smallCactus[i].breadth > 0) {
smallCactusToKeep.push(smallCactus[i]);
}
}
smallCactus = smallCactusToKeep; // remember the surviving buildings
}
function addNewSmallCactusWithSomeRandomProbability() {
// With a very tiny probability, add a new building to the end.
var newSmallCactusLikelihood = 0.007; //small cactus array has likelihood of showing up
if (random(0,1) < newSmallCactusLikelihood) {
smallCactus.push(makeSmallCactus(width));
}
}
// method to update position of building every frame
function smallCactusMove() {
this.x += this.speed;
}
function smallCactusDisplay() {
fill(130, 240, 120); //darker, more muted green
stroke(50, 210, 90); //darker outline
strokeWeight(1);
push();
translate(this.x, height - 20); //translates to second horizon line that is lighter than the first
beginShape(); //creates shorter tube shape of cactus emergying from ground
curveVertex(this.breadth/2 - 10, 0);
curveVertex(this.breadth/2 - 10, 0);
curveVertex(0, -this.cHeight);
curveVertex(this.breadth, -this.cHeight);
curveVertex(this.breadth/2 + 10, 0);
curveVertex(this.breadth/2 + 10, 0);
endShape();
pop();
}
function makeSmallCactus(birthLocationX) {
var sCact = {x: birthLocationX,
breadth: random(20, 50), //similar width as cactus
speed: -1.0,
cHeight: random(20, 80), //shorter height
move: smallCactusMove,
display: smallCactusDisplay}
return sCact;
}
function displayHorizon(){
stroke(255, 210, 80); //orange
strokeWeight(20); //thick line
line (0,height-50, width, height-50); //first opaque line
stroke(255, 210, 80, 200);
line(0, height-30, width, height-30); //second transparent line
stroke(255, 210, 80, 140);
line(0, height-10, width, height-10); //third, bottom-most translucent line
}
function displayStatusString(){
noStroke();
fill(0);
var statusString = "# Cactus = " + cactus.length; //text to display along with data available in arrays
var secondString = "# Small Cactus = " + smallCactus.length;
text(statusString, 5,20); //place to display text
text(secondString, 5, 35);
}
//Selina Lee
//section C
//selinal@andrew.cmu.edu
//Project-10
var cactus = []; //tall cacti array w/ arms array
var smallCactus = []; //lower, short cacti w/o arms array
function setup() {
createCanvas(640, 240);
// create an initial collection of buildings
for (var i = 0; i < 6; i++){ //there are a max of 6 objects in the array listed
var rx = random(width); //randomized placement of cactus
cactus[i] = makeCactus(rx); //creating cacti from position and read through cactus array
}
for(var i = 0; i < 8; i++) { //there is a max of 8 objects in listed array
var srx = random(width); //second varaiable for randomized placement
smallCactus[i] = makeSmallCactus(srx);
}
frameRate(10); //slower frame rate
}
function draw() {
background(255, 70, 235); //purple background
displayStatusString(); //displays text counting number of each object present in index
displayHorizon(); //shows horizon line and subseding lines underneath
updateAndDisplayCactus(); //updates position number of cactus depending on placement in array and time
removeCactusThatHaveSlippedOutOfView(); //removes cactus out of view
addNewCactusWithSomeRandomProbability(); //adds new object
updateAndDisplaySmallCactus(); //same functions as bigger cactus but representation is different
removeSmallCactusThatHaveSlippedOutOfView();
addNewSmallCactusWithSomeRandomProbability();
}
function updateAndDisplayCactus(){
// Update the building's positions, and display them.
for (var i = 0; i < cactus.length; i++){
cactus[i].move();
cactus[i].display();
}
}
function removeCactusThatHaveSlippedOutOfView(){
// If a building has dropped off the left edge,
// remove it from the array. This is quite tricky, but
// we've seen something like this before with particles.
// The easy part is scanning the array to find buildings
// to remove. The tricky part is if we remove them
// immediately, we'll alter the array, and our plan to
// step through each item in the array might not work.
// Our solution is to just copy all the buildings
// we want to keep into a new array.
var cactusToKeep = [];
for (var i = 0; i < cactus.length; i++){
if (cactus[i].x + cactus[i].breadth > 0) { //pushing objects into array of cacti to keep around based on present
cactusToKeep.push(cactus[i]);
}
}
cactus = cactusToKeep; // remember the surviving buildings
}
function addNewCactusWithSomeRandomProbability() {
// With a very tiny probability, add a new building to the end.
var newCactusLikelihood = 0.007;
if (random(0,1) < newCactusLikelihood) { //random out of 100%
cactus.push(makeCactus(width)); //pushing objects into array of cactus
}
}
// method to update position of building every frame
function cactusMove() {
this.x += this.speed;
}
// draw the building and some windows
function cactusDisplay() {
fill(150, 255, 100); //liget, bright green
stroke(50, 200, 50); //darker green stroke
strokeWeight(1); //normal weight for stroke
push(); //translations only to this object
translate(this.x, height - 40); //places cactus on horison line
beginShape(); //curve to make cactus shape emerging from ground
curveVertex(this.breadth/2 - 10, 0);
curveVertex(this.breadth/2 - 10, 0);
curveVertex(0, -this.cHeight);
curveVertex(this.breadth, -this.cHeight);
curveVertex(this.breadth/2 + 10, 0);
curveVertex(this.breadth/2 + 10, 0);
endShape();
for(var i = 0; i < this.nArmsLeft; i++) { //loop to place randomized number of arms on left side of cactus
beginShape();
curveVertex(this.breadth + 120, -i*30 - 10);
curveVertex(this.breadth/2 - 10, -i*30 - 12);
curveVertex(this.breadth/2 - 35, -i*40 - 50);
curveVertex(this.breadth/2 - 15, -i*40 - 45);
curveVertex(this.breadth/2 - 10, -i*30 - 17);
curveVertex(this.breadth + 60, -i*30 - 15);
endShape();
}
for(var i = 0; i < this.nArmsRight; i++) { //loop to place randomized number of arms on right side of cactus
beginShape();
curveVertex(this.breadth - 120, -i*30 - 10);
curveVertex(this.breadth/2 + 10, -i*30 - 12);
curveVertex(this.breadth/2 + 35, -i*40 - 50);
curveVertex(this.breadth/2 + 15, -i*40 - 45);
curveVertex(this.breadth/2 + 10, -i*30 - 17);
curveVertex(this.breadth - 60, -i*30 - 15);
endShape();
}
pop(); //end of translated parts
}
function makeCactus(birthLocationX) { //make a cactus at given location
var cact = {x: birthLocationX,
breadth: random(20, 50), //width of cactus
speed: -1.0,
cHeight: random(100, 200), //height of cactus
nArmsLeft: round(random(0,5)), // number of arms to display on left
nArmsRight: round(random(0,5)), // number of arms on right
move: cactusMove, //function to move cactus
display: cactusDisplay} //fucntion to draw cactus
return cact;
}
function updateAndDisplaySmallCactus(){ //same as for updateAndDisplayCactus but for smaller cactus
// Update the building's positions, and display them.
for (var i = 0; i < smallCactus.length; i++){
smallCactus[i].move();
smallCactus[i].display();
}
}
function removeSmallCactusThatHaveSlippedOutOfView(){ //similar as above
var smallCactusToKeep = [];
for (var i = 0; i < smallCactus.length; i++){
if (smallCactus[i].x + smallCactus[i].breadth > 0) {
smallCactusToKeep.push(smallCactus[i]);
}
}
smallCactus = smallCactusToKeep; // remember the surviving buildings
}
function addNewSmallCactusWithSomeRandomProbability() {
// With a very tiny probability, add a new building to the end.
var newSmallCactusLikelihood = 0.007; //small cactus array has likelihood of showing up
if (random(0,1) < newSmallCactusLikelihood) {
smallCactus.push(makeSmallCactus(width));
}
}
// method to update position of building every frame
function smallCactusMove() {
this.x += this.speed;
}
function smallCactusDisplay() {
fill(130, 240, 120); //darker, more muted green
stroke(50, 210, 90); //darker outline
strokeWeight(1);
push();
translate(this.x, height - 20); //translates to second horizon line that is lighter than the first
beginShape(); //creates shorter tube shape of cactus emergying from ground
curveVertex(this.breadth/2 - 10, 0);
curveVertex(this.breadth/2 - 10, 0);
curveVertex(0, -this.cHeight);
curveVertex(this.breadth, -this.cHeight);
curveVertex(this.breadth/2 + 10, 0);
curveVertex(this.breadth/2 + 10, 0);
endShape();
pop();
}
function makeSmallCactus(birthLocationX) {
var sCact = {x: birthLocationX,
breadth: random(20, 50), //similar width as cactus
speed: -1.0,
cHeight: random(20, 80), //shorter height
move: smallCactusMove,
display: smallCactusDisplay}
return sCact;
}
function displayHorizon(){
stroke(255, 210, 80); //orange
strokeWeight(20); //thick line
line (0,height-50, width, height-50); //first opaque line
stroke(255, 210, 80, 200);
line(0, height-30, width, height-30); //second transparent line
stroke(255, 210, 80, 140);
line(0, height-10, width, height-10); //third, bottom-most translucent line
}
function displayStatusString(){
noStroke();
fill(0);
var statusString = "# Cactus = " + cactus.length; //text to display along with data available in arrays
var secondString = "# Small Cactus = " + smallCactus.length;
text(statusString, 5,20); //place to display text
text(secondString, 5, 35);
}
My process for this project was based on a previous drawing I have done with cacti. To me, these are significant structures because they exist in some isolation from each other by their spread and spacing in the desert, away from clusters of other living organisms, so their visual existence is very extraordinary. To create the cacti in p5, I started with creating a curve shape as the base of the cactus. Then, I randomized the number of arms present on the cactus’s body, where I had to play around with trial and error in creating a curve shape which looked like a cactus arm, but also that was attached to the cactus’s main body. I then, played with creating other objects like the smaller, darker cactus and its visual randomization and its positioning on the second horizon line lower than the first, larger, lighter cactus which was on the first horizon line.
selinal-Looking-Outward-10
Work from Home
by Hanski aka Hannah Epstein
http://hannahness.com/work-from-home
Work from home was an interactive walk in installation. Users would use their phones to text short code to a number which then triggered a response on the participant’s phone. Hannah Epstein was a MFA candidate at Carnegie Mellon and TA’d one of my sculpture classes. Her work uses humor as means of expression in reflecting serious topics and consists mainly of rug-hooking, a type of soft sculpture, and video games. It was inspiring to hear her talk about her games and how she exists in the field because before, gaming in my mind belonged only to an audience and to creators of men.
selinal-Looking-Outwards-09
I enjoyed reading this blog post and learning about how artists are implementing their interactive, non-gallery work in public settings. I think that the gesture of flipping the plates in relation to the movement of water and downward movement of the eye is very clever. It creates the illusion of the fountain while also allowing more innovative room for the shape of the fountain, the movement of the water, the scale and closeness of the viewer to the work, and the interaction which initiates a change in the piece. I think especially with our most previous project, this work is relevant to expanding beyond the combination of code with two-dimensional visuals.
selinal-Project-09
var underlyingImage; //global variable for image that is not shown
function preload() {
var myImageURL = "https://i.imgur.com/wSnQo5j.jpg"; //image of dad
underlyingImage = loadImage(myImageURL);
}
function setup() {
createCanvas(700, 600);
background(0); //black background
underlyingImage.loadPixels(); //load pixels
frameRate(10); //slow placement of objects when pixels called
}
function draw() {
var px = random(width); //random x and y variables to place something at
var py = random(height);
var ix = constrain(floor(px), 0, width-1); //constrain the x and y variables for color sake
var iy = constrain(floor(py), 0, height-1);
var theColorAtLocationXY = underlyingImage.get(ix, iy); //getting color of each pixel
var r = theColorAtLocationXY[0]; //r value of color
var g = theColorAtLocationXY[1]; // g value of pixel color
var b = theColorAtLocationXY[2]; //b value of color
var r2 = 255- r; //opposite r value
var g2 = 255-r; //opposite g value
var b2 = 255 - r; //opposite b value
noStroke();
if(g < 150 & b < 150) { //if g and b values are lower, make a clear ellipse of that pixel color and a smaller circle inside that is slightly redder
fill(r, g, b, 170);
ellipse(px, py, 20, 20);
fill(r + 10, g - 10, b - 10);
ellipse(px, py, 5, 5);
}
if(b > 230) { //if the b value is large, make an ellipse that is bluer than the pixel and make an arrangement of other blue circles surrounding it
fill(r- 10, g - 10, b + 10, 150);
ellipse(px, py, 5, 5);
var numObjects = 5;
var angleObject = 360/numObjects;
for(var i = 0; i < numObjects; i++) {
var posX = px + random(2, 7) *cos(radians(angleObject*i) );
var posY = py + 5 *sin(radians(angleObject*i) );
ellipse(posX, posY, 10, 10);
}
}
if(g > 150) { //if the green value is low, make a circle slightly greener that is random in radius
fill(r, g + 10, b, 100);
var pointSize = random(10, 60);
ellipse(px, py, pointSize, pointSize);
}
if(r > 200) { //if the r value is large, make an arrangement of circles with strokes that is slightly redder
var numObjects = 8;
var angleObject = 360/numObjects;
for(var i = 0; i < numObjects; i++) {
var posX = px + random(-5, 5) *cos(radians(angleObject*i) );
var posY = py + 5 *sin(radians(angleObject*i) );
noFill();
stroke(r +20, g - 10, b - 10);
strokeWeight(random(.25, 5));
ellipse(posX, posY, 10, 10);
}
}
if(r < 50 & g < 50 && b < 50) { //if all r g b values are on the lower end, make a row of five circles of that color which is moving downwards to the right
for(var i = 0; i < 5; i++) {
fill(theColorAtLocationXY, 300 - i*40);
ellipse((px - 15) +5* i, (py-15)+ 5* i, 2, 2);
}
}
else {
noFill(); //if the pixel does not meet any of the conditional statements, make a blank circle with the strokeWeight random and the stroke of the color at the pixel
stroke(theColorAtLocationXY);
strokeWeight(random(1, 8));
ellipse(px,py, 10, 10);
}
var sx = mouseX; //when the mouse runs over the canvas
var sy = mouseY;
var mx = constrain(floor(sx), 0, width-1); //constrain the mouse value for color
var my = constrain(floor(sy), 0, height-1);
var theColorAtLocationMxMy = underlyingImage.get(mx, my); //color at point of mouse
var drawSize = dist(pmouseX, pmouseY, mouseX, mouseY); //distance between mouse coordinates at previous to current point
fill(r2, g2, b2, 200); //opposite color
ellipse(sx, sy, drawSize/10, drawSize/10); //draw a circle with mouse stroke depending on the mouse speed
if(mouseIsPressed) { //if the mouse is pressed, make a circle the color of that pixel
fill(theColorAtLocationMxMy);
ellipse(mouseX, mouseY, 7, 7);
}
}
I liked playing with opacity in the shapes we make in class. I think the randomization of pixels along with the overlapping of the colors is nice.
Looking-Outwards-08
Eric Fischer
https://www.mapbox.com/about/team/eric-fischer/
Eric Fischer describes himself as a data artist and software developer, and he is based in the California bay area. His work uses data points of crime rates, traffic, transit lines, race, etc. to map the US. He said his obsession for the past few years is “what makes cities walkable.” His process consists of him carrying a GPS and first personally observing the area he is in and trying to match his walking life with what the retrospective walkability of the area is. From his personal investigations of cities, he has made art about large scale issues in the critiques of those cities, making viewers step back both physically and metaphorically. His presentation was not the most captivating, but with visuals and realistic trends I found it to be very successful. I admire the point he made about how data visualization does net necessarily have to be abstract, and that the ideas behind his work do not end up being abstract. His research thus becomes more than a realization on paper.