Chapter 12 of Coding Curves
Guilloche patterns are very intricate and fascinating patterns. You’ll often find them on bank notes and other official documents as well as watches and other intricate machinery. Because they are so intricate and complex, and often engraved into metal, they are usually done by machines themselves. Imagine a high end spirograph machine with a metal etching tool rather than a ball point pen. The name “Guilloche pattern” is rather vague and can apply to all kinds of similar patterns. I’m going to explain how to make a pattern like the one you see here:
This is a lot like the kind of thing you’d see on some kind of certificate or bank note, and once you understand what’s going on, you can adapt the code to make other similar patterns.
Step One – A Simple Ring
We’ll start by making a single, simple ring that looks like this:
This is very much like a trochoid or a rose curve. In fact, you could probably make this with those formulas, but I’m going to do it a bit differently to set it up for the more complex stuff we’ll do later on.
This is essentially a sine wave that’s wrapped around a circle. Note that it has an inner radius and an outer radius. The sine wave has 80 nodes, but it overlaps itself. To simplify what’s happening here, I’ll increase the inner radius and make it so it doesn’t overlap:
Now you can see more clearly that this is, as I said, a sine wave wrapped around a circle. Now I’ll add a little bit of overlap:
Here, you should still be able to see the sine wave even with the overlap. The first image is the same idea, but with a lower inner radius and more overlap. Now let’s look how to draw this.
We start with an inner and outer radius. With a bit of easy math we can figure out a “mid” radius. This will be the the zero-point of the sine wave. And we’ll need a range, which is how much the sine wave will have to extend to either side of this radius to hit the inner and outer limits. You might also call this the amplitude of the wave.
width = 600
height = 600
canvas(width, height)
translate(width / 2, height / 2)
inner = 50
outer = 250
range = (outer - inner) * 0.5
mid = inner + range
Next, we need values for how many cycles in the wave, and how much it overlaps. I’ll call these nodes
and div
. These should be whole numbers and should not be evenly divisible. This is very similar to the n
and d
parameters in the rose curves we made in the last chapter, but I’ll name them differently to keep things clear.
nodes = 80
div = 11
Now we can loop t
from 0 to 2 * PI * div
and draw some line segments. The angle of each new point for the next segment is simply t
and the radius will be computed as shown. We need to multiply 2 * PI by div
to make sure we go around the circle enough times to meet back up correctly.
for (t = 0; t < 2 * PI * div; t += 0.01) {
radius = mid + sin(t * nodes / div) * range
x = cos(t) * radius
y = sin(t) * radius
lineTo(x, y)
}
stroke()
If you look back at the roses chapter, you’ll see this is very similar to how we got the radius there, but rather than figuring the radius as a sine and single multiplication, we’re using mid
and range
to fit the radius between inner
and outer
.
You can play with this a bit. Try different inner and outer radii and number of nodes and values for div
. For a good Guilloche pattern, you probably want to keep nodes
rather high, and div
lower. But Most importantly, they should not be evenly divisible. An easy formula for decent patterns is to make div
a small prime number and make sure nodes
is not a multiple of div
.
For example, if div
is 17, you wouldn’t want to use 170 for nodes
, or you’ll get this:
But changing nodes
to 171 gives you a much better pattern:
If you want to play with an interactive version of this, I made this a few years back:
https://bit101.github.io/lab/dailies/170120.html
Step 2 – A Complex Ring
Next, we’ll add some complexity to the mix. Rather than having our sine wave go back and forth between fixed inner and outer radii, we’ll have these radii themselves vary with a separate sine wave each! The result will look like this:
We’ll need a few more parameters for this. To calculate the final outer radius at any point, we’ll need the base outer radius, how many cycles of that sine wave and how far the final radius will differ from the base outer radius. And we’ll need the same three values for the inner radius. And of course we’ll still need nodes
and div
. The values I used for the above image are:
inner = 100.0
n0 = 7.0
h0 = 10.0
outer = 250.0
n1 = 17.0
h1 = 20.0
nodes = 142.0
div = 89.0
So the inner radius will have 7 nodes, and the radius will vary from 90 to 110, which means a base of 100, plus or minus 10. Similarly the outer radius will have 17 nodes and vary between 230 and 270.
All the code we did early to find the “mid radius” and range for the sine wave will have to be redone for each iteration of the for loop now, using these values and the dynamic inner and outer radii.
for (t = 0; t < 2 * PI * div; t += 0.01) {
r0 = inner + sin(t * n0) * h0
r1 = outer + sin(t * n1) * h1
range = (r1 - r0) * 0.5
mid = r0 + range
radius = mid + sin(t * nodes / div) * range
x = cos(t) * radius
y = sin(t) * radius
lineTo(x, y)
}
stroke()
You can surely simplify this code, but I wanted to write it all out explicitly for the sake of clarity.
Again this is a good stopping point to play with some of the parameters and see the different types of shapes you can make. We have one more level of complexity to tackle next.
Here’s an interactive version of this step:
https://bit101.github.io/lab/dailies/170121.html
Step 3 – Multiple Rings
The next step is to create multiple rings that will exactly fit together, like the image that appears at the start of this chapter:
This is easier than it might seem. If you draw one smaller ring, and then one larger one around that, you just have to make sure that the parameters for the larger ring’s inner radius match the parameters for the smaller ring’s outer radius. Since we’ll be calling the same code multiple times, this would be a good time to turn it into a reusable function. For the most part, this just means wrapping the for loop and stroke call in a function with all the parameters passed in. I also added x and y parameters, so you can center the pattern anywhere on the canvas.
function guilloche(x, y, ir, n0, h0, or, n1, h1, nodes, div) {
for (t = 0; t < 2 * PI * div; t += 0.01) {
r0 = ir + sin(t * n0) * h0
r1 = or + sin(t * n1) * h1
range = (r1 - r0) * 0.5
mid = r0 + range
radius = mid + sin(t * nodes / div) * range
lineTo(x +cos(t) * radius, y +sin(t) * radius)
}
stroke()
}
I upped the canvas size to 800×800 and then used this set of function calls:
guillloche(400, 400, 50, 6, 10, 120, 12, 20, 137, 37)
guillloche(400, 400, 120, 12, 20, 220, 18, 30, 141, 41)
guillloche(400, 400, 220, 18, 30, 350, 24, 20, 164, 53)
This resulted in the following image:
Note that in the first call, the outer radius params are 120, 12 and 20. These correspond to the inner radius params in the next call. And the outer radius params for the second call, 220, 18 and 30, correspond to the inner radius params on the final call. This way, each ring lines up perfectly.
As usual, play around with this. You can make as many ring as you want. You might want to set up a custom data type that encapsulates all of the radius parameters to make that part more reusable. I’ll leave it to you.
Another thing you might want to try is making each ring a different color:
Here’s an interactive version of the final product:
https://bit101.github.io/lab/dailies/170122.html
Note that there’s no rule that says the rings have to match exactly. Try putting some space between them or letting the overlap and see what kind of interesting patterns you can create that way. This next example has the first and last rings the same as in the previous example, but the middle ring is defined quite differently:
guillloche(400, 400, 20, 4, 5, 120, 8, 10, 137, 37)
guillloche(400, 400, 160, 5, 24, 160, 11, 24, 80, 17)
guillloche(400, 400, 220, 18, 16, 350, 10, 20, 164, 53)
Here, the inner and outer radius is the same, 160, which makes some interesting blobs rather than a discrete ring. All is fair in Guilloche patterns!
And of course, don’t forget to animate!
Summary
Do an image search for Guilloche patterns and you’ll find things that are much different, and often more complex than what I’ve presented here. This is just one take on them.
You might try altering the code do draw something other than circles. Ellipses would be a good place to start. And then move onto other shapes. But all that is a bit beyond the scope of this chapter.
Hi, I wonder if you could re-load your old flash lab swf files somewhere? There is ruffle and I would love to browse though them again.
Thanks
They never left. 🙂 https://www.bit-101.com/content/