The defintion of B-Spline basis function as shown below:
Let $\vec{U}=\{u_0,u_1,\ldots,u_m\}$ a nondecreasing sequence of real numbers,i.e, $u_i\leq u_{i+1}\quad i=0,1,2\ldots m-1$
$$N_{i,0}(u)= \begin{cases} 1 & u_i\leq u Although I know that Mathematica owns a built-in function Alogrithm: Test In my function In the book "The NURBS book", it defines this quotient $\frac{0}{0}$ to be zero. How to deal with the condition $\frac{0}{0}$ that I sometimes need to set it to 0 ? Namely, How to deal with the condition $u_i=u_{i+1}$ in B-Spline basis function?BSplineBasis
, however, I would like to write my auxiliay function $N_{i,p}(u)$ to learn the NURBS
theory and Mathematica programming.NBSpline
(*=======================Caculate N[i,0](u)================================*)
NBSpline[i_Integer, 0, u_Symbol, U : {Sequence[_] ..}] /;
i <= Length[U] - 2 :=
Piecewise[
{{1, U[[i + 1]] <= u < U[[i + 2]]},
{0, u < U[[i + 1]] || u >= U[[i + 2]]}}]
(*=======================Caculate N[i,p](u)================================*)
NBSpline[i_Integer, p_Integer, u_Symbol, U : {Sequence[_] ..}?OrderedQ] /;
p > 0 && i + p <= Length[U] - 2 :=
Module[{ini},
ini = Table[NBSpline[j, 0, u, U], {j, i, i + p}];
First@Simplify@
Nest[
Dot @@@
(Thread@
{Partition[#, 2, 1],
With[{m = i + p - Length@# + 1},
Table[
{(u - U[[k + 1]])/(U[[k + m + 1]] - U[[k + 1]]),
(U[[k + m + 2]] - u)/(U[[k + m + 2]] - U[[k + 2]])}, {k, i, i + Length@# - 2}]]}) &,
ini, p]
]NBSpline[1, 3, u, {1, 2, 3, 4, 5, 7}] // TraditionalForm
NBSpline
I avoid the condition $u_i=u_{i+1}$, because it will occured the case $\frac{0}{0}$Question
Answer
Here is one way to deal with repeated entries in U
. One can define a function to compute the coefficient, using one rule when $u_i = u_j$ and the general formula otherwise. One might put extra conditions on the patterns in coeff
below, but if the function is called only within NBSpline
, then one might assume the conditions are met.
ClearAll[coeff];
coeff[u_, i_, j_, U_] /; U[[i]] == U[[j]] := 0;
coeff[u_, i_, j_, U_] := (u - U[[i]])/(U[[j]] - U[[i]])
Then change the definition of NBSpline
for p != 0
as follows.
NBSpline[i_Integer, p_Integer, u_Symbol,
U : {Sequence[_] ..}?OrderedQ] /; p > 0 && i + p <= Length[U] - 2 :=
Module[{ini}, ini = Table[NBSpline[j, 0, u, U], {j, i, i + p}];
First@Simplify@
Nest[Dot @@@ (Thread@{Partition[#, 2, 1],
With[{m = i + p - Length@# + 1},
Table[{
coeff[u, k + 1, k + m + 1, U],
coeff[u, k + m + 2, k + 2, U]},
{k, i, i + Length@# - 2}]]}) &, ini, p]]
Example:
NBSpline[1, 3, u, {1, 2, 2, 4, 5, 7}]
The output of NBSpline[1, 3, u, {1, 2, 3, 4, 5, 7}]
agrees with the output in the question.
P.S. The pattern U : {Sequence[_] ..}?OrderedQ
is equivalent to U_List?OrderedQ
. You might want a check that restricts U
to be a list of numbers, since an ordered list of symbols such as {a, b, c}
passes the OrderedQ
test. The pattern U_?(VectorQ[#, NumericQ] && OrderedQ[#] &)
is one way.
Comments
Post a Comment