Points&Forces (survey)
Software tools facilitating the task of surveying architecture
a_rib.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_rib.h"
17 #include <sstream>
18 #include <iomanip>
19 
20 // .PORTABILITY : ansi C++
21 
22 //***************************************************************************
23 //---------------------------------------------------------------------------
25 {
26 }
27 //---------------------------------------------------------------------------
29 {
30  for (auto prof:profiles_)
31  delete prof;
32  profiles_.clear();
33 }
34 //---------------------------------------------------------------------------
36 {
37  this->construct_profile_pos();//find the position of the profiles along the path
38  a_point z = path_.z_axis();
39  a_point z1 = profiles_[0]->z_axis();//z axis of the first profile
40  double a = profile_pos_[0];//position of the first profile on the path
41  a_point z2 = path_.dz_axis(a);//z axis at the origin
42  if (z1*z2<0)//not the same direction
43  this->invert();
44  //some new profiles are possibly made to have a complete set of data for processing
45  if (profiles_.size()==1)// just 1 profile -> make 1 or 2 new profiles at the extremities
47  else //if no profile at extremities, extrapolate new ones
49  if (z1*z2<0)//not the same direction
50  this->invert();//necessary to invert the new profiles
51  //std::cout << *this;
52  //std::exit(0);
53 }
54 //---------------------------------------------------------------------------
56 {
57  int n_pat = profiles_.size();
58  for (int i = 0; i < n_pat; i++)//for each profile
59  profiles_[i]->invert();
60 }
61 //---------------------------------------------------------------------------
62 int a_rib::ref(double a) const//find the previous profile for a given relative position along the path
63 {
64  int i = -1;
65  double a2;
66  do
67  a2 = profile_pos_[++i];//profiles' relative positions
68  while ((a2 <= a)&&(i<profile_pos_.size()));
69  return i-1;
70 }//---------------------------------------------------------------------------
72 {
73  int n_pat = profiles_.size();
74  int ref0 = -1;
75  for (int i = 0; i < n_pat; i++)//for each profile
76  {
77  double m1;
78  a_curve_lin * pat = profiles_[i];
79  int ref1;
80  //find the reference of the point on the path closest to the profile
81  //& find the reference of the point on the profile closest to the path
82  double dist = path_.dist2(*pat,ref1,path_pos_,m1,m2_);
83  if (ref1<ref0)
84  {
85  int test = path_.size();
86  if (ref1==0)
87  profile_pos_.push_back(1);
88  else if (ref1==path_.size()-2)
89  profile_pos_.push_back(0);
90  else //for closed paths
91  {
92  std::cerr << "profiles should be ordered along the path" << std::endl;
93  std::cerr << "ref0 " << ref0 << std::endl;
94  std::cerr << "ref1 " << ref1 << std::endl;
95  throw profile_order_error();
96  }
97  }
98  else
99  {
100  double a1 = path_.a()[ref1];
101  double a2 = path_.a()[ref1+1];
102  profile_pos_.push_back(a1+m1*(a2-a1));
103  }
104  ref0 = ref1;
105  }
106 }
107 //---------------------------------------------------------------------------
108 double gia_f(double a, double a1, double a2, bool path_is_closed)
109 {
110  if (path_is_closed)
111  {
112  if (a1<a2)
113  return (a-a1)/(a2-a1);
114  else
115  {
116  double base = (1-a1)+a2;
117  if (a<=a2)
118  return 1.+(a-a2)/base;
119  else
120  return (a-a1)/base;
121  }
122  }
123  else
124  return (a-a1)/(a2-a1);
125 }
126 //---------------------------------------------------------------------------
127 a_curve_lin a_rib::gia_profile(double a, int ref1, int ref2) const
128 {
129  a_curve_lin pat1 = *profiles_[ref1];//the 2 profiles to interpolate
130  a_curve_lin pat2 = *profiles_[ref2];
131 
132  double a1 = profile_pos_[ref1];//position of the profile on the path
133  double a2 = profile_pos_[ref2];
134 
135  double m1,m2;
136  int r1,r2;
137  int rz1,rz2;
138  double mz1,mz2;
139 
140  a_point gap1_3D = path_.shortest(pat1,r1,rz1,m1,mz1).vec();//shortest segment between the path & profile
141  a_point gap2_3D = path_.shortest(pat2,r1,rz2,m1,mz2).vec();
142 
143  a_point x1 = pat1.x_axis();//reference system of the 1st profile
144  a_point y1 = pat1.y_axis();
145  a_point z1 = pat1.z_axis();
146 
147  a_point gap1_2D(x1*gap1_3D,y1*gap1_3D,0.);//find the gap coordinates in the plane of the profile
148 
149  a_point dx1 = path_.dx_axis(a1).rotate(x1,y1,z1);//angles with the reference system on the path at a1
150  a_point dy1 = path_.dy_axis(a1).rotate(x1,y1,z1);
151  a_point dz1 = path_.dz_axis(a1).rotate(x1,y1,z1);
152 
153  a_point x2 = pat2.x_axis();//reference system of the 2d profile
154  a_point y2 = pat2.y_axis();
155  a_point z2 = pat2.z_axis();
156 
157  a_point gap2_2D(x2*gap2_3D,y2*gap2_3D,0.);//find the gap coordinates in the plane of the profile
158 
159  a_point dx2 = path_.dx_axis(a2).rotate(x2,y2,z2);//angles with the reference system on the path at a2
160  a_point dy2 = path_.dy_axis(a2).rotate(x2,y2,z2);
161  a_point dz2 = path_.dz_axis(a2).rotate(x2,y2,z2);
162 
163  double f = gia_f(a,a1,a2,path_.is_closed());//relative position of the 2 profiles
164 
165  a_point dx3 = average_rot(dx1,dx2,f);//interpolated angle with the reference system on the path at a
166  a_point dy3 = average_rot(dy1,dy2,f);
167  a_point dz3 = average_rot(dz1,dz2,f);
168 
169  pat1.flatten2D();//the 2 profiles are flatten in 2D
170  pat2.flatten2D();
171 
172  a_curve_lin pat = interpolate(pat1,pat2,f);//an interpolated flatten path is found
173 
174  a_point ref1_2D = *pat1[rz1]+mz1*(*pat1[rz1+1]-*pat1[rz1]);//vector between the origin of the profile and the closest point to the path
175  a_point ref2_2D = *pat2[rz2]+mz2*(*pat2[rz2+1]-*pat2[rz2]);
176 
177  a_point gap_2D = average(gap1_2D,gap2_2D,f);
178  a_point ref_2D = average(ref1_2D,ref2_2D,f);
179 
180  a_point p = path_(a);//position of the new profile on the path
181 
182  a_point x0 = path_.dx_axis(a);
183  a_point y0 = path_.dy_axis(a);
184  a_point z0 = path_.dz_axis(a);
185 
186  a_point x = (x0*dx3.x()+y0*dy3.x()+z0*dz3.x()).normalise();
187  a_point y = (x0*dx3.y()+y0*dy3.y()+z0*dz3.y()).normalise();
188 
189  a_point ref_3D = ref_2D.x()*x+ref_2D.y()*y;//place the interpolated reference shift in the plane of the new profile
190  a_point gap_3D = gap_2D.x()*x+gap_2D.y()*y;//place the interpolated gap in the plane of the new profile
191 
192  a_point prov = p+gap_3D-ref_3D;
193  pat.place3D(prov,x,y);
194 
195  pat.set_horiz(path_.get_horiz());
196  pat.construct_axis();
197 
198  return pat;
199 }
200 //---------------------------------------------------------------------------
202 {
203  a_curve_lin pat = *profiles_[0];//the profile to extrapolate
204 
205  double a = profile_pos_[0];//position of the profile on the path
206 
207  double m1,m2;
208  int r1,r2;
209  a_point gap_3D = path_.shortest(pat,r1,r2,m1,m2).vec();
210 
211  a_point x = pat.x_axis();//reference system of the profile
212  a_point y = pat.y_axis();
213  a_point z = pat.z_axis();
214 
215  a_point gap_2D(x*gap_3D,y*gap_3D,0.);//find the gap coordinates in the plane of the profile
216 
217  a_point dx = path_.dx_axis(a).rotate(x,y,z);//angles with the reference system on the path at a
218  a_point dy = path_.dy_axis(a).rotate(x,y,z);
219  a_point dz = path_.dz_axis(a).rotate(x,y,z);
220  if (a > 0)//there is no profile at the path's beginning
221  {
222  auto patn = new a_curve_lin(pat);
223  patn->flatten2D();
224  a_point ref_2D = *(*patn)[r2]+m2*(*(*patn)[r2+1]-*(*patn)[r2]);//vector between the origin of the profile and the closest point to the path
225  a_point pa = path_(0.);//position of the profile on the path
226 
227  a_point x0 = path_.dx_axis(0.);
228  a_point y0 = path_.dy_axis(0.);
229  a_point z0 = path_.dz_axis(0.);
230 
231  a_point dxa = (x0*dx.x()+y0*dy.x()+z0*dz.x()).normalise();
232  a_point dya = (x0*dx.y()+y0*dy.y()+z0*dz.y()).normalise();
233 
234  a_point ref_3D = ref_2D.x()*dxa+ref_2D.y()*dya;//place the interpolated reference shift in the plane of the new profile
235  a_point gapn_3D = gap_2D.x()*dxa+gap_2D.y()*dya;//place the interpolated gap in the plane of the new profile
236  a_point prov = pa+gap_3D-ref_3D;
237  patn->place3D(prov,dxa,dya);
238  //patn->set_horiz(path_.get_horiz());
239  //patn->construct_axis();
240  profiles_.insert(profiles_.begin(),patn);
241  profile_pos_.insert(profile_pos_.begin(),0.);
242  }
243 
244  if ((a < 1)&&(!path_.is_closed()))//there is no profile at the path's end
245  {
246  auto patn = new a_curve_lin(pat);
247  patn->flatten2D();
248  a_point ref_2D = *(*patn)[r2]+m2*(*(*patn)[r2+1]-*(*patn)[r2]);//vector between the origin of the profile and the closest point to the path
249  a_point pb = path_(1.);//position of the profile on the path
250 
251  a_point x0 = path_.dx_axis(1.);
252  a_point y0 = path_.dy_axis(1.);
253  a_point z0 = path_.dz_axis(1.);
254 
255  a_point dxb = (x0*dx.x()+y0*dy.x()+z0*dz.x()).normalise();
256  a_point dyb = (x0*dx.y()+y0*dy.y()+z0*dz.y()).normalise();
257 
258  // a_point dxb = path_.dx_axis(1.).rotate(dx,dy,dz).normalise();
259  // a_point dyb = path_.dy_axis(1.).rotate(dx,dy,dz).normalise();
260 
261  a_point ref_3D = ref_2D.x()*dxb+ref_2D.y()*dyb;//place the interpolated reference shift in the plane of the new profile
262  a_point gapn_3D = gap_2D.x()*dxb+gap_2D.y()*dyb;//place the interpolated gap in the plane of the new profile
263  a_point prov = pb+gap_3D-ref_3D;
264  patn->place3D(prov,dxb,dyb);
265  //patn->set_horiz(path_.get_horiz());
266  //patn->construct_axis();
267  profiles_.push_back(patn);
268  profile_pos_.push_back(1.);
269  }
270 }
271 //---------------------------------------------------------------------------
273 {
274  if (!path_.is_closed())
275  {
276  if (profile_pos_[0] != 0)//no profile at the beginning
277  {
278  auto pat = new a_curve_lin(this->gia_profile(0,0,1));
279  profiles_.insert(profiles_.begin(),pat);
280  profile_pos_.insert(profile_pos_.begin(),0.);
281  }
282  int n_pat = profiles_.size();
283  if (profile_pos_[n_pat-1] < 1)//no profile at the end
284  {
285  auto pat = new a_curve_lin(this->gia_profile(1,n_pat-2,n_pat-1));
286  profiles_.push_back(pat);
287  profile_pos_.push_back(1.);
288  }
289  }
290 }
291 //---------------------------------------------------------------------------
293 {
294  if (path_.is_closed())
295  {
296  if ((a>=profile_pos_[0])&&(a<=*(profile_pos_.end()-1)))
297  {
298  int ref = this->ref(a);
299  if (ref==profiles_.size()-1)
300  ref--;
301  return this->gia_profile(a,ref,ref+1);
302  }
303  else
304  return this->gia_profile(a,profiles_.size()-1,0);
305  }
306  else
307  {
308  int ref = this->ref(a);
309  if (ref==profiles_.size()-1)
310  ref--;
311  return this->gia_profile(a,ref,ref+1);
312  }
313 }
314 //---------------------------------------------------------------------------
315 void a_rib::output_pts(std::ostream& o, int& imax, int& jmax, bool is_closed_volume) const
316 {
317  imax = path_.size();
318  jmax = profiles_[0]->size();
319  if (path_.is_closed())
320  {
321  imax--;
322  o << imax*jmax << std::endl;//number of points + 2 in the middle of the end faces
323  }
324  else
325  {
326  if (is_closed_volume) //closed triangle volume will be produced
327  o << imax*jmax+2 << std::endl;//number of points + 2 in the middle of the end faces
328  else //open triangle volume will be produced
329  o << imax*jmax << std::endl;//number of points
330  }
331 
332  //points
333  std::ostringstream out;
334  for (int i = 0; i < imax; i++)
335  {
336  a_point * p0 = path_[i];//a point along the path
337  double a = path_.a()[i];//its relative position (0-1)
338  a_curve_lin pat = this->profile(a);//the profile at that place
339  if (((i==0)||(i==imax-1))&&(is_closed_volume))//extreme section and closed set
340  {
341  // a 'centre' point is computed for the extremity's sections
342  a_point mid;
343  for (int j = 0; j < jmax; j++)//write the points of the profile
344  {
345  a_point * x = pat[j];
346  mid += *x;
347  o << *x << std::endl;
348  }
349  mid /= jmax;
350  out << mid << std::endl;//mid point is put in a provisory place
351  }
352  else
353  {
354  for (int j = 0; j < jmax; j++)//write the points of the profile
355  o << *pat[j] << std::endl;
356  }
357  }
358  if ((is_closed_volume)&&(!path_.is_closed()))
359  o << out.str();
360 }
361 //---------------------------------------------------------------------------
362 void a_rib::output_pts_vol(std::ostream& o, int& imax, int& jmax) const
363 {
364  imax = path_.size();
365  jmax = profiles_[0]->size();
366 
367  if (path_.is_closed())
368  imax--;
369  o << imax*(jmax+1) << std::endl;
370  //points
371  for (int i = 0; i < imax; i++)
372  {
373  a_point * p0 = path_[i];//a point along the path
374  double a = path_.a()[i];//its relative position (0-1)
375  a_curve_lin pat = this->profile(a);//the profile at that place
376  // a 'centre' point is computed
377  a_point mid;
378  for (int j = 0; j < jmax; j++)//write the points of the profile
379  {
380  a_point * x = pat[j];
381  mid += *x;
382  o << *x << std::endl;
383  }
384  mid /= jmax;
385  o << mid << std::endl;//mid point
386  }
387 }
388 //---------------------------------------------------------------------------
389 void a_rib::output_tri_open(std::ostream& o) const
390 {
391  int imax, jmax;
392  bool is_closed_volume = false;//open structure
393  this->output_pts(o,imax,jmax,is_closed_volume);
394  //triangles
395  if (path_.is_closed())
396  o << imax*(jmax-1)*2 << std::endl;//number of triangles
397  else
398  o << (imax-1)*(jmax-1)*2 << std::endl;//number of triangles
399  for (int i = 0; i < imax-1; i++)//write the topology
400  {
401  for (int j = 0; j < jmax-1; j++)
402  {
403  int i1 = i*jmax+j; int i2 = i1+1;
404  int j1 = i1+jmax; int j2 = j1+1;
405  o << i1 << "\t" << j2 << "\t" << j1 << std::endl;
406  o << i1 << "\t" << i2 << "\t" << j2 << std::endl;
407  }
408  }
409  if (path_.is_closed())//path is closed
410  {
411  for (int j = 0; j < jmax-1; j++)
412  {
413  int i1 = (imax-1)*jmax+j; int i2 = i1+1;
414  int j1 = j; int j2 = j1+1;
415  o << i1 << "\t" << j2 << "\t" << j1 << std::endl;
416  o << i1 << "\t" << i2 << "\t" << j2 << std::endl;
417  }
418  }
419 }
420 //---------------------------------------------------------------------------
421 void a_rib::output_tri_closed(std::ostream& o) const
422 {
423  int imax, jmax;
424  bool is_closed_volume = true;
425  this->output_pts(o,imax,jmax,is_closed_volume);
426  //triangles
427  o << imax*jmax*2 << std::endl;//number of triangles
428  for (int i = 0; i < imax-1; i++)//write the topology
429  {
430  for (int j = 0; j < jmax-1; j++)
431  {
432  int i1 = i*jmax+j; int i2 = i1+1;
433  int j1 = i1+jmax; int j2 = j1+1;
434  o << i1 << "\t" << j2 << "\t" << j1 << std::endl;
435  o << i1 << "\t" << i2 << "\t" << j2 << std::endl;
436  }
437  int i1 = (i+1)*jmax-1; int i2 = i*jmax;
438  int j1 = i1+jmax; int j2 = i2+jmax;
439  o << i1 << "\t" << j2 << "\t" << j1 << std::endl;
440  o << i1 << "\t" << i2 << "\t" << j2 << std::endl;
441  }
442  if (path_.is_closed())
443  {
444  //triangles connecting the sections of the extremities
445  for (int j = 0; j < jmax-1; j++)
446  {
447  int i1 = (imax-1)*jmax+j; int i2 = i1+1;
448  int j1 = j; int j2 = j1+1;
449  o << i1 << "\t" << j2 << "\t" << j1 << std::endl;
450  o << i1 << "\t" << i2 << "\t" << j2 << std::endl;
451  }
452  int i1 = imax*jmax-1; int i2 = i1-jmax+1;
453  int j1 = jmax-1; int j2 = 0;
454  o << i1 << "\t" << j2 << "\t" << j1 << std::endl;
455  o << i1 << "\t" << i2 << "\t" << j2 << std::endl;
456  }
457  else//path is open
458  {
459  //triangles closing the sections of the extremities
460  for (int j = 0; j < jmax-1; j++)
461  {
462  o << imax*jmax << "\t" << j+1 << "\t" << j << std::endl;
463  o << imax*jmax+1 << "\t" << (imax-1)*jmax+j << "\t" << (imax-1)*jmax+j+1 << std::endl;
464  }
465  o << imax*jmax << "\t" << 0 << "\t" << jmax-1 << std::endl;
466  o << imax*jmax+1 << "\t" << (imax-1)*jmax+jmax-1 << "\t" << (imax-1)*jmax << std::endl;
467  }
468 }
469 //---------------------------------------------------------------------------
470 void a_rib::output_vol(std::ostream& o) const
471 {
472  int imax, jmax;
473  bool is_closed_volume = true;
474  this->output_pts_vol(o,imax,jmax);
475  //prisms
476  o << (imax-1)*jmax << std::endl;//number of prisms
477  for (int i = 0; i < imax-1; i++)//write the topology
478  {
479  int k1 = i*(jmax+1)+jmax;
480  int k2 = (i+1)*(jmax+1)+jmax;
481  for (int j = 0; j < jmax; j++)
482  {
483  int i1 = i*(jmax+1)+j;
484  int i2;
485  if (j==jmax-1)
486  i2 = i*(jmax+1);
487  else
488  i2 = i1 + 1;
489  int j1 = i1 + jmax + 1;
490  int j2 = i2 + jmax + 1;
491  o << k1 << "\t" << i1 << "\t" << i2 << "\t" << k2 << "\t" << j1 << "\t" << j2 << std::endl;
492  }
493  }
494  if (path_.is_closed())
495  {
496  o << "to complete" << std::endl;
497  }
498 }
499 //***************************************************************************
500 //---------------------------------------------------------------------------
501 std::istream& operator>> (std::istream& in, a_rib & r)
502 {
503  in >> r.path_;//read the path
504  a_point h = r.path_.z_axis();
505  h.z(0);
506  r.path_.set_horiz(h);
507 
508  int n_pats;
509  in >> n_pats;//read all the profiles
510 
511  for (int i = 0; i < n_pats; i++)
512  {
513  auto pat = new a_curve_lin;
514  in >> *pat;
515  pat->set_horiz(h);
516  pat->construct_axis();
517  r.profiles_.push_back(pat);
518  }
519  r.init();
520  return in;
521 }
522 //---------------------------------------------------------------------------
523 std::ostream& operator<< (std::ostream& o, const a_rib & r)
524 {
525  o << r.path_;
526  int n_pats = r.profiles_.size();
527  o << n_pats << std::endl;
528  for (int i = 0; i < n_pats; i++)
529  o << *r.profiles_[i];
530  return o;
531 }
a_curve_lin interpolate(const a_curve_lin &pat1, const a_curve_lin &pat2, double a)
double gia_f(double a, double a1, double a2, bool path_is_closed)
Definition: a_rib.cxx:108
std::istream & operator>>(std::istream &in, a_rib &r)
Definition: a_rib.cxx:501
std::ostream & operator<<(std::ostream &o, const a_rib &r)
Definition: a_rib.cxx:523
a_mat_sq x2(3)
a curve with linear interpolation
Definition: a_curve_lin.h:28
a_point dx_axis(double a) const
a_point dz_axis(double a) const
std::vector< double > & a()
Definition: a_curve_lin.h:34
a_point dy_axis(double a) const
double dist2(const a_point &, int &ref, double &m) const
Definition: a_curve.cxx:316
void set_horiz(const a_point &p)
Definition: a_curve.h:62
a_curve & flatten2D()
Definition: a_curve.cxx:207
int size() const
Definition: a_curve.h:47
a_segment shortest(const a_curve &fn, int &ref1, int &ref2, double &m1, double &m2) const
Definition: a_curve.cxx:393
a_point z_axis() const
Definition: a_curve.h:77
a_point y_axis() const
Definition: a_curve.h:76
a_curve & place3D(a_point &origin, a_point &x_axis, a_point &y_axis)
Definition: a_curve.cxx:219
a_point get_horiz() const
Definition: a_curve.h:63
a_curve & construct_axis()
Definition: a_curve.cxx:267
bool is_closed() const
!!!!!!
Definition: a_curve.cxx:109
a_point x_axis() const
Definition: a_curve.h:75
a rib
Definition: a_rib.h:31
void output_tri_closed(std::ostream &o) const
Definition: a_rib.cxx:421
int path_pos_
Definition: a_rib.h:58
std::vector< double > profile_pos_
Definition: a_rib.h:63
int ref(double a) const
Definition: a_rib.cxx:62
void output_vol(std::ostream &o) const
Definition: a_rib.cxx:470
std::vector< a_curve_lin * > profiles_
Definition: a_rib.h:61
void output_pts_vol(std::ostream &o, int &imax, int &jmax) const
Definition: a_rib.cxx:362
void extrapolate_1profile_setup()
Definition: a_rib.cxx:201
void invert()
Definition: a_rib.cxx:55
double m2_
Definition: a_rib.h:59
void output_pts(std::ostream &o, int &imax, int &jmax, bool is_closed_volume) const
Definition: a_rib.cxx:315
a_curve_lin gia_profile(double a, int ref1, int ref2) const
Definition: a_rib.cxx:127
virtual ~a_rib()
Definition: a_rib.cxx:28
void construct_profile_pos()
Definition: a_rib.cxx:71
void init()
Definition: a_rib.cxx:35
void extrapolate_profiles_setup()
Definition: a_rib.cxx:272
a_curve_lin profile(double a) const
Definition: a_rib.cxx:292
void output_tri_open(std::ostream &o) const
Definition: a_rib.cxx:389
a_rib()
Definition: a_rib.cxx:24
a_curve_lin path_
Definition: a_rib.h:56
std::istringstream in
Definition: ply2tri.cxx:32