The cubic bezier spline drawing engine in the Freehand Drawing Library is now complete. As I mentioned in the prior post, the drawing engine fits into the FDL architecture and allows a spline to be treated as a stroke. The CubicBezierSpline drawing engine contains a reference to a FDLCubicBezierSpline, which handles all the spline computations except for tangents. Tangents are implemented via a Command pattern (with the spline as the receiver of the Command). Three tangent commands are now available for cubic splines. The NormalBisector Command uses the same algorithm as described in this TechNote. The CatmullRom Command uses an algorithm similar to that in Catmull-Rom splines. The Corner Command can be applied on a per-vertex basis and constructs splines with hard ‘corners’ or only G-0 continuity at a join point.

While the CubicBezierSpline engine manages the internal spline and tangent commands, the spline and tangent computations can be easily used outside the FDL in a purely computational context.

Every FDL spline is arc-length parameterized by default, using a fast algorithm for on-the-fly parameterization. So, every coordinate request, i.e. getX(t) and getY(t) is actually computed based on normalized arc length in [0,1]. So, getX(0.5) returns the x-coordinate at approximately half the length along the spline.

Splines are implemented as drawing engines for a PolyLine stroke. As always, a drawing engine is injected into the stroke,

__data.drawingEngine = “net.algorithmist.freehand.engine.CubicBezierSpline”;

Arbitrary parameters (name-value pairs) may be assigned to any drawing engine. All splines require a ‘tangentCommand’ parameter to inject the Command used for tangent computations. The normal bisector algorithm is applied as follows.

__data.engineParams = {“tangentCommand”:”net.algorithmist.freehand.commands.NormalBisector”};

or, substitute the Catmull-Rom algorithm, if desired,

__data.engineParams = {“tangentCommand”:”net.algorithmist.freehand.commands.CatmullRom”};

then, assign the data provider to the stroke,

__stroke.data = __data;

The cubic bezier spline supports auto-closure with G-1 continuity across the full set of tangent commands since the closure algorithm is inside the Command itself. Here is a screenshot,

and here is a screenshot of an open spline using the Catmull-Rom algorithm for tangent computations,

The next step is editing the spline by adjusting knots and tangents. I was originally skeptical how far the architecture could be pushed in terms of a ‘drawing’ that was not in line with a traditional stroke motion, i.e. press-move-release. Editing the mathematical properties of something like a spline seemed out of the question at first thought. So far, I’m glad the architecture is holding up without having to hack anything in. I suppose a demo containing a spline editor will be the ultimate test 🙂

As an aside, spline editing facilities are not part of the library; they are provided as one of the many demos available to FDL users.