Biomechanical Joint Model
 Author: Anderson Maciel

quat.cpp

Go to the documentation of this file.
00001 #include "quat.h"
00002 
00003 namespace LinAlg{
00004 
00005 
00006 
00007 QUAT::QUAT(const HMAT &M) : VEC(4)
00008 {
00009    REAL ww, xx, yy, four_w, two_x;   
00010    ww = 0.25 * (1.0 + M(0,0) + M(1,1) + M(2,2));
00011   
00012    if (ww > epsilon) 
00013    {
00014       v_[QUAT_W] = sqrt(ww);
00015       four_w  = 4.0 * v_[QUAT_W];
00016       v_[QUAT_X] = (M(2,1) - M(1,2)) / four_w;
00017       v_[QUAT_Y] = (M(0,2) - M(2,0)) / four_w;
00018       v_[QUAT_Z] = (M(1,0) - M(0,1)) / four_w;
00019    } 
00020    else 
00021    {
00022       v_[QUAT_W] = 0.0;
00023       xx = -0.5 * (M(1,1) + M(2,2));
00024      
00025       if (xx > epsilon) 
00026       {
00027          v_[QUAT_X] = sqrt(xx);
00028          two_x = v_[QUAT_X] * 2.0;
00029          v_[QUAT_Y] = M(1,0) / two_x;
00030          v_[QUAT_Z] = M(2,0) / two_x;
00031       } 
00032       else 
00033       {
00034          v_[QUAT_X] = 0.0;
00035          yy = 0.5 * (1.0 - M(2,2));
00036         
00037          if (yy > epsilon) 
00038          {
00039             v_[QUAT_Y] = sqrt(yy);
00040             v_[QUAT_Z] = M(2,1) / (2.0 * v_[QUAT_Y]);
00041          } 
00042          else 
00043          {
00044             v_[QUAT_Y] = 0.0;
00045             v_[QUAT_Z] = 1.0;
00046          }
00047       }
00048    }
00049 }
00050 
00051 QUAT::operator HMAT() const
00052 {
00053    REAL xx, yy, zz, xy, xz, yz, wx, wy, wz;
00054    HMAT result;
00055 
00056    REAL qnorm2 = norm2();
00057   
00058    xx = 2.0 * v_[QUAT_X] * v_[QUAT_X] / qnorm2;
00059    yy = 2.0 * v_[QUAT_Y] * v_[QUAT_Y] / qnorm2;
00060    zz = 2.0 * v_[QUAT_Z] * v_[QUAT_Z] / qnorm2;
00061    xy = 2.0 * v_[QUAT_X] * v_[QUAT_Y] / qnorm2;
00062    xz = 2.0 * v_[QUAT_X] * v_[QUAT_Z] / qnorm2;
00063    yz = 2.0 * v_[QUAT_Y] * v_[QUAT_Z] / qnorm2;
00064    wx = 2.0 * v_[QUAT_W] * v_[QUAT_X] / qnorm2;
00065    wy = 2.0 * v_[QUAT_W] * v_[QUAT_Y] / qnorm2;
00066    wz = 2.0 * v_[QUAT_W] * v_[QUAT_Z] / qnorm2;
00067   
00068    result(0,0)= 1.0-yy-zz; 
00069    result(1,0)= xy+wz;     
00070    result(2,0)= xz-wy;     
00071    result(0,1)= xy-wz;     
00072    result(1,1)= 1.0-xx-zz; 
00073    result(2,1)= yz+wx;     
00074    result(0,2)= xz+wy;     
00075    result(1,2)= yz-wx;     
00076    result(2,2)= 1.0-xx-yy; 
00077 
00078    return result;
00079 }
00080 
00081 QUAT 
00082 operator*(const QUAT &left, const QUAT &right)
00083 {
00084    QUAT result;
00085 
00086    result[QUAT_W] = 
00087       left[QUAT_W]*right[QUAT_W] - 
00088       left[QUAT_X]*right[QUAT_X] - 
00089       left[QUAT_Y]*right[QUAT_Y] - 
00090       left[QUAT_Z]*right[QUAT_Z];
00091 
00092    result[QUAT_X] = 
00093       left[QUAT_W]*right[QUAT_X] + 
00094       left[QUAT_X]*right[QUAT_W] + 
00095       left[QUAT_Y]*right[QUAT_Z] - 
00096       left[QUAT_Z]*right[QUAT_Y];
00097 
00098    result[QUAT_Y] = 
00099       left[QUAT_W]*right[QUAT_Y] + 
00100       left[QUAT_Y]*right[QUAT_W] + 
00101       left[QUAT_Z]*right[QUAT_X] - 
00102       left[QUAT_X]*right[QUAT_Z];
00103 
00104    result[QUAT_Z] = 
00105       left[QUAT_W]*right[QUAT_Z] + 
00106       left[QUAT_Z]*right[QUAT_W] + 
00107       left[QUAT_X]*right[QUAT_Y] - 
00108       left[QUAT_Y]*right[QUAT_X];
00109 
00110    return result;
00111 }
00112 
00113 void 
00114 QUAT::slerp(const QUAT &left, const QUAT &right, REAL u, QUAT &result)
00115 {
00116    QUAT Q2;
00117    REAL cs, sx, theta, scale0, scale1;
00118 
00119    cs = dot_prod(left, right);
00120    /* if quaternions are opposed, negate the second one */
00121    /* this ensures the shortest path is taken */
00122    if (cs < 0)
00123    {
00124       cs = -cs;
00125       Q2.set(-right);      
00126    }
00127    else Q2 = right;
00128 
00129    // calculate coefficients
00130    if (1.0-cs > epsilon) 
00131    {
00132       theta = acos(cs);
00133       sx = sin(theta);
00134       scale0 = sin((1.0-u) * theta) / sx;
00135       scale1 = sin(u * theta) / sx;
00136    }
00137    else
00138    {
00139       scale0 = 1.0 - u;
00140       scale1 = u;
00141    }
00142    
00143    result.set( scale0*left + scale1*Q2);
00144 }
00145 
00146 
00147 
00148 }

Generated on Thu Dec 1 10:13:39 2005 for COME - Biomechanical Joint Model by  doxygen 1.4.5