GteTCBSplineCurve.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <LowLevel/GteLogger.h>
12 
13 namespace gte
14 {
15 
16 template <int N, typename Real>
17 class TCBSplineCurve : public ParametricCurve<N, Real>
18 {
19 public:
20  // Construction and destruction. The object copies the input arrays.
21  // The number of points must be at least 2. To validate construction,
22  // create an object as shown:
23  // TCBSplineCurve<N, Real> curve(parameters);
24  // if (!curve) { <constructor failed, handle accordingly>; }
25  virtual ~TCBSplineCurve();
26  TCBSplineCurve(int numPoints, Vector<N, Real> const* points,
27  Real const* times, Real const* tension, Real const* continuity,
28  Real const* bias);
29 
30  // Member access.
31  inline int GetNumPoints() const;
32  inline Vector<N, Real> const* GetPoints() const;
33  inline Real const* GetTensions() const;
34  inline Real const* GetContinuities() const;
35  inline Real const* GetBiases() const;
36 
37  // Evaluation of the curve. The function supports derivative calculation
38  // through order 3; that is, maxOrder <= 3 is required. If you want
39  // only the position, pass in maxOrder of 0. If you want the position and
40  // first derivative, pass in maxOrder of 1, and so on. The output
41  // 'values' are ordered as: position, first derivative, second derivative,
42  // third derivative.
43  virtual void Evaluate(Real t, unsigned int maxOrder,
44  Vector<N, Real> values[4]) const;
45 
46 protected:
47  // Support for construction.
48  void ComputePoly(int i0, int i1, int i2, int i3);
49 
50  // Determine the index i for which times[i] <= t < times[i+1].
51  void GetKeyInfo(Real t, int& key, Real& dt) const;
52 
53  std::vector<Vector<N, Real>> mPoints;
54  std::vector<Real> mTension, mContinuity, mBias;
55 
56  // Polynomial coefficients. mA are the degree 0 coefficients, mB are
57  // the degree 1 coefficients, mC are the degree 2 coefficients, and mD
58  // are the degree 3 coefficients.
59  std::vector<Vector<N, Real>> mA, mB, mC, mD;
60 };
61 
62 
63 template <int N, typename Real>
65 {
66 }
67 
68 template <int N, typename Real>
70  Vector<N, Real> const* points, Real const* times, Real const* tension,
71  Real const* continuity, Real const* bias)
72  :
73  ParametricCurve<N, Real>(numPoints - 1, times)
74 {
75  if (numPoints < 2 || !points)
76  {
77  LogError("Invalid input.");
78  return;
79  }
80 
81  mPoints.resize(numPoints);
82  mTension.resize(numPoints);
83  mContinuity.resize(numPoints);
84  mBias.resize(numPoints);
85  std::copy(points, points + numPoints, mPoints.begin());
86  std::copy(tension, tension + numPoints, mTension.begin());
87  std::copy(continuity, continuity + numPoints, mContinuity.begin());
88  std::copy(bias, bias + numPoints, mBias.begin());
89 
90  int numSegments = numPoints - 1;
91  mA.resize(numSegments);
92  mB.resize(numSegments);
93  mC.resize(numSegments);
94  mD.resize(numSegments);
95 
96  // For now, treat the first point as if it occurred twice.
97  ComputePoly(0, 0, 1, 2);
98 
99  for (int i = 1; i < numSegments - 1; ++i)
100  {
101  ComputePoly(i - 1, i, i + 1, i + 2);
102  }
103 
104  // For now, treat the last point as if it occurred twice.
105  ComputePoly(numSegments - 2, numSegments - 1, numSegments, numSegments);
106 
107  this->mConstructed = true;
108 }
109 
110 template <int N, typename Real> inline
112 {
113  return static_cast<int>(mPoints.size());
114 }
115 
116 template <int N, typename Real> inline
118 {
119  return &mPoints[0];
120 }
121 
122 template <int N, typename Real> inline
124 {
125  return &mTension[0];
126 }
127 
128 template <int N, typename Real> inline
130 {
131  return &mContinuity[0];
132 }
133 
134 template <int N, typename Real> inline
136 {
137  return &mBias[0];
138 }
139 
140 template <int N, typename Real>
141 void TCBSplineCurve<N, Real>::Evaluate(Real t, unsigned int maxOrder,
142  Vector<N, Real> values[4]) const
143 {
144  if (!this->mConstructed)
145  {
146  // Errors were already generated during construction.
147  for (unsigned int order = 0; order < 4; ++order)
148  {
149  values[order].MakeZero();
150  }
151  return;
152  }
153 
154  int key;
155  Real dt;
156  GetKeyInfo(t, key, dt);
157  dt /= (this->mTime[key + 1] - this->mTime[key]);
158 
159  // Compute position.
160  values[0] = mA[key] + dt * (mB[key] + dt * (mC[key] + dt * mD[key]));
161  if (maxOrder >= 1)
162  {
163  // Compute first derivative.
164  values[1] = mB[key] + dt * (mC[key] * ((Real)2) + mD[key] *
165  (((Real)3) * dt));
166  if (maxOrder >= 2)
167  {
168  // Compute second derivative.
169  values[2] = mC[key] * ((Real)2) + mD[key] * (((Real)6) * dt);
170  if (maxOrder == 3)
171  {
172  values[3] = ((Real)6) * mD[key];
173  }
174  else
175  {
176  values[3].MakeZero();
177  }
178  }
179  }
180 }
181 
182 template <int N, typename Real>
183 void TCBSplineCurve<N, Real>::ComputePoly(int i0, int i1, int i2, int i3)
184 {
185  Vector<N, Real> diff = mPoints[i2] - mPoints[i1];
186  Real dt = this->mTime[i2] - this->mTime[i1];
187 
188  // Build multipliers at P1.
189  Real oneMinusT0 = (Real)1 - mTension[i1];
190  Real oneMinusC0 = (Real)1 - mContinuity[i1];
191  Real onePlusC0 = (Real)1 + mContinuity[i1];
192  Real oneMinusB0 = (Real)1 - mBias[i1];
193  Real onePlusB0 = (Real)1 + mBias[i1];
194  Real adj0 = ((Real)2)*dt / (this->mTime[i2] - this->mTime[i0]);
195  Real out0 = ((Real)0.5)*adj0*oneMinusT0*onePlusC0*onePlusB0;
196  Real out1 = ((Real)0.5)*adj0*oneMinusT0*oneMinusC0*oneMinusB0;
197 
198  // Build outgoing tangent at P1.
199  Vector<N, Real> tOut = out1*diff + out0*(mPoints[i1] - mPoints[i0]);
200 
201  // Build multipliers at point P2.
202  Real oneMinusT1 = (Real)1 - mTension[i2];
203  Real oneMinusC1 = (Real)1 - mContinuity[i2];
204  Real onePlusC1 = (Real)1 + mContinuity[i2];
205  Real oneMinusB1 = (Real)1 - mBias[i2];
206  Real onePlusB1 = (Real)1 + mBias[i2];
207  Real adj1 = ((Real)2)*dt / (this->mTime[i3] - this->mTime[i1]);
208  Real in0 = ((Real)0.5)*adj1*oneMinusT1*oneMinusC1*onePlusB1;
209  Real in1 = ((Real)0.5)*adj1*oneMinusT1*onePlusC1*oneMinusB1;
210 
211  // Build incoming tangent at P2.
212  Vector<N, Real> tIn = in1*(mPoints[i3] - mPoints[i2]) + in0*diff;
213 
214  mA[i1] = mPoints[i1];
215  mB[i1] = tOut;
216  mC[i1] = ((Real)3)*diff - ((Real)2)*tOut - tIn;
217  mD[i1] = ((Real)-2)*diff + tOut + tIn;
218 }
219 
220 template <int N, typename Real>
221 void TCBSplineCurve<N, Real>::GetKeyInfo(Real t, int& key, Real& dt) const
222 {
223  int numSegments = static_cast<int>(mA.size());
224  if (t <= this->mTime[0])
225  {
226  key = 0;
227  dt = (Real)0;
228  }
229  else if (t >= this->mTime[numSegments])
230  {
231  key = numSegments - 1;
232  dt = this->mTime[numSegments] - this->mTime[numSegments - 1];
233  }
234  else
235  {
236  for (int i = 0; i < numSegments; ++i)
237  {
238  if (t < this->mTime[i + 1])
239  {
240  key = i;
241  dt = t - this->mTime[i];
242  break;
243  }
244  }
245  }
246 }
247 
248 
249 }
void MakeZero()
Definition: GteVector.h:279
GLfixed GLfixed GLint GLint order
Definition: glext.h:4927
Real const * GetContinuities() const
std::vector< Vector< N, Real > > mA
void GetKeyInfo(Real t, int &key, Real &dt) const
std::vector< Vector< N, Real > > mB
std::vector< Real > mTime
Real const * GetBiases() const
Real const * GetTensions() const
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1597
std::vector< Real > mTension
GLfloat bias
Definition: glext.h:7490
virtual void Evaluate(Real t, unsigned int maxOrder, Vector< N, Real > values[4]) const
TCBSplineCurve(int numPoints, Vector< N, Real > const *points, Real const *times, Real const *tension, Real const *continuity, Real const *bias)
GLfixed GLfixed GLint GLint GLfixed points
Definition: glext.h:4927
std::vector< Real > mContinuity
#define LogError(message)
Definition: GteLogger.h:92
GLdouble GLdouble t
Definition: glext.h:239
std::vector< Vector< N, Real > > mD
Vector< N, Real > const * GetPoints() const
GLsizei GLsizei numSegments
Definition: glext.h:9703
void ComputePoly(int i0, int i1, int i2, int i3)
std::vector< Vector< N, Real > > mPoints
std::vector< Vector< N, Real > > mC
std::vector< Real > mBias


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:01