Letting Go of Random

tutorial

In a recent post I shared some thoughts about art and included a few, somewhat tongue-in-cheek comments about the use of random number generation. Specifically,

Random is evil. Random is lazy. Random is OK when you’re starting a new piece. It’s OK when you have a formula and you’re searching for an interesting range of input parameters. But once you find something interesting, lock in those parameters and start focusing.

Interestingly, this was the part of the post that generated the most comments – only a few, but it was definitely the thing that several people latched onto. So I thought I’d expand my thoughts on it.

Now of course I don’t actually think random is evil. But it can be lazy, and it can definitely be boring. But yes, I use random all the time. In my blgo library I have a random module with all kinds of useful functionality that derives from Golang’s built-in pseudo random number generator (PRNG). In my bljs library, I had to build my own PRNG because one doesn’t exist in JavaScript. No, Math.random is not a useful PRNG since you cannot seed it.

So what, in my opinion, is a good use of random and what is not?

Random positions and sizes

Not a great use of random. One of the most boring. I once said something like, “If you can draw a shape, you’re an artist. Randomly draw 10,000 of the same shape, you’re a generative artist.” But honestly I think that’s the ultimate in boring, lazy generative art. Here’s 10,000 random points:

And 500 random squares with random sizes:

And 500 random lines:

I could go on. And I could generate 10,000 individual “art works” like any one of these with a few lines of code. Each would be different. But I wouldn’t call it art. Maybe in my very, very early days of experimenting with graphic code I thought this looked kind of cool. But seriously, I hope your skills and self-expectation rise above this level really quickly.

A Different Random?

So what might be better? Taking it slowly, let’s just try a different random. If you’re using Math.random or something similar that generates a random number, you’re probably getting a uniform distribution. This means that there is an equal probability that you’ll hit any given number in a given range. So it’s all pretty flat and boring. You could try a normal distribution. This favors numbers in the center of your given range, giving you something like this:

For this, you’ll either need a PRNG that has a normal distribution function, or you’ll need to come up with one yourself. Here’s a JavaScript example I found on StackOverflow that seems to do the trick:

// Standard Normal variate using Box-Muller transform.
function randn_bm() {
    var u = 0, v = 0;
    while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
    while(v === 0) v = Math.random();
    return Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v );
}

Unlike a uniform distribution generators however, normal distribution generators will usually give you a range of numbers both negative and positive. Most of the generated numbers (around 99.7%) should fall into the range of -3.0 to +3.0. So you’ll have to do some transformations to get them into the range you actually want them.

Here’s an example that places 100 squares in a normally distributed random position, and uses a normal distribution for their sizes as well:

In this case, I took the absolute value of a generated number (which would generally wind up in the range of 0 to 3, weighted heavily towards 0) and multiplied it by 40 to get the size of each square. This skews the square sizes toward the smaller range. Of course, you could do different math to skew it to larger squares, or even towards medium sized squares, with smaller and larger ones occurring less frequently.

And some random lines with normal distribution:

If you find normal distribution interesting, you might want to look at one of the many other probability distributions.

We’re still in the realm of random, but even so, I think the results are much more interesting.

Noise

Another strategy that is more interesting than uniform random distribution is using noise. This usually means Perlin or Simplex noise (which I’ve discussed here in depth). Here, I chose 10,000 random points, but only accepted them if the noise value at that location was above 0 (in a range of -1 to +1):

Things get more interesting when you throw size into the mix. This one does the same thing, but draws squares. The size of each square is in proportion to the value of the noise at that point.

Other

Other things to try are various types of attractor formulas, chaos games, iterated function systems (IFS) and other fractal-related formulas. These can often be just as chaotic and unpredictable as PRNGs, but at the same time give some kind of underlying structure that is much more interesting than uniformly distributed random numbers.

Random Colors

I know next to nothing about color theory, and tend to do things in black and white as long as I can get away with it. Big fan of monochrome. But now and then I’m forced to use color under extreme duress. My first naive attempts to fly under the radar with color usually go along with a function I created called randomRGB, which does what you would guess.

Here’s the above normally distributed squares (a few more of them this time) with random RGB color values.

Well, it IS colorful. But it evokes absolutely nothing. From there, I usually move over to HSV colors, which at least sends me in the right direction. Here, I’m using a random hue from 0 to 60 and a saturation and value of 1.0:

At least this has something going for it. A kind of pixelated, MineCraftian fire maybe. Or, we could keep a single hue and vary the saturation:

Or a random value:

These at least have something going for them. If you want to go all out, you can start creating color palettes. Adobe Color Wheel is a great resource. Here’s a split complementary palette I generated:

To be fair, I’m still just picking one of the five values from the palette randomly, so it’s still pretty lame. I refer back to my first statement of this section. I think it would probably be better to use the reds in one area and the blues in another and the green as a highlight… or something.

Random is Not Evil

As you can see, in just about all of my “non-random” examples, I’m still using random to some degree. But I’m using it secondarily, piping it through something else, which gives it some structure. Once you have some kind of predictable structure, then you start tweaking values to move that structure a bit this way or that way and start adding some of your own taste and judgement into what you are creating. Then it starts to become more of your work, not just the work of a PRNG.

Often, I will have some formula that generates some kind of fractal or attractor. It can produces quite different images depending on what parameters you give it. But that means there can be millions or even billions of different potential images (infinite really, but many of them will be very similar). So I’ll create a loop that just makes a bunch of thumbnails with random parameters and generate a grid of images. On each thumbnail, I’ll print the parameters that created that image.Here’s a sample from last year:

click to see full size.

When I see one I like, I’ll hard code those parameters into the code and generate a larger version. Then I’ll tweak them one way or the other to create something that I really, really like. This use of random allows me to explore way more possibilities in a much shorter time than manually trying to find a good set of parameters.

Summary

I could probably go on about this subject a lot longer, but hopefully I’ve clarified my thoughts a little bit and maybe given you some ideas to try out.

Circle Inversion

tutorial

Circle inversion is a mathematical technique that holds a lot of opportunities for the creative coder.

Circle inversion, or circular inversion, or geometric inversion is a method of transforming a point within a circle to a new point outside the circle or vice-versa. By transforming multiple points, you can transform entire shapes, which become warped and curved in interesting ways, as if the original shape was reflected onto a curved surface. You can even do a circle inversion chaos game with multiple random circles to create interesting fractals. We’ll dive into that after we cover the basics.

The All Important Formula

So we start with a circle centered at x0, y0 with a radius of r. And a point x1, y1 within that circle. We want to invert that point to x2, y2, outside of the circle. That’s the point we need to find.

To describe it a different way, we can easily get the distance from the center of the circle to point x1, y1. We’ll call that dist0. We want to get the distance from the center to x2, y2, which we’ll call dist1.

The formula is simply r^2 / dist0. That’s if the first point is inside the circle. If you want to transform a point outside the circle to a point inside it … well, actually, it’s the exact same formula, which is nice and handy.

I’m not going to go deep into the geometry and math that you use to work out that formula, but it’s a good idea to work it out if you’re into that kind of stuff. There are plenty of pages that will show you exactly what’s going on here.

And the code that will make it happen:

function invert(cx, cy, r, x1, y1) {
  const dx = x1 - cx;
  const dy = y1 - cy;
  const dist0 = Math.sqrt(dx * dx + dy * dy);
  const dist1 = r * r / dist0;
  const angle = Math.atan2(y1 - cy, x1 - cx);

  return {
    x: cx + Math.cos(angle) * dist1,
    y: cy + Math.sin(angle) * dist1,
  }
}

This takes the center x, y and radius of a circle and the x, y of another point. It calculates the distance from the point to the center using standard Pythagorean theorem, and finds dist1 using the formula I just described. It then finds the angle from the circle center to the point and uses some trig to find the new point. And here it is in action:

You can move the circle’s center, change its radius, and move point p0. Point p1 will then move in accordance. Things to note:

  • As p0 gets close to the edge of the circle, p1 also moves in close to the edge of the circle.
  • As p0 gets close to the center of the circle, p1 moves out to infinity.
  • When p0 goes outside of the circle, p1 crosses over to the inside.

There’s a bit of an optimization you can make to this code to remove all the trig. I’ll just put it here and leave it to you to figure out how it’s working:

function invert(cx, cy, r, x1, y1) {
  const dx = x1 - cx;
  const dy = y1 - cy;
  const dist0 = Math.sqrt(dx * dx + dy * dy);
  const dist1 = r * r / dist0;
  const ratio = dist1 / dist0;

  return {
    x: cx + dx * ratio,
    y: cy + dy * ratio,
  };
}

In fact, you can go even one step further. Since we’re dividing by dist0 twice, we’re actually dividing by the square of dist0. So we can use that to get rid of the square root and both distances:

function invert(cx, cy, r, x1, y1) {
  const dx = x1 - cx;
  const dy = y1 - cy;
  const ratio = (r * r ) / (dx * dx + dy * dy);

  return {
    x: cx + dx * ratio,
    y: cy + dy * ratio,
  };
}

Shapes

Once you can invert a single point, you can start inverting entire paths of points, meaning you can invert shapes. To give you a feel for this, here’s a little app that lets you draw on the canvas with your mouse. It will draw both the exact path you are drawing, as well as the inverted path.

There’s no clear button, so you’ll have to refresh the whole page if you want to restart a drawing. If you want to spend some more time with it, you can open up the app in a fresh page.

I’m going to stop here for now. The core takeaway is that invert function. Play around with it and see what happens when you draw different shapes. I’ll come back later with that circle inversion chaos game concept I mentioned earlier. That’s where things get really fun.

Note on diagrams.

The drawings above were done on my Onyx Boox Note Air eInk tablet. I had talked about sketching in eInk in an earlier post. I was about to code up some graphics to show the principles, or maybe break out some kind of drawing application, then decided to give it a go just sketching on the tablet. I then exported the drawings and added them to the post. It’s also the first time I used color in sketching on eInk. Although the Note Air is not a color tablet, you can choose different colors to draw with. They render in black and white on the eInk screen, but when exported, they are indeed color drawings. Not super important to the post. It was just a fun little workflow that worked out pretty well from my viewpoint

Controls: MiniComps

Graphics: BLJS

Support this work

Source for the final piece.