BillyKeyes-13-9-65
Press SPACE to generate a new image.
/** * 13/9/65 on 23/1/12 * * Interactive Art and Computational Design * Billy Keyes, 2012 * * A generator of images similar to "13/9/65 Nr. 2" by Frieder Nake */ final int NUM_LINES = 9; final int SEGMENTS = 6; ArrayList lines; void setup() { size(650, 650); smooth(); noLoop(); stroke(0); strokeWeight(1.25); lines = new ArrayList(NUM_LINES + 2); } void draw() { background(240); // Draw horizontal lines lines.add(drawSegmentedLine(SEGMENTS, 50, 0, 0)); for (int i = 1; i < NUM_LINES; i++) { lines.add(drawSegmentedLine(SEGMENTS, 50, i * height / NUM_LINES, 40)); } lines.add(drawSegmentedLine(SEGMENTS, 50, height, 0)); // Draw vertical "connecting" lines for (int i = 0; i < lines.size() - 1; i++) { float[][] t = lines.get(i); float[][] b = lines.get(i+1); // Prefer higher numbers of connections between two given rows int connections = int(sqrt(random(1, 49))); for (int j = 0; j < connections; j++) { // Choose a segment to connect int seg = int(random(SEGMENTS)); if (random(1) < 0.5) { drawStraightConnectingLines(new float[][]{t[seg], t[seg+1]}, new float[][]{b[seg], b[seg+1]}, int(random(3, 9)), random(0.2, 0.6), random(0.25, 1.0)); } else { drawDiagConnectingLines(new float[][]{t[seg], t[seg+1]}, new float[][]{b[seg], b[seg+1]}, int(random(3, 9)), random(0.2, 0.6)); } } } // Draw circles ellipseMode(CENTER); noFill(); for (int i = 0; i < NUM_LINES; i++) { for (int j = 0; j < SEGMENTS; j++) { if (random(1) < 0.1) { float hf = (float) height; float wf = (float) width; float side = sqrt(random(16, sq(hf / (NUM_LINES - 3)))); ellipse(wobble(wf / (SEGMENTS * 2) + j * wf / SEGMENTS, wf / SEGMENTS), wobble(hf / (NUM_LINES * 2) + i * hf / NUM_LINES, hf / NUM_LINES), side, side); } } } } /** * @param segs The number of segments to draw * @param dx The amount of x variation in segment endpoints * @param y The base y coordinate of segment endpoints * @param dy The amount of y variation in segment endpoints */ float[][] drawSegmentedLine(int segs, float dx, float y, float dy) { float[][] points = new float[segs + 1][2]; points[0][0] = 0; points[0][1] = wobble(y, dy); for (int i = 1; i <= segs; i++) { points[i][0] = (i == segs) ? width : wobble(i * width / segs, dx); points[i][1] = wobble(y, dy); line(points[i - 1][0], points[i - 1][1], points[i][0], points[i][1]); } return points; } /** * @param top The top set of segments * @param bottom The bottom set of segments * @param density Approximately the number of clusters to draw * @param cluster Influences how many lines are in each cluster (greater than 0.25) * @param spread How much of the segment is filled with lines (between 0.0 and 1.0) */ void drawStraightConnectingLines(float[][] top, float[][] bottom, int density, float cluster, float spread) { for (int i = 0; i < top.length; i += 2) { float xl = max(top[i][0], bottom[i][0]); float xr = min(top[i+1][0], bottom[i+1][0]); float diff = spread * (xr - xl); float base = random(xl, xr - diff); density = density + int(random(0, 2)); for (int j = 1; j < density; j++) { for (int k = 0; k < cluster * 4; k++) { float x = base + wobble(j * diff / density, cluster * diff / density); float yt = ylerp(top, i, x); float yb = ylerp(bottom, i, x); line(x, yt, x, yb); } } } } /** * @param top The top set of segments * @param bottom The bottom set of segments * @param density Approximately the number of clusters to draw * @param cluster Influences how many lines are in each cluster (greater than 0.25) */ void drawDiagConnectingLines(float[][] top, float[][] bottom, int density, float cluster) { for (int i = 0; i < top.length; i += 2) { float[][] src, dest; if (random(1) < 0.5) { src = top; dest = bottom; } else { src = bottom; dest = top; } float diff = src[i+1][0] - src[i][0]; density = density + int(random(0, 2)); for (int j = 1; j < density; j++) { for (int k = 0; k < cluster * 4; k++) { float xs = src[i][0] + wobble(j * diff / density, cluster * diff / (density + 1)); float xd = random(dest[i][0], dest[i+1][0]); float ys = ylerp(src, i, xs); float yd = ylerp(dest, i, xd); line(xs, ys, xd, yd); } } } } /** * Produces a random value at most dv/2 away from the given value. */ float wobble(float v, float dv) { return v + random(-dv / 2, dv / 2); } /** * Linear interpolation to find the y coordinate on the degment for the * given x coordinate. */ float ylerp(float[][] points, int i, float x) { return lerp(points[i][1], points[i+1][1], (x - points[i][0]) / (points[i+1][0] - points[i][0])); } void keyPressed() { if (key == ' ') { lines.clear(); redraw(); } } |
Comments Off on BillyKeyes-13-9-65