00001
00002
00003
00004
00005
00006
00007
00008 #ifndef __HSPLINE_HEADER
00009 #define __HSPLINE_HEADER
00010
00011 #include "mlib/points.H"
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 class HSpline {
00023 public:
00024
00025
00026
00027
00028
00029
00030
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
00044
00045
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
00058 static const HermiteBasis _HemiteBasisConst;
00059 mlib::Wtransf _M;
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
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 class CRSpline {
00092 protected:
00093 ARRAY<mlib::Wpt> _pts;
00094 ARRAY<double> _u;
00095 ARRAY<HSpline*> _H;
00096 bool _valid;
00097
00098 int _update();
00099 int update() const {
00100 return _valid ? 1 : ((CRSpline*)this)->_update();
00101 }
00102
00103
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
00118
00119
00120
00121
00122
00123
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
00137
00138
00139
00140 mlib::Wpt pt (double u) const {
00141
00142
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
00155
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