1 // This is gel/vdgl/vdgl_interpolator_linear.cxx 2 //: 3 // \file 4 5 #include <iostream> 6 #include <cmath> 7 #include "vdgl_interpolator_linear.h" 8 #include <vdgl/vdgl_edgel_chain.h> 9 #include <vsol/vsol_point_2d.h> 10 #include "vgl/vgl_point_2d.h" 11 #ifdef _MSC_VER 12 # include "vcl_msvc_warnings.h" 13 #endif 14 #include "vnl/vnl_numeric_traits.h" 15 #include "vnl/vnl_math.h" 16 #include <cassert> 17 18 vdgl_interpolator_linear(const vdgl_edgel_chain_sptr & chain)19vdgl_interpolator_linear::vdgl_interpolator_linear( const vdgl_edgel_chain_sptr& chain) 20 : vdgl_interpolator( chain) 21 { 22 recompute_all(); 23 } 24 25 vdgl_interpolator_linear::~vdgl_interpolator_linear() = default; 26 closest_point_on_curve(vsol_point_2d_sptr p)27vsol_point_2d_sptr vdgl_interpolator_linear::closest_point_on_curve ( vsol_point_2d_sptr p ) 28 { 29 double min_distance = -1.0; 30 int index = -1; 31 for ( unsigned int i=0; i< chain_->size(); ++i) 32 { 33 vgl_point_2d<double> curve_point = chain_->edgel(i).get_pt(); 34 double d = p->distance ( vsol_point_2d ( curve_point ) ); 35 if ( min_distance < 0 || d < min_distance ) 36 { 37 index = i; 38 min_distance = d; 39 } 40 } 41 if ( index == -1 ) 42 return nullptr; 43 else 44 return new vsol_point_2d ( chain_->edgel(index).get_pt() ); 45 } 46 47 get_x(const double index)48double vdgl_interpolator_linear::get_x( const double index) 49 { 50 assert(index >= 0 && index < chain_->size()); 51 int a = int(index); // round down 52 double d = index- a; 53 54 double ae = chain_->edgel(a).get_x(); 55 if (d==0) return ae; // exactly at an edgel 56 double be = chain_->edgel(a+1).get_x(); 57 58 return be*d+ae*(1-d); 59 } 60 61 get_y(const double index)62double vdgl_interpolator_linear::get_y( const double index) 63 { 64 assert(index >= 0 && index < chain_->size()); 65 int a = int(index); // round down 66 double d = index- a; 67 68 double ae = chain_->edgel(a).get_y(); 69 if (d==0) return ae; // exactly at an edgel 70 double be = chain_->edgel(a+1).get_y(); 71 72 return be*d+ae*(1-d); 73 } 74 75 //: linearly interpolate the gradient magnitude 76 // get_grad(const double index)77double vdgl_interpolator_linear::get_grad( const double index) 78 { 79 assert(index >= 0 && index < chain_->size()); 80 int a = int(index); // round down 81 double d = index-a; 82 83 double ae = chain_->edgel(a).get_grad(); 84 if (d==0) return ae; // exactly at an edgel 85 double be = chain_->edgel(a+1).get_grad(); 86 87 return be*d+ae*(1-d); 88 } 89 90 //: linearly interpolate the gradient direction 91 // get_theta(const double index)92double vdgl_interpolator_linear::get_theta( const double index) 93 { 94 assert(index >= 0 && index < chain_->size()); 95 int a = int(index); // round down 96 double d = index-a; 97 98 double ae = chain_->edgel(a).get_theta(); 99 if (d==0) return ae; // exactly at an edgel 100 double be = chain_->edgel(a+1).get_theta(); 101 102 return be*d+ae*(1-d); 103 } 104 105 //: Compute the angle using two adjacent edgels 106 // (TargetJr used different computations at internal points and at endpoints 107 // For endpoints the geometric tangent was used, but image gradient directions 108 // were used for internal points on the chain.) 109 // Here we use direct geometric angle computation for all points 110 // The image-based directions are likely less accurate 111 // get_tangent_angle(const double index)112double vdgl_interpolator_linear::get_tangent_angle( const double index) 113 { 114 int N = chain_->size(); 115 assert(index >= 0 && index <= chain_->size() - 1); 116 if (N==1) 117 { 118 std::cout << " vdgl_interpolator_linear::get_theta(..) -" 119 << " can't compute angle for a chain with one edgel\n"; 120 return 0; 121 } 122 int a = int(index); // round down 123 // if index is exactly at N-1, a+1 is invalid, so take the preceding interval: 124 if (a == N-1) --a; 125 assert(a>=0 && a<N-1); // just in case... this should not happen. 126 double xi = (*chain_)[a].x(), yi = (*chain_)[a].y(); 127 double xip = (*chain_)[a+1].x(), yip = (*chain_)[a+1].y(); 128 double angle = vnl_math::deg_per_rad*std::atan2((yip-yi), (xip-xi)); 129 return angle; 130 } 131 132 get_curvature(const double index)133double vdgl_interpolator_linear::get_curvature( const double index) 134 { 135 int a = int(index); // round down 136 137 if ( a == index ) // if exactly at an edgel, curvature is undefined 138 return vnl_numeric_traits<double>::maxval; 139 else 140 return 0; // curvature of straight line segments is always zero 141 } 142 143 get_length()144double vdgl_interpolator_linear::get_length() 145 { 146 // length is cached (because it's expensive to compute) 147 if ( older( chain_.ptr())) 148 recompute_all(); 149 150 return lengthcache_; 151 } 152 153 get_min_x()154double vdgl_interpolator_linear::get_min_x() 155 { 156 if ( older( chain_.ptr())) 157 recompute_all(); 158 159 return minxcache_; 160 } 161 162 get_max_x()163double vdgl_interpolator_linear::get_max_x() 164 { 165 if ( older( chain_.ptr())) 166 recompute_all(); 167 168 return maxxcache_; 169 } 170 171 get_min_y()172double vdgl_interpolator_linear::get_min_y() 173 { 174 if ( older( chain_.ptr())) 175 recompute_all(); 176 177 return minycache_; 178 } 179 180 get_max_y()181double vdgl_interpolator_linear::get_max_y() 182 { 183 if ( older( chain_.ptr())) 184 recompute_all(); 185 186 return maxycache_; 187 } 188 189 // cache maintenance 190 recompute_all()191void vdgl_interpolator_linear::recompute_all() 192 { 193 recompute_length(); 194 recompute_bbox(); 195 196 touch(); 197 } 198 recompute_length()199void vdgl_interpolator_linear::recompute_length() 200 { 201 lengthcache_= 0; 202 203 for ( unsigned int i=0; i< chain_->size(); ++i) 204 { 205 unsigned int j = i==0 ? chain_->size()-1 : i-1; 206 vgl_point_2d<double> p1= chain_->edgel(j).get_pt(); 207 vgl_point_2d<double> p2= chain_->edgel(i).get_pt(); 208 209 lengthcache_ += length(p2-p1); 210 } 211 } 212 recompute_bbox()213void vdgl_interpolator_linear::recompute_bbox() 214 { 215 if ( chain_->size() == 0 ) 216 { 217 minxcache_= maxxcache_= minycache_= maxycache_ = 0.0; 218 return; 219 } 220 minxcache_= chain_->edgel( 0).get_x(); 221 maxxcache_= chain_->edgel( 0).get_x(); 222 minycache_= chain_->edgel( 0).get_y(); 223 maxycache_= chain_->edgel( 0).get_y(); 224 225 for (unsigned int i=1; i< chain_->size(); ++i) 226 { 227 if (chain_->edgel(i).get_x()< minxcache_) minxcache_= chain_->edgel(i).get_x(); 228 if (chain_->edgel(i).get_x()> maxxcache_) maxxcache_= chain_->edgel(i).get_x(); 229 if (chain_->edgel(i).get_y()< minycache_) minycache_= chain_->edgel(i).get_y(); 230 if (chain_->edgel(i).get_y()> maxycache_) maxycache_= chain_->edgel(i).get_y(); 231 } 232 } 233