Chanomic Sketch

Vases

const factor = 2;
const maxXSep = 60;
const maxNCols = 12;

function setup() {
  createCanvas(windowWidth, windowHeight);
  const palette = ['#E14D2A', '#FD841F', '#3E6D9C', '#001253'].map((c) => {
    const col = color(c);
    col.setAlpha(64);
    return col;
  })

  const xSep = min(width / maxNCols, maxXSep);
  const nCols = width / xSep;
  const ySep = xSep * factor;
  const nRows = ceil(height / ySep);
  const xRad = xSep / 2 * 0.5;
  const yRad = xRad/2;

  for (let i = 0; i < nRows; i++) {
    for (let j = 0; j < nCols; j++) {
      const x = j * xSep + xSep/2;
      const y = i * ySep + ySep/2;
      fill(random(palette));
      const t1 = random(0, 1);
      const t2 = random(0, 1);
      drawShapeBroken(x, y, xRad, yRad, ySep - 2*yRad, t1, t2);
    }
  }
}

const drawShapeBroken = (x, y, xRad, yRad, h, t1, t2) => {
  rectMode(CENTER);
  push();
  translate(x, y);
  translate(0, -h/2);
  for (let i = 0; i < 10; i++) {
    drawingContext.globalCompositeOperation = 'source-over';
    drawingContext.globalCompositeOperation = 'destination-out';
    for (let j = 0; j < 5; j++) {
      rect(random(-1.5*xRad, 1.5*xRad), h/2, random(0, 2*xRad), h + 2*yRad);
    }
    drawingContext.globalCompositeOperation = 'source-over';
    for (let j = 0; j < 4; j++) {
      drawShape(xRad, yRad, h, t1, t2);
    }
  }
  pop();
};

const drawShape = (xRad, yRad, h, t1, t2) => {
  const ctx = drawingContext;

  ctx.beginPath();
  ctx.ellipse(0, 0, xRad, yRad, 0, 0, PI, true);
  const xSkip1 = t1 * h/2;
  const xSkip2 = t2 * h/2;
  ctx.bezierCurveTo(-xRad + xSkip1, h/2, -xRad - xSkip2, h/2, -xRad, h);
  ctx.ellipse(0, h, xRad, yRad, 0, -PI, 0, true);
  ctx.bezierCurveTo(xRad + xSkip2, h/2, xRad - xSkip1, h/2, xRad, 0);
  ctx.fill();
}