contrib/gel/vdgl/vdgl_interpolator_linear.cxx
Go to the documentation of this file.
00001 // This is gel/vdgl/vdgl_interpolator_linear.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include "vdgl_interpolator_linear.h"
00009 #include <vdgl/vdgl_edgel_chain.h>
00010 #include <vsol/vsol_point_2d.h>
00011 #include <vgl/vgl_point_2d.h>
00012 #include <vcl_cmath.h>
00013 #include <vnl/vnl_numeric_traits.h>
00014 #include <vnl/vnl_math.h>
00015 #include <vcl_cassert.h>
00016 
00017 
00018 vdgl_interpolator_linear::vdgl_interpolator_linear( vdgl_edgel_chain_sptr chain)
00019   : vdgl_interpolator( chain)
00020 {
00021   recompute_all();
00022 }
00023 
00024 vdgl_interpolator_linear::~vdgl_interpolator_linear()
00025 {
00026 }
00027 
00028 vsol_point_2d_sptr vdgl_interpolator_linear::closest_point_on_curve ( vsol_point_2d_sptr p )
00029 {
00030   double min_distance = -1.0;
00031   int index = -1;
00032   for ( unsigned int i=0; i< chain_->size(); ++i)
00033   {
00034     vgl_point_2d<double> curve_point = chain_->edgel(i).get_pt();
00035     double d = p->distance ( vsol_point_2d ( curve_point ) );
00036     if ( min_distance < 0 || d < min_distance )
00037     {
00038       index = i;
00039       min_distance = d;
00040     }
00041   }
00042   if ( index == -1 )
00043     return NULL;
00044   else
00045     return new vsol_point_2d ( chain_->edgel(index).get_pt() );
00046 }
00047 
00048 
00049 double vdgl_interpolator_linear::get_x( const double index)
00050 {
00051   assert(index >= 0 && index < chain_->size());
00052   int a = int(index); // round down
00053   double d = index- a;
00054 
00055   double ae = chain_->edgel(a).get_x();
00056   if (d==0) return ae; // exactly at an edgel
00057   double be = chain_->edgel(a+1).get_x();
00058 
00059   return be*d+ae*(1-d);
00060 }
00061 
00062 
00063 double vdgl_interpolator_linear::get_y( const double index)
00064 {
00065   assert(index >= 0 && index < chain_->size());
00066   int a = int(index); // round down
00067   double d = index- a;
00068 
00069   double ae = chain_->edgel(a).get_y();
00070   if (d==0) return ae; // exactly at an edgel
00071   double be = chain_->edgel(a+1).get_y();
00072 
00073   return be*d+ae*(1-d);
00074 }
00075 
00076 //: linearly interpolate the gradient magnitude
00077 //
00078 double vdgl_interpolator_linear::get_grad( const double index)
00079 {
00080   assert(index >= 0 && index < chain_->size());
00081   int a = int(index); // round down
00082   double d = index-a;
00083 
00084   double ae = chain_->edgel(a).get_grad();
00085   if (d==0) return ae; // exactly at an edgel
00086   double be = chain_->edgel(a+1).get_grad();
00087 
00088   return be*d+ae*(1-d);
00089 }
00090 
00091 //: linearly interpolate the gradient direction
00092 //
00093 double vdgl_interpolator_linear::get_theta( const double index)
00094 {
00095   assert(index >= 0 && index < chain_->size());
00096   int a = int(index); // round down
00097   double d = index-a;
00098 
00099   double ae = chain_->edgel(a).get_theta();
00100   if (d==0) return ae; // exactly at an edgel
00101   double be = chain_->edgel(a+1).get_theta();
00102 
00103   return be*d+ae*(1-d);
00104 }
00105 
00106 //: Compute the angle using two adjacent edgels
00107 //  (TargetJr used different computations at internal points and at endpoints
00108 //  For endpoints the geometric tangent was used, but image gradient directions
00109 //  were used for internal points on the chain.)
00110 //  Here we use direct geometric angle computation for all points
00111 //  The image-based directions are likely less accurate
00112 //
00113 double vdgl_interpolator_linear::get_tangent_angle( const double index)
00114 {
00115   int N = chain_->size();
00116   assert(index >= 0 && index <= chain_->size() - 1);
00117   if (N==1)
00118   {
00119     vcl_cout << " vdgl_interpolator_linear::get_theta(..) -"
00120              << " can't compute angle for a chain with one edgel\n";
00121     return 0;
00122   }
00123   int a = int(index); // round down
00124   // if index is exactly at N-1, a+1 is invalid, so take the preceding interval:
00125   if (a == N-1) --a;
00126   assert(a>=0 && a<N-1); // just in case... this should not happen.
00127   double xi = (*chain_)[a].x(), yi = (*chain_)[a].y();
00128   double xip = (*chain_)[a+1].x(), yip = (*chain_)[a+1].y();
00129   double angle = vnl_math::deg_per_rad*vcl_atan2((yip-yi), (xip-xi));
00130   return angle;
00131 }
00132 
00133 
00134 double vdgl_interpolator_linear::get_curvature( const double index)
00135 {
00136   int a = int(index); // round down
00137 
00138   if ( a == index ) // if exactly at an edgel, curvature is undefined
00139     return vnl_numeric_traits<double>::maxval;
00140   else
00141     return 0; // curvature of straight line segments is always zero
00142 }
00143 
00144 
00145 double vdgl_interpolator_linear::get_length()
00146 {
00147   // length is cached (because it's expensive to compute)
00148   if ( older( chain_.ptr()))
00149     recompute_all();
00150 
00151   return lengthcache_;
00152 }
00153 
00154 
00155 double vdgl_interpolator_linear::get_min_x()
00156 {
00157   if ( older( chain_.ptr()))
00158     recompute_all();
00159 
00160   return minxcache_;
00161 }
00162 
00163 
00164 double vdgl_interpolator_linear::get_max_x()
00165 {
00166   if ( older( chain_.ptr()))
00167     recompute_all();
00168 
00169   return maxxcache_;
00170 }
00171 
00172 
00173 double vdgl_interpolator_linear::get_min_y()
00174 {
00175   if ( older( chain_.ptr()))
00176     recompute_all();
00177 
00178   return minycache_;
00179 }
00180 
00181 
00182 double vdgl_interpolator_linear::get_max_y()
00183 {
00184   if ( older( chain_.ptr()))
00185     recompute_all();
00186 
00187   return maxycache_;
00188 }
00189 
00190 // cache maintenance
00191 
00192 void vdgl_interpolator_linear::recompute_all()
00193 {
00194   recompute_length();
00195   recompute_bbox();
00196 
00197   touch();
00198 }
00199 
00200 void vdgl_interpolator_linear::recompute_length()
00201 {
00202   lengthcache_= 0;
00203 
00204   for ( unsigned int i=0; i< chain_->size(); ++i)
00205   {
00206     unsigned int j = i==0 ? chain_->size()-1 : i-1;
00207     vgl_point_2d<double> p1= chain_->edgel(j).get_pt();
00208     vgl_point_2d<double> p2= chain_->edgel(i).get_pt();
00209 
00210     lengthcache_ += length(p2-p1);
00211   }
00212 }
00213 
00214 void vdgl_interpolator_linear::recompute_bbox()
00215 {
00216   if ( chain_->size() == 0 )
00217   {
00218     minxcache_=  maxxcache_= minycache_= maxycache_ = 0.0;
00219     return;
00220   }
00221   minxcache_= chain_->edgel( 0).get_x();
00222   maxxcache_= chain_->edgel( 0).get_x();
00223   minycache_= chain_->edgel( 0).get_y();
00224   maxycache_= chain_->edgel( 0).get_y();
00225 
00226   for (unsigned int i=1; i< chain_->size(); ++i)
00227   {
00228     if (chain_->edgel(i).get_x()< minxcache_) minxcache_= chain_->edgel(i).get_x();
00229     if (chain_->edgel(i).get_x()> maxxcache_) maxxcache_= chain_->edgel(i).get_x();
00230     if (chain_->edgel(i).get_y()< minycache_) minycache_= chain_->edgel(i).get_y();
00231     if (chain_->edgel(i).get_y()> maxycache_) maxycache_= chain_->edgel(i).get_y();
00232   }
00233 }