Bases
The considered
- B-spline,
- Curry-Schoenberg, and
- NURBS
basis functions are defined by initializing corresponding structures. A naive evaluation method is available for all, an efficient evaluation only for B-splines and Curry-Schoenberg splines.
Defining Structures
B-spline, Curry-Schoenberg, and NURBS bases are defined by initializing a Bspline
, a CurrySchoenberg
, or a NURB
structure, respectively.
# --- parameters
b = 6 # number of basis functions
p = 2 # degree of NURBS
w = ones(b) # weights for NURBS
w[4] = 1.8
# --- resulting knot vector
kVec = generateKnotVec(b, p)
# --- structures
Bspl = Bspline(p, kVec)
Nrbs = NURB(p, kVec, w)
Cspl = CurrySchoenberg(p, kVec)
Naive Evaluation
To evaluate the bases at certain points the evalNaive
function is provided. It directly implemens the defining equations of the B-splines, the CurrySchoenberg, and NURBS. For the derivatives the evalNaiveDerivative
function is provided derectly implementing the defining equations of the derivatives.
The naive evaluation methods are solely implemented to play around with parameters (to get familiar with NURBS and B-splines).
# --- define points where the bases are evaluated
evalpoints = collect(0:0.001:1.0)
# --- evaluate bases (4-th basis function)
bspline = evalNaive(Bspl, 4, evalpoints)
nurb = evalNaive(Nrbs, 4, evalpoints)
cspl = evalNaive(Cspl, 4, evalpoints)
# --- evaluate derivatives (1st derivative of 4-th basis function)
bsplineD = evalNaiveDerivative(Bspl, 4, 1, evalpoints)
nurbD = evalNaiveDerivative(Nrbs, 4, 1, evalpoints)
using Plots
plotly()
Plots.plot(evalpoints, bspline, w=2,
label="B-spline",
title="4-th basis function",
xlabel="𝑢",
ylabel="𝑁₄,₂(𝑢)")
Plots.plot!(evalpoints, nurb, w=2, label="NURB")
Plots.plot!(evalpoints, cspl, w=2, label="Curry-Schoenberg")
Plots.plot(evalpoints, bsplineD, w=2,
label="B-spline",
title="1st derivative of 4-th basis function",
xlabel="𝑢",
ylabel="∂ᵤ 𝑁₄,₂(𝑢)")
Plots.plot!(evalpoints, nurbD, w=2, label="NURB")
Efficient Evaluation
For the B-splines and the Curry-Schoenberg splines the efficient evaluation of [1] is implemented by handing evaluation points to the Bspline
structure and optionally as second argument (only for the B-splines) the maximum derivative that shall be computed. That is, only the basis functions different from zero are evaluated:
For the evaluation of NURBS curves and surfaces (and their derivatives) the B-spline evaluation is sufficient.
bspline = Bspl(evalpoints)
crySbrg = Cspl(evalpoints)
bsplineD = Bspl(evalpoints, 2) # 0th, 1st, and 2nd derivative
Plots.plot(evalpoints, bspline, w=2,
leg=false,
title="all basis functions",
xlabel="𝑢",
ylabel="𝑁ᵢ,₂(𝑢)")
Plots.plot(evalpoints, crySbrg, w=2,
leg=false,
title="all basis functions",
xlabel="𝑢",
ylabel="𝑛ᵢ,₂(𝑢)")
Plots.plot(evalpoints, bsplineD[:, 2, :], w=2,
leg=false,
title="1st derivative of all basis functions",
xlabel="𝑢",
ylabel="∂ᵤ 𝑁ᵢ,₂(𝑢)")
Memory Preallocation
In case B-splines shall be evaluated repeatedly memory can be preallocated and reused in subsequent calls:
This is useful especially if single points are evaluated many times on demand.
pM = NURBS.preAlloc(p, evalpoints)
pD = NURBS.preAllocDer(p, evalpoints, 2)
bspline = Bspl(evalpoints, pM)
crySbrg = Cspl(evalpoints, pM)
bsplineD = Bspl(evalpoints, 2, pD) # 0th, 1st, and 2nd derivative