Line data Source code
1 3 : function catmullrom(x::AbstractVector, span::Tuple=(0, 1),
2 : parametrization::Symbol=:uniform)
3 3 : catmullrom(x, Val(parametrization), span)
4 : end
5 :
6 1 : function catmullrom(x::AbstractVector, ::Val{:uniform}, span)
7 1 : @assert length(x) > 1
8 :
9 1 : T = eltype(eltype(x))
10 1 : t0, t1 = T.(span)
11 1 : n = length(x)
12 1 : ts = range(t0, t1, n)
13 1 : dt = step(ts)
14 :
15 2 : dx = similar(x)
16 1 : dx[1] = (x[2] - x[1]) / dt
17 1 : dx[end] = (x[end] - x[end-1]) / dt
18 :
19 1 : for i in 2:n-1
20 98 : dx[i] = (x[i+1] - x[i-1]) / 2dt
21 195 : end
22 :
23 1 : hermitespline(collect(ts), collect(zip(x, dx)))
24 : end
25 :
26 2 : function catmullrom(x::AbstractVector, ::Val{P}, span) where {P}
27 2 : t = _parametrization(Val(P), x, span...)
28 2 : catmullrom(x, t)
29 : end
30 :
31 1 : function _parametrization(::Val{:chordal}, x, t0, t1)
32 1 : T = eltype(eltype(x))
33 1 : n = length(x)
34 2 : ts = Vector{T}(undef, n)
35 :
36 1 : ts[1] = T(0)
37 1 : for i = 2:n
38 99 : ts[i] = ts[i-1] + norm(x[i] - x[i-1])
39 197 : end
40 :
41 1 : ts .*= ((t1 - t0) / ts[end])
42 1 : ts .+= t0
43 :
44 1 : ts
45 : end
46 :
47 1 : function _parametrization(::Val{:centripetal}, x, t0, t1)
48 1 : T = eltype(eltype(x))
49 1 : n = length(x)
50 2 : ts = Vector{T}(undef, n)
51 :
52 1 : ts[1] = T(0)
53 1 : for i = 2:n
54 99 : ts[i] = ts[i-1] + sqrt(norm(x[i] - x[i-1]))
55 197 : end
56 :
57 1 : ts .*= ((t1 - t0) / ts[end])
58 1 : ts .+= t0
59 :
60 1 : ts
61 : end
62 :
63 3 : function catmullrom(x::AbstractVector, t::AbstractVector)
64 3 : @assert length(x) > 1
65 :
66 3 : T = eltype(eltype(x))
67 3 : n = length(x)
68 3 : @assert length(t) == n
69 :
70 6 : dx = similar(x)
71 3 : dx[1] = (x[2] - x[1]) / (t[2] - t[1])
72 3 : dx[end] = (x[end] - x[end-1]) / (t[end] - t[end-1])
73 :
74 3 : for i in 2:n-1
75 294 : dx[i] = ((x[i+1] - x[i]) / (t[i+1] - t[i]) +
76 : (x[i] - x[i-1]) / (t[i] - t[i-1])) / 2
77 585 : end
78 :
79 3 : hermitespline(T.(t), collect(zip(x, dx)))
80 : end
81 :
82 :
83 : """
84 : Create a Hermite spline from positions `xs` by sampling tangents
85 : from finite differences. This constructs a Catmull-Rom spline given as
86 : [`AbstractHermiteSpline`](@ref). The option `template` argument
87 : determines the concrete type. Tangents at the boundary are computed as
88 : forward or backward differences, i.e., the first and the last segment
89 : determine the respective tangent directions.
90 :
91 : hs = catmullrom(xs[, span=(0, 1), parametrization=:uniform])
92 :
93 : Valid options for `parametrization` are `:uniform`, `:chordal`, or
94 : `:centripetal`. The knots are always scaled that to match the bounds
95 : `t0, t1 = span...`.
96 :
97 : hs = catmullrom(xs[, ts=[...]])
98 :
99 : Knot vector `ts` determines parametrization.
100 :
101 : See also [`AbstractHermiteSpline`](@ref)
102 : """ catmullrom
|