### Setup: Load BasicBSpline and plotting packages Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/refinement Loads required packages for the refinement examples: BasicBSpline, BasicBSplineExporter, StaticArrays, and Plots. ```julia using BasicBSpline using BasicBSplineExporter using StaticArrays using Plots ``` -------------------------------- ### Setup dependencies Source: https://hyrodium.github.io/BasicBSpline.jl/stable/interpolations Initial imports required for the interpolation examples. ```julia using BasicBSpline using IntervalSets using Random; Random.seed!(42) using Plots ``` -------------------------------- ### Setup: Import BasicBSpline, Random, and Plots Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinebasis Loads the BasicBSpline package for B-spline functionality, Random for random number generation, and Plots for plotting. Required before using any B-spline functions in the examples. ```julia using BasicBSpline using Random using Plots ``` -------------------------------- ### Setup: import packages Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/fitting Loads the required packages for B-spline fitting and plotting. ```julia using BasicBSpline using BasicBSplineFitting using StaticArrays using Plots ``` -------------------------------- ### Install BasicBSplineExporter Source: https://hyrodium.github.io/BasicBSpline.jl/stable/visualization/basicbsplineexporter Install the BasicBSplineExporter package using Julia's package manager. ```julia ] add BasicBSplineExporter ``` -------------------------------- ### Import required packages for B-spline derivative examples Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/derivative Loads the BasicBSpline, StaticArrays, and Plots packages, which are required for the derivative examples on this page. ```julia using BasicBSpline using StaticArrays using Plots ``` -------------------------------- ### Setup: import BasicBSpline, StaticArrays, LinearAlgebra, Plots Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/rationalbsplinemanifold Loads the required packages for defining and plotting rational B-spline manifolds. ```julia using BasicBSpline using StaticArrays using LinearAlgebra using Plots ``` -------------------------------- ### Load BasicBSpline and Plots Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/knotvector Loads the BasicBSpline and Plots packages, required for the examples on this page. ```julia using BasicBSpline using Plots ``` -------------------------------- ### Setup: using BasicBSpline, StaticArrays, and Plots Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinemanifold Imports the required packages for working with B-splines and plotting. Note that StaticArrays is imported twice in the source. ```julia using BasicBSpline using StaticArrays using StaticArrays using Plots ``` -------------------------------- ### Plot support intervals with bsplinesupport_R Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinebasis Plots the support intervals returned by `bsplinesupport_R`, which is identical to `bsplinesupport`. Uses the same plotting style as the previous example. ```julia pl = plot(; yticks=nothing, legend=nothing, size=(600,150)) for i in 1:dim(P) plot!(pl, bsplinesupport_R(P,i); offset=-i/10, linewidth=3, markersize=5, ylims=(-(dim(P)+1)/10, 1/10)) end plot!(pl, k; color=:black) ``` -------------------------------- ### Construct and evaluate RationalBSplineManifold Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a rational B-spline manifold from control points, weights, and a B-spline space. The example creates a quarter arc and evaluates it at a parameter, showing the norm is 1.0. ```julia julia> using StaticArrays, LinearAlgebra julia> P = BSplineSpace{2}(KnotVector([0,0,0,1,1,1])) BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([0, 0, 0, 1, 1, 1])) julia> w = [1, 1/√2, 1] 3-element Vector{Float64}: 1.0 0.7071067811865475 1.0 julia> a = [SVector(1,0), SVector(1,1), SVector(0,1)] 3-element Vector{SVector{2, Int64}}: [1, 0] [1, 1] [0, 1] julia> M = RationalBSplineManifold(a,w,P); # 1/4 arc julia> M(0.3) 2-element SVector{2, Float64} with indices SOneTo(2): 0.8973756499953727 0.4412674277525845 julia> norm(M(0.3)) 1.0 ``` -------------------------------- ### Construct BSplineDerivativeSpace from BSplineSpace Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a derivative B-spline space from a B-spline space and a differential order. The example shows that the degree of the derivative space is one less than the original space. ```julia julia> P = BSplineSpace{2}(KnotVector([1,2,3,4,5,6])) BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([1, 2, 3, 4, 5, 6])) julia> dP = BSplineDerivativeSpace{1}(P) BSplineDerivativeSpace{1, BSplineSpace{2, Int64, KnotVector{Int64}}, Int64}(BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([1, 2, 3, 4, 5, 6]))) julia> degree(P), degree(dP) (2, 1) ``` -------------------------------- ### Base.:* — Method Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Product of integer and knot vector. For example, 2⋅(1,2,2,5)=(1,1,2,2,2,2,5,5). ```APIDOC ## `Base.:*` — Method ### Description Product of integer and knot vector. For example, 2⋅(1,2,2,5)=(1,1,2,2,2,2,5,5). ### Method `*` ### Parameters - **m** (integer) - Required - Integer multiplier - **k** (KnotVector) - Required - Knot vector ### Examples ```julia julia> k = KnotVector([1,2,2,5]); julia> 2 * k KnotVector([1, 1, 2, 2, 2, 2, 5, 5]) ``` ``` -------------------------------- ### Construct and evaluate BSplineManifold Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a B-spline manifold from control points and a B-spline space. The example evaluates the manifold at a parameter inside the domain and shows that evaluating outside the domain raises a DomainError. ```julia julia> using StaticArrays julia> P = BSplineSpace{2}(KnotVector([0,0,0,1,1,1])) BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([0, 0, 0, 1, 1, 1])) julia> a = [SVector(1,0), SVector(1,1), SVector(0,1)] 3-element Vector{SVector{2, Int64}}: [1, 0] [1, 1] [0, 1] julia> M = BSplineManifold(a, P); julia> M(0.4) 2-element SVector{2, Float64} with indices SOneTo(2): 0.84 0.64 julia> M(1.2) ERROR: DomainError with 1.2: The input 1.2 is out of domain 0 .. 1. [...] ``` -------------------------------- ### Base.:+ — Method Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Sum of knot vectors. For example, (1,2,3,5)+(4,5,8)=(1,2,3,4,5,5,8). ```APIDOC ## `Base.:+` — Method ### Description Sum of knot vectors. For example, (1,2,3,5)+(4,5,8)=(1,2,3,4,5,5,8). ### Method `+` ### Parameters - **k1** (KnotVector) - Required - First knot vector - **k2** (KnotVector) - Required - Second knot vector ### Examples ```julia julia> k1 = KnotVector([1,2,3,5]); julia> k2 = KnotVector([4,5,8]); julia> k1 + k2 KnotVector([1, 2, 3, 4, 5, 5, 8]) ``` ``` -------------------------------- ### Union and inclusion of knot vectors with ∪ and ⊆ Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs knot vectors using the knotvector string macro and demonstrates union (∪) and inclusion (⊆) operations. The example shows the resulting knot vectors and checks that k1 ∪ k2 equals k3, and that both k1 and k2 are subsets of the union. ```julia julia> k1 = knotvector"12 3 1" KnotVector([1, 2, 2, 4, 4, 4, 6]) julia> k2 = knotvector" 1 412" KnotVector([2, 4, 4, 4, 4, 5, 6, 6]) julia> k3 = knotvector"12 412" KnotVector([1, 2, 2, 4, 4, 4, 4, 5, 6, 6]) julia> k1 ∪ k2 == k3 julia> k1 ⊆ k1 ∪ k2 julia> k2 ⊆ k1 ∪ k2 ``` -------------------------------- ### Torus: rational B-spline torus from circle Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/rationalbsplinemanifold Builds a torus as a rational B-spline manifold by combining the circle control points and weights from the previous example. Uses plotly() and plots the resulting 3D surface. ```julia plotly() R1 = 3 R2 = 1 A = push.(a, 0) a1 = (R1+R2)*A a5 = (R1-R2)*A a2 = [p+R2*SVector(0,0,1) for p in a1] a3 = [p+R2*SVector(0,0,1) for p in R1*A] a4 = [p+R2*SVector(0,0,1) for p in a5] a6 = [p-R2*SVector(0,0,1) for p in a5] a7 = [p-R2*SVector(0,0,1) for p in R1*A] a8 = [p-R2*SVector(0,0,1) for p in a1] a = hcat(a1,a2,a3,a4,a5,a6,a7,a8,a1) M = RationalBSplineManifold(a,w*w',P,P) plot(M) ``` -------------------------------- ### Construct BSplineSpace from degree and knot vector Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a B-spline space from a polynomial degree and a knot vector. The example shows the resulting BSplineSpace type. ```julia julia> p = 2 2 julia> k = KnotVector([1,3,5,6,8,9]) KnotVector([1, 3, 5, 6, 8, 9]) julia> BSplineSpace{p}(k) BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([1, 3, 5, 6, 8, 9])) ``` -------------------------------- ### changebasis_R: compute change-of-basis matrix between B-spline spaces Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Computes the change-of-basis matrix from a B-spline space to a refined space using `changebasis_R`. The example defines two spaces with different degrees and knot vectors, checks that the first is a subset of the second, and prints the resulting sparse matrix. ```julia julia> P = BSplineSpace{2}(knotvector"3 13") BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([1, 1, 1, 3, 4, 4, 4])) julia> P′ = BSplineSpace{3}(knotvector"4124") BSplineSpace{3, Int64, KnotVector{Int64}}(KnotVector([1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 4])) julia> P ⊆ P′ true julia> changebasis_R(P, P′) 4×7 SparseArrays.SparseMatrixCSC{Float64, Int32} with 13 stored entries: 1.0 0.666667 0.166667 ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 0.722222 0.555556 0.111111 ⋅ ⋅ ⋅ ⋅ 0.111111 0.444444 0.888889 0.666667 ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 1.0 ``` -------------------------------- ### Create SubKnotVector with view Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Creates a sub knot vector by viewing a range of a knot vector. The example shows the resulting SubKnotVector. ```julia julia> k = knotvector"1 11 211" KnotVector([1, 3, 4, 6, 6, 7, 8]) julia> view(k, 2:5) SubKnotVector([3, 4, 6, 6]) ``` -------------------------------- ### Construct UniformKnotVector from range Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a uniform knot vector from a range. The example shows that a descending range is normalized to ascending order. ```julia julia> k = UniformKnotVector(1:8) UniformKnotVector(1:8) julia> UniformKnotVector(8:-1:3) UniformKnotVector(3:1:8) ``` -------------------------------- ### Check B-spline space inclusion with ⊆ and ⊈ Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Checks inclusive relationship between B-spline spaces using ⊆ and ⊈. The example defines three spaces and performs four comparisons, but the source does not show the resulting boolean values. ```julia julia> P1 = BSplineSpace{1}(KnotVector([1,3,5,8])); julia> P2 = BSplineSpace{1}(KnotVector([1,3,5,6,8,9])); julia> P3 = BSplineSpace{2}(KnotVector([1,1,3,3,5,5,8,8])); julia> P1 ⊆ P2 julia> P1 ⊆ P3 julia> P2 ⊆ P3 julia> P2 ⊈ P3 ``` -------------------------------- ### Evaluate B-spline basis functions with bsplinebasisall Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Compute all B-spline basis functions at a point t on a given interval. The example defines a knot vector, a spline space of degree 2, and evaluates the basis at t=5.7 using both bsplinebasisall and the broadcasted bsplinebasis. The output shows the three basis values. ```julia 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 = 2 2 julia> P = BSplineSpace{p}(k) BSplineSpace{2, Float64, KnotVector{Float64}}(KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])) julia> t = 5.7 5.7 julia> i = intervalindex(P,t) julia> bsplinebasisall(P,i,t) 3-element SVector{3, Float64} with indices SOneTo(3): 0.3847272727272727 0.6107012987012989 0.00457142857142858 julia> bsplinebasis.(P,i:i+p,t) 3-element Vector{Float64}: 0.38472727272727264 0.6107012987012989 0.00457142857142858 ``` -------------------------------- ### Evaluate right-sided B-spline basis with bsplinebasis₊₀ Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Evaluate the right-sided limit of B-spline basis functions for a degree-0 spline space. The example creates a space with knots 1:6 and computes the basis for indices 1:5 and parameter values 1:6, producing a 5x6 identity-like matrix. ```julia julia> P = BSplineSpace{0}(KnotVector(1:6)) BSplineSpace{0, Int64, KnotVector{Int64}}(KnotVector([1, 2, 3, 4, 5, 6])) julia> bsplinebasis₊₀.(P,1:5,(1:6)') 5×6 Matrix{Float64}: 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 ``` -------------------------------- ### derivative: compute derivative space of a B-spline space Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Applies `derivative` to a B-spline space to obtain its derivative space. The example shows that `derivative` on a `BSplineSpace{2}` returns a `BSplineDerivativeSpace{1}` (and also a second-order derivative space). ```julia julia> BSplineSpace{2}(KnotVector(0:5)) BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([0, 1, 2, 3, 4, 5])) julia> BasicBSpline.derivative(ans) BSplineDerivativeSpace{1, BSplineSpace{2, Int64, KnotVector{Int64}}, Int64}(BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([0, 1, 2, 3, 4, 5]))) BSplineDerivativeSpace{2, BSplineSpace{2, Int64, KnotVector{Int64}}, Int64}(BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([0, 1, 2, 3, 4, 5]))) ``` -------------------------------- ### Compare bsplinesupport, bsplinesupport_R, and bsplinesupport_I outputs Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinebasis Shows the output of `bsplinesupport`, `bsplinesupport_R`, and `bsplinesupport_I` for indices 1 and 3. Note that `bsplinesupport_I` returns a different interval for index 1, while all three agree for index 3. ```julia julia> bsplinesupport(P,1), bsplinesupport_R(P,1), bsplinesupport_I(P,1)(0.0 .. 5.5, 0.0 .. 5.5, 2.5 .. 5.5) julia> bsplinesupport(P,3), bsplinesupport_R(P,3), bsplinesupport_I(P,3)(2.5 .. 9.0, 2.5 .. 9.0, 2.5 .. 9.0) ``` -------------------------------- ### Get knot vector length Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/knotvector Returns the number of knots in each knot vector using length. ```julia julia> length(k1) 12 julia> length(k2) 18 ``` -------------------------------- ### Construct KnotVector from array or range Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a knot vector from an array or a range. The example shows both forms produce the same KnotVector. ```julia julia> k = KnotVector([1,2,3]) KnotVector([1, 2, 3]) julia> k = KnotVector(1:3) KnotVector([1, 2, 3]) ``` -------------------------------- ### Get unique elements of knot vector Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/knotvector Returns a knot vector containing only the unique elements of the original knot vector. ```julia julia> unique(k1) KnotVector([1, 3, 5, 7, 8, 10, 12, 13]) julia> unique(k2) KnotVector([1, 2, 3, 5, 7, 8, 10, 12, 13, 15, 18]) ``` -------------------------------- ### Compute bsplinesupport_R for basis functions Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Computes the support of the 1st and 2nd basis functions on the right side using bsplinesupport_R. The outputs are not shown in the source. ```julia julia> bsplinesupport_R(P,1) julia> bsplinesupport_R(P,2) ``` -------------------------------- ### Visualize tensor product basis function with BasicBSpline Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinemanifold Defines knot vectors and B-spline spaces, then plots the basis functions and the tensor product surface. Uses plotly backend and the bsplinebasis function. ```julia # Define shape k1 = KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0]) k2 = knotvector"31 2 121" P1 = BSplineSpace{3}(k1) P2 = BSplineSpace{2}(k2) # Choose indices i1 = 3 i2 = 4 # Visualize basis functions plotly() plot(P1; plane=:xz, label="P1", color=:red) plot!(P2; plane=:yz, label="P2", color=:green) plot!(k1; plane=:xz, label="k1", color=:red, markersize=2) plot!(k2; plane=:yz, label="k2", color=:green, markersize=2) xs = range(0,10,length=100) ys = range(1,9,length=100) surface!(xs, ys, bsplinebasis.(P1,i1,xs') .* bsplinebasis.(P2,i2,ys)) ``` -------------------------------- ### BasicBSpline.BSplineSpace — Method Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Convert BSplineSpace to BSplineSpace ```APIDOC ## `BasicBSpline.BSplineSpace` — Method ### Description Convert BSplineSpace to BSplineSpace ### Method `BSplineSpace` ### Parameters None explicitly documented. ### Examples No examples provided in source. ``` -------------------------------- ### Compute bsplinesupport_I for basis functions Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Computes the support of the 1st and 2nd basis functions restricted to the interval I using bsplinesupport_I. The output for the first call is truncated in the source. ```julia julia> bsplinesupport_I(P,1) 2.5 .. julia> bsplinesupport_I(P,2) ``` -------------------------------- ### Create EmptyKnotVector Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Creates an empty knot vector, which is intended for internal use. The example shows the default element type is Bool and that a type parameter can be specified. ```julia julia> EmptyKnotVector() EmptyKnotVector{Bool}() julia> EmptyKnotVector{Float64}() EmptyKnotVector{Float64}() ``` -------------------------------- ### Construct and evaluate a BSplineManifold Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinemanifold Creates a 2D B-spline manifold with quadratic basis and three control points, then evaluates it at t=0.4. The output is a 2-element SVector. ```julia P = BSplineSpace{2}(KnotVector([0,0,0,1,1,1])) a = [SVector(1,0), SVector(1,1), SVector(0,1)] # `length(a) == dim(P)` M = BSplineManifold(a, P) M(0.4) # Calculate `sum(a[i]*bsplinebasis(P, i, 0.4) for i in 1:dim(P))` ``` ```julia 2-element StaticArraysCore.SVector{2, Float64} with indices SOneTo(2): 0.84 0.64 ``` -------------------------------- ### Compute bsplinesupport for BSplineSpace{2} Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Creates a degree-2 B-spline space with a given knot vector and computes the support of the 1st and 2nd basis functions using bsplinesupport, returning intervals 0.0..5.5 and 1.5..8.0. ```julia 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) BSplineSpace{2, Float64, KnotVector{Float64}}(KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])) julia> bsplinesupport(P,1) 0.0 .. 5.5 julia> bsplinesupport(P,2) 1.5 .. 8.0 ``` -------------------------------- ### Hyperbolic paraboloid B-spline surface Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinemanifold Defines a hyperbolic paraboloid B-spline surface using plotly backend, reusing the knot vector and space from the previous paraboloid example. Plots the manifold. ```julia plotly() a = [SVector(i,j,2i^2-2j^2) for i in -1:1, j in -1:1] M = BSplineManifold(a,P,P) plot(M) ``` -------------------------------- ### BasicBSpline.changebasis_I Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Returns the coefficient matrix A that satisfies B_{(i,p,k)} = Σ_j A_{i,j} B_{(j,p',k')} for the change of basis between two B-spline spaces. ```APIDOC ## BasicBSpline.changebasis_I — Method ### Description Returns the coefficient matrix A that satisfies B_{(i,p,k)} = Σ_j A_{i,j} B_{(j,p',k')} for the change of basis between two B-spline spaces. ### Method Method ### Endpoint `BasicBSpline.changebasis_I` ### Parameters #### Arguments - **P** (AbstractFunctionSpace) - Required - Original function space - **P′** (AbstractFunctionSpace) - Required - Target function space ### Request Example ```julia julia> P = BSplineSpace{2}(knotvector"3 13") BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([1, 1, 1, 3, 4, 4, 4])) julia> P′ = BSplineSpace{3}(knotvector"4124") BSplineSpace{3, Int64, KnotVector{Int64}}(KnotVector([1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 4])) julia> P ⊑ P′ true julia> changebasis_I(P, P′) 4×7 SparseArrays.SparseMatrixCSC{Float64, Int32} with 13 stored entries: 1.0 0.666667 0.166667 ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 0.722222 0.555556 0.111111 ⋅ ⋅ ⋅ ⋅ 0.111111 0.444444 0.888889 0.666667 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 1.0 ``` ### Response #### Success Response Returns the coefficient matrix A. #### Response Example ```julia 4×7 SparseArrays.SparseMatrixCSC{Float64, Int32} with 13 stored entries: 1.0 0.666667 0.166667 ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 0.722222 0.555556 0.111111 ⋅ ⋅ ⋅ ⋅ 0.111111 0.444444 0.888889 0.666667 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 1.0 ``` ``` -------------------------------- ### Compute changebasis_I between BSplineSpaces Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Defines two B-spline spaces P and P′ with different degrees and knot vectors, checks that P is a subspace of P′ using ⊑, and computes the change-of-basis matrix with changebasis_I, returning a 4×7 sparse matrix. ```julia julia> P = BSplineSpace{2}(knotvector"3 13") BSplineSpace{2, Int64, KnotVector{Int64}}(KnotVector([1, 1, 1, 3, 4, 4, 4])) julia> P′ = BSplineSpace{3}(knotvector"4124") BSplineSpace{3, Int64, KnotVector{Int64}}(KnotVector([1, 1, 1, 1, 2, 3, 3, 4, 4, 4, 4])) julia> P ⊑ P′ true julia> changebasis_I(P, P′) 4×7 SparseArrays.SparseMatrixCSC{Float64, Int32} with 13 stored entries: 1.0 0.666667 0.166667 ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 0.722222 0.555556 0.111111 ⋅ ⋅ ⋅ ⋅ 0.111111 0.444444 0.888889 0.666667 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 0.333333 1.0 ``` -------------------------------- ### countknots(k): count multiplicities of all unique knots Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Counts the multiplicities of all unique knot values in a knot vector using `countknots(k)`. The example shows that `knotvector(values, counts)` reconstructs the original knot vector. ```julia julia> k = knotvector"21 3" KnotVector([1, 1, 2, 4, 4, 4]) julia> values = collect(unique(k)) 3-element Vector{Int64}: 4 julia> counts = countknots(k) 3 julia> knotvector(values, counts) # Equal to `k` ``` -------------------------------- ### Evaluate bsplinebasis₋₀I on BSplineSpace{0} Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Constructs a degree-0 B-spline space with knot vector 1:6 and evaluates the modified basis function bsplinebasis₋₀I on a grid, producing a 5×6 matrix of Float64 values. ```julia julia> P = BSplineSpace{0}(KnotVector(1:6)) BSplineSpace{0, Int64, KnotVector{Int64}}(KnotVector([1, 2, 3, 4, 5, 6])) julia> BasicBSpline.bsplinebasis₋₀I.(P,1:5,(1:6)') 5×6 Matrix{Float64}: 1.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 ``` -------------------------------- ### 3D Helix plot Source: https://hyrodium.github.io/BasicBSpline.jl/stable/visualization/plotlyjs Plot a 3D helix curve using PlotlyJS. The example fits a parametric helix function f(t), creates a BSplineSpace and BSplineManifold, and plots the control points and fitted curve in 3D using scatter3d and line traces. ```Julia using BasicBSpline using BasicBSplineFitting using StaticArrays using PlotlyJS f(t) = SVector(cos(t),sin(t),t) = 3 k = KnotVector(range(0,6π,15)) + p * KnotVector([0,6π]) T = BSplineSpace{p}(k) a = fittingcontrolpoints(f, P) M = BSplineManifold(a, P) ts = range(0,6π,250) xs_a = findall.(a,1) ys_a = findall.(a,2) zs_a = findall.(a,3) xs_f = findall.(M.(ts),1) ys_f = findall.(M.(ts),2) zs_f = findall.(M.(ts),3) fig = Plot(scatter3d(x=xs_a, y=ys_a, z=zs_a, name="control points", marker_size=8)) addtraces!(fig, scatter3d(x=xs_f, y=ys_f, z=zs_f, name="B-spline curve", mode="lines", line_color="red")) relayout!(fig, width=500, height=500) ``` -------------------------------- ### Interpolation with cubic B-spline Source: https://hyrodium.github.io/BasicBSpline.jl/stable/interpolations Implementation of cubic open B-spline interpolation with f''=0 boundary conditions. ```julia 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 plotly() scatter(xs, fs) plot!(t->f(t)) ``` -------------------------------- ### Compare M(t) and unbounded_mapping(M, t) with domain check Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinemanifold Shows that M(0.4) and unbounded_mapping(M, 0.4) give the same result, but M(1.2) throws a DomainError while unbounded_mapping(M, 1.2) returns a value without checking the domain. ```julia julia> M(0.4)2-element StaticArraysCore.SVector{2, Float64} with indices SOneTo(2): 0.84 0.64 julia> unbounded_mapping(M, 0.4)2-element StaticArraysCore.SVector{2, Float64} with indices SOneTo(2): 0.84 0.64 julia> M(1.2)ERROR: DomainError with 1.2: The input 1.2 is out of domain 0 .. 1. julia> unbounded_mapping(M, 1.2)2-element StaticArraysCore.SVector{2, Float64} with indices SOneTo(2): -0.4399999999999999 0.9600000000000001 ``` -------------------------------- ### BasicBSpline.bsplinesupport Source: https://hyrodium.github.io/BasicBSpline.jl/stable/api Returns the support of the i-th B-spline basis function, which is the interval [k_i, k_{i+p+1}]. The function takes a B-spline space and an index and returns the support interval. ```APIDOC ## BasicBSpline.bsplinesupport — Function ### Description Returns the support of the i-th B-spline basis function, which is the interval [k_i, k_{i+p+1}]. ### Method Function ### Endpoint `BasicBSpline.bsplinesupport` ### Parameters #### Arguments - **P** (BSplineSpace) - Required - B-spline space - **i** (Int) - Required - Basis function index ### Request Example ```julia 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) BSplineSpace{2, Float64, KnotVector{Float64}}(KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])) julia> bsplinesupport(P,1) 0.0 .. 5.5 julia> bsplinesupport(P,2) 1.5 .. 8.0 ``` ### Response #### Success Response Returns the support interval as a range. #### Response Example ```julia 0.0 .. 5.5 ``` ``` -------------------------------- ### 2D Cardioid plot Source: https://hyrodium.github.io/BasicBSpline.jl/stable/visualization/plotlyjs Plot a 2D cardioid B-spline curve using PlotlyJS. The example fits control points a to a parametric function f(t), creates BSplineSpace and BSplineManifold, and plots control points and the B-spline curve on a cardioid shape. The figure width and height are set to 500. ```Julia using BasicBSpline using BasicBSplineFitting using StaticArrays using PlotlyJS f(t) = SVector((1+cos(t))*cos(t),(1+cos(t))*sin(t)) p = 3 k = KnotVector(range(0,2π,15)) + p * KnotVector([0,2π]) + 2 * KnotVector([π]) P = BSplineSpace{p}(k) a = fittingcontrolpoints(f, P) M = BSplineManifold(a, P) ts = range(0,2π,250) xs_a = findall.(a,1) ys_a = findall.(a,2) xs_f = findall.(M.(ts),1) ys_f = findall.(M.(ts),2) fig = Plot(scatter(x=xs_a, y=ys_a, name="control points", line_color="blue", marker_size=8)) addtraces!(fig, scatter(x=xs_f, y=ys_f, name="B-spline curve", mode="lines", line_color="red")) relayout!(fig, width=500, height=500) ``` -------------------------------- ### Fix arguments of BSplineManifold (currying) and plot Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinemanifold Creates a B-spline surface and demonstrates fixing arguments via partial application. The first block constructs the manifold and checks that fixing the first argument yields a BSplineManifold{1}. The second block plots the surface and the fixed-argument curves with different colors and line widths. ```julia julia> p = 2; julia> k = KnotVector(1:8); julia> P = BSplineSpace{p}(k); julia> a = [SVector(5i+5j+rand(), 5i-5j+rand(), rand()) for i in 1:dim(P), j in 1:dim(P)]; julia> M = BSplineManifold(a,(P,P)); julia> M isa BSplineManifold{2}true julia> M(:,:) isa BSplineManifold{2}true julia> M(4.3,:) isa BSplineManifold{1} # Fix first argumenttrue ``` ```julia plot(M) plot!(M(4.3,:), linewidth = 5, color=:cyan) plot!(M(4.4,:), linewidth = 5, color=:red) plot!(M(:,5.2), linewidth = 5, color=:green) ``` -------------------------------- ### Plot support intervals with bsplinesupport_I Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/bsplinebasis Plots the support intervals returned by `bsplinesupport_I`, which differs from `bsplinesupport` by intersecting with the interior of the knot vector. The interval is [k_i, k_{i+p}] ∩ [k_{1+p}, k_{l-p}]. ```julia pl = plot(; yticks=nothing, legend=nothing, size=(600,150)) for i in 1:dim(P) plot!(pl, bsplinesupport_I(P,i); offset=-i/10, linewidth=3, markersize=5, ylims=(-(dim(P)+1)/10, 1/10)) end plot!(pl, k; color=:black) ``` -------------------------------- ### Evaluate B-spline basis function with bsplinebasis₊₀ Source: https://hyrodium.github.io/BasicBSpline.jl/stable Shows how to create a B-spline space with a knot vector and evaluate a basis function using `bsplinebasis₊₀`. The output displays the space object and the computed value. ```julia using BasicBSpline julia> P3 = BSplineSpace{3}(KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])) BSplineSpace{3, Float64, KnotVector{Float64}}(KnotVector([0.0, 1.5, 2.5, 5.5, 8.0, 9.0, 9.5, 10.0])) julia> bsplinebasis₊₀(P3, 2, 7.5) 0.13786213786213783 ``` -------------------------------- ### Export 2D B-spline manifold to PNG Source: https://hyrodium.github.io/BasicBSpline.jl/stable/visualization/basicbsplineexporter Create a 2D B-spline manifold with random control points and export it as a PNG image using save_png. ```julia using BasicBSpline using BasicBSplineExporter using StaticArrays p = 2 # degree of polynomial k1 = KnotVector(1:8) # knot vector k2 = KnotVector(rand(7))+(p+1)*KnotVector([1]) P1 = BSplineSpace{p}(k1) # B-spline space P2 = BSplineSpace{p}(k2) n1 = dim(P1) # dimension of B-spline space n2 = dim(P2) a = [SVector(2i-6.5+rand(),1.5j-6.5+rand()) for i in 1:dim(P1), j in 1:dim(P2)] # random generated control points M = BSplineManifold(a,(P1,P2)) # Define B-spline manifold save_png("BasicBSplineExporter_2dim.png", M) # save image ``` -------------------------------- ### Check inclusive relationships with ⊆ Source: https://hyrodium.github.io/BasicBSpline.jl/stable/math/inclusive Shows the results of subset checks between the spaces P1, P2, and P3 using the ⊆ operator. ```julia julia> P1 ⊆ P2true julia> P1 ⊆ P3true julia> P2 ⊆ P3, P3 ⊆ P2, P2 ⊆ P1, P3 ⊆ P1(false, false, false, false) ```