# `Curves.Spline.Type.NaturalCubic`
[🔗](https://github.com/greetingsfellowhumans/curves/blob/main/lib/curves/spline/types/natural_cubic.ex#L1)

A natural cubic spline: the smoothest curve that passes through every knot.

Catmull-Rom and its relatives only keep the curve's direction smooth at each knot. A natural
cubic spline also keeps its *bend* (its curvature) smooth, like a `Curves.Spline.Type.BSpline`,
but unlike a B-spline it still goes through every knot. It is what you get if you bend a thin,
flexible strip of wood or metal through pins at the knots, which is where the name "spline" comes
from. At the first and last knots it straightens out, as a free strip would.

The catch is that every knot affects the whole curve: moving one knot changes every segment a
little, not just the nearby ones.

A spline with `n` knots has `n - 1` segments, like Catmull-Rom.

```elixir
curve = Curves.define_natural_cubic([{0, 0}, {2, 3}, {4, 1}, {6, 4}, {8, 2}])

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

![Natural cubic spline](images/spline_natural_cubic.svg)

## How it is built

The tangents `D0 .. Dn-1` at the knots `P0 .. Pn-1` are the ones that make the curve's bend
continuous at every knot and zero at both ends. They come from solving these equations together
(each is one row of a tridiagonal system, solved in one pass each way):

```text
2 * D0   + D1                = 3 * (P1 - P0)
D(i - 1) + 4 * Di + D(i + 1) = 3 * (P(i + 1) - P(i - 1))     for every middle knot
D(n - 2) + 2 * D(n - 1)      = 3 * (P(n - 1) - P(n - 2))
```

Each segment is then the Hermite segment between two knots, stored as a cubic Bezier curve.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
