00001 #ifndef OPENTISSUE_DYNAMICS_PSYS_FORCE_PSYS_SPRING_H 00002 #define OPENTISSUE_DYNAMICS_PSYS_FORCE_PSYS_SPRING_H 00003 // 00004 // OpenTissue Template Library 00005 // - A generic toolbox for physics-based modeling and simulation. 00006 // Copyright (C) 2008 Department of Computer Science, University of Copenhagen. 00007 // 00008 // OTTL is licensed under zlib: http://opensource.org/licenses/zlib-license.php 00009 // 00010 #include <OpenTissue/configuration.h> 00011 00012 namespace OpenTissue 00013 { 00014 namespace psys 00015 { 00016 00017 template<typename types> 00018 class Spring 00019 : public types::force_type 00020 { 00021 public: 00022 00023 typedef typename types::math_types math_types; 00024 typedef typename math_types::real_type real_type; 00025 typedef typename math_types::vector3_type vector3_type; 00026 typedef typename types::particle_type particle_type; 00027 typedef typename types::system_type system_type; 00028 00029 protected: 00030 00031 particle_type * m_A; 00032 particle_type * m_B; 00033 real_type m_length; 00034 real_type m_length_sqr; 00035 real_type m_k; 00036 real_type m_c; 00037 00038 00039 public: 00040 00041 particle_type * A() { return m_A; } 00042 particle_type * B() { return m_B; } 00043 particle_type const * A() const { return m_A; } 00044 particle_type const * B() const { return m_B; } 00045 00046 real_type & damping() { return m_c; } 00047 real_type const & damping() const { return m_c; } 00048 real_type & stiffness() { return m_k; } 00049 real_type const & stiffness() const { return m_k; } 00050 real_type const & rest_length() const { return m_length; } 00051 00052 public: 00053 00054 Spring() 00055 : m_A(0) 00056 , m_B(0) 00057 , m_length(0) 00058 , m_length_sqr(0) 00059 , m_k(0) 00060 , m_c(0) 00061 { 00062 set_critical_damped(0.01); 00063 } 00064 00065 virtual ~Spring() { } 00066 00067 public: 00068 00075 void init(particle_type * A, particle_type * B) 00076 { 00077 assert(A!=B || !"Spring::set(): Particle A and B were the same"); 00078 assert(A || !"Spring::set(): Particle A was null"); 00079 assert(B || !"Spring::set(): Particle B was null"); 00080 00081 this->m_A = A; 00082 this->m_B = B; 00083 00084 set_rest_length( length(B->position()-A->position())); 00085 set_critical_damped(0.01); 00086 } 00087 00093 void set_rest_length(real_type l) 00094 { 00095 assert(l>=0 || !"Spring::set_length(): Spring rest length was negative"); 00096 this->m_length = l; 00097 this->m_length_sqr = l*l; 00098 } 00099 00104 void set_critical_damped( real_type const & tau) 00105 { 00106 if(tau>0) 00107 { 00108 m_c = 2./tau; 00109 m_k = 1./(tau*tau); 00110 } 00111 } 00112 00113 public: 00114 00115 void apply() 00116 { 00117 using std::fabs; 00118 00119 //--- F_A = - (k (l-l0) + c (v_a-v_b).((r_A-r_B)/ |(r_A-r_B)|) ) (r_A-r_B) / |(r_A-r_B)| 00120 //--- F_B = - F_A 00121 vector3_type dr = m_A->position() - m_B->position(); 00122 vector3_type dv = m_A->velocity() - m_B->velocity(); 00123 real_type l = length(dr); 00124 real_type l0 = rest_length(); 00125 if(fabs(l)>0) 00126 { 00127 dr = dr/l; 00128 vector3_type F_a = -(m_k*(l-l0) + m_c*(dv * dr)) * dr; 00129 m_A->force() += F_a; 00130 m_B->force() -= F_a; 00131 } 00132 } 00133 00134 }; 00135 00136 } // namespace psys 00137 } // namespace OpenTissue 00138 00139 // OPENTISSUE_DYNAMICS_PSYS_FORCE_PSYS_SPRING_H 00140 #endif