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

Comments are closed.