Where ideas percolate and thoughts brew

Voronoi Cells

About This Sketch

Voronoi diagrams appear throughout natureβ€”in giraffe spots, cracked mud, and cell structures. Each cell represents the region closer to one seed point than any other, creating natural-looking organic boundaries.

As the seed points drift slowly across the canvas, the cells reshape and flow like living tissue. This mathematical structure has applications from biology to computer graphics to urban planning.

Algorithm

Voronoi diagrams partition space based on distance to seed points. Each pixel is colored by its nearest point, creating organic cell-like regions. **Key Concepts:** - **Voronoi Tessellation**: Partitioning space by nearest neighbor - **Distance Field**: Each point defines a region of influence - **Cellular Patterns**: Natural looking cell divisions - **Nearest Neighbor Search**: Finding closest point for each pixel - **Dynamic Points**: Seeds move, causing cells to morph **How it works:** 1. Place seed points randomly on canvas 2. For each pixel, find the nearest seed point 3. Color pixel based on which point is closest 4. This creates boundaries equidistant between neighboring points 5. Move seed points slowly (random walk) 6. Cells dynamically reshape as seeds move 7. Draw seed points on top for visualization

Pseudocode

SETUP:
  FOR i = 0 to numPoints:
    CREATE point with:
      position = random
      velocity = random(-0.5, 0.5)

DRAW (every frame):
  CLEAR background

  FOR EACH point:
    position = position + velocity
    IF hitting boundary:
      velocity = -velocity

  FOR x = 0 to canvas_width STEP 2:
    FOR y = 0 to canvas_height STEP 2:
      min_distance = infinity
      closest_point = null

      FOR EACH point:
        distance = euclidean_distance(x, y, point)
        IF distance < min_distance:
          min_distance = distance
          closest_point = point

      color = color_for_point(closest_point)
      DRAW pixel at (x, y)

  FOR EACH point:
    DRAW circle at point position

Source Code

let sketch = function(p) {
    let points = [];
    let numPoints = 15;

    p.setup = function() {
        p.createCanvas(400, 300);
        p.colorMode(p.RGB);

        for (let i = 0; i < numPoints; i++) {
            points.push({
                x: p.random(p.width),
                y: p.random(p.height),
                vx: p.random(-0.15, 0.15),
                vy: p.random(-0.15, 0.15)
            });
        }
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg);

        // Update points
        for (let pt of points) {
            pt.x += pt.vx;
            pt.y += pt.vy;

            if (pt.x < 0 || pt.x > p.width) pt.vx *= -1;
            if (pt.y < 0 || pt.y > p.height) pt.vy *= -1;
        }

        // Draw Voronoi cells
        p.loadPixels();
        for (let x = 0; x < p.width; x += 2) {
            for (let y = 0; y < p.height; y += 2) {
                let minDist = Infinity;
                let closest = 0;

                for (let i = 0; i < points.length; i++) {
                    let d = p.dist(x, y, points[i].x, points[i].y);
                    if (d < minDist) {
                        minDist = d;
                        closest = i;
                    }
                }

                let t = closest / points.length;
                let col = t < 0.33 ? colors.accent1 :
                         t < 0.66 ? colors.accent2 : colors.accent3;

                p.stroke(...col, 150);
                p.strokeWeight(1);
                p.point(x, y);
            }
        }

        // Draw center points
        for (let i = 0; i < points.length; i++) {
            p.fill(...colors.accent2);
            p.noStroke();
            p.circle(points[i].x, points[i].y, 6);
        }
    };
};