Coding Curves 12: Guilloche Patterns

coding curves, misc

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:

three ringed guilloche pattern

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:

a circle composed of many looping waves

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:

a circle drawn with a sine wave instead of a single curve

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:

a circle drawn with an overlapping sine wave

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:

a rounded star kind of shape with 10 nodes

But changing nodes to 171 gives you a much better pattern:

a circle drawn with many overlapping loops

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:

a single ring of a guilloche pattern

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:

a three ringed guilloche pattern

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:

another three ringed guilloche pattern

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:

a colored three ringed guilloche pattern

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!

a three ringed guilloche pattern. the inner ring does not tightly interlock with the others

And of course, don’t forget to animate!

an animated guilloche pattern

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.

3 thoughts on “Coding Curves 12: Guilloche Patterns

    Mentions

  • 💬 Coding Curves 01

Leave a Reply