Very smooth, but with the drawback that the line does not actually pass through the control points.
curve = Curves.define_b_spline([
{0, -2},
{3, 4},
{6, 5},
{7, -1},
{10, 3},
{5, 1},
{12, 9}
])
# Find any point along the curve (u goes from 0.0 to Curves.max_u(curve))...
Curves.solve!(curve, 1.5)
# ...or draw the whole curve as an SVG image
Curves.Svg.save!(curve, "b_spline.svg")How it is built
The B-spline is turned into a chain of cubic Bezier segments, one for every 3 points in a row,
and those are solved like a Bezier spline. Each segment starts at (p0 + 4 * p1 + p2) / 6,
which is where a B-spline crosses between segments. So n points give n - 3 segments,
and max_u is n - 3.
Stored points
The curve stores those generated Bezier points, not the points you passed in: 4 per segment, with each joint stored twice. For example, 6 points become 12. This also affects:
:force_percent, which rescales between those bounds instead of between your points.Curves.Svg, which draws the generated points as its dots.