KrisLibrary  1.0.0
spline.h
1 #ifndef SPLINE_SPLINE_H
2 #define SPLINE_SPLINE_H
3 
4 #include "basis.h"
5 #include <KrisLibrary/math3d/primitives.h> //only used for TCB
6 #include <assert.h>
7 #include <vector>
8 class File;
9 using namespace Math3D;
10 
11 const Real Third = Real(1.0/3.0);
12 
14 {
16  SplineIterator(Real t);
17  SplineIterator(Real t, int seg);
18 
19  Real t;
20  int seg;
21 };
22 
24 {
25  public:
27 
28  enum InfinityBehavior {
29  InfinityEnd = 0x0,
30  InfinityLoop = 0x1
31  };
32 
33  enum TimeStatus {
34  Before,
35  During,
36  After
37  };
38 
39  virtual void init(int numKeys);
40  virtual void resize(int numKeys);
41  virtual void cleanup();
42 
43  const SplineTimeBase& operator = (const SplineTimeBase&);
44  void copyTimeBase(const SplineTimeBase&);
45  virtual bool Read(File&);
46  virtual bool Write(File&) const;
47 
48  //seek is pretty important -- it sets the iterator to an infinity mapped time, and the correct segment for that time
49  TimeStatus seek(SplineIterator&) const;
50 
51  inline int getNumKeys() const { return (int)times.size(); }
52  inline int getNumSegments() const { return (int)times.size()-1; }
53  Real& getTime(int i) { return times[i]; }
54  const Real& getTime(int i) const { return times[i]; }
55 
56  inline Real beginTime() const { return times[0]; }
57  inline Real endTime() const { return times[times.size()-1]; }
58  inline Real length() const { return endTime() - beginTime(); }
59  inline int isLooping() const { return flags & InfinityLoop; }
60  inline void setInfinityBehavior(InfinityBehavior b) { flags = b; }
61  void timeTransform(Real scale, Real offset);
62 
63  protected:
64  //evaluation helpers
65  inline Real mapSegmentU(int seg, Real t) const
66  {
67  return (t - times[seg])/(times[seg+1] - times[seg]);
68  }
69  Real infinityMap(Real t) const;
70 
71  std::vector<Real> times;
72  int flags;
73 };
74 
75 
76 template <class Point>
77 struct KeyHermite
78 {
79  Point pt;
80  Point tin,tout;
81 };
82 
83 template <class Point>
85 {
86  Point pt;
87  Real tension;
88 };
89 
90 template <class Point>
92 {
93  Point pt;
94  Point cpin,cpout;
95 };
96 
97 template <class Point>
98 struct KeyTCB
99 {
100  Point pt;
101  Real t,c,b;
102 };
103 
104 
105 template <class Key,class Point>
107 {
108  public:
109  SplineBase();
110  void init(int numKeys);
111  void cleanup();
112  int insertKey(Real time,int pos=-1);
113  void deleteKey(int key);
114 
115  void evaluate(SplineIterator&, Point& out) const;
116  inline Key& getKey(int i) { return keys[i]; }
117  inline const Key& getKey(int i) const { return keys[i]; }
118 
119  void operator = (const SplineBase<Key,Point>&);
120  virtual bool Read(File&);
121  virtual bool Write(File&) const;
122 
123  virtual void eval(int seg, Real u, Point& out) const = 0;
124 
125  std::vector<Key> keys;
126 };
127 
128 template <class Point>
129 class SplineLinear : public SplineBase<Point,Point>
130 {
131  public:
133  inline Point& getPoint(int i) { return ParentT::points[i]; }
134  inline const Point& getPoint(int i) const { return ParentT::points[i]; }
135  inline int getNumKeys() const { return ParentT::getNumKeys(); }
136  inline int getNumSegments() const { return ParentT::getNumSegments(); }
137 
138  virtual void eval(int seg, Real u, Point& out) const {
139  out = ParentT::keys[seg] + u*(ParentT::keys[seg+1]-ParentT::keys[seg]);
140  }
141 };
142 
143 template <class Point>
144 class SplineHermite : public SplineBase<KeyHermite<Point>,Point>
145 {
146  public:
147  typedef SplineBase<KeyHermite<Point>,Point> ParentT;
148  inline Point& getPoint(int i) { return ParentT::keys[i].pt; }
149  inline const Point& getPoint(int i) const { return ParentT::keys[i].pt; }
150  inline int getNumKeys() const { return ParentT::getNumKeys(); }
151  inline int getNumSegments() const { return ParentT::getNumSegments(); }
152 
153  inline Point& getTangentIn(int i) { return ParentT::keys[i].tin; }
154  inline const Point& getTangentIn(int i) const { return ParentT::keys[i].tin; }
155  inline Point& getTangentOut(int i) { return ParentT::keys[i].tout; }
156  inline const Point& getTangentOut(int i) const { return ParentT::keys[i].tout; }
157 
158  virtual void eval(int seg, Real u, Point& out) const {
159  HermiteSplineBasis basis;
160  Real b[4];
161  basis.EvalBasis(u, b);
162  //p0 p1 t0 t1
163  out = b[0]*getPoint(seg) + b[1]*getPoint(seg+1) + b[2]*getTangentOut(seg) + b[3]*getTangentIn(seg+1);
164  }
165 };
166 
167 template <class Point>
168 class SplineCardinal: public SplineBase<KeyCardinal<Point>,Point>
169 {
170  public:
171  typedef SplineBase<KeyCardinal<Point>,Point> ParentT;
172 
173  SplineCardinal();
174 
175  inline Point& getPoint(int i) { return ParentT::keys[i].pt; }
176  inline const Point& getPoint(int i) const { return ParentT::keys[i].pt; }
177  inline int getNumKeys() const { return ParentT::getNumKeys(); }
178  inline int getNumSegments() const { return ParentT::getNumSegments(); }
179 
180  inline Real& getTension(int i) { return ParentT::keys[i].tension; }
181  inline const Real& getTension(int i) const { return ParentT::keys[i].tension; }
182 
183  void toHermite(SplineHermite<Point>& spline) const;
184 
185  virtual void eval(int seg, Real u, Point& out) const {
186  int a = (seg > 0 ? seg-1 : 0);
187  int d = (seg+2 < ParentT::getNumKeys() ? seg+2 : getNumKeys()-1);
188 
189  const Point& P0 = getPoint(seg);
190  const Point& P1 = getPoint(seg+1);
191  Point T0,T1;
192  T0 = getTension(seg)*(P1 - getPoint(a));
193  T1 = getTension(seg)*(getPoint(d) - P0);
194 
195  HermiteSplineBasis basis;
196  Real b[4];
197  basis.EvalBasis(u, b);
198  out = b[0]*P0 + b[1]*P1 + b[2]*T0 + b[3]*T1;
199  }
200 };
201 
202 template <class Point>
203 class SplineBezierCubic : public SplineBase<KeyBezierCubic<Point>,Point>
204 {
205  public:
207 
208  inline Point& getPoint(int i) { return ParentT::keys[i].pt; }
209  inline const Point& getPoint(int i) const { return ParentT::keys[i].pt; }
210  inline int getNumKeys() const { return ParentT::getNumKeys(); }
211  inline int getNumSegments() const { return ParentT::getNumSegments(); }
212 
213  inline Point& getCPIn(int i) { return ParentT::keys[i].cpin; }
214  inline Point& getCPOut(int i) { return ParentT::keys[i].cpin; }
215  inline const Point& getCPIn(int i) const { return ParentT::keys[i].cpout; }
216  inline const Point& getCPOut(int i) const { return ParentT::keys[i].cpout; }
217 
218  void toHermite(SplineHermite<Point>& s) const;
219  void fromHermite(const SplineHermite<Point>& s);
220 
221  virtual void eval(int seg, Real u, Point& out) const {
223  Real b[4];
224  basis.EvalBasis(u, b);
225  //p0 c0 c1 p1
226  out = b[0]*getPoint(seg) + b[1]*getCPOut(seg) + b[2]*getCPIn(seg+1) + b[3]*getPoint(seg+1);
227  }
228 };
229 
230 template <class Point>
231 class SplineTCB: public SplineBase<KeyTCB<Point>,Point>
232 {
233  public:
234  typedef SplineBase<KeyTCB<Point>,Point> ParentT;
235 
236  SplineTCB();
237 
238  void toHermite(SplineHermite<Point>& s) const;
239  //void fromHermite(const SplineHermite<Point>& s);
240 
241  inline Point& getPoint(int i) { return ParentT::keys[i].pt; }
242  inline const Point& getPoint(int i) const { return ParentT::keys[i].pt; }
243  inline int getNumKeys() const { return ParentT::getNumKeys(); }
244  inline int getNumSegments() const { return ParentT::getNumSegments(); }
245 
246  inline Real& getTension(int i) { return ParentT::keys[i].t; };
247  inline Real& getContinuity(int i) { return ParentT::keys[i].c; };
248  inline Real& getBias(int i) { return ParentT::keys[i].b; };
249  inline const Real& getTension(int i) const { return ParentT::keys[i].t; };
250  inline const Real& getContinuity(int i) const { return ParentT::keys[i].c; };
251  inline const Real& getBias(int i) const { return ParentT::keys[i].b; };
252 
253  virtual void eval(int seg, Real u, Point& out) const {
254  int a = (seg > 0 ? seg-1 : 0);
255  int d = (seg+2 < getNumKeys() ? seg+2 : getNumKeys()-1);
256 
257  const Point& P_1 = getPoint(a);
258  const Point& P0 = getPoint(seg);
259  const Point& P1 = getPoint(seg+1);
260  const Point& P2 = getPoint(d);
261 
262  Point T0,T1;
263  T0 = outgoingTangent(seg, P_1, P0, P1);
264  T1 = incomingTangent(seg, P0, P1, P2);
265 
266  HermiteSplineBasis basis;
267  Real b[4];
268  basis.EvalBasis(u, b);
269  out = b[0]*P0 + b[1]*P1 + b[2]*T0 + b[3]*T1;
270  }
271 
272  Point incomingTangent(int seg, const Point& P_1, const Point& P0, const Point& P1) const
273  {
274  Real t,c,b;
275  t = getTension(seg); c = getContinuity(seg); b = getBias(seg);
276  return ((1-t)*(1-c)*(1+b)*Half)*(P0 - P_1) + ((1-t)*(1+c)*(1-b)*Half)*(P1 - P0);
277  }
278 
279  Point outgoingTangent(int seg, const Point& P_1, const Point& P0, const Point& P1) const
280  {
281  Real t,c,b;
282  t = getTension(seg); c = getContinuity(seg); b = getBias(seg);
283  return ((1-t)*(1+c)*(1+b)*Half)*(P0 - P_1) + ((1-t)*(1-c)*(1-b)*Half)*(P1 - P0);
284  }
285 };
286 
287 
288 
289 #endif
Definition: spline.h:98
Definition: spline.h:168
Definition: spline.h:129
Class declarations for useful 3D math types.
Definition: spline.h:23
Definition: spline.h:106
Contains all the definitions in the Math3D package.
Definition: AnyGeometry.h:13
Definition: spline/basis.h:62
Definition: spline.h:231
Definition: spline/basis.h:86
Definition: spline.h:84
Definition: spline.h:203
Definition: spline.h:13
Definition: spline.h:91
Definition: spline.h:77
A cross-platform class for reading/writing binary data.
Definition: File.h:47
Definition: spline.h:144