@@ -597,7 +597,7 @@ struct BSplineInterpolation{uType, tType, pType, kType, cType, scType, T, N} <:
597
597
end
598
598
599
599
function 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 )
601
601
u, t = munge_data (u, t)
602
602
n = length (t)
603
603
n < d + 1 && error (" BSplineInterpolation needs at least d + 1, i.e. $(d+ 1 ) points." )
@@ -665,6 +665,79 @@ function BSplineInterpolation(
665
665
u, t, d, p, k, c, sc, pVecType, knotVecType, extrapolate, assume_linear_t)
666
666
end
667
667
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
+
668
741
"""
669
742
BSplineApprox(u, t, d, h, pVecType, knotVecType; extrapolate = false)
670
743
@@ -738,7 +811,7 @@ struct BSplineApprox{uType, tType, pType, kType, cType, scType, T, N} <:
738
811
end
739
812
740
813
function 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 )
742
815
u, t = munge_data (u, t)
743
816
n = length (t)
744
817
h < d + 1 && error (" BSplineApprox needs at least d + 1, i.e. $(d+ 1 ) control points." )
@@ -827,6 +900,101 @@ function BSplineApprox(
827
900
u, t, d, h, p, k, c, sc, pVecType, knotVecType, extrapolate, assume_linear_t)
828
901
end
829
902
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
830
998
"""
831
999
CubicHermiteSpline(du, u, t; extrapolate = false, cache_parameters = false)
832
1000
0 commit comments