Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Matrix4.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Matrix4.cpp 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.7 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <base/Matrix4>
00026 
00027 #include <base/Serializer>
00028 
00029 using base::Matrix4;
00030 using base::Vector4;
00031 using base::Matrix3;
00032 
00033 using std::ostream;
00034 
00035 
00036 inline static void exchange(Real& a, Real& b)
00037 {
00038   Real t(a);
00039   a = b;
00040   b = t;
00041 }
00042 
00043 // row, col element exchange
00044 inline static void rcswap4(Real m[], Int r, Int c) 
00045 {
00046         Real* rcp = &m[MATRIX4_ACCESS(r,c)];
00047         Real* crp = &m[MATRIX4_ACCESS(c,r)];
00048         exchange(*rcp, *crp);
00049 }
00050 
00051 
00052 void Matrix4::setToTranslation(const Vector3& trans)
00053 {
00054   setDiag(Real(1));
00055   e(1,4) = trans.x;
00056   e(2,4) = trans.y;
00057   e(3,4) = trans.z;
00058 }
00059 
00060 void Matrix4::setTranslationComponent(const Vector3& trans)
00061 {
00062   e(1,4) = trans.x;
00063   e(2,4) = trans.y;
00064   e(3,4) = trans.z;
00065 }
00066 
00067 void Matrix4::setRotationAboutZ(Real angle)
00068 {
00069   Real cosa = cos(angle);
00070   Real sina = sin(angle);
00071   setDiag(Real(1));
00072   e(1,1)=cosa; e(1,2)=-sina;
00073   e(2,1)=sina; e(2,2)=cosa;
00074 }
00075 
00076 
00077 Matrix4& Matrix4::transpose()
00078 {
00079   rcswap4(m,1,2); rcswap4(m,1,3); rcswap4(m,1,4);
00080   rcswap4(m,2,3); rcswap4(m,2,4);
00081   rcswap4(m,3,4);
00082 
00083   return *this;
00084 }
00085 
00086 
00087 Matrix4& Matrix4::invert()
00088 {
00089   // Solve AX = I by solving 4 eqns: Ax = e (for each e a col of I)
00090   Matrix4 I; // identity
00091   Matrix4 X, A(*this);
00092   Vector4 x;
00093   
00094   Matrix4 L,U;
00095   Vector4 Pi;
00096   
00097   A.decomposeLUP(L,U,Pi);
00098   
00099   for(int c=1; c<=4; c++) {
00100     x = solveLUP(L,U,Pi,I.column(c));
00101     for(int r=1; r<=4; r++) X.e(r,c) = x[r];
00102   }
00103   
00104   return (*this = X);
00105 
00106 }
00107 
00108 
00109 void Matrix4::decomposeLUP(Matrix4& L, Matrix4& U, Vector4& Pi) const
00110 {
00111   Real p,a;
00112   int kp,i,j,k;
00113   Matrix4 AA(*this);
00114 
00115   for(i=1; i<=4; i++) Pi[i] = i;
00116   for(k=1; k<=4-1; k++) {
00117     p = Real(0); kp = 1;
00118     for(i=k; i<=4; i++) {
00119       a = Real(base::abs(AA.e(i,k)));
00120       if ( a > p ) {
00121         p = a;
00122         kp = i;
00123       }
00124     }
00125     if (p == Real(0))  
00126       throw std::invalid_argument(Exception("matrix is singular"));
00127     
00128     exchange(Pi[k],Pi[kp]);
00129     for(i=1; i<=4;i++) exchange(AA.e(k,i),AA.e(kp,i));
00130     
00131     for(i=k+1; i<=4;i++) {
00132       AA.e(i,k) /= AA.e(k,k);
00133       for(j=k+1; j<=4; j++)
00134         AA.e(i,j) -= AA.e(i,k)*AA.e(k,j);
00135     }
00136   }
00137   
00138   for(i=1;i<=4;i++) {
00139     for(j=1;j<=4;j++)
00140       if (i>j) {
00141         L.e(i,j) = AA.e(i,j); U.e(i,j) = Real(0);
00142       }
00143       else {
00144         U.e(i,j) = AA.e(i,j); L.e(i,j) = Real(0);
00145       }
00146     L.e(i,i) = Real(1);
00147     
00148   }
00149 
00150 }
00151 
00152 
00153 Vector4 Matrix4::solve(const Vector4& b) const
00154 {
00155   Matrix4 L,U;
00156   Vector4 Pi;
00157 
00158   decomposeLUP(L,U,Pi);
00159   return solveLUP(L,U,Pi,b);
00160 }
00161 
00162 
00163 Matrix4& Matrix4::negate() throw()
00164 {
00165   for(int i=0; i<16; i++)
00166     m[i]=-m[i];
00167   return *this;
00168 }
00169 
00170 
00171 // Operators
00172 
00173 // multiplication
00174 Matrix4& Matrix4::operator*=(const Matrix4& m2)
00175 {
00176   // !!! optimize (unroll loops)
00177   Matrix4 tmp;
00178 
00179   for(int row=1; row<=4; row++)
00180     for(int col=1; col<=4; col++)
00181       tmp.e(row,col) =  (e(row,1) * m2.e(1,col)) + (e(row,2) * m2.e(2,col))
00182                       + (e(row,3) * m2.e(3,col)) + (e(row,4) * m2.e(4,col));
00183  
00184   return (*this = tmp);
00185 }
00186 
00187 // addition
00188 Matrix4& Matrix4::operator+=(const Matrix4& m2)
00189 {
00190   for(int i=0; i<16; i++)
00191     m[i] += m2.m[i];
00192   return (*this);
00193 }
00194 
00195 // subtration
00196 Matrix4& Matrix4::operator-=(const Matrix4& m2)
00197 {
00198   for(int i=0; i<16; i++)
00199     m[i] -= m2.m[i];
00200   return (*this);
00201 }
00202 
00203 // Scalar multiplication
00204 Matrix4& Matrix4::operator*=(const Real& s)
00205 {
00206   for(int i=0; i<16; i++)
00207     m[i] *= s;
00208   return *this;
00209 }
00210 
00211 // Scalar division
00212 Matrix4& Matrix4::operator/=(const Real& s)
00213 {
00214   for(int i=0; i<16; i++)
00215     m[i] /= s;
00216   return *this;
00217 }
00218 
00219 
00220 Matrix4::operator Matrix3() const
00221 {
00222   Matrix3 r;
00223   r.e(1,1) = e(1,1); r.e(1,2)=e(1,2); r.e(1,3)=e(1,3);
00224   r.e(2,1) = e(2,1); r.e(2,2)=e(2,2); r.e(2,3)=e(2,3);
00225   r.e(3,1) = e(3,1); r.e(3,2)=e(3,2); r.e(3,3)=e(3,3);
00226   return r;
00227 }
00228 
00229 
00230 #ifdef USE_OSG
00231 Matrix4::operator osg::Matrix() const
00232 {
00233 #ifdef OSG_USE_DOUBLE_MATRICES
00234     typedef double osgreal;
00235 #else
00236     typedef float osgreal;
00237 #endif
00238   // NB: This relies on the two types having the same
00239   osg::Matrix mat;
00240   osgreal* _mat = mat.ptr();
00241   for(Int e=0; e<16; e++)
00242     _mat[e] = m[e];
00243   return mat;
00244 }
00245 #endif
00246 
00247 
00248 Vector4 Matrix4::matrixMulVector(const Matrix4& m, const Vector4& v) 
00249 { return Vector4(m.m[0]*v.x+m.m[4]*v.y+m.m[8]*v.z+m.m[12]*v.w,
00250                  m.m[1]*v.x+m.m[5]*v.y+m.m[9]*v.z+m.m[13]*v.w,
00251                  m.m[2]*v.x+m.m[6]*v.y+m.m[10]*v.z+m.m[14]*v.w,
00252                  m.m[3]*v.x+m.m[7]*v.y+m.m[11]*v.z+m.m[15]*v.w);
00253 }
00254 
00255 /* above is equivelent to: (which is slower but easier to read)
00256 Vector4 Matrix4::matrixMulVector(const Matrix4& m, const Vector4& v) 
00257 { return Vector4(m.e(1,1)*v.x+m.e(1,2)*v.y+m.e(1,3)*v.z+m.e(1,4)*v.w,
00258                  m.e(2,1)*v.x+m.e(2,2)*v.y+m.e(2,3)*v.z+m.e(2,4)*v.w,
00259                  m.e(3,1)*v.x+m.e(3,2)*v.y+m.e(3,3)*v.z+m.e(3,4)*v.w,
00260                  m.e(4,1)*v.x+m.e(4,2)*v.y+m.e(4,3)*v.z+m.e(4,4)*v.w);
00261 }
00262 */
00263 
00264 Vector4 Matrix4::matrixMulVector(const Matrix4& m, const Vector3& v) 
00265 { return Vector4(m.m[0]*v.x+m.m[4]*v.y+m.m[8]*v.z+m.m[12],
00266                  m.m[1]*v.x+m.m[5]*v.y+m.m[9]*v.z+m.m[13],
00267                  m.m[2]*v.x+m.m[6]*v.y+m.m[10]*v.z+m.m[14],
00268                  m.m[3]*v.x+m.m[7]*v.y+m.m[11]*v.z+m.m[15]);
00269 }
00270 
00271 Vector4 Matrix4::matrixMulVectorAddVector(const Matrix4& m, const Vector4& v, const Vector4& v2) 
00272 { return Vector4(m.m[0]*v.x+m.m[4]*v.y+m.m[8]*v.z+m.m[12]*v.w+v2.x,
00273                  m.m[1]*v.x+m.m[5]*v.y+m.m[9]*v.z+m.m[13]*v.w+v2.y,
00274                  m.m[2]*v.x+m.m[6]*v.y+m.m[10]*v.z+m.m[14]*v.w+v2.z,
00275                  m.m[3]*v.x+m.m[7]*v.y+m.m[11]*v.z+m.m[15]*v.w+v2.w);
00276 }
00277 
00278 
00279 // Solve for Ax = b, given LUP decomposition of A as L, U and Pi, and given b, returns x
00280 Vector4 Matrix4::solveLUP(const Matrix4& L, const Matrix4& U, const Vector4& Pi, const Vector4& b)
00281 {
00282   int i,j;
00283   Vector4 y, x;
00284   Real s;
00285   // forward subst.
00286   for(i=1;i<=4;i++) {
00287     s = Real(0);
00288     for(j=1;j<=i-1;j++) s += L.e(i,j)*y[j];
00289     y[i] = b[int(Pi[i])] - s;
00290   }
00291   // backward subst.
00292   for(i=4;i>=1;i--) {
00293     s = Real(0);
00294     for(j=i+1;j<=4;j++) s += U.e(i,j)*x[j];
00295     x[i] = (y[i] - s)/(U.e(i,i));
00296   }
00297   return x;
00298 }
00299 
00300 
00301 void Matrix4::serialize(Serializer& s)
00302 {
00303   for(Int i=0; i<15; i++) 
00304     s(m[i]);
00305 }
00306 
00307 
00308 // output
00309 ostream& base::operator<<(ostream& out, const Matrix4& m)
00310 {
00311   return out << m.e(1,1) << " " << m.e(1,2) << " " << m.e(1,3) << " " << m.e(1,4) << std::endl
00312              << m.e(2,1) << " " << m.e(2,2) << " " << m.e(2,3) << " " << m.e(2,4) << std::endl
00313              << m.e(3,1) << " " << m.e(3,2) << " " << m.e(3,3) << " " << m.e(3,4) << std::endl
00314              << m.e(4,1) << " " << m.e(4,2) << " " << m.e(4,3) << " " << m.e(4,4) << std::endl;
00315 }
00316 
00317 
00318 
00319 
00320 
00321 
00322 

Generated on Thu Jul 29 15:56:07 2004 for OpenSim by doxygen 1.3.6