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.

Note

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")
┌ Warning: `PlotlyKaleido` 2.2.4 is not compatible with this version of `Plots`. The declared compatibility is 1.
└ @ Plots ~/.julia/packages/Plots/du2dt/src/backends.jl:55
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:

Note

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:

Tip

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