3#include <Core/Containers/VectorArray.hpp>
4#include <Core/Math/Math.hpp>
5#include <Core/RaCore.hpp>
22template <u
int D, u
int K = 2>
31 using Vector =
typename Eigen::Matrix<Scalar, D, 1>;
47 inline void setType( Type type );
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,
89 static inline Vector evalRec( Scalar u,
104template <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 );
115template <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];
133template <u
int D, u
int K>
141template <u
int D, u
int K>
150template <u
int D, u
int K>
152 u = std::clamp( u, Scalar( 0 ), Scalar( 1 ) );
153 return eval( u, m_points, m_node, K );
158template <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 );
166template <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" );
175template <u
int D, u
int K>
179 setNodeToOpenUniform();
189template <u
int D, u
int K>
190inline 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 );
202template <u
int D, u
int K>
203inline 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 );
219template <u
int D, u
int K>
220inline typename Spline<D, K>::Vector Spline<D, K>::eval( Scalar u,
221 const Core::VectorArray<Vector>& points,
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 ) {
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 );
249template <u
int D, u
int K>
250inline typename Spline<D, K>::Vector Spline<D, K>::evalRec( Scalar u,
251 const Core::VectorArray<Vector>& points,
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;
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)
This class implements ContainerIntrospectionInterface for AlignedStdVector.
@ Geometry
"Geometry" render objects are those loaded using Radium::IO and generated by GeometrySystem
hepler function to manage enum as underlying types in VariableSet