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

A centripetal Catmull-Rom spline: like `Curves.Spline.Type.CatmullRom`, but it takes the
distances between the knots into account, so it never makes little loops or sharp points
(cusps), even when some knots are much closer together than others.

You only give the knots, and the curve passes through every one of them. The `:alpha` option,
between `0.0` and `1.0`, sets how much the distances count:

| `:alpha` | Name | The curve... |
| --- | --- | --- |
| `0.0` | uniform | is exactly a `Curves.Spline.Type.CatmullRom` spline |
| `0.5` (the default) | centripetal | never loops or makes cusps within a segment |
| `1.0` | chordal | bends even more gently near knots that are far apart |

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

```elixir
# Two knots close together between two far away: plain Catmull-Rom makes a little loop here.
curve = Curves.define_centripetal_catmull_rom([{0, 0}, {10, 10}, {10.5, 10}, {20, 0}])

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

| Plain Catmull-Rom | Centripetal |
| --- | --- |
| ![Catmull-Rom makes a loop](images/spline_bunched_catmull_rom.svg) | ![Centripetal makes no loop](images/spline_centripetal.svg) |

## How it is built

Each segment, from knot `p1` to knot `p2`, looks at the knots either side, `p0` and `p3`. With
`d01`, `d12` and `d23` for the distances between them, each raised to the power `alpha`:

```text
leaving p1  = p2 - p1 + d12 * ((p1 - p0) / d01 - (p2 - p0) / (d01 + d12))
arriving p2 = p2 - p1 + d12 * ((p3 - p2) / d23 - (p3 - p1) / (d12 + d23))
```

Each segment is the Hermite segment with those tangents, stored as a cubic Bezier curve, and
`u` still adds one per segment. A knot's tangent can be longer on one side than the other, so the
speed along the curve can jump at a knot, but its direction never does.

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). Two knots in the same place make a segment that stays on that
point; a knot's neighbour in the same place is treated like the end of the curve.

---

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