@@ -597,7 +597,7 @@ struct BSplineInterpolation{uType, tType, pType, kType, cType, scType, T, N} <:
597597end
598598
599599function BSplineInterpolation (
600- u, t, d, pVecType, knotVecType; extrapolate = false , assume_linear_t = 1e-2 )
600+ u:: AbstractVector , t, d, pVecType, knotVecType; extrapolate = false , assume_linear_t = 1e-2 )
601601 u, t = munge_data (u, t)
602602 n = length (t)
603603 n < d + 1 && error (" BSplineInterpolation needs at least d + 1, i.e. $(d+ 1 ) points." )
@@ -665,6 +665,79 @@ function BSplineInterpolation(
665665 u, t, d, p, k, c, sc, pVecType, knotVecType, extrapolate, assume_linear_t)
666666end
667667
668+ function BSplineInterpolation (
669+ u:: AbstractArray{T, N} , t, d, pVecType, knotVecType; extrapolate = false ,
670+ assume_linear_t = 1e-2 ) where {T, N}
671+ u, t = munge_data (u, t)
672+ n = length (t)
673+ n < d + 1 && error (" BSplineInterpolation needs at least d + 1, i.e. $(d+ 1 ) points." )
674+ s = zero (eltype (u))
675+ p = zero (t)
676+ k = zeros (eltype (t), n + d + 1 )
677+ l = zeros (eltype (u), n - 1 )
678+ p[1 ] = zero (eltype (t))
679+ p[end ] = one (eltype (t))
680+
681+ ax_u = axes (u)[1 : (end - 1 )]
682+
683+ for i in 2 : n
684+ s += √ ((t[i] - t[i - 1 ])^ 2 + sum ((u[ax_u... , i] - u[ax_u... , i - 1 ]) .^ 2 ))
685+ l[i - 1 ] = s
686+ end
687+ if pVecType == :Uniform
688+ for i in 2 : (n - 1 )
689+ p[i] = p[1 ] + (i - 1 ) * (p[end ] - p[1 ]) / (n - 1 )
690+ end
691+ elseif pVecType == :ArcLen
692+ for i in 2 : (n - 1 )
693+ p[i] = p[1 ] + l[i - 1 ] / s * (p[end ] - p[1 ])
694+ end
695+ end
696+
697+ lidx = 1
698+ ridx = length (k)
699+ while lidx <= (d + 1 ) && ridx >= (length (k) - d)
700+ k[lidx] = p[1 ]
701+ k[ridx] = p[end ]
702+ lidx += 1
703+ ridx -= 1
704+ end
705+
706+ ps = zeros (eltype (t), n - 2 )
707+ s = zero (eltype (t))
708+ for i in 2 : (n - 1 )
709+ s += p[i]
710+ ps[i - 1 ] = s
711+ end
712+
713+ if knotVecType == :Uniform
714+ # uniformly spaced knot vector
715+ # this method is not recommended because, if it is used with the chord length method for global interpolation,
716+ # the system of linear equations would be singular.
717+ for i in (d + 2 ): n
718+ k[i] = k[1 ] + (i - d - 1 ) // (n - d) * (k[end ] - k[1 ])
719+ end
720+ elseif knotVecType == :Average
721+ # average spaced knot vector
722+ idx = 1
723+ if d + 2 <= n
724+ k[d + 2 ] = 1 // d * ps[d]
725+ end
726+ for i in (d + 3 ): n
727+ k[i] = 1 // d * (ps[idx + d] - ps[idx])
728+ idx += 1
729+ end
730+ end
731+ # control points
732+ sc = zeros (eltype (t), n, n)
733+ spline_coefficients! (sc, d, k, p)
734+ c = (sc \ reshape (u, prod (size (u)[1 : (end - 1 )]), :)' )'
735+ c = reshape (c, size (u)... )
736+ sc = zeros (eltype (t), n)
737+ BSplineInterpolation (
738+ u, t, d, p, k, c, sc, pVecType, knotVecType, extrapolate, assume_linear_t)
739+ end
740+
668741"""
669742 BSplineApprox(u, t, d, h, pVecType, knotVecType; extrapolate = false)
670743
@@ -738,7 +811,7 @@ struct BSplineApprox{uType, tType, pType, kType, cType, scType, T, N} <:
738811end
739812
740813function BSplineApprox (
741- u, t, d, h, pVecType, knotVecType; extrapolate = false , assume_linear_t = 1e-2 )
814+ u:: AbstractVector , t, d, h, pVecType, knotVecType; extrapolate = false , assume_linear_t = 1e-2 )
742815 u, t = munge_data (u, t)
743816 n = length (t)
744817 h < d + 1 && error (" BSplineApprox needs at least d + 1, i.e. $(d+ 1 ) control points." )
@@ -827,6 +900,101 @@ function BSplineApprox(
827900 u, t, d, h, p, k, c, sc, pVecType, knotVecType, extrapolate, assume_linear_t)
828901end
829902
903+ function BSplineApprox (
904+ u:: AbstractArray{T, N} , t, d, h, pVecType, knotVecType; extrapolate = false ,
905+ assume_linear_t = 1e-2 ) where {T, N}
906+ u, t = munge_data (u, t)
907+ n = length (t)
908+ h < d + 1 && error (" BSplineApprox needs at least d + 1, i.e. $(d+ 1 ) control points." )
909+ s = zero (eltype (u))
910+ p = zero (t)
911+ k = zeros (eltype (t), h + d + 1 )
912+ l = zeros (eltype (u), n - 1 )
913+ p[1 ] = zero (eltype (t))
914+ p[end ] = one (eltype (t))
915+
916+ ax_u = axes (u)[1 : (end - 1 )]
917+
918+ for i in 2 : n
919+ s += √ ((t[i] - t[i - 1 ])^ 2 + sum ((u[ax_u... , i] - u[ax_u... , i - 1 ]) .^ 2 ))
920+ l[i - 1 ] = s
921+ end
922+ if pVecType == :Uniform
923+ for i in 2 : (n - 1 )
924+ p[i] = p[1 ] + (i - 1 ) * (p[end ] - p[1 ]) / (n - 1 )
925+ end
926+ elseif pVecType == :ArcLen
927+ for i in 2 : (n - 1 )
928+ p[i] = p[1 ] + l[i - 1 ] / s * (p[end ] - p[1 ])
929+ end
930+ end
931+
932+ lidx = 1
933+ ridx = length (k)
934+ while lidx <= (d + 1 ) && ridx >= (length (k) - d)
935+ k[lidx] = p[1 ]
936+ k[ridx] = p[end ]
937+ lidx += 1
938+ ridx -= 1
939+ end
940+
941+ ps = zeros (eltype (t), n - 2 )
942+ s = zero (eltype (t))
943+ for i in 2 : (n - 1 )
944+ s += p[i]
945+ ps[i - 1 ] = s
946+ end
947+
948+ if knotVecType == :Uniform
949+ # uniformly spaced knot vector
950+ # this method is not recommended because, if it is used with the chord length method for global interpolation,
951+ # the system of linear equations would be singular.
952+ for i in (d + 2 ): h
953+ k[i] = k[1 ] + (i - d - 1 ) // (h - d) * (k[end ] - k[1 ])
954+ end
955+ elseif knotVecType == :Average
956+ # NOTE: verify that average method can be applied when size of k is less than size of p
957+ # average spaced knot vector
958+ idx = 1
959+ if d + 2 <= h
960+ k[d + 2 ] = 1 // d * ps[d]
961+ end
962+ for i in (d + 3 ): h
963+ k[i] = 1 // d * (ps[idx + d] - ps[idx])
964+ idx += 1
965+ end
966+ end
967+ # control points
968+ c = zeros (eltype (u), size (u)[1 : (end - 1 )]. .. , h)
969+ c[ax_u... , 1 ] = u[ax_u... , 1 ]
970+ c[ax_u... , end ] = u[ax_u... , end ]
971+ q = zeros (eltype (u), size (u)[1 : (end - 1 )]. .. , n)
972+ sc = zeros (eltype (t), n, h)
973+ for i in 1 : n
974+ spline_coefficients! (view (sc, i, :), d, k, p[i])
975+ end
976+ for k in 2 : (n - 1 )
977+ q[ax_u... , k] = u[ax_u... , k] - sc[k, 1 ] * u[ax_u... , 1 ] -
978+ sc[k, h] * u[ax_u... , end ]
979+ end
980+ Q = Array {eltype(u), N} (undef, size (u)[1 : (end - 1 )]. .. , h - 2 )
981+ for i in 2 : (h - 1 )
982+ s = zeros (eltype (sc), size (u)[1 : (end - 1 )]. .. )
983+ for k in 2 : (n - 1 )
984+ s = s + sc[k, i] * q[ax_u... , k]
985+ end
986+ Q[ax_u... , i - 1 ] = s
987+ end
988+ sc = sc[2 : (end - 1 ), 2 : (h - 1 )]
989+ M = transpose (sc) * sc
990+ Q = reshape (Q, prod (size (u)[1 : (end - 1 )]), :)
991+ P = (M \ Q' )'
992+ P = reshape (P, size (u)[1 : (end - 1 )]. .. , :)
993+ c[ax_u... , 2 : (end - 1 )] = P
994+ sc = zeros (eltype (t), h)
995+ BSplineApprox (
996+ u, t, d, h, p, k, c, sc, pVecType, knotVecType, extrapolate, assume_linear_t)
997+ end
830998"""
831999 CubicHermiteSpline(du, u, t; extrapolate = false, cache_parameters = false)
8321000
0 commit comments