Hand drawn circles

I wanted to draw a month-at-a-glance calendar page with several days circled, but drawing perfect circles looked odd, so I looked for a way to imitiate hand-drawn (imperfect) circles.

For my application the circles don't need to be closed since I'm not filling them, but that would be an easy modification.

I started from this nice approximation of a perfect circle based on cubic Bézier segments, where they show that a good approximation to a quarter circle of unit radius is a cubic Bézier curve with control points P0 = (0, 1), P1 = (c, 1), P2 = (1, c), P3 = (1, 0) where c = 0.551915024494. For example we can use this SVG, with the control points shown in red: <path d="M0,1 C0.552,1 1,0.552 1,0"/>

To draw a full circle, we just chain four of these together, using a path like this: <path d="M0,1 C0.552,1 1,0.552 1,0 S0.552,-1 0,-1 S-1,-0.552 -1,0 S-0.552,1 0,1"/>

To make an approximate circle, it's more convenient to work in polar coordinates, where we represent points using a radius and angle, (r, θ), relative to the origin. So the four control points for each arc, in polar coordinates, become P0 = (1, 0), P1 = (d, β), P2 = (d, π/2 - β), P3 = (1, π/2), where β = tan-1(c) and d = √ (c2 + 1).

Now we just need to add a bit of randomness as we generate the path. I decided to do this in four ways:

  1. Add a random delta to the current radius (starting from r = 1) when we generate the start of each quarter (along with its corresponding control points). If we bias the change to be slightly positive (or negative), the circle ends up looking more like a spiral.
  2. Start the path at a random angle.
  3. Add a random delta to the angle we rotate for each quarter, instead of exactly π/2. If we bias the change to be slightly positive (or negative) then the circle tends to overshoot (undershoot) the starting point.
  4. Squash the circle using a non-uniform scaling and random rotation. If we bias the scaling to be more or less than one we can make the circles tend to fit inside a fixed outline for example.
If we plan to draw lots of circles, we might want to choose the random variations from a limited range so they all look like the same "handwriting". Try experimenting:

Radius variation (0: none, <0: shrink, >0: grow)

Starting angle (0-360):

Rotation variation (0: none, <0: undershoot, >0: overshoot)

Squash factor (1: none, <1: shrink, >1: grow)

Squash orientation (0-360)