# BasicBSpline.jl - Basic mathematical operations for B-spline

**URL:** <https://discourse.julialang.org/t/basicbspline-jl-basic-mathematical-operations-for-b-spline/96323>\
**Category:** Package Announcements\
**Tags:** splines\
**Created:** [March 20, 2023, 12:56am UTC](https://discourse.julialang.org/t/basicbspline-jl-basic-mathematical-operations-for-b-spline/96323 "2023-03-20T00:56:11Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![hyrodium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hyrodium/32/27015_2.png) [@hyrodium](https://discourse.julialang.org/u/hyrodium)\
**Post date:** [March 20, 2023, 12:56am UTC](https://discourse.julialang.org/t/basicbspline-jl-basic-mathematical-operations-for-b-spline/96323/1 "2023-03-20T00:56:11Z")

</div>

Hi all,  
I’m pleased to announce my package BasicBSpline.jl v0.9.4 ([repo](https://github.com/hyrodium/BasicBSpline.jl), [docs](https://hyrodium.github.io/BasicBSpline.jl/dev/)).

# Introduction

This package provides basic mathematical operations for [B-spline](https://en.wikipedia.org/wiki/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](https://hyrodium.github.io/BasicBSpline.jl/dev/interpolations/))
- Fitting control points for a given function (in [BasicBSplineFitting.jl](https://github.com/hyrodium/BasicBSplineFitting.jl))
- Export graphics (in [BasicBSplineExporter.jl](https://github.com/hyrodium/BasicBSplineExporter.jl))

# Basic usage

## Evaluating B-spline function

```julia
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])

```

 ![bsb](https://global.discourse-cdn.com/julialang/original/3X/a/1/a16dde3f7f610f624b8149dfb1a711686d80f963.png)

## Creating NURBS surface

The following example creates a torus.

```julia
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)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/7/b/7bfa0c29b6811e52c799294f8cf72914580d2b87.png)

A function `refinement` can be used to insert knot vectors without changing its shape.

```julia
N = refinement(M, (KnotVector([0.5, 0.8]), KnotVector([0.2,3.4])))
plot(N)

```

 ![image](https://global.discourse-cdn.com/julialang/original/3X/4/d/4dd948edbd279aa4da7a119f3996add07dc2da00.png)

## 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](https://hyrodium.github.io/BasicBSpline.jl/dev/interpolations/))

```julia
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))

```

 ![int](https://global.discourse-cdn.com/julialang/original/3X/3/6/36cdef92c3f705cb98d1c0e987167ca3900e8200.png)

# Comparison to other packages

Of course, there are other packages that provide B-spline functions.

- [BSplines.jl](https://github.com/sostock/BSplines.jl)
- [BSplineKit.jl](https://github.com/jipolanco/BSplineKit.jl)
- [NURBS.jl](https://github.com/HoBeZwe/NURBS.jl)
- [Interpolations.jl](https://github.com/JuliaMath/Interpolations.jl)

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](https://hyrodium.github.io/BasicBSpline.jl/dev/math-knotvector/))
    - e.g. `KnotVector([1,2]) + KnotVector([1,2,3]) == KnotVector([1,1,2,2,3])`

  - `BSplineSpace` type as a linear space
    - e.g. `P1 = BSplineSpace{2}(KnotVector)` is treated as a linear space. ([docs](https://hyrodium.github.io/BasicBSpline.jl/dev/math-bsplinespace/))
    - `⊆(::BSplineSpace, ::BSplineSpace)` can be used to check lhs is a linear subspace of rhs.

  - See [BasicBSpline.jl#172](https://github.com/hyrodium/BasicBSpline.jl/issues/172) for a comment by @empet.

- 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](https://github.com/jipolanco/BSplineKit.jl) provides more functionality such as banded Galerkin and collocation matrices.
  - [Interpolations.jl](https://github.com/JuliaMath/Interpolations.jl) also supports B-spline, but it seems no functionality for shape representation.

- Less dependency
  - [BasicBSpline.jl depends on StaticArrays.jl](https://github.com/hyrodium/BasicBSpline.jl/blob/main/Project.toml), 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](https://github.com/jipolanco/BSplineKit.jl/blob/master/Project.toml).

- 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!
