Cinder  0.8.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
BSpline.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010, The Barbarian Group
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
6  the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this list of conditions and
9  the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
11  the following disclaimer in the documentation and/or other materials provided with the distribution.
12 
13  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
14  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
15  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
17  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
18  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
19  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
20  POSSIBILITY OF SUCH DAMAGE.
21 
22  Significant Portions Copyright:
23  Geometric Tools, LLC
24  Copyright (c) 1998-2010
25  Distributed under the Boost Software License, Version 1.0.
26  http://www.boost.org/LICENSE_1_0.txt
27  http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
28 */
29 
30 #pragma once
31 
32 #include <vector>
33 #include "cinder/Vector.h"
34 
35 namespace cinder {
36 
38 {
39  public:
40  BSplineBasis();
41 
42  // Open uniform or periodic uniform. The knot array is internally
43  // generated with equally spaced elements.
44  BSplineBasis( int aNumCtrlPoints, int iDegree, bool bOpen );
45  void create( int aNumCtrlPoints, int iDegree, bool bOpen );
46 
47  // Open nonuniform. The knot array must have n-d elements. The elements
48  // must be nondecreasing. Each element must be in [0,1]. The caller is
49  // responsible for deleting afKnot. An internal copy is made, so to
50  // dynamically change knots you must use the setKnot function.
51  BSplineBasis( int aNumCtrlPoints, int iDegree, const float* afKnot );
52  void create( int aNumCtrlPoints, int iDegree, const float* afKnot );
53 
54  BSplineBasis( const BSplineBasis &basis );
55  BSplineBasis& operator=( const BSplineBasis &basis );
56 
57  ~BSplineBasis();
58 
59  int getNumControlPoints() const;
60  int getDegree() const;
61  bool isOpen() const;
62  bool isUniform() const;
63 
64  // The knot values can be changed only if the basis function is nonuniform
65  // and the input index is valid (0 <= i <= n-d-1). If these conditions
66  // are not satisfied, getKnot returns MAX_REAL.
67  void setKnot( int i, float fKnot );
68  float getKnot( int i ) const;
69 
70  // access basis functions and their derivatives
71  float getD0( int i ) const;
72  float getD1( int i ) const;
73  float getD2( int i ) const;
74  float getD3( int i ) const;
75 
76  // evaluate basis functions and their derivatives
77  void compute( float fTime, unsigned int uiOrder, int &riMinIndex, int &riMaxIndex ) const;
78 
79  protected:
80  int initialize( int iNumCtrlPoints, int iDegree, bool bOpen );
81  float** allocate() const;
82  void deallocate( float** aafArray );
83 
84  // Determine knot index i for which knot[i] <= rfTime < knot[i+1].
85  int getKey( float& rfTime ) const;
86 
87  int mNumCtrlPoints; // n+1
88  int mDegree; // d
89  float *mKnots; // knot[n+d+2]
90  bool mOpen, mUniform;
91 
92  // Storage for the basis functions and their derivatives first three
93  // derivatives. The basis array is always allocated by the constructor
94  // calls. A derivative basis array is allocated on the first call to a
95  // derivative member function.
96  float **m_aafBD0; // bd0[d+1][n+d+1]
97  mutable float **m_aafBD1; // bd1[d+1][n+d+1]
98  mutable float **m_aafBD2; // bd2[d+1][n+d+1]
99  mutable float **m_aafBD3; // bd3[d+1][n+d+1]
100 };
101 
102 template<typename T>
103 class BSpline
104 {
105  public:
106  // Construction and destruction. The caller is responsible for deleting
107  // the input arrays if they were dynamically allocated. Internal copies
108  // of the arrays are made, so to dynamically change control points or
109  // knots you must use the 'setControlPoint', 'getControlPoint', and
110  // 'Knot' member functions.
111 
112  // Uniform spline. The number of control points is n+1 >= 2. The degree
113  // of the B-spline is d and must satisfy 1 <= d <= n. The knots are
114  // implicitly calculated in [0,1]. If bOpen is 'true', the spline is
115  // open and the knots are
116  // t[i] = 0, 0 <= i <= d
117  // (i-d)/(n+1-d), d+1 <= i <= n
118  // 1, n+1 <= i <= n+d+1
119  // If bOpen is 'false', the spline is periodic and the knots are
120  // t[i] = (i-d)/(n+1-d), 0 <= i <= n+d+1
121  // If bLoop is 'true', extra control points are added to generate a closed
122  // curve. For an open spline, the control point array is reallocated and
123  // one extra control point is added, set to the first control point
124  // C[n+1] = C[0]. For a periodic spline, the control point array is
125  // reallocated and the first d points are replicated. In either case the
126  // knot array is calculated accordingly.
127  BSpline( const std::vector<T> &points, int degree, bool loop, bool open );
128 
129  // Open, nonuniform spline. The knot array must have n-d elements. The
130  // elements must be nondecreasing. Each element must be in [0,1].
131  BSpline() : mCtrlPoints( 0 ), mNumCtrlPoints( -1 ) {}
132  BSpline( int numControlPoints, const T *controlPoints, int degree, bool loop, const float *knots );
133  BSpline( const BSpline &bspline );
134  BSpline& operator=( const BSpline &bspline );
135 
136  ~BSpline();
137 
138  int getNumControlPoints() const { return mNumCtrlPoints; }
139  int getDegree() const { return mBasis.getDegree(); }
140  int getNumSpans() const { return mNumCtrlPoints - mBasis.getDegree(); }
141  bool isOpen() const { return mBasis.isOpen(); }
142  bool isUniform() const { return mBasis.isUniform(); }
143  bool isLoop() const { return mLoop; }
144 
145  // Control points may be changed at any time. The input index should be
146  // valid (0 <= i <= n). If it is invalid, getControlPoint returns a
147  // vector whose components are all MAX_REAL.
148  void setControlPoint( int i, const T &rkCtrl );
149  T getControlPoint( int i ) const;
150 
151  // The knot values can be changed only if the basis function is nonuniform
152  // and the input index is valid (0 <= i <= n-d-1). If these conditions
153  // are not satisfied, getKnot returns MAX_REAL.
154  void setKnot( int i, float fKnot );
155  float getKnot( int i ) const;
156 
157  // The spline is defined for 0 <= t <= 1. If a t-value is outside [0,1],
158  // an open spline clamps t to [0,1]. That is, if t > 1, t is set to 1;
159  // if t < 0, t is set to 0. A periodic spline wraps to to [0,1]. That
160  // is, if t is outside [0,1], then t is set to t-floor(t).
161  T getPosition( float t ) const;
162  T getDerivative( float t ) const;
163  T getSecondDerivative( float t ) const;
164  T getThirdDerivative( float t ) const;
165  typename T::TYPE getSpeed( float t ) const { return getDerivative( t ).length(); }
166 
167  float getLength( float fT0, float fT1 ) const;
168 
169  // If you need position and derivatives at the same time, it is more
170  // efficient to call these functions. Pass the addresses of those
171  // quantities whose values you want. You may pass 0 in any argument
172  // whose value you do not want.
173  void get( float t, T *position, T *firstDerivative = NULL, T *secondDerivative = NULL, T *thirdDerivative = NULL ) const;
175  float getTime( float length ) const;
176 
177  // Access the basis function to compute it without control points. This
178  // is useful for least squares fitting of curves.
180 
181  protected:
182  // Replicate the necessary number of control points when the create
183  // function has bLoop equal to true, in which case the spline curve must
184  // be a closed curve.
185  void createControl( const T *akCtrlPoint );
186 
188  T *mCtrlPoints; // ctrl[n+1]
189  bool mLoop;
191  int mReplicate; // the number of replicated control points
192 };
193 
196 
197 } // namespace cinder
void setKnot(int i, float fKnot)
Definition: BSpline.cpp:504
BSpline()
Definition: BSpline.h:131
void create(int aNumCtrlPoints, int iDegree, bool bOpen)
Definition: BSpline.cpp:106
T getDerivative(float t) const
Definition: BSpline.cpp:636
int mNumCtrlPoints
Definition: BSpline.h:187
float * mKnots
Definition: BSpline.h:89
BSpline< Vec3f > BSpline3f
Definition: BSpline.h:195
float getD1(int i) const
Definition: BSpline.cpp:195
int getNumSpans() const
Definition: BSpline.h:140
float ** m_aafBD0
Definition: BSpline.h:96
int mDegree
Definition: BSpline.h:88
T getControlPoint(int i) const
Definition: BSpline.cpp:494
int mReplicate
Definition: BSpline.h:191
bool isOpen() const
Definition: BSpline.cpp:177
void setKnot(int i, float fKnot)
Definition: BSpline.cpp:243
T getPosition(float t) const
Definition: BSpline.cpp:628
float ** m_aafBD1
Definition: BSpline.h:97
bool isLoop() const
Definition: BSpline.h:143
BSplineBasis & getBasis()
Definition: BSpline.cpp:622
float getD2(int i) const
Definition: BSpline.cpp:201
float ** m_aafBD3
Definition: BSpline.h:99
BSpline & operator=(const BSpline &bspline)
Definition: BSpline.cpp:443
BSplineBasis mBasis
Definition: BSpline.h:190
BSplineBasis & operator=(const BSplineBasis &basis)
Definition: BSpline.cpp:81
int getDegree() const
Definition: BSpline.h:139
void deallocate(float **aafArray)
void compute(float fTime, unsigned int uiOrder, int &riMinIndex, int &riMaxIndex) const
Definition: BSpline.cpp:305
int getNumControlPoints() const
Definition: BSpline.h:138
float ** allocate() const
Definition: BSpline.cpp:213
BSplineBasis()
Definition: BSpline.cpp:62
~BSplineBasis()
Definition: BSpline.cpp:157
int getKey(float &rfTime) const
Definition: BSpline.cpp:268
bool isUniform() const
Definition: BSpline.h:142
GLuint GLsizei GLsizei * length
Definition: GLee.h:2313
~BSpline()
Definition: BSpline.cpp:462
float getKnot(int i) const
Definition: BSpline.cpp:510
Definition: BSpline.h:37
float getKnot(int i) const
Definition: BSpline.cpp:254
void setControlPoint(int i, const T &rkCtrl)
Definition: BSpline.cpp:480
int getDegree() const
Definition: BSpline.cpp:171
T getThirdDerivative(float t) const
Definition: BSpline.cpp:652
float getD0(int i) const
Definition: BSpline.cpp:189
bool mOpen
Definition: BSpline.h:90
Definition: BSpline.h:103
bool isUniform() const
Definition: BSpline.cpp:183
float getLength(float fT0, float fT1) const
Definition: BSpline.cpp:613
float getD3(int i) const
Definition: BSpline.cpp:207
bool isOpen() const
Definition: BSpline.h:141
int getNumControlPoints() const
Definition: BSpline.cpp:166
T * mCtrlPoints
Definition: BSpline.h:188
float ** m_aafBD2
Definition: BSpline.h:98
int initialize(int iNumCtrlPoints, int iDegree, bool bOpen)
Definition: BSpline.cpp:223
bool mUniform
Definition: BSpline.h:90
float getTime(float length) const
Returns the time associated with an arc length in the range [0,getLength(0,1)].
Definition: BSpline.cpp:563
T::TYPE getSpeed(float t) const
Definition: BSpline.h:165
GLsizei const GLfloat * points
Definition: GLee.h:6298
bool mLoop
Definition: BSpline.h:189
void createControl(const T *akCtrlPoint)
Definition: BSpline.cpp:468
int mNumCtrlPoints
Definition: BSpline.h:87
BSpline< Vec2f > BSpline2f
Definition: BSpline.h:194
GLdouble GLdouble t
Definition: GLee.h:1426
T getSecondDerivative(float t) const
Definition: BSpline.cpp:644