contrib/rpl/rgrl/rgrl_spline.cxx
Go to the documentation of this file.
00001 #include "rgrl_spline.h"
00002 //:
00003 // \file
00004 // \author Lee, Ying-Lin (Bess)
00005 // \date   Sept 2003
00006 
00007 #include <vcl_cmath.h>
00008 #include <vcl_iostream.h>
00009 #include <vcl_cassert.h>
00010 #include <vnl/vnl_math.h>
00011 #include <vcl_vector.h>
00012 
00013 static double g( int a1, int a2, int m );
00014 static double g_prime( int a1, int a2, int m );
00015 static double g_double_prime( int a1, int a2, int m );
00016 
00017 //: calculate the uniform cubic B-spline basis functions $B_i(u)$
00018 // Here $u \in [0,1]$ is a local parameter and
00019 // \f[B_0(u) = (1-u)^3 / 6\f],
00020 // \f[B_1(u) = (3u^3 - 6u^2 +4) / 6\f],
00021 // \f[B_2(u) = (-3u^3 + 3u^2 +3u + 1) / 6\f],
00022 // \f[B_3(u) = u^3 / 6\f].
00023 static double bspline_basis_function( int i, double u );
00024 static double bspline_basis_prime_function( int i, double u );
00025 
00026 rgrl_spline::
00027 rgrl_spline( vnl_vector< unsigned > const& m )
00028   : m_( m )
00029 {
00030   int n = 1;
00031   for (unsigned i=0; i<m.size(); ++i)
00032     n *= (m_[i]+3);
00033   c_.set_size(n);
00034   c_.fill( 0.0 );
00035 }
00036 
00037 rgrl_spline::
00038 rgrl_spline( vnl_vector< unsigned > const& m, vnl_vector< double > const& c )
00039   : m_( m ), c_( c )
00040 {
00041   unsigned int n = 1;
00042   for (unsigned i=0; i<m.size(); ++i)
00043     n *= (m_[i]+3);
00044   assert ( c.size() == n );
00045 }
00046 
00047 void
00048 rgrl_spline::
00049 set_control_points( vnl_vector<double> const& c )
00050 {
00051   unsigned n = 1;
00052   for (unsigned i=0; i < m_.size(); ++i)
00053     n *= (m_[i]+3);
00054   assert ( c.size() == n );
00055   c_ = c;
00056 }
00057 
00058 // f( x )
00059 //
00060 // At the beginning, I truncated f(x) so that f(x)=0 when x<0 or
00061 // x>m. But this causes the boundary not continuous. Now I fix it.
00062 // fixed????? -Gehua
00063 // I can see it is still f(x)=0 when x<0 or x>m
00064 double
00065 rgrl_spline::
00066 f_x( vnl_vector<double> const& point ) const
00067 {
00068   assert ( point.size() == m_.size() );
00069 
00070   for ( unsigned i=0; i<m_.size(); ++i ) {
00071     // assert ( point[i] >= 0 && point[i] <= m_[i] );
00072     // check if it's in the valid region
00073     if ( point[i] < 0 || point[i] > m_[i] ) // was: ( point[i] < -3 || point[i] >= m_[i]+3 )
00074       // if it's out of the support region of control points, don't need
00075       // to calculate the value.
00076       return 0;
00077   }
00078 
00079   // to decrease memory allocation
00080   // make gr static
00081   static vnl_vector< double > gr;
00082   basis_response( point, gr );
00083 
00084   return inner_product( c_, gr );
00085 }
00086 
00087 // Jacobian of f( x, y, z ) = ( d f(x,y,z) / dx, d f(x,y,z) / dy, d f(x,y,z) / dz )
00088 vnl_vector< double >
00089 rgrl_spline::
00090 jacobian( vnl_vector< double > const& point ) const
00091 {
00092   assert ( point.size() == m_.size() );
00093 
00094   // check if it's in the valid region
00095   for ( unsigned i=0; i<m_.size(); ++i ) {
00096     // assert ( point[i] >= 0 && point[i] <= m_[i] );
00097     if ( point[i] < 0 || point[i] > m_[i] )
00098       return vnl_vector< double >(m_.size(), 0.0);
00099   }
00100 
00101   unsigned num_control_pts = 1;
00102   const unsigned dim = m_.size();
00103   for (unsigned n=0; n<dim; ++n)
00104     num_control_pts *= m_[n]+3;
00105 
00106   vnl_matrix<double> br( dim, num_control_pts, 0 );
00107 
00108   vnl_vector< int > floor( dim );
00109   vnl_vector< int > ceil( dim );
00110   vnl_vector< double > u( dim );
00111   vnl_vector< int > min( dim );
00112   vnl_vector< int > max( dim );
00113 
00114   for ( unsigned n=0; n<dim; ++n ) {
00115     floor[n] = (int)vcl_floor( point[n] ) ;
00116     ceil[n] = (int)vcl_ceil( point[n] );
00117     u[n] = point[n] - floor[n];
00118     min[ n ] = ( floor[n] < 0 ) ? 0 : floor[n];
00119     max[ n ] = ( ceil[n] > (int)m_[n] ) ? m_[n] + 2 : ceil[n]+2;
00120   }
00121 
00122   // 3D case
00123   if (dim == 3) {
00124     int a = (m_[0]+3) * (m_[1]+3);
00125     int b = m_[0]+3;
00126     for ( int i=min[2], index = a*i; i<=max[2]; ++i, index+=a ) {
00127       double b1 = bspline_basis_function( i-floor[2], u[2] );
00128       double b1_prime = bspline_basis_prime_function( i-floor[2], u[2] );
00129       for ( int j=min[1], d = b*j + index; j<=max[1]; ++j, d+=b ) {
00130         double b2 = bspline_basis_function( j-floor[1], u[1] );
00131         double b2_prime = bspline_basis_prime_function( j-floor[1], u[1] );
00132         for ( int k=min[0], e = d+k; k<=max[0]; ++k, ++e ) {
00133           double b3 = bspline_basis_function( k-floor[0], u[0] );
00134           double b3_prime = bspline_basis_prime_function( k-floor[0], u[0] );
00135           br(0, e) = b1_prime * b2 * b3;
00136           br(1, e) = b1 * b2_prime * b3;
00137           // ???? - Gehua
00138           // should this be br(2,e)?
00139           br(2, e) = b1 * b2 * b3_prime;
00140         }
00141       }
00142     }
00143   }
00144   // 2D case
00145   else if (dim == 2) {
00146     int a =(m_[0]+3);
00147     for ( int i=min[1], index = a*i; i<=max[1]; ++i, index+=a ) {
00148       double b1 = bspline_basis_function( i-floor[1], u[1] );
00149       double b1_prime = bspline_basis_prime_function( i-floor[1], u[1] );
00150       for ( int j=min[0], b = j + index; j<=max[0]; ++j, ++b ) {
00151         double b2 = bspline_basis_function( j-floor[0], u[0] );
00152         double b2_prime = bspline_basis_prime_function( j-floor[0], u[0] );
00153         br(0, b) = b1_prime * b2;
00154         br(1, b) = b1 * b2_prime;
00155       }
00156     }
00157   }
00158   // 1D case
00159   else if (dim == 1) {
00160     for ( int i=min[0], b = i; i<= max[0]; ++i, ++b ) {
00161       double b1_prime = bspline_basis_prime_function( i-floor[0], u[0] );
00162       br( 0, b ) = b1_prime;
00163     }
00164   }
00165   else
00166     assert ( !"dim should be 1, 2 or 3" );
00167 
00168   // ---Gehua
00169   // Instead of matrix multiplication, another way is to move it
00170   // into the loops, such as:
00171   // br(0, b) = c_(b) * b1_prime * b2;
00172   // This touches less memory.
00173   return br * c_;
00174 }
00175 
00176 void
00177 rgrl_spline::
00178 basis_response( vnl_vector<double> const& point, vnl_vector<double>& br ) const
00179 {
00180   basis_response_helper( point, br, &bspline_basis_function );
00181 }
00182 
00183 void
00184 rgrl_spline::
00185 basis_response_helper( vnl_vector<double> const& point, vnl_vector<double>& br, func_type basis_func ) const
00186 {
00187   unsigned num_element = 1;
00188   const unsigned dim = m_.size();
00189   for (unsigned n=0; n<dim; ++n)
00190     num_element *= m_[n]+3;
00191 
00192   br.set_size(num_element);
00193   br.fill(0);
00194 
00195   vnl_vector< int > floor(dim);
00196   vnl_vector< int > ceil(dim);
00197   vnl_vector< double > u(dim);
00198   vnl_vector< int > min( dim );
00199   vnl_vector< int > max( dim );
00200 
00201   for ( unsigned n=0; n<dim; ++n ) {
00202     floor[n] = (int)vcl_floor( point[n] ) ;
00203     ceil[n] = (int)vcl_ceil( point[n] );
00204     u[n] = point[n] - floor[n];
00205     min[ n ] = ( floor[n] < 0 ) ? 0 : floor[n];
00206     max[ n ] = ( ceil[n] > (int)m_[n] ) ? m_[n] + 2 : ceil[n]+2;
00207   }
00208 
00209   // 3D case
00210   if (dim == 3) {
00211     int a = (m_[0]+3) * (m_[1]+3);
00212     int b = m_[0]+3;
00213     for ( int i=min[2], index = a*i; i<=max[2]; ++i, index+=a ) {
00214       double b1 = basis_func( i-floor[2], u[2] );
00215       for ( int j=min[1], d = b*j + index; j<=max[1]; ++j, d+=b ) {
00216         double b2 = basis_func( j-floor[1], u[1] );
00217         for ( int k=min[0], e = d+k; k<=max[0]; ++k, ++e ) {
00218           double b3 = basis_func( k-floor[0], u[0] );
00219           br[e] = b1 * b2 * b3;
00220         }
00221       }
00222     }
00223   }
00224   // 2D case
00225   else if (dim == 2) {
00226     int a =(m_[0]+3);
00227     for ( int i=min[1], index = a*i; i<=max[1]; ++i, index+=a ) {
00228       double b1 = basis_func( i-floor[1], u[1] );
00229       for ( int j=min[0], b = j + index; j<=max[0]; ++j, ++b ) {
00230         double b2 = basis_func( j-floor[0], u[0] );
00231         br[b] = b1 * b2;
00232       }
00233     }
00234   }
00235   // 1D case
00236   else if (dim == 1) {
00237     for ( int i=min[0], b = i; i<= max[0]; ++i, ++b ) {
00238       double b1 = basis_func( i-floor[0], u[0] );
00239       br[b] = b1;
00240     }
00241   }
00242   else
00243     assert ( !"dim should be 1, 2 or 3" );
00244 }
00245 
00246 double
00247 rgrl_spline::
00248 element_1d_thin_plate(unsigned i, unsigned j) const
00249 {
00250   // a1, b1 : {-1, 0, ..., m_[0] + 1}
00251   int a1 = i - 1;
00252   int b1 = j - 1;
00253 
00254   if ( vnl_math_abs( a1 - b1 ) > 3 )
00255     return 0;
00256 #if 0
00257   return g( delta_[0], a1, b1, m_[0] ) * delta_[0];
00258   return g_prime( delta_[0], a1, b1, m_[0] ) * delta_[0];
00259   return g_double_prime( delta_[0], a1, b1, m_[0] ) * delta_[0];
00260 #endif // 0
00261   return g_double_prime( a1, b1, m_[0] );
00262 }
00263 
00264 double
00265 rgrl_spline::
00266 element_2d_thin_plate(unsigned i, unsigned j) const
00267 {
00268   // a1, b1 : {-1, 0, ..., m_[0] + 1}
00269   // a2, b2 : {-1, 0, ..., m_[1] + 1}
00270   int a1 = i % ( m_[0] + 3 ) - 1;
00271   int a2 = ( i / ( m_[0] + 3 ) ) - 1;
00272 
00273   int b1 = j % ( m_[0] + 3 ) - 1;
00274   int b2 = ( j / ( m_[0] + 3 ) ) - 1;
00275 
00276   if ( vnl_math_abs( a1 - b1 ) > 3 )
00277     return 0;
00278   if ( vnl_math_abs( a2 - b2 ) > 3 )
00279     return 0;
00280 
00281 #if 0
00282   double gx = g( delta_[0], a1, b1, m_[0] ) * delta_[0];
00283   double gx_prime = g_prime( delta_[0], a1, b1, m_[0] ) * delta_[0];
00284   double gx_double_prime = g_double_prime( delta_[0], a1, b1, m_[0] ) * delta_[0];
00285 
00286   double gy = g( delta_[0], a2, b2, m_[1] ) * delta_[1];
00287   double gy_prime = g_prime( delta_[0], a2, b2, m_[1] ) * delta_[1];
00288   double gy_double_prime = g_double_prime( delta_[0], a2, b2, m_[1] ) * delta_[1];
00289 #else
00290   double gx = g( a1, b1, m_[0] );
00291   double gx_prime = g_prime( a1, b1, m_[0] );
00292   double gx_double_prime = g_double_prime( a1, b1, m_[0] );
00293 
00294   double gy = g( a2, b2, m_[1] );
00295   double gy_prime = g_prime( a2, b2, m_[1] );
00296   double gy_double_prime = g_double_prime( a2, b2, m_[1] );
00297 #endif // 0
00298 
00299   return gx_double_prime * gy +
00300          gx * gy_double_prime +
00301          2 * gx_prime * gy_prime;
00302 }
00303 
00304 double
00305 rgrl_spline::
00306 element_3d_thin_plate(unsigned i, unsigned j) const
00307 {
00308   // a1, b1 : {-1, 0, ..., m_[0] + 1}
00309   // a2, b2 : {-1, 0, ..., m_[1] + 1}
00310   // a3, b3 : {-1, 0, ..., m_[2] + 1}
00311   int a1 = i % ( m_[0] + 3 ) - 1;
00312   int a2 = ( i / ( m_[0] + 3 ) ) % ( m_[1] + 3 ) - 1;
00313   int a3 = ( i / ( m_[0] + 3 ) ) / ( m_[1] + 3 ) - 1;
00314 
00315   int b1 = j % ( m_[0] + 3 ) - 1;
00316   int b2 = ( j / ( m_[0] + 3 ) ) % ( m_[1] + 3 ) - 1;
00317   int b3 = ( j / ( m_[0] + 3 ) ) / ( m_[1] + 3 ) - 1;
00318 
00319   if ( vnl_math_abs( a1 - b1 ) > 3 )
00320     return 0;
00321   if ( vnl_math_abs( a2 - b2 ) > 3 )
00322     return 0;
00323   if ( vnl_math_abs( a3 - b3 ) > 3 )
00324     return 0;
00325 
00326 #if 0
00327   double gx = g( delta_[0], a1, b1, m_[0] ) * delta_[0];
00328   double gx_prime = g_prime( delta_[0], a1, b1, m_[0] ) * delta_[0];
00329   double gx_double_prime = g_double_prime( delta_[0], a1, b1, m_[0] ) * delta_[0];
00330 
00331   double gy = g( delta_[0], a2, b2, m_[1] ) * delta_[1];
00332   double gy_prime = g_prime( delta_[0], a2, b2, m_[1] ) * delta_[1];
00333   double gy_double_prime = g_double_prime( delta_[0], a2, b2, m_[1] ) * delta_[1];
00334 
00335   double gz = g( delta_[0], a3, b3, m_[2] ) * delta_[2];
00336   double gz_prime = g_prime( delta_[0], a3, b3, m_[2] ) * delta_[2];
00337   double gz_double_prime = g_double_prime( delta_[0], a3, b3, m_[2] ) * delta_[2];
00338 #else
00339   double gx = g( a1, b1, m_[0] );
00340   double gx_prime = g_prime( a1, b1, m_[0] );
00341   double gx_double_prime = g_double_prime( a1, b1, m_[0] );
00342 
00343   double gy = g( a2, b2, m_[1] );
00344   double gy_prime = g_prime( a2, b2, m_[1] );
00345   double gy_double_prime = g_double_prime( a2, b2, m_[1] );
00346 
00347   double gz = g( a3, b3, m_[2] );
00348   double gz_prime = g_prime( a3, b3, m_[2] );
00349   double gz_double_prime = g_double_prime( a3, b3, m_[2] );
00350 #endif // 0
00351 
00352   return gx_double_prime * gy * gz +
00353          gx * gy_double_prime * gz +
00354          gx * gy * gz_double_prime +
00355          2 * gx_prime * gy_prime * gz +
00356          2 * gx_prime * gy * gz_prime +
00357          2 * gx * gy_prime * gz_prime;
00358 }
00359 
00360 void
00361 rgrl_spline::
00362 thin_plate_regularization(vnl_matrix<double>& regularization) const
00363 {
00364   const unsigned dim = m_.size();
00365   // The volume
00366   double vol = 1;
00367   for ( unsigned i=0; i<dim; ++i ) {
00368     vol *= m_[i]; // was: *= m_[i]*delta_[i];
00369   }
00370   // The number of control points
00371   unsigned num = 1;
00372   for ( unsigned i=0; i<dim; ++i ) {
00373     num *= m_[i] + 3;
00374   }
00375 
00376   regularization.set_size(num, num);
00377   for ( unsigned i=0; i<num; ++i ) {
00378     for ( unsigned j=i; j<num; ++j ) {
00379       if ( dim == 1 )
00380         regularization[i][j] = regularization[j][i] = element_1d_thin_plate(i, j) / vol;
00381       else if ( dim == 2 )
00382         regularization[i][j] = regularization[j][i] = element_2d_thin_plate(i, j) / vol;
00383       else if ( dim == 3 )
00384         regularization[i][j] = regularization[j][i] = element_3d_thin_plate(i, j) / vol;
00385     }
00386   }
00387 }
00388 
00389 // b_{i}(u), 0 <= u <= 1
00390 double
00391 bspline_basis_function( int i, double u )
00392 {
00393   assert ( u <= 1.0 && u >= 0.0 );
00394   assert ( i <= 3 && i >= 0 );
00395   double b = 0;
00396   double s = 1 - u;
00397 
00398   switch (i) {
00399    case 0:
00400     b = s*s*s / 6;
00401     break;
00402    case 1:
00403     b = ( 4 - 3 * u * u * (s+1) ) / 6;
00404     break;
00405    case 2:
00406     b = ( 3 * u * (u*s+1) + 1 ) / 6;
00407     break;
00408    case 3:
00409     b = u*u*u / 6;
00410     break;
00411    default:
00412     vcl_cerr << "rgrl_spline::basis_function: wrong index for basis functions : " << i << '\n';
00413   }
00414   return b;
00415 }
00416 
00417 double
00418 bspline_basis_prime_function( int i, double u )
00419 {
00420   assert ( u <= 1 && u >= 0 );
00421   assert ( i <= 3 && i >= 0 );
00422   double b = 0;
00423   double s = 1 - u;
00424 
00425   switch (i) {
00426    case 0:
00427     b = - s*s / 2;
00428     break;
00429    case 1:
00430     b = - u * (3*s+1) / 2;
00431     break;
00432    case 2:
00433     b = s * (3*u+1) / 2;
00434     break;
00435    case 3:
00436     b = u*u / 2;
00437     break;
00438    default:
00439     vcl_cerr << "rgrl_spline::basis_function: wrong index for basis functions\n";
00440   }
00441   return b;
00442 }
00443 
00444 static
00445 double
00446 g( int a1, int a2, int m ) // was: g( double u, int a1, int a2, int m )
00447 {
00448   int min_a, max_a;
00449   if ( a1 < a2 ) {
00450     min_a = a1;
00451     max_a = a2;
00452   }
00453   else {
00454     min_a = a2;
00455     max_a = a1;
00456   }
00457 
00458   assert ( min_a >= -1 );
00459   assert ( max_a <= m+1 );
00460   int diff_a = vnl_math_abs( a1 - a2 );
00461 
00462   double ans = 0;
00463   if ( diff_a == 0 ) {
00464     double ans = 0;
00465     if ( max_a <= m-2 ) {
00466       // $\int [b_0(x)*b_0(x)] \, dx = \int [(1-u)^6 / 36] \, dx$
00467       ans += 1.0 / 252 ;
00468     }
00469     if ( min_a >= 0 && max_a <= m-1 ) {
00470       // $\int [b_1(x)*b_1(x)] \, dx = \int [(3u^3-6u^2+4)^2 / 36] \, dx$
00471       ans += 0.2 + 1.0 / 28;
00472     }
00473     if ( min_a >= 1 && max_a <= m ) {
00474       // $\int [b_2(x)*b_2(x)] \, dx = \int [b_1(x)*b_1(x)] \, dx$
00475       ans += 0.2 + 1.0 / 28;
00476     }
00477     if ( min_a >= 2 ) {
00478       // $\int [b_3(x)*b_3(x)] \, dx = \int [b_0(x)*b_0(x)] \, dx$
00479       ans += 1.0 / 252;
00480     }
00481     return ans;
00482   }
00483 
00484   if ( diff_a == 1 ) {
00485     if ( max_a <= m-1 ) {
00486       // $\int [b_0(u)*b_1(u)] \, du = \int [-3u^6 + 15u^5 - 27u^4 + 17u^3 + 6u^2 - 12u + 4]/36 \, du$
00487       ans += 0.0375 - 1.0 / 84;
00488     }
00489     if ( min_a >= 0 && max_a <= m ) {
00490       // $\int [b_1(u)*b_2(u)] \, du = \int [-9u^6 + 27u^5 - 9u^4 -27u^3 + 6u^2 + 12u + 4]/36 \, du$
00491       ans += -0.1125 - 1.0 / 28 + 1.0 / 3;
00492     }
00493     if ( min_a >= 1 ) {
00494       // $\int [b_2(u)*b_3(u)] \, du = \int [b_0(u)*b_1(u)] \, du$
00495       ans += 0.0375 - 1.0 / 84;
00496     }
00497     return ans;
00498   }
00499 
00500   if ( diff_a == 2 ) {
00501     if ( max_a <= m ) {
00502       // $\int [b_0(u)*b_2(u)] \, du = \int [3u^6 - 12u^5 + 15u^4 - 4u^3 - 3u^2 + 1]/36 \, du$
00503       ans += 1.0 / 84;
00504     }
00505     if ( min_a >= 0 ) {
00506       // $\int [b_1(u)*b_3(u)] \, du = \int [b_0(u)*b_2(u)] \, du$
00507       ans += 1.0 / 84;
00508     }
00509     return ans;
00510   }
00511 
00512   if ( diff_a == 3 ) {
00513     // $\int [b_0(u)*b_3(u)] \, du = \int [-u^6 + 3u^5 -3u^4 + u3]/36 \, du$
00514     ans += 1.0 / 240 - 1.0 / 252;
00515     return ans;
00516   }
00517 
00518   return 0;
00519 }
00520 
00521 static
00522 double
00523 g_prime( int a1, int a2, int m ) // was: g_prime(double u, int a1, int a2, int m )
00524 {
00525   int min_a = (a1 < a2) ? a1 : a2;
00526   int max_a = (a1 < a2) ? a2 : a1;
00527   assert ( min_a >= -1 );
00528   assert ( max_a <= m+1 );
00529   int diff_a = vnl_math_abs( a1 - a2 );
00530 
00531   double ans = 0;
00532   if ( diff_a == 0 ) {
00533     if ( max_a <= m-2 ) {
00534       // $\int [b'_0(x)*b'_0(x)] \, dx = \int [(1-u)^4]/4 \, dx = (1-u^2+u^3/3)/4$
00535       ans += 0.05;
00536     }
00537     if ( min_a >= 0 && max_a <= m-1 ) {
00538       // $\int [b'_1(x)*b'_1(x)] \, dx = \int [9u^4 -24u^3+16u^2]/4 \, dx$
00539       ans += 0.2 + 1.0 / 12;
00540     }
00541     if ( min_a >= 1 && max_a <= m ) {
00542       // $\int [b'_2(x)*b'_2(x)] \, dx = \int [b'_1(x)*b'_1(x)] \, dx$
00543       ans += 0.2 + 1.0 / 12;
00544     }
00545     if ( min_a >= 2 ) {
00546       // $\int [b_3(x)*b_3(x)] \, dx = \int [b'_0(x)*b'_0(x)] \, dx$
00547       ans += 0.05;
00548     }
00549     return ans;
00550   }
00551 
00552   if ( diff_a == 1 ) {
00553     if ( max_a <= m-1 ) {
00554       // $\int [b'_0(u)*b'_1(u)] \, du = \int [-3u^4 + 10u^3 - 11u^2 + 4u]/4 \, du$
00555       ans += -0.025 + 1.0 / 12;
00556     }
00557     if ( min_a >= 0 && max_a <= m) {
00558       // $\int [b'_1(u)*b'_2(u)] \, du = \int [- 9u^4 + 18u^3 - 5u^2 - 4u]/4 \, du$
00559       ans += 0.175 - 5.0 / 12;
00560     }
00561     if ( min_a >= 1 ) {
00562       // $\int [b'_2(u)*b'_3(u)] \, du = \int [b'_0(u)*b'_1(u)] \, du$
00563       ans += -0.025 + 1.0 / 12;
00564     }
00565     return ans;
00566   }
00567 
00568   if ( diff_a == 2 ) {
00569     if ( max_a <= m ) {
00570       // $\int [b'_0(u)*b'_2(u)] \, du = \int [3u^4 - 8u^3 + 6u^2 - 1]/4 \, du$
00571       ans += -0.1;
00572     }
00573     if ( min_a >= 0 ) {
00574       // $\int [b'_1(u)*b'_3(u)] \, du = \int [b'_0(u)*b'_2(u)] \, du$
00575       ans += -0.1;
00576     }
00577     return ans;
00578   }
00579 
00580   if ( diff_a == 3 ) {
00581     // $\int [b'_0(u)*b'_3(u)] \, du = \int [-u^4 + 2u^3 - u^2]/4 \, du$
00582     ans += 0.075 - 1.0 / 12;
00583     return ans;
00584   }
00585 
00586   return 0;
00587 }
00588 
00589 static
00590 double
00591 g_double_prime( int a1, int a2, int m ) // was: g_double_prime( double u, int a1, int a2, int m )
00592 {
00593   int min_a = (a1 < a2) ? a1 : a2;
00594   int max_a = (a1 < a2) ? a2 : a1;
00595   assert ( min_a >= -1 );
00596   assert ( max_a <= m+1 );
00597   int diff_a = vnl_math_abs( a1 - a2 );
00598 
00599   double ans = 0;
00600   if ( diff_a == 0 ) {
00601     if ( max_a <= m-2 ) {
00602       // $\int [b"_0(x)*b"_0(x)] \, dx = \int [(1-u)^2] \, dx = (u-u^2+u^3/3)$
00603       ans += 1.0 / 3;
00604     }
00605     if ( min_a >= 0 && max_a <= m-1 ) {
00606       // $\int [b"_1(x)*b"_1(x)] \, dx = \int [9u^2 - 12u + 4] \, dx = 3u^3 -6u + 4$
00607       ans += 1.0;
00608     }
00609     if ( min_a >= 1 && max_a <= m ) {
00610       // $\int [b"_2(x)*b"_2(x)] \, dx = \int [b"_1(x)*b"_1(x)] \, dx$
00611       ans += 1.0;
00612     }
00613     if ( min_a >= 2 ) {
00614       // $\int [b"_3(x)*b"_3(x)] \, dx = \int [b"_0(x)*b"_0(x)] \, dx$
00615       ans += 1.0 / 3;
00616     }
00617     return ans;
00618   }
00619 
00620   if ( diff_a == 1 ) {
00621     if ( max_a <= m-1 ) {
00622       // $\int [b"_0(u)*b"_1(u)] \, du = \int [-3u^2 + 5u - 2] \, du$
00623       ans += -0.5;
00624     }
00625     if ( min_a >= 0 && max_a <= m) {
00626       // $\int [b"_1(u)*b"_2(u)] \, du = \int [- 9u^2 + 9u - 2] \, du$
00627       ans += -0.5;
00628     }
00629     if ( min_a >= 1 ) {
00630       // $\int [b"_2(u)*b"_3(u)] \, du = \int [b"_0(u)*b"_1(u)] \, du$
00631       ans += -0.5;
00632     }
00633     return ans;
00634   }
00635 
00636   if ( diff_a == 2 ) {
00637     // if ( max_a <= m )
00638       // $\int [b"_0(u)*b"_2(u)] du \, = 0$
00639     // if ( min_a >= 0 )
00640       // $\int [b"_1(u)*b"_3(u)] du \, = 0$
00641     return ans;
00642   }
00643 
00644   if ( diff_a == 3 ) {
00645     // $\int [b"_0(u)*b"_3(u)] \, du = \int [-u^4 + 2u3 - u^2]/4 \, du$
00646     ans += 0.5 - 1.0 / 3;
00647     return ans;
00648   }
00649 
00650   return 0;
00651 }
00652 
00653 static
00654 inline
00655 double
00656 refine_helper_f1( double v1, double v2)
00657 {
00658   return ( v1 + v2 ) / 2;
00659 }
00660 
00661 static
00662 inline
00663 double
00664 refine_helper_f2( double v1, double v2, double v3 )
00665 {
00666   return v1 / 8 + v2 * 3 / 4 + v3 / 8;
00667 }
00668 
00669 rgrl_spline_sptr
00670 rgrl_spline::
00671 refinement( vnl_vector< unsigned > const& m ) const
00672 {
00673   const unsigned dim = m_.size();
00674   rgrl_spline_sptr refined_spline = new rgrl_spline( m );
00675   vnl_vector< double > w( refined_spline->num_of_control_points() );
00676 
00677   // 0--1--2--3 ==> -0-1-2-3-4-
00678   if ( dim == 1 )
00679   {
00680     for ( unsigned i = 0; i<m_[0]+2; ++i ) {
00681       // 2*i
00682       if ( 2*i < m[0]+3 )
00683       w[2*i] = refine_helper_f1( c_[i], c_[i+1] );
00684       // 2*i+1
00685       if ( i!=m_[0]+1 && 2*i+1 < m[0]+3 )
00686         w[2*i+1] = refine_helper_f2( c_[i], c_[i+1], c_[i+2] );
00687     }
00688   }
00689   else if ( dim == 2 )
00690   {
00691     vcl_vector< double > tmp( m_[1] + 3, 0.0 );
00692     vcl_vector< vcl_vector< double > > v2( m_[0] + 1, tmp );
00693     vcl_vector< vcl_vector< double > > v1( m_[0] + 2, tmp );
00694     unsigned a = m_[0]+3;
00695 
00696     for ( unsigned i=0; i<m_[0]+2; ++i ) {
00697       for ( unsigned j=0, n=i; j<m_[1]+3; ++j, n+=a ) {
00698         v1[i][j] = refine_helper_f1( c_[n], c_[n+1] );
00699         if ( i!=m_[0]+1 )
00700           v2[i][j] = refine_helper_f2( c_[n], c_[n+1], c_[n+2] );
00701       }
00702     }
00703     for ( unsigned i=0; i<m_[0]+2; ++i ) {
00704       for ( unsigned j=0; j<m_[1]+2; ++j ) {
00705         // 2*j
00706         if ( 2*i < m[0]+3 && 2*j < m[1]+3 ) {
00707           w[2*i + 2*j*(m[0]+3)] = refine_helper_f1( v1[i][j], v1[i][j+1] );
00708         }
00709         if ( i!=m_[0]+1 && 2*i+1 < m[0]+3 && 2*j < m[1]+3 ) {
00710           w[2*i+1 + 2*j*(m[0]+3)] = refine_helper_f1( v2[i][j], v2[i][j+1] );
00711         }
00712         // 2*j+1
00713         if ( j!=m_[1]+1 && 2*i < m[0]+3 && 2*j+1 < m[1]+3 ) {
00714           w[2*i + (2*j+1)*(m[0]+3)] = refine_helper_f2( v1[i][j], v1[i][j+1], v1[i][j+2] );
00715         }
00716         if ( i!=m_[0]+1 && j!=m_[1]+1 && 2*i+1 < m[0]+3 && 2*j+1 < m[1]+3 ) {
00717           w[2*i+1 + (2*j+1)*(m[0]+3)] = refine_helper_f2( v2[i][j], v2[i][j+1], v2[i][j+2] );
00718         }
00719       }
00720     }
00721   }
00722   else if ( dim == 3 )
00723   {
00724     vcl_vector< double > tmp( m_[2] + 3, 0.0 );
00725     vcl_vector< vcl_vector< double > > tmp1( m_[1] + 3, tmp );
00726     vcl_vector< vcl_vector< double > > tmp2( m_[1] + 1, tmp );
00727     vcl_vector< vcl_vector< double > > tmp3( m_[1] + 2, tmp );
00728     vcl_vector< vcl_vector< vcl_vector< double > > > v2( m_[0] + 1, tmp1 );
00729     vcl_vector< vcl_vector< vcl_vector< double > > > v1( m_[0] + 2, tmp1 );
00730     vcl_vector< vcl_vector< vcl_vector< double > > > v12( m_[0]+2, tmp2 );
00731     vcl_vector< vcl_vector< vcl_vector< double > > > v22( m_[0]+1, tmp2 );
00732     vcl_vector< vcl_vector< vcl_vector< double > > > v11( m_[0]+2, tmp3 );
00733     vcl_vector< vcl_vector< vcl_vector< double > > > v21( m_[0]+1, tmp3 );
00734 
00735     unsigned b = m_[1]+3;
00736     unsigned a = m_[0]+3;
00737     unsigned ab = a * b;
00738     for ( unsigned i=0; i<m_[0]+2; ++i ) {
00739       for ( unsigned j=0; j<m_[1]+3; ++j ) {
00740         for ( unsigned k=0, n=j*a+i; k<m_[2]+3; ++k, n+=ab ) {
00741           v1[i][j][k] = refine_helper_f1( c_[n], c_[n+1] );
00742           if ( i!=m_[0]+1 )
00743             v2[i][j][k] = refine_helper_f2( c_[n], c_[n+1], c_[n+2] );
00744         }
00745       }
00746     }
00747 
00748     for ( unsigned i=0; i<m_[0]+2; ++i ) {
00749       for ( unsigned j=0; j<m_[1]+2; ++j ) {
00750         for ( unsigned k=0; k<m_[2]+3; ++k ) {
00751           v11[i][j][k] = refine_helper_f1( v1[i][j][k], v1[i][j+1][k] );
00752           if ( i!=m_[0]+1 )
00753             v21[i][j][k] = refine_helper_f1( v2[i][j][k], v2[i][j+1][k] );
00754           if ( j!=m_[1]+1 )
00755             v12[i][j][k] = refine_helper_f2( v1[i][j][k], v1[i][j+1][k], v1[i][j+2][k] );
00756           if ( i!=m_[0]+1 && j!=m_[1]+1 )
00757             v22[i][j][k] = refine_helper_f2( v2[i][j][k], v2[i][j+1][k], v2[i][j+2][k] );
00758         }
00759       }
00760     }
00761 
00762     for ( unsigned i=0; i<m_[0]+2; ++i ) {
00763       for ( unsigned j=0; j<m_[1]+2; ++j ) {
00764         for ( unsigned k=0; k<m_[2]+2; ++k ) {
00765           // 2*k
00766           if ( 2*i < m[0]+3 && 2*j < m[1]+3 && 2*k < m[2]+3 )
00767             w[2*i + 2*j*(m[0]+3) + 2*k*(m[0]+3)*(m[1]+3)] =
00768               refine_helper_f1( v11[i][j][k], v11[i][j][k+1] ) ;
00769           if ( i!=m_[0]+1 && 2*i+1 < m[0]+3 && 2*j < m[1]+3 && 2*k < m[2]+3 )
00770             w[2*i+1 + 2*j*(m[0]+3) + 2*k*(m[0]+3)*(m[1]+3) ] =
00771               refine_helper_f1( v21[i][j][k], v21[i][j][k+1] );
00772           if ( j!=m_[1]+1 && 2*i < m[0]+3 && 2*j+1 < m[1]+3 && 2*k < m[2]+3 )
00773             w[2*i + (2*j+1)*(m[0]+3) + 2*k*(m[0]+3)*(m[1]+3)] =
00774               refine_helper_f1( v12[i][j][k], v12[i][j][k+1] );
00775           if ( i!=m_[0]+1 && j!=m_[1]+1 && 2*i+1 < m[0]+3 && 2*j+1 < m[1]+3 && 2*k < m[2]+3 )
00776           w[2*i+1 + (2*j+1)*(m[0]+3) + 2*k*(m[0]+3)*(m[1]+3) ] =
00777             refine_helper_f1( v22[i][j][k], v22[i][j][k+1] );
00778 
00779           // 2*k+1
00780           if ( k!=m_[2]+1 && 2*i < m[0]+3 && 2*j < m[1]+3 && 2*k+1 < m[2]+3 )
00781             w[2*i + 2*j*(m[0]+3) + (2*k+1)*(m[0]+3)*(m[1]+3)] =
00782               refine_helper_f2( v11[i][j][k], v11[i][j][k+1], v11[i][j][k+2] );
00783           if ( i!=m_[0]+1 && k!=m_[2]+1 && 2*i+1 < m[0]+3 && 2*j < m[1]+3 && 2*k+1 < m[2]+3 )
00784             w[2*i+1 + 2*j*(m[0]+3) + (2*k+1)*(m[0]+3)*(m[1]+3) ] =
00785               refine_helper_f2( v21[i][j][k], v21[i][j][k+1], v21[i][j][k+2] );
00786           if ( j!=m_[1]+1 && k!=m_[2]+1 && 2*i < m[0]+3 && 2*j+1 < m[1]+3 && 2*k+1 < m[2]+3 )
00787             w[2*i + (2*j+1)*(m[0]+3) + (2*k+1)*(m[0]+3)*(m[1]+3)] =
00788               refine_helper_f2( v12[i][j][k], v12[i][j][k+1], v12[i][j][k+2] );
00789           if ( i!=m_[0]+1 && j!=m_[1]+1 && k!=m_[2]+1 && 2*i+1 < m[0]+3 && 2*j+1 < m[1]+3 && 2*k+1 < m[2]+3 )
00790             w[2*i+1 +(2*j+1)*(m[0]+3) + (2*k+1)*(m[0]+3)*(m[1]+3) ] =
00791               refine_helper_f2( v22[i][j][k], v22[i][j][k+1], v22[i][j][k+2] );
00792         }
00793       }
00794     }
00795 #if 0
00796     for ( unsigned i=0; i<m_[0]+2; ++i ) {
00797       for ( unsigned j=0; j<m_[1]+2; ++j ) {
00798         for ( unsigned k=0; k<m_[2]+2; ++k ) {
00799           // 2*k
00800           w[2*i + 2*j*(2*m_[0]+3) + 2*k*(2*m_[0]+3)*(2*m_[1]+3)] =
00801             refine_helper_f1( v11[i][j][k], v11[i][j][k+1] ) ;
00802           if ( i!=m_[0]+1 )
00803             w[2*i+1 + 2*j*(2*m_[0]+3) + 2*k*(2*m_[0]+3)*(2*m_[1]+3) ] =
00804               refine_helper_f1( v21[i][j][k], v21[i][j][k+1] );
00805           if ( j!=m_[1]+1 )
00806             w[2*i + (2*j+1)*(2*m_[0]+3) + 2*k*(2*m_[0]+3)*(2*m_[1]+3)] =
00807               refine_helper_f1( v12[i][j][k], v12[i][j][k+1] );
00808           if ( i!=m_[0]+1 && j!=m_[1]+1 )
00809           w[2*i+1 + (2*j+1)*(2*m_[0]+3) + 2*k*(2*m_[0]+3)*(2*m_[1]+3) ] =
00810             refine_helper_f1( v22[i][j][k], v22[i][j][k+1] );
00811 
00812           // 2*k+1
00813           if ( k!=m_[2]+1 )
00814             w[2*i + 2*j*(2*m_[0]+3) + (2*k+1)*(2*m_[0]+3)*(2*m_[1]+3)] =
00815               refine_helper_f2( v11[i][j][k], v11[i][j][k+1], v11[i][j][k+2] );
00816           if ( i!=m_[0]+1 && k!=m_[2]+1 )
00817             w[2*i+1 + 2*j*(2*m_[0]+3) + (2*k+1)*(2*m_[0]+3)*(2*m_[1]+3) ] =
00818               refine_helper_f2( v21[i][j][k], v21[i][j][k+1], v21[i][j][k+2] );
00819           if ( j!=m_[1]+1 && k!=m_[2]+1 )
00820             w[2*i + (2*j+1)*(2*m_[0]+3) + (2*k+1)*(2*m_[0]+3)*(2*m_[1]+3)] =
00821               refine_helper_f2( v12[i][j][k], v12[i][j][k+1], v12[i][j][k+2] );
00822           if ( i!=m_[0]+1 && j!=m_[1]+1 && k!=m_[2]+1 )
00823             w[2*i+1 +(2*j+1)*(2*m_[0]+3) + (2*k+1)*(2*m_[0]+3)*(2*m_[1]+3) ] =
00824               refine_helper_f2( v22[i][j][k], v22[i][j][k+1], v22[i][j][k+2] );
00825         }
00826       }
00827     }
00828 #endif // 0
00829   }
00830   else
00831     assert ( !"dim should be 1, 2 or 3" );
00832 
00833 #ifdef DEBUG
00834   vcl_cout << "rgrl_spline.cxx: refinement set_control_points: " << w << vcl_endl;
00835 #endif
00836   refined_spline->set_control_points( w );
00837   return refined_spline;
00838 }
00839 
00840 
00841 vcl_ostream&
00842 operator<< (vcl_ostream& os, rgrl_spline const& spline )
00843 {
00844   // output m(# of intervals) vector
00845   os << spline.m_.size() << ' '
00846      << spline.m_ << vcl_endl;
00847 
00848   // control points
00849   os << spline.c_.size() << vcl_endl
00850      << spline.c_;
00851 
00852   //
00853   return os;
00854 }
00855 
00856 vcl_istream&
00857 operator>> (vcl_istream& is, rgrl_spline& spline )
00858 {
00859   int s;
00860 
00861   s=-1;
00862   is >> s;
00863   spline.m_.set_size( s );
00864   is >> spline.m_;
00865 
00866   // control points
00867   s=-1;
00868   is >> s;
00869   spline.c_.set_size( s );
00870   is >> spline.c_;
00871 
00872   return is;
00873 }
00874 
00875 #if 0
00876 bool
00877 rgrl_spline::
00878 is_support( vnl_vector< double > const& pt, unsigned index )
00879 {
00880   assert ( pt.size() == m_.size() );
00881   const unsigned dim = pt.size();
00882 
00883   for ( unsigned i=0; i<m_.size(); ++i )
00884     if ( pt[i] < -3 || pt[i] >= m_[i]+3 )
00885       return false;
00886 
00887   vnl_vector< int > floor(dim);
00888   vnl_vector< int > ceil(dim);
00889 
00890   for ( unsigned n=0; n<dim; ++n ) {
00891     floor[n] = (int)vcl_floor( pt[n] ) ;
00892     ceil[n] = (int)vcl_ceil( pt[n] );
00893   }
00894 
00895   // 3D case
00896   if (dim == 3) {
00897     int a = (m_[0]+3) * (m_[1]+3);
00898     int b = m_[0]+3;
00899 
00900     unsigned blk[ 3 ];
00901     blk[ 0 ] = index % b;
00902     blk[ 1 ] = index % a / b;
00903     blk[ 2 ] = index / a;
00904 
00905     for ( unsigned i = 0; i < dim; ++i )
00906       if ( blk[i] < floor[i] || blk[i] > ceil[i]+2 )
00907         return false;
00908   }
00909   // 2D case
00910   else if (dim == 2) {
00911     int a =(m_[0]+3);
00912     unsigned blk[ 2 ];
00913     blk[ 0 ] = index % a;
00914     blk[ 1 ] = index / a;
00915 
00916     for ( unsigned i = 0; i < dim; ++i )
00917       if ( blk[i] < floor[i] || blk[i] > ceil[i]+2 )
00918         return false;
00919   }
00920   // 1D case
00921   else if (dim == 1) {
00922     if ( index < floor[0] || index > ceil[0]+2 )
00923       return false;
00924   }
00925   return true;
00926 }
00927 #endif // 0