matrix equations for a spline
matrix equation for an open curve
The matrix equation to be solved is
$$
\begin{pmatrix}
b_{0} & c_0 & & & 0 \\
a_{1} & b_{1} & c_1 & & \\
& a_{2} & b_{2} & \ddots & \\
& & \ddots & \ddots & c_{n-1} \\
0 & & & a_n & b_n
\end{pmatrix}
\begin{pmatrix}
P_{1,0} \\
P_{1,1} \\
P_{1,2} \\
\vdots \\
P_{1,n}
\end{pmatrix}
=
\begin{pmatrix}
r_{0} \\
r_{1} \\
r_{2} \\
\vdots \\
r_{n}
\end{pmatrix}
\quad\quad\quad (12)
$$
in which
$$
\begin{align}
b_{0} &= 2 &\\
c_{0} &= w_0/w_1 &\\
a_{i} &= w_i^2 & i \in \{1,\dots, n-1\} \\
b_{i} &= 2w_{i-1}(w_{i-1}+w_i) & i \in \{1,\dots, n-1\} \\
c_{i} &= (w_{i-1})^2w_i/w_{i+1} & i \in \{1,\dots, n-1\} \\
a_{n} &= 1 &\\
b_{n} &= 2 w_{n-1}/w_n&
\end{align}
$$ and
$$
\begin{align}
r_0 &= K_{0} + K_1 \left( 1+ {w_{0} \over w_{1}} \right) \\
r_i &= K_{i}\left( w_{i-1} + w_{i}\right)^2 + K_{i+1} w_{i-1}^2 \left( 1+ {w_{i} \over w_{i+1}} \right) & i \in \{1,\dots, n-1\} \\
r_n &= K_n \left( 1+2 {w_{n-1} \over w_{n}} \right)
\end{align}
$$
(corrected on 2018-08-16 after a comment by R.B.A. van Hoek)
The equation must be solved 2 times: 1 time for the \(x\) coordinates, and 1 time for the \(y\) coordinates of \(\mathbf P_{1,i}\).
matrix equation for a closed curve
In this case, \(n\) knots will be labeled \(0,1,\dots,n-1\).
$$
\begin{pmatrix}
b_{0} & c_0 & & & a_0 \\
a_{1} & b_{1} & c_1 & & \\
& a_{2} & b_{2} & \ddots & \\
& & \ddots & \ddots & c_{n-2} \\
c_{n-1} & & & a_{n-1} & b_{n-1}
\end{pmatrix}
\begin{pmatrix}
P_{1,0} \\
P_{1,1} \\
P_{1,2} \\
\vdots \\
P_{1,n-1}
\end{pmatrix}
=
\begin{pmatrix}
r_{0} \\
r_{1} \\
r_{2} \\
\vdots \\
r_{n-1}
\end{pmatrix}
\quad\quad\quad (13)$$
Again we have
$$
\begin{align}
a_{i} &= w_i^2 & i \in \{0,\dots, n-1\} \\
b_{i} &= 2w_{i-1}(w_{i-1}+w_i) & i \in \{1,\dots, n-1\} \\
c_{i} &= (w_{i-1})^2w_i/w_{i+1} & i \in \{1,\dots, n-2\} \\
r_i &= K_{i}\left( w_{i-1} + w_{i}\right)^2 + K_{i+1} w_{i-1}^2 \left( 1+ {w_{i} \over w_{i+1}} \right) & i \in \{1,\dots, n-2\} \\
\end{align}
$$
Of course, we use index \(0\) in stead of \(n\), so the formulas yield:
$$
\begin{align}
b_{0} &= 2w_{n-1}(w_{n-1}+w_0) \\
c_{0} &= (w_{n-1})^2w_0/w_{1} \\
c_{n-1} &= (w_{n-2})^2w_{n-1}/w_{0} \\
r_0 &= K_{0}\left( w_{n-1} + w_{0}\right)^2 + K_{1} w_{n-1}^2 \left( 1+ {w_{0} \over w_{1}} \right) \\
r_{n-1} &= K_{n-1}\left( w_{n-2} + w_{n-1}\right)^2 + K_{0} w_{n-2}^2 \left( 1+ {w_{n-1} \over w_{0}} \right)
\end{align}
$$
Gaussian elimination
The equation (12) can be solved using Gaussian elimination. Because the matrix for the open curve is tri-diagonal the Thomas algorithm can be used.
For a looped curve (equation (13)), I will describe the algorithm below.
The non-zero entries of the matrix will be stored in arrays
a, b
and c
with indices 0 till n-1
.
The right-hand-side is the array r
with indices 0 till n-1
.
During Gaussian elimination, the elements in the most right column of the matrix (under \(a_0\)) will change and I will store them in the array u
with indices 0 till n-2
.
The elements on the lowest row will also change, but become zero again. So, in stead of an array L
with indices 0 till n-2
, I use a single variable L
.
In this way, the algorithm becomes:
u[0] = a[0]
L = c[n-1]
for (i = 0; i < n-3; i++)
{
m1 = a[i+1]/b[i];
b[i+1] -= m1 * c[i];
// last column
u[i+1] = -m1 * u[i]
// last row :
m2 = L/b[i]
b[n-1] -= m2 * u[i]
L = - m2 * c[i]
// right-hand side
r[i+1] -= m1 * r[i];
r[n-1] -= m2 * r[i]
}
After this, the matrix equation has become
$$
\begin{pmatrix}
b_{0} & c_0 & & & & u_0 \\
0 & b_{1} & c_1 & & & u_1\\
& \ddots & \ddots & \ddots & & \vdots\\
& & 0 & b_{n-3} & c_{n-3} & u_{n-3}\\
& & & a_{n-2} & b_{n-2} & c_{n-2} \\
0 & & & L & a_{n-1} & b_{n-1} \end{pmatrix}
\begin{pmatrix}
P_{1,0} \\
P_{1,1} \\
P_{1,2} \\
\vdots \\
P_{1,n-1}
\end{pmatrix}
=
\begin{pmatrix}
r_{0} \\
r_{1} \\
r_{2} \\
\vdots \\
r_{n-1}
\end{pmatrix}
$$
So the next steps must be (note that i = n-3
)
m1 = a[i+1]/b[i];
b[i+1] -= m1 * c[i];
// last column
c[i+1] -= m1 * u [i]
// last row
m2 = L/b[i]
b[n-1] -= m2 * u[i]
a[n-1] -= m2 * c[i]
// right-hand side
r[i+1] -= m1 * r[i];
r[n-1] -= m2 * r[i]
which yields
$$
\begin{pmatrix}
b_{0} & c_0 & & & & u_0 \\
0 & b_{1} & c_1 & & & u_1\\
& \ddots & \ddots & \ddots & & \vdots\\
& & 0 & b_{n-3} & c_{n-3} & u_{n-3}\\
& & & 0 & b_{n-2} & c_{n-2} \\
0 & & & 0 & a_{n-1} & b_{n-1} \end{pmatrix}
\begin{pmatrix}
P_{1,0} \\
P_{1,1} \\
P_{1,2} \\
\vdots \\
P_{1,n-1}
\end{pmatrix}
=
\begin{pmatrix}
r_{0} \\
r_{1} \\
r_{2} \\
\vdots \\
r_{n-1}
\end{pmatrix}
$$
After
i = n-2
m = a[i+1]/b[i];
b[i+1] -= m * c[i];
r[i+1] -= m * r[i];
this becomes
$$
\begin{pmatrix}
b_{0} & c_0 & & & & u_0 \\
0 & b_{1} & c_1 & & & u_1\\
& \ddots & \ddots & \ddots & & \vdots\\
& & 0 & b_{n-3} & c_{n-3} & u_{n-3}\\
& & & 0 & b_{n-2} & c_{n-2} \\
0 & & & & 0 & b_{n-1} \end{pmatrix}
\begin{pmatrix}
P_{1,0} \\
P_{1,1} \\
P_{1,2} \\
\vdots \\
P_{1,n-1}
\end{pmatrix}
=
\begin{pmatrix}
r_{0} \\
r_{1} \\
r_{2} \\
\vdots \\
r_{n-1}
\end{pmatrix}
$$
Then the backward substitution becomes easy:
x[n-1] = r[n-1]/b[n-1];
x[n-2] = (r[n-2] - c[n-2] * x[n-1]) / b[n-2];
for (i = n - 3; i >= 0; --i)
{ x[i] = (r[i] - c[i] * x[i+1]-u[i]*x[n-1]) / b[i];
}
Previous