Hi all,
I’m pleased to announce my package BasicBSpline.jl v0.9.4 (repo, docs).
Introduction
This package provides basic mathematical operations for B-spline.
- B-spline basis function
- Some operations for knot vector
- Some operations for B-spline space (piecewise polynomial space)
- B-spline manifold (includes curve, surface, and solid)
- Refinement algorithm for B-spline manifold
- Interpolations (not fully supported. see documentation)
- Fitting control points for a given function (in BasicBSplineFitting.jl)
- Export graphics (in BasicBSplineExporter.jl)
Basic usage
Evaluating B-spline function
julia> using BascBSpline
julia> using Plots
julia> k = KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])
KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])
julia> P = BSplineSpace{2}(k) # 2nd degree piecewise polynomial space
BSplineSpace{2, Float64, KnotVector{Float64}}(KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0]))
julia> b = bsplinebasis(P,1,1.2)
0.38399999999999995
julia> plot(P)
julia> scatter!([1.2], [b])
Creating NURBS surface
The following example creates a torus.
using BasicBSpline
using StaticArrays
using Plots
plotly()
p = 2
k = KnotVector([0,0,0,1,1,2,2,3,3,4,4,4])
P = BSplineSpace{p}(k)
R = 3
r = 1
a0 = [
SVector( 1, 0, 0),
SVector( 1, 1, 0),
SVector( 0, 1, 0),
SVector(-1, 1, 0),
SVector(-1, 0, 0),
SVector(-1,-1, 0),
SVector( 0,-1, 0),
SVector( 1,-1, 0),
SVector( 1, 0, 0)
]
a1 = (R+r)*a0
a5 = (R-r)*a0
a2 = [p+r*SVector(0,0,1) for p in a1]
a3 = [p+r*SVector(0,0,1) for p in R*a0]
a4 = [p+r*SVector(0,0,1) for p in a5]
a6 = [p-r*SVector(0,0,1) for p in a5]
a7 = [p-r*SVector(0,0,1) for p in R*a0]
a8 = [p-r*SVector(0,0,1) for p in a1]
a9 = a1
a = hcat(a1,a2,a3,a4,a5,a6,a7,a8,a9)
w = [1,1/√2,1,1/√2,1,1/√2,1,1/√2,1]
M = RationalBSplineManifold(a,w*w',P,P)
plot(M)
A function refinement
can be used to insert knot vectors without changing its shape.
N = refinement(M, (KnotVector([0.5, 0.8]), KnotVector([0.2,3.4])))
plot(N)
Interpolations
Currently, BasicBSpline.jl doesn’t have API for interpolations, but it is not hard to implement some basic interpolation algorithms with this package. (more docs about interpolations)
using BasicBSpline
using Plots
function interpolate(xs::AbstractVector, fs::AbstractVector{T}) where T
# Cubic open B-spline space
p = 3
k = KnotVector(xs) + KnotVector([xs[1],xs[end]]) * p
P = BSplineSpace{p}(k)
# dimensions
m = length(xs)
n = dim(P)
# The interpolant function has a f''=0 property at bounds.
ddP = BSplineDerivativeSpace{2}(P)
dda = [bsplinebasis(ddP,j,xs[1]) for j in 1:n]
ddb = [bsplinebasis(ddP,j,xs[m]) for j in 1:n]
# Compute the interpolant function (1-dim B-spline manifold)
M = [bsplinebasis(P,j,xs[i]) for i in 1:m, j in 1:n]
M = vcat(dda', M, ddb')
y = vcat(zero(T), fs, zero(T))
return BSplineManifold(M\y, P)
end
# Example inputs
xs = [1, 2, 3, 4, 6, 7]
fs = [1.3, 1.5, 2, 2.1, 1.9, 1.3]
f = interpolate(xs,fs)
# Plot
scatter(xs, fs)
plot!(t->f(t))
Comparison to other packages
Of course, there are other packages that provide B-spline functions.
These packages are excellent, but they have different focus and functionality from BasicBSpline.jl.
BasicBSpline.jl was developed with the following motivations.
- Mathematical oriented
- Knot vector operations
- We use
+
for addition of knot vectors because commutative and not just a union of sets. (docs) - e.g.
KnotVector([1,2]) + KnotVector([1,2,3]) == KnotVector([1,1,2,2,3])
- We use
BSplineSpace
type as a linear space- e.g.
P1 = BSplineSpace{2}(KnotVector)
is treated as a linear space. (docs) ⊆(::BSplineSpace, ::BSplineSpace)
can be used to check lhs is a linear subspace of rhs.
- e.g.
- See BasicBSpline.jl#172 for a comment by @empet.
- Knot vector operations
- Focus on basic B-splline functionalities
- B-spline has many applications. We aimed to create a basic package that can be applied to geometric shape representation, interpolation, and more!
- In contrast, BSplineKit.jl provides more functionality such as banded Galerkin and collocation matrices.
- Interpolations.jl also supports B-spline, but it seems no functionality for shape representation.
- Less dependency
- BasicBSpline.jl depends on StaticArrays.jl, so it is hardly lightweight, but we are trying to make it as little dependent as possible. While, on the other hand, BSplineKit.jl depends on more packages.
- High performance
- We are trying to create the fastest B-spline Julia package.
Any feedback is welcome, one of my dreams in Julia is that BasicBSpline.jl will be so basic that it will be depended on by other packages.
Thank you for reading!