core/vgl/algo/vgl_fit_lines_2d.txx
Go to the documentation of this file.
00001 // This is core/vgl/algo/vgl_fit_lines_2d.txx
00002 #ifndef vgl_fit_lines_2d_txx_
00003 #define vgl_fit_lines_2d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_fit_lines_2d.h"
00008 #include <vgl/algo/vgl_line_2d_regression.h>
00009 #include <vcl_iostream.h>
00010 #include <vcl_cassert.h>
00011 
00012 //--------------------------------------------------------------
00013 //: Constructor
00014 template <class T>
00015 vgl_fit_lines_2d<T>::vgl_fit_lines_2d(unsigned int min_length, T tol)
00016 {
00017   min_length_ = min_length;
00018   tol_ = tol;
00019   verbose_ = false;
00020 }
00021 
00022 // == OPERATIONS ==
00023 
00024 //: add point
00025 template <class T>
00026 void vgl_fit_lines_2d<T>::add_point(vgl_point_2d<T> const& p)
00027 {
00028   curve_.push_back(p);
00029 #ifdef DEBUG
00030   vcl_cout << p << '\n';
00031 #endif
00032 }
00033 
00034 //: add point
00035 template <class T>
00036 void vgl_fit_lines_2d<T>::add_point(T x, T y)
00037 {
00038   curve_.push_back(vgl_point_2d<T>(x, y));
00039 }
00040 
00041 //: clear
00042 template <class T>
00043 void vgl_fit_lines_2d<T>::clear()
00044 {
00045   curve_.clear();
00046   segs_.clear();
00047   curve_indices_.clear();
00048 }
00049 
00050 template <class T>
00051 void vgl_fit_lines_2d<T>::output(unsigned int start_index, unsigned int end_index)
00052 {
00053   assert(start_index < curve_.size() && end_index <= curve_.size());
00054   vgl_line_segment_2d<T> line(curve_[start_index], curve_[end_index-1]);
00055 #ifdef DEBUG
00056   vcl_cout << "output " << line << '\n';
00057 #endif
00058   for(unsigned i=start_index; i<end_index; ++i)
00059     curve_indices_[i] = segs_.size();
00060   segs_.push_back(line);
00061 }
00062 
00063 template <class T>
00064 bool vgl_fit_lines_2d<T>::fit()
00065 {
00066   if (curve_.size()<min_length_)
00067   {
00068     if(verbose_)
00069       vcl_cout << "In vgl_fit_lines_2d<T>::fit() - "
00070                << "number of points < min_length " << min_length_ << '\n';
00071     return false;
00072   }
00073   // each point initially belongs to no curve
00074   curve_indices_.clear();
00075   curve_indices_.resize(curve_.size(), -1);
00076   //A helper to hold points and do the linear regression
00077   vgl_line_2d_regression<T> reg;
00078   // Start at the beginning of the curve with
00079   // a segment with minimum number of points
00080   unsigned int ns = 0, nf = min_length_, cur_len = curve_.size();
00081   for (unsigned int i = ns; i<nf; ++i)
00082     reg.increment_partial_sums(curve_[i].x(), curve_[i].y());
00083   //The main loop
00084   while (nf<=cur_len)
00085   {
00086     reg.fit();
00087     reg.init_rms_error_est();
00088     if (reg.get_rms_error()<tol_)
00089     {
00090       if (nf==cur_len)
00091       {
00092         output(ns, nf);
00093         return true;
00094       }
00095       bool below_error_tol = true;
00096       bool data_added = false;
00097       while (nf<cur_len&&below_error_tol)
00098       {
00099         vgl_point_2d<T>& p = curve_[nf];
00100         //if the point can be added without exeeding the threshold, do so
00101         double error = reg.get_rms_error_est(p);
00102         below_error_tol = error<tol_;
00103         if (below_error_tol)
00104         {
00105           reg.increment_partial_sums(p.x(), p.y());
00106           data_added = true;
00107           nf++;
00108         }
00109       }
00110        //if no points were added output the line
00111        //and initialize a new fit
00112       if (!data_added)
00113       {
00114         output(ns, nf);
00115         ns = nf-1; nf=ns+min_length_;
00116         if (nf<=cur_len)
00117         {
00118           reg.clear();
00119           for (unsigned int i = ns; i<nf; i++)
00120             reg.increment_partial_sums(curve_[i].x(), curve_[i].y());
00121         }
00122       }
00123     }
00124     // Else the fit is not good enough. We therefore remove the first
00125     // point and add or delete points from the end of the current line
00126     // segment until the resulting segment length is _min_fit_length
00127     else
00128     {
00129       reg.decrement_partial_sums(curve_[ns].x(), curve_[ns].y());
00130       ns++;
00131       if (reg.get_n_pts()>min_length_)
00132         while (reg.get_n_pts()>min_length_+1)
00133         {
00134           reg.decrement_partial_sums(curve_[nf].x(), curve_[nf].y());
00135           nf--;
00136         }
00137       else if (nf<cur_len)
00138       {
00139         reg.increment_partial_sums(curve_[nf].x(), curve_[nf].y());
00140         nf++;
00141       }
00142       else
00143         nf++;
00144     }
00145   }
00146   return true;
00147 }
00148 
00149 //--------------------------------------------------------------------------
00150 #undef VGL_FIT_LINES_2D_INSTANTIATE
00151 #define VGL_FIT_LINES_2D_INSTANTIATE(T) \
00152 template class vgl_fit_lines_2d<T >
00153 
00154 #endif // vgl_fit_lines_2d_txx_