Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

hspline.H

Go to the documentation of this file.
00001 
00002 /****************************************************************/
00003 /*    NAME: J.D. Northrup                                       */
00004 /*    ACCT: jdn                                                 */
00005 /*    FILE: hspline.H                                           */
00006 /*    DATE: Wed Jul 29 11:48:12 1998                            */
00007 /****************************************************************/
00008 #ifndef __HSPLINE_HEADER
00009 #define __HSPLINE_HEADER
00010 
00011 #include "mlib/points.H"
00012 
00013 /****************************************************************/
00014 /* CLASS NAME :  HSpline                                        */
00015 /*                                                              */
00016 /* A Hermite spline curve class. Set the constraints, and then  */
00017 /* query for points along the curve by calling value_at where   */
00018 /* 0 <= t <= 1. See Sec. 11.2.1 in the Bible for more info.     */
00019 /*                                                              */
00020 /****************************************************************/
00021 
00022 class HSpline {
00023  public:
00024    // need following class to be public
00025    // to have a static instance below
00026 
00027    /*******************************************************
00028     * HermiteBasis:
00029     *
00030     *  transpose of the matrix Mh from "Bible" sec. 11.2.1:
00031     *******************************************************/
00032    class HermiteBasis : public mlib::Wtransf {
00033     public:
00034       HermiteBasis() {
00035          row[0][0] =  2; row[0][1] = -3; row[0][2] = 0; row[0][3] = 1; 
00036          row[1][0] = -2; row[1][1] =  3; row[1][2] = 0; row[1][3] = 0; 
00037          row[2][0] =  1; row[2][1] = -2; row[2][2] = 1; row[2][3] = 0; 
00038          row[3][0] =  1; row[3][1] = -1; row[3][2] = 0; row[3][3] = 0; 
00039       }
00040    };
00041  protected:
00042    /*******************************************************
00043     * HermiteGeometry:
00044     *
00045     *  transpose of the matrix Gh from "Bible" sec. 11.2.1:
00046     *******************************************************/
00047    class HermiteGeometry : public mlib::Wtransf {
00048     public:
00049       HermiteGeometry() {}
00050       HermiteGeometry(mlib::CWpt& p1, mlib::CWpt& p2, mlib::CWvec& v1, mlib::CWvec& v2) {
00051          set(p1, p2, v1, v2);
00052       }
00053 
00054       void set(mlib::CWpt& p1, mlib::CWpt& p2, mlib::CWvec& v1, mlib::CWvec& v2);
00055    };
00056 
00057    // HSpline member data:
00058    static const HermiteBasis _HemiteBasisConst;  // const thing
00059    mlib::Wtransf                      _M;     // our thing
00060 
00061 public:
00062    HSpline() {}
00063    HSpline(mlib::CWpt& p1, mlib::CWpt& p2, mlib::CWvec& v1, mlib::CWvec& v2) {
00064       set_constraints(p1, p2, v1, v2);
00065    }
00066    virtual ~HSpline() {}
00067 
00068    void set_constraints(mlib::CWpt& p1, mlib::CWpt& p2, mlib::CWvec& v1, mlib::CWvec& v2) {
00069       _M = HermiteGeometry(p1, p2, v1, v2) * _HemiteBasisConst;
00070    }
00071    mlib::Wpt  value_at(double t) const {
00072       double t2 = t*t;
00073       return _M * mlib::Wpt(t2*t,t2,t);
00074    }
00075    mlib::Wvec  tan_at(double t) const { return _M * mlib::Wvec(3*sqr(t), 2*t, 1); }
00076 };
00077 
00078 /************************************************************
00079  * CRSpline:
00080  *
00081  *      Catmull-Rom spline
00082  *
00083  *      interpolates given points _pts and 
00084  *      associated parameter vals _u
00085  *      strives to be C1
00086  *
00087  *      Based on:
00088  *        Gerald Farin: Curves and Surfaces for CAGD,
00089  *        3rd Ed., section 8.3 (pp 126-128)
00090  ************************************************************/
00091 class CRSpline {
00092  protected:
00093    ARRAY<mlib::Wpt>           _pts;   // interpolated points
00094    ARRAY<double>        _u;     // parameter values
00095    ARRAY<HSpline*>      _H;     // splines between adjacent points
00096    bool                 _valid; // tells if _H is up-to-date
00097 
00098    int _update();
00099    int update() const {
00100       return _valid ? 1 : ((CRSpline*)this)->_update();
00101    }
00102 
00103    // for internal convenience:
00104    int    num()       const { return _pts.num(); }
00105    double delt(int i) const { return _u[i+1] - _u[i]; }
00106    mlib::Wvec   m(int i)    const { return (_pts[i+1]-_pts[i-1])/(_u[i+1]-_u[i-1]); }
00107 
00108  public:
00109    CRSpline() : _pts(0), _u(0), _H(0), _valid(0) {}
00110    ~CRSpline() { clear(); }
00111 
00112    void clear(int all=1);
00113    void set(mlib::CWpt_list& p, CARRAY<double> &u);
00114    void add(mlib::CWpt& p, double u);
00115 
00116    ////////////////////////////////////////////////////
00117    // not for casual users:
00118    // 
00119    //   u is the global parameter over whole spline.
00120    //   t is a local parameter varying from 0 to 1
00121    //   between a given pair of interpolated points.
00122    //
00123    // regular users only care about u
00124    //////////////////////////////////////////////////
00125    void get_seg(double u, int& seg, double& t) const;
00126 
00127    mlib::Wpt pt(int k, double t) const {
00128       return update() ? _H[k]->value_at(t) : mlib::Wpt::Origin();
00129    }
00130 
00131    mlib::Wvec tan(int k, double t) const {
00132       return update() ? _H[k]->tan_at(t)/delt(k) : mlib::Wvec();
00133    }
00134 
00135    ////////////////////////////////////////////////////
00136    // for regular users:
00137    // 
00138    //   (see above)
00139    //////////////////////////////////////////////////
00140    mlib::Wpt pt (double u) const {
00141       // go out of our way not to segv
00142       // even for short splines
00143       int k; double t;
00144       switch (num()) {
00145          case 0: return mlib::Wpt::Origin();
00146          case 1: return _pts[0];
00147          case 2: get_seg(u,k,t);
00148                  return _pts[0] + (_pts[1]-_pts[0])*t;
00149       }
00150       get_seg(u,k,t);
00151       return pt(k,t);
00152    }
00153    mlib::Wvec tan(double u) const {
00154       // go out of our way not to segv
00155       // even for short splines
00156       switch (num()) {
00157          case   0: 
00158          case   1: return mlib::Wvec();
00159          case   2: return (_pts[1]-_pts[0])/delt(0);
00160       }
00161       int k; double t; get_seg(u,k,t);
00162       return tan(k,t);
00163    }
00164 };
00165 
00166 #define CCRSpline_list const CRSpline_list
00167 typedef ARRAY<CRSpline*> CRSpline_list;
00168 
00169 #endif // __HSPLINE_HEADER

Generated on Mon Sep 18 11:39:31 2006 for jot by  doxygen 1.4.4