KelseyLee-13-9-65

by kelsey @ 3:42 am 23 January 2012

 

Using Processing, I tried to replicate the piece 13/9/65 Nr. 2, by Frieder Nake . By storing all of the points in arrays to access later, I was able to slow down the output so that you can see each line being drawn.

/*
 *Kelsey Lee 13/9/65 Nr. 2, by Frieder Nake (born 1938, Germany)
 *trying to replicate  13/9/65 Nr. 2, by Frieder Nake (born 1938, Germany)
 *randomly selects widths of columns
 *randomly selects where to place horizontal lines, width of segments & incline/decline of those segments
 *will then chose whether the block created by the column/horizontal line barriers should contain 
 *straight lines, triangles/angles or nothing - if trianlges will choose whether to originate from top or bottom
 *when done, will randomly select number of circles, radius of circles and placement of circles
 *
 *  ***will draw it line by line so you can see process***
 */
 
int WIN_WIDTH = 600;
 
int COLS;
int CUBE_WIDTH_MIN = 30;
int CUBE_WIDTH_MAX = 80;
 
int[]colSegments = new int[int(WIN_WIDTH/CUBE_WIDTH_MIN)+1];
 
horizLine startHorizLine;
horizLine endHorizLine;
horizLine screenBottom;
 
vertLineHolder vertHolder;
vertLineSeg vertSeg;
 
int ctr;
int horizCtr;
int yHeight;
int circleCtr;
int numCircles;
 
String phase;
boolean moreVert;
boolean lastLine;
 
int CUBE_HEIGHT_START_MIN = 60;
int CUBE_HEIGHT_START_MAX = 100; //prior to sloping lines up or down
 
void setup(){
  size(WIN_WIDTH, WIN_WIDTH); //create window
  stroke(0);
  strokeWeight(1.5);
  smooth();
  background(255); 
  frameRate(40);
   yHeight =  0;
   lastLine = false;
 
   startHorizLine = new horizLine(0);
   startHorizLine.createTop();
 
   screenBottom = new horizLine(WIN_WIDTH);
   screenBottom.createBottom();
 
   //find column widths
   colSegments[0] = int(random(CUBE_WIDTH_MIN,CUBE_WIDTH_MAX)); //generates first cube width
   ctr=1;
   COLS=0;
   //randomly chose width of column until nearly at edge of screen, make sure last column is at least min cube width
   while ((colSegments[ctr-1]+CUBE_WIDTH_MIN)  endHorizLine.numPts) {
           phase="startVertSeg";
        }
    }  
    else if (phase == "startVertSeg") {
        vertHolder = new vertLineHolder(startHorizLine, endHorizLine);
        moreVert = vertHolder.drawLine();
        phase = "continueVertSeg"; 
    }
    else if (phase == "continueVertSeg") {
       moreVert = vertHolder.drawLine();
       if (moreVert == false) {
        // print("end vert seg\n");
         phase = "endVertSeg"; 
       }
    }
    else if (phase == "endVertSeg") {
       phase = "endHorizLineBegin";
       startHorizLine = endHorizLine; //now the bottom horizontal line is the starting horizontal line for the next iteration
       yHeight += int(random(int(WIN_WIDTH/10),int(WIN_WIDTH/8))); //choose starting height of the next line 
       if (lastLine == true) {
        phase = "circles"; 
       }
       if((yHeight+CUBE_HEIGHT_START_MAX+(CUBE_HEIGHT_START_MAX/5)) >= WIN_WIDTH) {
          lastLine = true;
       }
    }
    else if (phase == "circles") {
      boolean endOfCircles = makeCircles(); // draw circles
      if (endOfCircles == true) {
        phase="completed";
      }
  }
 
  if (phase == "completed"){
    noLoop();
  }
}
 
 
 
//make line equation from horizontal line of points and plug in known xVal to find the yVal
float findYVal(int xVal, int[][]horizLine) {
   int ctr = 0;
   boolean foundY = false;
   float yVal =0;
 
  //find which column this xVal is in
  while (foundY == false) {
    //if true, xVal is in this column
     if (xVal >=  horizLine[ctr][0] && xVal <= horizLine[ctr][2]) {  
       //line eq, plug in x 
       yVal = float(horizLine[ctr][3]-horizLine[ctr][1])/float(horizLine[ctr][2]-horizLine[ctr][0])*float(xVal-horizLine[ctr][2]) +horizLine[ctr][3];
       foundY=true;
      }
      else {
        ctr++; 
      }
  }
  return yVal;
}
 
/* 
 * structure that holds a whole row's worth of vertical line segments
 * keeps track of which segment is being drawn & which line in that segment is being drawn.
 * creates many vertLineSeg structures which contain the points of all vertical lines to be drawn
 */
class vertLineHolder{
  vertLineSeg[] segs = new vertLineSeg[COLS]; //holds vertical line segments
  horizLine startLine; 
  horizLine endLine;
  int col; //for total number of columns
  int currentCol; //used later to iterate through all columns
  int currentLine; //keeps track of which line in a segment is being drawn
 
  //constructor
  vertLineHolder(horizLine startHorizLine, horizLine endHorizLine){
      startLine = startHorizLine;
      endLine = endHorizLine;
      col = 0; 
      int vertLineStart = 0;
      currentCol = 0;
 
      //now create segments for whole row; randomize type of vertical lines for segment
      while (colSegments[col+1] < WIN_WIDTH) {
       // print("col: " +col);
         int vertLineEnd = colSegments[col];
 
         int pattern = int(random(0,8)); //0,1 -vert lines; 2,3 - triangles, 4-8 -empty makes it  5/8ths likely that nothing will be drawn
         //when creating vertLineSeg, call that constructor to choose lines
         if (pattern  segs[currentCol].numLines-1) {
      //  print("from check to next col update col \n\n");
         currentLine=0;
         currentCol+=1; 
      }
    }
 
    //if now onto a column that exceeds the number of columns present, then must go to next row to draw
    if (currentCol >= COLS) {
   //   print("resetCol \n");
        currentCol = 0;
       return false; //meaning row is done being drawn
    }
    else {
      return true; //row is not done being drawn
    }
  }
}
 
 
//a single segment of vertical lines
class vertLineSeg {
  int numLines;
  int type; //type of lines
  int vertSeg;
  int vertStart; // value of starting x
  int vertEnd; // valiue of ending x
  float [][]segPts; // array of points for this segment
  int currentLine; //current line being drawn
 
 
   vertLineSeg(horizLine startHorizLine, horizLine endHorizLine, int t, int vertLineStart, int vertLineEnd) {
      type = t; // for straight or angled lines
      vertSeg = 0;
      vertStart = vertLineStart; // value of starting X
      vertEnd = vertLineEnd; //value of ending X
 
      currentLine =0; //current Line being created
 
      int lineCtr = 0; // the line being drawn
      numLines = int(random(1,(vertEnd-vertStart)/6)); //arbitrary 6 - total number of lines/angles for this seg,ent
 
      segPts = new float[(numLines*2)][4]; //array of points
 
 
 
      if (type == 1) { // straight lines
      //print(" lines: " + numLines + " | ");
       while (lineCtr  WIN_WIDTH) {
               startXVal=WIN_WIDTH;  //don't draw past end of screen
          }
          float yValStart = findYVal(startXVal, startHorizLine.horizPts);
          float yValEnd = 0;
 
          yValEnd = findYVal(startXVal, endHorizLine.horizPts);
          //store values
          segPts[lineCtr][0] = segPts[lineCtr][2] = startXVal;
          segPts[lineCtr][1] = yValStart;
          segPts[lineCtr][3] = yValEnd;
          lineCtr+=1; //increment to create next line
       }
 
      }
      else if (type==2) { //create angles starting from top
        numLines *=2;  // will need to store double the amount of lines b/c 2 lines for angle
     //   print(" lines: " + numLines + " | ");
        while ((lineCtr+2)  WIN_WIDTH) {
               startXVal=WIN_WIDTH;  //don't draw past end of screen
          }
          float yValStart = findYVal(startXVal, startHorizLine.horizPts);
          float yValEnd = 0;
          //create both lines of angle
          for (int i=0; i WIN_WIDTH) {
                   endXVal=WIN_WIDTH; 
               }    
                yValEnd = findYVal(endXVal, endHorizLine.horizPts);
 
                segPts[lineCtr][0] = startXVal;
                segPts[lineCtr][1] = yValStart;
                segPts[lineCtr][2] = endXVal;
                segPts[lineCtr][3] = yValEnd;
                lineCtr+=1;
          }
       }
      }
      else if (type == 3) { // create angles starting from bottom
        numLines *=2; 
     //   print(" lines: " + numLines + " | ");
        while ((lineCtr+2)  WIN_WIDTH) {
               startXVal=WIN_WIDTH;  //don't draw past end of screen
          }
          float yValStart = findYVal(startXVal, endHorizLine.horizPts);
           float yValEnd = 0;
          for (int i=0; i WIN_WIDTH) {
                   endXVal=WIN_WIDTH; 
               }    
               yValEnd = findYVal(endXVal, startHorizLine.horizPts); //ending yVals are on the top horizontal line
 
                segPts[lineCtr][0] = startXVal;
                segPts[lineCtr][1] = yValStart;
                segPts[lineCtr][2] = endXVal;
                segPts[lineCtr][3] = yValEnd;
                lineCtr+=1;
          }
        }
      }
 //  print( "\n");
 } 
}
 
//creates a horizontal line
class horizLine {
   int[][]horizPts = new int[10][4]; // stores points for horiz line
   int numPts;
   int minStartY; // starting Y
   int horizCtr; //number of horiz segments
 
   horizLine (int y){
      numPts = 0;
      minStartY = y;
      horizCtr=0;
   } 
 
   //line for top of screen
   void createTop() {
     horizPts[0][0] = horizPts[0][1] = horizPts[0][3] = 0;
     horizPts[0][2] = WIN_WIDTH;
   }
 
   //line for bottom of screen
   void createBottom() {
     horizPts[0][0]= 0;
     horizPts[0][1] = horizPts[0][2] = horizPts[0][3] = WIN_WIDTH;
   }
 
   // all other lines
   void createLine(){
     int remainingWidth = WIN_WIDTH;
 
      //starting coordinate
      int startX=0; 
      int startY = minStartY + int(random(CUBE_HEIGHT_START_MIN ,CUBE_HEIGHT_START_MAX));
 
      //line can slope up or down only w/in the following range - so as not to allow the horizontal lines to intersect with each other
      int minY = startY - ((startY-minStartY)/5); 
      int maxY = startY + ((startY-minStartY)/5);
      numPts = 0;
      while (remainingWidth > 0) {
        //find ending point for hte line segment
        int endX = startX + int(random(CUBE_HEIGHT_START_MIN ,CUBE_HEIGHT_START_MAX));
        //if chosen end X coordinate is past the end of the screen, reset to end of screen
        if (endX > WIN_WIDTH || (endX+CUBE_WIDTH_MIN)>WIN_WIDTH) {
          endX = WIN_WIDTH;
         }
         //will this segment of line slope up (0) or down (1)
         int sign = int(random(0,1));
         int endY;
         if (sign == 0 ) {
           endY = int(random(minY, maxY));
          }
          else {
            endY = -1*int(random(minY, maxY));
          }
          //store that line segment
          horizPts[numPts][0] = startX;
          horizPts[numPts][1] = startY;
          horizPts[numPts][2] = endX;
          horizPts[numPts][3] = endY;
          numPts+=1;
 
          remainingWidth = WIN_WIDTH - endX;
          ctr+=1;
          //end point from previous segment becomes the start of the next
          startX = endX;
          startY = endY;
        }
       }
 
       int[][] getLine() {
          return horizPts; 
       }
 
}
 
 
//draw circles, xVal of center will fall inside a column
boolean makeCircles() {
  fill(255, 0);
 
  //randomly choose number of circles
 
  if (circleCtr < numCircles) {
    //randomly choose radius
    int circleRadius = int(random(CUBE_WIDTH_MIN,200))/2;
    int cubeNum  = int(random(1,COLS));
    int xCoord= int(random(colSegments[cubeNum-1],colSegments[cubeNum]));
    ellipse(xCoord, int(random(circleRadius,WIN_WIDTH-circleRadius)), circleRadius, circleRadius);
    circleCtr++;
  } 
  else {
   return true; 
  }
  return false;
}

Heather Knight – 13-9-65

by heather @ 11:34 pm 22 January 2012

  

In this program, I attempt to recreate the experience of witnessing Frieder Nake’s “13/9/65 Nr. 2” come to life. My functions create X-Y paths for the plotter pixel by pixel, and are mutually inspired the line-thicknesses and supporting-structures of a 3D-printer (hence the initial outline, and the white dot left each time the ‘nozzle’ is lifted). I wanted to create a modern-day instantiation and took poetic license with the simplifications of resulting forms. The most challenging part was deriving how to draw a circle without using a pre-built function, for which I borrowed an early computer graphics technique called the Midpoint Circle Algorithm.

[vimeo=https://vimeo.com/35554900]

Above you find a demo video of the program. My browser couldn’t handle my .jar but the file is here. Please find my code below. To run the program with full effect, download the printer soundclip here.

//Heather Knight - HW2.2 - "13-9-65" Plotter

import ddf.minim.*;

// states
boolean draw_outline=true;
boolean draw_lines=false;
boolean next_vertical = false;
boolean next_horizontal = false;
boolean carriage_return = false;
boolean next_circle=false;
boolean next_blip = false;
boolean done = false;

// screen variables
int x=0;
int y=0;
int w=640;
int h=480;
int liw=8; //linewidth

// function variables
int i=0;
int hjump=0;
int minjump=15;
int blipval = 0;
int circleval = 0;
int savey=0;
int savex=0;
boolean error=false;
boolean first = true;

// circle variables
int[] xarray = new int[1];
int[] yarray = new int[1];
int numpix=0; //number pixels per octant
int radius;
int rad_sq;
int j=0;
int center_x;
int center_y;

//sound
Minim minim;
AudioPlayer player;

void setup() {
  // set draw characteristics
  fill(255);
  // setup window
  size(w+liw, h+liw);
  //setup sound
  minim = new Minim(this);
  player = minim.loadFile("printer.wav");
  player.loop();
  println("Setup Complete");
}

void draw() {
  i += 1;
  //println(i);
  if (draw_outline) {
    if (!first&&(x==0)&&(y==0)) {
      draw_outline=false;
      draw_lines=true;
      next_vertical=true;
    }
    else if ((x<w)&&(y==0)) {
      x = x + 1;
      first = false;
      //println("top");
    }
    else if ((x==w)&&(y0)) {
      x = x - 1;
      //println("bottom");
    }
    else if ((x==0)&&(y>0)) {
      //println("leftside");
      y = y - 1;
    }
    else{
      error=true;
      println("error");
    }
  }
  else if (draw_lines) {
    if(next_vertical){
      if(y==h){
        player.close();
        println("done");
        next_vertical=false;
        done = true;
      }
      else{
        hjump=int(random(h)/3);
        if(hjumph){
          println("jump down!");;
          hjump = h-y;
          y=h;
        }else{
          y=y+hjump;
        }
        next_vertical=false;
        next_horizontal=true;
      }
    }
    else if(next_horizontal){
      blipval = int(random(100));
      if (x==w){
        next_horizontal=false;
        carriage_return=true;
      }
      else if (blipval < 2){
        //randomly decide on brips travel up
        println("blip!");
        savey=y;
        next_blip = true;
        next_horizontal = false;
      }
      else{
        //travel horizontally
        x+=1;
      }
    }
    else if(next_blip){
      if(y==(savey-hjump)){
      y=savey;
      next_blip=false;
      next_horizontal=true;
      }
      else{
        y=y-1;
      }
    }
    else if(carriage_return){
      circleval = int(random(1000));
      if (x==0){
        carriage_return=false;
        next_vertical=true;
      }
      else if (circleval < 2){
        //randomly decide on brips travel up
        println("circle!");
        //circle inits
        center_y=x;
        center_x=y-hjump/2;
        radius=hjump/2;
        if(((center_x+radius/2)=0)&((center_y+radius/2)=0)){
          savey=y;
          savex=x;
          next_circle = true;
          calc_circle(radius);
          carriage_return = false;
        }
      }
      else{
        //travel horizontally back to zero
        x-=1;
      }
    }
    else if(next_circle){
      j+=1;
      if(j<numpix){
        println("j="+j+" yval="+yarray[j]+" xval="+xarray[j]);
        ellipse(yarray[j]+center_y,xarray[j]+center_x,liw,liw);
        if(j==numpix-1){
        println("octant1 done");
        }
      }
      else if(j<numpix*2){
        ellipse(xarray[numpix-(j-numpix)-1]+center_y,yarray[numpix-(j-numpix)-1]+center_x,liw,liw);
        if(j==numpix*2-1){
          println("octant2 done");
        }
      }
      else if(j<numpix*3){
        ellipse(xarray[j-numpix*2]+center_y,-yarray[j-numpix*2]+center_x,liw,liw);
        if(j==numpix*3-1){
           println("octant3 done");
        }
      }
      else if(j<numpix*4){
        ellipse(yarray[numpix-(j-numpix*3)-1]+center_y,-xarray[numpix-(j-numpix*3)-1]+center_x,liw,liw);
        if(j==numpix*4-1){
           println("octant4 done");
        }
      }
      else if(j<numpix*5){
        ellipse(-yarray[j-numpix*4]+center_y,-xarray[j-numpix*4]+center_x,liw,liw);
        if(j==numpix*5-1){
           println("octant5 done");
        }
      }
      else if(j<numpix*6){
        ellipse(-xarray[numpix-(j-numpix*5)-1]+center_y,-yarray[numpix-(j-numpix*5)-1]+center_x,liw,liw);
        if(j==numpix*6-1){
          println("octant6 done");
        }
      }
      else if(j<numpix*7){
        ellipse(-xarray[j-numpix*6]+center_y,yarray[j-numpix*6]+center_x,liw,liw);
        if(j==numpix*7-1){
          println("octant7 done");
        }
      }
      else if(j=radius/2){
      yy=yy+1;
      xx=int(sqrt(rad_sq-yy*yy));
      xarray=append(xarray, xx);
      yarray=append(yarray, yy);
  } 

  println("xarray.length "+xarray.length);
  numpix=xarray.length;
  j=0;
}

void stop()
{
  //player.close();
  minim.stop();
  super.stop();
}

 

EvanSheehan-13-9-65

by Evan @ 11:29 pm


Also available here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
PVector[][] vertices;
 
void setup() {
  size(600, 600);
  background(255);
  smooth();
 
  vertices = new PVector[int(random(5, 10)) + 1][int(random(6, 10)) + 1];
 
  for (int i = 0; i < vertices.length; i++) {
    PVector row[] = vertices[i];
 
    for (int j = 0; j < row.length; j++) {
      int x = 0, y = 0;
 
      if (i > 0) {
        x = int(vertices[0][j].x);
      } else if (j > 0) {
        x = int(row[j - 1].x + random(width / 10, width / 6));
        if (x > width || j >= row.length - 1) {
          x = width;
        }
      }
 
      if (i > 0) {
        do {
          float dy = random(height / 10, height / 5);
          y = int(vertices[i - 1][j].y + dy);
        } while (y < vertices[i - 1][j].y);
 
        if (y > height) {
          y = height;
        }
      }
 
      row[j] = new PVector(x, y);
    }
  }
 
  noFill(); 
  noLoop();
}
 
void draw() {
  // Set up margins and border
  scale(0.9);
  translate(.05 * width, .05 * height);
  rect(0, 0, width, height);
 
  for (int i = 0; i < vertices.length; i++) {
    PVector row[] = vertices[i];
    PVector last = row[0];
 
    for (int j = 1; j < row.length; j++) {
      PVector v = row[j];
 
      if (i+1 < vertices.length) {
        float p = random(1.0);
        if (p < 0.4) {
          verticalLines(last, v, vertices[i+1][j-1], vertices[i+1][j]);
        } else if (p < 0.65) {
          drawTriangles(last, v, vertices[i+1][j-1], vertices[i+1][j]);
        }
      }
 
      line(last.x, last.y, v.x, v.y);
      last = v;
    }
  }
 
  for (int i = 0; i < random(1, 6); i++) {
    int r = int(random(10, height / 4));
    ellipse(int(random(r / 2, width - r / 2)), int(random(r / 2, height - r / 2)), r, r);
  }
 
  save("plotter.tif");
}
 
void verticalLines(PVector tl, PVector tr, PVector bl, PVector br) {
  float top_slope = (tr.y - tl.y) / (tr.x - tl.x);
  float bottom_slope = (br.y - bl.y) / (br.x - bl.x);
  float top_b = tl.y - top_slope * tl.x;
  float bottom_b = bl.y - bottom_slope * bl.x;
 
  for (int i = 0; i < random(30); i++) {
    int x = int(random(tl.x, tr.x));
    line(x, top_slope * x + top_b, x, bottom_slope * x + bottom_b);
  }
}
 
void drawTriangles(PVector tl, PVector tr, PVector bl, PVector br) {
  float top_slope = (tr.y - tl.y) / (tr.x - tl.x);
  float bottom_slope = (br.y - bl.y) / (br.x - bl.x);
  float top_b = tl.y - top_slope * tl.x;
  float bottom_b = bl.y - bottom_slope * bl.x;
 
  for (int i = 0; i < random(30); i++) {
    int x = int(random(tl.x, tr.x));
    int x2 = int(random(tl.x, tr.x));
    int x3 = int(random(tl.x, tr.x));
 
    while (x3 == x2) {
      x3 = int(random(tl.x, tr.x));
    }
 
    if (random(1.0) < 0.3) {
      line(x2, top_slope * x2 + top_b, x, bottom_slope * x + bottom_b);
      line(x3, top_slope * x3 + top_b, x, bottom_slope * x + bottom_b);
    } else {
      line(x, top_slope * x + top_b, x2, bottom_slope * x2 + bottom_b);
      line(x, top_slope * x + top_b, x3, bottom_slope * x3 + bottom_b);
    }
  }
}

EliRosen – 13-9-65

by eli @ 10:27 am


/**
 * Program to recreate 13/9/65 by Frieder Nake
 * Creates a random drawing similar to Nake's drawing
 */
 
int drawWidth = 600;
int drawHeight = 600;
 
float numCircles = random(6,10);
 
int numLines = 11;
int numVertices = 8;
 
// Create arrays to hold x, y coords
// holds x coords of the vertices
float[]x = new float[numVertices];
/* holds y coordinates of the vertices, where the first index refers to the vertical grid line it falls on (counted left to right)
 * and the second index refers to the zigzag line it belongs to (counted top to bottom)
 */
float[][]y = new float[numVertices][numLines];
 
boolean[][]filled = new boolean[numVertices][numLines];
 
void setup()
{
  size(drawWidth, drawHeight);
  background(255);
  smooth();
  noFill();
  stroke(0);
 
  // sets minimum horizontal segment width
  int minSegmentWidth = 45;
  //set x position of vertices
  x[0]=0;
  for(int i =1; i&lt;numVertices-1; i++)
  {
    // creates random horizontal segment widths (vertical grid lines)
    x[i] = ((drawWidth/(numVertices-1))*i) + random((((drawWidth/(numVertices-1))-minSegmentWidth)*-1), ((drawWidth/(numVertices-1))-minSegmentWidth));
  }
  x[numVertices-1]=drawWidth-1;
 
  // bounds for random vertical offset from initial y value in zigzag line
  int vertBound = 45;
  //set y position of vertices
  //loop through all zigzag lines
  for(int iy = 0; iy &lt; numLines; iy++)
  {
    // loop through all vertical grid lines
    for(int ix = 0; ix &lt; numVertices; ix++)
    {
      if(iy==0)
      {
        y[ix][iy] = 0;
      }
      else if(iy==numLines-1)
      {
        y[ix][iy] = drawHeight;
      }
      else
      {
        y[ix][iy] = ((drawHeight/(numLines-1))*iy) + random((((drawHeight/(numLines-1))-vertBound)*-1), (drawHeight/(numLines-1))-vertBound);
      }
    }
  }
}
 
void draw()
{
  background(255);
  //Draw top line
  line(0,0,drawWidth,0);
  line(0,1,drawWidth,1);
  //draw bottom line
  line(0,drawHeight,drawWidth,drawHeight);
  line(0,drawHeight-1,drawWidth,drawHeight-1);
  line(0,drawHeight-2,drawWidth,drawHeight-2);
  //draw left line
  line(0,0,0,drawHeight);
  line(1,0,1,drawHeight);
  //draw right line
  line(drawWidth,0,drawWidth,drawHeight);
  line(drawWidth-1,0,drawWidth-1,drawHeight);
  line(drawWidth-2,0,drawWidth-2,drawHeight);
 
  // Draw all the zigzag lines
  //loop through all horizontal grid lines
  for(int iy = 1; iy &lt; numLines; iy++)
  {
    // loop through all vertical grid lines
    for(int ix = 1; ix &lt; numVertices; ix++)
    {
      //draw all the zig zag lines
      line(x[ix-1],y[ix-1][iy], x[ix],y[ix][iy]);
    }
  }
 
 
  //loop through all horizontal grid lines
  for(int iy = 1; iy &lt; numLines; iy++)
  {
    // loop through all vertical grid lines
    for(int ix = 1; ix &lt; numVertices; ix++)
    {
      //Draw the quadrilateral fills (this determines chance of getting any particular fill)
      int fillPick = int(random(0,12));
      // if fillPick is 0 do nothing
      // if fillPick is 1 then draw triangles
      if((fillPick &lt; 3) &amp;&amp; filled[ix][iy]==false)
      {
        // whether to put the point of the triangle on the to or bottom of the quadrilateral
        int dirPick = int(random(1,3));
 
        // declare slope and intercept variables for bottom and top of quadrilateral
        float slope1=0;
        float intercept1=0;
        float slope2=0;
        float intercept2=0;
 
        // if dirPick is 1 then put the point of the triangle at the top
        if(dirPick==1)
        {
          // the slope of the top bound of the current quadrilateral
          slope1 = (y[ix-1][iy-1]- y[ix][iy-1])/(x[ix-1]-x[ix]);
          // the y intercept of the top bound
          intercept1 = y[ix-1][iy-1] - (slope1*x[ix-1]);
 
          // the slope of the bottom bound of the current quadrilateral
          slope2 = (y[ix-1][iy]- y[ix][iy])/(x[ix-1]-x[ix]);
          // the y intercept of the bottom bound of the current quadrilateral
          intercept2 = y[ix-1][iy] - (slope2*x[ix-1]);  
        }
        // otherwise put the point at the bottom
        else
        {
          // the slope of the top bound of the current quadrilateral
          slope2 = (y[ix-1][iy-1]- y[ix][iy-1])/(x[ix-1]-x[ix]);
          // the y intercept of the top bound
          intercept2 = y[ix-1][iy-1] - (slope2*x[ix-1]);
 
          // the slope of the bottom bound of the current quadrilateral
          slope1 = (y[ix-1][iy]- y[ix][iy])/(x[ix-1]-x[ix]);
          // the y intercept of the bottom bound of the current quadrilateral
          intercept1 = y[ix-1][iy] - (slope1*x[ix-1]); 
        }
        // the number of triangles to draw
        float numTriangles = random(5, 10);
        // loop through the number of triangles
        for(int i=0; i 2 &amp;&amp; fillPick &lt; 6) &amp;&amp; filled[ix][iy]==false)
      {
        // the slope of the top bound of the current quadrilateral
        float slope1 = (y[ix-1][iy-1]- y[ix][iy-1])/(x[ix-1]-x[ix]);
        // the y intercept of the top bound
        float intercept1 = y[ix-1][iy-1] - (slope1*x[ix-1]);
 
        // the slope of the bottom bound of the current quadrilateral
        float slope2 = (y[ix-1][iy]- y[ix][iy])/(x[ix-1]-x[ix]);
        // the y intercept of the bottom bound of the current quadrilateral
        float intercept2 = y[ix-1][iy] - (slope2*x[ix-1]);
 
       // the number of lines to draw
        float numLines = random(5, 15);
        // loop through the number of lines
        for(int i=0; i&lt;numLines; i++)
        {
          // get a random x in the current quadrilateral
          float randomX1 = random(x[ix-1],x[ix]);
          // get a random y based on the random x (so that it falls on one of the quadrilateral bounding lines)
          float randomY1 = (slope1*randomX1)+intercept1;
          // get a random y based on the random x (so that it falls on one of the quadrilateral bounding lines)
          float randomY2 = (slope2*randomX1)+intercept2;
          // draw a lines to from the top to the bottom bounding lines
          line(randomX1, randomY1, randomX1, randomY2);
        } 
      }
      // if fillPick is 3 then draw straight lines down an extra row
      else if(fillPick == 6 &amp;&amp; iy &lt; numLines-1 &amp;&amp; filled[ix][iy]==false)
      {
        // the slope of the top bound of the current quadrilateral
        float slope1 = (y[ix-1][iy-1]- y[ix][iy-1])/(x[ix-1]-x[ix]);
        // the y intercept of the top bound
        float intercept1 = y[ix-1][iy-1] - (slope1*x[ix-1]);
 
        // the slope of the bottom bound of the current quadrilateral
        float slope2 = (y[ix-1][iy+1]- y[ix][iy+1])/(x[ix-1]-x[ix]);
        // the y intercept of the bottom bound of the current quadrilateral
        float intercept2 = y[ix-1][iy+1] - (slope2*x[ix-1]);
 
        // the number of lines to draw
        float numLines = random(5, 15);
        // loop through the number of lines
        for(int i=0; i&lt;numLines; i++)
        {
          // get a random x in the current quadrilateral
          float randomX1 = random(x[ix-1],x[ix]);
          // get a random y based on the random x (so that it falls on one of the quadrilateral bounding lines)
          float randomY1 = (slope1*randomX1)+intercept1;
          // get a random y based on the random x (so that it falls on one of the quadrilateral bounding lines)
          float randomY2 = (slope2*randomX1)+intercept2;
          // draw a lines to from the top to the bottom bounding lines
          line(randomX1, randomY1, randomX1, randomY2);
        }
        // set the lower quadrilateral to filled
        filled[ix][iy+1] = true; 
      }
    }
  }
 
 
  // Draw the circles
  for (int i = 0; i &lt; numCircles; i++)
  {
    // get a circle with a random circumference
    float circum = random(4, 100);
    // get the circle&#039;s radius
    float circRad = circum/2;
    // get the minimum x and y postion that would keep the circle in frame
    float minPos = 0+circRad;
    // get the maximum x and y position that would keep the circle in frame
    float maxPos = drawHeight-circRad;
    // draw the random circle
    ellipse(random(minPos, maxPos), random(minPos, maxPos), circum, circum);
  }
  delay(2500);
}

Nick Inzucchi – 13-9-65

by nick @ 8:02 pm 21 January 2012


 

#include "testApp.h"
 
int gap = 30;	// Ev!l globals
int noise = 4;
int nLines = 8;
int nPoints = 8;
int nCircles = 8;
 
//--------------------------------------------------------------
void testApp::setup(){
	ofBackground(255,255,255);
 
	ofNoFill();			// Setup Drawing
	ofSetColor(0,0,0);
	ofSetLineWidth(2);
}
 
//--------------------------------------------------------------
void testApp::draw(){
	drawLines();			// Draw each component
	drawStripes();
	drawCircles();
 
	ofSaveScreen(ofToString(ofGetFrameNum()));
	ofSleepMillis(2000);		// Save screen / rest
}
 
void testApp::drawLines(){	
	int w = ofGetWidth() - 2 * gap;		// Frame size
	int h = ofGetHeight() - 2 * gap;
 
	int hSpace = w / ( nPoints - 1 );	// Dist between lines / vertices
	int vSpace = h / ( nLines + 1 );
 
	for( int i = 0; i &lt; nLines; i++ ){	// Calc vertical divisions
		vertGrid[i] = vSpace * i + gap + vSpace + ofRandom( -vSpace / noise, vSpace / noise );
	}
	for( int i = 0; i &lt; nPoints; i++ ){	// Calc horizontal divisions
		horizGrid[i] = hSpace * i + gap + ofRandom( -hSpace / noise, hSpace / noise );
	}
	horizGrid[0] = gap;			// Move L/R vertices to edges
	horizGrid[nPoints - 1] = w + gap;
 
	for( int i = 0; i &lt; nLines; i++ ){	// Create vertex array for drawing
		for( int j = 0; j &lt; nPoints; j++ ){		
			lines[i][j].x = horizGrid[j];
			lines[i][j].y = vertGrid[i] + ofRandom( -vSpace / noise, vSpace / noise );
		}
	}
 
	for( int i = 0; i &lt; nLines; i++ ){	// Draw lines
		ofBeginShape();
		for( int j = 0; j &lt; nPoints; j++ ){
			ofVertex( lines[i][j].x, lines[i][j].y );
		}
		ofEndShape();
	}
 
	ofRect(gap, gap, ofGetWidth() - 2 * gap, ofGetHeight() - 2 * gap );	// Draw Frame
}
 
void testApp::drawStripes(){
	for( int i = 0; i &lt; nLines; i++ ){
		for( int j = 0; j &lt; nPoints - 1; j++ ){
			int type = ofRandom(0,2);		// Flip a coin
 
			if (type){				// Draw stripes if true
				int stripes = ofRandom(10,20);
				int crossed = ofRandom(0,2);	// Flip a coin straight/crossed
 
				ofVec2f leftUp = lines[i][j];	// Each block of stripes depends on 4 vertices
				ofVec2f rightUp = lines[i][j+1];
				ofVec2f leftDown = lines[i+1][j];
				ofVec2f rightDown = lines[i+1][j+1];
 
				for( int k = 0; k &lt; stripes; k++ ){
					ofVec2f lineStart;	// Draw a block of stripes
					ofVec2f lineEnd;
 
					lineStart.x = ofRandom( leftUp.x, rightUp.x );						
					lineEnd.x = (crossed) ? ofRandom( leftUp.x, rightUp.x ) : lineStart.x;
 
					float slopeUp = (rightUp.y - leftUp.y) / (rightUp.x - leftUp.x);
					float slopeDown = (rightDown.y - leftDown.y) / (rightDown.x - leftDown.x);
 
					lineStart.y = leftUp.y + ( ( lineStart.x - leftUp.x ) * slopeUp );
					lineEnd.y = leftDown.y + ( ( lineEnd.x - leftUp.x ) * slopeDown );
 
					if (i == nLines - 1){	// Account for final line
						lineEnd.y = ofGetHeight() - gap;
					}
					ofLine(lineStart.x, lineStart.y, lineEnd.x, lineEnd.y);
				}
			}
		}
	}
}
 
void testApp::drawCircles(){
	for( int i = 0; i &lt; nCircles; i++ ){	   	// Draw circles
		float r = ofRandom( 5, 50 );		// Randomize size
		ofCircle( ofRandom( gap + r, ofGetWidth() - gap - r ), ofRandom( gap + r, ofGetHeight() - gap - r), r);
	}
}

Nir Rachmel | 01-20-2012

by nir @ 10:34 pm 20 January 2012

Following is an image created by an algorithm inspired by Nake’s work from 1965.

 
Following is the code that generates an image following the same concepts as Nake's pioneering work in <a title="digital art" href="http://dam.org/artists/phase-one/frieder-nake" target="_blank">digital art</a> using a plotter.
 
NakeDraw myNake;
 
void setup() {
  size(801,801);
  background(255);
  stroke(0);
  myNake = new NakeDraw();
}
 
int drawOnce = 0;
 
void draw() {
  if (drawOnce == 0)
  {
    myNake.draw();
    drawOnce = 1;
  }
}
 
/**
* Class NakeDraw - Implements an algorithm to create an image inspired by Frieder Nake's work publshed 1956-57
* called Nr. 2 ("Klee").
* The image is composed of several repeated and random elements
* 1. Horizontal lines that "break" in the middle and change direction. They never intersect each other.
* 2. These lines create quadrilaterals between them.
* 3. Each quadrilateral can either be empty, have a random set of vertical+parallel lines or have a set of triangles
*
* Nir Rachmel, Interactive art and computational design, Jan 2012 (C)
* A link that helped analyze the original image: http://dada.compart-bremen.de/node/2875.
*/
class NakeDraw {
  int numOfRows; // number of rows on the canvas
  int numOfColumns; // number of columns on the canvas
  PVector[][] verticesArr; // array that holds all the vertices that define the skeleton of the horizontal lines
  float[] horizontalSpaces; // array to hold the distance that defines a horizontal section
  float baseBandWidth; // basic width between two consequtive horizontal lines (subject to noise)
  float verticalNoise; // vertical noise limit
  float smallNoise; // 
 
  // C'tor
  NakeDraw() {
    numOfRows = 11; // including both upper and lower frame borders
    numOfColumns = 9;
    verticesArr = new PVector[numOfRows][numOfColumns];
    horizontalSpaces = new float[] {1/6f, 1/6f, 1/12f, 1/6f, 1/12f, 1/12f, 1/6f, 1/12f};
    // Basic space between two horizontal lines
    baseBandWidth = height / 10;
    verticalNoise = baseBandWidth * 0.05;
    smallNoise    = baseBandWidth / 8;    
 
    // Initialize arrray
    for (int i=0 ; i &lt; numOfRows ; i = i+1)
    {
      for (int j=0 ; j &lt; numOfColumns ; j = j+1)
      {
        verticesArr[i][j] = new PVector(0,0);
      }
    }
 
  }
 
  // performs the drawing of the image. Using random numbers, the decision is made
  // for each quadrilateral if to leave it blank, fill it with horizontal lines or vertical lines.
  void draw()
  {
    // Draw the horizontal rows
     drawRows();
 
     // go over each quadrilateral and randomly draw lines / triangles / nothing
     int numOfBands = numOfRows -1;
     for (int i=0 ; i &lt; numOfBands ; i=i+1)
    {
       for (int j=0 ; j &lt; numOfColumns-1 ; j=j+1)
      {
         int pattern = int(random(0,3));
         if (pattern == 0)
         {
            drawVerticalLinesPattern(i,j);
         }
         if (pattern == 1)
         {
            drawTriangles(i,j);
         }
      }
    }
 
    // Circles are drawn on the image without relation to the other shapes.
    drawCircles();
  }
 
  /**
  * Draw the horiztonal rows.
  */
  void drawRows()
  {    
 
   // initialize top and bottom row (which are straight lines, part of the frame)
   verticesArr[0][0].set(0f,0f,0f);
   verticesArr[numOfRows-1][0].set(0f,height,0f);
   for (int j=1 ; j &lt; numOfColumns ; j=j+1)
   {
      float xVal = verticesArr[0][j-1].x + horizontalSpaces[j-1] * width;
      verticesArr[0][j].set(xVal, 0f, 0f);
      verticesArr[numOfRows-1][j].set(xVal,height,0f);
   }
 
    // Set the initial vertices on the left border
    for (int i=1 ; i&lt;numOfRows-1 ; i=i+1)
    {
       float yVal = 0;
       yVal = verticesArr[i-1][0].y + baseBandWidth + random(-verticalNoise, verticalNoise);
       verticesArr[i][0].set(0f,yVal,0f);
    }
 
    // start from each randomly generated vertex and draw a random horizontal line that stretches
    // all the way to the right border of the window. This line is not straight, and randomly changes its direction.
    for (int i=1 ; i &lt; numOfRows-1 ; i = i+1) // rows
    {
      for (int j=1 ; j &lt; numOfColumns ; j = j+1) // columns (first is already set)
      {
         float xVal = verticesArr[i][j-1].x + horizontalSpaces[j-1] * width;
         float yVal = verticesArr[i][j-1].y + random(-smallNoise, smallNoise);
         verticesArr[i][j].set(xVal, yVal, 0f);
          line(verticesArr[i][j-1].x,verticesArr[i][j-1].y,
               xVal, yVal);
      }
    }
  }
 
  /**
  * A helper function that calculates the y coordinates according to a given x coordinate, row and column
  * (that uniquely identifies a straight line on the screen)
  */
  float calculateY(int rowNum, int colNum, float xCoordinate, boolean isTop)
  {
       float yCoordinate = 0;
 
       if (isTop)
       {
         if (rowNum == 0)
         {
           yCoordinate = 0;
         }
         else
         {
           // y coordinate needs to be calculated for both top line and bottom.
           float slopeTop = (verticesArr[rowNum][colNum+1].y - verticesArr[rowNum][colNum].y) /
                       (verticesArr[rowNum][colNum+1].x - verticesArr[rowNum][colNum].x );
 
           float constValTop =  verticesArr[rowNum][colNum].y - slopeTop * verticesArr[rowNum][colNum].x;
 
           // now we have the equation, we can find the top coordinates for the vertical line
           yCoordinate = slopeTop * xCoordinate + constValTop;
         }
       }
       if (!isTop)
       {
         if (rowNum == (numOfRows - 1))
         {
           yCoordinate = height;
         }
         else
         {
           float slopeBottom = (verticesArr[rowNum+1][colNum+1].y - verticesArr[rowNum+1][colNum].y) /
                       (verticesArr[rowNum+1][colNum+1].x - verticesArr[rowNum+1][colNum].x );
 
           float constValBottom =  verticesArr[rowNum+1][colNum].y - slopeBottom * verticesArr[rowNum+1][colNum].x;
 
           yCoordinate = slopeBottom * xCoordinate + constValBottom;
         }  
 
       }
 
       return yCoordinate;
 
  }
 
  /**
  * Draws the random group of vertical lines as constrained by a single quadrilateral.
  * Will draw up to 15 lines.
  */
  void drawVerticalLinesPattern(int rowNum, int colNum)
  {
    /* Draw vertical lines */
    int numOfLines = int(random(1, 15));
    for (int i=0 ; i &lt; numOfLines ; i=i+1)
    {
       // x coordinate is just a random x between the two adjacent vertices
       println("rowNum is " + rowNum + " colNum is " + colNum);
       float xCoordinate = random(verticesArr[rowNum][colNum].x, verticesArr[rowNum][colNum+1].x);
 
       float yCoordinateTop = calculateY(rowNum, colNum, xCoordinate, true);
       float yCoordinateBottom = calculateY(rowNum, colNum, xCoordinate, false);       
 
       line(xCoordinate, yCoordinateTop, xCoordinate, yCoordinateBottom);
 
    }
 
  }
 
  /**
  * Draws the random group of triangles as contrained by a single quadrilateral.
  * Will draw up to 15 triangles.
  **/
  void drawTriangles(int rowNum, int colNum)
  {
     int numOfTriangles = int(random(1,15));
     for (int k=0 ; k &lt; numOfTriangles ; k = k+1)
     {
        // randomly select 3 x's
       float x1 = random(verticesArr[rowNum][colNum].x, verticesArr[rowNum][colNum+1].x);
       float x2 = random(verticesArr[rowNum][colNum].x, verticesArr[rowNum][colNum+1].x);
       float x3 = random(verticesArr[rowNum][colNum].x, verticesArr[rowNum][colNum+1].x);
 
       // x1 will always be on the top line, x2+x3 will be on the bottom line
       float y1 = calculateY(rowNum, colNum, x1,true);
       float y2 = calculateY(rowNum, colNum, x2, false);
       float y3 = calculateY(rowNum, colNum, x3, false );  
 
       line(x1,y1,x2,y2);
       line(x1,y1,x3,y3);
     }
 
  }
 
  /**
  * Draws random circles on the screen (up to 10). Radius and locations are random.
  * Locations are calculated such as the circle is always completely visible within the given window frame.
  **/
  void drawCircles()
  {
     int numOfCircles = int(random(1,11));
     noFill();
     for (int i=0 ; i &lt; numOfCircles ; i=i+1)
    {
       float circleRadius = random(1, baseBandWidth);
       float xCoordinates = random(circleRadius,width-circleRadius); // we want to make sure the circle can be fit entirely on our canvas
       float yCoordinates = random(circleRadius,height-circleRadius); // we want to make sure the circle can be fit entirely on our canvas
 
       ellipse(xCoordinates, yCoordinates, circleRadius, circleRadius);
    }
  }
 
}

MadelineGannon-13-9-65

by madeline @ 7:44 pm 18 January 2012

______________________________________________________________________________________


____________________________________________________________________________

 
void setup() {
  size(600, 600);
  smooth();
  background(255);
  frameRate(.5);
  stroke(0);
  noFill();
}
 
void draw() {
  background(255);
  rect(0,0,width-1,height-1);
 
  // (1) create distorted grid
 
  // make x-intervals
  List xInt = new ArrayList();
  int x = 0;
  xInt.add(x);
  while (x &lt; width-20) {
    int randX = int(random(20, width/4+20));
    x += randX;
    xInt.add(x);       
  }  
 
  // make initial y-intervals
  List yInt = new ArrayList();
  int y = 20;
  while (y  height)
 
     int randY = int(random(20, height/8+20));
 
     if (randY &gt; height)
      y = height;
    else
      y += randY;
    yInt.add(y);
  }
 
  // store the distorted grid
  List grid = new ArrayList();
 
  for (int j=0; j&lt;yInt.size(); j++){
    for (int i=0; i&lt;xInt.size(); i++){
        // get the current and previous point 
        PVector pt1 = grid.get(j*xInt.size()+i-1);
        PVector pt2 = grid.get(j*xInt.size()+i);
 
        line(pt1.x,pt1.y,pt2.x,pt2.y);
      }    
    }
  }
 
 
  // (2) add verticle elements 
 
  // for each grid cell
  for (int col=0; col&lt;yInt.size()-1; col++){
    for (int row=1; row&lt;xInt.size(); row++){
 
      // get cell points
      PVector s1 = grid.get(col*xInt.size()+row-1);
      PVector e1 = grid.get(col*xInt.size()+row);
      PVector s2 = grid.get((col+1)*xInt.size()+row-1);
      PVector e2 = grid.get((col+1)*xInt.size()+row);      
 
      // percentage (k) of a line segment: 
      //    x0 = (1-k)*start.x + k*end.x
      //    y0 = (1-k)*start.y + k*end.y
 
      // create randomly spaced line
      if (ceil(e1.y % 3) == 2){
 
        for (int i=0; i&lt;10; i++){
          float k = random(0,1);
          float x0 = (1-k)*s1.x + k*e1.x;
          float y0 = (1-k)*s1.y + k*e1.y;
          float x1 = (1-k)*s2.x + k*e2.x;
          float y1 = (1-k)*s2.y + k*e2.y;
          line(x0,y0,x1,y1);
        }
      }
 
      // create randomly spaced,random endpoints
      if (ceil(e1.y % 3) == 3){
 
        for (int i=0; i&lt;20; i++){
          float k = random(0,1);
          float x0 = (1-k)*s1.x + k*e1.x;
          float y0 = (1-k)*s1.y + k*e1.y;
          k = random(0,1);
          float x1 = (1-k)*s2.x + k*e2.x;
          float y1 = (1-k)*s2.y + k*e2.y;
          line(x0,y0,x1,y1);
        }
      }
 
    }
  }
 
  // (3) create circles
  for (int c=0; c &lt; xInt.size(); c++){
 
    int margin = 52; 
    float radius = random(2,125);   
    ellipseMode(CENTER);    
    ellipse(random(margin,width-margin),random(margin,height-margin),radius,radius);
 
  }
 
 
}
« Previous Page
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2023 Interactive Art and Computational Design, Spring 2012 | powered by WordPress with Barecity