Curves.Spline.Type.KochanekBartels (curves v1.0.1)

Copy Markdown View Source

A Kochanek–Bartels spline, also called a TCB spline: a Catmull-Rom spline with three dials, :tension, :continuity and :bias, that change how the curve passes through each knot. Animation tools use it for keyframes.

You only give the knots, and the curve passes through every one of them. Each dial is a number, usually between -1.0 and 1.0, and 0.0 by default. With all three at 0.0 it is exactly a Curves.Spline.Type.CatmullRom spline.

OptionBelow 0.0Above 0.0
:tensionrounder, wider bendstighter bends (1.0 stops at each knot), like Curves.Spline.Type.Cardinal
:continuitysharper corners: at -1.0 it turns at each knot like a polylinecorners that bulge out: it keeps going past each knot, then turns back
:biasturns early: the curve leans towards the next knotturns late: the curve overshoots past each knot

A spline with n knots has n - 1 segments, like Catmull-Rom. The dials apply to every knot.

curve = Curves.define_kochanek_bartels([{0, 0}, {2, 3}, {4, 1}, {6, 4}, {8, 2}], bias: 0.5)

# 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, "kochanek_bartels.svg")

Kochanek-Bartels spline with bias 0.5

How it is built

Unlike the other splines, the curve can arrive at a knot with one tangent and leave it with another (that is how :continuity makes corners). With t, c and b for the three dials, and the knot p between previous and next:

leaving  = (1 - t)(1 + c)(1 + b) / 2 * (p - previous) + (1 - t)(1 - c)(1 - b) / 2 * (next - p)
arriving = (1 - t)(1 - c)(1 + b) / 2 * (p - previous) + (1 - t)(1 + c)(1 - b) / 2 * (next - p)

The first and last knots have no knot on one side, so they get a made-up one, mirrored through the end (the same as Catmull-Rom). Each segment is then the Hermite segment between two knots, stored as a cubic Bezier curve.