Common How-to's
<!–
Bezier Functions
Splines.binomialcoeff
— Functionbinomialcoeff(n, i)
Calculate the Binomial Coefficient defined as:
\[\binom{n}{i} = \frac{n!}{i!(n-1)!}\]
Example
n = 6
i = 2
nchoosei = Splines.binomialcoeff(n, i)
15.0
Splines.bernsteincoeff
— Functionbernsteincoeff(u, n, i)
Calculate Bernstein Coefficient (Bezier Basis Function) defined as:
\[B_{i, n}(u) = \binom{n}{i} u^i (1-u)^{n-1}\]
at parametric point, $u$, where $0\leq u\leq1$. $u$ may either be a single value or an array.
(see NURBS, eqn 1.8)
Examples
example 1: single u value
u = 0.5
n = 6
i = 2
b = Splines.bernsteincoeff(u, n, i)
0.234375
example 2: u as an array
u = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
n = 6
i = 2
b = Splines.bernsteincoeff(u, n, i)
11-element Array{Float64,1}:
0.0
0.09841500000000002
0.2457600000000001
0.3241349999999999
0.31104000000000004
0.234375
0.13824
0.059535000000000025
0.015359999999999988
0.0012149999999999989
0.0
Splines.simple_bezier1D
— Functionsimple_bezier1D(P, u)
Calculate a point along a Bezier curve at the parametric point, $u$, based on the control points, $\mathbf{P}$, where the Bezier curve, $\mathbf{C}(u)$, is defined as:
\[\mathbf{C}(u) = \sum_{i=0}^n B_{i, n}(u) \mathbf{P}_i~, ~~~~ 0 \leq u \leq 1\]
where $B$ is the basis (Bernstein Coefficient) at parametric point, $u$, as calculated from bernsteincoeff
, and n is the number of control points in vector $\mathbf{P}$. Again, $u$ may either be a single value or an array.
(see NURBS eqn 1.7)
Example
P = [0.0 0.0; 0.0 0.1; 0.3 0.25; 1.0 0.0] #control point definition
u = collect(0:0.05:1.0) #parametric points
bezierCurve = Splines.simple_bezier1D(P, u)
21×2 Array{Float64,2}:
0.0 0.0
0.00014875 0.0014725
0.00118 0.00576
0.00394875 0.0126225
0.00928 0.02176
0.0179687 0.0328125
0.03078 0.04536
0.0484487 0.0589225
0.07168 0.07296
0.101149 0.0868725
⋮
0.23328 0.12096
0.293849 0.127173
0.36358 0.12936
0.442969 0.126562
0.53248 0.11776
0.632549 0.101873
0.74358 0.07776
0.865949 0.0442225
1.0 0.0
B-Spline Functions
Missing docstring for Splines.getspanindex(n, p, u, U)
. Check Documenter's build log for details.
Example
U = [0,0,0,1,2,3,4,4,5,5,5]
p = 2
n = length(U)-p-1
u = 5/2
Splines.getspanindex(n,p,u,U)
u = 5
Splines.getspanindex(n,p,u,U)
u = 0
Splines.getspanindex(n,p,u,U)
Splines.basisfunctions
— Methodbasisfunctions(span, deg, knots, u)
(private function) Compute nonvanishing basis functions (NURBS A2.2)
Arguments
deg::Integer
: degreeknots::Vector{Float64}
:: a knot vector (u0, ... un+1)u
::Float64`: nondimensional location we are searching forspan::Integer
: corresponding index i for u between knotsi and knotsi+1 (computed from getspanindex)
Returns
N::Vector{Float64}
: vector of length N0 ... Ndeg
Example
import Splines # hide
U = [0,0,0,1,2,3,4,4,5,5,5]
u = 5/2
p = 2
i = 5
bases = Splines.basisfunctions(i,u,p,U)
Splines.basisfunctionsderivatives
— Methodbasisfunctionsderivatives(span, deg, knots, u, n)
(private function) Calculate the non-vanishing basis functions and derivatives of the B-Spline of order $p$, defined by knots U at parametric point,
u
`. (NURBS A 2.3)
Arguments
span::Integer
: knot span containing udeg::Integer
: the curve orderknots::Vector{Float}
: the knot vectoru::Float
: parametric point of interestn::Integer
: the max derivative order (n ≦ p)
Returns
ders::Matrix{Float}
: [0..n, 0..p] ders[0, :] function values, ders[1: :], first derivatives, etc.
Example
import Splines # hide
U = [0,0,0,1,2,3,4,4,5,5,5]
u = 5/2
p = 2
i = 5
n = p
derivatives = Splines.basisfunctionsderivatives(i,u,p,n,U)
Missing docstring for Splines.curvederivatives1(n, p, U, P, u, d)
. Check Documenter's build log for details.
Example
import Splines # hide
U = [0,0,0,1,2,3,4,4,5,5,5]
u = 5/2
p = 2
n = length(U)-p-1
P = [0 0; 1/2 1/2; 1 0; 3/2 1/2; 2 0; 5/2 1/2; 3 0]
d = 1
curveDerivatives = Splines.curvederivatives1(n, p, U, P, u, d)
Missing docstring for Splines.curvederivativecontrolpoints(n, p, U, P, d, r1, r2)
. Check Documenter's build log for details.
Example
import Splines # hide
U = [0,0,0,0,2/5,3/5,3/5,1,1,1,1]
u = 1/2
i = 4
d = 1
p = 3
P = [0 0; 1/2 1/2; 1 0; 3/2 1/2; 2 0; 5/2 1/2; 3 0]
n = length(P[:,1])-1
r1 = 0
r2 = n
cprime = Splines.curvederivativecontrolpoints(n, p, U, P, d, r1, r2)
Missing docstring for Splines.globalcurveinterpolation(n,Q,r,p; knotplacement)
. Check Documenter's build log for details.
Example
import Splines # hide
Q = [0 0; 3 4; -1 4; -4 0; -4 -3]
r = 2
n = 4
p = 3
U = [0 0 0 0 28/51 1 1 1 1]
m, U, P = Splines.globalcurveinterpolation(n,Q,r,p;knotplacement="chordlength")
NURBS Functions
Splines.nurbsbasis
— Functionnurbsbasis(u,p,d,U,w)
Get rational basis functions and derivatives.
\[R_{i,p}(u) = \frac{N_{i,p}(u)w_i}{\sum_{j=0}^n N_{j,p}(u)w_j}\]
where $N_{i,p}(u )$ are B-Spline Basis Functions and $w_i$ are weights associated with the NURBS control points.
(see NURBS eqn 4.2)
Inputs:
- u : parametric point of interest
- p : the curve order
- d : the max derivative order (n ≦ p)
- U : the knot vector
- w : control point weights
Example
import Splines #hide
U = [0,0,0,1,2,3,4,4,5,5,5] #knot vector
w = [1,1,1,1,1,1,1] #control point weights
u = 5/2 #parametric point of interest
p = 2 #curve degree
n = 1 #number of derivatives
R, dR = Splines.nurbsbasis(u,p,n,U,w) #rational bases and first derivatives
Splines.curvepoint
— FunctionEvaluate point on B-spline curve (NURBS, A3.1)
Arguments
bspline::BSpline: bspline object
u::Float
: point on spline to evaluate at
Returns
C::Vector{Float}
: point in ND space
Evaluate point on rational b-spline curve (NURBS, A4.1)
Arguments
nurbs::NURBS: NURBS object
u::Float
: point on spline to evaluate at
Returns
C::Vector{Float}
: point in ND space
Examples
example 1: single point
import Splines # hide
U = [0, 0, 0, 1, 1, 1] #knot vector
u = 0 #parametric point of interest
p = 2 #curve order
P = [1 0; 1 1; 0 1] #unweighted points
w = [1 1 2] #weights
Pw = [1 0 1; 1 1 1; 0 2 2] #weighted points
n = length(P[:, 1])-1
Cw = Splines.curvepoint(n, p, U, Pw, u)
example 2: array of points
U = [0, 0, 0, 1, 1, 1] #knot vector
u = collect(0:0.05:1.0) #parametric points
p = 2 #curve order
P = [1 0; 1 1; 0 1] #unweighted points
w = [1 1 2] #weights
Pw = [1 0 1; 1 1 1; 0 2 2] #weighted points
n = length(P[:, 1])-1
Cw = zeros(length(u), length(Pw[1, :]))
for i = 1:length(u)
Cw[i, :] = Splines.curvepoint(n, p, U, Pw, u[i])
end
Missing docstring for Splines.rationalcurvederivatives
. Check Documenter's build log for details.
Example
import Splines # hide
U = [0, 0, 0, 1, 1, 1] #knot vector
u = 0 #parametric point of interest
p = 2 #curve order
P = [1 0; 1 1; 0 1] #unweighted points
w = [1 1 2] #weights
Pw = [1 0 1; 1 1 1; 0 2 2] #weighted points
n = length(P[:, 1])-1
d = 2 #max derivative level (2nd derivative)
#Calculate Cw(u) derivatives
ders = Splines.curvederivatives1(n, p, U, Pw, u, d)
#Separate derivatives
Aders = ders[:, 1:end-1]
wders = ders[:, end]
#Calculate NURBS derivatives
CK = Splines.rationalcurvederivatives(Aders, wders, d)
Splines.curveknotinsertion
— Functioncurveknotinsertion(np, p, UP, Pw, u, k, s, r)
Compute a new curve from knot insertion. Using the formula:
\[\mathbf{Q}_{i, r}^w = \alpha_{i, r} \mathbf{Q}_{i, r-1}^w + (1-\alpha_{i, r}) \mathbf{Q}_{i-1, r-1}^w\]
where
\[\alpha_{i, r} = \begin{cases} 1 & i \leq k-p+r-1 \\ \frac{\bar{u} - u_i}{u_{i+p-r+1} - \bar{u}_i} & k-p+r \leq i\leq k-s \\ 0 & i \geq k-s+1 \end{cases}\]
(see NURBS eqn 5.15 and A5.1)
Inputs:
- np : the number of control points minus 1 (the index of the last control point) before insertion
- p : the curve order
- UP : the knot vector before insertion
- Pw : the set of weighted control points and weights before insertion
- u : the knot to be added
- k : the span index at which the knot is to be inserted.
- s : numer of instances of the new knot alrady present in the knot vector, UP
- r : number of times the new knot is inserted (it is assumed that $r+s \leq p$ )
Outputs:
- nq : the number of control points minus 1 (the index of the last control point) after insertion
- UQ : the knot vector after insertion
- Qw : the set of weighted control points and weights after insertion
Examples
example 1: Unique Knot Insertion
UP = [0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5]
u = 5/2
p = 3
P = [0 0; 1 1; 2 0; 3 0; 4 1; 3 2; 2 2; 1.5 1]
w = [1 1 1 1 1 1 1 1]
Pw = [0 0 1; 1 1 1; 2 0 1; 3 0 1; 4 1 1; 3 2 1; 2 2 1; 1.5 1 1]
np = length(P[:, 1])-1
k = 5
s = 0
r = 1
nq, UQ, Qw = Splines.curveknotinsertion(np, p, UP, Pw, u, k, s, r)
example 2: Repeated Knot Insertion
UP = [0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5]
u = 2
p = 3
P = [0 0; 1 1; 2 0; 3 0; 4 1; 3 2; 2 2; 1.5 1]
w = [1 1 1 1 1 1 1 1]
Pw = [0 0 1; 1 1 1; 2 0 1; 3 0 1; 4 1 1; 3 2 1; 2 2 1; 1.5 1 1]
np = length(P[:, 1])-1
k = 5
s = 1
r = 1
nq, UQ, Qw = Splines.curveknotinsertion(np, p, UP, Pw, u, k, s, r)
Splines.refineknotvectorcurve
— Functionrefineknotvectorcurve(n, p, U, Pw, X, r)
Refine curve knot vector using NURBS A5.4.
This algorithm is simply a knot insertion algorithm that allows for multiple knots to be added simulataneously, i.e., a knot refinement procedure.
Inputs:
- n : the number of control points minus 1 (the index of the last control point) before insertion
- p : the curve order
- U : the knot vector before insertion
- Pw : the set of weighted control points and weights before insertion
- X : elements, in ascending order, to be inserted into U (elements should be repeated according to their multiplicities, e.g., if x and y have multiplicites 2 and 3, X = [x,x,y,y,y])
- r : length of X vector - 1
Outputs:
- Ubar : the knot vector after insertion
- Qw : the set of weighted control points and weights after insertion
Example
U = [0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5] #original knot vector
X = [1.5, 2.5] #knots to be added (ascending order)
p = 3 #curve order
Pw = [0 0 1; 1 1 1; 2 0 1; 3 0 1; 4 1 1; 3 2 1; 2 2 1; 1 1 1] #weighted control points
n = length(P[:,1])-1 #largest zero-based index in control point vector
r = length(X)-1 #largest zero-based index in X (vector of knots to be added)
Ubar, Qw = Splines.refineknotvectorcurve(n, p, U, Pw, X, r)
Splines.degreeelevatecurve
— Functiondegreeelevatecurve(n,p,U,Pw,t)
Raise degree of spline from p to p $+t$, $t \geq 1$ by computing the new control point vector and knot vector.
Knots are inserted to divide the spline into equivalent Bezier Curves. These curves are then degree elevated using the following equation.
\[\mathbf{P}^t_i = \sum^{\textrm{min}(p,i)}_{j=\textrm{max}(0,i-t)} \frac{\binom{p}{j} \binom{t}{i-j} \mathbf{P}_j}{\binom{p+t}{i}}~,~~~~~i=0,...,p+t\]
where $\mathbf{P}^t_i$ are the degree elevated control points after $t$ -degree elevations
Finally, the excess knots are removed and the degree elevated spline is returned.
(see NURBS eqn 5.36, A5.9)
Inputs:
- n : the number of control points minus 1 (the index of the last control point) before degree elevation
- p : the curve order
- U : the knot vector before degree elevation
- Pw : the set of weighted control points and weights before degree elevation
- t : the number of degrees to elevate, i.e. the new curve degree is p+t
Outputs:
- nh : the number of control points minus 1 (the index of the last control point) after degree elevation
- Uh : the knot vector after degree elevation
- Qw : the set of weighted control points and weights after degree elevation
Examples
example 1: Single Degree Elevation
U = [0,0,0,0,3/10,7/10,1,1,1,1]
p = 3
P = [-1 0; -1.5 1; -0.5 2; 0.5 2; 1.5 1; 1 0]
w = [1 1 1 1 1 1]
Pw = [-1 0 1; -1.5 1 1; -0.5 2 1; 0.5 2 1; 1.5 1 1; 1 0 1]
n = length(P[:,1])-1
t = 1
nh, Uh, Qw = Splines.degreeelevatecurve(n,p,U,Pw,t)
example 2: 2 Degree Elevation
U = [0,0,0,0,3/10,7/10,1,1,1,1]
p = 3
P = [-1 0; -1.5 1; -0.5 2; 0.5 2; 1.5 1; 1 0]
w = [1 1 1 1 1 1]
Pw = [-1 0 1; -1.5 1 1; -0.5 2 1; 0.5 2 1; 1.5 1 1; 1 0 1]
n = length(P[:,1])-1
t = 2
nh, Uh, Qw = Splines.degreeelevatecurve(n,p,U,Pw,t)
–>