sketch
//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;
}