Although de Boor's algorithm is a standard way for computing the point on a B-spline curve that corresponds to a given u, we really need these coefficients in many cases (e.g., curve interpolation and approximation). We shall illustrate a simple way to do this.
Given a clamped B-spline curve of degree p defined by n+1 control points P_{0}, P_{1}, ..., P_{n}, and m+1 knots u_{0}=u_{1}=...=u_{p}=0, u_{p+1}, u_{p+2}, ..., u_{m-p-1}, u_{m-p}=u_{m-p+1}=...= u_{m}=1, we want to compute the coefficients N_{0,p}(u), N_{1,p}(u), ..., N_{n,p}(u) for any given u in [0,1]. A naive way is the use of the following recurrence relation:
However, this is a very time consuming process. To compute N_{i,p}(u), we need to compute N_{i,p-1}(u) and N_{i+1,p-1}(u). To compute N_{i,p-1}(u), we need to compute N_{i,p-2}(u) and N_{i+1,p-2}(u). To compute N_{i+1,p-1}(u), we need N_{i+1,p-2}(u) and N_{i+2,p-2}(u). As you can see, N_{i+1,p-2}(u) appears twice, and, as a result, its recursive computations will also be repeated. As the recursion goes deeper, more duplicated computations will occur. This is very similar to the recursive version of de Casteljau's algorithm discussed on a previous page. Consequently, the computation speed is very slow.
There is an easy way. Suppose u is in knot span [u_{k},u_{k+1}). An important property of B-spline basis functions states that at most p+1 basis functions of degree p are non-zero on [u_{k},u_{k+1}), namely: N_{k-p,p}(u), N_{k-p+1,p}(u), N_{k-p+2,p}(u), ..., N_{k-1,p}(u), N_{k,p}(u). By definition, the only non-zero basis function of degree 0 on [u_{k},u_{k+1}) is N_{k,0}(u). As a result, the coefficients can be computed from N_{k,0}(u) in a "fan-out" triangular form as shown below:
Since N_{k,0}(u) = 1 on knot span [u_{k},u_{k+1}) and other B-spline basis functions of degree 0 are zero on [u_{k},u_{k+1}), we can start from N_{k,0}(u) and compute the basis functions of degree 1 N_{k-1,1}(u) and N_{k,1}(u). From these two values, we can compute the basis functions of degree 2 N_{k-2,2}(u), N_{k-1,2}(u) and N_{k,2}(u). This process repeats until all p+1 non-zero coefficients are computed.
In this computation, "internal" values such as N_{k-1,2}(u) has a north-west predecessor (i.e., N_{k-1,1}(u)) and a south-west predecessor (i.e., N_{k,1}(u)); values on the north-east direction boundary of the above triangle such as N_{k-1,1}(u) has only a south-west predecessor (i.e., N_{k,0}(u)); and values on the south-east direction boundary of this triangle such as N_{k,2}(u) has only a north-west predecessor (i.e., N_{k,1}(u)). Thus, values that are on the north-east (resp., south-east) direction boundary use the second (resp., first) term of the recurrence relation in the definition. Only the internal values use both terms. Based on this observation, we have the following algorithm:
// now u is between u_{0} and u_{m}
Let u be in knot span
[u_{k},u_{k+1});
N[k] := 1.0 // degree 0 coefficient
for d :=1 to p do // degree d goes from 1 to p
Can you make this algorithm more efficient?