Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_COLLISION_RESOLVERS_MBD_SEQUENTIAL_COLLISION_RESOLVER_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_COLLISION_RESOLVERS_MBD_SEQUENTIAL_COLLISION_RESOLVER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/mbd/interfaces/mbd_collision_resolver_interface.h>
00013 #include <OpenTissue/dynamics/mbd/mbd_apply_impulse.h>
00014 #include <OpenTissue/dynamics/mbd/mbd_compute_relative_contact_velocity.h>
00015 #include <OpenTissue/core/math/math_precision.h>
00016
00017 namespace OpenTissue
00018 {
00019 namespace mbd
00020 {
00037 template< typename mbd_types, typename collision_law_policy >
00038 class SequentialCollisionResolver
00039 : public CollisionResolverInterface<mbd_types>
00040 , public collision_law_policy
00041 {
00042 protected:
00043
00044 typedef typename mbd_types::math_policy::real_type real_type;
00045 typedef typename mbd_types::math_policy::vector3_type vector3_type;
00046 typedef typename mbd_types::group_type group_type;
00047 typedef typename mbd_types::body_type body_type;
00048 typedef typename mbd_types::edge_type edge_type;
00049
00050 typedef typename mbd_types::contact_type contact_type;
00051 typedef typename mbd_types::material_type material_type;
00052 typedef typename std::vector<contact_type*> contact_ptr_heap;
00053
00054 public:
00055
00056 class node_traits{};
00057 class edge_traits{};
00058 class constraint_traits{ };
00059
00060 protected:
00061
00069 struct ContactPointComparision
00070 {
00071 bool operator()(contact_type const * x, contact_type const * y) const
00072 {
00073 if(x->m_un < y->m_un)
00074 return true;
00075 return false;
00076 }
00077 };
00078
00079 public:
00080
00081 SequentialCollisionResolver() {}
00082 virtual ~SequentialCollisionResolver() {}
00083
00084 public:
00085
00086 void resolve_collisions(group_type & group)
00087 {
00088 if(group.size_contacts()==0)
00089 {
00090 return;
00091 }
00092 typename group_type::indirect_contact_iterator cbegin = group.contact_begin();
00093 typename group_type::indirect_contact_iterator cend = group.contact_end();
00094 contact_ptr_heap S;
00095 init_heap(cbegin,cend,S);
00096 vector3_type J_a,J_b;
00097 while(true)
00098 {
00099 contact_type * cp = minimum(S);
00100
00101 real_type epsilon = OpenTissue::math::working_precision<real_type>();
00102 if(cp->m_un >= -epsilon)
00103 return;
00104 J_b = compute_impulse(cp);
00105 J_a = - J_b;
00106 mbd::apply_impulse(cp->get_body_A(),cp->m_rA,J_a);
00107 mbd::apply_impulse(cp->get_body_B(),cp->m_rB,J_b);
00108 update_all_dependent_contacts(cp);
00109 update_heap(S);
00110 }
00111 }
00112
00113 protected:
00114
00122 template<typename iterator>
00123 void init_heap(iterator const & cbegin,iterator const & cend,contact_ptr_heap & S)
00124 {
00125 for(iterator contact=cbegin;contact!=cend;++contact)
00126 {
00127 update(&(*contact));
00128 S.push_back(&(*contact));
00129 }
00130 update_heap(S);
00131 }
00132
00138 void update_heap(contact_ptr_heap & S)
00139 {
00140
00141
00142
00143
00144 make_heap(S.begin(),S.end(),ContactPointComparision());
00145 sort_heap(S.begin(),S.end(),ContactPointComparision());
00146 }
00147
00155 contact_type * minimum(contact_ptr_heap & S)
00156 {
00157 return S.front();
00158 }
00159
00168 void update_all_dependent_contacts(contact_type * cp)
00169 {
00170 body_type * A = cp->get_body_A();
00171 body_type * B = cp->get_body_B();
00172 typename body_type::indirect_edge_iterator ebegin,eend,edge;
00173 typename edge_type::contact_iterator cbegin,cend,contact;
00174 ebegin = A->edge_begin();
00175 eend = A->edge_end();
00176 for(edge=ebegin;edge!=eend;++edge)
00177 {
00178 if(!edge->is_up_to_date())
00179 continue;
00180 cbegin = edge->contact_begin();
00181 cend = edge->contact_end();
00182 for(contact=cbegin;contact!=cend;++contact)
00183 {
00184 update(&(*contact));
00185 }
00186 }
00187 ebegin = B->edge_begin();
00188 eend = B->edge_end();
00189 for(edge=ebegin;edge!=eend;++edge)
00190 {
00191 if(!edge->is_up_to_date())
00192 continue;
00193 if(edge->get_body_A()==A)
00194 continue;
00195 cbegin = edge->contact_begin();
00196 cend = edge->contact_end();
00197 for(contact=cbegin;contact!=cend;++contact)
00198 {
00199 update(&(*contact));
00200 }
00201 }
00202 }
00203
00211 void update(contact_type * cp)
00212 {
00213 assert(cp);
00214 body_type * A = cp->get_body_A();
00215 body_type * B = cp->get_body_B();
00216 assert(A);
00217 assert(B);
00218 vector3_type v_a,v_b,w_a,w_b;
00219 A->get_velocity(v_a);
00220 A->get_spin(w_a);
00221 B->get_velocity(v_b);
00222 B->get_spin(w_b);
00223 vector3_type u = mbd::compute_relative_contact_velocity(v_a,w_a,cp->m_rA,v_b,w_b,cp->m_rB);
00224
00225
00226 cp->m_un = cp->m_n*u;
00227 }
00228
00229 };
00230
00231 }
00232 }
00233
00234 #endif