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