A lib2geom braindump

I’m hacking with lib2geom, the base geometry library that underlies Inkscape. I don’t understand a lot of it, so here’s a braindump of what I’ve figured out now. I’ll modify it as I figure out where I’m wrong. (We’re all n00bs all the time :) )

A user inputting using a mouse or pen device can click and drag. On click we record a sequence of points in device coordinates until the user releases the mouse button. However close these recorded points are, they are not a continuous function. If you zoom in close enough, there are gaps between the points. In order to solve this problem we interpolate between the points. We’re – effectively – guessing the path of the mouse/pen movement in real space (i.e. R^2) as we can’t know the real function.

There are several ways to interpolate. The most common using cubic or Bezier curves. We fit an n-order polynomial between each pair of points. To ensure the smoothness of the curve we insist that either the first or second derivative (or both derivatives) of the join is a continuous function. Thus fitting multiple cubics to a set of points results in a cubic-spline. Fitting multiple Bezier curves to a set of points results in a Bezier-spline. It is common for graphics APIs to allow curve representation using non-uniform rational B-splines.

Recently [2000] S-power basis functions were proposed as a basic building building block of splines. Inkscape represents interpolated input strokes as sequences of pairs of S-power basis functions (SBasis functions in lib2geom speak).

Each SBasis function is lifted into two dimensions. Thus a D2 function (from the documentation) “provides a 2d parametric function which maps t to a point x(t) y(t)” [[Todo: Explain This With a Diagram]]. A sequence of D2 functions, as interpolated from input pen strokes, is a Piecewise<D2 >. A Piecewise has the added advantage of storing the temporal nature of the input points.

Iterating through a Piecewise<D2 >:
Piecewises are useful for two reasons
(a) we may compute very high fidelity operations such as dot product, and
(b) we may compute stuff that uses the temporal information stored in a Piecewise.
For general computation, such as computing the intersection of a Piecewise and a primitive shape, we need to build Paths from our Piecewise. The joins between the splines in a Piecewise are called knots. The following builds a Path from a Piecewise (with thanks to Johan Engelen):

// Where spline_path is a Piecewise<D2 >
Geom::Point knot = spline_path[i].at0();
Geom::Path path = Geom::Path(knot);
for (unsigned i=0; i < spline_path.size(); i++) {
path.append(spline_path[i]);
}

One Response to “A lib2geom braindump”

  1. njh says:

    It is rare to want to match second derivatives but not first derivatives (it is not geometrically interesting). I usually say matching 0th derivative makes the curve continuous, and the first removes the kinks, and the second the lumps.

    Good write up, would you consider adding this to the documentation directory?

Leave a Reply