0
votes

I've read many articles that describe how to convert cardinal or canonical splines into cubic bezier curves, such as this one.

Is there a way to do the reverse, i.e. convert a set of cubic bezier curves into a cardinal spline? We know, for example, that the endpoints of each curve are on the spline.

What I'm looking for is a way to roundtrip through the two representations with minimal loss of information. Also ideally the solution should be stable, so that going from cubic bezier => cardinal spline => cubic bezier => cardinal spline should result in the same (or nearly same) curves after the second operation.

3

3 Answers

6
votes

Imagine cubic curve between points B and E.
If it is defined as cardinal spline with tension parameter s, then tangent vectors in these points are

Tb = s * (E - A)
Te = s * (F - B)

If curve is defined as Bezier one, then tangent vectors are

Tb = 3 * (C - B)
Te = 3 * (E - D)

If curve BE is the same, then values of tangents are equal, and we can find control points of Bezier, if A,B,E,F,s are known. And vice versa - we can find A,F points for cardinal spline, if B,C,D,E,s are known. For example, the first control point of Bezier is

C = B + s * (E - A) / 3

enter image description here--

0
votes

Furthering MBo's answer above, the formula for bezier -> cardinal is:

A = E - (C - B) * 3 / s
F = (E - D) * 3 / s + B

0
votes

Just in case you don't wish to having to think about it too much, here's a super simple way to go about it. Bezier is really just a piece of a spline, so to say. The trick is to simplify the instructions for the spline:

Some java style... say you have a drawSpline function with arguments drawSpline(int degree, double[] controlPoints, double[] knots);

Cubic:

 double controlPoints[] = {start.x, start.y, handleA.x, handleA.y, handleB.x, handleB.y, end.x, end.y};
 double knots[] = {0,0,0,0,1,1,1,1};
 drawSpline(3, controlPoints, knots);

Quadratic:

double controlPoints[] = {start.x, start.y, handle.x, handle.y, end.x, end.y};
double knots[] = {0,0,0,1,1,1};
drawSpline(2, controlPoints, knots);

That is possibly the easiest way to recognize how you may have to go about it. It really is far easier than some make it sound. However, backwards from Spline to Bezier may proof to be a little trickier, if the spline has more knots. The above, though, may provide some orientation.

I hope that helps!