Points&Forces (survey)
Software tools facilitating the task of surveying architecture
a_shape_circle.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2009-2019 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_circle.h"
17 #include <math.h>
18 #include <time.h>
19 #include <vnl/vnl_least_squares_function.h>
20 
21 //***************************************************************************
24 {
25  public:
27  const std::vector<a_point> & cloud) :
28  vnl_least_squares_function(7, cloud.size(), no_gradient),
29  shape_(shape),
30  cloud_(cloud) {};
31  void f(const vnl_vector<double>& x, vnl_vector<double>& fx);
32  protected:
34  const std::vector<a_point> & cloud_;
35 };
36 //---------------------------------------------------------------------------
37 void a_shape_circle_function::f(const vnl_vector<double>& x, vnl_vector<double>& fx)
38 {
39  a_point dir(x[0],x[1],x[2]);
40  a_point orig(x[3],x[4],x[5]);
41  dir.normalise();
42  shape_.dir(dir);
43  // shape_.orig(orig-(dir*orig)*dir);
44  shape_.orig(orig);
45  shape_.radius(x[6]);
46  for (int i = 0; i< fx.size(); i++)
47  fx[i] = shape_.dist_point(cloud_[i]);
48 }
49 //***************************************************************************
50 //---------------------------------------------------------------------------
51 const std::string a_shape_circle::help()
52 {
53  std::ostringstream o;
54  o << "***************" << std::endl;
55  o << "a_shape_circle:" << std::endl;
56  o << "***************" << std::endl;
57  o << "This is a 'circle' fitting class" << std::endl;
58  o << std::endl;
59  o << a_shape::help();
60  return o.str();
61 }
62 //---------------------------------------------------------------------------
63 void a_shape_circle::p3pts(const a_point p1, const a_point p2, const a_point p3)
64 {
65  a_point d1 = p2-p1;
66  a_point d2 = p3-p1;
67  a_point dir = cross(d1,d2);
68  if (dir.norm()==0) return;
69  this->dir(dir.normalise());
70  a_point ce = circle_centre(p1,p2,p3);
71  this->orig(ce);
72  this->radius(((p1-ce).norm()+(p2-ce).norm()+(p3-ce).norm())/3.);
73 }
74 //---------------------------------------------------------------------------
75 a_point a_shape_circle::closest_point(const a_point pt) const
76 {
77  a_point d = pt-this->orig();
78  a_point pv = this->dir()*(this->dir()*d);
79  double dv = pv.norm();
80  a_point ph = (d-pv).normalise();
81  return (this->orig()+ph*this->radius());
82 }
83 //---------------------------------------------------------------------------
84 double a_shape_circle::dist_point(const a_point pt) const
85 {
86  a_point d = pt-this->orig();
87  a_point pv = this->dir()*(this->dir()*d);
88  double dv = pv.norm();
89  a_point ph = d-pv;
90  double dh = ph.norm()-this->radius();
91  return sqrt(dh*dh+dv*dv);
92 }
93 //---------------------------------------------------------------------------
94 void a_shape_circle::random_hint(const std::vector<a_point>& pts)
95 {
96  //srand(time(NULL));
97  int n = pts.size();
98  int i1 = rand()%n;
99  int i2,i3;
100  do
101  {
102  i2 = rand()%n;
103  } while (i1==i2);
104  do
105  {
106  i3 = rand()%n;
107  } while ((i1==i3)||(i2==i3));
108  a_point p1 = pts[i1];
109  a_point p2 = pts[i2];
110  a_point p3 = pts[i3];
111  this->p3pts(p1,p2,p3);
112 }
113 //---------------------------------------------------------------------------
114 void a_shape_circle::fit_cloud(std::vector<a_point>& pts, short nl)
115 {
116  std::vector<a_point> pts2;
117  int cs0 = pts.size();
118  this->best_fitting_cloud(pts,pts2);
119  if (verbose_)
120  {
121  std::cerr << "current estimate:" << std::endl;
122  std::cerr << "c: " << this->orig() << std::endl;
123  std::cerr << "n: " << this->dir() << std::endl;
124  std::cerr << "r: " << this->radius() << std::endl;
125  }
126  if (nl==1)
127  {
128  a_shape_circle_function f(*this,pts2);
129  a_shape::fit_cloud(pts2,f);
130  }
131  pts = pts2;
132 }
133 //---------------------------------------------------------------------------
134 void a_shape_circle::export_points(const unsigned int nseg, const std::vector<a_point>& pts) const
135 {
136  const double pi2 = 2*3.14159265358979;
137  a_point ce = this->orig();
138  a_point nz = this->dir();
139  a_point p, nx, ny;
140  if (fabs(nz.x())>fabs(nz.y()))
141  p = a_point(0.,1.,0.);
142  else
143  p = a_point(1.,0.,0.);
144  nx = cross(p,nz).normalise()*this->radius();
145  ny = cross(nz,nx).normalise()*this->radius();
146  std::cout << nseg << std::endl;
147  for (int i = 0; i<nseg; i++)
148  {
149  double a = i*pi2/nseg;
150  double c = cos(a);
151  double s = sin(a);
152  a_point n = ce+nx*c+ny*s;
153  std::cout << n << std::endl;
154  }
155 }
156 //---------------------------------------------------------------------------
157 void a_shape_circle::export_lines(const unsigned int nseg, const std::vector<a_point>& pts) const
158 {
159  const double pi2 = 2*3.14159265358979;
160  a_point ce = this->orig();
161  a_point nz = this->dir();
162  a_point p, nx, ny;
163  if (fabs(nz.x())>fabs(nz.y()))
164  p = a_point(0.,1.,0.);
165  else
166  p = a_point(1.,0.,0.);
167  nx = cross(p,nz).normalise()*this->radius();
168  ny = cross(nz,nx).normalise()*this->radius();
169  a_point n;
170  a_point n0 = ce+nx;
171  std::cout << nseg << std::endl;
172  for (int i = 1; i<nseg; i++)
173  {
174  double a = i*pi2/nseg;
175  double c = cos(a);
176  double s = sin(a);
177  n = ce+nx*c+ny*s;
178  std::cout << n0 << " " << n << std::endl;
179  n0 = n;
180  }
181  n0 = ce+nx;
182  std::cout << n << " " << n0 << std::endl;
183 }
circle shape solver
a_shape_circle_function(a_shape_circle &shape, const std::vector< a_point > &cloud)
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
a_shape_circle & shape_
const std::vector< a_point > & cloud_
circle shape
a_point orig() const
double radius() const
a_point dir() const
void export_points(const unsigned int nseg, const std::vector< a_point > &pts) const
void export_lines(const unsigned int nseg, const std::vector< a_point > &pts) const
double dist_point(const a_point p) const
void fit_cloud(std::vector< a_point > &pts, short nl=1)
a_point closest_point(const a_point p) const
void random_hint(const std::vector< a_point > &pts)
void p3pts(const a_point p1, const a_point p2, const a_point p3)
static const std::string help()
bool verbose_
Definition: a_shape.h:69
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
int best_fitting_cloud(const std::vector< a_point > &pts, std::vector< a_point > &pts2)
Definition: a_shape.cxx:82
e_point & normalise()
Definition: e_point.cxx:67
e_point cross(e_point &a, e_point &b)
Definition: e_point.cxx:105
uint32_t n[]
Definition: generate.cxx:34
a_point dir(int i, int l)
Definition: rib0.cxx:60
Definition: stlb2stla.cxx:21