vgl_fit_lines_2d.hxx
Go to the documentation of this file.
1 // This is core/vgl/algo/vgl_fit_lines_2d.hxx
2 #ifndef vgl_fit_lines_2d_hxx_
3 #define vgl_fit_lines_2d_hxx_
4 //:
5 // \file
6 
7 #include <iostream>
8 #include "vgl_fit_lines_2d.h"
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 #include <cassert>
14 
15 //--------------------------------------------------------------
16 //: Constructor
17 template <class T>
18 vgl_fit_lines_2d<T>::vgl_fit_lines_2d(unsigned int min_length, T tol)
19 {
20  min_length_ = min_length;
21  tol_ = tol;
22  verbose_ = false;
23 }
24 
25 // == OPERATIONS ==
26 
27 //: add point
28 template <class T>
30 {
31  curve_.push_back(p);
32 #ifdef DEBUG
33  std::cout << p << '\n';
34 #endif
35 }
36 
37 //: add point
38 template <class T>
40 {
41  curve_.push_back(vgl_point_2d<T>(x, y));
42 }
43 
44 //: clear
45 template <class T>
47 {
48  curve_.clear();
49  segs_.clear();
50  curve_indices_.clear();
51 }
52 
53 template <class T>
54 void vgl_fit_lines_2d<T>::output(unsigned int start_index, unsigned int end_index)
55 {
56  assert(start_index < curve_.size() && end_index <= curve_.size());
57  vgl_line_segment_2d<T> line(curve_[start_index], curve_[end_index-1]);
58 #ifdef DEBUG
59  std::cout << "output " << line << '\n';
60 #endif
61  for(unsigned i=start_index; i<end_index; ++i)
62  curve_indices_[i] = segs_.size();
63  segs_.push_back(line);
64 }
65 
66 template <class T>
68 {
69  if (curve_.size()<min_length_)
70  {
71  if(verbose_)
72  std::cout << "In vgl_fit_lines_2d<T>::fit() - "
73  << "number of points < min_length " << min_length_ << '\n';
74  return false;
75  }
76  // each point initially belongs to no curve
77  curve_indices_.clear();
78  curve_indices_.resize(curve_.size(), -1);
79  //A helper to hold points and do the linear regression
81  // Start at the beginning of the curve with
82  // a segment with minimum number of points
83  unsigned int ns = 0, nf = min_length_, cur_len = curve_.size();
84  for (unsigned int i = ns; i<nf; ++i)
85  reg.increment_partial_sums(curve_[i].x(), curve_[i].y());
86  //The main loop
87  while (nf<=cur_len)
88  {
89  reg.fit();
90  reg.init_rms_error_est();
91  if (reg.get_rms_error()<tol_)
92  {
93  if (nf==cur_len)
94  {
95  output(ns, nf);
96  return true;
97  }
98  bool below_error_tol = true;
99  bool data_added = false;
100  while (nf<cur_len&&below_error_tol)
101  {
102  vgl_point_2d<T>& p = curve_[nf];
103  //if the point can be added without exeeding the threshold, do so
104  double error = reg.get_rms_error_est(p);
105  below_error_tol = error<tol_;
106  if (below_error_tol)
107  {
108  reg.increment_partial_sums(p.x(), p.y());
109  data_added = true;
110  nf++;
111  }
112  }
113  //if no points were added output the line
114  //and initialize a new fit
115  if (!data_added)
116  {
117  output(ns, nf);
118  ns = nf-1; nf=ns+min_length_;
119  if (nf<=cur_len)
120  {
121  reg.clear();
122  for (unsigned int i = ns; i<nf; i++)
123  reg.increment_partial_sums(curve_[i].x(), curve_[i].y());
124  }
125  }
126  }
127  // Else the fit is not good enough. We therefore remove the first
128  // point and add or delete points from the end of the current line
129  // segment until the resulting segment length is _min_fit_length
130  else
131  {
132  reg.decrement_partial_sums(curve_[ns].x(), curve_[ns].y());
133  ns++;
134  if (reg.get_n_pts()>min_length_)
135  while (reg.get_n_pts()>min_length_+1)
136  {
137  reg.decrement_partial_sums(curve_[nf].x(), curve_[nf].y());
138  nf--;
139  }
140  else if (nf<cur_len)
141  {
142  reg.increment_partial_sums(curve_[nf].x(), curve_[nf].y());
143  nf++;
144  }
145  else
146  nf++;
147  }
148  }
149  return true;
150 }
151 
152 //--------------------------------------------------------------------------
153 #undef VGL_FIT_LINES_2D_INSTANTIATE
154 #define VGL_FIT_LINES_2D_INSTANTIATE(T) \
155 template class vgl_fit_lines_2d<T >
156 
157 #endif // vgl_fit_lines_2d_hxx_
bool fit()
the fitting method.
void clear()
clear internal data.
vgl_fit_lines_2d(unsigned int min_length=10, T tol=0.15)
Constructor.
bool fit()
Fit a line to the current point set.
double get_rms_error_est(vgl_point_2d< T > const &p, bool increment=true)
Get estimated fitting error if the point (x, y) were added to the fit.
unsigned int get_n_pts() const
The number of points added.
A class to hold the line 2d_regression data and actual fitting code.
Definition: vgl_algo_fwd.h:7
double get_rms_error(const T a, const T b, const T c)
Get fitting error for a given line.
void increment_partial_sums(const T x, const T y)
Add a point to the 2d_regression.
void init_rms_error_est()
Initialize estimated fitting error.
void clear()
Clear 2d_regression sums.
void decrement_partial_sums(const T x, const T y)
Remove a point from the 2d_regression.
Fits a contiguous set of line segments to a sampled curve.
Type & y()
Definition: vgl_point_2d.h:72
A helper class for line fitting.
void add_point(vgl_point_2d< T > const &p)
add a point to the curve.
void output(unsigned int start_index, unsigned int end_index)
output a line that fits from start to end.
Type & x()
Definition: vgl_point_2d.h:71