Points&Forces (survey)
Software tools facilitating the task of surveying architecture
a_structure.cxx
Go to the documentation of this file.
1 /*
2 Copyright 2010-2016 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 <math.h> // math routines
17 
18 #include "a_structure.h"
19 #include "a_block_2d4.h"
20 #include "a_face_2d4.h"
21 #include <vnl/vnl_vector.h>
22 #include <vnl/vnl_matrix.h>
23 #include <vnl/algo/vnl_svd.h>
24 #include <vnl/vnl_least_squares_function.h>
25 #include <vnl/algo/vnl_levenberg_marquardt.h>
26 #include <vnl/vnl_cost_function.h>
27 #include <vnl/algo/vnl_levenberg_marquardt.h>
28 #include <vnl/vnl_least_squares_cost_function.h>
29 #include <vnl/algo/vnl_amoeba.h>
30 #include <vnl/algo/vnl_powell.h>
31 #include <vnl/algo/vnl_conjugate_gradient.h>
32 #include <vnl/algo/vnl_lbfgs.h>
33 
34 #include "config.h"
35 
36 //---------------------------------------------------------------------------
38 {
39  objective_ = 0;
40  penalty_factor_ = 1.;
41 }
42 //---------------------------------------------------------------------------
44 {
45  this->clear();
46 }
47 //---------------------------------------------------------------------------
49 {
50  for(std::vector<a_block *>::iterator it = blocks_.begin(); it != blocks_.end(); ++it) (*it)->clear();
51  blocks_.clear();
52 }
53 //---------------------------------------------------------------------------
54 const std::string a_structure::help()
55 {
56  std::ostringstream o;
57  o << "************" << std::endl;
58  o << "a_structure:" << std::endl;
59  o << "************" << std::endl;
60  o << "This class is used to model structures made of blocks" << std::endl;
61  o << "Commands:" << std::endl;
62  o << "--------" << std::endl;
63  o << "a_structure S: create a structure named S" << std::endl;
64  o << "" << std::endl;
65  o << "> building the structure" << std::endl;
66  o << "......................" << std::endl;
67  o << "clear: clear completely the structure" << std::endl;
68  o << "add_block 'block_object': add a block" << std::endl;
69  o << "link_blocks 'b1' 'f1' 'b2' 'f2': link blocks 'b1' and 'b2' by their faces 'f1' and 'f2'" << std::endl;
70  o << "material 'material': link a material (can also be defined block by block)" << std::endl;
71  o << "criteria 'criteria': set a global resistance criteria for the structure (can also be specified block by block)" << std::endl;
72  o << "penalty_factor 'value': set penalty factor" << std::endl;
73  o << "b 'ref': returns block 'ref' (possibly used to specify parameters for this block)" << std::endl;
74  o << "rotate 'b' 'f' 'p' 'a' 'r': rotate 'b' and all connected blocks of an angle 'r' (rad), starting from face 'f', using axis 'a'" << std::endl;
75  o << "rotate 'b' 'f' 'e' 'r': rotate 'b' and all connected blocks of an angle 'r' (rad), starting from face 'f' at relative distance (-1 - 1) 'e' from the face center, using ny as an axis" << std::endl;
76  o << "slide 'b' 'f' 'u' 'v': slide of ('u','v') all blocks connected to 'b' in the plane of 'f'" << std::endl;
77  o << std::endl;
78  o << "> export data" << std::endl;
79  o << "............." << std::endl;
80  o << "convert tri 'filename': write triangle cloud (filename is optional)" << std::endl;
81  o << "convert blender 'filename': write structure in blender format (filename is optional)" << std::endl;
82  o << "convert brlcad 'filename': write structure in brlcad format (filename is optional)" << std::endl;
83  o << "trianglecloud 'a_trianglecloud': write structure in a 'a_trianglecloud' object (points&forces)" << std::endl;
84  o << "polyline 'a_linecloud': write line of resistance in a 'a_linecloud' object (points&forces)" << std::endl;
85  o << std::endl;
86  o << "> query the structure" << std::endl;
87  o << "....................." << std::endl;
88  o << "nb: returns number of blocks in the structure" << std::endl;
89  o << "rb 'block_object': returns reference number of block" << std::endl;
90  o << "V: returns volume" << std::endl;
91  o << "c: returns centre of mass" << std::endl;
92  o << "m: returns mass" << std::endl;
93  o << "Ws: returns scalar weight" << std::endl;
94  o << "W: returns weight (wrench)" << std::endl;
95  o << "potential: returns potential energy" << std::endl;
96  o << "b 'ref': returns block 'ref'" << std::endl;
97  o << "connected: check whether all blocks are connected" << std::endl;
98  o << "out: get list of extreme blocks (blocks connected only to 1 other block" << std::endl;
99  o << "in: get list of internal blocks (blocks connected at least to 2 other blocks)" << std::endl;
100  o << "nodes: get list of blocks connected to more than 2 other blocks (sources of hyperstaticity)" << std::endl;
101  o << "clearinternal: clear all the internal face forces" << std::endl;
102  o << "clearexternal: clear all the forces on faces" << std::endl;
103  o << "clearall: clear all the forces on faces" << std::endl;
104  o << "objective 'objective': set objective function (used for optimisation)" << std::endl;
105  o << "objective: get value of objective function" << std::endl;
106  o << "ok: check whether forces are acceptable" << std::endl;
107  o << "penalty: penalty value used for optimization" << std::endl;
108  o << "penalty_factor: get penalty factor" << std::endl;
109  o << "objectivep: get value of objective function + penalty*penalty_factor" << std::endl;
110  o << std::endl;
111  o << "> Compute forces" << std::endl;
112  o << "................" << std::endl;
113  o << "compute 'b' 'f': compute as far as possible the forces on the blocks, starting from block b, entrance face f, return the last block for which it succeeded" << std::endl;
114  o << "compute 'b1' 'f1' 'u1' 'v1' 'b2' 'f2' 'u2' 'v2' 'b3' 'f3' 'u3' 'v3': compute inside forces resulting in resistance line passing by 3 points. 'bi': block references, 'fi': faces references, 'ui': excentricity in the direction of u in local reference system of face (def depends of face), 'vj': excentricity in the direction of v in local reference system of face" << std::endl;
115  o << "others... work in progress" << std::endl;
116  return o.str();
117 }
118 //---------------------------------------------------------------------------
120 {
121  blocks_.push_back(b);
122  return this->nb()-1;
123 }
124 //---------------------------------------------------------------------------
125 int a_structure::rb(const a_block* b) const
126 {
127  for (int i=0; i<blocks_.size(); i++)
128  {
129  a_block * b2 = blocks_[i];
130  if (b==b2)
131  return i;
132  }
133  return -1;
134 }
135 //---------------------------------------------------------------------------
136 double a_structure::V() const
137 {
138  double v;
139  for (int i=0; i<blocks_.size(); i++)
140  v += blocks_[i]->V();
141  return v;
142 }
143 //---------------------------------------------------------------------------
144 a_point a_structure::c() const
145 {
146  double w = this->Ws();
147  a_point c;
148  for (int i=0; i<blocks_.size(); i++)
149  {
150  a_point ci = blocks_[i]->c();
151  double wi = blocks_[i]->Ws();
152  c += (ci*wi);
153  }
154  return c/w;
155 }
156 //---------------------------------------------------------------------------
157 double a_structure::m() const
158 {
159  double m;
160  for (int i=0; i<blocks_.size(); i++)
161  m += blocks_[i]->m();
162  return m;
163 }
164 //---------------------------------------------------------------------------
165 double a_structure::Ws() const
166 {
167  double w;
168  for (int i=0; i<blocks_.size(); i++)
169  w += blocks_[i]->Ws();
170  return w;
171 }
172 //---------------------------------------------------------------------------
174 {
175  a_wrench w;
176  for (int i=0; i<blocks_.size(); i++)
177  w += blocks_[i]->W();
178  return w;
179 }
180 //---------------------------------------------------------------------------
182 {
183  a_wrench w;
184  for (int i=0; i<blocks_.size(); i++)
185  w += blocks_[i]->fe();
186  return w;
187 }
188 //---------------------------------------------------------------------------
190 {
191  a_wrench w;
192  for (int i=0; i<blocks_.size(); i++)
193  w += blocks_[i]->ft();
194  return w;
195 }
196 //---------------------------------------------------------------------------
198 {
199  double p;
200  for (int i=0; i<blocks_.size(); i++)
201  p += blocks_[i]->potential();
202  return p;
203 }
204 //---------------------------------------------------------------------------
205 void a_structure::link_blocks(int rb1, int rf1, int rb2, int rf2)
206 {
207  a_block * b1 = blocks_[rb1];
208  a_block * b2 = blocks_[rb2];
209  a_face * f1 = b1->i(rf1);
210  a_face * f2 = b2->i(rf2);
211  f1->lface(f2);
212  f2->lface(f1);
213  if (f1->contacttype()==-1)
214  std::cerr << "warning! faces of block " << rb1 << " and " << rb2 << " are not touching." << std::endl;
215 }
216 //---------------------------------------------------------------------------
217 a_block * a_structure::b(const int i) const
218 {
219  if ((i<0)||(i>blocks_.size()-1)) throw range_error();
220  return blocks_[i];
221 }
222 //---------------------------------------------------------------------------
224 {
225  for (int i=0; i<blocks_.size(); i++)
226  {
227  if (blocks_[i]->out().size()==4)
228  return false;
229  }
230  return true;
231 }
232 //---------------------------------------------------------------------------
233 std::vector<int> a_structure::out() const
234 {
235  std::vector<int> list;
236  for (int i=0; i<blocks_.size(); i++)
237  {
238  if (blocks_[i]->in().size()==1)
239  list.push_back(i);
240  }
241  return list;
242 }
243 //---------------------------------------------------------------------------
244 std::vector<int> a_structure::in() const
245 {
246  std::vector<int> list;
247  for (int i=0; i<blocks_.size(); i++)
248  {
249  if (blocks_[i]->in().size()>1)
250  list.push_back(i);
251  }
252  return list;
253 }
254 //---------------------------------------------------------------------------
255 std::vector<int> a_structure::nodes() const
256 {
257  std::vector<int> list;
258  for (int i=0; i<blocks_.size(); i++)
259  {
260  if (blocks_[i]->in().size()>2)
261  list.push_back(i);
262  }
263  return list;
264 }
265 //---------------------------------------------------------------------------
267 {
268  for (int i=0; i<this->blocks_.size(); i++)
269  blocks_[i]->clearinternal();
270 }
271 //---------------------------------------------------------------------------
273 {
274  for (int i=0; i<this->blocks_.size(); i++)
275  blocks_[i]->clearexternal();
276 }
277 //---------------------------------------------------------------------------
279 {
280  for (int i=0; i<this->blocks_.size(); i++)
281  blocks_[i]->clearall();
282 }
283 //---------------------------------------------------------------------------
285 {
286  if (objective_==0) return 0;
287  return objective_->f(this);
288 }
289 //---------------------------------------------------------------------------
290 double a_structure::objectivep() const
291 {
292  return this->objective()+penalty_factor_*this->penalty();
293 }
294 //---------------------------------------------------------------------------
296 {
297  for (int i=0; i<this->blocks_.size(); i++)
299 }
300 //---------------------------------------------------------------------------
301 bool a_structure::ok() const
302 {
303  for (int i=0; i<this->blocks_.size(); i++)
304  {
305  if (!blocks_[i]->ok())
306  return false;
307  }
308  return true;
309 }
310 //---------------------------------------------------------------------------
311 double a_structure::penalty() const
312 {
313  double val = 0;
314  for (int i=0; i<this->blocks_.size(); i++)
315  {
316  double v = blocks_[i]->penalty();
317 //VE(v)
318  if (v>val)
319  val = v;
320  }
321  return val;
322 }
323 //---------------------------------------------------------------------------
324 void a_structure::rotate(int rb, int rf, const a_point& x, const a_point& dir, double r)
325 {
326  if (!this->check_blockref(rb,rf)) return;
327  a_block * b = blocks_[rb];
328  b->entrance(rf);
329  b->pos()->rotate(x,dir,r);
330  while (a_block * b2 = b->nextblock())
331  {
332  b2->pos()->rotate(x,dir,r);
333  b = b2;
334  }
335 }
336 //---------------------------------------------------------------------------
337 void a_structure::rotate(int rb, int rf, double ex, double r)
338 {
339  if (!this->check_blockref(rb,rf)) return;
340  a_block * b = blocks_[rb];
341  a_face * f = b->i(rf);
342  //a_face_2d4 * f = cf_2d4(b->i(rf));
343  a_point x = f->point(ex,0.);
344  a_point dir = f->ny();
345  this->rotate(rb,rf,x,dir,r);
346 }
347 //---------------------------------------------------------------------------
348 void a_structure::slide(int rb, int rf, double u, double v)
349 {
350  if (!this->check_blockref(rb,rf)) return;
351  a_block * b = blocks_[rb];
352  b->entrance(rf);
353  a_face_2d4 * f = cf_2d4(b->i(rf));
354  a_point nx = f->nx();
355  a_point ny = f->ny();
356  a_point d = u*nx+v*ny;
357  b->pos()->translate(d);
358  while (a_block * b2 = b->nextblock())
359  {
360  b2->pos()->translate(d);
361  b = b2;
362  }
363 }
364 //---------------------------------------------------------------------------
366 {
367  for (int i=0; i<blocks_.size(); i++)
369 }
370 //---------------------------------------------------------------------------
371 void a_structure::storeexits(std::vector<int>& exits) const
372 {
373  for (int i=0; i<this->nb(); i++)
374  exits.push_back(blocks_[i]->exit());
375 }
376 //---------------------------------------------------------------------------
377 void a_structure::restoreexits(std::vector<int>& exits)
378 {
379  for (int i=0; i<this->nb(); i++)
380  blocks_[i]->exit(exits[i]);
381  exits.clear();
382 }
383 //---------------------------------------------------------------------------
384 bool a_structure::faceonexit(const int rb1, const int rf1, const int rb2, const int rf2)
385 {
386 //VE(rb1)
387 //VE(rf1)
388 //VE(rb2)
389 //VE(rf2)
390  bool exit;
391  std::vector<int> exits;
392  this->storeexits(exits);
393  a_block * b1 = blocks_[rb1];
394 //VE(b1->c())
395  b1->entrance(rf1);
396  a_block * b2 = blocks_[rb2];
397  while (true)
398  {
399  a_block * b = b1->nextblock();
400 //VE(b1->c())
401  if (b==0)
402  {
403  throw a_block::no_block_error();
404  }
405  if (b==b2)
406  {
407  if (b->exit()==rf2)
408  exit = true;
409  else
410  exit = false;
411  break;
412  }
413  b1=b;
414  }
415  this->restoreexits(exits);
416  return exit;
417 }
418 //---------------------------------------------------------------------------
420 {
421  std::vector<int> exits;
422  this->storeexits(exits);
423  a_block * block = blocks_[b];
424  a_block * block0 = block;
425  //set the exit face of first block
426  int code = block->entrance(f);
427  if (code != 0)
428  {
429  return 0;
430  }
431  while (a_block * block2 = block->compute())
432  {
433  block = block2;
434  }
435  this->restoreexits(exits);
436  return block;
437 }
438 //---------------------------------------------------------------------------
439 bool a_structure::check_block(const int rb) const
440 {
442  int nb = this->nb();
443  if ((rb<0)||(rb>nb-1))
444  return false;
445  return true;
446 }
447 //---------------------------------------------------------------------------
448 bool a_structure::check_blockref(const int rb, const int rf) const
449 {
451  int nb = this->nb();
452  if ((rb<0)||(rb>nb-1))
453  return false;
455  if ((rf<0)||(rf>3))
456  return false;
457  return true;
458 }
459 //---------------------------------------------------------------------------
460 void a_structure::compute(const int rb1, const int rf1, const double u1, const double v1,
461  const int rb2, const int rf2, const double u2, const double v2,
462  const int rb3, const int rf3, const double u3, const double v3)
463 {
465  if (!this->check_blockref(rb1,rf1)) return;
466  if (!this->check_blockref(rb2,rf2)) return;
467  if (!this->check_blockref(rb3,rf3)) return;
468  std::vector<int> exits;
469  this->storeexits(exits);
471  a_block * b0 = blocks_.front();
472  for (int i =0; i<b0->ni(); i++)
473  {
474  a_face * f = b0->i(i);
475  if ((f->out())&&(f->exit()))
476  f->f(0.,0.,0.);
477  }
478  a_block * bn = blocks_.back();
479  for (int i =0; i<bn->ni(); i++)
480  {
481  a_face * f = bn->i(i);
482  if ((f->out())&&(f->exit()))
483  f->f(0.,0.,0.);
484  }
487  a_block * b1 = blocks_[rb1];
488  b1->entrance(rf1);
489  a_block * b2 = blocks_[rb2];
490  a_block * bm;
491  if (!this->faceonexit(rb1,rf1,rb2,rf2))
492  {
495  b2->exit(rf2);
496  bm = b2->nextblock();
497  a_face_2d4 * f2 = cf_2d4(b2->i(rf2));
498  int r = f2->lface()->rf();
499  bm->exit(r);
500  }
501  else
502  {
503  bm = b2;
504  bm->exit(rf2);
505  }
506  a_block * bm2 = bm->nextblock();
507  a_block * b3 = blocks_[rb3];
509  a_wrench ft1 = b1->ft(*bm);
510  a_wrench ft2 = bm2->ft(*b3);
511  a_wrench ftt = ft1+ft2;
513  a_face_2d4 * f1 = cf_2d4(b1->i(rf1));
514  a_face_2d4 * f2 = cf_2d4(b2->i(rf2));
515  a_face_2d4 * f3 = cf_2d4(b3->i(rf3));
517  a_point p1 = f1->point(u1,v1);
518  a_point p2 = f2->point(u2,v2);
519  a_point p3 = f3->point(u3,v3);
520  //now use directly a_wrench capacity (not sure it is a good idea, see commit 64503e0a4b243fbc50fced6c738aefec455a8879 in case of problem)
521  a_wrench f0(p1,p2,p3,ft1,ft2);
522  f1->f(f0);
524  this->compute(rb1,rf1);
525  a_face * f1b = f1->lface();
526  if (f1b!=0)
527  {
529  a_block * b1b = f1b->block();
530  f1b->f(-f0);
531  //get reference of face
532  int rf1b = f1b->rf();
533  //set the exit face block
534  b1b->entrance(rf1b);
535  int r1b = this->rb(b1b);
536  this->compute(r1b,rf1b);
537  }
538  this->restoreexits(exits);
539 //VE(this->objective())
540 //VE(this->b(0)->i(3)->f())
541 }
542 //---------------------------------------------------------------------------
543 void a_structure::midblock( const int rb1, const int rf1,
544  const int rb2, const int rf2,
545  a_block *& b, int&rf)
546 {
548  if (!this->check_blockref(rb1,rf1)) return;
549  if (!this->check_blockref(rb2,rf2)) return;
551  a_block * b1 = blocks_[rb1];
552  a_block * b0 = b1;
553  b1->entrance(rf1);
554  a_block * b2 = blocks_[rb2];
555  int r = 0;
556  while (true)
557  {
558  r++;
559  a_block * b = b1->nextblock();
560  if (b==0)
561  throw a_block::no_block_error();
562  if (b==b2)
563  break;
564  b1=b;
565  }
566  if (r<2)
567  return;
568  int rb = r/2;
569  b1 = b0;
570  for (int i=0; i<rb; i++)
571  {
572  a_block * b = b1->nextblock();
573  b1 = b;
574  }
575  b = b1;
576  rf = b1->exit();
577 }
578 //---------------------------------------------------------------------------
580 {
581 public:
583  int rb1, int rf1,
584  int rb2, int rf2,
585  int rb3, int rf3):
586  vnl_least_squares_function(3, 2, no_gradient), rb1_(rb1), rf1_(rf1), rb2_(rb2), rf2_(rf2), rb3_(rb3), rf3_(rf3),
587  s_(s), pfactor_(1.) {}
588  void f(const vnl_vector<double>& x, vnl_vector<double>& fx)
589  {
590  s_->compute(rb1_,rf1_,x[0],0.,rb2_,rf2_,x[1],0.,rb3_,rf3_,x[2],0.);
591  double v = s_->objective();
592  double p = s_->penalty();
593  fx[0] = v;
594  fx[1] = p*pfactor_;
595 //VL(x[0])
596 //VL(x[1])
597 //VL(x[2])
598 //VE(v)
599  }
600  void pfactor(const double val) {pfactor_=val;}
601 protected:
604  double pfactor_;
605 
606 };
607 //---------------------------------------------------------------------------
609 {
610 public:
612  int rb1, int rf1,
613  int rb2, int rf2,
614  int rb3, int rf3) :
616  rb1_(rb1), rf1_(rf1), rb2_(rb2), rf2_(rf2), rb3_(rb3), rf3_(rf3),
617  s_(s) {};
618  double f(const vnl_vector<double>& x);
619 protected:
622 };
623 //---------------------------------------------------------------------------
624 double a_objective_function::f(const vnl_vector<double>& x)
625 {
626 /* double u0 = sin(x[0]);
627  double u1 = sin(x[1]);
628  double u2 = sin(x[2]);
629 */
630  double u0 = x[0];
631  double u1 = x[1];
632  double u2 = x[2];
633  s_->compute(rb1_,rf1_,u0,0.,rb2_,rf2_,u1,0.,rb3_,rf3_,u2,0.);
634  return s_->objectivep();
635 }
636 /*
637 //---------------------------------------------------------------------------
638 void a_structure::min( const int rb1, const int rf1,
639  const int rb3, const int rf3)
640 {
641  this->optimise(true,rb1,rf1,rb3,rf3);
642 }
643 */
644 //---------------------------------------------------------------------------
645 void a_structure::max( const int rb1, const int rf1,
646  const int rb3, const int rf3)
647 {
648  this->optimise(false,rb1,rf1,rb3,rf3);
649 }
650 //---------------------------------------------------------------------------
651 double a_structure::grad1(const int rb1, const int rf1,
652  const int rb2, const int rf2,
653  const int rb3, const int rf3,
654  const double * u)
655 {
656  const double small=1.e-4;
657  this->compute(rb1,rf1,u[0]+small,0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
658  double v2 = this->objectivep();
659  this->compute(rb1,rf1,u[0]-small,0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
660  double v1 = this->objectivep();
661  return (v2-v1)/small/2.;
662 }
663 //---------------------------------------------------------------------------
664 double a_structure::grad2(const int rb1, const int rf1,
665  const int rb2, const int rf2,
666  const int rb3, const int rf3,
667  const double * u)
668 {
669  const double small=1.e-4;
670  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1]+small,0.,rb3,rf3,u[2],0.);
671  double v2 = this->objectivep();
672  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1]-small,0.,rb3,rf3,u[2],0.);
673  double v1 = this->objectivep();
674  return (v2-v1)/small/2.;
675 }
676 //---------------------------------------------------------------------------
677 double a_structure::grad3(const int rb1, const int rf1,
678  const int rb2, const int rf2,
679  const int rb3, const int rf3,
680  const double * u)
681 {
682  const double small=1.e-4;
683  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2]+small,0.);
684  double v2 = this->objectivep();
685  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2]-small,0.);
686  double v1 = this->objectivep();
687  return (v2-v1)/small/2.;
688 }
689 //---------------------------------------------------------------------------
690 void a_structure::minsteep( const int rb1, const int rf1,
691  const int rb3, const int rf3)
692 {
693  if (objective_ == 0) return;
694  std::vector<int> exits;
695  this->storeexits(exits);
696  int rf2;
697  a_block * b2;
698  this->midblock(rb1,rf1,rb3,rf3,b2,rf2);
699  int rb2 = this->rb(b2);
700  double u[] = {0.,0.,0.};
701  double g1 = this->grad1(rb1,rf1,rb2,rf2,rb3,rf3,u);
702  double g2 = this->grad2(rb1,rf1,rb2,rf2,rb3,rf3,u);
703  double g3 = this->grad3(rb1,rf1,rb2,rf2,rb3,rf3,u);
704  a_point g(g1,g2,g3);
705  this->mindir(g,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
706 /*
707 // g.max();
708  VE(g)
709  for (int i=0; i<20; i++)
710  {
711  this->mindir(g,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
712 VL(u[0])
713 VL(u[1])
714 VE(u[2])
715  double g1 = this->grad1(rb1,rf1,rb2,rf2,rb3,rf3,u);
716  double g2 = this->grad2(rb1,rf1,rb2,rf2,rb3,rf3,u);
717  double g3 = this->grad3(rb1,rf1,rb2,rf2,rb3,rf3,u);
718  g.set(g1,g2,g3);
719  }
720 */
721  this->restoreexits(exits);
722 }
723 //---------------------------------------------------------------------------
724 void a_structure::optimise( const bool is_min,
725  const int rb1, const int rf1,
726  const int rb3, const int rf3)
727 {
728  if (objective_ == 0) return;
729  std::vector<int> exits;
730  this->storeexits(exits);
731  double penalty_factor0 = penalty_factor_;
732  const double mult = 10.;
733  int rf2;
734  a_block * b2;
735  this->midblock(rb1,rf1,rb3,rf3,b2,rf2);
736  int rb2 = this->rb(b2);
737  double u[] = {0.,0.,0.};
738  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
740  double v0 = this->objectivep();
741  for (int i=0;i<5;i++)
742  {
743 VE(this->b(0)->exit())
745 VE(penalty_factor_)
746 this->minsteep(rb1,rf1,rb3,rf3);
747  while (1)
748  {
749  for (int f=0;f<3;f++)
750  {
751  if (is_min)
752  u[f] = this->min(f,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
753  else
754  u[f] = this->max(f,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
755  }
756  double v = this->objectivep();
757  if (v==v0)
758  break;
759  v0=v;
760  }
761 VL(u[0])
762 VL(u[1])
763 VE(u[2])
764  }
765  this->restoreexits(exits);
766  penalty_factor_ = penalty_factor0;
767 }
768 //---------------------------------------------------------------------------
769 void a_structure::min( const int rb1, const int rf1,
770  const int rb3, const int rf3)
771 {
772  if (objective_ == 0) return;
773  std::vector<int> exits;
774  this->storeexits(exits);
775  double penalty_factor0 = penalty_factor_;
776  const double mult = 10.;
777  int rf2;
778  a_block * b2;
779  this->midblock(rb1,rf1,rb3,rf3,b2,rf2);
780  int rb2 = this->rb(b2);
781 
782  vnl_vector<double> x(3);
783  x(0) = x(1) = x(2) = 0;
784  a_objective_function f(this,rb1,rf1,rb2,rf2,rb3,rf3);
785  vnl_lbfgs op(f);
786 // op.minimize(x);
787 
788  this->restoreexits(exits);
789  penalty_factor_ = penalty_factor0;
790 }
791 //---------------------------------------------------------------------------
792 double a_structure::min( const int face,
793  const int rb1, const int rf1, const double u1,
794  const int rb2, const int rf2, const double u2,
795  const int rb3, const int rf3, const double u3)
796 {
797  double u[] = {u1,u2,u3};
798  const double gold = (1+sqrt(5.))/2.;
799  double x1 = -1;
800  double x3 = 1.;
801  double x2 = x3-(x3-x1)/gold;
802  u[face] = x2;
803  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
804  double f2 = this->objectivep();
805  bool grow = true;
806  while (x3-x1>0.0001)
807  {
808  double xn;
809  if (grow)
810  xn = x3-(x3-x2)/gold;
811  else
812  xn = x1+(x2-x1)/gold;
813  u[face] = xn;
814  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
815  double fn = this->objectivep();
816  if (fn<f2)
817  {
818  if (grow)
819  x1 = x2;
820  else
821  x3 = x2;
822  x2 = xn;
823  f2 = fn;
824  }
825  else
826  {
827  if (grow)
828  x3 = xn;
829  else
830  x1 = xn;
831  grow = !grow;
832  }
833  }
834  VE(f2)
835  return x2;
836 }
837 //---------------------------------------------------------------------------
838 double a_structure::mindir(const a_point & dir,
839  const int rb1, const int rf1, double & u1,
840  const int rb2, const int rf2, double & u2,
841  const int rb3, const int rf3, double & u3)
842 {
843  a_point u(u1,u2,u3);
844  double step = .1;
845  double f;
846  do
847  {
848  VE(step)
849  f = 1.e30;
850  double f0;
851  for (int i=0; i<100; i++)
852  {
853  f0 = f;
854  u -= step*dir;
855  this->compute(rb1,rf1,u.x(),0.,rb2,rf2,u.y(),0.,rb3,rf3,u.z(),0.);
856  f = this->objectivep();
857  if (f>f0)
858  {
859  CL(**)
860  break;
861  }
862  VL(f)
863  VL(f0)
864  }
865  if (f<f0)
866  std::exit(-1);
867  u += 2*step*dir;
868  step /= 10.;
869  CE(-)
870  } while (step>.0001);
871  u1 = u.x(); u2 = u.y(); u3 = u.z();
872  return f;
873 }
874 //---------------------------------------------------------------------------
875 double a_structure::max(const int face,
876  const int rb1, const int rf1, const double u1,
877  const int rb2, const int rf2, const double u2,
878  const int rb3, const int rf3, const double u3)
879 {
880  double u[] = {u1,u2,u3};
881  const double gold = (1+sqrt(5.))/2.;
882  double x1 = -1;
883  double x3 = 1.;
884  double x2 = x3-(x3-x1)/gold;
885  u[face] = x2;
886  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
887  double f2 = this->objectivep();
888  bool grow = true;
889  while (x3-x1>0.0001)
890  {
891  double xn;
892  if (grow)
893  xn = x3-(x3-x2)/gold;
894  else
895  xn = x1+(x2-x1)/gold;
896  u[face] = xn;
897  this->compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
898  double fn = this->objectivep();
899  if (fn>f2)
900  {
901  if (grow)
902  x1 = x2;
903  else
904  x3 = x2;
905  x2 = xn;
906  f2 = fn;
907  }
908  else
909  {
910  if (grow)
911  x3 = xn;
912  else
913  x1 = xn;
914  grow = !grow;
915  }
916  }
917  VE(f2)
918  return x2;
919 }
920 //***************************************************************************
921 //---------------------------------------------------------------------------
922 void a_structure::writetri(std::ostream &o) const
923 {
924  a_trianglecloud tri;
925  this->trianglecloud(tri);
926  tri.write(o);
927  tri.clear();
928 }
929 //---------------------------------------------------------------------------
930 void a_structure::writeb(std::ostream &o) const
931 {
932  for (int i=0; i<blocks_.size(); i++)
933  {
934  blocks_[i]->writeb(o);
935  o << std::endl;
936  }
937 }
938 //---------------------------------------------------------------------------
939 void a_structure::writeg(std::ostream &o) const
940 {
941  for (int i=0; i<blocks_.size(); i++)
942  {
943  o << "in b" << i << ".s ";
944  blocks_[i]->writeg(o);
945  o << std::endl;
946  o << "r b" << i << ".r u b" << i << ".s" << std::endl;
947  }
948  o << "g structure.g ";
949  for (int i=0; i<blocks_.size(); i++)
950  o << "b" << i << ".r ";
951  o << std::endl;
952 }
953 //---------------------------------------------------------------------------
954 void a_structure::trianglecloud(a_trianglecloud& tri) const
955 {
956  tri.clear();
957  for (int i=0; i<blocks_.size(); i++)
958  blocks_[i]->trianglecloud(tri);
959 }
960 //---------------------------------------------------------------------------
961 void a_structure::polyline(a_linecloud& li) const
962 {
963  li.clear();
964  for (int i=0; i<blocks_.size(); i++)
965  {
966  a_block * block = blocks_[i];
967  int k;
968  k = 0;
969  a_point p[2];
970  for (int j=0; j<block->ni(); j++)
971  {
972  a_face * fac = blocks_[i]->i(j);
973  //will work only if 2 inside faces -> arch, column...
974  //but polyline make no sense otherwise
975  if ((fac->exit()==1)||(fac->in()==1))
976  {
977  p[k] = fac->x();
978  k += 1;
979  }
980  }
981  if (k==2)
982  li.addline(p[0],p[1]);
983  if (k>2)
984  {
985  std::cout << "block " << i << " contains too many inside connections (" << k << ")!" << std::endl;
986  std::cout << "no line was added for this block" << std::endl;
987  }
988  }
989 }
990 //---------------------------------------------------------------------------
991 std::istream& operator>> (std::istream& in, a_structure& s)
992 {
993  int nb;
994  in >> nb;
995  for (int i=0; i<nb; i++)
996  {
997  a_block * b = new a_block_2d4;
998  s.blocks_.push_back(b);
999  in >> (*b);
1000  }
1001  return in;
1002 }
1003 //---------------------------------------------------------------------------
1004 std::ostream& operator<<(std::ostream& o, const a_structure& s)
1005 {
1006  o << s.nb() << std::endl;
1007  for (int i=0; i<s.nb(); i++)
1008  o << s.blocks_[i] << std::endl;
1009  return o;
1010 }
a_face_2d4 * cf_2d4(a_face *f)
Definition: a_face_2d4.cxx:26
std::istream & operator>>(std::istream &in, a_structure &s)
std::ostream & operator<<(std::ostream &o, const a_structure &s)
a_block * compute()
compute the exit force from all the forces on the block, return next block or 0 if last one or proble...
Definition: a_block.cxx:310
int entrance(int ref)
set exit face specifying where the force enters
Definition: a_block.cxx:409
a_wrench ft() const
total force on block in world coordinate
Definition: a_block.cxx:200
a_face * i(const int i)
get pointer to face
Definition: a_block.cxx:148
int ni() const
get number of faces
Definition: a_block.h:83
a_twist * pos() const
get pointer to position handle
Definition: a_block.h:101
void exit(int ref)
set exit face
Definition: a_block.cxx:397
a_block * nextblock() const
block connected (return 0 if end or problem)
Definition: a_block.cxx:229
a_point nx() const
direction of face
Definition: a_face_2d4.cxx:89
a_point ny() const
normal to the vertices of the block
Definition: a_face_2d4.cxx:113
Definition: a_face.h:33
bool in() const
face is connected to other faces, inside the structure
Definition: a_face.h:159
void lface(a_face *f)
set connected face
Definition: a_face.h:153
void exit(bool exit)
set as an exit face
Definition: a_face.h:72
virtual a_point x() const
application point of f on face
Definition: a_face.cxx:400
int rf() const
get face reference in connected block
Definition: a_face.h:47
virtual int contacttype() const =0
contact type: (-2: no sister face, -1: not touching, 2: plane contact, 1: edge contact,...
virtual a_point point(const double &u, const double &v=0.) const
get point on face given excentricities
Definition: a_face.cxx:212
void f(const a_wrench &f)
set force on the face
Definition: a_face.h:133
virtual a_point ny() const =0
normal to the vertices of the block (in world coordinate)
bool out() const
face is not connected to other faces, on the boudary
Definition: a_face.h:161
a_block * block()
get block
Definition: a_face.h:49
a_objective_function(a_structure *s, int rb1, int rf1, int rb2, int rf2, int rb3, int rf3)
double f(const vnl_vector< double > &x)
virtual double f(const a_structure *f) const
return an objective value used for optimization (can be the thrust for instance) (look at derived cla...
Definition: a_ocriteria.h:29
structure class
Definition: a_structure.h:33
int rb(const a_block *b) const
get reference of a block (-1 if no block)
std::vector< int > nodes() const
get list of blocks connected to more than 2 other blocks (sources of hyperstaticity)
void rotate(int rb, int f, const a_point &x, const a_point &dir, double r)
rotate of angle r (rad) all blocks connected to rb, around x using axis dir
void minsteep(const int rb1, const int rf1, const int rb2, const int rf2)
a_ocriteria * objective_
Definition: a_structure.h:188
double max(const int face, const int rb1, const int rf1, const double u1, const int rb2, const int rf2, const double u2, const int rb3, const int rf3, const double u3)
vary force on face to get a maximal objective function, respecting face criteria
void trianglecloud(a_trianglecloud &) const
a_wrench W()
get weight (wrench)
void polyline(a_linecloud &) const
double min(const int face, const int rb1, const int rf1, const double u1, const int rb2, const int rf2, const double u2, const int rb3, const int rf3, const double u3)
vary force on face to get a minimal objective function, respecting face criteria
void restoreexits(std::vector< int > &)
restore face exits situation
a_block * compute(int b, int f)
compute as far as possible the forces on the blocks, starting from block b, entrance face f,...
double V() const
get volume of structure
void clearexternal()
clear all the external face forces
bool connected() const
check whether all blocks are connected
void clear()
Definition: a_structure.cxx:48
double penalty_factor_
Definition: a_structure.h:189
bool faceonexit(const int rb1, const int rf1, const int rb2, const int rf2)
check whether rf2 in an exit face
std::vector< int > out() const
get list of extreme blocks (blocks connected only to 1 other block)
void clearall()
clear all the forces on faces
int nb() const
get number of blocks
Definition: a_structure.h:41
static const std::string help()
get information about the class
Definition: a_structure.cxx:54
double objectivep() const
get value of objective function + penalty*penalty_factor_
double grad2(const int rb1, const int rf1, const int rb2, const int rf2, const int rb3, const int rf3, const double *u)
grad of objective function + penalty
void slide(int b, int f, double u, double v)
slide of (u,v) all blocks connected to b in the plane of f
virtual void writeb(std::ostream &o) const
write structure in blender format
void clearinternal()
clear all the internal face forces
double potential() const
get potential energy
int add_block(a_block *b)
add a block to the structure
a_wrench ft()
get total force on structure fe+W (wrench)
std::vector< int > in() const
get list of internal blocks (blocks connected at least to 2 other blocks)
double mindir(const a_point &dir, const int rb1, const int rf1, double &u1, const int rb2, const int rf2, double &u2, const int rb3, const int rf3, double &u3)
vary force on faces (in proportion to dir) to get a minimal objective function, respecting face crite...
double Ws() const
get weight (scalar)
a_wrench fe()
get external force on structure (wrench)
void material(a_material *material)
link a material
double grad1(const int rb1, const int rf1, const int rb2, const int rf2, const int rb3, const int rf3, const double *u)
grad of objective function + penalty
bool ok() const
check if forces on face are acceptable
void criteria(a_fcriteria *criteria)
set resistance criteria
a_block * b(const int i) const
get pointer to the block i
void optimise(const bool is_min, const int rb1, const int rf1, const int rb2, const int rf2)
compute inside forces leading to an optimal objective function, respecting face criteria
double grad3(const int rb1, const int rf1, const int rb2, const int rf2, const int rb3, const int rf3, const double *u)
grad of objective function + penalty
void objective(a_ocriteria *objective)
set objective function (used for optimisation)
Definition: a_structure.h:81
void link_blocks(int b1, int f1, int b2, int f2)
link 2 blocks: [b1: ref_block1, f1: ref_face1, b2:...]
virtual void writetri(std::ostream &o) const
write a triangle file
double objective() const
get value of objective function
void midblock(const int rb1, const int rf1, const int rb2, const int rf2, a_block *&rb, int &rf)
block and face in between two face blocks
std::vector< a_block * > blocks_
Definition: a_structure.h:187
virtual void writeg(std::ostream &o) const
write structure in brlcad format
double m() const
mass
bool check_block(const int rb) const
check whether references are in range
double penalty() const
penalty value used for optimization
bool check_blockref(const int rb, const int rf) const
check whether references are in range
a_point c() const
get centre of mass
void storeexits(std::vector< int > &) const
store face exits situation
void rotate(const a_point &pt, const a_point &dir, double v)
Definition: a_twist.cxx:209
void translate(const a_point &d)
iterative transformation
Definition: a_twist.cxx:151
a wrench class
Definition: a_wrench.h:30
double pfactor_
int rf1_
int rb3_
void pfactor(const double val)
int rb1_
int rf2_
int rf3_
int rb2_
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
a_structure * s_
vet(a_structure *s, int rb1, int rf1, int rb2, int rf2, int rb3, int rf3)