- Main Page
- Related Pages
- Classes
- Files

# _bspline.h

Go to the documentation of this file.

    00001
    00025 /* === S T A R T =========================================================== */
    00026
    00027 #ifndef __ETL__BSPLINE_H
    00028 #define __ETL__BSPLINE_H
    00029
    00030 /* === H E A D E R S ======================================================= */
    00031
    00032 #include <vector>
    00033 #include <functional>
    00034 #include "_curve_func.h"
    00035
    00036 /* === M A C R O S ========================================================= */
    00037
    00038 /* === T Y P E D E F S ===================================================== */
    00039
    00040 /* === C L A S S E S & S T R U C T S ======================================= */
    00041
    00042 _ETL_BEGIN_NAMESPACE
    00043
    00044 template <class T, class K=float, class C=affine_combo<T,K>, class D=distance_func<T> >
    00045 class bspline : public std::unary_function<K,T>
    00046 {
    00047 public:
    00048     typedef T value_type;
    00049     typedef K knot_type;
    00050     typedef std::vector<knot_type>  knot_container;
    00051     typedef std::vector<value_type> cpoint_container;
    00052     typedef typename knot_container::iterator knot_iterator;
    00053     typedef typename cpoint_container::iterator cpoint_iterator;
    00054
    00055     typedef C affine_func_type;
    00056     typedef D distance_func_type;
    00057
    00058 protected:
    00059     affine_func_type affine_func;
    00060     distance_func_type distance_func;
    00061
    00062 private:
    00063     int m;
    00064     knot_container _knots;
    00065     cpoint_container _cpoints;
    00066     bool _loop;
    00067
    00068 public:
    00069     bspline():m(2),_loop(false) {  }
    00070
    00071     int get_m()const { return m-1; };
    00072     int set_m(int new_m) { m=new_m+1; return m-1; };
    00073
    00074     bool set_loop(bool x) { _loop=x; reset_knots(); return _loop; }
    00075
    00076     knot_container & knots() { return _knots; };
    00077     cpoint_container & cpoints() { return _cpoints; };
    00078
    00079     const knot_container & knots()const { return _knots; };
    00080     const cpoint_container & cpoints()const { return _cpoints; };
    00081
    00082     void reset_knots()
    00083     {
    00084         int i;
    00085
    00086         if(!_loop)
    00087         {
    00088             _knots.clear();
    00089             if(!_cpoints.size())
    00090                 return;
    00091             while(m>(signed)_cpoints.size())
    00092                 m--;
    00093             for(i=0;i<m;i++)
    00094                 *_knots.insert(_knots.end())=0;
    00095             for(i=1;i<(signed)_cpoints.size()-m+1;i++)
    00096                 *_knots.insert(_knots.end())=i;
    00097             for(i=0;i<m;i++)
    00098                 *_knots.insert(_knots.end())=_cpoints.size()-m+1;
    00099         }
    00100         else
    00101         {
    00102             _knots.clear();
    00103             if(!_cpoints.size())
    00104                 return;
    00105             while(m>(signed)_cpoints.size())
    00106                 m--;
    00107             for(i=0;i<=(signed)_cpoints.size()-m+1;i++)
    00108                 *_knots.insert(_knots.end())=i;
    00109         }
    00110     }
    00111
    00112     int calc_curve_segment(knot_type t)const
    00113     {
    00114         int k;
    00115         if(t<0)
    00116             t=0;
    00117         if(t>=_knots.back())
    00118             t=_knots.back()-0.0001;
    00119         for(k=0;_knots[k]>t || _knots[k+1]<=t;k++)
    00120           ;
    00121
    00122         return k;
    00123     }
    00124
    00125     knot_container get_segment_knots(int i)const
    00126     {
    00127         if(i+1<m)
    00128         {
    00129             knot_container ret(_knots.begin(),_knots.begin()+i+m+1);
    00130
    00131             return ret;
    00132         }
    00133         if(i+1>=(signed)_knots.size())
    00134         {
    00135             knot_container ret(_knots.begin()+i-m+1,_knots.end());
    00136             return ret;
    00137         }
    00138         return knot_container(_knots.begin()+i-m+1, _knots.begin()+i+m);
    00139     }
    00140
    00141     cpoint_container get_segment_cpoints(int i)const
    00142     {
    00143         if(i+1<m)
    00144         {
    00145             return cpoint_container();
    00146         }
    00147         if(i+1>=(signed)_knots.size())
    00148         {
    00149             return cpoint_container();
    00150         }
    00151         return cpoint_container(_cpoints.begin()+i-m+1, _cpoints.begin()+i+1);
    00152     }
    00153
    00154     cpoint_container calc_shell(knot_type t, int level)const
    00155     {
    00156         int
    00157             i=calc_curve_segment(t),
    00158             j,k;
    00159
    00160         knot_container u=get_segment_knots(i);
    00161
    00162         cpoint_container d=get_segment_cpoints(i);
    00163
    00164         if(!d.size())
    00165             return cpoint_container();
    00166
    00167         for(j=0;d.size()>1 && j<level;d.pop_back(),j++)
    00168         {
    00169             for(k=0;k<d.size()-1;k++)
    00170             {
    00171                 d[k]=affine_func(d[k],d[k+1],((t-u[j+k+1])/(u[m+k]-u[j+k+1])));
    00172             }
    00173         }
    00174         return d;
    00175     }
    00176
    00177     value_type operator()(knot_type t)const
    00178     {
    00179         return get_curve_val(calc_curve_segment(t),t);
    00180     }
    00181
    00182     value_type get_curve_val(int i,knot_type t)const
    00183     {
    00184         int
    00185             j,k;
    00186
    00187         knot_container u=get_segment_knots(i);
    00188
    00189         cpoint_container d=get_segment_cpoints(i);
    00190
    00191         if(!d.size())
    00192             return value_type();
    00193
    00194         for(j=0;d.size()>1;d.pop_back(),j++)
    00195         {
    00196             for(k=0;k<(signed)d.size()-1;k++)
    00197             {
    00198                 d[k]=affine_func(d[k],d[k+1],((t-u[j+k+1])/(u[m+k]-u[j+k+1])));
    00199             }
    00200         }
    00201         return d.front();
    00202     }
    00203
    00204     cpoint_iterator find_closest_cpoint(const value_type &point, typename distance_func_type::result_type max)
    00205     {
    00206         cpoint_iterator i=_cpoints.begin();
    00207         cpoint_iterator ret=i;
    00208         typename distance_func_type::result_type dist=distance_func(point,_cpoints[0]);
    00209
    00210         // The distance function returns "cooked" (ie: squared)
    00211         // distances, so we need to cook our max distance for
    00212         // the comparison to work correctly.
    00213         max=distance_func.cook(max);
    00214
    00215         for(++i;i<_cpoints.end();i++)
    00216         {
    00217             typename distance_func_type::result_type thisdist=distance_func(point,*i);
    00218
    00219             if(thisdist<dist)
    00220             {
    00221                 dist=thisdist;
    00222                 ret=i;
    00223             }
    00224         }
    00225         if(dist<max)
    00226             return ret;
    00227         return _cpoints.end();
    00228     }
    00229 };
    00230
    00231 _ETL_END_NAMESPACE
    00232
    00233 /* -- F U N C T I O N S ----------------------------------------------------- */
    00234
    00235 /* -- E N D ----------------------------------------------------------------- */
    00236
    00237 #endif