Skip to content

Commit fa367af

Browse files
authored
Add minor util functions (#393)
* remove unnecessary `BasicBSpline.` * add new method `knotvector(values, counts)` * add `copy(::BSplineSpace)` * add `clamp`, `clamp, and `isclamped` * add `expand_domain`, `Base.:+(::BSplineSpace, ::BSplineSpace)`, and `Base.union(::KnotVector, ::KnotVector)` * fix * add more `RationalBSplineManifold` method * fix stackoverflow, add more tests * fix test * fix == * add more `knotvector` methods * update around `countknots` * udpate tests * update docs * update tests * add missing return etc. * update tests * refactor refinement * update docs and tests of `union` * fix unique * add tests for countknots * update union * add more tests on knot vectors * fix ambiguity * fix _sorted_unique * update tests
1 parent 61ad7eb commit fa367af

17 files changed

+454
-162
lines changed

docs/src/math/bsplinebasis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ N = 10
223223
c=2/√3
224224
f(t) = ifelse(t>0, exp(-1/t), 0.0)
225225
g(t) = 1 - f(c*t) / (f(c*t) + f(c-c*t))
226-
h(t) = clamp(1 - f((1-t)/2) / f(1/2), 0, 1)
226+
h(t) = Base.clamp(1 - f((1-t)/2) / f(1/2), 0, 1)
227227
228228
# Default knot vector
229229
v = 10*(1:N-1)/N + randn(N-1)*0.5

src/_BSplineBasis.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ julia> bsplinebasis₊₀.(P,1:5,(1:6)')
5151
push!(exs, :($(K_l(p+2-i)) = $(K_r(i,p+2-i))))
5252
push!(exs, :($(B_l(p+1-i)) = $(B_r(p+1-i))))
5353
end
54-
Expr(:block,
54+
return Expr(:block,
5555
:(v = knotvector(P).vector),
5656
:($k_l = $k_r),
5757
:($(B_l(p+1)) = $(A_r(p+1))),
@@ -109,7 +109,7 @@ julia> bsplinebasis₋₀.(P,1:5,(1:6)')
109109
push!(exs, :($(K_l(p+2-i)) = $(K_r(i,p+2-i))))
110110
push!(exs, :($(B_l(p+1-i)) = $(B_r(p+1-i))))
111111
end
112-
Expr(:block,
112+
return Expr(:block,
113113
:(v = knotvector(P).vector),
114114
:($k_l = $k_r),
115115
:($(B_l(p+1)) = $(A_r(p+1))),
@@ -168,7 +168,7 @@ julia> bsplinebasis.(P,1:5,(1:6)')
168168
push!(exs, :($(K_l(p+2-i)) = $(K_r(i,p+2-i))))
169169
push!(exs, :($(B_l(p+1-i)) = $(B_r(p+1-i))))
170170
end
171-
Expr(:block,
171+
return Expr(:block,
172172
:(v = knotvector(P).vector),
173173
:($k_l = $k_r),
174174
:($(B_l(p+1)) = $(A_r(p+1))),
@@ -228,7 +228,7 @@ julia> BasicBSpline.bsplinebasis₋₀I.(P,1:5,(1:6)')
228228
push!(exs, :($(K_l(p+2-i)) = $(K_r(i,p+2-i))))
229229
push!(exs, :($(B_l(p+1-i)) = $(B_r(p+1-i))))
230230
end
231-
Expr(:block,
231+
return Expr(:block,
232232
:(v = knotvector(P).vector),
233233
:($k_l = $k_r),
234234
:($(B_l(p+1)) = $(A_r(p+1))),
@@ -297,7 +297,7 @@ bsplinebasisall
297297

298298
@inline function bsplinebasisall(P::BSplineSpace{0,T},i::Integer,t::S) where {T, S<:Real}
299299
U = StaticArrays.arithmetic_closure(promote_type(T,S))
300-
SVector(one(U),)
300+
return SVector(one(U),)
301301
end
302302

303303
@inline function bsplinebasisall(P::BSplineSpace{1}, i::Integer, t::Real)
@@ -315,7 +315,7 @@ end
315315
b = Expr(:tuple, bs...)
316316
B = Expr(:tuple, Bs...)
317317
exs = [:($(Bs[j+1]) = ($(K1s[j+1])*$(bs[j+1]) + $(K2s[j])*$(bs[j]))) for j in 1:p-1]
318-
Expr(:block,
318+
return Expr(:block,
319319
:($(Expr(:meta, :inline))),
320320
:(k = knotvector(P)),
321321
:($b = bsplinebasisall(_lower_R(P),i+1,t)),
@@ -349,11 +349,11 @@ end
349349

350350
@inline function uniform_bsplinebasisall_kernel(::Val{0},t::T) where T<:Real
351351
U = StaticArrays.arithmetic_closure(T)
352-
SVector{1,U}(one(t))
352+
return SVector{1,U}(one(t))
353353
end
354354
@inline function uniform_bsplinebasisall_kernel(::Val{1},t::T) where T<:Real
355355
U = StaticArrays.arithmetic_closure(T)
356-
SVector{2,U}(1-t,t)
356+
return SVector{2,U}(1-t,t)
357357
end
358358
@generated function uniform_bsplinebasisall_kernel(::Val{p}, t::T) where {p, T<:Real}
359359
bs = [Symbol(:b,i) for i in 1:p]
@@ -363,7 +363,7 @@ end
363363
b = Expr(:tuple, bs...)
364364
B = Expr(:tuple, Bs...)
365365
exs = [:($(Bs[j+1]) = ($(K1s[j+1])*$(bs[j+1]) + $(K2s[j])*$(bs[j]))) for j in 1:p-1]
366-
Expr(
366+
return Expr(
367367
:block,
368368
:($(Expr(:meta, :inline))),
369369
:($b = uniform_bsplinebasisall_kernel(Val{$(p-1)}(),t)),

src/_BSplineManifold.jl

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct BSplineManifold{Dim,Deg,C,T,S<:NTuple{Dim, BSplineSpace{p,T} where p}} <:
4141
controlpoints::Array{C,Dim}
4242
bsplinespaces::S
4343
function BSplineManifold{Dim,Deg,C,T,S}(a::Array{C,Dim},P::S) where {S<:NTuple{Dim, BSplineSpace{p,T} where p},C} where {Dim, Deg, T}
44-
new{Dim,Deg,C,T,S}(a,P)
44+
return new{Dim,Deg,C,T,S}(a,P)
4545
end
4646
end
4747

@@ -61,17 +61,17 @@ end
6161

6262
BSplineManifold(a::Array{C,Dim},Ps::Vararg{BSplineSpace, Dim}) where {C,Dim} = BSplineManifold(a,Ps)
6363

64-
Base.:(==)(M1::AbstractManifold, M2::AbstractManifold) = (bsplinespaces(M1)==bsplinespaces(M2)) & (controlpoints(M1)==controlpoints(M2))
64+
Base.:(==)(M1::BSplineManifold, M2::BSplineManifold) = (bsplinespaces(M1)==bsplinespaces(M2)) & (controlpoints(M1)==controlpoints(M2))
6565

6666
bsplinespaces(M::BSplineManifold) = M.bsplinespaces
6767
controlpoints(M::BSplineManifold) = M.controlpoints
6868

6969
function Base.hash(M::BSplineManifold{0}, h::UInt)
70-
hash(BSplineManifold{0}, hash(controlpoints(M), h))
70+
return hash(BSplineManifold{0}, hash(controlpoints(M), h))
7171
end
7272

7373
function Base.hash(M::BSplineManifold, h::UInt)
74-
hash(xor(hash.(bsplinespaces(M), h)...), hash(controlpoints(M), h))
74+
return hash(xor(hash.(bsplinespaces(M), h)...), hash(controlpoints(M), h))
7575
end
7676

7777
@doc raw"""
@@ -118,7 +118,7 @@ function unbounded_mapping end
118118
push!(exs, ex)
119119
end
120120
exs[1].head = :(=)
121-
Expr(
121+
return Expr(
122122
:block,
123123
Expr(:(=), Expr(:tuple, [Symbol(:P, i) for i in 1:Dim]...), :(bsplinespaces(M))),
124124
Expr(:(=), Expr(:tuple, [Symbol(:t, i) for i in 1:Dim]...), :t),
@@ -137,7 +137,7 @@ end
137137
T = Expr(:tuple, ts...)
138138
exs = [:($(Symbol(:t,i)) in domain($(Symbol(:P,i))) || throw(DomainError($(Symbol(:t,i)), "The input "*string($(Symbol(:t,i)))*" is out of domain $(domain($(Symbol(:P,i))))."))) for i in 1:Dim]
139139
ret = Expr(:call,:unbounded_mapping,:M,[Symbol(:t,i) for i in 1:Dim]...)
140-
Expr(
140+
return Expr(
141141
:block,
142142
:($(Expr(:meta, :inline))),
143143
:($T = t),
@@ -263,3 +263,14 @@ end
263263
a = controlpoints(M)
264264
return a[]
265265
end
266+
267+
function clamp(M::AbstractManifold)
268+
Ps = bsplinespaces(M)
269+
Ps′ = clamp.(Ps)
270+
return refinement_I(M, Ps′)
271+
end
272+
273+
function isclamped(M::AbstractManifold)
274+
Ps = bsplinespaces(M)
275+
return all(isclamped, Ps)
276+
end

src/_BSplineSpace.jl

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ Base.iterate(::AbstractFunctionSpace, ::Any) = nothing
6767
@inline Base.:(==)(P1::BSplineSpace{p}, P2::BSplineSpace{p}) where p = knotvector(P1) == knotvector(P2)
6868
@inline Base.:(==)(P1::BSplineSpace{p1}, P2::BSplineSpace{p2}) where {p1, p2} = false
6969

70+
Base.copy(P::BSplineSpace{p}) where p = BSplineSpace{p}(copy(P.knotvector))
71+
7072
bsplinespace(P::BSplineSpace) = P
7173

7274
@inline function degree(::BSplineSpace{p}) where p
@@ -78,7 +80,7 @@ end
7880
end
7981

8082
@generated function _promote_knottype(P::NTuple{Dim,BSplineSpace}) where Dim
81-
Expr(
83+
return Expr(
8284
:block,
8385
Expr(:(=), Expr(:tuple, [Symbol(:P, i) for i in 1:Dim]...), :P),
8486
Expr(:(=), Expr(:tuple, [Symbol(:k, i) for i in 1:Dim]...), Expr(:tuple, [:(knotvector($(Symbol(:P, i)))) for i in 1:Dim]...)),
@@ -594,14 +596,45 @@ Expand B-spline space with given additional degree and knotvector.
594596
The behavior of `expandspace` is same as `expandspace_I`.
595597
"""
596598
function expandspace(P::BSplineSpace{p,T}, _p₊::Val{p₊}, k₊::AbstractKnotVector=EmptyKnotVector{T}()) where {p,p₊,T}
597-
expandspace_I(P,_p₊,k₊)
599+
return expandspace_I(P,_p₊,k₊)
598600
end
599601

600602
function expandspace(P::BSplineSpace{p,T}, k₊::AbstractKnotVector=EmptyKnotVector{T}()) where {p,T}
601-
expandspace_I(P,k₊)
603+
return expandspace_I(P,k₊)
602604
end
603605

604606
function Base.hash(P::BSplineSpace{p}, h::UInt) where p
605607
k = knotvector(P)
606-
hash(BSplineSpace{p}, hash(_vec(k), h))
608+
return hash(BSplineSpace{p}, hash(_vec(k), h))
609+
end
610+
611+
function clamp!(P::BSplineSpace{p, T, <:KnotVector}) where {p, T}
612+
v = _vec(knotvector(P))
613+
v[1:p] .= v[p+1]
614+
v[end-p+1:end] .= v[end-p]
615+
return P
616+
end
617+
function clamp(P::BSplineSpace{p, T, <:KnotVector}) where {p, T}
618+
return clamp!(copy(P))
619+
end
620+
function clamp(P::BSplineSpace{p, T, <:UniformKnotVector}) where {p, T}
621+
k = knotvector(P)
622+
return clamp(BSplineSpace{p}(KnotVector(k)))
623+
end
624+
625+
function isclamped(P::BSplineSpace{p}) where p
626+
k = knotvector(P)
627+
return k[1] == k[p+1] && k[end-p] == k[end]
628+
end
629+
630+
function Base.:+(P1::BSplineSpace{p}, P2::BSplineSpace{p}) where {p}
631+
return BSplineSpace{p}(knotvector(P1) knotvector(P2))
632+
end
633+
634+
function expand_domain(P::BSplineSpace{p,T1}, Δt::T2) where {p,T1,T2}
635+
U = promote_type(T1, T2)
636+
v = Vector{U}(_vec(knotvector(P)))
637+
v[1:p+1] .= v[p+1]-Δt
638+
v[end-p:end] .= v[end-p]+Δt
639+
return BSplineSpace{p}(KnotVector(v))
607640
end

src/_ChangeBasis.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ end
341341

342342
@generated function _derivatives_at_left(P::BSplineSpace{p,T}) where {p, T}
343343
args = [:(pop(bsplinebasisall(BSplineDerivativeSpace{$(r)}(P),1,a))) for r in 0:p-1]
344-
quote
344+
return quote
345345
a, _ = extrema(domain(P))
346346
$(Expr(:call, :hcat, args...))
347347
end
@@ -353,15 +353,15 @@ end
353353

354354
@generated function _derivatives_at_right(P::BSplineSpace{p,T}) where {p, T}
355355
args = [:(popfirst(bsplinebasisall(BSplineDerivativeSpace{$(r)}(P),n-p,b))) for r in 0:p-1]
356-
quote
356+
return quote
357357
n = dim(P)
358358
_, b = extrema(domain(P))
359359
$(Expr(:call, :hcat, args...))
360360
end
361361
end
362362
function _derivatives_at_right(::BSplineSpace{0,T}) where {T}
363363
U = StaticArrays.arithmetic_closure(T)
364-
SMatrix{0,0,U}()
364+
return SMatrix{0,0,U}()
365365
end
366366

367367
@doc raw"""

src/_DerivativeBasis.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@
2424
push!(exs, :($(K_l(p+2-i)) = $(L_r(i,p+2-i))))
2525
push!(exs, :($(B_l(p+1-i)) = $(C_r(p+1-i))))
2626
end
27-
Expr(:block,
27+
return Expr(:block,
2828
:(v = knotvector(dP).vector),
2929
:($k_l = $k_r),
3030
:($(B_l(p+1)) = $(A_r(p+1))),
3131
exs...,
3232
:(return $(prod(p-r+1:p))*B1)
3333
)
3434
else
35-
:(return zero($U))
35+
return :(return zero($U))
3636
end
3737
end
3838

@@ -60,15 +60,15 @@ end
6060
push!(exs, :($(K_l(p+2-i)) = $(L_r(i,p+2-i))))
6161
push!(exs, :($(B_l(p+1-i)) = $(C_r(p+1-i))))
6262
end
63-
Expr(:block,
63+
return Expr(:block,
6464
:(v = knotvector(dP).vector),
6565
:($k_l = $k_r),
6666
:($(B_l(p+1)) = $(A_r(p+1))),
6767
exs...,
6868
:(return $(prod(p-r+1:p))*B1)
6969
)
7070
else
71-
:(return zero($U))
71+
return :(return zero($U))
7272
end
7373
end
7474

@@ -96,15 +96,15 @@ end
9696
push!(exs, :($(K_l(p+2-i)) = $(L_r(i,p+2-i))))
9797
push!(exs, :($(B_l(p+1-i)) = $(C_r(p+1-i))))
9898
end
99-
Expr(:block,
99+
return Expr(:block,
100100
:(v = knotvector(dP).vector),
101101
:($k_l = $k_r),
102102
:($(B_l(p+1)) = $(A_r(p+1))),
103103
exs...,
104104
:(return $(prod(p-r+1:p))*B1)
105105
)
106106
else
107-
:(return zero($U))
107+
return :(return zero($U))
108108
end
109109
end
110110

@@ -166,7 +166,7 @@ end
166166
B = Expr(:tuple, Bs...)
167167
exs = [:($(Bs[j+1]) = ($(K1s[j+1])*$(bs[j+1]) + $(K2s[j])*$(bs[j]))) for j in 1:p-1]
168168
if r p
169-
Expr(:block,
169+
return Expr(:block,
170170
:($(Expr(:meta, :inline))),
171171
:(k = knotvector(dP)),
172172
:($b = bsplinebasisall(_lower_R(dP),i+1,t)),
@@ -177,13 +177,13 @@ end
177177
)
178178
else
179179
Z = Expr(:tuple, [:(zero($U)) for i in 1:p+1]...)
180-
:(return SVector($(Z)))
180+
return :(return SVector($(Z)))
181181
end
182182
end
183183

184184
@inline function bsplinebasisall(dP::BSplineDerivativeSpace{0,<:BSplineSpace{p,T}}, i::Integer, t::Real) where {p, T}
185185
P = bsplinespace(dP)
186-
bsplinebasisall(P,i,t)
186+
return bsplinebasisall(P,i,t)
187187
end
188188

189189
# TODO: add methods for UniformBSplineSpace (and OpenUniformBSplineSpace)

src/_DerivativeSpace.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,24 @@ julia> degree(P), degree(dP)
2323
struct BSplineDerivativeSpace{r, S<:BSplineSpace, T} <: AbstractFunctionSpace{T}
2424
bsplinespace::S
2525
function BSplineDerivativeSpace{r,S,T}(P::S) where {r, S<:BSplineSpace{p,T}} where {p,T}
26-
new{r,S,T}(P)
26+
return new{r,S,T}(P)
2727
end
2828
end
2929

3030
function BSplineDerivativeSpace{r}(P::S) where {r, S<:BSplineSpace{p,T}} where {p,T}
31-
BSplineDerivativeSpace{r,S,T}(P)
31+
return BSplineDerivativeSpace{r,S,T}(P)
3232
end
3333
function BSplineDerivativeSpace{r,S}(P::S) where {r, S<:BSplineSpace{p,T}} where {p,T}
34-
BSplineDerivativeSpace{r,S,T}(P)
34+
return BSplineDerivativeSpace{r,S,T}(P)
3535
end
3636
function BSplineDerivativeSpace{r,S1}(P::S2) where {r, S1<:BSplineSpace{p,T1}, S2<:BSplineSpace{p,T2}} where {p,T1,T2}
37-
BSplineDerivativeSpace{r}(S1(P))
37+
return BSplineDerivativeSpace{r}(S1(P))
3838
end
3939
function BSplineDerivativeSpace{r,S}(dP::BSplineDerivativeSpace{r,S}) where {r,S}
40-
dP
40+
return dP
4141
end
4242
function BSplineDerivativeSpace{r,S1}(dP::BSplineDerivativeSpace{r,S2}) where {r,S1,S2}
43-
BSplineDerivativeSpace{r,S1}(S1(bsplinespace(dP)))
43+
return BSplineDerivativeSpace{r,S1}(S1(bsplinespace(dP)))
4444
end
4545

4646
# Broadcast like a scalar
@@ -128,5 +128,5 @@ end
128128
function Base.hash(dP::BSplineDerivativeSpace{r,<:BSplineSpace{p}}, h::UInt) where {r,p}
129129
P = bsplinespace(dP)
130130
k = knotvector(P)
131-
hash(BSplineDerivativeSpace{r,<:BSplineSpace{p}}, hash(_vec(k), h))
131+
return hash(BSplineDerivativeSpace{r,<:BSplineSpace{p}}, hash(_vec(k), h))
132132
end

0 commit comments

Comments
 (0)