yalbert-viewing04

Speculation subverts itself in the overwhelming hodgepodge of digital media that is constantly being produced. Spectacle attempts to elevate above it in order to be considered refined and immortal.

Marco Brambilla's Civilization is interesting in the sense that it takes various spectacles from movies and hodgepodges it into speculation. It is overwhelming by design and almost mocks the artwork it's made out of by stereotyping all items into either heaven, hell or somewhere in between. Based on the dichotomies Warburton presents, it could be categorized as digital acceleration, visible, surplus (in the sense that it's reveling in it's overwhelming nature), art, and dysfunction.

I really like this artwork because it makes a familiar image out of works that are trying to be original and insightful. In other words, it displays how every new item that we as a society tries to produce simply fits within an ancient image of heaven and hell. As much as we can try to escape our traditional concepts of the world, it will follow us.

yalbert-reading03

Although I recognize the importance of first word art, I generally enjoy last word art more. I think this is because in many ways I'm comforted by its traditional nature and find it easier to appreciate the master of craft that is associated with it.

Technologies have an extraordinary impact on culture. One particularly interesting example of this is how modern technology shapes the way we absorb culture. The methods of consumption, instagram, facebook, youtube, affect how we interpret modern culture and therefore the content itself. On the flip side, culture has a tremendous affect on our technology. In particular, America's culture of capitalism and innovation has shaped Silicon Valley's endless drive to innovate, to both negative and positive effects.

I think that when work is technologically novel it ages poorly because work made in new media can't help but be scrappy. No one knows how to use the media yet so the craft is inevitably poor. Making something the second time around is bound to be better simply from learning from the original works' process.

yalbert-clock

For this project, I wanted to capture how time is not necessarily experienced linearly. Often time is is measured by the speed at which moments pass by. When moments are plentiful, they pass by quickly. However, when we only have a few left, we savor them lest they slip away from us. I did my best to express this in a visual way. Making this clock was fairly straightforward as I was able to reuse a particle system from a previous project. However, I'm not thrilled with how the particles clump together oddly when the minute is midway through. I think the clock is most visually pleasing at the beginning and end of the minute. Because my clock is heavily motion based, I chose to use a minute long loop. However, I think this draws away from using the clock for day long timekeeping (the hours are on the left and minutes on the right).

var offset = 25;
var plugOffset = 10;
var cirlceDist = 15;
var miniFill = 170;
var correctnessIndex = 1;
var plugThickness = 15;
var plugTipThickness = 45;
var plugTipHeight = 25;
var miniSize = 450;
 
var particleSystem;
var voiceSystem;
 
var modes = ["off", "listening", "answering"];
var currMode = "off";
 
var speech;
var mic;
 
var scenarios = []
var nullScenario;
var currScenario;
var anotherDayOfSun;
var activate;
var selectAnswers;
var demi;
var instrumental;
var startTime;
 
var instructionsX = 50;
var instructionsY = 50;
 
var barrier = 450
var baselineSec = 0
var resetted = false;
var subjectiveMin = 0
var numActiveParticles = 220;
var r
var g
var b
 
function setup(){
    angleMode(DEGREES);
    createCanvas(700, 700);
    particleSystem = new ParticleSystem();
    particleSystem.reset();
    baselineSec = second();
    subjectiveMin = minute();
 
}
 
function draw(){
    r = map(second()%60 - baselineSec, 0, 60, 0, 255);
    g = map(subjectiveMin, 0, 60, 0, 255);
    b = map(minute(), 0, 24, 0, 255);
 
    print(second(), baselineSec)
    print(second()%60 - baselineSec)
    print("")
 
    background(r, g, b);
    currMode = "listening";
    particleSystem.updateOpacity();
    particleSystem.updateVelocities();
    particleSystem.updatePosition();
    particleSystem.draw();
    // print(resetted)
    if(second()%60 == baselineSec && resetted == false){
      particleSystem.reset();
      resetted = true;
      subjectiveMin =(subjectiveMin + 1)%60
    }
    if(second() != baselineSec){
      resetted = false;
    }
    drawHours();
    drawMins();
}
 
function drawMins(){
  for(i = 1; i <= 2; i++){
    for(j = 1; j <= 30; j++){ if(i == 1){ minValue = j; }else{ minValue = j + 30; } if(subjectiveMin > minValue){
        opacity = 255;
      }else{
        opacity = 100;
      }
      fill(255-r, 255-g, 255-b, opacity);
      ellipse(width - 20 - 12*2+ 12*i, j*12 + 20, 10, 10);
      //text(minValue, width - 20 - 12*2+ 12*i, (j-1)*12 + 20)
 
    }
  }
}
 
function drawHours(){
  for(i = 0; i < 24; i++){ if(hour() > i){
      opacity = 255;
    }else{
      opacity = 100;
    }
    fill(255-r, 255-g, 255-b, opacity);
    ellipse(20, i*12 + 20, 10, 10);
  }
}
 
//courtesy of Golan Levin (http://cmuems.com/2015c/november-4/)
function ParticleSystem(){
    this.bigParticles = [];
    this.myParticles = [];
    this.nParticles = 300;
    this.particleSize = 10;
    this.isVisible = false;
    this.opacity = 0;
    this.reset = function(){
      this.myParticles = [];
      numActiveParticles = 220
        for (var i = 0; i < this.nParticles; i++) {
            var distFromCenter = random(0, miniSize/2);
            var degree = random(0, 360);
            var rx = cos(degree)*distFromCenter + width/2;
            var ry = sin(degree)*distFromCenter;
            this.myParticles[i] = new Particle(rx, ry, 10, random(.7, 1), true);
        }
 
        for(i = 0; i < 80; i+=2){
          var x1 = width/2 + i*3 + 10;
          var x2 = width/2 - i*3 - 10;
          var y = -i*3 + barrier;
          this.myParticles[i] = new Particle(x1, y, 10, random(.7, 1), false);
          this.myParticles[i+1] = new Particle(x2, y, 10, random(.7, 1), false);
        }
    }
 
    this.setForScenario = function(scenario){
        if(this.bigParticles.length != scenario.possibleAnswers.length){
            for(ansInd = 0; ansInd < scenario.possibleAnswers.length; ansInd++){
                this.addToBigParticles(scenario.answerProbabilities[ansInd]*250);
            }
        }
        for(ind = 0; ind < this.bigParticles.length; ind++){
            if(ind == scenario.selectedInd){
                this.bigParticles[ind].answering = true;
            }else{
                this.bigParticles[ind].answering = false;
            }
        }
    }
 
    this.addToBigParticles = function(goalSize){
        index = floor(random(0, particleSystem.nParticles));
        changingParticle = particleSystem.myParticles[index];
        changingParticle.goalSize = goalSize;
        particleSystem.bigParticles.push(changingParticle);
    }
 
    this.updateVelocities = function(){
        var gravityForcex = 0;
        var gravityForcey = -.17;
 
 
        for (var i = 0; i < this.myParticles.length; i++) {
            var ithParticle = this.myParticles[i];
            var px = ithParticle.px;
            var py = ithParticle.py;
 
 
            ithParticle.addForce(gravityForcex, gravityForcey);
 
            for (var j = 0; j < i; j++) { var jthParticle = this.myParticles[j]; var qx = jthParticle.px; var qy = jthParticle.py; var mutualAttractionAmount = (ithParticle.mass * jthParticle.mass)/2; var dx = px - qx; var dy = py - qy; var dh = sqrt(dx*dx + dy*dy); var componentInX = dx/dh; var componentInY = dy/dh; var proportionToDistanceSquared = 1.0/(dh*dh); var attractionForcex = mutualAttractionAmount * componentInX * proportionToDistanceSquared; var attractionForcey = mutualAttractionAmount * componentInY * proportionToDistanceSquared; if (dh > (ithParticle.mass + jthParticle.mass)/2 * 8) {
                    ithParticle.addForce( attractionForcex,  attractionForcey); // add in forces
                    jthParticle.addForce(-attractionForcex, -attractionForcey); // add in forces
                }else{
                    ithParticle.addForce( -attractionForcex,  -attractionForcey); // add in forces
                    jthParticle.addForce(attractionForcex, attractionForcey);  // add in forces
                }
            }
        }
    }
 
    this.updatePosition = function(){
        for (var i = 0; i < this.myParticles.length; i++) {
                particle = this.myParticles[i];
                particle.update();
        }
    }
 
    this.draw = function(){
        for (var i = 0; i < this.myParticles.length; i++) { particle = this.myParticles[i]; particle.render(this.opacity); } } this.updateOpacity = function(){ if(this.isVisible == false){ //if(this.opacity > 0){
                this.opacity = this.opacity*.9 +0*.1;
            //}
        }else{
            //if(this.opacity < 255){
                this.opacity = this.opacity*.9 + 255*.1 ;               
            //}
        }
 
    }
}
 
 
 
 
//courtesy of Golan Levin (http://cmuems.com/2015c/november-4/)
function Particle(x, y, mass, personalOpacity, canMove){
    this.personalOpacity = personalOpacity;
    this.size = mass;
    this.px= x;
    this.py=y;
    this.vx= 0;
    this.vy=0;
    this.damping = 0.96;
    this.mass = (pow(mass, 3))/100;
    this.bLimitVelocities=true;
    this.bPeriodicBoundaries=false;
    this.bElasticBoundaries=true;
    this.goalSize = mass;
    this.answering = false;
    this.opacity = 0;
    this.movable = canMove;
    this.passedThrough = false;
 
    this.addForce=function(fx,fy){
        var ax=fx/this.mass*1.5;
        var ay=fy/this.mass*1.5;
        if(this.goalSize < 30){ this.vx+=ax; this.vy+=ay; }else{ this.vx+=ax*.1; this.vy+=ay*.1; } } this.update=function(){ this.vx*=this.damping; this.vy*=this.damping; this.limitVelocities(); this.handleBoundaries(); if(this.movable){ this.py-=this.vy; this.px-=this.vx; } // if(abs(this.goalSize-this.size) > 1){
        //     this.size = this.size*.9 + this.goalSize*.1;
        // }
 
        if(this.py > barrier){
          if(this.passedThrough == false){
            numActiveParticles -=1
          }
          this.passedThrough = true
        }
    }
    this.limitVelocities=function(){
        if(this.bLimitVelocities){
            var speed=sqrt(this.vx*this.vx+this.vy*this.vy);
            var maxSpeed=10;
            if(speed>maxSpeed){
                this.vx*=maxSpeed/speed;this.vy*=maxSpeed/speed;
            }
        }
    }
    this.inBounds=function(){
        return(this.px<width&&this.px>0&&this.py<height&&this.py>0);
    }
    this.handleBoundaries=function(){
        if(this.bPeriodicBoundaries){
            if(this.px>width)
                this.px-=width;
            if(this.px<0) this.px+=width; if(this.py>height)
                this.py-=height;
            if(this.py<0) this.py+=height; }else if(this.bElasticBoundaries){ if(particle.py > height){
                this.vy = this.vy*-1; // draw all particles
                this.vx = this.vx*-1;
            }
        }
    }
    this.render=function(parentOpacity){
 
        if(abs(this.goalSize-this.size) < 15 && this.goalSize < 20){
 
                // this.opacity = 255 -getDist(this.px, this.py, width/2, height/2)*1.2 //+ this.size*this.size;
                // this.opacity = this.opacity*this.personalOpacity 
            noStroke();
 
            if(this.movable){
              if(this.passedThrough == false){
                opacity = 255;
              }else{
                opacity = map(numActiveParticles, 220, 0, 100, 25) //50;
              }
 
              fill(255, 255, 255, opacity);
              ellipse(this.px,this.py,this.size,this.size);
            }
        }else{
            if(this.answering){
                numLayers = 5;
            }else{
                numLayers = 1;
            }
           for(j = 0; j < numLayers; j++){
                diameter = this.size - j*5
                r = lerp(255, 40, 1 - j*.1);
                g = lerp(255, 140, 1 - j*.1);
                b = lerp(255, 250, 1 - j*.1);
 
                fill(r, g, b, 255*(parentOpacity/255));
                ellipse(this.px,this.py,diameter,diameter);
           }
 
        }
    }
}
 
function getDist(x1, y1, x2, y2){
    return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2))
}
 
//for testing
 
function mousePressed(){
 
}
 
function keyPressed(){
    if(particleSystem.isVisible){
        particleSystem.isVisible = false;
    }else{
        particleSystem.isVisible = true;
    }
}

yalbert-LookingOutwards02

microsurface video from Maayan Albert on Vimeo.

Title of Work: Microsurface
Artist: AlteredQualia
Link

This is a generative art project that features a series of multicolored cubes that rotate when you move over them. I admire how engaging the work is and how the individual cubes form a larger pattern. I suppose that this algorithm simply generates many three dimensional cubes that are programmed to rotate in response to the mouse. Some easing function is probably involved in the motion and the colors are likely generated by perlin noise or some similar function. I admire how organic the motion feels and how it is juxtaposed by the technological modernity implied by the colors and medium.

yalbert-AnimatedLoop

Although this pretty much turned out as an elaborate loading bar, I enjoyed making this piece. I'm partial to animation and using an easing technique was a good way to hone that skill. One part of this that I struggled with was color balance. It took me a while to experiment with black on white, white on black, and other colors until I finally settled on this combination. An element that I didn't fully resolve was the relationship between the spiral and the canvas. Making it too small made it feel like it was floating in space, but when it was too big it fit oddly in it.

// This is a template for creating a looping animation in p5.js (JavaScript). 
// When you press the 'F' key, this program will export a series of images into
// your default Downloads folder. These can then be made into an animated gif. 
// This code is known to work with p5.js version 0.6.0
// Prof. Golan Levin, 28 January 2018
 
// INSTRUCTIONS FOR EXPORTING FRAMES (from which to make a GIF): 
// 1. Run a local server, using instructions from here:
//    https://github.com/processing/p5.js/wiki/Local-server
// 2. Set the bEnableExport variable to true.
// 3. Set the myNickname variable to your name.
// 4. Run the program from Chrome, press 'f'. 
//    Look in your 'Downloads' folder for the generated frames.
// 5. Note: Retina screens may export frames at twice the resolution.
 
 
//===================================================
// User-modifiable global variables. 
var myNickname = "nickname";
var nFramesInLoop = 120;
var bEnableExport = true;
var dots = [];
var radius = 1200;
var dotSize = 45;
var worms = [];
var numWorms = 5
var colors = [[255, 0, 0], [0, 255, 0], [0, 0, 255]]
var curColor = [255, 0, 0]
var curColorInd = 0;
 
// Other global variables you don't need to touch.
var nElapsedFrames;
var bRecording;
var theCanvas;
 
//===================================================
function setup() {
  theCanvas = createCanvas(640, 640);
  bRecording = false;
  nElapsedFrames = 0;
  angleMode(DEGREES)
 
  for(j = 0; j <= numWorms; j++){ var r = lerp(243, 0, (j)/(numWorms)); var g = lerp(206, 0, (j)/(numWorms)); var b = lerp(80, 0, (j)/(numWorms)); var color = [r, g, b] var worm = new Worm(color) worm.setup() worms.push(worm) } } //=================================================== 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) {
  //
  // THIS IS WHERE YOUR ART GOES. 
  // This is an example of a function that renders a temporally looping design. 
  // It takes a "percent", between 0 and 1, indicating where we are in the loop. 
  // Use, modify, or delete whatever you prefer from this example. 
  // This example uses several different graphical techniques. 
  // Remember to SKETCH FIRST!
 
  //----------------------
 
 
 
 
  // here, I set the background and some other graphical properties
  background(0);
  smooth();
  stroke(0, 0, 0);
  strokeWeight(2);
 
 
  // if(percent == 0.75){
  //   curColorInd +=1;
  //   curColorInd = curColorInd % colors.length;
  //   curColor = colors[curColorInd];
  // }
 
  print(percent)
 
  for(j = 0; j < worms.length; j++){
    var r = lerp(curColor[0], 0, (j)/(numWorms));
    var g = lerp(curColor[1], 0, (j)/(numWorms));
    var b = lerp(curColor[2], 0, (j)/(numWorms));
    var color = [r, g, b];
 
    var worm = worms[j];
    worm.col = color
    worm.update((percent + .04 *j)%1, j);
  }
 
 
}
 
function Worm(c){
  this.dots = []
  this.col = c
  this.setup = function(){
    for(i = 0; i< 60; i++){
      dots.push(new Dot(i * .003))
    }
  }
  this.update = function(percent, sizeOff){
    for(i = 0; i < dots.length; i++){
      d = dots[i];
      d.calculatePos(percent);
      d.draw(this.col, sizeOff);
    }
  }
}
 
function Dot(off){
  this.offset = off
  this.x = 0
  this.y = 0
  this.radius = map(this.offset, 0, 1, 0, radius)
  this.angle = 0
  this.eased = 0
 
  this.calculatePos = function(percent){
    this.eased = quadraticInOut((percent + this.offset)%1);
    this.eased = (this.eased - 0.25)%1.0; // shifted by a half-loop, for fun
    this.angle = map(this.eased, 0, 1, 0, 360); 
 
    this.x = cos(this.angle)*this.radius + width/2;
    this.y = sin(this.angle)*this.radius + height/2;
  }
 
  this.draw = function(color, sizeOff){
    fill(color);
    noStroke();
    ellipse(this.x, this.y, dotSize + sizeOff*2, dotSize + sizeOff*2);
  }
}
 
 
// symmetric double-element sigmoid function (a is slope)
// See https://github.com/IDMNYU/p5.js-func/blob/master/lib/p5.func.js
// From: https://idmnyu.github.io/p5.js-func/
//===================================================
 
function gompertz(_x, _a){
    if(!_a) _a = 0.25; // default
    var min_param_a = 0.0 + Number.EPSILON;
    _a = max(_a, min_param_a);
 
    var b = -8.0;
    var c = 0 - _a*16.0;
    var _y = exp( b * exp(c * _x));
 
    var maxVal = exp(b * exp(c));
    var minVal = exp(b);
    _y = map(_y, minVal, maxVal, 0, 1);
 
    return(_y);
}
 
function quadraticInOut(_x) {
    if(_x < 0.5)
    {
      return(8 * _x * _x * _x * _x);
    }
    else
    {
      var _v = (_x - 1);
      return(-8 * _v * _v * _v * _v + 1);
    }
}
function sineOut(_x) {
    return(sin(_x * HALF_PI));
  }
 
function cubicIn(_x) {
    return(_x * _x * _x);
}

yalbert-Reading02

1. One example of effective complexity that I am particularly fond of is the sound of shoes walking through gravel. Initially I assumed that similar to white noise and static, this would be an example of total randomness. However, upon further thought it occurred to me that there is some order and rhythm to it because of the way a shoe distributes weight as it steps.

 

2. I relate to the problem of authenticity. This is because I often times see generative art as an opportunity to solve technical problems and get lost in these challenges as opposed to the form of expression itself. However, in the end the value I derive from such projects is the self expression, so I would say that generative art is authentic.

yalbert-Interruptions

This project was an interesting challenge because it forced me to evaluate the correctness of my work in an analogue as opposed to digital manner. By this I mean that I was not evaluating whether my project worked or not in absolute terms. Instead, I was observing its correctness in a fluid manner. There were many instances where I looked at it and thought, this almost seems right, but it isn't quite there yet. This is a workflow that I'm accustomed to in design classes but feels foreign in the context of a computationally based course. That being said, I really enjoyed working on this. In particular, computing line visibility on a grid taught me a new thing about Perlin noise. I've been using it for a few years but didn't fully understand how it worked until this project, which was really exciting.

var segs = [];
var margin = 20;
var segLength = 20;
var numSegs = 1500;
var clicked = false;
var segsSpacing = 13;
var xVisOff = 0.0;
var yVisOff = 0.0;
 
function setup() {
  angleMode(DEGREES);
  createCanvas(555, 555);
  resetSegs();
}
 
function draw() {
  background(255);
  if(clicked){
    clicked = false;
    resetSegs();
  }
  drawSegs();
}
 
function resetSegs(){
  segs = [];
  for(i = 0; i < sqrt(numSegs); i++){
    xVisOff = xVisOff + 0.2;
    yVisOff = 0.0
    for(j = 0; j < sqrt(numSegs); j++){
      yVisOff = yVisOff + 0.2;
      var x1 = i*segsSpacing + margin*1.5;
      var y1 = j*segsSpacing + margin;
      var secondPoint = setSecondPoint(x1, y1);
      var x2 = secondPoint[0];
      var y2 = secondPoint[1];  
      newSeg = new Segment(x1, x2, y1, y2, setVisibility());
      segs.push(newSeg);
    }
  }
}
 
//uses perlin noise to determine whether the line is visible or not
function setVisibility(){
  var opValue = noise(xVisOff, yVisOff);
  if(opValue > .3){
    return true;
  }else{
    return false;
  }
}
 
function drawSegs(){
  for(i = 0; i < numSegs; i++){
    segs[i].drawSeg();
  }
}
 
 
function mousePressed() {
  clicked = true;
}
 
function Segment(x1, x2, y1, y2, visibility){
  this.x1 = x1;
  this.x2 = x2;
  this.y1 = y1;
  this.y2 = y2;
  this.drawSeg = function(){
    stroke(0);
    strokeWeight(1);
    if(this.isVisible){
      line(this.x1, this.y1, this.x2, this.y2);      
    }
  }
  this.isVisible = visibility;
}
 
//Calculates the second point by selecting a point at the edge of a circle
//where the radius is the desired length of the lines and the center
//is the first point
function setSecondPoint(x1, y1){
  var angle = random(50, 150);
  var y2 = sin(angle) * segLength + y1;
  var x2 = cos(angle) * segLength + x1; 
  return [x2, y2];
}

yalbert-Intersections


var segs = [];
var intersections = [];
var clicked = false;
var numSegs = 12;
var lineLength = 300;
var dotSize = 20;
 
function setup() {
  angleMode(DEGREES);
  createCanvas(700, 700);
  resetLines();
  findIntersections();
}
 
function draw() {
  background(255);
 
  //creates a new set of segments if the mouse is clicked
  if(clicked){
    resetLines();
    findIntersections();
    clicked = false;
  }
  drawSegs();
  drawIntersections();
}
 
function drawSegs(){
  for(i = 0; i &lt; numSegs; i++){
    segs[i].drawSeg();
  }
}
 
function drawIntersections(){
  for(i = 0; i&lt; intersections.length; i++){
    intersections[i].drawIntersection();
  }
}
 
function mousePressed() {
  clicked = true;
}
 
function Segment(x1, x2, y1, y2){
  this.x1 = x1;
  this.x2 = x2;
  this.y1 = y1;
  this.y2 = y2;
  this.drawSeg = function(){
    stroke(0);
    strokeWeight(2);
    line(this.x1, this.y1, this.x2, this.y2);
  }
}
 
function Intersection(x, y){
  this.xPos = x;
  this.yPos = y;
  this.drawIntersection = function(){
    strokeWeight(0);
    fill(0, 100);
    ellipse(this.xPos, this.yPos, dotSize, dotSize);
  }
}
 
function resetLines(){
  segs = [];
  for(i = 0; i &lt; numSegs; i++){
    var x1 = random(0, width);
    var y1 = random(0, height);
    var secondPoint = setSecondPoint(x1, y1);
    var x2 = secondPoint[0];
    var y2 = secondPoint[1];  
    newSeg = new Segment(x1, x2, y1, y2);
    segs.push(newSeg);
  }
}
 
//Calculates the second point by selecting a point at the edge of a circle
//where the radius is the desired length of the lines and the center
//is the first point
function setSecondPoint(x1, y1){
  var angle = random(0, 360);
  var y2 = sin(angle) * lineLength + y1;
  var x2 = cos(angle) * lineLength + x1; 
 
  //If the second point is outside the canvas, another one is calculated
  while(x2 &lt; 0 || x2 &gt;= width || y2 &lt; 0 || y2 &gt;= height){
    angle = random(0, 360);
    y2 = sin(angle) * lineLength + y1;
    x2 = cos(angle) * lineLength + x1; 
  }
 
  return [x2, y2];
}
 
//iterates through all of the segments to find the intersections
function findIntersections(){
  intersections = [];
  for(firstInd = 0; firstInd &lt; numSegs; firstInd++){
    firstSeg = segs[firstInd];
    for(secInd = 0; secInd &lt; numSegs; secInd++){
      secondSeg = segs[secInd];
      intersection = findIntersection(firstSeg.x1, firstSeg.y1, 
                                      firstSeg.x2, firstSeg.y2,
                                      secondSeg.x1, secondSeg.y1,
                                      secondSeg.x2, secondSeg.y2);
      if(intersectionIsValid(intersection)){
        intersections.push(new Intersection(intersection[0], intersection[1]));
      }
    }
  }
}
 
//check that the intersection exists and hasn't already been discovered
function intersectionIsValid(intersection){
  if(intersection == false){
    return false;
  }
  for(i = 0; i &lt; intersections.length; i++){
    if(intersections[i].xPos == intersection[0] &amp;&amp; intersections[i].yPos == intersection[1]){
      return false;
    }
  }
  return true;
}
 
//Paul Bourke's equation for finding the intersection of two lines
//Code courtesy of Leo Bottaro
function findIntersection(x1, y1, x2, y2, x3, y3, x4, y4) {
  // Check if none of the lines are of length 0
  if ((x1 === x2 &amp;&amp; y1 === y2) || (x3 === x4 &amp;&amp; y3 === y4)) {
    return false
  }
 
  denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1))
 
  // Lines are parallel
  if (denominator === 0) {
    return false
  }
 
  let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator
  let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator
 
  // is the intersection along the segments
  if (ua &lt; 0 || ua &gt; 1 || ub &lt; 0 || ub &gt; 1) {
    return false
  }
 
  // Return a object with the x and y coordinates of the intersection
  let x = x1 + ua * (x2 - x1)
  let y = y1 + ua * (y2 - y1)
 
  return [floor(x), floor(y)]
}

yalbert-IterationExcercise

//global values
var boolDoRefresh;
var grid = [];
var gridSize = 8;
var spotSize = 30;
var margin = 20;
var spotGap = 10;
var probabilityOfCircle = .1
 
function setup() {
  createCanvas(400, 400);
  boolDoRefresh =true;
 
  //create the first grid
  recreateGrid();
 
  //calculate margin based on grid and canvas size
  margin = (width - gridSize*(spotSize+spotGap))/2;
}
 
function draw() {
  background(41, 233, 86);
 
  //create a new grid if a mouse was clicked
  if(boolDoRefresh) {
    recreateGrid();
    boolDoRefresh = false;
  }
  drawGrid();
}
 
function mousePressed() {
  boolDoRefresh = true;
}
 
function drawGrid(){
    for(row = 0; row &lt; gridSize; row++){
        for(col = 0; col &lt; gridSize; col++){
            grid[row][col].drawSpot();
        }
    }
}
 
function spot(x, y, isSq){
    this.xPos = x;
    this.yPos = y;
    this.isSquare = isSq;
    this.drawSpot = function(){
        if(this.isSquare){
            stroke(0, 75);
            strokeWeight(0);
            fill(0, 0, 0, 30);
            rect(this.xPos, this.yPos, spotSize, spotSize);
        }else{
            stroke(0, 150);
            strokeWeight(0);
            fill(0, 0, 0, 100);
            ellipse(this.xPos + spotSize/2, this.yPos + spotSize/2, spotSize, spotSize);            
        }
    }
}
 
//recreate the grid, assigning each spot a new shape
function recreateGrid(){
    grid = [];
    for(row = 0; row &lt; gridSize; row++){
        tempRow = [];
        for(col = 0; col &lt; gridSize; col++){
            newSpot = new spot(margin + col*(spotSize+spotGap), margin + row*(spotSize+spotGap), chooseShape());
            tempRow.push(newSpot);
        }
        grid.push(tempRow);
    }
}
 
//randomly assign a shape based on the give square vs circle probability
function chooseShape(){
    var randVal = random(0,1);
    if(randVal &lt;= probabilityOfCircle){
        return false;
    }else{
        return true;
    }
}

yalbert-reading01

5. The Critical Engineer recognises that each work of engineering engineers its user, proportional to that user's dependency upon it.

In other words, the design of a product affects its users' behavior. This can happen with or without the participants' knowledge and is nearly impossible to avoid. As a designer, this is a fact that I must constantly contend with. Recognizing these behavioral nudges and understanding how to shape them is a key skill for those in my trade.

One common example of this is the scrolling interaction on mobile phones. Scrollable pages often lack clearly defined bottoms. As a result, users are disposed to lose track of time and spend longer on an app or site than initially intended. Since we are highly dependent on smartphones, this interaction of 'endlessly scrolling' through a given feed has become a mainstay in contemporary culture and raised questions about the role technology can and should play in our lives.