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 imitate hand-drawn (imperfect) circles. TL;DR Cubic Bézier segments do the trick, based on this approximation to a perfect circle.
This was originally a gist hosted at bl.ocks.org, which seems dead now. This clone might still work.
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
$P_0 = (0, 1)$, $P_1 = (c, 1)$, $P_2 = (1, c)$, $P_3 = (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 easier to work in polar coordinates representing points as a radius and angle relative to the origin, $(r, \theta)$. In polar coordinates the four control points for each arc become $P_0 = (1, 0)$, $P_1 = (d, \beta)$, $P_2 = (d, \pi/2 - \beta)$, $P_3 = (1, \pi/2)$, where $\beta = \arctan c$ and $d = \sqrt{c^2+1}$.
Now we just need to add a bit of randomness as we generate the path. I decided to do this in four ways:
-
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.
-
Start the path at a random angle.
-
Add a random delta to the angle we rotate for each quarter, instead of exactly $\pi/2$. If we bias the change to be slightly positive (or negative) then the circle tends to overshoot (undershoot) the starting point.
-
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)