Duncan Boehle – 13-9-65

by duncan @ 4:59 am 24 January 2012

This is my attempt at generating pieces of art that follow the convents of Frieder Nake’s work 13/9/65. Press any key to continually generate more random versions.

//
// Duncan Boehle
// Emulation of 13/9/65 - Nake
//
 
int minCols = 6;
int maxCols = 8;
int minRows = 8;
int maxRows = 12;
int minCircles = 4;
int maxCircles = 8;
int minRadius = 3;
int maxRadius = 50;
float vertProb = 0.25f;
float crossProb = 0.35f;
int sideSize = 550;
int sideBuffer = 8;
 
ArrayList heightRows;
 
// ArrayList of rows, which is length "rows", and each
// element is an ArrayList of length "cols"
// each element of this inner ArrayList is a Box
Box[][] boxes;
 
int numRows;
int numCols;
int[] colMinXs;
int[] rowStartYs;
 
ArrayList circles;
 
void setup() {
  size(566, 566);
  smooth();
  stroke(0);
  strokeWeight(1.5);
  noFill();
 
  drawNake();
}
 
public void drawNake() {
 
  background(255);
 
  heightRows = new ArrayList();
  numRows = int(random(minRows, maxRows));
  numCols = int(random(minCols, maxCols));
  boxes = new Box[numRows][numCols];
 
  colMinXs = makePosArray(numCols, sideBuffer, sideSize + sideBuffer, 1.0f, 3.0f);
  rowStartYs = makePosArray(numRows, sideBuffer, sideSize + sideBuffer, 1.0f, 2.5f);
 
  for (int y = 0; y <= numRows; y++) {
    ArrayList row = new ArrayList();
    int rowHeight = y < numRows ? rowStartYs[y] : (sideSize + sideBuffer);
    row.add(rowHeight);
    for (int x = 0; x  0 && y < numRows) {
        rowHeight += int(random(-12, 12));
      }
      row.add(rowHeight);
    }
 
    heightRows.add(row);
  }
 
  rect(sideBuffer, sideBuffer, sideSize, sideSize);
 
  for (int y = 0; y < numRows; y++) {
    ArrayList topRowHeightRow = (ArrayList)heightRows.get(y);
    ArrayList botRowHeightRow = (ArrayList)heightRows.get(y + 1);
    for (int x = 0; x < numCols; x++) {
      int minX = colMinXs[x];
      int maxX = (x < numCols - 1) ? colMinXs[x + 1] : (sideSize + sideBuffer);
      int ulY = (Integer)topRowHeightRow.get(x);
      int urY = (Integer)topRowHeightRow.get(x + 1);
      int blY = (Integer)botRowHeightRow.get(x);
      int brY = (Integer)botRowHeightRow.get(x + 1);
 
      line(minX, ulY, maxX, urY);
      //line(minX, ulY, minX, blY);
      //line(maxX, urY, maxX, brY);
      line(minX, blY, maxX, brY);
 
      float rand = random(0.0f, 1.0f);
      int type = Box.TYPE_EMPTY;
      if (rand < vertProb)
        type = Box.TYPE_VERTICAL;
      else if (rand  0) {
        Box boxAbove = boxes[y - 1][x];
        if (type == Box.TYPE_VERTICAL && boxAbove.type == Box.TYPE_VERTICAL) {
          newBox = boxAbove;
        }
      }
 
      if (newBox == null) {
        newBox = new Box(type, int(random(1, 5)));
      }
      newBox.draw(minX, maxX, ulY, urY, blY, brY);
      boxes[y][x] = newBox;
    }
  }
 
  int numCircles = int(random(minCircles, maxCircles));
  circles = new ArrayList();
  for (int i = 0; i < numCircles; i++) {
    int rad = int(random(minRadius, maxRadius));
    int x = int(random(2 * sideBuffer + rad, sideSize - rad));
    int y = int(random(2 * sideBuffer + rad, sideSize - rad));
    Circle circle = new Circle(x, y, rad);
 
    boolean intersects = false;
    for (int c = 0; c < circles.size(); c++) {
      Circle otherCircle = (Circle)circles.get(c);
      if (circle.intersects(otherCircle)) {
        intersects = true;
        break;
      }
    }
 
    if (!intersects) {
      circles.add(circle);
      ellipse(x, y, rad * 2, rad * 2);
    }
  }
}
 
public int[] makePosArray(int num, int minN, int maxN, float minRat, float maxRat) {
  float[] ratioList = new float[num];
  float totalRat = 0.0f;
  for (int i = 0; i < num; i++) {
    float ratio = random(minRat, maxRat);
    ratioList[i] = ratio;
    totalRat += ratio;
  }
 
  int curN = minN;
  int[] pixelList = new int[num];
  for (int i = 0; i < num; i++) {
    pixelList[i] = curN;
    float ratio = ratioList[i];
    ratio /= totalRat;
    curN += ratio * (maxN - minN);
  }
 
  return pixelList;
}
 
void draw() {
  if (keyPressed) {
    drawNake();
  }
}
 
class Box {
 
  public static final int TYPE_EMPTY = 0;
  public static final int TYPE_VERTICAL = 1;
  public static final int TYPE_CROSSED = 2;
 
  public int type;
  public int maxDegree;
  public ArrayList topRow;
  public ArrayList bottomRow;
 
  public Box(int type, int maxDegree) {
    this.type = type;
    this.maxDegree = maxDegree;
    topRow = new ArrayList();
    bottomRow = new ArrayList();
 
    switch (type) {
      case TYPE_EMPTY:
        break;
      case TYPE_VERTICAL:
        fillRow(topRow, 2, 16);
        break;
      case TYPE_CROSSED:
        fillRow(topRow, 2, 16);
        fillRow(bottomRow, 2, 16);
        break;
      default:
        break;
    }
  }
 
  public void draw(int minX, int maxX, int ulY, int urY, int blY, int brY) {
 
    switch (type) {
      case TYPE_EMPTY:
        break;
      case TYPE_VERTICAL:
        // for each point along the line, draw a vertical line to the bottom
        for (int i = 0; i < topRow.size(); i++) {
          float n = (Float)topRow.get(i);
          float x = lerp(minX, maxX, n);
          float topY = lerp(ulY, urY, n);
          float bottomY = lerp(blY, brY, n);
          line(x, topY, x, bottomY);
        }
        break;
      case TYPE_CROSSED:
        // for each point along the top row, draw a random number of lines
        // to points in the bottom row
        for (int i = 0; i < topRow.size(); i++) {
          float topN = (Float)topRow.get(i);
          float topX = lerp(minX, maxX, topN);
          float topY = lerp(ulY, urY, topN);
 
          int outDegree = int(random(1, maxDegree));
          for (int j = 0; j < outDegree; j++) {
            int randIndex = int(random(0, bottomRow.size()));
            float botN = (Float)bottomRow.get(randIndex);
            float botX = lerp(minX, maxX, botN);
            float botY = lerp(blY, brY, botN);
            line(topX, topY, botX, botY);
          }
        }
        break;
      default:
        break;
    }
 
  }
 
  public void fillRow(ArrayList inList, int minEls, int maxEls) {
    int numEls = (int)random(minEls, maxEls);
    inList.clear();
 
    for (int i = 0; i < numEls; i++) {
      inList.add(random(0.0f, 1.0f));
    }
 
    return;
  }
}
 
class Circle {
  public int x;
  public int y;
  public int rad;
 
  public Circle(int x, int y, int rad) {
    this.x = x;
    this.y = y;
    this.rad = rad;
  }
 
  public boolean intersects(Circle other) {
    int xdiff = other.x - x;
    int ydiff = other.y - y;
    float distance = sqrt(xdiff * xdiff + ydiff * ydiff);
 
    return distance < (other.rad + rad);
  }
}

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