harsh-LookingOutwards02

Ars (Rockheim) - Feb 2012

link

This project by Marius Watz particularly caught my eye. It's a  generative video for the LED media facade of Norway's national museum of pop&rock. What makes it particularly compelling for me (as may be painfully obvious) is its direct link to architecture. I've rarely seen generative art being linked to built architecture before, and this one is particularly compelling. Not only because of the striking image it makes, but also because of the algorithm that generated it. It looks like Watz used a 2-D ribbon explosion (for the lack of a better word) algorithm in this project - which he then mapped onto the 3-D facade. The 2-D image has a certain animated quality about it which I think is partly the result of some stochastic process. This, combined with the multitude and composition of colors, makes the image very aesthetically pleasing to me - which then directly impacts the architecture.

 

harsh – Reading03

Reading Naimark makes me deeply uncomfortable. It's not because of the complexities that arise in the definitions of "First Word" and "Last Word" art, I'm okay with that, it's the deep level of ambiguity between these two terms that hits the uncanny spot. I get it, Naimark is trying to argue that the very nature of the relationship between art and technology means that it's almost impossible to say what's "First Word" and what's "Last Word", and this questions my assumptions about technology as an artistic medium to a very fundamental level. I've always assumed that Real art is First Word, art that is not afraid to experiment, art that tries to expand the field and its definition, art that uses new media as exploration, or uses old media in a new way.

But, Naimark sheds doubt upon this whole worldview - isn't art done with high skill, in an established setting also art? And isn't art playing with technology just that? A form of play?  I guess a conclusion for me is not about the medium, but about the effect of the art. Does the art make a comment on society and the way we operate? Is it aesthetic? Does it move people? If so, yes, it's  both First Word and Last Word, but then I ask, why all this playing around with technology?

harsh – Clock

IMAGES

GIF 

 

EMBED

This project was really fun to work on, with my intention being to make a linguistic representation of time. I first started with trying to tell the time in an interesting way - which simply involved applying a polish notation idea to the time itself, so something like 8:41 would become "eleven past half past eight" - while this was alright, I tried to make it more and more interesting. This led me to make the time more complex, by adding and removing common idioms such as "Half" and "Quarter" from the time. After this, a friend suggested for this complexity to increase the longer the function runs, which I thought was an awesome idea, and was the last thing I implemented.

In its current state, the text overflows from the screen and you must scroll to see the rest, I've currently paused trying to make the text smaller for it to fit in the screen - hopefully, this will come to realization in a future version. (Update- fixed it!)

let timer = 2;
 
function getWord(number){
 
  number = int(number);
 
  if (number==1){return "one "}
  else if (number==2){return "two "}
  else if (number==3){return "three "}
  else if (number==4){return "four "}
  else if (number==5){return "five "}
  else if (number==6){return "six "}
  else if (number==7){return "seven "}
  else if (number==8){return "eight "}
  else if (number==9){return "nine "}
  else if (number==10){return "ten "}
  else if (number==11){return "one " + "past " +"ten "}
  else if (number==12){return "two " + "past " +"ten "}
  else if (number==13){return "three " + "past " +"ten "}
  else if (number==14){return "four " + "past " +"ten "}
  else if (number==15){return "QUARTER "}
 
  return number.toString();
 
}
 
function getWordHour(number){
 
  number = int(number);
 
 
  if (number==0){return "twelve"}
  else if (number==1){return "one "}
  else if (number==2){return "two "}
  else if (number==3){return "three "}
  else if (number==4){return "four "}
  else if (number==5){return "five "}
  else if (number==6){return "six "}
  else if (number==7){return "seven "}
  else if (number==8){return "eight "}
  else if (number==9){return "nine "}
  else if (number==10){return "ten "}
  else if (number==11){return "eleven"}
  else if (number==12){return "twelve"}
 
  return number.toString();
 
}
 
function makeTimeString(listWithShit){
var decimalTime = listWithShit[0];
var changes = listWithShit[1];
var operator = listWithShit[2];
 
var decimalTimeString = decimalTime.toString();
 
var hourString = decimalTimeString.slice(0,2);
 
if(int(hourString) > 12)
 
{ 
  hourString = int(hourString) - 12;
  hourString = hourString.toString();
 
}
 
else if(int(hourString) < 1) { hourString = int(hourString) + 12; hourString = hourString.toString(); } var minuteString = decimalTimeString.slice(3,5); var minuteStringInt = int(minuteString); minuteStringInt = int( map(minuteStringInt,0,100,0,60) ); var finalString = "" for(var i=operator.length-1; i>=0; i--){
  var curOperator = operator[i];
 
  var curChange = changes[i]
 
  if(curChange == 15){curChange = "QUARTER "}
  else if(curChange == 30){curChange = "HALF "}
  else if(curChange == 10){curChange = "TEN ";}
  else if(curChange == 5){curChange = "FIVE ";}
 
  finalString+=curChange;
 
  if(curOperator == "-"){finalString+="past ";}
  else if(curOperator == "+"){finalString+="to ";}
}
 
 
var newMinuteString = "";
 
if(minuteStringInt>=45){
  var hourStringInt = int(hourString)+1;
  hourString = hourStringInt.toString();
  var leftOverMinutes = minuteStringInt-45;
 
  if(leftOverMinutes == 0){
    newMinuteString = "QUARTER "+"before "
  }
  else{
    newMinuteString = getWord(leftOverMinutes) + "past " + "QUARTER " + "before "
  }
}
 
else if(30<=minuteStringInt  && minuteStringInt<45){
  var leftOverMinutes = 45-minuteStringInt;
 
  if(leftOverMinutes == 15){
    newMinuteString = "HALF "+"past "
  }
  else{
    newMinuteString = getWord(leftOverMinutes) + "past "+"HALF "+"past "
  }
}
 
else if(15<=minuteStringInt  && minuteStringInt<30){
  if(minuteStringInt == 15){
    newMinuteString = "QUARTER "+"past ";
  }
  else{
    var leftOverMinutes = 30-minuteStringInt;
    newMinuteString = getWord(leftOverMinutes) + "to "+"QUARTER "+"past ";
  }
}
 
else if(0<=minuteStringInt  && minuteStringInt<15){
    if(minuteStringInt != 0){
      newMinuteString = getWord(minuteStringInt) +"past "      
    }
 
}
 
var hourStringWord = getWordHour(int(hourString));
//hourStringWord = hourStringWord.slice(0,hourStringWord.length-1);
 
var timestring = finalString + newMinuteString + hourStringWord + "."
 
finalString = "It is " + timestring.toLowerCase();
return finalString;
}
 
 
function complicatedClock(hour,minute){
  var currentTime = hour+map(minute,0,60,0,1);
  var newTime = currentTime;
 
  // LIST TO KEEP TRACK OF ALL THE SUBTRACTIONS/ADDITIONS BEING MADE
  var changes = [];
 
  // LIST TO KEEP TRACK OF WHETHER THE CHANGES ARE ADDITIONS OR SUBTRACTIONS
  var operator = [];
 
  var timeChanges = [30,15,10,5];
 
  for(var i = 0; i < timer; i++){
 
    var curIndex = int(random(0,4));
 
    var stepChange = timeChanges[curIndex];
 
    var addOrSubtract = random(0,1);
 
    if(addOrSubtract < 0.5){ changes.push(stepChange); operator.push("+"); newTime = newTime + map(stepChange,0,60,0,1); } else { changes.push(stepChange); operator.push("-"); newTime = newTime-map(stepChange,0,60,0,1); } } return [newTime,changes,operator]; } var curTimeString; var increasing = true; var textYTop = 20; function setup() { createCanvas(500,500); background(50); textFont("Helvetica"); fill(255); noStroke(); curTimeString = makeTimeString(complicatedClock(hour(),minute())); } function keyPressed(){ if (keyCode == ESCAPE){ increasing = false; } else { increasing = true; } } function mouseWheel(event) { textYTop -= event.delta; if(textYTop > 30){
  	textYTop = 29;
  }
 
}
 
function draw() {
  rectMode(CORNER);
  background(50);
 
  if (frameCount % (120) == 0 && increasing == true){
    curTimeString = makeTimeString(complicatedClock(hour(),minute()));
    timer+= 4;
  }
  text(curTimeString,20,textYTop,460,curTimeString.length*100);
}

harsh-Scope

praxinoscope-output

Here's an interpolation between Batman and a Coorgi - I'm not sure there's much else to say beyond that I would like to improve the interpolation between these two beings in the near future.

 
 
 
double[][] points = {
 
  {86.920948, -23.249132}, 
 
  {86.664672, -24.823893}, 
 
  {86.175996, -26.342519}, 
 
  {85.463499, -27.769999}, 
 
  {84.557778, -29.083769}, 
 
  {83.499422, -30.278466}, 
 
  {82.332896, -31.368541}, 
 
  {81.149804, -32.441065}, 
 
  {79.973249, -33.520753}, 
 
  {78.804825, -34.609233}, 
 
  {77.646171, -35.708105}, 
 
  {76.498983, -36.818939}, 
 
  {75.365020, -37.943267}, 
 
  {74.246116, -39.082578}, 
 
  {73.144184, -40.238308}, 
 
  {72.061223, -41.411829}, 
 
  {70.972337, -42.579390}, 
 
  {69.761074, -43.618243}, 
 
  {68.418840, -44.480833}, 
 
  {66.966098, -45.140455}, 
 
  {65.435219, -45.590573}, 
 
  {63.859903, -45.846697}, 
 
  {62.266241, -45.938590}, 
 
  {60.670160, -45.900258}, 
 
  {59.079093, -45.765953}, 
 
  {57.495346, -45.562513}, 
 
  {55.921415, -45.293435}, 
 
  {54.359616, -44.961068}, 
 
  {52.811914, -44.568224}, 
 
  {51.279888, -44.118075}, 
 
  {49.764723, -43.614049}, 
 
  {48.267215, -43.059734}, 
 
  {46.787793, -42.458789}, 
 
  {45.326554, -41.814870}, 
 
  {43.883302, -41.131573}, 
 
  {42.455647, -40.416190}, 
 
  {41.029901, -39.696975}, 
 
  {39.603639, -38.978787}, 
 
  {38.177011, -38.261328}, 
 
  {36.750165, -37.544299}, 
 
  {35.323253, -36.827402}, 
 
  {33.896425, -36.110339}, 
 
  {32.469830, -35.392812}, 
 
  {31.043618, -34.674523}, 
 
  {29.617942, -33.955174}, 
 
  {28.192952, -33.234467}, 
 
  {26.768798, -32.512105}, 
 
  {25.345168, -31.788715}, 
 
  {23.953224, -31.009128}, 
 
  {22.902710, -29.831666}, 
 
  {22.680213, -28.269473}, 
 
  {23.119263, -26.745011}, 
 
  {24.109144, -25.503345}, 
 
  {25.432246, -24.616583}, 
 
  {26.880274, -23.943827}, 
 
  {28.355004, -23.331482}, 
 
  {29.844053, -22.754683}, 
 
  {31.337536, -22.189417}, 
 
  {32.829143, -21.619219}, 
 
  {34.321058, -21.049826}, 
 
  {35.813617, -20.482123}, 
 
  {37.307001, -19.916596}, 
 
  {38.801390, -19.353730}, 
 
  {40.296962, -18.794014}, 
 
  {41.793891, -18.237937}, 
 
  {43.292349, -17.685990}, 
 
  {44.792498, -17.138667}, 
 
  {46.294506, -16.596460}, 
 
  {47.798529, -16.059869}, 
 
  {49.304718, -15.529390}, 
 
  {50.813220, -15.005525}, 
 
  {52.324176, -14.488776}, 
 
  {53.837714, -13.979648}, 
 
  {55.353963, -13.478649}, 
 
  {56.873039, -12.986285}, 
 
  {58.395047, -12.503068}, 
 
  {59.920088, -12.029507}, 
 
  {61.448249, -11.566115}, 
 
  {62.979608, -11.113404}, 
 
  {64.514231, -10.671886}, 
 
  {66.052173, -10.242072}, 
 
  {67.593476, -9.824473}, 
 
  {69.138972, -9.422747}, 
 
  {70.696441, -9.070563}, 
 
  {72.264665, -8.769725}, 
 
  {73.840441, -8.511216}, 
 
  {75.421355, -8.286148}, 
 
  {77.010010, -8.129169}, 
 
  {78.605791, -8.140331}, 
 
  {80.180613, -8.391741}, 
 
  {81.669897, -8.958155}, 
 
  {82.980798, -9.863096}, 
 
  {84.054231, -11.041537}, 
 
  {84.902440, -12.392737}, 
 
  {85.573674, -13.840886}, 
 
  {86.109564, -15.344604}, 
 
  {86.500435, -16.892308}, 
 
  {86.756509, -18.468101}, 
 
  {86.900946, -20.058175}, 
 
  {86.960155, -21.653820}, 
 
  {-92.890651, -19.904734}, 
 
  {-92.758800, -18.310670}, 
 
  {-92.471637, -16.737408}, 
 
  {-92.016404, -15.204235}, 
 
  {-91.449681, -13.708261}, 
 
  {-90.762578, -12.264018}, 
 
  {-89.904046, -10.915597}, 
 
  {-88.818938, -9.743826}, 
 
  {-87.491318, -8.858478}, 
 
  {-85.987059, -8.323836}, 
 
  {-84.404541, -8.101408}, 
 
  {-82.805413, -8.104900}, 
 
  {-81.213356, -8.260255}, 
 
  {-79.633312, -8.511646}, 
 
  {-78.059562, -8.800258}, 
 
  {-76.491277, -9.117235}, 
 
  {-74.928640, -9.460988}, 
 
  {-73.371745, -9.829889}, 
 
  {-71.820604, -10.222284}, 
 
  {-70.275145, -10.636502}, 
 
  {-68.735225, -11.070864}, 
 
  {-67.200631, -11.523689}, 
 
  {-65.671088, -11.993299}, 
 
  {-64.146266, -12.478025}, 
 
  {-62.625786, -12.976208}, 
 
  {-61.109226, -13.486201}, 
 
  {-59.596125, -14.006370}, 
 
  {-58.085991, -14.535094}, 
 
  {-56.578306, -15.070764}, 
 
  {-55.072531, -15.611780}, 
 
  {-53.568110, -16.156552}, 
 
  {-52.064477, -16.703494}, 
 
  {-50.561059, -17.251026}, 
 
  {-49.057280, -17.797568}, 
 
  {-47.552568, -18.341535}, 
 
  {-46.046930, -18.882933}, 
 
  {-44.543998, -19.431792}, 
 
  {-43.044152, -19.989031}, 
 
  {-41.546932, -20.553289}, 
 
  {-40.051859, -21.123215}, 
 
  {-38.558441, -21.697462}, 
 
  {-37.066172, -22.274690}, 
 
  {-35.574540, -22.853560}, 
 
  {-34.083026, -23.432738}, 
 
  {-32.602190, -24.038181}, 
 
  {-31.188586, -24.784709}, 
 
  {-29.920084, -25.757031}, 
 
  {-28.873428, -26.961008}, 
 
  {-28.366090, -28.458148}, 
 
  {-28.837907, -29.958080}, 
 
  {-29.979152, -31.068115}, 
 
  {-31.364692, -31.864293}, 
 
  {-32.799297, -32.572786}, 
 
  {-34.229666, -33.289793}, 
 
  {-35.656745, -34.013328}, 
 
  {-37.081507, -34.741413}, 
 
  {-38.504946, -35.472085}, 
 
  {-39.928063, -36.203384}, 
 
  {-41.351862, -36.933352}, 
 
  {-42.777344, -37.660029}, 
 
  {-44.205493, -38.381447}, 
 
  {-45.637276, -39.095625}, 
 
  {-47.073627, -39.800568}, 
 
  {-48.515442, -40.494263}, 
 
  {-49.963570, -41.174676}, 
 
  {-51.418802, -41.839756}, 
 
  {-52.881861, -42.487433}, 
 
  {-54.353390, -43.115622}, 
 
  {-55.843187, -43.698704}, 
 
  {-57.360900, -44.204745}, 
 
  {-58.901183, -44.637333}, 
 
  {-60.459110, -45.001394}, 
 
  {-62.030409, -45.302675}, 
 
  {-63.611515, -45.547465}, 
 
  {-65.199561, -45.742361}, 
 
  {-66.792327, -45.894092}, 
 
  {-68.389148, -45.989422}, 
 
  {-69.986322, -45.913703}, 
 
  {-71.558823, -45.625548}, 
 
  {-73.072593, -45.111904}, 
 
  {-74.494369, -44.381058}, 
 
  {-75.801778, -43.460694}, 
 
  {-76.987623, -42.387789}, 
 
  {-78.090404, -41.228551}, 
 
  {-79.204089, -40.079757}, 
 
  {-80.332115, -38.945038}, 
 
  {-81.472894, -37.823139}, 
 
  {-82.624892, -36.712761}, 
 
  {-83.786625, -35.612569}, 
 
  {-84.956653, -34.521201}, 
 
  {-86.133574, -33.437269}, 
 
  {-87.316018, -32.359364}, 
 
  {-88.502641, -31.286059}, 
 
  {-89.662006, -30.183974}, 
 
  {-90.710170, -28.976114}, 
 
  {-91.607478, -27.652752}, 
 
  {-92.309427, -26.216646}, 
 
  {-92.772766, -24.687142}, 
 
  {-92.970204, -23.101314}, 
 
  {-92.902345, -21.504445}, 
 
  {-129.502091, 180.180550}, 
 
  {-129.507482, 164.442770}, 
 
  {-129.513007, 148.705005}, 
 
  {-129.518513, 132.967252}, 
 
  {-129.523847, 117.229485}, 
 
  {-129.528855, 101.491718}, 
 
  {-129.533384, 85.753951}, 
 
  {-129.537280, 70.016183}, 
 
  {-129.540391, 54.278430}, 
 
  {-129.542563, 38.540675}, 
 
  {-129.543643, 22.802917}, 
 
  {-129.543478, 7.065147}, 
 
  {-129.541914, -8.672636}, 
 
  {-129.510250, -24.410276}, 
 
  {-128.922206, -40.135459}, 
 
  {-127.518102, -55.808502}, 
 
  {-125.221334, -71.375413}, 
 
  {-121.966708, -86.770227}, 
 
  {-117.706449, -101.917288}, 
 
  {-112.464760, -116.753698}, 
 
  {-106.223176, -131.197025}, 
 
  {-98.879381, -145.111265}, 
 
  {-90.364763, -158.340456}, 
 
  {-80.660813, -170.722832}, 
 
  {-69.780142, -182.082796}, 
 
  {-57.521073, -191.926997}, 
 
  {-58.772610, -185.584243}, 
 
  {-67.867493, -172.742816}, 
 
  {-76.128119, -159.351540}, 
 
  {-83.232804, -145.315234}, 
 
  {-88.701519, -130.574089}, 
 
  {-91.396571, -115.096454}, 
 
  {-90.763584, -99.402505}, 
 
  {-80.036844, -92.128944}, 
 
  {-64.313423, -91.457100}, 
 
  {-48.591017, -90.761965}, 
 
  {-32.870304, -90.029598}, 
 
  {-18.688792, -95.010335}, 
 
  {-6.490756, -104.952791}, 
 
  {7.097693, -99.136269}, 
 
  {20.286833, -90.562913}, 
 
  {35.920805, -89.863825}, 
 
  {51.657024, -90.078996}, 
 
  {67.389870, -90.469174}, 
 
  {82.866490, -91.885923}, 
 
  {83.592484, -107.469820}, 
 
  {82.098356, -123.128586}, 
 
  {78.826175, -138.512956}, 
 
  {73.710584, -153.385459}, 
 
  {66.795536, -167.511537}, 
 
  {58.231384, -180.704310}, 
 
  {48.064174, -192.693474}, 
 
  {56.484543, -188.494910}, 
 
  {68.265753, -178.083644}, 
 
  {78.744886, -166.351783}, 
 
  {88.011195, -153.638207}, 
 
  {96.142146, -140.168805}, 
 
  {103.159462, -126.086670}, 
 
  {109.081474, -111.509484}, 
 
  {113.961065, -96.550422}, 
 
  {117.876295, -81.309913}, 
 
  {120.822162, -65.853597}, 
 
  {122.772684, -50.239291}, 
 
  {123.930784, -34.545743}, 
 
  {124.381162, -18.815322}, 
 
  {124.415292, -3.077775}, 
 
  {124.363530, 12.659900}, 
 
  {124.556184, 28.396048}, 
 
  {124.916964, 44.129654}, 
 
  {125.200108, 59.864862}, 
 
  {125.426946, 75.600990}, 
 
  {125.618815, 91.337587}, 
 
  {125.797050, 107.074340}, 
 
  {125.982987, 122.811015}, 
 
  {126.142263, 138.547961}, 
 
  {126.306783, 154.284848}, 
 
  {126.637997, 170.018978}, 
 
  {126.998187, 185.752555}, 
 
  {123.113824, 192.106662}, 
 
  {113.081976, 179.980683}, 
 
  {103.050481, 167.854411}, 
 
  {93.021684, 155.725898}, 
 
  {82.992929, 143.597374}, 
 
  {72.969703, 131.464277}, 
 
  {63.030681, 119.262190}, 
 
  {49.152882, 121.381742}, 
 
  {34.321587, 126.606509}, 
 
  {18.920668, 129.793153}, 
 
  {3.251805, 131.194827}, 
 
  {-12.476601, 130.991172}, 
 
  {-28.067009, 128.918767}, 
 
  {-43.284620, 124.948457}, 
 
  {-57.811610, 118.931459}, 
 
  {-69.911034, 123.154878}, 
 
  {-79.780560, 135.413353}, 
 
  {-89.653501, 147.669061}, 
 
  {-99.526905, 159.924395}, 
 
  {-119.263262, 184.443480}, 
 
  {-129.361095, 195.914930}, 
 
  {-109.397811, 172.181740}
};
 
double[][] points2 =
  {
 
 
  {23.808966, -113.235216}, 
 
  {16.635916, -112.718379}, 
 
  {10.350569, -109.414393}, 
 
  {9.787917, -102.591103}, 
 
  {14.697923, -97.775923}, 
 
  {21.683358, -96.093647}, 
 
  {27.760598, -92.266242}, 
 
  {32.959011, -87.276243}, 
 
  {38.112019, -82.237850}, 
 
  {40.135701, -76.239025}, 
 
  {33.162074, -76.496060}, 
 
  {25.971810, -76.250705}, 
 
  {19.412552, -73.533725}, 
 
  {19.375470, -66.845310}, 
 
  {25.648075, -63.928877}, 
 
  {32.458588, -65.927568}, 
 
  {37.550441, -70.980427}, 
 
  {43.095733, -68.889276}, 
 
  {43.306455, -61.722080}, 
 
  {42.182402, -54.609678}, 
 
  {39.647631, -47.879381}, 
 
  {35.368905, -42.113381}, 
 
  {29.496984, -37.982276}, 
 
  {22.694314, -35.651093}, 
 
  {15.572475, -34.549303}, 
 
  {8.381446, -34.068737}, 
 
  {1.175449, -34.196535}, 
 
  {-5.995360, -34.920180}, 
 
  {-13.004710, -36.533705}, 
 
  {-19.331836, -39.942841}, 
 
  {-24.559522, -44.878857}, 
 
  {-28.394366, -50.961248}, 
 
  {-30.564968, -57.814209}, 
 
  {-30.806298, -64.995263}, 
 
  {-28.179931, -71.428779}, 
 
  {-22.504746, -68.424416}, 
 
  {-16.557793, -64.484394}, 
 
  {-9.470728, -64.501048}, 
 
  {-5.402746, -69.961212}, 
 
  {-9.237203, -75.334086}, 
 
  {-16.316738, -76.556345}, 
 
  {-23.509609, -76.213244}, 
 
  {-27.774878, -79.315776}, 
 
  {-22.801899, -84.446119}, 
 
  {-17.794330, -89.632110}, 
 
  {-12.273657, -94.247705}, 
 
  {-5.656351, -96.997920}, 
 
  {1.022123, -99.393558}, 
 
  {3.565160, -105.911456}, 
 
  {0.115215, -111.654576}, 
 
  {-6.944447, -113.001965}, 
 
  {-14.150145, -112.991888}, 
 
  {-15.991661, -115.214339}, 
 
  {-9.821899, -118.885535}, 
 
  {-2.922179, -120.935067}, 
 
  {4.229913, -121.784446}, 
 
  {11.430442, -121.590557}, 
 
  {18.519665, -120.324183}, 
 
  {25.245947, -117.769912}, 
 
  {31.006976, -113.495662}, 
 
  {61.769050, 0.148968}, 
 
  {60.506181, 0.298494}, 
 
  {59.258436, 0.543902}, 
 
  {58.034888, 0.890169}, 
 
  {56.846253, 1.341809}, 
 
  {55.705058, 1.902470}, 
 
  {54.625694, 2.574379}, 
 
  {53.624268, 3.357601}, 
 
  {52.718089, 4.249192}, 
 
  {51.924670, 5.242375}, 
 
  {51.260217, 6.326028}, 
 
  {50.737782, 7.484829}, 
 
  {50.365561, 8.700256}, 
 
  {50.145883, 9.952332}, 
 
  {50.075800, 11.221653}, 
 
  {50.169674, 12.489172}, 
 
  {50.434694, 13.732246}, 
 
  {50.862390, 14.929202}, 
 
  {51.439025, 16.062047}, 
 
  {52.148122, 17.117157}, 
 
  {52.972582, 18.084914}, 
 
  {53.896019, 18.958830}, 
 
  {54.903377, 19.734612}, 
 
  {55.981057, 20.409391}, 
 
  {57.116769, 20.981199}, 
 
  {58.299291, 21.448653}, 
 
  {59.518206, 21.810823}, 
 
  {60.763684, 22.067221}, 
 
  {62.026337, 22.217873}, 
 
  {63.297142, 22.263428}, 
 
  {64.567284, 22.202720}, 
 
  {65.827524, 22.033238}, 
 
  {67.068329, 21.755193}, 
 
  {68.279977, 21.369465}, 
 
  {69.452469, 20.877424}, 
 
  {70.575344, 20.280821}, 
 
  {71.637431, 19.581767}, 
 
  {72.626547, 18.782862}, 
 
  {73.529207, 17.887506}, 
 
  {74.330452, 16.900448}, 
 
  {75.013948, 15.828582}, 
 
  {75.562596, 14.681929}, 
 
  {75.959913, 13.474561}, 
 
  {76.192239, 12.224980}, 
 
  {76.252197, 10.955376}, 
 
  {76.155592, 9.687826}, 
 
  {75.905593, 8.441491}, 
 
  {75.501295, 7.236374}, 
 
  {74.947676, 6.092139}, 
 
  {74.255056, 5.026245}, 
 
  {73.437704, 4.052627}, 
 
  {72.512110, 3.181166}, 
 
  {71.495388, 2.417865}, 
 
  {70.404110, 1.765454}, 
 
  {69.253608, 1.224131}, 
 
  {68.057651, 0.792256}, 
 
  {66.828379, 0.466920}, 
 
  {65.576369, 0.244373}, 
 
  {64.310760, 0.120322}, 
 
  {63.039413, 0.090151}, 
 
  {23.145407, -16.569632}, 
 
  {31.407213, -22.473820}, 
 
  {39.364234, -28.808981}, 
 
  {46.229010, -36.313033}, 
 
  {51.846433, -44.792493}, 
 
  {56.216224, -53.980719}, 
 
  {59.670030, -63.554621}, 
 
  {62.255874, -73.398170}, 
 
  {64.431294, -83.314028}, 
 
  {73.583158, -84.001785}, 
 
  {82.405532, -79.001163}, 
 
  {89.120694, -71.413967}, 
 
  {93.196416, -62.118915}, 
 
  {95.246725, -52.156101}, 
 
  {95.989943, -42.007343}, 
 
  {95.838591, -31.829269}, 
 
  {95.231246, -21.666633}, 
 
  {98.822119, -12.569717}, 
 
  {105.572084, -4.960520}, 
 
  {113.730059, 1.081138}, 
 
  {122.570998, 6.031498}, 
 
  {127.963270, 14.533056}, 
 
  {129.967263, 24.488706}, 
 
  {129.978649, 34.660827}, 
 
  {136.481603, 40.896205}, 
 
  {145.954738, 44.575234}, 
 
  {154.409211, 50.210262}, 
 
  {161.481541, 57.509949}, 
 
  {167.108658, 65.980932}, 
 
  {171.581032, 75.123461}, 
 
  {175.353007, 84.577760}, 
 
  {178.487040, 94.262667}, 
 
  {181.043772, 104.116137}, 
 
  {183.046785, 114.095927}, 
 
  {181.275910, 123.614825}, 
 
  {171.317668, 124.193373}, 
 
  {161.295997, 122.400646}, 
 
  {151.331419, 120.314525}, 
 
  {141.449706, 117.866719}, 
 
  {131.685071, 114.988121}, 
 
  {122.080674, 111.614143}, 
 
  {112.688536, 107.688677}, 
 
  {103.567770, 103.169047}, 
 
  {94.724927, 98.125753}, 
 
  {86.179872, 92.593630}, 
 
  {78.010688, 86.520949}, 
 
  {70.303655, 79.872219}, 
 
  {63.147133, 72.634804}, 
 
  {55.084571, 66.560119}, 
 
  {45.106691, 66.299406}, 
 
  {35.222399, 68.505619}, 
 
  {25.098334, 67.633681}, 
 
  {16.411610, 62.855009}, 
 
  {13.323250, 53.275827}, 
 
  {13.293436, 43.111661}, 
 
  {14.657844, 33.024943}, 
 
  {16.483712, 23.009311}, 
 
  {18.393108, 13.008972}, 
 
  {19.988524, 2.954796}, 
 
  {20.893476, -7.182849}, 
 
  {-49.122441, 22.217810}, 
 
  {-47.860844, 22.067039}, 
 
  {-46.616729, 21.809128}, 
 
  {-45.399560, 21.444695}, 
 
  {-44.219091, 20.974835}, 
 
  {-43.085543, 20.401000}, 
 
  {-42.009847, 19.724966}, 
 
  {-41.003955, 18.948939}, 
 
  {-40.081149, 18.075825}, 
 
  {-39.256276, 17.109749}, 
 
  {-38.545743, 16.056828}, 
 
  {-37.967042, 14.926184}, 
 
  {-37.537513, 13.730982}, 
 
  {-37.272200, 12.489043}, 
 
  {-37.181056, 11.222393}, 
 
  {-37.259653, 9.954679}, 
 
  {-37.494533, 8.706459}, 
 
  {-37.884483, 7.497691}, 
 
  {-38.423085, 6.347414}, 
 
  {-39.099191, 5.272134}, 
 
  {-39.898479, 4.284898}, 
 
  {-40.805077, 3.395099}, 
 
  {-41.802878, 2.608830}, 
 
  {-42.876407, 1.929487}, 
 
  {-44.011289, 1.358393}, 
 
  {-45.194422, 0.895340}, 
 
  {-46.413987, 0.538990}, 
 
  {-47.659374, 0.287159}, 
 
  {-48.921096, 0.137011}, 
 
  {-50.190692, 0.085191}, 
 
  {-51.460735, 0.125786}, 
 
  {-52.724424, 0.258709}, 
 
  {-53.974083, 0.488573}, 
 
  {-55.200754, 0.819717}, 
 
  {-56.394032, 1.256000}, 
 
  {-57.541913, 1.800499}, 
 
  {-58.630707, 2.455079}, 
 
  {-59.645082, 3.219809}, 
 
  {-60.568363, 4.092235}, 
 
  {-61.383234, 5.066596}, 
 
  {-62.072924, 6.133165}, 
 
  {-62.622859, 7.278032}, 
 
  {-63.022482, 8.483619}, 
 
  {-63.266719, 9.730044}, 
 
  {-63.356550, 10.997059}, 
 
  {-63.291323, 12.265438}, 
 
  {-63.058264, 13.513884}, 
 
  {-62.662688, 14.720765}, 
 
  {-62.116354, 15.867389}, 
 
  {-61.434461, 16.939049}, 
 
  {-60.633519, 17.925015}, 
 
  {-59.729842, 18.817866}, 
 
  {-58.738729, 19.612637}, 
 
  {-57.674177, 20.306042}, 
 
  {-56.548906, 20.895909}, 
 
  {-55.374547, 21.380809}, 
 
  {-54.161861, 21.759882}, 
 
  {-52.920944, 22.032778}, 
 
  {-51.661371, 22.199695}, 
 
  {-50.392274, 22.261463}, 
 
  {-170.029712, 112.646242}, 
 
  {-167.878571, 102.750798}, 
 
  {-165.143284, 92.955007}, 
 
  {-161.988301, 83.287202}, 
 
  {-158.180015, 73.859166}, 
 
  {-153.539639, 64.812700}, 
 
  {-147.950196, 56.325429}, 
 
  {-140.854960, 49.074473}, 
 
  {-131.949641, 44.267443}, 
 
  {-122.617962, 40.342771}, 
 
  {-117.143744, 32.074879}, 
 
  {-116.810525, 21.942561}, 
 
  {-114.676831, 12.084432}, 
 
  {-107.922918, 4.673181}, 
 
  {-98.968563, -0.122670}, 
 
  {-91.171855, -6.627108}, 
 
  {-84.514767, -14.307625}, 
 
  {-82.460242, -24.008103}, 
 
  {-83.069300, -34.160061}, 
 
  {-83.062854, -44.328172}, 
 
  {-82.026737, -54.439867}, 
 
  {-79.569790, -64.296816}, 
 
  {-74.918582, -73.302787}, 
 
  {-67.681553, -80.378620}, 
 
  {-58.552911, -84.779207}, 
 
  {-50.814140, -81.202803}, 
 
  {-48.842995, -71.226384}, 
 
  {-46.140336, -61.424398}, 
 
  {-42.508198, -51.929298}, 
 
  {-37.795316, -42.923865}, 
 
  {-31.915224, -34.635452}, 
 
  {-24.893712, -27.289902}, 
 
  {-16.877927, -21.043334}, 
 
  {-8.837724, -14.968966}, 
 
  {-7.823433, -5.007337}, 
 
  {-6.894073, 5.115414}, 
 
  {-5.125987, 15.130290}, 
 
  {-3.157561, 25.108817}, 
 
  {-1.402295, 35.127041}, 
 
  {-0.208894, 45.222097}, 
 
  {-0.773757, 55.354816}, 
 
  {-4.757859, 64.499935}, 
 
  {-14.198983, 67.964996}, 
 
  {-24.335335, 68.166945}, 
 
  {-34.271283, 66.056079}, 
 
  {-44.001896, 67.288219}, 
 
  {-51.438635, 74.213193}, 
 
  {-58.878796, 81.147278}, 
 
  {-66.638185, 87.720472}, 
 
  {-74.825785, 93.751064}, 
 
  {-83.411227, 99.200610}, 
 
  {-92.339443, 104.068714}, 
 
  {-101.553467, 108.371995}, 
 
  {-110.998679, 112.141585}, 
 
  {-120.625822, 115.419562}, 
 
  {-130.392640, 118.255225}, 
 
  {-140.264313, 120.701829}, 
 
  {-160.228011, 124.577380}, 
 
  {-170.029712, 122.817151}, 
 
  {-150.213054, 122.814114}
 
};
 
 
 
 
// Template for KidzLabs/4M/Toysmith Animation Praxinoscope
// https://www.amazon.com/4M-3474-Animation-Praxinoscope/dp/B000P02HYC
// https://www.walmart.com/ip/Animation-Praxinoscope-Science-Kits-by-Toysmith-3474/45681503
// Developed for Processing 3.3.6 * http://processing.org
// 23 January 2018 * Golan Levin 
 
// See information about Processing PDF export at: 
// https://processing.org/reference/libraries/pdf/index.html
// PDF generated by Processing can be opened in Adobe Illustrator.
import processing.pdf.*;
boolean bRecordingPDF = false;
 
float inch = 72; 
float diamArtInner = inch * 1.50; 
float diamArtOuter = inch * 4.80; 
float diamCutInner = inch * 1.41; 
float diamCutOuter = inch * 4.875; 
float holeDy = inch * 0.23;
float holeDx = inch * 0.20;
float holeD = inch * 0.1;
 
final int nFrames = 10; 
int myFrameCount = 0;
int exportFrameCount = 0; 
boolean bAnimate = true; 
boolean bExportFrameImages = false;
 
 
 
 
//////////////////////////////////////////////////////////
 
int lenPoints = points2.length;
 
double[][] scaledPoints = new double [lenPoints][2];
 
double[][] squishedPoints = new double [lenPoints][2];
 
double[][] squishedDiff = new double [lenPoints][2];
 
double[][] repPoints = new double [lenPoints][2];
 
//-------------------------------------------------------
void setup() {
  size(792, 612); // 11x8.5" at 72DPI
  frameRate(15);
  smooth();
 
 
 
for (int j =0; j <points.length; j++) {
  double pointX = points2[j][0]*0.2;
  double pointY = -1*(points2[j][1]*0.2);
  scaledPoints[j][0] = pointX;
  scaledPoints[j][1] = pointY;
}
 
 
for (int i=0; i<points.length; i++) {
  double pointX = (points[i][0]*0.2);
  double pointY = (-1*(points[i][1]*0.2));
  squishedPoints[i][0] = pointX; 
  squishedPoints[i][1] = pointY;
}
 
for (int i=0; i<points.length; i++) {
  double squishedPointX = squishedPoints[i][0];
  double squishedPointY = squishedPoints[i][1];
 
  double scaledPointX = scaledPoints[i][0];
  double scaledPointY = scaledPoints[i][1];
 
  double diffX = squishedPointX-scaledPointX;
  double diffY = squishedPointY-scaledPointY;
  squishedDiff[i][0] = diffX;
  squishedDiff[i][1] = diffY;
}
 
for (int i=0; i<points.length; i++) {
  double pointX = scaledPoints[i][0];
  double pointY = scaledPoints[i][1];
 
  repPoints[i][0] = pointX;
  repPoints[i][1] = pointY;
}
} 
 
//-------------------------------------------------------
void draw() {
  background(240); 
  if (bRecordingPDF) {
    beginRecord(PDF, "praxinoscope-output.pdf");
  }
 
  // Do all the drawing. 
  pushMatrix(); 
  translate(width/2, height/2);
  drawCutLines(); 
  drawGuides(); 
  drawAllFrames();
  popMatrix();
 
  if (bExportFrameImages) {
    // If activated, export .PNG frames 
    if (exportFrameCount < nFrames) {
      String filename = "frame_" + nf((exportFrameCount%nFrames), 3) + ".png";
      saveFrame("frames/" + filename);
      println("Saved: " + filename); 
      exportFrameCount++;
      if (exportFrameCount >= nFrames) {
        bExportFrameImages = false;
        exportFrameCount = 0;
      }
    }
  }
 
  if (bRecordingPDF) {
    endRecord();
    bRecordingPDF = false;
  }
}
 
 
//-------------------------------------------------------
void keyPressed() {
  switch (key) {
  case ' ': 
    // Press spacebar to pause/unpause the animation. 
    bAnimate = !bAnimate;
    break;
 
  case 'p': 
  case 'P':
    // Press 'p' to export a PDF for the Praxinoscope.
    bRecordingPDF = true; 
    break;
 
  case 'f': 
  case 'F': 
    // Press 'f' to export .png Frames (to make an animated .GIF)
    myFrameCount = 0; 
    exportFrameCount = 0; 
    bExportFrameImages = true;
    bAnimate = true; 
    break;
  }
}
 
//-------------------------------------------------------
void drawCutLines() {
  fill(0); 
  textAlign(CENTER, BOTTOM); 
  text("Praxinoscope Template", 0, 0-diamCutOuter/2-6); 
 
  stroke(0); 
  strokeWeight(1.0);
 
  noFill(); 
  if (!bRecordingPDF) {
    fill(255);
  }
  ellipse(0, 0, diamCutOuter, diamCutOuter);
 
  noFill(); 
  if (!bRecordingPDF) {
    fill(240);
  }
  ellipse(0, 0, diamCutInner, diamCutInner);
 
  noFill(); 
  ellipse(diamCutOuter/2 - holeDx, 0-holeDy, holeD, holeD); 
 
  line (diamCutInner/2, 0, diamCutOuter/2, 0);
}
 
//-------------------------------------------------------
void drawGuides() {
  // This function draws the guidelines. 
  // Don't draw these when we're exporting the PDF. 
  if (!bRecordingPDF) {
 
    noFill(); 
    stroke(128); 
    strokeWeight(0.2); 
    ellipse(0, 0, diamArtInner, diamArtInner); 
    ellipse(0, 0, diamArtOuter, diamArtOuter);
 
    for (int i=0; i<nFrames; i++) {
      float angle = map(i, 0, nFrames, 0, TWO_PI); 
      float pxi = diamArtInner/2 * cos(angle);
      float pyi = diamArtInner/2 * sin(angle);
      float pxo = diamArtOuter/2 * cos(angle);
      float pyo = diamArtOuter/2 * sin(angle);
      stroke(128); 
      strokeWeight(0.2);
      line (pxi, pyi, pxo, pyo);
    }
 
    // Draw the red wedge outline, highlighting the main view.
    int redWedge = 7; // assuming nFrames = 10
    for (int i=redWedge; i<=(redWedge+1); i++) {
      float angle = map(i, 0, nFrames, 0, TWO_PI); 
      float pxi = diamArtInner/2 * cos(angle);
      float pyi = diamArtInner/2 * sin(angle);
      float pxo = diamArtOuter/2 * cos(angle);
      float pyo = diamArtOuter/2 * sin(angle);
      stroke(255, 0, 0); 
      strokeWeight(2.0);
      line (pxi, pyi, pxo, pyo);
    }
    noFill(); 
    stroke(255, 0, 0); 
    strokeWeight(2.0);
    float startAngle = redWedge*TWO_PI/nFrames;
    float endAngle = (redWedge+1)*TWO_PI/nFrames;
    arc(0, 0, diamArtInner, diamArtInner, startAngle, endAngle); 
    arc(0, 0, diamArtOuter, diamArtOuter, startAngle, endAngle); 
 
 
    for (int i=0; i<nFrames; i++) {
      float angle = map(i, 0, nFrames, 0, TWO_PI); 
 
      pushMatrix();
      rotate(angle); 
      float originY = ((diamArtOuter + diamArtInner)/2)/2;
      translate(0, 0-originY); 
 
      noFill(); 
      stroke(128); 
      strokeWeight(0.2);
      line (-inch/2, 0, inch/2, 0); 
      line (0, -inch/2, 0, inch/2); 
 
      popMatrix();
    }
  }
}
 
//-------------------------------------------------------
void drawAllFrames() {
  for (int i=0; i<nFrames; i++) {
    float angle = map(i, 0, nFrames, 0, TWO_PI); 
    float originY = ((diamArtOuter + diamArtInner)/2)/2;
 
    pushMatrix();
    rotate(angle); 
    translate(0, 0-originY); 
    scale(0.8, 0.8); // feel free to ditch this 
 
    int whichFrame = i; 
    if (bAnimate) {
      whichFrame = (i+myFrameCount)%nFrames;
    }
    drawArtFrame (whichFrame); 
    // drawArtFrameAlternate (whichFrame); 
 
    popMatrix();
  }
  myFrameCount++;
}
 
 
//-------------------------------------------------------
void drawArtFrame (int whichFrame) { 
  // Draw the artwork for a generic frame of the Praxinoscope, 
  // given the framenumber (whichFrame) out of nFrames.
  // NOTE #1: The "origin" for the frame is in the center of the wedge.
  // NOTE #2: Remember that everything will appear upside-down!
 
  // Draw the frame number
  fill(0); 
  noStroke(); 
  //textAlign(CENTER, CENTER); 
  //text (whichFrame, -1, -47);
 
 
 
  if (whichFrame<5) {
    for (int i=0; i<points.length; i++) {
      double[] curPoint = scaledPoints[i];
      double curX = curPoint[0];
      double curY = curPoint[1];
      double diffX = squishedDiff[i][0];
      double diffY = squishedDiff[i][1];
      double fMapped = map(whichFrame, 0, 5, 0, 1);
      double newX = curX+(diffX*fMapped);
      double newY = curY+(diffY*fMapped);
 
      repPoints[i][0] = newX;
      repPoints[i][1] = newY;
    }
  }
 
  else if (whichFrame>=5) {
    for (int i=0; i<points.length; i++) {
      double[] curPoint = squishedPoints[i];
      double curX = curPoint[0];
      double curY = curPoint[1];
      double diffX = squishedDiff[i][0];
      double diffY = squishedDiff[i][1];
      double fMapped = map(whichFrame, 5, 10, 0, 1);
      double newX = -1*((diffX*fMapped)-curX);
      double newY = -1*((diffY*fMapped)-curY);
 
      repPoints[i][0] = newX;
      repPoints[i][1] = newY;     
    }
  }
 
 
 
//if(whichFrame == 9){
//      pushMatrix();
//  fill(0);
//  beginShape();
//  for (int i=200; i<300; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
 
//  pushMatrix();
//  fill(0);
//  beginShape();
//  for (int i=0; i<100; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
//   pushMatrix();
//  fill(255);
//  beginShape();
//  for (int i=100; i<200; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
 
 
//}
 
 
 
//else if(whichFrame == 0){
//  pushMatrix();
//  fill(255);
//  beginShape();
//  for (int i=0; i<60; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
//   pushMatrix();
//  fill(0);
//  beginShape();
//  for (int i=60; i<120; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
//    pushMatrix();
//  fill(0);
//  beginShape();
//  for (int i=120; i<180; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
//      pushMatrix();
//  fill(0);
//  beginShape();
//  for (int i=180; i<240; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
 
 
//      pushMatrix();
//  fill(0);
//  beginShape();
//  for (int i=240; i<300; i++) {
//    float[] curPoint = repPoints[i];
//    //float[] nextPoint = repPoints[i+1];
//    vertex(curPoint[0], curPoint[1]);
//      //ellipse(curPoint[0],curPoint[1],2,2);
//  }
//  endShape();
//  popMatrix();
//}
 
 
  pushMatrix();
  fill(255);
  stroke(0);
  strokeWeight(1);
  //beginShape();
  for (int i=0; i<points.length-1; i++) {
    if ((i+1)%60==0 || (i+1)%100==0 ) {
      continue;
    }
    double[] curPoint = repPoints[i];
    double[] nextPoint = repPoints[i+1];
    //double[] nextNextPoint = repPoints[i+2];
 
    line((float)curPoint[0], (float)curPoint[1],(float)nextPoint[0],(float)nextPoint[1]);
    //vertex((float)curPoint[0],(float)curPoint[1]);
    //bezierVertex((float)nextPoint[0],(float)nextPoint[1],(float)nextNextPoint[0],(float)nextNextPoint[1],(float)nextNextNextPoint[0],(float)nextNextNextPoint[1]);
     // ellipse((float)curPoint[0],(float)curPoint[1],2,2);
 
  }
  //endShape();
popMatrix();
 
  //line(repPoints[0][0], repPoints[0][1], repPoints[repPoints.length-1][0], repPoints[repPoints.length-1][1]);
  //line( repPoints[repPoints.length-1][0], repPoints[repPoints.length-1][1],repPoints[0][0], repPoints[0][1]);
 
}
 
//-------------------------------------------------------
void drawArtFrameAlternate(int whichFrame) { 
  // An alternate drawing test. 
  // Draw a falling object. 
 
 
  // Draw a little splat on the frame when it hits the ground. 
  if (whichFrame == (nFrames-1)) {
    stroke(0, 0, 0); 
    strokeWeight(0.5); 
    int nL = 10;
    for (int i=0; i<nL; i++) {
      float a = HALF_PI + map(i, 0, nL-1, 0, TWO_PI);
      float cx = 12 * cos(a);
      float cy = 10 * sin(a); 
      float dx = 16 * cos(a);
      float dy = 13 * sin(a); 
      line (cx, 45+cy, dx, 45+dy);
    }
  }
 
  // Draw a little box frame
  fill(255); 
  stroke(0, 0, 0);
  strokeWeight(1); 
  rect(-5, -50, 10, 100); 
 
  // Make the puck accelerate downward
  float t = map(whichFrame, 0, nFrames-1, 0, 1); 
  float t2 = pow(t, 2.0); 
  float rh = 8 + whichFrame * 0.5; // wee stretch
  float ry = map(t2, 0, 1, 0, 100-rh) - 50; 
 
  noStroke(); 
  fill(0, 0, 0);
  rect(-5, ry, 10, rh);
}

harsh – AnimatedLoop

I started off with inspiration from D'arcy Thompson's "Theory of Transformations" - where he uses grid transformations to morph between different species of animals. I found his idea of being able to use simple mathematical equations to create transformations quite fascinating. So, I began to implement some of these systems, which included shear, scale, polar co-ordinate and exponential-scaling transformations. First, I tested this theory out on something simple - like a circle, before moving on to more complex geometries. I decided to keep my objects constructed as point clouds - as this kept my process of iteration quick, and the system scalable. By a sheer stroke of luck, I tried a polar coordinate transform before transforming it into a cartesian system - this created a really cool, point dissipation effect. I then began playing with these transformations, eventually closing in on using Mattise's Dancers - I thought the notion of an emergent composition from a seemingly random point cloud was quite interesting. It also connotated notions of the Gestalt and the border between familiarity and familiarity of a representation. I also thought that it made an interesting take on composition, referencing Mattise's methods in a digital medium. This was probably one the most iterations I have gone through in a week-long project, tweaking transformations, easing functions and point clouds numerous times before arriving at this result. I used the exponentialInOut and quinticInOut easing functions - both primarily to increase the time spent at the actual image and to speed up the transformation process. The process of crafting these transformations, both with morphing and easing functions was quite a novel one for me, having never really thought about computational craft before. Overall, I'm happy with the effect, and I think the easing and transformation functions work well. If I had more time on this, I would increase the complexity of the animation to emphasize this idea of composition - trying to recreate each object like pieces of paper cut by Mattise.

For this project, I did not really keep "sketches" - instead relying on Thompson's illustrations and descriptions as a means of generation:

 
 
 
//===================================================
// User-modifiable global variables.
var myNickname = "Harsh";
var nFramesInLoop = 120;
var bEnableExport = true;
 
 
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 
 
var circVals = [];
for(var i=0; i<pointsVals.length; i++){
  var curPointVals = pointsVals[i];
  circVals.push([curPointVals[0],curPointVals[1]*-1]);
}
 
 
var polarVals = []
for(var i=0; i<circVals.length; i++){
  var polarRadius = 30;
  var curPointVals = circVals[i];
  var cosX = polarRadius*Math.cos(curPointVals[0]);
  var sinY = polarRadius*Math.sin(curPointVals[1])
  polarVals.push([cosX,sinY]);
}
 
 
var shearVals = [];
for(var i=0; i<circVals.length; i++){
  var curPointVals = polarVals[i];
  var newX = curPointVals[0]-200;
  var newY = curPointVals[1]+200;
  shearVals.push([newX,newY]);
}
 
var shearDifferencesCartesian = []
for(var i=0; i<pointsVals.length; i++){
  var curCartValx = circVals[i][0];
  var curCartValy = circVals[i][1];
  var curShearValx = shearVals[i][0];
  var curShearValy = shearVals[i][1];
  var curTotalDifferenceX = curShearValx-curCartValx;
  var curTotalDifferenceY = curShearValy-curCartValy;
  shearDifferencesCartesian.push([curTotalDifferenceX,curTotalDifferenceY]);
}
 
var shearDifferencesPolar = []
for(var i=0; i<pointsVals.length; i++){
  var curPolarValx = polarVals[i][0];
  var curPolarValy = polarVals[i][1];
  var curShearValx = shearVals[i][0];
  var curShearValy = shearVals[i][1];
  var curTotalDifferenceX = curPolarValx-curShearValx;
  var curTotalDifferenceY = curPolarValy-curShearValy;
  shearDifferencesPolar.push([curTotalDifferenceX,curTotalDifferenceY]);
}
 
var cartesianDifferences = []
for(var i=0; i<pointsVals.length; i++){
  var curCartValx = circVals[i][0];
  var curCartValy = circVals[i][1];
  var curPolarValx = polarVals[i][0];
  var curPolarValy = polarVals[i][1];
  var curTotalDifferenceX = curPolarValx-curCartValx;
  var curTotalDifferenceY = curPolarValy-curCartValy;
  cartesianDifferences.push([curTotalDifferenceX,curTotalDifferenceY]);
}
 
var repVals = [];
for(var i=0; i<pointsVals.length; i++){
  var curPointVals = pointsVals[i];
  repVals.push([curPointVals[0],curPointVals[1]]);
}
 
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 
var circValsHead = [];
for(var i=0; i<headVals.length; i++){
  var curPointVals = headVals[i];
  circValsHead.push([curPointVals[0],curPointVals[1]*-1]);
}
 
 
var polarValsHead = []
for(var i=0; i<circValsHead.length; i++){
  var polarRadius = 30;
  var curPointVals = circValsHead[i];
  var cosX = polarRadius*Math.cos(curPointVals[0]);
  var sinY = polarRadius*Math.sin(curPointVals[1])
  polarValsHead.push([cosX,sinY]);
}
 
 
var shearValsHead = [];
for(var i=0; i<circValsHead.length; i++){
  var curPointVals = polarValsHead[i];
  var newX = curPointVals[0]+200;
  var newY = curPointVals[1]+200;
  shearValsHead.push([newX,newY]);
}
 
var shearDifferencesCartesianHead = []
for(var i=0; i<circValsHead.length; i++){
  var curCartValx = circValsHead[i][0];
  var curCartValy = circValsHead[i][1];
  var curShearValx = shearValsHead[i][0];
  var curShearValy = shearValsHead[i][1];
  var curTotalDifferenceX = curShearValx-curCartValx;
  var curTotalDifferenceY = curShearValy-curCartValy;
  shearDifferencesCartesianHead.push([curTotalDifferenceX,curTotalDifferenceY]);
}
 
var shearDifferencesPolarHead = []
for(var i=0; i<circValsHead.length; i++){
  var curPolarValx = polarValsHead[i][0];
  var curPolarValy = polarValsHead[i][1];
  var curShearValx = shearValsHead[i][0];
  var curShearValy = shearValsHead[i][1];
  var curTotalDifferenceX = curPolarValx-curShearValx;
  var curTotalDifferenceY = curPolarValy-curShearValy;
  shearDifferencesPolarHead.push([curTotalDifferenceX,curTotalDifferenceY]);
}
 
var cartesianDifferencesHead = []
for(var i=0; i<circValsHead.length; i++){
  var curCartValx = circValsHead[i][0];
  var curCartValy = circValsHead[i][1];
  var curPolarValx = polarValsHead[i][0];
  var curPolarValy = polarValsHead[i][1];
  var curTotalDifferenceX = curPolarValx-curCartValx;
  var curTotalDifferenceY = curPolarValy-curCartValy;
  cartesianDifferencesHead.push([curTotalDifferenceX,curTotalDifferenceY]);
}
 
var repValsHead = [];
for(var i=0; i<circValsHead.length; i++){
  var curPointVals = headVals[i];
  repValsHead.push([curPointVals[0],curPointVals[1]]);
}
 
 
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
 
 
// Other global variables you don't need to touch.
var nElapsedFrames;
var bRecording;
var theCanvas;
//===================================================
function setup() {
  theCanvas = createCanvas(900, 900);
  bRecording = false;
  nElapsedFrames = 0;
}
//===================================================
function keyTyped() {
  if (bEnableExport) {
    if ((key === 'f') || (key === 'F')) {
      bRecording = true;
      nElapsedFrames = 0;
    }
  }
}
//===================================================
function draw() {
  // Compute a percentage (0...1) representing where we are in the loop.
  var percentCompleteFraction = 0;
  if (bRecording) {
    percentCompleteFraction = float(nElapsedFrames) / float(nFramesInLoop);
  } else {
    percentCompleteFraction = float(frameCount % nFramesInLoop) / float(nFramesInLoop);
  }
  // Render the design, based on that percentage.
  // This function renderMyDesign() is the one for you to change.
  renderMyDesign (percentCompleteFraction);
  // If we're recording the output, save the frame to a file.
  // Note that the output images may be 2x large if you have a Retina mac.
  // You can compile these frames into an animated GIF using a tool like:
  if (bRecording && bEnableExport) {
    var frameOutputFilename = myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png";
    print("Saving output image: " + frameOutputFilename);
    saveCanvas(theCanvas, frameOutputFilename, 'png');
    nElapsedFrames++;
 
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
    }
  }
}
//===================================================
function renderMyDesign (percent) {
 
  background(13, 60, 85);
  smooth();
  stroke(0, 0, 0);
  strokeWeight(2);
 
  //----------------------
  var e = new p5.Ease(); // easing function object
 
  // percentSig = e.quadraticInOut(percent);
  // console.log(percentSig);
 
  percentSig = percent;
  if(0<=percentSig && percentSig<0.1){
 
    for(var i=0; i<circVals.length; i++){
      var curVal = polarVals[i];
      var curX = curVal[0];
      var curY = curVal[1];
      var curDifferenceX = shearDifferencesPolar[i][0];
      var curDifferenceY = shearDifferencesPolar[i][1];
      var newPerc = map(percent,0,0.1,0,1);
      var e = new p5.Ease(); // easing function object
      newPerc = e.exponentialInOut(newPerc);
      var newX = -1*((curDifferenceX*newPerc)-curX)
      var newY = -1*((curDifferenceY*newPerc)-curY)
      repVals[i] = [newX,newY];
    }
 
 
    for(var i=0; i<circValsHead.length; i++){
      var curVal = polarValsHead[i];
      var curX = curVal[0];
      var curY = curVal[1];
      var curDifferenceX = shearDifferencesPolarHead[i][0];
      var curDifferenceY = shearDifferencesPolarHead[i][1];
      var newPerc = map(percent,0,0.1,0,1);
      var e = new p5.Ease(); // easing function object
      newPerc = e.exponentialInOut(newPerc);
      var newX = -1*((curDifferenceX*newPerc)-curX)
      var newY = -1*((curDifferenceY*newPerc)-curY)
      repValsHead[i] = [newX,newY];
    }
 
  }
 
  else if(.1<=percentSig&& percentSig<0.66){
 
    for(var i=0; i<circVals.length; i++){
      var curVal = shearVals[i];
      var curX = curVal[0];
      var curY = curVal[1];
      var curDifferenceX = shearDifferencesCartesian[i][0];
      var curDifferenceY = shearDifferencesCartesian[i][1];
      var newPerc = map(percent,0.1,0.66,0,1)
      var e = new p5.Ease(); // easing function object
      newPerc = e.quinticInOut(newPerc);
      var newX = -1*((curDifferenceX*newPerc) - curX)
      var newY =  -1*((curDifferenceY*newPerc) - curY)
      repVals[i] = [newX,newY];
    }
 
 
    for(var i=0; i<circValsHead.length; i++){
      var curVal = shearValsHead[i];
      var curX = curVal[0];
      var curY = curVal[1];
      var curDifferenceX = shearDifferencesCartesianHead[i][0];
      var curDifferenceY = shearDifferencesCartesianHead[i][1];
      var newPerc = map(percent,0.1,0.66,0,1)
      var e = new p5.Ease(); // easing function object
      newPerc = e.quinticInOut(newPerc);
      var newX = -1*((curDifferenceX*newPerc) - curX)
      var newY =  -1*((curDifferenceY*newPerc) - curY)
      repValsHead[i] = [newX,newY];
    }
  }
 
  else if(.66<=percentSig&& percentSig<1){
 
    for(var i=0; i<circVals.length; i++){
      var curVal = circVals[i];
      var curX = curVal[0];
      var curY = curVal[1];
      var curDifferenceX = cartesianDifferences[i][0];
      var curDifferenceY = cartesianDifferences[i][1];
      var newPerc = map(percent,0.66,1,0,1)
      var e = new p5.Ease(); // easing function object
      newPerc = e.quadraticInOut(newPerc);
      var newX = (curDifferenceX*newPerc) + curX
      var newY =  (curDifferenceY*newPerc) + curY
      repVals[i] = [newX,newY];
    }
 
    for(var i=0; i<circValsHead.length; i++){
      var curVal = circValsHead[i];
      var curX = curVal[0];
      var curY = curVal[1];
      var curDifferenceX = cartesianDifferencesHead[i][0];
      var curDifferenceY = cartesianDifferencesHead[i][1];
      var newPerc = map(percent,0.66,1,0,1)
      var e = new p5.Ease(); // easing function object
      newPerc = e.quadraticInOut(newPerc);
      var newX = (curDifferenceX*newPerc) + curX
      var newY =  (curDifferenceY*newPerc) + curY
      repValsHead[i] = [newX,newY];
    }
  }
 
 
  for(var i=0; i<repVals.length; i++){
    //console.log((oldVals[i][0]+50),(oldVals[i][1]+50))
    push();
    fill(19, 149, 186);
    stroke(19, 149, 186);
    ellipse((repVals[i][0]+450),(repVals[i][1]+450),2,2);
    pop();
  }
 
 
  for(var i=0; i<repValsHead.length; i++){
    //console.log((oldVals[i][0]+50),(oldVals[i][1]+50))
    push();
    fill(241, 108, 32);
    stroke(241, 108, 32);
    ellipse((repValsHead[i][0]+450),(repValsHead[i][1]+450),5,5);
    pop();
  }
 
  //----------------------
  // Include some visual feedback.
  // fill(255, 0, 0);
  // noStroke();
  // textAlign(CENTER);
  // var percentDisplayString = "" + nf(percent, 1, 3);
  // text(percentDisplayString, 100, 200 - 15);
}

02 – Reading

Here's a major major throwback: Craig Reynolds' Boids

I believe that this project is one of the earliest examples of effective complexity in digital and generative art - where simple rules create a generative behaviour that ends up becoming a good mixture between order and disorder. In the spectrum between total order and total randomness, I believe that this sits somewhere in the middle, which is what makes it so effective. Though this slide can be adjusted depending on the number of boids in the system, and the complexity of the rules being followed.

The Problem of Postmodernity

This problem hits closest to home for me, as someone who is an acute observer/believer in the postmodern phenomenon. The shift away from modernist top-down approaches (where the whole must resemble the parts, or the theory of composition) to the postmodern beliefs of bottom-up generation, complex systems and chaos theory hold more truth in the contemporary world, especially one where technology plays such a decisive role. The world unfortunately just is not that coherent anymore.

harsh-Interruptions

Observations:

  1. The lines have seemingly random angles with the square of the paper
  2. While the pattern seems random, the lines are evenly distributed on the paper
  3. Some lines intersect others
  4. There are some irregularly large white-spaces in the artwork where lines have been removed
  5. There is a white border around the edge of the artwork
  6. The lines tend to break into this border, preventing it from being a square
  7. The border's on the top, left and right are larger than the ones at the bottom
  8. There exists a signature at the bottom right corner
  9. Generally, most lines tend to bias verticality
  10. The lines seem to be part of a general grid system

I thought of this as a grid distortion process - where most lines in a column system get rotated by some kind of distribution. After the distortion, there is a sequential "culling" of lines, which is not random but happens in chunks or groups, so it can be thought of as culling blocks of grids instead of individual lines.

Initially, I used the P5.JS random function to generate the values that would rotate each line segment, but I quickly realized that Molnar's piece had some kind of specific mathematical distribution. After messing around with Perlin Noise, I used Gaussian Distribution to generate the rotation (seeing as most lines tend t0 be more vertical). I think the calibration of the distribution still needs some work - and so does the calibration of the culling of the "patches" in the grid.

This was quite an interesting process, learning to re-create a visual effect through code - the process involved a lot of educated guessing, which while tough, was an interesting experience because of its iterative nature.

harsh-reading01

9. The Critical Engineer notes that written code expands into social and
psychological realms, regulating behaviour between people and the machines they
interact with. By understanding this, the Critical Engineer seeks to reconstruct
user-constraints and social action through means of digital excavation.

What this strikes a chord with me about this proposition is the very explicit notion here that code is not just a technological artefact but also a cultural one. I would argue that this idea extends beyond code, to all objects of technology and design - anything human created for human use, really. The objects we design, design us - and what makes code particularly tricky with this notion is that it is often very difficult to exactly point to how the software and interface are changing us. Thus, the role of the "Critical Engineer" to dissect this social interaction and reveal it is crucial.

Designed artefacts (and this includes code) are not just banal "objects" - they are encoded beings with inherent political, social and cultural meanings - intentional or unintentional. As Abraham Maslow has been credited to have said, "When you're holding a hammer, everything tends to look like a nail" - I think the same philosophy applies for code, in an even more potent way. While a hammer is still an immobile object, code is living, acting and shaping. The way google maps shows the world to you eventually influences the way you see the world, and a critical approach to dissecting and revealing this influence must be undertaken.

harsh-lookingoutwards01

One of my first introductions to the practice of expressing culture through the medium of technology was through Deeplocal. Though I've been interested in their work for a little while now (and curious about how the idea factory over there really works), a project that struck a variety of cords with me is their "Old Navy Selfiebration Machine". The questions this project indirectly asks about the homogeneity of screens in contemporary culture and the projections it makes about new mediums of interactions with technology make this project stand out for me. Beyond that, it does all of this while still maintaining a certain punchiness that's attention-grabbing in a rather ludicrous fashion.

As someone who's trained as an architect, any new medium of interfacing with computation that is physical in nature is always interesting to me. Which is what makes this radical questioning of what a "pixel" means for computation, executed in such a non-conventional method is deeply fascinating.

To briefly describe this project, it is a grid of inflatable balloons connected to Twitter, where people can post their selfies, which then get rasterized and displayed through this inflatable balloon grid. (The video below explains it in a little more depth) . Knowing Deeplocal's project cycle, it's most likely that this was done in a timeframe between 2 weeks and a month, with a team of 5-10 engineers and designers working on it.

From my knowledge of how they work, I'd say Deeplocal probably developed custom hardware (pneumatic systems, circuit boards etc) for this installation, and used some form of either C or C++ to program this system (though I am unsure how they linked it to Twitter).

The potential something like this holds in my mind is enormous. I hate the homogeneity of the screen-based interface of technology, and I envision a world where technology operates around us in a very real and physical manner.  This project for me is both a  provocation and a beginning of that idea(again, this also just might be because of my architecture background). I yearn to experiment and play in that place where the material world interfaces with technology.

 

harsh-Intersections

// First, create each line
// 		- line is constrained in length, and saved as [x1,y1],[x2,y2]
//		- draw the line
// Second, for each line, run algorithm to find int point
//		- save point to point masterlist
//    - draw point masterlist
 
 
var boolDoRefresh;
var numLinesSlider;
var lineLengthSlider;
 
function setup() {
	createCanvas(720, 400);
	numLinesSlider = createSlider(0,50,10);
	numLinesSlider.position(20,20);
 
	lineLengthSlider = createSlider(0,400,200);
	lineLengthSlider.position(20,40);
	background(255);
	boolDoRefresh = true;
}
 
 
function draw() {
	if (boolDoRefresh) {
		background(204, 255, 204)
 
		var lines = [];
		var lineLength = lineLengthSlider.value();
		var numLines = numLinesSlider.value();
		text("Number of Lines = "+ numLines.toString(), 30 + numLinesSlider.width, 35);
		text("Line Length = "+ lineLength.toString(), 30 + lineLengthSlider.width, 55);
 
		for (var i = 0; i < numLines; i++) {
			var curLine = makeLine(lineLength);
			lines.push(curLine);
			push();
			stroke(102, 204, 255);
			strokeWeight(2);
			line(curLine[0][0], curLine[0][1], curLine[1][0], curLine[1][1]);
			pop();
		}
 
 
		var points = [];
		for (var j = 0; j < lines.length; j++) {
			for (var k = 0; k < lines.length; k++) {			
				if (j === k) {
					continue;
				}		
				else {
					var line1 = lines[j];
					var line2 = lines[k];
					var curPoint = findIntersection(line1, line2);		
					if (curPoint != false) {
						points.push(curPoint);
						push();
						noStroke();
						fill(255, 153, 0,50);
						ellipse(curPoint[0], curPoint[1], 20, 20);
						pop();
					} 
				}
			}
		}
 
		var numIntersections = points.length;
		text("Intersections: "+ numIntersections.toString(),625,380);
		boolDoRefresh = false;
	}		
}
 
function mousePressed() {
	boolDoRefresh = true;
}
 
function makeLine(length) {
	var x1 = random(length, width - length);
	var y1 = random(length, height - length);
	var randAngle = Math.round(random(0, 360));
	var xLength = Math.cos(randAngle) * length;
	var yLength = Math.sin(randAngle) * length;
	var x2 = x1 + xLength;
	var y2 = y1 + yLength;
	var curLine = [
		[x1, y1],
		[x2, y2]
	];
	return curLine;
}
 
 
function findIntersection(line1, line2) {
	// line intercept math by Paul Bourke http://paulbourke.net/geometry/pointlineplane/
	// Determine the intersection point of two line segments
 
	var x1 = line1[0][0]
	var y1 = line1[0][1]
	var x2 = line1[1][0]
	var y2 = line1[1][1]
 
	var x3 = line2[0][0]
	var y3 = line2[0][1]
	var x4 = line2[1][0]
	var y4 = line2[1][1]
 
	var denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
 
	if (denominator === 0) {
		return false;
	} 
 
		var ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator
		var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator
 
		if (ua < 0 || ua > 1 || ub < 0 || ub > 1) {
			return false;
		} 
 
			var x = x1 + ua * (x2 - x1)
			var y = y1 + ua * (y2 - y1)
			return [x, y];
}