Here's my version of a design taken from the Jared Tarbell talk that I referenced earlier.
The recipe is simple:
* Fully connect points that are equispaced around the circumference of a circle
* Repeat for circles of various radii
This exercise posed an interesting challenge. Full details in my repository here, but the short version is that I thought I could take a clever approach using Processing's scale transform and—well—it didn't pan out.
So it was pretty obvious from the symmetry of the pattern that I would want to do my math in polar coordinates and then convert to cartesian at the last moment. And rather than recalculating the points around the edge of the circle whenever I change the radius of the circle, I can leave the points' r and theta (and their equivalent x and y) untouched and use Processing's scale() transform to change the underlying basis vectors and hence the points' position on the screen. Neat! No recalculations!
Unfortunately, scale() scales everything. It's not just that all the basis vectors are scaled, the actual screen representation of a pixel is scaled too. So if I call scale(8) all of a sudden any line (say) that used to be one pixel wide is now 8 pixels wide. And although I can downscale the resulting line widths, I cannot do so below the new representation of 1 pixel. For example, the minimum value that I can pass to strokeWeight() is 1. This is 1 transformed pixel, not 1 actual pixel. So when I use a large value in scale(), my lines suddenly start to get thick and they stay thick. Here's a detail from an early iteration of the design:
The solution is not to use scale(): instead simply recalculate the points
I had speculated in an earlier post that I could get better (pseudo-)random colors if I pulled from color mixing models like Pantone or perceptual color models like NCS or Munsell. I'd love to, but it turns out that they are all copyright. That's a dead end then.
However my instinct that HSB is probably a better model from which to draw than RGB is supported elsewhere. There's an old post on Martin Ankeri's blog that has an interesting discussion on the issue, and he comes out firmly on the HSB side.
So let's think about how I want to vary hue, saturation, and brightness:
Hue: I don't really care about the underlying color so I will just pull from a uniform distribution between 0 and 1. (By the way, I'm assuming HSB are all on a 0-1 scale).
Saturation: I know I'm going to want some sort of lumpiness but I'm not sure exactly how much and where. Maybe I want a lot of the colors bleached out. Or really saturated. This suggests that I need should pull randomly from a beta distribution and then play around with the distribution's parameters to change where the lump/lumps occur.
Brightness: ditto for brightness. I want it non-uniform but tweakable. Another beta distribution.
I'm now using the python version of Processing instead of Java. It may have some issue around importing third-party libraries but this last week of using the Java version has just reminded me how much I don't like that damn language.
The translation of the Java code to Python was simple; the inclusion of the beta distributions is straightforward too as they are already available in Python's random module.
If you want to play with the code it is in my repository here. If you want to mess around with the paramaters in a beta distributions and see the impact on the shape of the distribution, there's a handly online tool here.
I show a couple of examples below. Personally I think they are an improvement on the earlier examples. (And yes, I've gone full Richter. No gutters here.)
Obviously, the colors are different every time I run the code. But it's the overall feel of how these colors work together that interests me. And this overall feel is—again, as one would expect—pretty sensitive with respect to the parameters you set in the beta-distributions for saturation and brightness.
It's a lovely piece of software but, coming out of the box, it does not really fit my typical workflow. The problem? It's an IDE. I can't stand IDEs. Not only do I have to learn a new language but I have to learn a whole new toolkit for working in it. I much much prefer being able to compose a script in my favorite text editor and then summon that script from the command line.
Fortunately Processing supports this workflow. I found this post at dsfcode.com that does a great job of describing how to set it up. And once I had done so it becomes so easy to get into my usual edit/run/re-edit cycle.
The only thing to watch out for is that the order of parameters in the processing-java command matters. So this command succeeds: