3 #include <Core/Containers/VectorArray.hpp>
4 #include <Core/Math/Math.hpp>
5 #include <Core/RaCore.hpp>
22 template <u
int D, u
int K = 2>
31 using Vector =
typename Eigen::Matrix<Scalar, D, 1>;
51 inline Vector
f( Scalar u )
const;
54 inline Vector
df( Scalar u )
const;
61 inline void assertSplines()
const;
65 inline void setNodalVector();
68 inline void setNodeToUniform();
71 inline void setNodeToOpenUniform();
83 static inline Vector eval( Scalar u,
85 const std::vector<Scalar>& node,
89 static inline Vector evalRec( Scalar u,
91 const std::vector<Scalar>& node,
100 std::vector<Scalar> m_node;
104 template <u
int D, u
int K>
106 static_assert( K >= 2,
"Order must be at least two" );
107 m_points.resize( K, Vector::Zero() );
108 m_vecs.resize( K - 1, Vector::Zero() );
109 m_node.resize( K + K, 0.f );
115 template <u
int D, u
int K>
119 m_vecs.resize( points.size() - 1, Vector::Zero() );
120 for ( uint i = 0; i < m_vecs.size(); ++i ) {
121 m_vecs[i] = m_points[i + 1] - m_points[i];
126 for ( uint i = 0; i < m_vecs.size(); ++i ) {
127 m_vecs[i] /= m_node[K + i] - m_node[i + 1];
133 template <u
int D, u
int K>
141 template <u
int D, u
int K>
150 template <u
int D, u
int K>
152 u = std::clamp( u, Scalar( 0 ), Scalar( 1 ) );
153 return eval( u, m_points, m_node, K );
158 template <u
int D, u
int K>
160 u = std::clamp( u, Scalar( 0 ), Scalar( 1 ) );
161 return eval( u, m_vecs, m_node, K - 1, 1 ) * Scalar( K - 1 );
166 template <u
int D, u
int K>
168 CORE_ASSERT( m_points.size() >= K,
"Not enough points" );
169 CORE_ASSERT( m_node.size() == ( K + m_points.size() ),
"Wrong nodal vector size" );
170 CORE_ASSERT( m_points.size() == ( m_vecs.size() + 1 ),
"Wrong point / diffs size" );
175 template <u
int D, u
int K>
179 setNodeToOpenUniform();
189 template <u
int D, u
int K>
190 inline void Spline<D, K>::setNodeToUniform() {
191 const uint n = m_points.size() - 1;
192 m_node.resize( K + n + 1 );
194 Scalar step = 1.f / Scalar( n - K + 2 );
195 for ( uint i = 0; i < m_node.size(); ++i ) {
196 m_node[i] = Scalar( i ) * step - step * (Scalar)( K - 1 );
202 template <u
int D, u
int K>
203 inline void Spline<D, K>::setNodeToOpenUniform() {
204 m_node.resize( K + m_points.size() );
207 for ( uint i = 0; i < m_node.size(); ++i ) {
208 if ( i < K ) { m_node[i] = 0.f; }
209 else if ( i >= ( m_points.size() + 1 ) ) { m_node[i] = 1.f; }
211 m_node[i] = Scalar( acc ) / Scalar( m_points.size() + 1 - K );
219 template <u
int D, u
int K>
220 inline typename Spline<D, K>::Vector Spline<D, K>::eval( Scalar u,
221 const Core::VectorArray<Vector>& points,
222 const std::vector<Scalar>& node,
225 CORE_ASSERT( k >= 2,
"K must be at least 2" );
226 CORE_ASSERT( points.size() >= k,
"Not enough points" );
230 while ( u > node[dec + k + off] ) {
235 Core::VectorArray<Vector> pOut( k, Vector::Zero() );
236 for ( uint i = dec, j = 0; i < ( dec + k ); ++i, ++j ) {
240 std::vector<Scalar> nodeOut( k + k - 2, Scalar( 0 ) );
241 for ( uint i = ( dec + 1 ), j = 0; i < ( dec + k + k - 1 ); ++i, ++j ) {
242 nodeOut[j] = node[i + off];
244 return evalRec( u, pOut, nodeOut, k );
249 template <u
int D, u
int K>
250 inline typename Spline<D, K>::Vector Spline<D, K>::evalRec( Scalar u,
251 const Core::VectorArray<Vector>& points,
252 const std::vector<Scalar>& node,
254 if ( points.size() == 1 ) {
return points[0]; }
257 Core::VectorArray<Vector> pOut( k - 1, Vector::Zero() );
259 for ( uint i = 0; i < ( k - 1 ); ++i ) {
260 const Scalar n0 = node[i + k - 1];
261 const Scalar n1 = node[i];
262 const Scalar f0 = ( n0 - u ) / ( n0 - n1 );
263 const Scalar f1 = ( u - n1 ) / ( n0 - n1 );
265 pOut[i] = points[i] * f0 + points[i + 1] * f1;
268 std::vector<Scalar> nodeOut( node.size() - 2 );
270 for ( uint i = 1; i < node.size() - 1; ++i ) {
271 nodeOut[i - 1] = node[i];
273 return evalRec( u, pOut, nodeOut, k - 1 );
Handling spline curves of arbitrary dimensions.
@ OPEN_UNIFORM
Connected to the first and last control points.
const Core::VectorArray< Vector > & getCtrlPoints() const
Get the control points of the spline.
void setCtrlPoints(const Core::VectorArray< Vector > &points)
Set the position of the spline control points.
Vector df(Scalar u) const
Evaluate speed of the spline.
void setType(Type type)
The the nodal vector type.
Spline(Type type=OPEN_UNIFORM)