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>
50 for(std::vector<a_block *>::iterator it =
blocks_.begin(); it !=
blocks_.end(); ++it) (*it)->clear();
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;
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;
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;
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;
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;
127 for (
int i=0; i<
blocks_.size(); i++)
139 for (
int i=0; i<
blocks_.size(); i++)
146 double w = this->
Ws();
148 for (
int i=0; i<
blocks_.size(); i++)
160 for (
int i=0; i<
blocks_.size(); i++)
168 for (
int i=0; i<
blocks_.size(); i++)
176 for (
int i=0; i<
blocks_.size(); i++)
184 for (
int i=0; i<
blocks_.size(); i++)
192 for (
int i=0; i<
blocks_.size(); i++)
200 for (
int i=0; i<
blocks_.size(); i++)
214 std::cerr <<
"warning! faces of block " << rb1 <<
" and " << rb2 <<
" are not touching." << std::endl;
225 for (
int i=0; i<
blocks_.size(); i++)
235 std::vector<int> list;
236 for (
int i=0; i<
blocks_.size(); i++)
246 std::vector<int> list;
247 for (
int i=0; i<
blocks_.size(); i++)
257 std::vector<int> list;
258 for (
int i=0; i<
blocks_.size(); i++)
268 for (
int i=0; i<this->
blocks_.size(); i++)
274 for (
int i=0; i<this->
blocks_.size(); i++)
280 for (
int i=0; i<this->
blocks_.size(); i++)
297 for (
int i=0; i<this->
blocks_.size(); i++)
303 for (
int i=0; i<this->
blocks_.size(); i++)
314 for (
int i=0; i<this->
blocks_.size(); i++)
316 double v =
blocks_[i]->penalty();
332 b2->pos()->rotate(x,dir,r);
343 a_point x = f->
point(ex,0.);
344 a_point dir = f->
ny();
345 this->
rotate(rb,rf,x,dir,r);
354 a_point nx = f->
nx();
355 a_point ny = f->
ny();
356 a_point d = u*nx+v*ny;
360 b2->pos()->translate(d);
367 for (
int i=0; i<
blocks_.size(); i++)
373 for (
int i=0; i<this->
nb(); i++)
374 exits.push_back(
blocks_[i]->exit());
379 for (
int i=0; i<this->
nb(); i++)
391 std::vector<int> exits;
421 std::vector<int> exits;
443 if ((rb<0)||(
rb>
nb-1))
452 if ((rb<0)||(
rb>
nb-1))
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)
468 std::vector<int> exits;
472 for (
int i =0; i<b0->
ni(); i++)
479 for (
int i =0; i<bn->
ni(); i++)
498 int r = f2->
lface()->rf();
517 a_point p1 = f1->
point(u1,v1);
518 a_point p2 = f2->
point(u2,v2);
519 a_point p3 = f3->
point(u3,v3);
532 int rf1b = f1b->
rf();
535 int r1b = this->
rb(b1b);
544 const int rb2,
const int rf2,
570 for (
int i=0; i<
rb; i++)
588 void f(
const vnl_vector<double>& x, vnl_vector<double>& fx)
590 s_->
compute(
rb1_,
rf1_,x[0],0.,
rb2_,
rf2_,x[1],0.,
rb3_,
rf3_,x[2],0.);
618 double f(
const vnl_vector<double>& x);
633 s_->
compute(
rb1_,
rf1_,u0,0.,
rb2_,
rf2_,u1,0.,
rb3_,
rf3_,u2,0.);
646 const int rb3,
const int rf3)
648 this->
optimise(
false,rb1,rf1,rb3,rf3);
652 const int rb2,
const int rf2,
653 const int rb3,
const int rf3,
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.);
659 this->
compute(rb1,rf1,u[0]-small,0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
661 return (v2-v1)/small/2.;
665 const int rb2,
const int rf2,
666 const int rb3,
const int rf3,
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.);
672 this->
compute(rb1,rf1,u[0],0.,rb2,rf2,u[1]-small,0.,rb3,rf3,u[2],0.);
674 return (v2-v1)/small/2.;
678 const int rb2,
const int rf2,
679 const int rb3,
const int rf3,
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.);
685 this->
compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2]-small,0.);
687 return (v2-v1)/small/2.;
691 const int rb3,
const int rf3)
694 std::vector<int> exits;
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);
705 this->
mindir(g,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
725 const int rb1,
const int rf1,
726 const int rb3,
const int rf3)
729 std::vector<int> exits;
732 const double mult = 10.;
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.);
741 for (
int i=0;i<5;i++)
743 VE(this->
b(0)->exit())
749 for (
int f=0;f<3;f++)
752 u[f] = this->
min(f,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
754 u[f] = this->
max(f,rb1,rf1,u[0],rb2,rf2,u[1],rb3,rf3,u[2]);
770 const int rb3,
const int rf3)
773 std::vector<int> exits;
776 const double mult = 10.;
779 this->
midblock(rb1,rf1,rb3,rf3,b2,rf2);
780 int rb2 = this->
rb(b2);
782 vnl_vector<double> x(3);
783 x(0) = x(1) = x(2) = 0;
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)
797 double u[] = {u1,u2,u3};
798 const double gold = (1+sqrt(5.))/2.;
801 double x2 = x3-(x3-x1)/gold;
803 this->
compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
810 xn = x3-(x3-x2)/gold;
812 xn = x1+(x2-x1)/gold;
814 this->
compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
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)
851 for (
int i=0; i<100; i++)
855 this->
compute(rb1,rf1,u.x(),0.,rb2,rf2,u.y(),0.,rb3,rf3,u.z(),0.);
870 }
while (step>.0001);
871 u1 = u.x(); u2 = u.y(); u3 = u.z();
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)
880 double u[] = {u1,u2,u3};
881 const double gold = (1+sqrt(5.))/2.;
884 double x2 = x3-(x3-x1)/gold;
886 this->
compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
893 xn = x3-(x3-x2)/gold;
895 xn = x1+(x2-x1)/gold;
897 this->
compute(rb1,rf1,u[0],0.,rb2,rf2,u[1],0.,rb3,rf3,u[2],0.);
932 for (
int i=0; i<
blocks_.size(); i++)
941 for (
int i=0; i<
blocks_.size(); i++)
943 o <<
"in b" << i <<
".s ";
946 o <<
"r b" << i <<
".r u b" << i <<
".s" << std::endl;
948 o <<
"g structure.g ";
949 for (
int i=0; i<
blocks_.size(); i++)
950 o <<
"b" << i <<
".r ";
957 for (
int i=0; i<
blocks_.size(); i++)
964 for (
int i=0; i<
blocks_.size(); i++)
970 for (
int j=0; j<block->
ni(); j++)
975 if ((fac->
exit()==1)||(fac->
in()==1))
982 li.addline(p[0],p[1]);
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;
995 for (
int i=0; i<nb; i++)
1006 o << s.
nb() << std::endl;
1007 for (
int i=0; i<s.
nb(); i++)
1008 o << s.
blocks_[i] << std::endl;
a_face_2d4 * cf_2d4(a_face *f)
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...
int entrance(int ref)
set exit face specifying where the force enters
a_wrench ft() const
total force on block in world coordinate
a_face * i(const int i)
get pointer to face
int ni() const
get number of faces
a_twist * pos() const
get pointer to position handle
void exit(int ref)
set exit face
a_block * nextblock() const
block connected (return 0 if end or problem)
a_point nx() const
direction of face
a_point ny() const
normal to the vertices of the block
bool in() const
face is connected to other faces, inside the structure
void lface(a_face *f)
set connected face
void exit(bool exit)
set as an exit face
virtual a_point x() const
application point of f on face
int rf() const
get face reference in connected block
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
void f(const a_wrench &f)
set force on the face
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
a_block * block()
get block
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...
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)
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
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
static const std::string help()
get information about the class
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)
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_
virtual void writeg(std::ostream &o) const
write structure in brlcad format
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)
void translate(const a_point &d)
iterative transformation
void pfactor(const double val)
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
vet(a_structure *s, int rb1, int rf1, int rb2, int rf2, int rb3, int rf3)