I have a bezier curve B with points S, C1, C2, E, and a positive number w representing width. Is there a way of quickly computing the control points of two bezier curves B1, B2 such that the stuff between B1 and B2 is the widened path represented by B?
More formally: compute the control points of good Bezier approximations to B1, B2, where
B1 = {(x,y) + N(x,y)(w/2) | (x,y) in C}
B2 = {(x,y) – N(x,y)(w/2) | (x,y) in C},
where N(x,y) is the normal
of C at (x,y).
I say good approximations because B1, B2 might not be polynomial curves (I’m not sure if they are).
The exact parallel of a bezier curve is quite ugly from a mathematical point of view (it requires 10th-degree polynomials).
What is easy to do is compute a widening from a polygonal approximation of the bezier (that is you compute line segments from the bezier and then move the points along the normals on the two sides of the curve).
This gives good results if your thickness isn’t too big compared to the curvature… a “far parallel” instead is a monster on its own (and it’s not even easy to find a definition of what is a parallel of an open curve that would make everyone happy).
Once you have two polylines for the two sides what you can do is finding a best approximating bezier for those paths if you need that representation. Once again I think that for “normal cases” (that is reasonably thin lines) even just a single bezier arc for each of the two sides should be quite accurate (the error should be much smaller than the thickness of the line).
EDIT: Indeed using a single bezier arc looks much worse than I would have expected even for reasonably normal cases. I tried also using two bezier arcs for each side and the result are better but still not perfect. The error is of course much smaller than the thickness of the line so unless lines are very thick it could be a reasonable option. In the following picture it’s shown a thickened bezier (with per-point thickening), an approximation using a single bezier arc for each side and an approximation using two bezier arcs for each side.
EDIT 2: As requested I add the code I used to get the pictures; it’s in python and requires only Qt. This code wasn’t meant to be read by others so I used some tricks that probably I wouldn’t use in real production code. The algorithm is also very inefficient but I didn’t care about speed (this was meant to be a one-shot program to see if the idea works).