Splines
Given a set of control points, we are interested in finding a "smooth" interpolation (note that this can be \(C^k\) smooth, not necessarily mathematically smooth \(C^\infty\)) over the control points. In general, we look at splines, or piecewise polynomials functions because they are easy to construct and evaluate.
Cubic Hermite Interpolation
Given the endpoints \(P(0), P(1)\) and its derivative \(P'(0), P'(1)\), we can interpolate a spline over the interval \([0, 1]\) using a cubic polynomial.
Polynomial basis functions
A polynomial function is defined as
where \(C = [c_0, c_1, c_2, \cdots c_d], \mathcal P^d(u) = [1, u, u^2, \cdots, u^d]\) and the elements of \(P^d\) are linearly independent \(\forall k. u^k \neq \sum_{i\neq k} c_i u^i\).
Polynomial Fitting
Construct a cubic polynomial and its derivative
Then, given the endpoints and derivative at end points
This system of equations can be written as \(\begin{bmatrix}1&0&0&0\\1&1&1&1\\0&1&0&0\\0&1&2&3\end{bmatrix} \begin{bmatrix}c_0\\c_1\\c_2\\c_3\end{bmatrix} = \begin{bmatrix}P(0)\\P(1)\\P'(0)\\P'(1)\end{bmatrix}\), or conveniently through a multiplication of the inverse matrix
\(\beta_H\) is called the Hermite basis matrix.
Catmull-Rom Interpolation
Now, consider multiple control points (without knowing the derivative). Note that each points introduces one equations and we could use high-order polynomials to fit. However, high-order polynomials require more computations and is not stable. Instead, for each control point, we aim to match slop between its previous and next value.
Consider 4 points \((u_0, x(u_0)), (u_1, x(u_1)), (u_2, x(u_2)), (u_3, x(u_3))\), set the slope at \(x(u_i)\) as \(d_ux|_{u_i} = \frac{1}{2}{x(u_{i+1}) - x(u_{i-1})}\) and we can use cubic Hermite interpolation to compute the curve between each pair of neighboring points. In addition, the overall curve is \(C^1\) continuous. For each point, its derivative is defined and it's continuous from both left and right.
Matrix Form
Note that for every parameterized curve \((u, \mathbf x(u))\), whether \(\mathbf x\) is 1D, 2D, or 3D, we have the general schema
where \(\mathcal P(u)\) is the polynomial basis, \(\beta_H\) is the Hermite basis matrix, and \(\mathbf h\) are the control points values. In this case,
so that we can write everything in full
Then, note that \(\beta_H\cdot M_{CR\rightarrow H}\) are both pre-defined and we can combine them into one Catmull-Rom basis matrix as
Bezier Curves
Instead of finding a curve passing through 4 points, now we let \(\mathbf x'(u_0) = 3(\mathbf p_1 - \mathbf p_0)\) be the tangent for \(\mathbf p_0\) and \(\mathbf x'(u_3) = 3(\mathbf p_3 - \mathbf p_2)\) be the tangent of \(\mathbf p_3\), and Bezier curve pass through \(\mathbf p_0\) and \(\mathbf p_3\) with slope specified before. Now, we can use cubic Hermite directly as
and similarly we have
and the cubic Bezier matrix as
Convex hull property
Convex hull property means that all points on curve are inside the convex hull formed by control points. A spline has convex hull property if for any \(u\), the basis functions are all non-negative and sum to \(1\).
For example, the Bezier basis functions are
Implementing splines
basis_catmull_rom = np.array([
[0, 1, 0, 0],
[-0.5, 0, 0.5, 0],
[1, -2.5, 2,-0.5],
[-0.5, 1.5,-1.5, 0.5]
])
basis_cubic_bezier = np.array([
[1, 0, 0, 0],
[-3, 3, 0, 0],
[3, -6, 3, 0],
[-1, 3, -3, 1]
])
def spline(p, basis, n=20):
u = np.linspace(0, 1, n)
P = np.vstack([
np.ones(n),
u,
u * u,
u * u * u
])
return P.T @ basis @ p
de Casteljau Algorithm
Consider control points \(\mathbf p^0_0, \mathbf p^0_1, \mathbf p^0_2, \mathbf p^0_3\) and \(u\in[0, 1]\). Define
We can recursively compute the equation 3 times until one point left and let \(\mathbf x(t) = \mathbf p^3_0\). Then, it is the value for Bezier curve.
Note that this can be extended to \(n\)-order polynomials as
Bezier Surfaces
A surface is defined by some function \(\mathbf x(u, v)\). Therefore, we need \(4\times 4\) control points and then for each \((u,v)\) we can interpolate per-row Bezier curves in \(u\), and then per-column Bezier curve in \(v\).
We can write the surface in matrix form as
where \(P\) is the \(4 \times (4 \times 3)\) matrix of all control points.