Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_STACK_ANALYSIS_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_STACK_ANALYSIS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 namespace OpenTissue
00013 {
00014 namespace mbd
00015 {
00031 template<typename mbd_types>
00032 class StackAnalysis
00033 {
00034 protected:
00035
00036 typedef typename mbd_types::math_policy::index_type index_type;
00037 typedef typename mbd_types::math_policy::index_type size_type;
00038
00039 typedef typename mbd_types::math_policy::real_type real_type;
00040 typedef typename mbd_types::math_policy::vector3_type vector3_type;
00041 typedef typename mbd_types::group_type group_type;
00042 typedef typename mbd_types::body_type body_type;
00043 typedef typename mbd_types::edge_type edge_type;
00044
00045 typedef typename mbd_types::contact_type contact_type;
00046 typedef typename mbd_types::material_type material_type;
00047 typedef typename mbd_types::edge_ptr_container edge_ptr_container;
00048 typedef typename mbd_types::indirect_edge_iterator indirect_edge_iterator;
00049 typedef typename mbd_types::group_container group_container;
00050
00051 protected:
00052
00053 typedef typename std::vector<contact_type*> contact_ptr_heap;
00054 typedef typename std::list<body_type*> body_ptr_queue;
00055
00056 public:
00057
00058 class node_traits
00059 {
00060 public:
00061 size_type m_sa_stack_height;
00062 bool m_sa_queue_tag;
00063
00064 node_traits()
00065 : m_sa_stack_height(0)
00066 {}
00067
00068 };
00069
00070 class edge_traits
00071 {
00072 public:
00073 size_type m_sa_stack_layer;
00074 size_type m_sa_visit_time_stamp;
00075
00076 edge_traits()
00077 : m_sa_visit_time_stamp(0)
00078 {}
00079 };
00080
00081 class constraint_traits{ };
00082
00083 protected:
00084
00085 index_type m_time_stamp;
00086
00087 public:
00088
00089 StackAnalysis()
00090 : m_time_stamp(0)
00091 {}
00092
00093 public:
00094
00103 size_type analyze(group_type & group,group_container & layers)
00104 {
00105 using std::min;
00106 using std::max;
00107
00108 layers.clear();
00109
00110 size_type N = group.size_bodies();
00111 if(N==0)
00112 return 0;
00113
00114 ++m_time_stamp;
00115 body_ptr_queue Q;
00116 {
00117 typename group_type::indirect_body_iterator begin = group.body_begin();
00118 typename group_type::indirect_body_iterator end = group.body_end();
00119 typename group_type::indirect_body_iterator body;
00120 for( body=begin; body!=end; ++body )
00121 {
00122 if(body->is_fixed() || body->is_scripted())
00123 {
00124 body->m_sa_stack_height = 0;
00125 Q.push_back(&(*body));
00126 body->m_sa_queue_tag = true;
00127 }
00128 else
00129 {
00130 body->m_sa_stack_height = N;
00131 body->m_sa_queue_tag = false;
00132 }
00133 }
00134 }
00135 if(Q.empty() || (group.size_contacts()==0))
00136 {
00137
00138 layers.resize(1);
00139 layers[0] = group;
00140 return 1;
00141 }
00142
00143 edge_ptr_container edges;
00144 size_type height = 0;
00145 while(!Q.empty())
00146 {
00147 body_type * body = Q.front();
00148 Q.pop_front();
00149 typename body_type::indirect_edge_iterator begin = body->edge_begin();
00150 typename body_type::indirect_edge_iterator end = body->edge_end();
00151 for(typename body_type::indirect_edge_iterator edge = begin;edge!=end;++edge)
00152 {
00153 if(!edge->is_up_to_date())
00154 continue;
00155
00156 body_type * next = (body==edge->get_body_A())? edge->get_body_B(): edge->get_body_A();
00157 bool has_joint = body->has_joint_to(next);
00158 if(edge->size_contacts()==0 && !has_joint)
00159 continue;
00160
00161 if(!next->m_sa_queue_tag)
00162 {
00163 Q.push_back(next);
00164 next->m_sa_queue_tag = true;
00165 }
00166
00167 next->m_sa_stack_height = min(next->m_sa_stack_height,body->m_sa_stack_height + 1);
00168
00169 if(next->m_sa_stack_height == body->m_sa_stack_height && next->m_sa_stack_height!=0)
00170 edge->m_sa_stack_layer = next->m_sa_stack_height-1;
00171 else
00172 edge->m_sa_stack_layer = min(next->m_sa_stack_height,body->m_sa_stack_height);
00173
00174 height = max(height,edge->m_sa_stack_layer);
00175
00176 if(edge->m_sa_visit_time_stamp!=m_time_stamp)
00177 {
00178 edge->m_sa_visit_time_stamp=m_time_stamp;
00179 edges.push_back(&(*edge));
00180 }
00181 }
00182 }
00183 if(edges.empty())
00184 {
00185
00186 layers.resize(1);
00187 layers[0] = group;
00188 return 1;
00189 }
00190
00191 {
00192 layers.resize(height+1);
00193 indirect_edge_iterator begin = edges.begin();
00194 indirect_edge_iterator end = edges.end();
00195 for(indirect_edge_iterator edge = begin;edge!=end;++edge)
00196 {
00197 size_type layer = edge->m_sa_stack_layer;
00198
00199 for(typename edge_type::contact_iterator contact = edge->contact_begin();contact!=edge->contact_end();++contact)
00200 {
00201 layers[layer].m_contacts.push_back( &(*contact) );
00202 }
00203
00204 if(edge->get_body_A()->has_joint_to(edge->get_body_B()))
00205 {
00206 for(typename body_type::indirect_joint_iterator joint = edge->get_body_A()->joint_begin();joint!=edge->get_body_A()->joint_end();++joint)
00207 {
00208 if(joint->get_socket_A()->get_body()==edge->get_body_B() || joint->get_socket_B()->get_body()==edge->get_body_B())
00209 {
00210 layers[layer].m_constraints.push_back(&(*joint));
00211 }
00212 }
00213 }
00214 }
00215 }
00216
00217 {
00218 typename group_type::indirect_body_iterator begin = group.body_begin();
00219 typename group_type::indirect_body_iterator end = group.body_end();
00220 for(typename group_type::indirect_body_iterator body=begin;body!=end;++body)
00221 {
00222 if(body->m_sa_stack_height==N)
00223 {
00224
00225 layers[height].m_bodies.push_back(&(*body));
00226 continue;
00227 }
00228 bool in_lower = false;
00229 bool in_upper = false;
00230 typename body_type::indirect_edge_iterator begin = body->edge_begin();
00231 typename body_type::indirect_edge_iterator end = body->edge_end();
00232 for(typename body_type::indirect_edge_iterator edge = begin;edge!=end;++edge)
00233 {
00234 if(!edge->is_up_to_date())
00235 continue;
00236 body_type * other = (edge->get_body_A()==&(*body))?edge->get_body_B():edge->get_body_A();
00237 if(other->m_sa_stack_height==N)
00238 continue;
00239 if(other->m_sa_stack_height > body->m_sa_stack_height)
00240 in_upper = true;
00241 if(other->m_sa_stack_height < body->m_sa_stack_height)
00242 in_lower = true;
00243 if(in_upper && in_lower)
00244 break;
00245 }
00246 if(in_upper)
00247 layers[body->m_sa_stack_height].m_bodies.push_back(&(*body));
00248 if(in_lower)
00249 layers[body->m_sa_stack_height - 1].m_bodies.push_back(&(*body));
00250 }
00251 }
00252 return height+1;
00253 }
00254
00255 };
00256
00257 }
00258 }
00259
00260 #endif