Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_MATH_EULER_ANGLES_H
00002 #define OPENTISSUE_CORE_MATH_MATH_EULER_ANGLES_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_quaternion.h>
00013
00014 #include <OpenTissue/core/math/math_functions.h>
00015 #include <OpenTissue/core/math/math_is_number.h>
00016
00017 #include <boost/cast.hpp>
00018
00019 #include <cmath>
00020 #include <cassert>
00021
00022
00023 namespace OpenTissue
00024 {
00025
00026 namespace math
00027 {
00028
00043 template<typename matrix3x3_type,typename real_type>
00044 inline bool euler_angles(matrix3x3_type const & R,real_type & rx, real_type & ry, real_type & rz)
00045 {
00046 using std::atan2;
00047 using std::asin;
00048
00049 typedef typename matrix3x3_type::value_type T;
00050 typedef typename matrix3x3_type::value_traits value_traits;
00051
00052 T const & m00 = R(0,0);
00053 T const & m01 = R(0,1);
00054 T const & m02 = R(0,2);
00055 T const & m10 = R(1,0);
00056 T const & m20 = R(2,0);
00057 T const & m21 = R(2,1);
00058 T const & m22 = R(2,2);
00059
00060
00061
00062 if ( m20 < value_traits::one() )
00063 {
00064 if ( m20 > -value_traits::one() )
00065 {
00066 rz = boost::numeric_cast<real_type>( atan2(m10,m00) );
00067 ry = boost::numeric_cast<real_type>( asin(-m20) );
00068 rx = boost::numeric_cast<real_type>( atan2(m21,m22) );
00069 return true;
00070 }
00071
00072
00073 rz = boost::numeric_cast<real_type>( - atan2(m01,m02) );
00074 ry = value_traits::pi_2();
00075 rx = value_traits::zero();
00076 return false;
00077 }
00078
00079
00080 rz = boost::numeric_cast<real_type>( atan2(-m01,-m02) );
00081 ry = value_traits::pi_2();
00082 rx = value_traits::zero();
00083 return false;
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 template<typename T>
00108 inline void ZYZ_euler_angles( OpenTissue::math::Quaternion<T> const & Q, T & phi, T & psi, T & theta )
00109 {
00110 using std::atan2;
00111 using std::cos;
00112
00113 typedef typename OpenTissue::math::Quaternion<T> quaternion_type;
00114 typedef typename quaternion_type::vector3_type vector3_type;
00115 typedef typename quaternion_type::value_traits value_traits;
00116
00117 phi = value_traits::zero();
00118 psi = value_traits::zero();
00119 theta = value_traits::zero();
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 vector3_type const k = vector3_type(value_traits::zero(),value_traits::zero(),value_traits::one());
00135 vector3_type const u = Q.rotate(k);
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 T const u_z = clamp( u(2), -value_traits::one(), value_traits::one());
00165 assert(is_number(u_z) || !"ZYZ_euler_angles(): not an number encountered");
00166 assert(u_z <= value_traits::one() || !"ZYZ_euler_angles(): u_z was too big");
00167 assert(u_z >= -value_traits::one() || !"ZYZ_euler_angles(): u_z was too small");
00168
00169 psi = boost::numeric_cast<T>( acos(u_z) );
00170 assert(is_number(psi) || !"ZYZ_euler_angles(): psi was not an number encountered");
00171 assert(psi <= value_traits::pi() || !"ZYZ_euler_angles(): psi was too big");
00172 assert(psi >= value_traits::zero() || !"ZYZ_euler_angles(): psi was too small");
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 T const too_small = boost::numeric_cast<T>( 0.0001 );
00194 if(psi<too_small)
00195 {
00196
00197
00198
00199 vector3_type const i = vector3_type(value_traits::one(),value_traits::zero(),value_traits::zero());
00200 vector3_type const w = Q.rotate(i);
00201
00202 T const w_x = w(0);
00203 T const w_y = w(1);
00204 assert(is_number(w_x) || !"ZYZ_euler_angles(): w_x was not an number encountered");
00205 assert(is_number(w_y) || !"ZYZ_euler_angles(): w_y not an number encountered");
00206 phi = boost::numeric_cast<T>( atan2(w_y,w_x) );
00207 assert(is_number(phi) || !"ZYZ_euler_angles(): phi was not an number encountered");
00208 assert(phi <= value_traits::pi() || !"ZYZ_euler_angles(): phi was too big");
00209 assert(phi >= -value_traits::pi() || !"ZYZ_euler_angles(): phi was too small");
00210
00211
00212
00213
00214 return;
00215 }
00216 else
00217 {
00218
00219 T const u_x = u(0);
00220 T const u_y = u(1);
00221 assert(is_number(u_x) || !"ZYZ_euler_angles(): u_x was not an number encountered");
00222 assert(is_number(u_y) || !"ZYZ_euler_angles(): u_y not an number encountered");
00223 phi = boost::numeric_cast<T>( atan2(u_y,u_x) );
00224 assert(is_number(phi) || !"ZYZ_euler_angles(): phi was not an number encountered");
00225 assert(phi <= value_traits::pi() || !"ZYZ_euler_angles(): phi was too big");
00226 assert(phi >= -value_traits::pi() || !"ZYZ_euler_angles(): phi was too small");
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 quaternion_type Qy;
00259 quaternion_type Qz;
00260 quaternion_type H;
00261 Qy.Ry(psi);
00262 Qz.Rz(phi);
00263 H = prod( conj( prod( Qz , Qy ) ), Q );
00264
00265 vector3_type const i = vector3_type(value_traits::one(),value_traits::zero(),value_traits::zero());
00266 vector3_type const w = H.rotate(i);
00267
00268 T const w_x = w(0);
00269 T const w_y = w(1);
00270 assert(is_number(w_x) || !"ZYZ_euler_angles(): w_x was not an number encountered");
00271 assert(is_number(w_y) || !"ZYZ_euler_angles(): w_y not an number encountered");
00272 theta = boost::numeric_cast<T>( atan2(w_y,w_x) );
00273 assert(is_number(theta) || !"ZYZ_euler_angles(): phi was not an number encountered");
00274 assert(theta <= value_traits::pi() || !"ZYZ_euler_angles(): phi was too big");
00275 assert(theta >= -value_traits::pi() || !"ZYZ_euler_angles(): phi was too small");
00276
00277
00278
00279
00280
00281
00283
00284
00285
00286 return;
00287 }
00288
00289 }
00290
00291 }
00292
00293
00294 #endif