Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_PSYS_MASS_SPRING_SYSTEM_PSYS_MASS_SPRING_SYSTEM_H
00002 #define OPENTISSUE_DYNAMICS_PSYS_MASS_SPRING_SYSTEM_PSYS_MASS_SPRING_SYSTEM_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <boost/iterator/indirect_iterator.hpp>
00013 #include <boost/bind.hpp>
00014
00015 #include <list>
00016
00017 namespace OpenTissue
00018 {
00019
00020 namespace psys
00021 {
00022
00023 template<
00024 typename types
00025 , typename integrator_policy
00026 >
00027 class MassSpringSystem : public System<types>, public integrator_policy
00028 {
00029 public:
00030
00031 typedef typename types::system_type system_type;
00032 typedef typename system_type::particle_iterator particle_iterator;
00033 typedef typename system_type::const_particle_iterator const_particle_iterator;
00034
00035 typedef typename types::math_types math_types;
00036 typedef typename math_types::real_type real_type;
00037 typedef typename math_types::vector3_type vector3_type;
00038 typedef typename types::particle_type particle_type;
00039 typedef typename types::constraint_type constraint_type;
00040 typedef typename types::force_type force_type;
00041 typedef typename types::geometry_holder_type geometry_holder_type;
00042 typedef typename types::contact_point_type contact_point_type;
00043
00044 protected:
00045
00046 unsigned int m_iterations;
00047 bool m_relaxation;
00048 bool m_projection;
00049
00050 public:
00051
00052 bool & relaxation() { return m_relaxation; }
00053 bool const & relaxation() const { return m_relaxation; }
00054 bool & projection() { return m_projection; }
00055 bool const & projection() const { return m_projection; }
00056 unsigned int & iterations() { return m_iterations; }
00057 unsigned int const & iterations() const { return m_iterations; }
00058
00059 protected:
00060
00061 typedef std::list<force_type *> force_ptr_container;
00062 typedef std::list<geometry_holder_type> geometry_container;
00063 typedef std::list<constraint_type *> constraint_ptr_container;
00064
00065 public:
00066
00067 typedef boost::indirect_iterator< typename force_ptr_container::iterator, force_type> force_iterator;
00068 typedef boost::indirect_iterator< typename constraint_ptr_container::iterator, constraint_type> constraint_iterator;
00069
00070 typedef typename geometry_container::iterator geometry_iterator;
00071
00072 protected:
00073
00074 force_ptr_container m_forces;
00075 constraint_ptr_container m_constraints;
00076 geometry_container m_geometries;
00077
00078 public:
00079
00080 force_iterator force_begin() { return force_iterator(m_forces.begin()); }
00081 force_iterator force_end() { return force_iterator(m_forces.end()); }
00082 constraint_iterator constraint_begin() { return constraint_iterator(m_constraints.begin());}
00083 constraint_iterator constraint_end() { return constraint_iterator(m_constraints.end()); }
00084 geometry_iterator geometry_begin() { return geometry_iterator(m_geometries.begin()); }
00085 geometry_iterator geometry_end() { return geometry_iterator(m_geometries.end()); }
00086
00087 void clear(void)
00088 {
00089 m_forces.clear();
00090 m_constraints.clear();
00091 m_geometries.clear();
00092 system_type::clear();
00093 };
00094
00095 void add_force(force_type * F) { F->connect(*this); m_forces.push_back(F); }
00096 void remove_force(force_type * F) { m_forces.remove(F); F->disconnect(); }
00097
00098 void add_constraint(constraint_type * C) { C->connect(*this); m_constraints.push_back(C); }
00099 void remove_constraint(constraint_type * C) { m_constraints.remove(C); C->disconnect(); }
00100
00101 template<typename geometry_type>
00102 void add_geometry(geometry_type * G)
00103 {
00104 geometry_holder_type holder;
00105 holder.set(G);
00106 holder.connect(*this);
00107 m_geometries.push_back(holder);
00108 }
00109
00110 template<typename geometry_type>
00111 void remove_geometry(geometry_type * G)
00112 {
00113 geometry_holder_type holder;
00114 holder.set(G);
00115 m_geometries.remove(holder);
00116 }
00117
00118 public:
00119
00120 MassSpringSystem(void)
00121 : m_iterations(10)
00122 , m_relaxation(true)
00123 , m_projection(true)
00124 {}
00125
00126 ~MassSpringSystem(){ clear(); }
00127
00128 public:
00129
00130 void run(real_type timestep)
00131 {
00132 assert(timestep>0 || !"MassSpringSystem::run(): Non-positive time-step");
00133 integrate ( *this, timestep );
00134 do_relaxation();
00135 this->time() += timestep;
00136 }
00137
00138 protected:
00139
00140 void do_relaxation()
00141 {
00142 if(!m_relaxation)
00143 return;
00144
00145 for(unsigned int i=0;i<m_iterations;++i)
00146 {
00147 constraint_iterator c = constraint_begin();
00148 constraint_iterator end = constraint_end();
00149 for(;c!=end;++c)
00150 c->satisfy();
00151
00152 do_projection();
00153 }
00154 }
00155
00156 void do_projection()
00157 {
00158 typedef std::list<contact_point_type> contact_point_container;
00159
00160 if(!m_projection)
00161 return;
00162
00163 contact_point_container contacts;
00164
00165
00166 {
00167 geometry_iterator g = geometry_begin();
00168 geometry_iterator end = geometry_end();
00169 for(;g!=end;++g)
00170 g->dispatch( *this, contacts );
00171
00172
00173
00177
00178 }
00179
00180 {
00181 typename std::list<contact_point_type>::iterator cp = contacts.begin();
00182 typename std::list<contact_point_type>::iterator end = contacts.end();
00183 for(;cp!=end;++cp)
00184 {
00185 if(cp->m_A0 && !cp->m_A1 && !cp->m_A2 && !cp->m_B0 && !cp->m_B1 && !cp->m_B2)
00186 {
00187 cp->m_A0->position() += cp->m_n*cp->m_distance;
00188 }
00189
00190
00191 if(cp->m_A0 && cp->m_A1 && !cp->m_A2 && cp->m_B0 && cp->m_B1 && cp->m_B2)
00192 {
00193
00194 cp->m_A0->position() = cp->m_A0->old_position();
00195 cp->m_A1->position() = cp->m_A1->old_position();
00196
00197 cp->m_A0->velocity().clear();
00198 cp->m_A1->velocity().clear();
00199
00200 cp->m_B0->position() = cp->m_B0->old_position();
00201 cp->m_B1->position() = cp->m_B1->old_position();
00202 cp->m_B2->position() = cp->m_B2->old_position();
00203
00204 cp->m_B0->velocity().clear();
00205 cp->m_B1->velocity().clear();
00206 cp->m_B2->velocity().clear();
00207
00208 }
00209
00210 }
00211 }
00212 }
00213
00214 public:
00215
00216 void compute_accelerations()
00217 {
00218 particle_iterator p = this->particle_begin();
00219 particle_iterator end = this->particle_end();
00220 for(;p!=end;++p)
00221 p->acceleration() = p->force() * p->inv_mass();
00222 }
00223
00224 void compute_forces()
00225 {
00226 particle_iterator p = this->particle_begin();
00227 particle_iterator end = this->particle_end();
00228 for(;p!=end;++p)
00229 p->force().clear();
00230
00231 std::for_each( force_begin(), force_end(), boost::bind( &force_type::apply, _1 ));
00232 }
00233
00234 };
00235
00236 }
00237 }
00238
00239
00240 #endif