Points&Forces (survey)
Software tools facilitating the task of surveying architecture
a_curve.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2002-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_curve.h"
17 #include "a_segment.h"
18 #include <iomanip>
19 #include <stdlib.h>
20 
21 // .PORTABILITY : ansi C++
22 
23 //***************************************************************************
24 const a_point horiz0(0,1,0);
25 //---------------------------------------------------------------------------
26 a_curve::a_curve(double da) : da_(da)
27 {
28  initialised_ = false;
29  orient_ = 1;
30  n_pts_ = 0;
31  horiz_ = horiz0;
32 }
33 //---------------------------------------------------------------------------
35 {
36  initialised_ = false;
37  da_ = ifn.da();
38  orient_ = ifn.orient_;
39  horiz_ = ifn.horiz_;
40  for (int i = 0; i < ifn.size(); i++)
41  {
42  auto p = new a_point;
43  *p = *ifn[i];
44  x_.push_back(p);
45  }
46  this->init();
47 }
48 //---------------------------------------------------------------------------
50 {
51  for (auto c:x_)
52  delete c;
53  x_.clear();
54 }
55 //---------------------------------------------------------------------------
57 {
58  if (!initialised_)
59  {
60  initialised_ = true;
61  n_pts_ = x_.size();
62  this->construct_axis();
63  }
64  return *this;
65 }
66 //---------------------------------------------------------------------------
67 a_point a_curve::dz_axis(double a) const
68 {
69  //tangent along the path
70  a_point xi,xs;
71  if (a-da_<0)
72  {
73  if (this->is_closed())
74  {
75  xi = (*this)(a-da_+1.);
76  xs = (*this)(a+da_);
77  return (.5*(xs-xi)/da_);
78  }
79  else
80  {
81  xi = (*this)(a);
82  xs = (*this)(a+da_);
83  return ((xs-xi)/da_);
84  }
85  }
86  else if (a+da_>1)
87  {
88  if (this->is_closed())
89  {
90  xi = (*this)(a-da_);
91  xs = (*this)(a+da_-1.);
92  return (.5*(xs-xi)/da_);
93  }
94  else
95  {
96  xi = (*this)(a-da_);
97  xs = (*this)(a);
98  return ((xs-xi)/da_);
99  }
100  }
101  else
102  {
103  xi = (*this)(a-da_);
104  xs = (*this)(a+da_);
105  return (.5*(xs-xi)/da_);
106  }
107 }
108 //---------------------------------------------------------------------------
109 bool a_curve::is_closed() const
110 {
111  a_point * p0 = (*this)[0];
112  a_point * pn = (*this)[this->size()-1];
113  return ((*p0)==(*pn));
114 }
115 //---------------------------------------------------------------------------
116 a_point a_curve::dy_axis(double a) const
117 {
118  a_point xi,xs;
119  if (a-da_<0)
120  {
121  xi = this->dz_axis(a);
122  xs = this->dz_axis(a+da_);
123  return ((xs-xi)/da_);
124  }
125  else if (a-da_>1)
126  {
127  xi = this->dz_axis(a-da_);
128  xs = this->dz_axis(a);
129  return ((xs-xi)/da_);
130  }
131  else
132  {
133  xi = this->dz_axis(a-da_);
134  xs = this->dz_axis(a+da_);
135  return (.5*(xs-xi)/da_);
136  }
137 }
138 //---------------------------------------------------------------------------
139 a_point a_curve::dx_axis(double a) const
140 {
141  a_point z = this->dz_axis(a);
142  a_point y = this->dy_axis(a);
143  return cross(y,z);
144 }
145 //---------------------------------------------------------------------------
147 {
148  a_point pd = p-*x_[0];
149  return this->translate(pd);
150 }
151 //---------------------------------------------------------------------------
152 a_curve& a_curve::origin(double x, double y, double z)
153 {
154  a_point p(x,y,z);
155  return this->origin(p);
156 }
157 //---------------------------------------------------------------------------
158 a_point a_curve::centre() const
159 {
160  a_point sum;
161  int n_pts = x_.size();
162  for (int i = 0; i < n_pts; i++)
163  sum += *x_[i];
164  return sum/n_pts;
165 }
166 //---------------------------------------------------------------------------
167 /*a_curve& a_curve::invert()
168  {
169  int n_pts = x_.size();
170  std::vector<a_point *> x(n_pts);
171  for (int i = 0; i < n_pts; i++)
172  x[i] = x_[n_pts-i-1];
173  for (int i = 0; i < n_pts; i++)
174  x_[i] = x[i];
175  x.clear();
176  return *this;
177  }*/
178 //---------------------------------------------------------------------------
179 a_curve& a_curve::translate(const a_point & p)
180 {
181  int n_pts = x_.size();
182  for (int i = 0; i < n_pts; i++)
183  *x_[i] += p;
184  return *this;
185 }
186 //---------------------------------------------------------------------------
187 a_curve& a_curve::translate(double x, double y, double z)
188 {
189  a_point p(x,y,z);
190  return this->translate(p);
191 }
192 //---------------------------------------------------------------------------
194 {
195  //project the set of point on the plan passing by the centre of the set and having
196  double f0 = (*x_[0])*z_axis_;
197  for (int i = 0; i < n_pts_; i++)
198  {
199  double f = (*x_[i])*z_axis_;
200  a_point p = *x_[i] - z_axis_*(f-f0);
201  *x_[i] = p;
202  }
203  initialised_ = false;
204  return this->init();
205 }
206 //---------------------------------------------------------------------------
208 {
209  a_point x0 = *x_[0];
210  for (int i = 0; i < n_pts_; i++)
211  {
212  a_point x1 = *x_[i]-x0;
213  x_[i]->set(x1*x_axis_,x1*y_axis_,0);
214  }
215  initialised_ = false;
216  return this->init();
217 }
218 //---------------------------------------------------------------------------
219 a_curve& a_curve::place3D(a_point& origin, a_point& x_axis, a_point& y_axis)
220 {
221  for (int i = 0; i < n_pts_; i++)
222  {
223  a_point po = *x_[i];
224  *x_[i] = origin+po.x()*x_axis+po.y()*y_axis;
225  }
226  initialised_ = false;
227  return this->init();
228 }
229 //---------------------------------------------------------------------------
231 {
233  return *this;
234 }
235 //---------------------------------------------------------------------------
237 {
238  // a_point horizontal(1,0,0);
239  if ((z_axis_-horiz_).norm()<1e-5)//the plane is vertical // xz
240  y_axis_ = a_point(0,0,1);
241  else if ((z_axis_+horiz_).norm()<1e-5)//the plane is vertical // xz
242  y_axis_ = a_point(0,0,-1);
243  else
244  y_axis_ = (cross(z_axis_,horiz_)).normalise();
245  return *this;
246 }
247 //---------------------------------------------------------------------------
248 //find the average perpendicular to the set of points
250 {
251  a_point centre = this->centre();
252  a_point perp;
253  for (int i = 0; i < n_pts_-1; i++)
254  {
255  a_point pt = *x_[i+1]-*x_[i];
256  a_point pr = *x_[i]-centre;
257  perp += cross(pr,pt);
258  }
259  a_point pt = *x_[0]-**(x_.end()-1);
260  a_point pr = **(x_.end()-1)-centre;
261  perp += cross(pr,pt);
262  perp.normalise();
263  z_axis_ = orient_*perp;
264  return *this;
265 }
266 //---------------------------------------------------------------------------
268 {
269  a_point centre = this->centre();
270  a_point perp;
271  for (int i = 0; i < n_pts_-1; i++)
272  {
273  a_point pt = *x_[i+1]-*x_[i];
274  a_point pr = *x_[i]-centre;
275  perp += cross(pr,pt);
276  }
277  a_point pt = *x_[0]-**(x_.end()-1);
278  a_point pr = **(x_.end()-1)-centre;
279  perp += cross(pr,pt);
280  if (perp.norm()<1e-8) //only a line
281  {
282  x_axis_ = (*x_[1]-*x_[0]).normalise();
283  a_point p(0,0,1);
284  if (cross(p,x_axis_).norm()<1e-8)
285  {
286  std::cerr << "this case is not yet supported (see code a_curve)" << std::endl;
287  exit(-1);
288  }
289  p += x_axis_;
290  perp = cross(p,x_axis_).normalise();
291  y_axis_ = orient_*perp;
293  return *this;
294  }
295  else
297 }
298 //---------------------------------------------------------------------------
299 double a_curve::dist(const a_point & p, int & ref) const
300 {
301  double d0 = 1e30;
302  int i0;
303  int n_pts = x_.size();
304  for (int i = 0; i < n_pts; i++)
305  {
306  double d = ((*x_[i])-p).norm();
307  if (d<d0)
308  {
309  d0 = d;
310  ref = i;
311  }
312  }
313  return d0;
314 }
315 //---------------------------------------------------------------------------
316 double a_curve::dist2(const a_point & p, int & ref, double & m) const
317 {
318  double d0 = 1e30;
319  a_point a0;
320  int i0;
321  int n_pts = x_.size();
322  for (int i = 0; i < n_pts-1; i++)
323  {
324  a_segment s(*x_[i],*x_[i+1]);
325  a_point a = s.closest(p);
326  double d = (a-p).norm();
327  if (d<d0)
328  {
329  d0 = d;
330  a0 = a;
331  ref = i;
332  }
333  }
334  m = (a0-*x_[ref]).norm()/(*x_[ref+1]-*x_[ref]).norm();
335  return d0;
336 }
337 //---------------------------------------------------------------------------
338 double a_curve::dist_last(const a_point & p, int & ref) const
339 {
340  double d0 = 1e30;
341  int i0;
342  int n_pts = x_.size();
343  for (int i = 0; i < n_pts; i++)
344  {
345  double d = ((*x_[i])-p).norm();
346  if (d<=d0)
347  {
348  d0 = d;
349  ref = i;
350  }
351  }
352  return d0;
353 }
354 //---------------------------------------------------------------------------
355 double a_curve::dist(const a_curve & fn, int & ref1, int & ref2) const
356 {
357  double d0 = 1e30;
358  int i0;
359  int n_pts = fn.size();
360  for (int i = 0; i < n_pts; i++)
361  {
362  int ref1t;
363  double d = this->dist(*fn[i],ref1t);
364  if (d<d0)
365  {
366  d0 = d;
367  ref1 = ref1t;
368  ref2 = i;
369  }
370  }
371  return d0;
372 }
373 //---------------------------------------------------------------------------
374 double a_curve::dist_last(const a_curve & fn, int & ref1, int & ref2) const
375 {
376  double d0 = 1e30;
377  int i0;
378  int n_pts = fn.size();
379  for (int i = 0; i < n_pts; i++)
380  {
381  int ref1t;
382  double d = this->dist_last(*fn[i],ref1t);
383  if (d<=d0)
384  {
385  d0 = d;
386  ref1 = ref1t;
387  ref2 = i;
388  }
389  }
390  return d0;
391 }
392 //---------------------------------------------------------------------------
393 a_segment a_curve::shortest(const a_curve & fn, int & ref1, int & ref2, double& m1, double& m2) const
394 {
395  a_segment sshort;
396  const double eps = 1e-10;
397  double d0 = 1e30;
398  double mm1,mm2;
399  int n_pt2 = fn.size();
400  for (int i2 = 0; i2 < n_pt2-1; i2++)
401  {
402  a_segment seg2(*fn[i2],*fn[i2+1]);
403  if (seg2.length()<eps)
404  {
405  std::cerr << "error: |seg2(" << i2+1 << ")| ~= 0" << std::endl;
406  exit(-1);
407  }
408  int n_pt1 = x_.size();
409  for (int i1 = 0; i1 < n_pt1-1; i1++)
410  {
411  a_segment seg1(*x_[i1],*x_[i1+1]);
412  if (seg1.length()<eps)
413  {
414  std::cerr << "error: |seg1(" << i1+1 << ")| ~= 0" << std::endl;
415  exit(-1);
416  }
417  a_segment inter = seg1.shortest(seg2,mm1,mm2);
418  double d = inter.length();
419  if (d<d0)
420  {
421  sshort = inter;
422  d0 = d;
423  ref1 = i1;
424  ref2 = i2;
425  m1 = mm1;
426  m2 = mm2;
427  if (mm2<0)
428  {
429  std::cerr << "-----------------" << std::endl;
430  std::cerr << seg1 << std::endl;
431  std::cerr << seg2 << std::endl;
432  exit(-1);
433  }
434  }
435  }
436  }
437  return sshort;
438 }
439 //---------------------------------------------------------------------------
440 double a_curve::dist2(const a_curve & fn, int & ref1, int & ref2, double& m1, double& m2) const
441 {
442  const double eps = 1e-10;
443  double d0 = 1e30;
444  double mm1,mm2;
445  int n_pt2 = fn.size();
446  for (int i2 = 0; i2 < n_pt2-1; i2++)
447  {
448  a_segment seg2(*fn[i2],*fn[i2+1]);
449  if (seg2.length()<eps)
450  {
451  std::cerr << "error: |seg2(" << i2+1 << ")| ~= 0" << std::endl;
452  exit(-1);
453  }
454  int n_pt1 = x_.size();
455  for (int i1 = 0; i1 < n_pt1-1; i1++)
456  {
457  a_segment seg1(*x_[i1],*x_[i1+1]);
458  if (seg1.length()<eps)
459  {
460  std::cerr << "error: |seg1(" << i1+1 << ")| ~= 0" << std::endl;
461  exit(-1);
462  }
463  a_segment inter = seg1.shortest(seg2,mm1,mm2);
464  double d = inter.length();
465  if (d<d0)
466  {
467  d0 = d;
468  ref1 = i1;
469  ref2 = i2;
470  m1 = mm1;
471  m2 = mm2;
472  }
473  }
474  }
475  return d0;
476 }
477 //***************************************************************************
478 //---------------------------------------------------------------------------
479 std::istream& operator>> (std::istream& in, a_curve & f)
480 {
481  int n_pts;
482  in >> n_pts;
483  for (int i = 0; i < n_pts; i++)
484  {
485  double x,y,z;
486  in >> x >> y >> z;
487  auto p = new a_point(x,y,z);
488  f.x_.push_back(p);
489  }
490  return in;
491 }
492 //---------------------------------------------------------------------------
493 std::ostream& operator<< (std::ostream& o, const a_curve & f)
494 {
495  int n_pts = f.x_.size();
496  o << n_pts << std::endl;
497  for (int i = 0; i < n_pts; i++)
498  o << f.x_[i] << std::endl;
499  return o;
500 }
const a_point horiz0(0, 1, 0)
std::ostream & operator<<(std::ostream &o, const a_curve &f)
Definition: a_curve.cxx:493
std::istream & operator>>(std::istream &in, a_curve &f)
Definition: a_curve.cxx:479
sampled parametric function class (interface)
Definition: a_curve.h:35
a_curve & construct_y_axis()
Definition: a_curve.cxx:236
a_point y_axis_
Definition: a_curve.h:105
double dist_last(const a_point &, int &ref) const
Definition: a_curve.cxx:338
a_curve & flatten()
Definition: a_curve.cxx:193
double dist2(const a_point &, int &ref, double &m) const
Definition: a_curve.cxx:316
a_curve & construct_z_axis()
Definition: a_curve.cxx:249
virtual a_point dx_axis(double a) const
Definition: a_curve.cxx:139
std::deque< a_point * > & x()
Definition: a_curve.h:49
a_curve(double da=1e-6)
Definition: a_curve.cxx:26
double da_
Definition: a_curve.h:102
a_point z_axis_
Definition: a_curve.h:106
double da() const
Definition: a_curve.h:78
a_curve & flatten2D()
Definition: a_curve.cxx:207
virtual a_point dz_axis(double a) const
Definition: a_curve.cxx:67
virtual a_curve & init()
Definition: a_curve.cxx:56
int size() const
Definition: a_curve.h:47
virtual a_point dy_axis(double a) const
Definition: a_curve.cxx:116
int orient_
Definition: a_curve.h:107
a_point horiz_
Definition: a_curve.h:108
bool initialised_
Definition: a_curve.h:100
double dist(const a_point &, int &ref) const
Definition: a_curve.cxx:299
a_segment shortest(const a_curve &fn, int &ref1, int &ref2, double &m1, double &m2) const
Definition: a_curve.cxx:393
virtual ~a_curve()
Definition: a_curve.cxx:49
a_point y_axis() const
Definition: a_curve.h:76
a_point x_axis_
Definition: a_curve.h:104
a_curve & place3D(a_point &origin, a_point &x_axis, a_point &y_axis)
Definition: a_curve.cxx:219
a_curve & construct_x_axis()
Definition: a_curve.cxx:230
a_curve & construct_axis()
Definition: a_curve.cxx:267
a_point origin() const
Definition: a_curve.h:68
bool is_closed() const
!!!!!!
Definition: a_curve.cxx:109
a_curve & translate(const a_point &p)
Definition: a_curve.cxx:179
a_point x_axis() const
Definition: a_curve.h:75
int n_pts_
Definition: a_curve.h:103
std::deque< a_point * > x_
Definition: a_curve.h:101
a_point centre() const
Definition: a_curve.cxx:158
e_point & normalise()
Definition: e_point.cxx:67
e_point cross(e_point &a, e_point &b)
Definition: e_point.cxx:105
std::istringstream in
Definition: ply2tri.cxx:32
Definition: stlb2stla.cxx:21