Chanomic Sketch

Gaussian City

ガウス分布から2次元座標をサンプリングし,それをビル群に見立てた.ランダムな間隔で道路を引くことでより都市感が出せた.

"use strict";

let cam, img, boxLen;
const board = [];
const [nRow, nCol] = [50, 50];
let rotX, rotY, rotZ;
const samplingNum = 10000;
const variance = 4;

function setup() {
  createCanvas(windowWidth, windowHeight, WEBGL);

  boxLen = min(min(width, height)/15, 50);

  for (let i = 0; i < nRow; i++) {
    board.push(Array.from({ length: nCol }).map(() => 0));
  }

  for (let i = 0; i < samplingNum; i++) {
    const x = randomGaussian(nCol/2, variance);
    const y = randomGaussian(nRow/2, variance);

    if (0 <= x && x < nCol && 0 <= y && y < nRow) {
      board[floor(y)][floor(x)] += 0.1;
    }
  }

  for (let i = 0; i  < nRow; i += floor(random(3, 5))) {
    for (let j = 0; j < nCol; j++) {
      board[i][j] = 0;
    }
  }

  for (let i = 0; i  < nCol; i += floor(random(3, 5))) {
    for (let j = 0; j < nRow; j++) {
      board[j][i] = 0;
    }
  }

  rotX = -PI/6;
  rotY = PI/6;
  rotZ = 0;

  img = createGraphics(width, height);
}

function draw() {
  background(0);

  push();
  translate(0, 50, -600);
  rotateX(rotX);
  rotateY(rotY);
  rotateZ(rotZ);
  translate(-nRow*boxLen/2, 0, -nRow*boxLen/2);
  drawCity();
  pop();

  push();
  translate(-width/2, -height/2);
  drawImage(img);
  image(img, 0, 0);
  pop();

  noLoop();
}

const drawCity = () => {
  for (let i = 0; i < nRow; i++) {
    for (let j = 0; j < nCol; j++) {
      const x = i * boxLen;
      const z = j * boxLen;

      const v = board[i][j];

      let scX, scZ;
      if (v < 1e-9) {
        fill('black');
        [scX, scZ] = [1, 1];
      } else {
        fill('lightgray');
        [scX, scZ] = [0.9, 0.9];
      }

      push();
      translate(x, 0, z);
      scale(scX, v, scZ);
      translate(0, -boxLen/2, 0)
      box(boxLen);
      pop();
    }
  }
}

const drawImage = (img) => {
  img.noStroke();

  for (let x = 0; x < width; x += random(1, 10)) {
    for (let y = 0; y < height; y += random(1, 20)) {
      img.fill(128, random(32, 128));
      img.ellipse(x, y, 1, random(2, 10));
    }
  }

  for (let y = 0; y < height; y += random(1, 10)) {
    for (let x = 0; x < width; x += random(1, 20)) {
      img.fill(128, random(32, 128));
      img.ellipse(x, y, random(2, 10), 1);
    }
  }
};