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 }