Category: Assignment-06-LasercutScreen

move fish get out of the way

./wp-content/uploads/sites/2/2013/10/really.pdf

I heavily borrowed Golan’s repulsion code, mostly because I had to start a new one today (the one I was working on was on my USB drive, which I had left in a studio class in a locked room… sigh). Because of this, I was determined to at least make the curves look nice. So I spent a lot of time on various fluid shapes I could make, something that would look interesting laser cut:

blarhg

Then with the code, I abused curveVertex to death. That’s basically it, other than some adjustments for the fishies to not intersect with the big fish for the sake of the laser cutter. I also really wanted to make the fishies naturally shy away from the big fish, but didn’t have time to implement it… and I figured that it wouldn’t even show up on the lasercut screen anyway.

//code from Golan Levin; modified for fishies

ArrayList myFishys;

void setup() {
  size(600, 600);
  myFishys = new ArrayList();
  for (int i=0; i<100; i++) {
    float rx = random(width);
    float ry = random(height);
    while(rx > 50 && (ry > 100 && ry < 500)){
      rx = random(width);
      ry = random(height);
    }
    myFishys.add( new Fishy(rx, ry));
  }
}

void draw() {
  background (255);
  stroke(0);
  noFill();
  bigfish();
  float mutualRepulsionAmount = 1.5;
  for (int i=0; i 1.0) {
        float componentInX = dx/dh;
        float componentInY = dy/dh;
        float proportionToDistanceSquared = 1.0/(dh*dh);
        float repulsionForcex = mutualRepulsionAmount * componentInX * proportionToDistanceSquared;
        float repulsionForcey = mutualRepulsionAmount * componentInY * proportionToDistanceSquared;
        ithFishy.addForce( repulsionForcex, repulsionForcey); // add in forces
        jthFishy.addForce(-repulsionForcex, -repulsionForcey); // add in forces
      }
    }
  }
  for (int i=0; i
void bigfish() {
  pushMatrix();
  translate(width/2+200, height/2+20);
  scale(2);
  line(-180, 0, -70, 0);
  bigfishhead();
  bigfishbones();
  pushMatrix();
  translate(0, -20);
  bigfishtail();
  popMatrix();
  popMatrix();
}
void bigfishtail() {
  tail();
  pushMatrix();
  translate(5, 10);
  scale(0.7);
  tail();
  popMatrix();
  pushMatrix();
  rotate(0.5);
  translate(40, 80);
  tail();
  popMatrix();
}
void tail() {
  beginShape();
  curveVertex(-120, 0);
  curveVertex(-120, 0);
  curveVertex(-125, -5);
  curveVertex(-60, -40);
  curveVertex(30, -50);
  curveVertex(30, -50);
  endShape();
  beginShape();
  curveVertex(30, -50);
  curveVertex(30, -50);
  curveVertex(-60, -20);
  curveVertex(-120, 0);
  curveVertex(-120, 0);
  endShape();
}
void bigfishhead() {
  beginShape();
  curveVertex(-170, -40);
  curveVertex(-170, -40);
  curveVertex(-190, -20);  
  curveVertex(-200, 0);
  curveVertex(-190, 20);
  curveVertex(-170, 40);
  curveVertex(-170, 40);
  endShape();
  beginShape();
  curveVertex(-170, -40);
  curveVertex(-170, -40);
  curveVertex(-180, 0);
  curveVertex(-170, 40);
  curveVertex(-170, 40);
  endShape();
}
void bigfishbones()
{
  topbone();
  pushMatrix();
  for (int i = 0; i < 5; i++) {
    scale(0.85);
    topbone();
  }
  popMatrix();
  bottombone();
  for (int j = 0; j< 5; j++) {
    scale(0.85);
    bottombone();
  }
}
void topbone() {
  beginShape();
  curveVertex(-150, -15);
  curveVertex(-150, -15);
  curveVertex(-155, -17);
  curveVertex(-147, -35);
  curveVertex(-150, -42);
  curveVertex(-142, -55);
  curveVertex(-130, -95);
  curveVertex(-125, -100);
  curveVertex(-125, -100);
  endShape();
  beginShape();
  curveVertex(-125, -100);
  curveVertex(-125, -100);
  curveVertex(-150, -15);
  curveVertex(-150, -15);
  endShape();
}
void bottombone() {
  beginShape();
  curveVertex(-150, 20);
  curveVertex(-150, 20);
  curveVertex(-140, 45);
  curveVertex(-135, 53);
  curveVertex(-135, 53);
  endShape();
}
class Fishy {
  float size;
  float px;
  float py;
  float vx;
  float vy;
  float damping;
  boolean bLimitVelocities = true;

  // Constructor for the Fishy
  Fishy (float x, float y) {
    px = x;
    py = y;
    vx = vy = 0;
    damping = 0.96;
    size = random(0.5, 1.5);
  }

  // Add a force in. One step of Euler integration.
  void addForce (float fx, float fy) {
    float ax = fx;
    float ay = fy;
    vx += ax;
    vy += ay;
  }

  // Update the position. Another step of Euler integration.
  void update() {
    vx *= damping;
    vy *= damping;
    limitVelocities();

    px += vx;
    py += vy;
  }

  void limitVelocities() {
    if (bLimitVelocities) {
      float speed = sqrt(vx*vx + vy*vy);
      float maxSpeed = 10;
      if (speed > maxSpeed) {
        vx *= maxSpeed/speed;
        vy *= maxSpeed/speed;
      }
    }
  }

  void render() {
    noFill();
    pushMatrix();
    translate(px, py);
    fishy();
    endShape();
    popMatrix();
  }

  void fishy() {
    scale(size);
    beginShape();
    curveVertex(-10, 0);
    curveVertex(-10, 0);
    curveVertex(-5, -2);
    curveVertex(0, -3);
    curveVertex(5, -2);
    curveVertex(10, 0);
    curveVertex(10, 0);
    curveVertex(13, -3);
    curveVertex(13, -3);
    endShape();
    beginShape();
    curveVertex(-10, 0);
    curveVertex(-10, 0);
    curveVertex(-5, 2);
    curveVertex(0, 3);
    curveVertex(5, 2);
    curveVertex(10, 0);
    curveVertex(10, 0);
    curveVertex(13, 3);
    curveVertex(13, 3);
    endShape();
  }
}

Ticha-Sound Repulsion (updated)

./wp-content/uploads/sites/2/2013/10/waves.pdf
./wp-content/uploads/sites/2/2013/10/waves-3.pdf

UPDATE: Hopefully the first one will lasercut now.

When I approached the project initially, I really wanted to create a cellular simulation of sorts – I got as far as creating hideous ‘blobs’ formed by attaching various Spring objects to a centroid particle… but they looked so terrible (and defied too much physics) that I decided to scrap the idea completely and try something fresh. I was interested in making another semi-interactive piece – and as I had recently discovered that Processing supported audio, I decided to scour the internet for java libraries that potentially supported audio input. Fortunately, there existed an AudioInput Class that was easy to understand and was suitable for my purposes (kudos to CreativeCoding.org for introducing it to me).

Because I was creating a system that was affected by sound, I wanted to make a structure that visually cohered to the concept of sound, audio, or music. The final design ended up resembling a stylized vinyl record, which I am quite satisfied with. Additionally when the arcs get propagated outwards they somewhat resemble radio waves, which is another interesting effect. But despite how I am satisfied with how it turned out visually, I have mixed feelings towards its functionality. To maintain a certain degree of order, I initially intended to create springs that connected each arc to the centroid, so that after they had stretched out to a certain extent they would regain their initial positions. Perhaps it can be an adjustment I will work on in the future.

The code is here, but the application itself must be downloaded to work properly. I should also add that the PDF recording option was adapted from Michelle’s clever recording trick, which comes in handy for ‘screenshotting’ Processing output windows. 😀

Rain Water-Maryyann Landlord

In the beginning, I wanted started with the idea of creating a 3 dimensional object from the 2 dimensional cut outs. It would be cut out into separate parts and then assembled after the pieces were popped out. My idea was a fish, with 9 circular disks as “ribs” and supporting beams going around the body as well as fins and a tail. However, after making some calculations, I realized how precise the measurements would have to be and the fact that aesthetically speaking, a generated pattern of sorts would have a better visual appeal.

Images of my idea:

IMG_4211

IMG_4212

Next I explored other areas that would create a more visually pleasing piece. Since we recently learned about particles, I decided to incorporate that into my piece. I thought about the effect of rain dropping on the ground on a rainy day. From there my thoughts wondered towards the comparisons of the effects of water. How could I show contrasts between the same element? I also wanted to explore text because I had never used text in my pieces before.

Following that thought, I decided to represent rain drops using letters of the alphabet,which was the first appearance of water. The “rain” fell slightly at an angle, at different speeds which gave it the calming appearance of rain. I needed more types of water. So, I placed an invisible pool of water at the bottom of the piece, which gathered the rain letters and slowly dispensed them to the bottom, where they were recycled back as rain. I thought it was interesting that the letters, which begin as rain(water) fall into another pool of water, but then gain the appearance of a solid object while the viewer still understood them as rain drops.

This is a fairly simple design which I think creates more satisfaction as a animated piece than a static one. A single photo merely doesn’t contain the comparison of the water against water as the moving piece contains. I do understand though, laser cutting letters may become a problems due to the little number of closed shapes that come with the alphabet, but I think it’ll be interesting to see how it plays out.

use the arrow keys to see it animate:

./wp-content/uploads/sites/2/2013/10/rain.pdf

update:

After downloading the geomerative library, I used it to tweak my code so that all the falling letters became outlines. Now, the laser cutting will be able to cut around the shape and they will become visible. One problem I realized I had after first remaking the piece, was that certain letters would have huge holes because of the way the letters connected to themselves. So, I changed the ending to the letters and reconnected it to another point and therefore leaving another space for the laser cutting to go around. I added a phrase as well in the various letters so that when people look closely, they will find a present surprise.  Another add on I implemented was a repulsion force the letters had towards every other letter. However, because the library and the number of letters made the code run quite slowly, the repulsion didn’t work as well as I wanted it to. I do hope that after changing the code, the laser cutting will cut the pdf correctly.

updated:

./wp-content/uploads/sites/2/2013/10/rain1.pdf

./wp-content/uploads/sites/2/2013/10/rain2.pdf
 

./wp-content/uploads/sites/2/2013/10/rain3.pdf

Segregation and Other Intolerant Algorithms [Lasercut Screen]

./wp-content/uploads/sites/2/2013/10/output1.pdf

Drawing loosely from the Nervous System presentation, I began thinking about processes I could exploit to churn out varied, yet unified designs. While searching for information about laplacian growth, I found this pithy sketch by echoechonoisenoise on OpenProcessing, which employs a grid of automata to generate a segregation pattern.

My cells are similarly situated in a grid, wherein three main processes occur. First, a matrix of cells is seeded by a scaled noise field, which is in turn refined and restricted using the modulus operator and a threshold. This design is problematic out of the tube, since the laser cutter wants lines and not filled blobs.

Filled blobs, before the outlines are isolated

So the second step is to use a neighbor-counting technique similar to echoechonoisenoise’s to isolate the border of the blob shapes. (If a cell has three out of eight possible neighbors, I can assume with some confidence that it is a bordering cell.) Third, to convert a set of disparate points to vector lines, I plot lines from each cell to the nearest available living cell.

Disclaimer: I try to produce smooth-ish lines in a relatively straight-forward fashion, but I admit that there are instances of weirdo trickery in my code:

import processing.pdf.*;

float cells[][];
float noiseScale = 100.0;
float scaleFactor = 1;
int dist = 3;
//density of pattern
int bandWidth = 1200;
//noise seed
int seed = 9;
int[] rule = {
  0, 0, 0, 1, 0, 0, 0, 0, 0
};
int searchRad = 12;
int cellCount = 0;

void setup() {
  size(900, 900); 
  cells = new float[width][height];
  generateWorld();
  noStroke();
  smooth();
  beginRecord(PDF, "output.pdf");
}

void generateWorld() {
  noiseSeed(seed);
  //Using a combination of modulus and noise to generate a pattern
  for (int x = 0; x < cells.length; x++) {
    for (int y = 0; y < cells[x].length; y++) {       float noise = noise(x/noiseScale, y/noiseScale);       if (x % int(bandWidth*noise) > int(bandWidth*noise)/2) {
        cells[x][y] = 0;
      }
      else if (y % int(bandWidth*noise) > int(bandWidth*noise)/2) {
        cells[x][y] = 0;
      }
      else {
        cells[x][y] = 1;
      }
    }
  }
}

void draw() {
  background(255);
  drawCells();
  //Draw the world on the first frame with points, connect the points on the second frame
  if (frameCount == 1) updateCells();
  else {
    for (int x = 0; x < cells.length; x++) {
      for (int y = 0; y < cells[x].length; y++) {         if (cells[x][y] > 0) {
          stroke(0);
          strokeWeight(1);
          //Arbitrary 
          for (int i = 0; i < 20; i++) {
            PVector closestPt = findClosest(new PVector(x, y));
            line(x * scaleFactor, y * scaleFactor, closestPt.x*scaleFactor, closestPt.y*scaleFactor);
          }
        }
      }
    }
    endRecord();
    println("okay!");
    noLoop();
  }
}

//Finds closest neighbor that doesn't already have a line drawn to it
PVector findClosest(PVector pos) {
  PVector closest = new PVector(0, 0);
  float least = -1;
  for (int _y = -searchRad; _y <= searchRad; _y++) {
    for (int _x = -searchRad; _x <= searchRad; _x++) {
      int x = int(_x + pos.x), y = int(_y + pos.y);
      float distance = abs(dist(x, y, pos.x, pos.y));
      if (x < 900 && x > 0 && y < 900 && y > 0) {
        if (distance != 0.0 && (cells[x][y] == 1) && ((distance < least) || (least == -1))  
          && cells[x][y] != 2) {
          least = distance;
          closest = new PVector(x, y);
        }
      }
    }
  }
  cells[int(closest.x)][int(closest.y)] = 2;
  if (closest.x == 0 && closest.y == 0) return pos;
  else return closest;
}

//If the sum of the cell's neighbors complies with the rule, i.e. has exacly 4 neighbors,
//it is left on, otherwise it is turned off. This effectively removes everything but the 
//outlines of the blob patterns. 
void updateCells() {
  for (int x = 0; x < cells.length; x++) {
    for (int y = 0; y < cells[x].length; y++) {
      cells[x][y] = rule[sumNeighbors(x, y)];
      if (cells[x][y] == 1) cellCount ++;
    }
  }
}
int sumNeighbors(int startx, int starty) {
  int sum = 0;
  for (int y = -1; y <= 1; y++) {
    for (int x = -1; x <= 1; x++) {
      int ix = startx + x, iy = starty + y;
      if (ix < width && ix >= 0 && iy >= 0 && iy < width) {
        if (cells[ix][iy] == 1) {
          if (x != 0 || y != 0) sum++;
        }
      }
    }
  }
  return sum;
}

void drawCells() {
  loadPixels();
  for (int x = 0; x < cells.length; x++) {
    for (int y = 0; y < cells[x].length; y++) {
      int index = (int(y*scaleFactor) * width) + int(x*scaleFactor);
      if (cells[x][y]==1) {
        pixels[index] = color(255);
      }
    }
  }
  updatePixels();
}

void mousePressed() {
  saveFrame(str(random(100)) + ".jpg");
}

 

Laser Cut – Fallen Leaves

./wp-content/uploads/sites/2/2013/10/screen_output.pdf

This is my first attempt at data visualization. Each leaf represents the amount of deaths per 100,000 people caused by a category of cancer in 2009. The size of each leaf is proportional to square root of 5 to those numbers.

The tree is also generated by Processing by consecutively drawing smaller rectangles. The leaves are made from Bezier curves.

I was inspired by “Epilogue” by The Antlers in regards to cancer.

Thanks to CDC for their data.

http://apps.nccd.cdc.gov/uscs/cancersbyraceandethnicity.aspx

int square_width = 15;
import processing.pdf.*;


PVector[] leaves;

// these represent cancer death rate per 100,000 people in 2009 US
// data from CDC http://apps.nccd.cdc.gov/uscs/cancersbyraceandethnicity.aspx
float[] rates = {3.7, 54.6, 64.3, 1.5, 5.7, 0.3, 22.4, 13.7,
				 0.1, 5.3, 0.8, 8.6, 4.2, 9.5, 1.5, 14.9};

void setup() {
  randomSeed(15251);
  smooth();
  noLoop();
  size(640, 640 , PDF, "output.pdf");
  //size(640, 640);
}

void draw() {
	background(255);
	fill(0);
	
	pushMatrix();
	translate(width/2-50, 0);
	scale(0.75, -0.75);
	draw_trunk(0, 0, 30.0, 200, 30);
	popMatrix();
	noFill();

	leaves = new PVector[rates.length];
	for(int i = 0; i < rates.length; i++)
	{
		pushMatrix();
		float r = rates[i];
		float x = random(30, width - 30);
		float y = 250+4*r+random(-30, 200);

		// loop through old leaves
		for(int j = 0; j < i; j++)
		{
			float old_x = leaves[j].x;
			float old_y = leaves[j].y;

			// if similar position, set new
			if((old_x + 50.0 > x && old_x - 50.0 < x) ||
			   (old_y + 50.0 > y && old_y - 50.0 < y))
			{
				x = random(30, width - 30);
				y = 250+4*r+random(-30, 200);
			}
		}

		leaves[i] = new PVector(x, y);

		translate(x, y);
		rotate(radians(random(-170, -10)));
		scale(pow(r, 0.2), pow(r, 0.2));
		draw_leaf(0.0,0.0);
		popMatrix();
	}
	exit();
}

  void draw_leaf(float x, float y)
  {
    bezier(x+10, y-3, 
           x+5, y-8, 
           x-5, y-8, 
           x-10, y);
    bezier(x+10, y+3, 
           x+5, y+8, 
           x-5, y+8, 
           x-10, y);

    strokeWeight(0.7);
    bezier(x+15, y, 
           x+12, y-2, 
           x-2, y+2, 
           x-5, y);

    strokeWeight(0.3);
    line(x+7, y, x+5, y-3);
    line(x+7, y, x+5, y+4);

    line(x+3, y+0.2, x+1, y-3);
    line(x+3, y+0.2, x+1, y+4);

    line(x-1, y+0.2, x-3, y-3);
    line(x-1, y+0.2, x-3, y+3.5);
    strokeWeight(1);
    
  }

void draw_trunk(int x, int y, float tree_thickness, int tree_height, int segments)
{
  pushMatrix();
  float current_tree_thickness = tree_thickness;
  float segment_height = tree_height/segments;

  translate(x,y);

  for(int i = 0; i < segments; i++)
  {
    translate(0, -segment_height);
    rect(0, 0, current_tree_thickness, segment_height*2.0);
    rotate(random(-0.1,0.1));
    current_tree_thickness *= 0.97;
  }

  for(int i = 0; i < 10; i++)
  {
    float random_scale = random(0.3, 3.0);
    draw_branch(0,0,radians(random(-30,40)),random_scale, random_direction());
  }

  popMatrix();
}

void draw_branch(int x, int y, float theta, float curve_scale, int direction)
{

  float len = 20.0;
  float branch_width = 5.0;

  pushMatrix();
  translate(x,y);
  rotate(theta*-1*direction);
  scale(direction, 1);
  
  if(direction < 0.0)
    translate(-25,0);
  else
    translate(-20,0);

  int branch_blocks = (int)random(2, 6);


  for(int i = 0; i < 80; i++)
  {
    translate(len, 0);
    rotate(random(-0.15, 0.05));
    rect(0,0,len,branch_width);
    branch_width *= 0.9;
    len = len*0.9;
  }
  popMatrix();
}

int random_direction()
{
  if(random(-1,1) > 0)
    return 1;
  else
    return -1;
}

Lasercut 2.0 – Cracks

./wp-content/uploads/sites/2/2013/10/cracks3.pdf

The results:

img001

img002

I changed my idea for the lasercut after the lecture today. Because of the limitations on shapes you can make with the lasercut, I decided to go back to using simple lines. I remembered back to the Recursive Trees code in the book Form + Code by Casey Reas and decided to search around the internet for similar code. Most trees had the problem of intersecting lines that would be impractical to lasercut. I was also thinking about the instructional art we had to engineer in an earlier assignment, because it was able to stop drawing lines once it detected another line.

Then I was looking at particle systems on OpenProcessing and found this one code called “Roots” that uses nodes like particles, and creates new nodes based on their distance from other nodes. His inspiration was Rapidly-exploring Random Trees (RRT). The link to that person’s code is here: https://openprocessing.orgsketch/38518

So I thought that would be very applicable to a lasercut, where everything has to be intact. I studied and grossly simplified the code to the point where I could understand it and modeled the growth of the nodes to match the Lissajous curves we learned in class. (Although, the circle still looked the best out of the various PDFs I saved…)

Here are my sketches:

photo (2)

photo (3)

Unfortunately, my code doesn’t work in Javascript so I can’t show it on OpenProcessing, but it is below:

// Credit goes to Alexander Mordvintsev for his code "Roots"
// which was inspired by RRT (Rapidly-exploring Random Trees)
// See here: https://openprocessing.orgsketch/38518

import processing.pdf.*;

ArrayList nodes;
int     branching    = 100;
float   branchLength = 5.0;
 
void setup()
{
  size(500,500);
  background(255);
  strokeWeight(1);
  smooth();
  nodes = new ArrayList();
  beginRecord(PDF, "cracks1.pdf");
}

void draw() {
  // Adds the parent node
  if (nodes.size() == 0)
    nodes.add(new Node(width-20,height/2));
  // Accelerates the amount of growth per frame
  for (int i=0; i<10; i++)
    grow();
}

void keyPressed() {
  endRecord();
  exit();
}

Node findNearest(Node p) {
  float minDist = 1e10;
  int minIndex  = -1;
  for (int i=0; i sq(branching));
  x += px;
  y += py;
  
  // Boundaries for the frame of the lasercut
  if(x>20 && x20 && y= branchLength) {
      Node newNode = new Node(base, sample);
      nodes.add(newNode);
      newNode.display();
    }
  }
}

class Node
{
  PVector pos;
  Node parent;
 
  Node(float x, float y) {
    pos = new PVector(x,y);
  }
  
  Node(Node base, Node sample) {
    PVector step = PVector.sub(sample.pos,base.pos);
    step.limit(5.0);
    pos = PVector.add(base.pos,step);
    parent = base;
  }
 
  float dist(Node other) {
    return PVector.dist(pos,other.pos);
  }
  
  // Draws a line between nearest node and new node
  void display() {
    if (parent!=null) {
      line(parent.pos.x, parent.pos.y, pos.x, pos.y);
    }
  }
}