Points&Forces (survey)
Software tools facilitating the task of surveying architecture
a_shape.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2009-2020 Pierre SMARS (smars@yuntech.edu.tw)
3  This program is free software: you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation, either version 2 of the License, or
6  (at your option) any later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 #include "a_shape.h"
17 #include <iostream>
18 #include <sstream>
19 #include <vnl/algo/vnl_levenberg_marquardt.h>
20 //---------------------------------------------------------------------------
21 const std::string a_shape::help()
22 {
23  std::ostringstream o;
24  o << "********" << std::endl;
25  o << "a_shape:" << std::endl;
26  o << "********" << std::endl;
27  o << "This library provides classes to fit shapes to point clouds." << std::endl;
28  o << "classes: a_shape_line, a_shape_circle, a_shape_sphere, a_shape_plane, a_shape_quadric, a_shape_cylinder" << std::endl;
29  o << "use a_shape_line_help for more explanations." << std::endl;
30  o << a_base::help();
31  return o.str();
32 }
33 //---------------------------------------------------------------------------
35 {
36  para_.clear();
37 }
38 //---------------------------------------------------------------------------
39 double a_shape::dist_cloud(const std::vector<a_point>& pts)
40 {
41  double d=0;
42  this->init_dist();
43  for (auto pt:pts)
44  d += this->dist_point(pt);
45  return d;
46 }
47 //---------------------------------------------------------------------------
48 double a_shape::average_dist_cloud(const std::vector<a_point>& pts)
49 {
50  return this->dist_cloud(pts)/pts.size();
51 }
52 //---------------------------------------------------------------------------
53 double a_shape::rms_dist_cloud(const std::vector<a_point>& pts)
54 {
55  double d=0;
56  this->init_dist();
57  for (auto pt:pts)
58  {
59  double di = this->dist_point(pt);
60  d += di*di;
61  }
62  return sqrt(d/pts.size());
63 }
64 //---------------------------------------------------------------------------
65 int a_shape::threshold_cloud(const std::vector<a_point>& pts, std::vector<a_point>& pts2)
66 {
67  int iter = 0;
68  pts2.clear();
69  this->init_dist();
70  for (auto pt:pts)
71  {
72  double d = this->dist_point(pt);
73  if (d<verysmall_)
74  {
75  pts2.push_back(pt);
76  iter += 1;
77  }
78  }
79  return iter;
80 }
81 //---------------------------------------------------------------------------
82 int a_shape::best_fitting_cloud(const std::vector<a_point>& pts, std::vector<a_point>& pts2)
83 {
84  const double P = log(1.-P_);
85  int niter = 1000000; // very big number
86  int nc0 = pts.size();
87  vnl_vector<double> bpara;
88  int npara=this->npara();
89  std::vector<a_point> bfit;
90  int nf0 = 0;
91  double w = 0.;
92  int i = 0;
93  while (i<niter)
94  {
95  this->random_hint(pts);
96  int nf = threshold_cloud(pts,bfit);
97  if (nf>nf0)
98  {
99  nf0 = nf;
100  pts2 = bfit;
101  bpara = para_;
102  w = nf/double(nc0); //proportion of inliers
103  std::cerr << "proportion of inliers: " << w*100 << "%" << std::endl;
104  //new estimate of the number of iterations necessary to achieve
105  //a probability P_ that we got a sample with 100% inliers
106  double niterd = P/log(1.-exp(npara*log(w)));
107  //if it is too big, probably a bad sample anyway, do not change value!
108  if (niterd<1000000)
109  niter = int(niterd+.5);
110  if (niter<0)
111  niter = 1000000;
112  std::cerr << i << " " << niterd << std::endl;
113  }
114  i++;
115  }
116  if (verbose_)
117  {
118  std::cerr << "RANSAC: number of random tests: " << i << std::endl;
119  std::cerr << nf0 << " inliers in a cloud of " << pts.size()
120  << " points (RANSAC sample)" <<std::endl;
121  }
122  para_ = bpara;
123  return nf0;
124 }
125 //---------------------------------------------------------------------------
126 void a_shape::fit_cloud(const std::vector<a_point>& pts, vnl_least_squares_function& f)
127 {
128  if (verbose_)
129  std::cerr << "rms dist (RANSAC sample, before LSF): " << this->rms_dist_cloud(pts) << std::endl;
130  vnl_vector<double> x0 = this->getparameters();
131  vnl_vector<double> x = x0;
132  vnl_levenberg_marquardt levmarq(f);
133  levmarq.minimize(x);
134  if (verbose_)
135  {
136  std::cerr << "Least Squares Fitting (Levenberg Marquardt)" << std::endl
137  << "min: " << levmarq.get_end_error() << " at " << x << std::endl;
138  levmarq.diagnose_outcome();
139  std::cerr << "rms dist (RANSAC sample, after LSF): " << this->rms_dist_cloud(pts) << std::endl;
140  }
141 }
142 //---------------------------------------------------------------------------
143 void a_shape::export_inliers(const std::vector<a_point>& pts)
144 {
145  int n = 0;
146  this->init_dist();
147  for (auto pt:pts)
148  {
149  double d = this->dist_point(pt);
150  if (d<=verysmall_)
151  n++;
152  }
153  if (n>0)
154  {
155  std::cout << n << std::endl;
156  for (auto pt:pts)
157  {
158  double d = this->dist_point(pt);
159  if (d<=verysmall_)
160  std::cout << pt << std::endl;
161  }
162  }
163 }
164 //---------------------------------------------------------------------------
165 void a_shape::export_outliers(const std::vector<a_point>& pts)
166 {
167  int n = 0;
168  this->init_dist();
169  for (auto pt:pts)
170  {
171  double d = this->dist_point(pt);
172  if (d>verysmall_)
173  n++;
174  }
175  if (n>0)
176  {
177  std::cout << n << std::endl;
178  for (auto pt:pts)
179  {
180  double d = this->dist_point(pt);
181  if (d>verysmall_)
182  std::cout << pt << std::endl;
183  }
184  }
185 }
186 //***************************************************************************
187 //-operator>>----------------------------------------------------------------
188 /*std::istream& operator>> (std::istream& i, a_shape& v)
189  {
190  return i;
191  }*/
192 //-operator<<----------------------------------------------------------------
193 std::ostream& operator<< (std::ostream& o, const a_shape& v)
194 {
195  o << v.classname() << std::endl;
196  o << v.small() << std::endl;
197  o << v.getparameters() << std::endl;
198  return o;
199 }
200 
std::ostream & operator<<(std::ostream &o, const a_shape &v)
Definition: a_shape.cxx:193
shape
Definition: a_shape.h:32
double rms_dist_cloud(const std::vector< a_point > &pts)
Definition: a_shape.cxx:53
vnl_vector< double > para_
Definition: a_shape.h:68
double dist_cloud(const std::vector< a_point > &pts)
Definition: a_shape.cxx:39
void export_outliers(const std::vector< a_point > &pts)
Definition: a_shape.cxx:165
virtual void random_hint(const std::vector< a_point > &pts)=0
int threshold_cloud(const std::vector< a_point > &pts, std::vector< a_point > &pts2)
Definition: a_shape.cxx:65
unsigned int npara() const
Definition: a_shape.h:41
bool verbose_
Definition: a_shape.h:69
double P() const
Definition: a_shape.h:40
double average_dist_cloud(const std::vector< a_point > &pts)
Definition: a_shape.cxx:48
void fit_cloud(const std::vector< a_point > &pts, vnl_least_squares_function &fn)
Definition: a_shape.cxx:126
static const std::string help()
Definition: a_shape.cxx:21
double P_
Definition: a_shape.h:67
virtual double dist_point(const a_point p) const =0
virtual ~a_shape()
Definition: a_shape.cxx:34
vnl_vector< double > getparameters() const
Definition: a_shape.h:56
int best_fitting_cloud(const std::vector< a_point > &pts, std::vector< a_point > &pts2)
Definition: a_shape.cxx:82
virtual void init_dist()
Definition: a_shape.h:63
void export_inliers(const std::vector< a_point > &pts)
Definition: a_shape.cxx:143
double v(const uint32_t step, const uint32_t n)
Definition: generate.cxx:42
uint32_t n[]
Definition: generate.cxx:34
Definition: stlb2stla.cxx:21