Points&Forces (survey)
Software tools facilitating the task of surveying architecture
a_curve_lin.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_lin.h"
17 #include <math.h>
18 
19 // .PORTABILITY : ansi C++
20 
21 //---------------------------------------------------------------------------
23 {
24 }
25 //---------------------------------------------------------------------------
27 {
28  ltot_ = ifn.ltot();
29  for (int i = 0; i < ifn.size(); i++)
30  a_.push_back(ifn.a()[i]);
31 }
32 //---------------------------------------------------------------------------
34 {
35  a_.clear();
36 }
37 //---------------------------------------------------------------------------
39 {
40  int n_pt_profile = this->size();
41  //find the position of a mean plane through the profile along the path
42 
43  a_point xg;
44  for (int i = 0; i < n_pt_profile; i++)
45  xg += *x_[i];
46  xg /= n_pt_profile;
47 
48  int ref;
49  double m;
50  double dist = path.dist2(xg,ref,m);//find the closest reference along the path
51 
52  a_point x0 = *path[ref]+ m*(*path[ref+1]-*path[ref]);//reference point on the path
53  double a = path.a()[ref]+m*(path.a()[ref+1]-path.a()[ref]);//relative position on the path
54 
55 
56  /* int reft = 0;
57  for (int i = 0; i < n_pt_profile; i++)
58  {
59  a_point * x = x_[i];//for each pt of the profile
60  int ref;
61  double dist = path.dist(*x,ref);//find the closest reference along the path
62  reft += ref;
63  // std::cerr << ref << " ";
64  }
65  int refm = double(reft)/n_pt_profile+.5;//take the mean
66  // std::cerr << std::endl << refm << std::endl;
67 
68  a_point x0 = *path[refm];//reference point on the path
69  double a = path.a()[refm];//relative position on the path
70  */
71 
72 
73  a_point centre = path.curvature_centre();
74 
75  // a_point centre = path.curvature_centre(a);
76  //define the profile plane
77 
78  a_point y_axis = (x0-centre).normalise();
79  a_point z_dir = path.dz_axis(a);//not perpendicular to y_axis, used to define x_axis
80  a_point x_axis = cross(y_axis,z_dir).normalise();//the axis of rotation
81  a_point z_axis = cross(x_axis,y_axis).normalise();
82  //project the profile's points
83  std::vector<a_point> points_n;
84  for (int i = 0; i < n_pt_profile; i++)
85  {
86  a_point p = *x_[i]-centre;//the vector to rotate
87  a_point px = (p*x_axis)*x_axis;//component along axis do not change
88  a_point pyz = ((p*y_axis)*y_axis)+((p*z_axis)*z_axis);//component perpendicular will change
89  a_point pyz_r = (pyz.norm())*y_axis;//component rotated
90  a_point xn = centre+pyz_r+px;//new vector
91  points_n.push_back(xn);
92  }
93  for (int i = 0; i < n_pt_profile; i++)
94  *x_[i] = points_n[i];
95  points_n.clear();
96  this->init();
97  return *this;
98 }
99 //---------------------------------------------------------------------------
101 {
102  if (!initialised_)
103  {
104  a_curve::init();
105  double l = 0;
106  a_.resize(n_pts_);
107  a_[0] = 0.;
108  a_point * p0 = x_[0];
109  for (int i = 1; i < n_pts_; i++)
110  {
111  a_point * p = x_[i];
112  l += (*p-*p0).norm();
113  a_[i] = l;
114  p0 = p;
115  }
116  ltot_ = l;
117  for (int i = 1; i < n_pts_; i++)
118  a_[i] /= ltot_;
119  }
120  return *this;
121 }
122 //---------------------------------------------------------------------------
123 int a_curve_lin::ref(double a) const
124 {
125  int i = -1;
126  double a2;
127  do
128  a2 = a_[++i];
129  while (a2 <= a);
130  return i-1;
131 }
132 //---------------------------------------------------------------------------
133 a_point a_curve_lin::operator()(double a) const
134 {
135  if (a<=0)
136  return *x_[0];
137  if (a>=1)
138  return **(x_.end()-1);
139  int ref = this->ref(a);
140  a_point x1 = *x_[ref];
141  a_point x2 = *x_[ref+1];
142  double a1 = a_[ref];
143  double a2 = a_[ref+1];
144  double f = (a-a1)/(a2-a1);
145  return (x1 + (x2-x1)*f);
146 }
147 //---------------------------------------------------------------------------
148 a_point a_curve_lin::dx_axis(double a) const
149 {
150  a_point z = this->dz_axis(a);
151  a_point y = this->dy_axis(a);
152  return cross(y,z).normalise();
153 }
154 //---------------------------------------------------------------------------
155 a_point a_curve_lin::dy_axis(double a) const
156 {
157  // a_point horizontal(0,1,0);
158  a_point y;
159  a_point z = this->dz_axis(a);
160  if ((z-horiz_).norm()<1e-5)//the plane is not vertical // xz
161  y = a_point(0,0,1);
162  else if ((z+horiz_).norm()<1e-5)//the plane is not vertical // xz
163  y = a_point(0,0,-1);
164  else
165  y = (cross(z,horiz_)).normalise();
166  return y;
167 }
168 //---------------------------------------------------------------------------
169 a_point a_curve_lin::dz_axis(double a) const
170 {
171  if (a>1)
172  return this->dz_axis(a-1);
173  else if (a==1)//at the extremity, take the direction of the last segment
174  {
175  int n = x_.size();
176  a_point x1 = *x_[n-2];
177  a_point x2 = *x_[n-1];
178  return (x2-x1).normalise();
179  }
180  int ref = this->ref(a);
181  //interpolate the tangent
182  double a1 = a_[ref];
183  double a2 = a_[ref+1];
184  double f = (a-a1)/(a2-a1);
185  a_point x1 = a_curve::dz_axis(a1);
186  a_point x2 = a_curve::dz_axis(a2);
187  return (x1 + (x2-x1)*f).normalise();
188 }
189 //---------------------------------------------------------------------------
190 a_point a_curve_lin::tangent(double a) const
191 {
192  if (a>=1)
193  return a_curve::dz_axis(a);
194  int ref = this->ref(a);
195  //interpolate the tangent
196  double a1 = a_[ref];
197  double a2 = a_[ref+1];
198  double f = (a-a1)/(a2-a1);
199  a_point x1 = a_curve::dz_axis(a1);
200  a_point x2 = a_curve::dz_axis(a2);
201  return x1 + (x2-x1)*f;
202 }
203 //---------------------------------------------------------------------------
205 {
206  int n = x_.size();
207  a_point p1,p2,p3;
208  if (this->is_closed())
209  {
210  p1 = *x_[0];
211  p2 = *x_[int((n-1)/3.+.5)];
212  p3 = *x_[int((n-1)/1.5+.5)];
213  }
214  else
215  {
216  p1 = *x_[0];
217  p2 = *x_[int((n-1)/2.+.5)];
218  p3 = *x_[n-1];
219  }
220  return circle_centre(p1,p2,p3);
221 }
222 //---------------------------------------------------------------------------
223 a_point a_curve_lin::curvature_centre(double a) const
224 {
225  a_point p1,p2,p3;
226  if (a>0.99)
227  {
228  p1 = (*this)(0.98);
229  p2 = (*this)(0.99);
230  p3 = (*this)(1.);
231  }
232  else if (a>0.01)
233  {
234  p1 = (*this)(a-0.01);
235  p2 = (*this)(a);
236  p3 = (*this)(a+0.01);
237  }
238  else
239  {
240  p1 = (*this)(0.);
241  p2 = (*this)(0.01);
242  p3 = (*this)(0.02);
243  }
244  return circle_centre(p1,p2,p3);
245 }
246 //---------------------------------------------------------------------------
247 double a_curve_lin::curvature(double a) const
248 {
249  a_point xm = this->tangent(a-da_);
250  a_point xM = this->tangent(a+da_);
251  a_point dx = (xM-xm)/da_;
252  //crash if 0
253  return 1/dx.norm();
254 }
255 //---------------------------------------------------------------------------
256 a_curve_lin& a_curve_lin::extrapolate(double f1, double f2)
257 {
258  if (f1>0) return *this;
259  if (f2<1) return *this;
260  a_point centre = this->curvature_centre();
261  a_point p1 = *x_[0];
262  a_point p2 = *x_[n_pts_-1];
263  a_point r1 = p1-centre;
264  a_point r2 = p2-centre;
265  double rn1 = r1.norm();
266  double rn2 = r2.norm();
267  r1.normalise();
268  r2.normalise();
269  a_point d = p1-p2;
270  a_point normal = cross(r1,d).normalise();
271  double da = acos(r1*r2)/(2.*n_pts_);
272  if (f1<0)
273  {
274  int n = (int)fabs(f1)*n_pts_;
275  double ds = 2*rn1*sin(da);
276  a_point x = p1;
277  for (int i=0; i < n; i++)
278  {
279  a_point uy = (centre-x).normalise();
280  a_point ux = cross(normal,uy).normalise();
281  x -= ds*(ux*cos(da)+uy*sin(da));
282  auto xp = new a_point(x);
283  x_.push_front(xp);
284  }
285  }
286  if (f2>1)
287  {
288  int n = (int)(f2-1)*n_pts_;
289  double ds = 2*rn2*sin(da);
290  a_point x = p2;
291  for (int i=0; i < n; i++)
292  {
293  a_point uy = (centre-x).normalise();
294  a_point ux = cross(normal,uy).normalise();
295  x += ds*(ux*cos(da)+uy*sin(da));
296  auto xp = new a_point(x);
297  x_.push_back(xp);
298  }
299  }
300  a_.clear();
301  this->init();
302  return *this;
303 }
304 //***************************************************************************
305 //---------------------------------------------------------------------------
306 std::istream& operator>> (std::istream& in, a_curve_lin & f)
307 {
308  in >> *((a_curve *)(&f));
309  f.init();
310  return in;
311 }
312 //***************************************************************************
313 //---------------------------------------------------------------------------
314 a_curve_lin interpolate(const a_curve_lin& pat1,const a_curve_lin& pat2, double a)
315 {
316  std::vector<double> merge;
317  int n1 = pat1.size();
318  int n2 = pat2.size();
319  if (n1!=n2)
321  a_curve_lin patn;
322  for (int i = 0; i < n1; i++)
323  {
324  a_point p1 = *pat1[i];
325  a_point p2 = *pat2[i];
326  auto p = new a_point(p1+a*(p2-p1));
327  patn.x_.push_back(p);
328  }
329  patn.init();
330  return patn;
331 }
std::istream & operator>>(std::istream &in, a_curve_lin &f)
a_curve_lin interpolate(const a_curve_lin &pat1, const a_curve_lin &pat2, double a)
a_mat_sq x2(3)
a curve with linear interpolation
Definition: a_curve_lin.h:28
a_point dx_axis(double a) const
int ref(double a) const
a_point dz_axis(double a) const
a_curve_lin(double da=1e-6)
Definition: a_curve_lin.cxx:22
double ltot() const
Definition: a_curve_lin.h:36
std::vector< double > a_
Definition: a_curve_lin.h:57
a_curve_lin & extrapolate(double f1, double f2)
a_point curvature_centre() const
double curvature(double a) const
a_point operator()(double a) const
a_curve & init()
a_point tangent(double a) const
double ltot_
Definition: a_curve_lin.h:56
std::vector< double > & a()
Definition: a_curve_lin.h:34
a_point dy_axis(double a) const
sampled parametric function class (interface)
Definition: a_curve.h:35
a_curve & flatten()
Definition: a_curve.cxx:193
std::deque< a_point * > & x()
Definition: a_curve.h:49
double da_
Definition: a_curve.h:102
double da() const
Definition: a_curve.h:78
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
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_point z_axis() const
Definition: a_curve.h:77
a_point y_axis() const
Definition: a_curve.h:76
bool is_closed() const
!!!!!!
Definition: a_curve.cxx:109
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
uint32_t n[]
Definition: generate.cxx:34
int xm
Definition: pixelpos.cxx:73
int xM
Definition: pixelpos.cxx:75
std::istringstream in
Definition: ply2tri.cxx:32
a_point normal(int i, int l)
Definition: rib0.cxx:72
std::vector< a_point * > path
Definition: rib0.cxx:58