I was prototyping something and I needed to draw a curve with some thickness. It wasn’t just the case of increasing the thickness of the stroke, I wanted to find the contour of a curve, to draw two new curves around one in the center. After some research, I learnt that the correct term for that is parallel curve or offset curve.
The task turned out to be not as simple as I thought. After some failed attempts I found the solution in a paper by Gabriel Suchowolski entitled ‘Quadratic bezier offsetting with selective subdivision‘. The recipe is there, but I was missing an open source implementation so I decided to write one.
How to draw an offset curve:
Start with 3 points.
Draw a quadratic curve using
p2 as anchors and
c as the control point.
Get the vectors between these points.
v1 = c - p1
v2 = p2 - c
Find the vector perpendicular to
v1 and scale it to the width (or thickness) of the new curve.
Add the new temporary vector to
p1 to find
p1a, then subtract from
p1 it to find
Do the same with
c to find
Repeat the same process with
v2 to find the points on the other side.
Find vectors between the new points. These are parallel to
v2 and offset by the given thickness.
The intersection points of these vectors are the new control points
Draw a curve from
p2a with control point at
Draw another curve from
p2b with control point at
This method works only when the angle between
v2 is wide (bigger than 90 degrees), it doesn’t work for sharp angles.
For angles smaller than 90 degrees it is necessary to split the curve. In fact the curve could be split several times, the more the better the precision of the offset curve. To do it only at 90 degrees is fast and the result is not too bad.
The curve needs to be split at
t, which is the closest point to
c in the curve. The technique to find
t has been described in the paper I mentioned before. It requires solving a third degree polynomial like this
The equation returns a number between 0 and 1 that can be plotted in the curve to find
Find the tangent of
t and the points
t2 where it intersects
Create a new vector perpendicular to the tangent of
t, scale it to the given thickness and find
qb. This vector splits the original curve at
Add the tangent of
qb and find the points where it intersects the offset vectors.
These are all the points needed to draw an offset curve. All the others that were created in the process can be removed for clarity.
Draw a curve with anchors at
qa with the control point at
Repeat the process for all the new points to get the offset curve.
Here is an interactive version. Drag the gray dots to change the curve.