00001 #ifndef rgrl_spline_h_ 00002 #define rgrl_spline_h_ 00003 00004 //: \file 00005 // \author Lee, Ying-Lin (Bess) 00006 // \date Sep 2003 00007 // \brief A class for dealing a uniform cubic B-spline up to 4D (a hypersurface in 4D). 00008 00009 #include "rgrl_spline_sptr.h" 00010 #include "rgrl_object.h" 00011 00012 #include <vcl_iosfwd.h> 00013 #include <vnl/vnl_matrix.h> 00014 #include <vnl/vnl_vector.h> 00015 00016 //: A tensor-product B-spline in 4D can be written in 00017 // \f[ 00018 // \mathbf{Q}_{ijk}(u,v,w) = \sum_{r=0}^{3} \sum_{s=0}^{3} \sum_{t=0}^{3}V_{i+r,j+s,k+t} b_r(u) b_s(v) b_t(w) 00019 // \f] 00020 // where 00021 // \verbatim 00022 // i=\ceil{x}-1, i=\ceil{y}-1, i=\ceil{z}-1, 00023 // \endverbatim 00024 // and \f$u=x-i\f$,\f$v=y-j\f$\f$w=z-k\f$ are local parameters ranging in $[0,1)$ 00025 // and 00026 // \f[ 00027 // b_{3}(u) = \frac{1}{6}u^3 00028 // \f] 00029 // \f[ 00030 // b_{2}(u) = \frac{1}{6}(-3u^3+3u^2+3u+1) 00031 // \f] 00032 // \f[ 00033 // b_{1}(u) = \frac{1}{6}(3u^3-6u^2+4) 00034 // \f] 00035 // \f[ 00036 // b_{0}(u) = \frac{1}{6}(1-u)^3 00037 // \f] 00038 // or can be expressed in 00039 // \f[ 00040 // \mathbf{Q}_(x,y,z)= 00041 // \sum_{i=-1}^{m+1} \sum_{j=-1}^{n+1} \sum_{k=-1}^{l+1}V_{ijk} B_i(x) B_j(y) B_k(z) 00042 // \f] 00043 // The control vertex \f$V_{0,0,0}\f$ is located at \f$(0,0,0)\f$. 00044 00045 class rgrl_spline 00046 : public rgrl_object 00047 { 00048 public: 00049 //: Constructor 00050 rgrl_spline( ) : rgrl_object() { } 00051 rgrl_spline( vnl_vector< unsigned > const& m ); 00052 rgrl_spline( vnl_vector< unsigned > const& m, vnl_vector< double > const& c ); 00053 00054 // rgrl_spline( vnl_vector<double> const& delta, 00055 // vnl_vector<double> const& x0, 00056 // vnl_vector<double> const& x1 ); 00057 // rgrl_spline( vnl_vector<int> const& m, 00058 // vnl_vector<double> const& delta, 00059 // vnl_vector<double> const& p0); 00060 // rgrl_spline( vnl_vector<double> const& c, 00061 // vnl_vector<double> const& delta, 00062 // vnl_vector<double> const& x0, 00063 // vnl_vector<double> const& x1 ); 00064 // rgrl_spline( vnl_vector<double> const& c, 00065 // vnl_vector<int> const& m, 00066 // vnl_vector<double> const& delta, 00067 // vnl_vector<double> const& p0 ); 00068 00069 //: Destructor. 00070 ~rgrl_spline(){} 00071 00072 //: Set controls points 00073 void set_control_points( vnl_vector<double> const& c ) ; 00074 vnl_vector< double > const& get_control_points() const { return c_; } 00075 vnl_vector< double > & get_control_points() { return c_; } 00076 00077 //: The spline value 00078 // 00079 // \f[ f(\overline{u},y,z) = \sum_{i=-1}^{m[0]_+1} 00080 // \sum_{j=-1}^{m[1]_+1} \sum_{k=-1}^{m_[2]+1} V_{ijk} * B_i(x) * 00081 // B_j(y) * B_k(z)\f] 00082 double f_x( vnl_vector<double> const& x ) const; 00083 vnl_vector< double > jacobian( vnl_vector< double > const& x ) const; 00084 00085 //: The basis responses at \f$(x,y,z)\f$. 00086 // 00087 // It returns a 1 by \f$(m_[0]+3)*(m_[1]+3)*(m_[2]+3)\f$ vector which contains 00088 // [$B_{-1}(x)*B_{-1}(y)*B_{-1}(z)$,..., 00089 // $B_{m_[0]+1}(x)B_{m_[1]+1}(y)B_{m_[2]+1}(z)$], 00090 // in the same order as in c_ 00091 void basis_response( vnl_vector<double> const& point, vnl_vector<double>& br ) const; 00092 00093 void thin_plate_regularization( vnl_matrix<double>& regularization ) const; 00094 00095 unsigned num_of_control_points( ) const { return c_.size(); } 00096 00097 // for tester to access its private members 00098 friend class test_rgrl_spline; 00099 00100 // for output 00101 friend vcl_ostream& operator<< (vcl_ostream& os, rgrl_spline const& spline ); 00102 00103 // for input 00104 friend vcl_istream& operator>> (vcl_istream& is, rgrl_spline& spline ); 00105 00106 00107 //: Generate a refined B-spline that produces the same surface. 00108 rgrl_spline_sptr refinement( vnl_vector< unsigned > const& new_m ) const; 00109 00110 // //: True if the i-th control point has support on pt 00111 // bool is_support( vnl_vector< double > const& pt, unsigned i ); 00112 00113 // Defines type-related functions 00114 rgrl_type_macro( rgrl_spline, rgrl_object ); 00115 00116 private: 00117 00118 double element_1d_thin_plate( unsigned i, unsigned j ) const; 00119 double element_2d_thin_plate( unsigned i, unsigned j ) const; 00120 double element_3d_thin_plate( unsigned i, unsigned j ) const; 00121 00122 typedef double (*func_type)( int i, double u ); 00123 void basis_response_helper( vnl_vector<double> const& point, vnl_vector<double>& br, func_type func ) const; 00124 00125 // The control vertices indices are from -1 to \f$m_[i]+1\f$. 00126 // The total number of control vertices in each dimension is \f$m_[i]+3\f$ 00127 vnl_vector< unsigned > m_; 00128 00129 // The control points in the order of 00130 // $c_{-1,-1,-1}$,..., $c_{m_[0]+1,-1,-1}$ 00131 // $c_{-1,0, -1}$,..., $c_{m_[0]+1,0,-1}$,..., $c_{m_[0]+1,m_[1]+1,-1}$ 00132 // ... $c_{m_[0]+1, m_[1]+1, m_[2]+1}$ 00133 // Gehua: 00134 // In general The control point (i, j, k) is converted to 00135 // (i+1) + (m_[0]+3)(j+1) + (m_[0]+3)(m_[1]+3)(k+1) 00136 // i+1 is to shift the starting point from -1 to 0 00137 vnl_vector<double> c_; 00138 00139 00140 // // to specify $\delta x$, $\delta y$, and $\delta z$ for uniform spline 00141 // vnl_vector<double> delta_; 00142 // vnl_vector<double> p0_; 00143 }; 00144 00145 #endif