Skip to content

Commit

Permalink
faster findSpan function + more memory preallocation
Browse files Browse the repository at this point in the history
  • Loading branch information
HoBeZwe committed Oct 31, 2023
1 parent 497dd8a commit 3e8a76b
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 23 deletions.
57 changes: 42 additions & 15 deletions src/bSplines/basis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,12 @@ function (basis::Union{Bspline,CurrySchoenberg})(evalpoints)
end


struct pAlloc{T<:Real}
struct pAlloc{T<:Real,F<:Int}
B::Matrix{T}
N::Vector{T}
left::Vector{T}
right::Vector{T}
spanVec::Vector{F}
end


Expand All @@ -136,7 +137,7 @@ Evaluate B-spline basis at all evalpoints.
function (basis::Union{Bspline,CurrySchoenberg})(evalpoints, prealloc::pAlloc)

numBasis = numBasisFunctions(basis)
knotSpan = findSpan(numBasis, evalpoints, basis.knotVec, basis.degree)
knotSpan = findSpan!(prealloc.spanVec, numBasis, evalpoints, basis.knotVec, basis.degree)

return basisFun!(prealloc, knotSpan, evalpoints, basis)
end
Expand All @@ -155,12 +156,27 @@ function preAlloc(degree::Int, uVector::Vector{T}) where {T}
left = zeros(T, degree + 1)
right = zeros(T, degree + 1)

return pAlloc(B, N, left, right)
spanVec = similar(uVector, eltype(degree))

return pAlloc(B, N, left, right, spanVec)
end


"""
findSpan(b::T, uVec, kVec, p::T)
Allocate memory and call findSpan!
"""
function findSpan(b::T, uVec, kVec, p::T) where {T<:Int}

spanVec = similar(uVec, eltype(b))

return findSpan!(spanVec, b, uVec, kVec, p)
end


"""
findSpan(n::Int, u, knotVector)
findSpan!(spanVec, b::T, uVec, kVec, p::T)
Find the spans of a B-spline knot vector at the parametric points 'u', where 'b' is the number of basis functions (control points).
Expand All @@ -170,23 +186,34 @@ Modification of Algorithm A2.1 from 'The NURBS Book' p. 68.
Assumption that the knotVector is open! (the first and last knot are repeated degree + 1 times)
"""
function findSpan(b::Int, u, knotVector, p)
function findSpan!(spanVec, b::T, uVec, kVec, p::T) where {T<:Int}

# check input
#(minimum(u) < knotVector[1]) && (maximum(u) > knotVector[end]) && error("Some value is outside the knot span")
for (j, u) in enumerate(uVec)

# initialize the vector containing the indices
spanVec = similar(u, eltype(b))

for (j, uEval) in enumerate(u)

# special case: uEval == to last knot vector entry
if uEval == knotVector[end]
# --- Special case
if u == kVec[end]
spanVec[j] = b
continue
end

spanVec[j] = findlast(knotVector .≤ uEval)
# --- Do binary search
low = p + 1
high = b + 1

mid = Base.midpoint(low, high)

while u < kVec[mid] || u >= kVec[mid + 1] # is u in interval [ kVec[mid]...kVec[mid+1] ) ?

if u < kVec[mid]
high = mid
else
low = mid
end

mid = Base.midpoint(low, high)
end

spanVec[j] = mid
end

return spanVec
Expand Down
9 changes: 6 additions & 3 deletions src/bSplines/basisDerivatives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ function (basis::Bspline)(evalpoints, k::Int)
end


struct pAllocDer{T<:Real,L}
struct pAllocDer{T<:Real,F<:Int,L}
dersv::Array{T,L}
ders::Matrix{T}
ndu::Matrix{T}
left::Vector{T}
right::Vector{T}
a::Matrix{T}
spanVec::Vector{F}
end


Expand All @@ -101,7 +102,7 @@ function (basis::Bspline)(evalpoints::Vector{T}, k::Int, prealloc::pAllocDer) wh
#basis.divMax < 0 && error("The k-th derivative has to be k ≥ 0!")

numBasis = numBasisFunctions(basis)
knotSpan = findSpan(numBasis, evalpoints, basis.knotVec, basis.degree)
knotSpan = findSpan!(prealloc.spanVec, numBasis, evalpoints, basis.knotVec, basis.degree)

return derBasisFun!(prealloc, knotSpan, basis.degree, evalpoints, basis.knotVec, k)
end
Expand All @@ -122,7 +123,9 @@ function preAllocDer(degree::Int, evalpoints::Vector{T}, numberDerivatives::Int)
right = zeros(T, degree + 1)
a = zeros(T, 2, degree + 1)

return pAllocDer(dersv, ders, ndu, left, right, a)
spanVec = similar(evalpoints, eltype(degree))

return pAllocDer(dersv, ders, ndu, left, right, a, spanVec)
end


Expand Down
10 changes: 5 additions & 5 deletions src/nurbs/surfaces.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ Convenience function to compute points on all k derivatives of a NURBSsurface.
)


struct pAllocNURBSsuface{T<:Real,L}
preallocU::pAllocDer{T,L}
preallocV::pAllocDer{T,L}
struct pAllocNURBSsuface{T<:Real,F<:Int,L}
preallocU::pAllocDer{T,F,L}
preallocV::pAllocDer{T,F,L}
surfaces::Matrix{Matrix{SVector{3,T}}}
w::Matrix{Matrix{T}}
end
Expand Down Expand Up @@ -187,12 +187,12 @@ function surfaceDerivativesPoints!(

# u-direction: determine the basis functions evaluated at uVector
nbasisFun = length(uKnotVector) - uDegree - 1
uSpan = findSpan(nbasisFun, uVector, uKnotVector, uDegree)
uSpan = findSpan!(preallocU.spanVec, nbasisFun, uVector, uKnotVector, uDegree)
Nu = derBasisFun!(preallocU, uSpan, uDegree, uVector, uKnotVector, k)

# v-direction: determine the basis functions evaluated at vVector
nbasisFun = length(vKnotVector) - vDegree - 1
vSpan = findSpan(nbasisFun, vVector, vKnotVector, vDegree)
vSpan = findSpan!(preallocV.spanVec, nbasisFun, vVector, vKnotVector, vDegree)
Nv = derBasisFun!(preallocV, vSpan, vDegree, vVector, vKnotVector, k)

# initialize
Expand Down

0 comments on commit 3e8a76b

Please sign in to comment.