Repository: hyrodium/BasicBSpline.jl
Pull request #162 (2022-02-09 14:33:03)

Breaking changes and update version to `v0.5.0`
* Remove old `@deprecate_binding`s
* Remove old `BSplineManifold`
* Rename `CustomBSplinefold` to `BSplineManifold`
  * This may be confusing, but I've already added warnings for the old `BSplineManifold` in `v0.4.2`, so it seems okay.
  * I've also added `@deprecate_binding` for this.
* Bump version to `v0.5.0`.


Patch:
diff --git a/Project.toml b/Project.toml
index 62814785..4891847a 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "BasicBSpline"
 uuid = "4c5d9882-2acf-4ea4-9e48-968fd4518195"
 authors = ["hyrodium <hyrodium@gmail.com>"]
-version = "0.4.2"
+version = "0.5.0"
 
 [deps]
 FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
diff --git a/README.md b/README.md
index 040c115b..c20dbaac 100644
--- a/README.md
+++ b/README.md
@@ -85,7 +85,7 @@ 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 = CustomBSplineManifold(a,(P1,P2)) # Define B-spline manifold
+M = BSplineManifold(a,(P1,P2)) # Define B-spline manifold
 save_png("2dim.png", M) # save image
 ```
 ![](docs/src/img/2dim.png)
@@ -124,7 +124,7 @@ P2 = BSplineSpace{p2}(k2)
 f(u1, u2) = SVector(2u1 + sin(u1) + cos(u2) + u2 / 2, 3u2 + sin(u2) + sin(u1) / 2 + u1^2 / 6) / 5
 
 a = fittingcontrolpoints(f, (P1, P2))
-M = CustomBSplineManifold(a, (P1, P2))
+M = BSplineManifold(a, (P1, P2))
 save_png("fitting.png", M, unitlength=50, xlims=(-10,10), ylims=(-10,10))
 ```
 ![](docs/src/img/fitting_desmos.png)
@@ -142,7 +142,7 @@ P2 = BSplineSpace{p2}(k2)
 f(u1, u2) = SVector(2u1 + sin(u1) + cos(u2) + u2 / 2, 3u2 + sin(u2) + sin(u1) / 2 + u1^2 / 6) / 5
 
 a = fittingcontrolpoints(f, (P1, P2))
-M = CustomBSplineManifold(a, (P1, P2))
+M = BSplineManifold(a, (P1, P2))
 save_png("fitting_coarse.png", M, unitlength=50, xlims=(-10,10), ylims=(-10,10))
 ```
 ![](docs/src/img/fitting_coarse.png)
@@ -156,7 +156,7 @@ P = BSplineSpace{p}(k)
 f(u) = SVector(u,sin(u))
 
 a = fittingcontrolpoints(f, (P,))
-M = CustomBSplineManifold(a, (P,))
+M = BSplineManifold(a, (P,))
 save_svg("sine-curve.svg", M, unitlength=50, xlims=(-2,2), ylims=(-8,8))
 save_svg("sine-curve_no-points.svg", M, unitlength=50, xlims=(-2,2), ylims=(-8,8), points=false)
 ```
diff --git a/docs/src/basicbsplineexporter.md b/docs/src/basicbsplineexporter.md
index cbc74f5b..6b5e333a 100644
--- a/docs/src/basicbsplineexporter.md
+++ b/docs/src/basicbsplineexporter.md
@@ -1,6 +1,6 @@
 # BasicBSplineExporter.jl
 
-[BasicBSplineExporter.jl](https://github.com/hyrodium/BasicBSplineExporter.jl) supports export `BasicBSpline.BSplineManifold` and `BasicBSpline.CustomBSplineManifold{Dim,Deg,<:StaticVector}` to:
+[BasicBSplineExporter.jl](https://github.com/hyrodium/BasicBSplineExporter.jl) supports export `BasicBSpline.BSplineManifold{Dim,Deg,<:StaticVector}` to:
 * PNG image (`.png`)
 * SVG image (`.png`)
 * POV-Ray mesh (`.inc`)
@@ -24,7 +24,7 @@ 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 = CustomBSplineManifold(a,(P1,P2)) # Define B-spline manifold
+M = BSplineManifold(a,(P1,P2)) # Define B-spline manifold
 save_png("2dim.png", M) # save image
 ```
 
diff --git a/docs/src/math.md b/docs/src/math.md
index 6a00072d..1b9dd87f 100644
--- a/docs/src/math.md
+++ b/docs/src/math.md
@@ -400,7 +400,7 @@ P2 = BSplineSpace{1}(KnotVector([1,1,2,3,3]))
 n1 = dim(P1) # 2
 n2 = dim(P2) # 3
 a = [SVector(i, j) for i in 1:n1, j in 1:n2]  # n1 × n2 array of d̂ array.
-M = CustomBSplineManifold(a, (P1, P2))
+M = BSplineManifold(a, (P1, P2))
 ```
 
 
@@ -411,7 +411,7 @@ p = 2 # degree of polynomial
 k = KnotVector(1:12) # knot vector
 P = BSplineSpace{p}(k) # B-spline space
 a = [SVector(i-5, 3*sin(i^2)) for i in 1:dim(P)] # control points
-M = CustomBSplineManifold(a, (P,)) # Define B-spline manifold
+M = BSplineManifold(a, (P,)) # Define B-spline manifold
 save_png("1dim.png", M, unitlength = 50)
 ```
 ![](img/1dim.png)
@@ -424,7 +424,7 @@ k = KnotVector(1:8) # knot vector
 P = BSplineSpace{p}(k) # B-spline space
 rand_a = [SVector(rand(), rand()) for i in 1:dim(P), j in 1:dim(P)]
 a = [SVector(2*i-6.5, 2*j-6.5) for i in 1:dim(P), j in 1:dim(P)] + rand_a # random generated control points
-M = CustomBSplineManifold(a,(P,P)) # Define B-spline manifold
+M = BSplineManifold(a,(P,P)) # Define B-spline manifold
 save_png("2dim.png", M) # save image
 ```
 ![](img/2dim.png)
@@ -480,7 +480,7 @@ P2 = BSplineSpace{p2}(k2)
 f(u1, u2) = SVector(2u1 + sin(u1) + cos(u2) + u2 / 2, 3u2 + sin(u2) + sin(u1) / 2 + u1^2 / 6) / 5
 
 a = fittingcontrolpoints(f, (P1, P2))
-M = CustomBSplineManifold(a, (P1, P2))
+M = BSplineManifold(a, (P1, P2))
 save_png("fitting.png", M, unitlength=50, xlims=(-10,10), ylims=(-10,10))
 ```
 ![](img/fitting_desmos.png)
diff --git a/src/BasicBSpline.jl b/src/BasicBSpline.jl
index a6ae5724..c70e6136 100644
--- a/src/BasicBSpline.jl
+++ b/src/BasicBSpline.jl
@@ -9,7 +9,7 @@ export AbstractKnotVector, KnotVector, UniformKnotVector
 export BSplineSpace, UniformBSplineSpace
 export dim, ⊑, ⊒, ⋢, ⋣, ≃
 export BSplineDerivativeSpace
-export BSplineManifold, CustomBSplineManifold
+export BSplineManifold
 export bsplinebasis₊₀, bsplinebasis₋₀, bsplinebasis
 export bsplinebasis′₊₀, bsplinebasis′₋₀, bsplinebasis′
 export bsplinesupport, domain, changebasis, expandspace
@@ -32,7 +32,6 @@ include("_DerivativeSpace.jl")
 include("_DerivativeBasis.jl")
 include("_ChangeBasis.jl")
 include("_BSplineManifold.jl")
-include("_CustomBSplineManifold.jl")
 include("_Refinement.jl")
 include("_Fitting.jl")
 
diff --git a/src/_BSplineManifold.jl b/src/_BSplineManifold.jl
index ff318d84..7295ff8b 100644
--- a/src/_BSplineManifold.jl
+++ b/src/_BSplineManifold.jl
@@ -4,43 +4,39 @@ abstract type AbstractBSplineManifold{Dim, Deg} end
 
 dim(::AbstractBSplineManifold{Dim}) where Dim = Dim
 
-# struct BSplineManifold{Dim,Deg,T,S<:Tuple,Dim₊₁} <: AbstractBSplineManifold{Dim,Deg,T}
-struct BSplineManifold{Dim,Deg,T,S<:Tuple,Dim₊₁} <: AbstractBSplineManifold{Dim,Deg}
+struct BSplineManifold{Dim,Deg,C,S<:Tuple} <: AbstractBSplineManifold{Dim,Deg}
     bsplinespaces::S
-    controlpoints::Array{T,Dim₊₁}
-    function BSplineManifold(a::Array{T,Dim₊₁},Ps::S) where {S<:Tuple,Dim₊₁,T<:Real}
-        @warn "BSplineManifold may be removed in the future release. Please use CustomBSplineManifold instead."
+    controlpoints::Array{C,Dim}
+    function BSplineManifold(a::Array{C,Dim},Ps::S) where {S<:Tuple,C,Dim}
         for P in Ps
             if !(P isa AbstractBSplineSpace)
-                throw(TypeError(:CustomBSplineManifold,AbstractBSplineSpace,P))
+                throw(TypeError(:BSplineManifold,AbstractBSplineSpace,P))
             end
         end
-        if size(a)[1:Dim₊₁-1] != dim.(Ps)
-            msg = "The size of control points array $(size(a)[1:Dim₊₁-1]) and dimensions of B-spline spaces $(dim.(Ps)) must be equal."
+        if size(a) != dim.(Ps)
+            msg = "The size of control points array $(size(a)) and dimensions of B-spline spaces $(dim.(Ps)) must be equal."
             throw(DimensionMismatch(msg))
         end
-        Dim = length(Ps)
         Deg = degree.(Ps)
-        new{Dim,Deg,T,S,Dim+1}(Ps,a)
+        new{Dim,Deg,C,S}(Ps,a)
     end
 end
 
 bsplinespaces(M::BSplineManifold) = M.bsplinespaces
 controlpoints(M::BSplineManifold) = M.controlpoints
 
-@generated function unsafe_mapping(M::BSplineManifold{1,Deg,S,T},t1) where {Deg,S,T}
+@generated function unsafe_mapping(M::BSplineManifold{1,Deg,S,T},t1::Real) where {Deg,S,T}
     p1, = Deg
     exs = Expr[]
     for j1 in 1:p1
-        push!(exs, :(v .+= b1[$(1+j1)]*view(a,i1+$(j1),:)))
+        push!(exs, :(v += b1[$(1+j1)]*getindex(a,i1+$(j1))))
     end
-    Expr(
-        :block,
+    Expr(:block,
         :((P1,) = bsplinespaces(M)),
         :(a = controlpoints(M)),
         :(i1 = intervalindex(P1,t1)),
         :(b1 = bsplinebasisall(P1,i1,t1)),
-        :(v = b1[1]*view(a,i1,:)),
+        :(v = b1[1]*getindex(a,i1)),
         exs...,
         :(return v)
     )
@@ -50,7 +46,7 @@ end
     p1, p2 = Deg
     exs = Expr[]
     for j2 in 1:p2+1, j1 in 1:p1+1
-        push!(exs, :(v .+= b1[$(j1)]*b2[$(j2)]*view(a,i1+$(j1-1),i2+$(j2-1),:)))
+        push!(exs, :(v += b1[$(j1)]*b2[$(j2)]*getindex(a,i1+$(j1-1),i2+$(j2-1))))
     end
     deleteat!(exs,1)
     Expr(
@@ -59,7 +55,7 @@ end
         :(a = controlpoints(M)),
         :((i1, i2) = (intervalindex(P1,t1), intervalindex(P2,t2))),
         :((b1, b2) = (bsplinebasisall(P1,i1,t1), bsplinebasisall(P2,i2,t2))),
-        :(v = b1[1]*b2[1]*view(a,i1,i2,:)),
+        :(v = b1[1]*b2[1]*getindex(a,i1,i2)),
         exs...,
         :(return v)
     )
@@ -69,7 +65,7 @@ end
     p1, p2, p3 = Deg
     exs = Expr[]
     for j3 in 1:p3+1, j2 in 1:p2+1, j1 in 1:p1+1
-        push!(exs, :(v .+= b1[$(j1)]*b2[$(j2)]*b3[$(j3)]*view(a,i1+$(j1-1),i2+$(j2-1),i3+$(j3-1),:)))
+        push!(exs, :(v += b1[$(j1)]*b2[$(j2)]*b3[$(j3)]*getindex(a,i1+$(j1-1),i2+$(j2-1),i3+$(j3-1))))
     end
     deleteat!(exs,1)
     Expr(
@@ -78,7 +74,7 @@ end
         :(a = controlpoints(M)),
         :((i1, i2, i3) = (intervalindex(P1,t1), intervalindex(P2,t2), intervalindex(P3,t3))),
         :((b1, b2, b3) = (bsplinebasisall(P1,i1,t1), bsplinebasisall(P2,i2,t2), bsplinebasisall(P3,i3,t3))),
-        :(v = b1[1]*b2[1]*b3[1]*view(a,i1,i2,i3,:)),
+        :(v = b1[1]*b2[1]*b3[1]*getindex(a,i1,i2,i3)),
         exs...,
         :(return v)
     )
@@ -106,3 +102,4 @@ end
 end
 
 # TODO add mappings higher dimensionnal B-spline manifold with @generated macro
+Base.@deprecate_binding CustomBSplineManifold BSplineManifold true
diff --git a/src/_BSplineSpace.jl b/src/_BSplineSpace.jl
index 8336a866..1ee5b335 100644
--- a/src/_BSplineSpace.jl
+++ b/src/_BSplineSpace.jl
@@ -117,7 +117,6 @@ isnondegenerate(P::AbstractBSplineSpace, i::Int) = !isdegenerate(P, i)
 function _iszeros(P::AbstractBSplineSpace{p}) where p
     return [isdegenerate(P,i) for i in 1:dim(P)]
 end
-Base.@deprecate_binding iszeros _iszeros true
 
 @doc raw"""
 Check if given B-spline space is non-degenerate.
@@ -162,10 +161,6 @@ function exactdim(P::AbstractBSplineSpace)
     return n
 end
 
-# These bindings will be removed when releasing v0.5.0
-Base.@deprecate_binding isproper isnondegenerate true
-Base.@deprecate_binding properdim exactdim true
-
 @doc raw"""
 Return the support of ``i``-th B-spline basis function.
 ```math
@@ -177,12 +172,6 @@ function bsplinesupport(P::AbstractBSplineSpace{p}, i::Integer) where p
     return k[i]..k[i+p+1]
 end
 
-function bsplinesupport(P::AbstractBSplineSpace{p}) where p
-    @warn "bsplinesupport(P::AbstractBSplineSpace{p}) will be removed in the next breaking release."
-    k = knotvector(P)
-    return [k[i]..k[i+p+1] for i in 1:dim(P)]
-end
-
 @doc raw"""
 Internal methods for obtaining a B-spline space with one degree lower.
 ```math
diff --git a/src/_CustomBSplineManifold.jl b/src/_CustomBSplineManifold.jl
deleted file mode 100644
index 36d607eb..00000000
--- a/src/_CustomBSplineManifold.jl
+++ /dev/null
@@ -1,79 +0,0 @@
-# B-spline manifold with given type as a type of control points
-
-struct CustomBSplineManifold{Dim,Deg,C,S<:Tuple} <: AbstractBSplineManifold{Dim,Deg}
-    bsplinespaces::S
-    controlpoints::Array{C,Dim}
-    function CustomBSplineManifold(a::Array{C,Dim},Ps::S) where {S<:Tuple,C,Dim}
-        for P in Ps
-            if !(P isa AbstractBSplineSpace)
-                throw(TypeError(:CustomBSplineManifold,AbstractBSplineSpace,P))
-            end
-        end
-        if size(a) != dim.(Ps)
-            msg = "The size of control points array $(size(a)) and dimensions of B-spline spaces $(dim.(Ps)) must be equal."
-            throw(DimensionMismatch(msg))
-        end
-        Deg = degree.(Ps)
-        new{Dim,Deg,C,S}(Ps,a)
-    end
-end
-
-bsplinespaces(M::CustomBSplineManifold) = M.bsplinespaces
-controlpoints(M::CustomBSplineManifold) = M.controlpoints
-
-@generated function unsafe_mapping(M::CustomBSplineManifold{1,Deg,S,T},t1::Real) where {Deg,S,T}
-    p1, = Deg
-    exs = Expr[]
-    for j1 in 1:p1
-        push!(exs, :(v += b1[$(1+j1)]*getindex(a,i1+$(j1))))
-    end
-    Expr(:block,
-        :((P1,) = bsplinespaces(M)),
-        :(a = controlpoints(M)),
-        :(i1 = intervalindex(P1,t1)),
-        :(b1 = bsplinebasisall(P1,i1,t1)),
-        :(v = b1[1]*getindex(a,i1)),
-        exs...,
-        :(return v)
-    )
-end
-
-@generated function unsafe_mapping(M::CustomBSplineManifold{2,Deg,S,T},t1,t2) where {Deg,S,T}
-    p1, p2 = Deg
-    exs = Expr[]
-    for j2 in 1:p2+1, j1 in 1:p1+1
-        push!(exs, :(v += b1[$(j1)]*b2[$(j2)]*getindex(a,i1+$(j1-1),i2+$(j2-1))))
-    end
-    deleteat!(exs,1)
-    Expr(
-        :block,
-        :((P1, P2) = bsplinespaces(M)),
-        :(a = controlpoints(M)),
-        :((i1, i2) = (intervalindex(P1,t1), intervalindex(P2,t2))),
-        :((b1, b2) = (bsplinebasisall(P1,i1,t1), bsplinebasisall(P2,i2,t2))),
-        :(v = b1[1]*b2[1]*getindex(a,i1,i2)),
-        exs...,
-        :(return v)
-    )
-end
-
-@generated function unsafe_mapping(M::CustomBSplineManifold{3,Deg,S,T},t1,t2,t3) where {Deg,S,T}
-    p1, p2, p3 = Deg
-    exs = Expr[]
-    for j3 in 1:p3+1, j2 in 1:p2+1, j1 in 1:p1+1
-        push!(exs, :(v += b1[$(j1)]*b2[$(j2)]*b3[$(j3)]*getindex(a,i1+$(j1-1),i2+$(j2-1),i3+$(j3-1))))
-    end
-    deleteat!(exs,1)
-    Expr(
-        :block,
-        :((P1, P2, P3) = bsplinespaces(M)),
-        :(a = controlpoints(M)),
-        :((i1, i2, i3) = (intervalindex(P1,t1), intervalindex(P2,t2), intervalindex(P3,t3))),
-        :((b1, b2, b3) = (bsplinebasisall(P1,i1,t1), bsplinebasisall(P2,i2,t2), bsplinebasisall(P3,i3,t3))),
-        :(v = b1[1]*b2[1]*b3[1]*getindex(a,i1,i2,i3)),
-        exs...,
-        :(return v)
-    )
-end
-
-# TODO add mappings higher dimensionnal B-spline manifold with @generated macro
diff --git a/src/_Refinement.jl b/src/_Refinement.jl
index 70ad187a..b5720f8d 100644
--- a/src/_Refinement.jl
+++ b/src/_Refinement.jl
@@ -11,58 +11,24 @@ refinement
 function refinement(M::BSplineManifold{1}, Ps′::Tuple{<:AbstractBSplineSpace})
     Ps = bsplinespaces(M)
     a = controlpoints(M)
-    d = size(a,2)  # 2 == Dim+1
     (n1,) = dim.(Ps)
     (n1′,) = dim.(Ps′)
     (A1,) = changebasis.(Ps, Ps′)
 
-    a′ = [sum(A1[I₁,J₁] * a[I₁,j] for I₁ in 1:n1) for J₁ in 1:n1′, j in 1:d]
+    a′ = [sum(A1[I₁,J₁] * a[I₁] for I₁ in 1:n1) for J₁ in 1:n1′]
     return BSplineManifold(a′, Ps′)
 end
 function refinement(M::BSplineManifold{2}, Ps′::Tuple{<:AbstractBSplineSpace,<:AbstractBSplineSpace})
     Ps = bsplinespaces(M)
     a = controlpoints(M)
-    d = size(a,3)  # 3 == Dim+1
     (n1,n2) = dim.(Ps)
     (n1′,n2′) = dim.(Ps′)
     (A1,A2) = changebasis.(Ps, Ps′)
 
-    a′ = [sum(A1[I₁,J₁] * A2[I₂,J₂] * a[I₁,I₂,j] for I₁ in 1:n1, I₂ in 1:n2) for J₁ in 1:n1′, J₂ in 1:n2′, j in 1:d]
+    a′ = [sum(A1[I₁,J₁] * A2[I₂,J₂] * a[I₁,I₂] for I₁ in 1:n1, I₂ in 1:n2) for J₁ in 1:n1′, J₂ in 1:n2′]
     return BSplineManifold(a′, Ps′)
 end
 function refinement(M::BSplineManifold{3}, Ps′::Tuple{<:AbstractBSplineSpace,<:AbstractBSplineSpace,<:AbstractBSplineSpace})
-    Ps = bsplinespaces(M)
-    a = controlpoints(M)
-    d = size(a,4)  # 4 == Dim+1
-    (n1,n2,n3) = dim.(Ps)
-    (n1′,n2′,n3′) = dim.(Ps′)
-    (A1,A2,A3) = changebasis.(Ps, Ps′)
-
-    a′ = [sum(A1[I₁,J₁] * A2[I₂,J₂]* A3[I₃,J₃] * a[I₁,I₂,I₃,j] for I₁ in 1:n1, I₂ in 1:n2, I₃ in 1:n3) for J₁ in 1:n1′, J₂ in 1:n2′, J₃ in 1:n3′, j in 1:d]
-    return BSplineManifold(a′, Ps′)
-end
-
-function refinement(M::CustomBSplineManifold{1}, Ps′::Tuple{<:AbstractBSplineSpace})
-    Ps = bsplinespaces(M)
-    a = controlpoints(M)
-    (n1,) = dim.(Ps)
-    (n1′,) = dim.(Ps′)
-    (A1,) = changebasis.(Ps, Ps′)
-
-    a′ = [sum(A1[I₁,J₁] * a[I₁] for I₁ in 1:n1) for J₁ in 1:n1′]
-    return CustomBSplineManifold(a′, Ps′)
-end
-function refinement(M::CustomBSplineManifold{2}, Ps′::Tuple{<:AbstractBSplineSpace,<:AbstractBSplineSpace})
-    Ps = bsplinespaces(M)
-    a = controlpoints(M)
-    (n1,n2) = dim.(Ps)
-    (n1′,n2′) = dim.(Ps′)
-    (A1,A2) = changebasis.(Ps, Ps′)
-
-    a′ = [sum(A1[I₁,J₁] * A2[I₂,J₂] * a[I₁,I₂] for I₁ in 1:n1, I₂ in 1:n2) for J₁ in 1:n1′, J₂ in 1:n2′]
-    return CustomBSplineManifold(a′, Ps′)
-end
-function refinement(M::CustomBSplineManifold{3}, Ps′::Tuple{<:AbstractBSplineSpace,<:AbstractBSplineSpace,<:AbstractBSplineSpace})
     Ps = bsplinespaces(M)
     a = controlpoints(M)
     (n1,n2,n3) = dim.(Ps)
@@ -70,35 +36,13 @@ function refinement(M::CustomBSplineManifold{3}, Ps′::Tuple{<:AbstractBSplineS
     (A1,A2,A3) = changebasis.(Ps, Ps′)
 
     a′ = [sum(A1[I₁,J₁] * A2[I₂,J₂] * A3[I₃,J₃] * a[I₁,I₂,I₃] for I₁ in 1:n1, I₂ in 1:n2, I₃ in 1:n3) for J₁ in 1:n1′, J₂ in 1:n2′, J₃ in 1:n3′]
-    return CustomBSplineManifold(a′, Ps′)
-end
-
-
-@doc raw"""
-Refinement of B-spline manifold with additional degree and knotvector.
-"""
-function refinement(M::BSplineManifold{Dim}; p₊::Union{Nothing,NTuple{Dim,Int}}=nothing, k₊::Union{Nothing,NTuple{Dim,KnotVector{T}}}=nothing) where {Dim, T}
-    Ps = bsplinespaces(M)
-    if isnothing(p₊)
-        p₊ = tuple(zeros(Int, Dim)...)
-    elseif length(Ps) ≠ length(p₊)
-        throw(DimensionMismatch())
-    end
-    if isnothing(k₊)
-        k₊ = tuple(zeros(KnotVector, Dim)...)
-    elseif length(Ps) ≠ length(k₊)
-        throw(DimensionMismatch())
-    end
-
-    Ps′ = [expandspace(Ps[i], p₊=p₊[i], k₊=k₊[i]) for i in 1:Dim]
-
-    return refinement(M, tuple(Ps′...))
+    return BSplineManifold(a′, Ps′)
 end
 
 @doc raw"""
 Refinement of B-spline manifold with additional degree and knotvector.
 """
-function refinement(M::CustomBSplineManifold; p₊::Union{Nothing,NTuple{Dim,Int}}=nothing, k₊::Union{Nothing,NTuple{Dim,KnotVector{T}}}=nothing) where {Dim, T}
+function refinement(M::BSplineManifold; p₊::Union{Nothing,NTuple{Dim,Int}}=nothing, k₊::Union{Nothing,NTuple{Dim,KnotVector{T}}}=nothing) where {Dim, T}
     Ps = collect(bsplinespaces(M))
     d = length(Ps)
     if isnothing(p₊)


Test patch:
diff --git a/test/test_BSplineManifold.jl b/test/test_BSplineManifold.jl
index 2fb23f34..4a60e98a 100644
--- a/test/test_BSplineManifold.jl
+++ b/test/test_BSplineManifold.jl
@@ -22,37 +22,10 @@
         @testset "BSplineManifold-1dim" begin
             Random.seed!(42)
 
-            P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1]))
-            n1 = dim(P1) # 2
-            ax = [i for i in 1:n1]
-            ay = [rand() for i in 1:n1]
-            a = hcat(ax,ay)  # n1 × 2 array of d̂-dim vector.
-            M = BSplineManifold(a, (P1,))
-            @test dim(M) == 1
-
-            P1′ = BSplineSpace{2}(KnotVector([-2, 0, 0, 1, 1, 2]))
-            p₊ = (1,)
-            k₊ = (KnotVector(0.3),)
-
-            @test P1 ⊑ P1′
-
-            M′ = refinement(M, (P1′,))
-            M′′ = refinement(M, p₊=p₊, k₊=k₊)
-            ts = [rand() for _ in 1:10]
-            for t in ts
-                @test M(t) ≈ M′(t)
-                @test M(t) ≈ M′′(t)
-            end
-            @test_throws DomainError M(-5)
-        end
-
-        @testset "CustomBSplineManifold-1dim" begin
-            Random.seed!(42)
-
             P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1]))
             n1 = dim(P1) # 2
             a = [Point(i, rand()) for i in 1:n1]  # n1 × n2 array of d̂-dim vector.
-            M = CustomBSplineManifold(a, (P1,))
+            M = BSplineManifold(a, (P1,))
             @test dim(M) == 1
 
             P1′ = BSplineSpace{2}(KnotVector([-2, 0, 0, 1, 1, 2]))
@@ -76,42 +49,12 @@
         @testset "BSplineManifold-2dim" begin
             Random.seed!(42)
 
-            P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1]))
-            P2 = BSplineSpace{1}(KnotVector([1, 1, 2, 3, 3]))
-            n1 = dim(P1) # 2
-            n2 = dim(P2) # 3
-            rand_a = [rand(2) for i in 1:n1, j in 1:n2]
-            a = [[2*i-6.5,2*j-6.5] for i in 1:n1, j in 1:n2] + rand_a
-            M = BSplineManifold(arrayofvector2array(a), (P1, P2))
-            @test dim(M) == 2
-
-            P1′ = BSplineSpace{2}(KnotVector([-2, 0, 0, 1, 1, 2]))
-            P2′ = BSplineSpace{1}(KnotVector([-3, 1, 2, 1.45, 3, 4]))
-            p₊ = (1, 0)
-            k₊ = (KnotVector(), KnotVector(1.45))
-
-            @test P1 ⊑ P1′
-            @test P2 ⊑ P2′
-
-            M′ = refinement(M, (P1′, P2′))
-            M′′ = refinement(M, p₊=p₊, k₊=k₊)
-            ts = [[rand(), 1 + 2 * rand()] for _ in 1:10]
-            for t in ts
-                @test M(t...) ≈ M′(t...)
-                @test M(t...) ≈ M′′(t...)
-            end
-            @test_throws DomainError M(-5,-8)
-        end
-
-        @testset "CustomBSplineManifold-2dim" begin
-            Random.seed!(42)
-
             P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1]))
             P2 = BSplineSpace{1}(KnotVector([1, 1, 2, 3, 3]))
             n1 = dim(P1) # 2
             n2 = dim(P2) # 3
             a = [Point(i, j) for i in 1:n1, j in 1:n2]  # n1 × n2 array of d̂-dim vector.
-            M = CustomBSplineManifold(a, (P1, P2))
+            M = BSplineManifold(a, (P1, P2))
             @test dim(M) == 2
 
             P1′ = BSplineSpace{2}(KnotVector([0, 0, 0, 1, 1, 1]))
@@ -137,30 +80,6 @@
         @testset "BSplineManifold-3dim" begin
             Random.seed!(42)
 
-            P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1]))
-            P2 = BSplineSpace{1}(KnotVector([1, 1, 2, 3, 3]))
-            P3 = BSplineSpace{2}(KnotVector(rand(16)))
-            n1 = dim(P1) # 2
-            n2 = dim(P2) # 3
-            n3 = dim(P3)
-            a = [rand(2) for i1 in 1:n1, i2 in 1:n2, i3 in 1:n3]
-            M = BSplineManifold(arrayofvector2array(a), (P1, P2, P3))
-            @test dim(M) == 3
-
-            p₊ = (1, 0, 1)
-            k₊ = (KnotVector(), KnotVector(1.45), KnotVector())
-
-            M′′ = refinement(M, p₊=p₊, k₊=k₊)
-            ts = [[rand(), 1 + 2 * rand(), 0.5] for _ in 1:10]
-            for t in ts
-                @test M(t...) ≈ M′′(t...)
-            end
-            @test_throws DomainError M(-5,-8,-120)
-        end
-
-        @testset "CustomBSplineManifold-3dim" begin
-            Random.seed!(42)
-
             P1 = BSplineSpace{1}(KnotVector([0, 0, 1, 1]))
             P2 = BSplineSpace{1}(KnotVector([1, 1, 2, 3, 3]))
             P3 = BSplineSpace{2}(KnotVector(rand(16)))
@@ -168,7 +87,7 @@
             n2 = dim(P2) # 3
             n3 = dim(P3)
             a = [Point(i1, i2, 3) for i1 in 1:n1, i2 in 1:n2, i3 in 1:n3]
-            M = CustomBSplineManifold(a, (P1, P2, P3))
+            M = BSplineManifold(a, (P1, P2, P3))
             @test dim(M) == 3
 
             p₊ = (1, 0, 1)
diff --git a/test/test_BSplineSpace.jl b/test/test_BSplineSpace.jl
index 20c9750d..512a2336 100644
--- a/test/test_BSplineSpace.jl
+++ b/test/test_BSplineSpace.jl
@@ -24,12 +24,6 @@
         @test exactdim(P2) == 3
     end
 
-    @testset "support" begin
-        k = KnotVector(rand(10))
-        P = BSplineSpace{2}(k)
-        @test bsplinesupport(P) == [bsplinesupport(P, i) for i in 1:dim(P)]
-    end
-
     @testset "denegeration with lower degree" begin
         k = KnotVector([1, 3, 3, 3, 6, 8, 9])
         @test isnondegenerate(BSplineSpace{2}(k))
diff --git a/test/test_Fitting.jl b/test/test_Fitting.jl
index aaeec8fa..479d56d3 100644
--- a/test/test_Fitting.jl
+++ b/test/test_Fitting.jl
@@ -29,7 +29,7 @@
         P1 = BSplineSpace{p1}(k1)
         n1 = dim(P1)
         a_org = [Point(i1, rand()) for i1 in 1:n1]
-        M = CustomBSplineManifold(a_org, (P1,))
+        M = BSplineManifold(a_org, (P1,))
 
         P1′ = expandspace(P1, p₊=1, k₊=KnotVector(rand(2)))
 
@@ -51,7 +51,7 @@
         P1 = BSplineSpace{p1}(k1)
         n1 = dim(P1)
         a_org = [Point(i1, rand()) for i1 in 1:n1]
-        M = CustomBSplineManifold(a_org, (P1,))
+        M = BSplineManifold(a_org, (P1,))
 
         P1′ = expandspace(P1, p₊=1, k₊=KnotVector(rand(2)))
 
@@ -75,7 +75,7 @@
         P2 = BSplineSpace{p2}(k2)
         n2 = dim(P2)
         a_org = [Point(i1, i2, rand()) for i1 in 1:n1, i2 in 1:n2]
-        M = CustomBSplineManifold(a_org, (P1, P2))
+        M = BSplineManifold(a_org, (P1, P2))
 
         P1′ = expandspace(P1, p₊=1, k₊=KnotVector(rand(2)))
         P2′ = expandspace(P2, p₊=1, k₊=KnotVector(rand(2)))
@@ -102,7 +102,7 @@
         P2 = BSplineSpace{p2}(k2)
         n2 = dim(P2)
         a_org = [Point(i1, i2, rand()) for i1 in 1:n1, i2 in 1:n2]
-        M = CustomBSplineManifold(a_org, (P1, P2))
+        M = BSplineManifold(a_org, (P1, P2))
 
         P1′ = expandspace(P1, p₊=1, k₊=KnotVector(rand(2)))
         P2′ = expandspace(P2, p₊=1, k₊=KnotVector(rand(2)))
@@ -130,7 +130,7 @@
         P3 = BSplineSpace{p3}(k3)
         n3 = dim(P3)
         a_org = [Point(i1, i2, i3, rand()) for i1 in 1:n1, i2 in 1:n2, i3 in 1:n3]
-        M = CustomBSplineManifold(a_org, (P1, P2, P3))
+        M = BSplineManifold(a_org, (P1, P2, P3))
 
         P1′ = expandspace(P1, p₊=1, k₊=KnotVector(rand(2)))
         P2′ = expandspace(P2, p₊=1, k₊=KnotVector(rand(2)))
@@ -162,7 +162,7 @@
         P3 = BSplineSpace{p3}(k3)
         n3 = dim(P3)
         a_org = [Point(i1, i2, i3, rand()) for i1 in 1:n1, i2 in 1:n2, i3 in 1:n3]
-        M = CustomBSplineManifold(a_org, (P1, P2, P3))
+        M = BSplineManifold(a_org, (P1, P2, P3))
 
         P1′ = expandspace(P1, p₊=1, k₊=KnotVector(rand(2)))
         P2′ = expandspace(P2, p₊=1, k₊=KnotVector(rand(2)))
diff --git a/test/test_UniformBSplineSpace.jl b/test/test_UniformBSplineSpace.jl
index 8b759b39..b29494b2 100644
--- a/test/test_UniformBSplineSpace.jl
+++ b/test/test_UniformBSplineSpace.jl
@@ -61,7 +61,6 @@
     @testset "support" begin
         k = UniformKnotVector(0:9)
         P = UniformBSplineSpace{2}(k)
-        @test bsplinesupport(P) == [bsplinesupport(P, i) for i in 1:dim(P)]
         @test bsplinesupport(P,1) == 0..3
         @test bsplinesupport(P,2) == 1..4
     end