Duncan Boehle – 13-9-65
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); } } |
Comments Off on Duncan Boehle – 13-9-65