Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

Spline.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 /*========================================================================
00003     spline.h : Implementation  of Uniform and Non-Uniform Hermite Splines 
00004   ------------------------------------------------------------------------
00005     Copyright (C) 1999-2002  James R. Bruce
00006     School of Computer Science, Carnegie Mellon University
00007   ------------------------------------------------------------------------
00008     This software is distributed under the GNU General Public License,
00009     version 2.  If you do not have a copy of this licence, visit
00010     www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
00011     Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
00012     in the hope that it will be useful, but WITHOUT ANY WARRANTY,
00013     including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00014     ========================================================================*/
00015 
00016 #ifndef __SPLINE_H__
00017 #define __SPLINE_H__
00018 
00019 #define HSPLINE HermiteSplineSegment<point,fnum>
00020 #define NUHSPLINE NonUniformHermiteSplineSegment<point,fnum>
00021 
00022 #define HSPLINE_TEM    template <class point,class fnum>
00023 #define NUHSPLINE_TEM  template <class point,class fnum>
00024 
00025 // #define TSPLINE  HermiteSplineSegment<fnum,fnum>
00026 // #define CRSPLINE CatmullRomSpline<point,fnum>
00027 // #define CRSPLINE_TEM template <class point,class fnum>
00028 
00029 #define EPS 1E-6
00030 
00031 // #define DEBUG
00032 
00033 HSPLINE_TEM
00034 class HermiteSplineSegment{
00035 public:
00036   HermiteSplineSegment() : a(),b(),c(),d() {}
00037   point a,b,c,d;
00038 public:
00039   void create(point x1,point x2,point dx1,point dx2);
00040   void create(point *pts,int num,int i);
00041   point eval(fnum u);
00042   point eval_deriv(fnum u);
00043 };
00044 
00045 NUHSPLINE_TEM
00046 class NonUniformHermiteSplineSegment{
00047 public:
00048   NonUniformHermiteSplineSegment() : a(),b(),c(),d(),t() {}
00049   point a,b,c,d;
00050   fnum t;
00051 public:
00052   void create(point x0,point x1,point dx0,point dx1,fnum t1);
00053   void create(point *pts,double t1,int num,int i);
00054   point eval(fnum u);
00055   point eval_deriv(fnum u);
00056 };
00057 
00058 /*
00059 template <class point,class fnum>
00060 class CatmullRomSpline{
00061   typedef HermiteSplineSegment<point,fnum> segment;
00062   segment *seg;
00063   int num_segs,max;
00064   double 
00065 public:
00066   CatmullRomSpline()
00067     {seg=NULL; num_segs=max=0;}
00068 
00069   bool allocate(int num);
00070   int find_segment(fnum t);
00071 
00072   //  void create(point *pts,num *time,point dx1,point dx2,int num);
00073   bool create(point *pts,fnum *time,int num);
00074   bool create_loop(point *pts,fnum *time,int num);
00075   point eval(fnum t);
00076   point eval_deriv(fnum t);
00077 };
00078 */
00079 
00080 
00081 //==== Hermite Spline Segment Implementation ====//
00082 
00083 HSPLINE_TEM
00084 void HSPLINE::create(point x1,point x2,point dx1,point dx2)
00085 {
00086   // a = (x1 *  2) + (x2 * -2) + (dx1 *  1) + (dx2 *  1);
00087   // b = (x1 * -3) + (x2 *  3) + (dx1 * -2) + (dx2 * -1);
00088   a = (x1 - x2)*2 + dx1 + dx2;
00089   b = (x2 - x1)*3 - dx1*2 - dx2;
00090   c = dx1;
00091   d = x1;
00092 }
00093 
00094 HSPLINE_TEM
00095 void HSPLINE::create(point *pts,int num,int i)
00096 {
00097   point x1,x2,dx1,dx2;
00098 
00099   x1 = pts[(i + 1) % num];
00100   x2 = pts[(i + 2) % num];
00101   dx1 = x2 - pts[(i + 0) % num];
00102   dx2 = pts[(i + 3) % num] - x1;
00103 
00104   create(x1,x2,dx1,dx2);
00105 }
00106 
00107 HSPLINE_TEM
00108 point HSPLINE::eval(fnum u)
00109 {
00110   fnum u2,u3;
00111   point p;
00112 
00113   u2 = u*u;
00114   u3 = u*u*u;
00115 
00116   p = a*u3 + b*u2 + c*u + d;
00117 
00118   return(p);
00119 }
00120 
00121 HSPLINE_TEM
00122 point HSPLINE::eval_deriv(fnum u)
00123 {
00124   fnum u2;
00125   point p;
00126 
00127   u2 = u*u;
00128 
00129   p = a*(3*u2) + b*(2*u) + c;
00130 
00131   return(p);
00132 }
00133 
00134 
00135 //==== Non-Uniform Hermite Spline Segment Implementation ====//
00136 
00137 NUHSPLINE_TEM
00138 void NUHSPLINE::create(point x0,point x1,point dx0,point dx1,fnum t1)
00139 {
00140   t = t1;
00141   d = x0;
00142   c = dx0;
00143   // b = ((x1-c*t1-d)*3 - dx1*t1) / (t1*t1);
00144   // a = (dx1 - b*t1*2 - c) / (t1*t1*3);
00145   b = ((x1 - x0)*3 - dx0*(t*2) - dx1*t) / (t*t);
00146   a = (dx1 - dx0 - b*(t*2)) / (3*t*t);
00147 
00148 #ifdef DEBUG
00149   /*  point tx0,tx1,tdx0,tdx1;
00150 
00151   tx0 = eval(0.0) - x0;
00152   tx1 = eval(t1) - x1;
00153   tdx0 = eval_deriv(0.0) - dx0;
00154   tdx1 = eval_deriv(t1) - dx1;
00155 
00156   / *
00157   printf("Error: %f\n",
00158          tx0.sqlength() + tx1.sqlength() +
00159          tdx0.sqlength() + tdx1.sqlength());
00160   * /
00161 
00162   printf("Error: x0(%f,%f,%f) x1(%f,%f,%f) dx0(%f,%f,%f) dx1(%f,%f,%f)\n",
00163          tx0.x, tx0.y, tx0.z,
00164          tx1.x, tx1.y, tx1.z,
00165          tdx0.x, tdx0.y, tdx0.z,
00166          tdx1.x, tdx1.y, tdx1.z);*/
00167 #endif
00168 }
00169 
00170 NUHSPLINE_TEM
00171 void NUHSPLINE::create(point *pts,double t1,int num,int i)
00172 // Not 100% sure this is a logical thing to calculate
00173 {
00174   point x0,x1,dx0,dx1;
00175 
00176   x0 = pts[(i + 1) % num];
00177   x1 = pts[(i + 2) % num];
00178   dx0 = (x1 - pts[(i + 0) % num]) / (2*t1);
00179   dx1 = (pts[(i + 3) % num] - x0) / (2*t1);
00180 
00181   create(x0,x1,dx0,dx1,t1);
00182 }
00183 
00184 NUHSPLINE_TEM
00185 point NUHSPLINE::eval(fnum u)
00186 {
00187   fnum u2,u3;
00188   point p;
00189 
00190   u2 = u*u;
00191   u3 = u*u*u;
00192 
00193   p = a*u3 + b*u2 + c*u + d;
00194 
00195   return(p);
00196 }
00197 
00198 NUHSPLINE_TEM
00199 point NUHSPLINE::eval_deriv(fnum u)
00200 {
00201   fnum u2;
00202   point p;
00203 
00204   u2 = u*u;
00205 
00206   p = a*(3*u2) + b*(2*u) + c;
00207 
00208   return(p);
00209 }
00210 
00211 //==== Catmull-Rom Spline Implementation ====//
00212 
00213 /*
00214 HSPLINE_TEM
00215 void makeSpline(HSPLINE *seg,const point *pts,int num)
00216 {
00217   int i;
00218 
00219   for(i=0; i<num-3; i++){
00220     seg[i].create(pts[i+1],pts[i+2],pts[i+2] - pts[i+0],pts[i+3] - pts[i+1]);
00221   }
00222 }
00223 
00224 HSPLINE_TEM
00225 point evalSpline(HSPLINE *seg,int num,double t)
00226 {
00227   int s;
00228 
00229   if(t >= num) t = num - EPS;
00230   if(t <= 0.0) t = 0.0;
00231   s = (int)t;
00232 
00233   return(seg[s].eval(t - s));
00234 }
00235 
00236 HSPLINE_TEM
00237 void makeSpline(HSPLINE *seg,TSPLINE *tseg,const point *pts,fnum time,int num)
00238 {
00239   int i;
00240 
00241   for(i=0; i<num-3; i++){
00242     tseg[i].create(time[i+1],time[i+2],time[i+2] - time[i+0],time[i+3] - time[i+1]);
00243     seg[i].create(pts[i+1],pts[i+2],pts[i+2] - pts[i+0],pts[i+3] - pts[i+1]);
00244   }
00245 }
00246 
00247 HSPLINE_TEM
00248 point evalSpline(HSPLINE *seg,TSPLINE *tseg,int num,double t)
00249 {
00250   int s;
00251 
00252   // find time to evaluate point spline
00253   if(t >= num) t = num - EPS;
00254   if(t <= 0.0) t = 0.0;
00255   s = (int)t;
00256   t = tseg[s].eval(t - s);
00257 
00258   // evaluate it
00259   s = (int)t;
00260   return(seg[s].eval(t - s));
00261 }
00262 */
00263 
00264 /*
00265 CRSPLINE_TEM
00266 bool CRSPLINE::allocate(int num)
00267 {
00268   current = 0;
00269 
00270   if(num <= max){
00271     num_segs = num;
00272     return(true);
00273   }
00274 
00275   if(seg) delete(seg);
00276   seg = new segment[num];
00277 
00278   if(seg){
00279     max = num_segs = num;
00280     return(true);
00281   }else{
00282     max = num_segs = 0;
00283     return(false);
00284   }
00285 }
00286 
00287 CRSPLINE_TEM
00288 bool CRSPLINE::create(point *pts,fnum *ntime,int num)
00289 {
00290   if(!allocate(num)) return(false);
00291 
00292   // TODO
00293 
00294   return(false);
00295 }
00296 
00297 CRSPLINE_TEM
00298 bool CRSPLINE::create_loop(point *pts,fnum *time,int num)
00299 {
00300   point ldx,dx;
00301   fnum sum,t;
00302   int i;
00303 
00304   if(!allocate(num)) return(false);
00305 
00306   ldx = (pts[1] - pts[num-1]) / time[0];
00307   sum = 0.0;
00308 
00309   for(i=0; i<num_segs; i++){
00310     dx = (pts[(i+2)%num_segs] - pts[i]) / time[(i+1)%num_segs];
00311     t = time[i];
00312 
00313     // printf("i = %d\n",i); fflush(stdout);
00314     seg[i].create(pts[i],pts[(i+1)%num_segs],ldx*t,dx*t,sum,t);
00315 
00316     sum += t;
00317     ldx = dx;
00318   }
00319 
00320   return(true);
00321 }
00322 
00323 CRSPLINE_TEM
00324 int CRSPLINE::find_segment(fnum t)
00325 {
00326   fnum d;
00327   int i;
00328 
00329   d = t - seg[current].start;
00330   if(d>=0 && d<=seg[current].time) return(current);
00331 
00332   for(i=0; i<num_segs; i++){
00333     d = t - seg[i].start;
00334     if(d>=0 && d<=seg[i].time) return(current = i);
00335   }
00336 
00337   return(current = num_segs - 1);
00338 }
00339 
00340 CRSPLINE_TEM
00341 point CRSPLINE::eval(fnum t)
00342 {
00343   int i;
00344   i = find_segment(t);
00345   return(seg[i].eval(t));
00346 }
00347 
00348 CRSPLINE_TEM
00349 point CRSPLINE::eval_deriv(fnum t)
00350 {
00351   int i;
00352   i = find_segment(t);
00353   return(seg[i].eval_deriv(t));
00354 }
00355 */
00356 
00357 /*! @file
00358  * @brief Performs calculations regarding splines for path execution
00359  * @author James R. Bruce (Creator)
00360  * 
00361  * @verbatim
00362   ========================================================================
00363     spline.h : Implementation  of Uniform and Non-Uniform Hermite Splines 
00364   ------------------------------------------------------------------------
00365     Copyright (C) 1999-2002  James R. Bruce
00366     School of Computer Science, Carnegie Mellon University
00367   ------------------------------------------------------------------------
00368     This software is distributed under the GNU General Public License,
00369     version 2.  If you do not have a copy of this licence, visit
00370     www.gnu.org, or write: Free Software Foundation, 59 Temple Place,
00371     Suite 330 Boston, MA 02111-1307 USA.  This program is distributed
00372     in the hope that it will be useful, but WITHOUT ANY WARRANTY,
00373     including MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00374     ========================================================================
00375  * @endverbatim
00376  *
00377  * $Author: ejt $
00378  * $Name: tekkotsu-1_4_1 $
00379  * $Revision: 1.4 $
00380  * $State: Exp $
00381  * $Date: 2003/01/23 18:14:04 $
00382  */
00383 
00384 #endif
00385 // __SPLINE_H__
00386 

Tekkotsu v1.4
Generated Sat Jul 19 00:06:31 2003 by Doxygen 1.3.2