Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_COMPUTE_POSITION_UPDATE_H
00002 #define OPENTISSUE_DYNAMICS_MBD_UTIL_MBD_COMPUTE_POSITION_UPDATE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_is_number.h>
00013 #include <OpenTissue/core/math/math_functions.h>
00014
00015 namespace OpenTissue
00016 {
00017 namespace mbd
00018 {
00042 template<typename indirect_body_iterator,typename vector_type,typename real_type>
00043 void compute_position_update(
00044 indirect_body_iterator begin
00045 , indirect_body_iterator end
00046 , vector_type const & s
00047 , vector_type const & u
00048 , real_type const & h
00049 , vector_type & snew
00050 )
00051 {
00052 typedef typename indirect_body_iterator::value_type body_type;
00053 typedef typename body_type::math_policy math_policy;
00054 typedef typename body_type::value_traits value_traits;
00055 typedef typename body_type::vector3_type vector3_type;
00056 typedef typename body_type::quaternion_type quaternion_type;
00057 typedef typename vector_type::size_type size_type;
00058
00059 using std::cos;
00060
00061 vector3_type W;
00062 vector3_type r_axis;
00063 vector3_type W_finite;
00064 vector3_type W_infinite;
00065
00066 quaternion_type Q;
00067 quaternion_type Qtmp;
00068 quaternion_type Qdot;
00069
00070 size_type n = std::distance(begin,end);
00071
00072 if(s.size()!=7*n)
00073 throw std::logic_error("compute_position_update(): s has incorrect dimension");
00074 if(u.size()!=6*n)
00075 throw std::logic_error("compute_position_update(): u has incorrect dimension");
00076
00077 if(&s != &snew)
00078 math_policy::resize( snew, 7*n );
00079
00080 typename vector_type::const_iterator sval = s.begin();
00081 typename vector_type::const_iterator uval = u.begin();
00082 typename vector_type::iterator snewval = snew.begin();
00083
00084 real_type h_half = h / value_traits::two();
00085
00086 for(indirect_body_iterator body = begin;body!=end;++body)
00087 {
00088 if(body->is_active())
00089 {
00090 assert(is_number(*uval) || !"compute_position_update(): non number encountered");
00091 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00092 *snewval++ = *sval++ + (h * (*uval++));
00093 assert(is_number(*uval) || !"compute_position_update(): non number encountered");
00094 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00095 *snewval++ = *sval++ + (h * (*uval++));
00096 assert(is_number(*uval) || !"compute_position_update(): non number encountered");
00097 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00098 *snewval++ = *sval++ + (h * (*uval++));
00099 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00100 Q.s() = *sval++;
00101 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00102 Q.v()(0) = *sval++;
00103 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00104 Q.v()(1) = *sval++;
00105 assert(is_number(*sval) || !"compute_position_update(): non number encountered");
00106 Q.v()(2) = *sval++;
00107 assert(is_number(*uval) || !"compute_position_update(): non number encountered");
00108 W(0) = *uval++;
00109 assert(is_number(*uval) || !"compute_position_update(): non number encountered");
00110 W(1) = *uval++;
00111 assert(is_number(*uval) || !"compute_position_update(): non number encountered");
00112 W(2) = *uval++;
00113 if( body->has_finite_rotation_update())
00114 {
00115 if(body->has_finite_rotation_axis())
00116 {
00117
00118
00119
00120 body->get_finite_rotation_axis(r_axis);
00121 real_type tmp = r_axis * W;
00122 W_finite = r_axis * tmp;
00123 W_infinite = W - W_finite;
00124
00125
00126 real_type theta = tmp*h_half;
00127 real_type tmp2 = OpenTissue::math::sinc(theta)*h_half;
00128 Qtmp.s() = cos(theta);
00129 Qtmp.v() = W_finite;
00130 Qtmp.v() *= tmp2;
00131 Q = Qtmp % Q;
00132
00133
00134 Q += (W_infinite % Q)* h_half;
00135 }
00136 else
00137 {
00138
00139 real_type theta = length(W)*h_half;
00140 real_type tmp2 = OpenTissue::math::sinc(theta)*h_half;
00141 Qtmp.s() = cos(theta);
00142 Qtmp.v() = W*tmp2;
00143 Q = Qtmp%Q;
00144 }
00145 }
00146 else
00147 {
00148
00149 Q += (W % Q)*h_half;
00150 }
00151 Q = normalize(Q);
00152 *snewval++ = Q.s();
00153 *snewval++ = Q.v()(0);
00154 *snewval++ = Q.v()(1);
00155 *snewval++ = Q.v()(2);
00156 }
00157 }
00158 }
00159
00160 template<typename group_type,typename vector_type,typename real_type>
00161 void compute_position_update(
00162 group_type const & group
00163 , vector_type const & s
00164 , vector_type const & u
00165 , real_type const & h
00166 , vector_type & snew
00167 )
00168 {
00169 compute_position_update(group.body_begin(),group.body_end(),s,u,h,snew);
00170 }
00171
00172 }
00173 }
00174
00175 #endif