Walking Ripples

circles along a wavy curve with random radii and shading is alternating between white  and blue gradients.


Over the last week I have been drawing circles along paths and then shading them with 2 colors using random numbers to determine their radii.

For example, the one on this card was drawn with 10 evenly spaced circles along a line using the random radii of 48,30,70,7,1,68,26,81,36,63.

circles of random sizes drawn along a line then shaded with alternating black and white regions

I wanted to code this, but wasn't quite sure where to start. So I began with just drawing 25 random circles in p5js.

25 circles of random radii drawn along a horizontal line
let circles = [];//circle array
let w, h;//width and height
function setup() {
  cnv = createCanvas((w = 800), (h = w / 2));
  background(0);
  //make random circle sizes and walk them along x
  for (let i = 0; i <= 25; i++) {
    circles[i] = {
      x: w / 10 + (4 * i * w) / 125,
      y: h / 2,
      r: random(10, h / 2)
    };
  }
  noFill();
}
function draw() {
  //draw each circle
  for (let j = 0; j < circles.length; j++) {
    stroke(100);
    circle(circles[j].x, circles[j].y, circles[j].r);
  }
}

So, how do we shade these regions so that no two regions that share an edge have the same color? This is a good place for you to stop reading and go try it.


First, I thought about the region outside of all of the circles and decided to shade that.

25 random circles with the region shaded white outside of their areas
//...previous setup code
function draw() {
  for (let i = 0; i < 5000; i++) {
    inCircle = false;
    let x = random(0, w);
    let y = random(0, h);
    for (let j = 0; j < circles.length; j++) {
      stroke(100);
      circle(circles[j].x, circles[j].y, circles[j].r);
      if (dist(circles[j].x, circles[j].y, x, y) < circles[j].r / 2) {
        inCircle = true;
      }
    }
    if (!inCircle) {
      stroke(255);
      point(x, y);
    }
  }
}

Ok, so next I thought about shading the regions that are not intersections. So, instead of using a boolean, I decided to count how many circles each random point was inside. If it is 1, then shade it something else:

//...previous setup code
function draw() {
  for (let i = 0; i < 1000; i++) {
    inCircle = 0;
    let x = random(0, w);
    let y = random(0, h);
    for (let j = 0; j < circles.length; j++) {
      stroke(100);
      circle(circles[j].x, circles[j].y, circles[j].r);
      if (dist(circles[j].x, circles[j].y, x, y) < circles[j].r / 2) {
        inCircle++;
      }
    }
    if (inCircle === 0) {
      stroke(255);
      point(x, y);
    } else if (inCircle === 1) {
      stroke(100, 150, 205);
      point(x, y);
    }
  }
}

Here is another good place to stop to see if you can change the code - just 2 lines to solve the problem. Here is working code for you to problem solve with. I will reveal it below.

randomly sized circles along the horizontal with shading that alternates between blue and white

After I thought about how many circles a point is considered to be in, it clicked. If the number is even it is one color, and if the number is odd it is another color. By finding if the remainder is 1 or 0, you can determine the color of a point in a region. Here is the complete code.


After I did this - then changed my colors, played with composition and color and got these. Here is the code.

This is the first post after my Wordpress to Ghost migration - ping me if there are any issues or if you want to be removed from this list.

This chalkdust article was shared with me after I posted - It's a really nice deep dive into some of the math.