Matrix.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Imetric 3D GmbH                                    *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00024 #include "PreCompiled.h"
00025 #ifndef _PreComp_
00026 # include <memory>
00027 # include <cstring>
00028 # include <sstream>
00029 #endif
00030 
00031 
00032 #include "Matrix.h"
00033 
00034 using namespace Base;
00035 
00036 Matrix4D::Matrix4D (void)
00037 {
00038   setToUnity();
00039 }
00040 
00041 Matrix4D::Matrix4D (float a11, float a12, float a13, float a14, 
00042                     float a21, float a22, float a23, float a24,
00043                     float a31, float a32, float a33, float a34,
00044                     float a41, float a42, float a43, float a44 )
00045 {
00046   dMtrx4D[0][0] = a11; dMtrx4D[0][1] = a12; dMtrx4D[0][2] = a13; dMtrx4D[0][3] = a14;
00047   dMtrx4D[1][0] = a21; dMtrx4D[1][1] = a22; dMtrx4D[1][2] = a23; dMtrx4D[1][3] = a24;
00048   dMtrx4D[2][0] = a31; dMtrx4D[2][1] = a32; dMtrx4D[2][2] = a33; dMtrx4D[2][3] = a34;
00049   dMtrx4D[3][0] = a41; dMtrx4D[3][1] = a42; dMtrx4D[3][2] = a43; dMtrx4D[3][3] = a44;
00050 }
00051 
00052 Matrix4D::Matrix4D (double a11, double a12, double a13, double a14, 
00053                     double a21, double a22, double a23, double a24,
00054                     double a31, double a32, double a33, double a34,
00055                     double a41, double a42, double a43, double a44 )
00056 {
00057   dMtrx4D[0][0] = a11; dMtrx4D[0][1] = a12; dMtrx4D[0][2] = a13; dMtrx4D[0][3] = a14;
00058   dMtrx4D[1][0] = a21; dMtrx4D[1][1] = a22; dMtrx4D[1][2] = a23; dMtrx4D[1][3] = a24;
00059   dMtrx4D[2][0] = a31; dMtrx4D[2][1] = a32; dMtrx4D[2][2] = a33; dMtrx4D[2][3] = a34;
00060   dMtrx4D[3][0] = a41; dMtrx4D[3][1] = a42; dMtrx4D[3][2] = a43; dMtrx4D[3][3] = a44;
00061 }
00062 
00063 
00064 Matrix4D::Matrix4D (const Matrix4D& rclMtrx)
00065 {
00066   (*this) = rclMtrx;
00067 }
00068 
00069 Matrix4D::Matrix4D (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle)
00070 {
00071   setToUnity();
00072   this->rotLine(rclBase,rclDir,fAngle);
00073 }
00074 
00075 void Matrix4D::setToUnity (void)
00076 {
00077   dMtrx4D[0][0] = 1.0; dMtrx4D[0][1] = 0.0; dMtrx4D[0][2] = 0.0; dMtrx4D[0][3] = 0.0;
00078   dMtrx4D[1][0] = 0.0; dMtrx4D[1][1] = 1.0; dMtrx4D[1][2] = 0.0; dMtrx4D[1][3] = 0.0;
00079   dMtrx4D[2][0] = 0.0; dMtrx4D[2][1] = 0.0; dMtrx4D[2][2] = 1.0; dMtrx4D[2][3] = 0.0;
00080   dMtrx4D[3][0] = 0.0; dMtrx4D[3][1] = 0.0; dMtrx4D[3][2] = 0.0; dMtrx4D[3][3] = 1.0;
00081 }
00082 
00083 double Matrix4D::determinant() const
00084 {
00085     double fA0 = dMtrx4D[0][0]*dMtrx4D[1][1] - dMtrx4D[0][1]*dMtrx4D[1][0];
00086     double fA1 = dMtrx4D[0][0]*dMtrx4D[1][2] - dMtrx4D[0][2]*dMtrx4D[1][0];
00087     double fA2 = dMtrx4D[0][0]*dMtrx4D[1][3] - dMtrx4D[0][3]*dMtrx4D[1][0];
00088     double fA3 = dMtrx4D[0][1]*dMtrx4D[1][2] - dMtrx4D[0][2]*dMtrx4D[1][1];
00089     double fA4 = dMtrx4D[0][1]*dMtrx4D[1][3] - dMtrx4D[0][3]*dMtrx4D[1][1];
00090     double fA5 = dMtrx4D[0][2]*dMtrx4D[1][3] - dMtrx4D[0][3]*dMtrx4D[1][2];
00091     double fB0 = dMtrx4D[2][0]*dMtrx4D[3][1] - dMtrx4D[2][1]*dMtrx4D[3][0];
00092     double fB1 = dMtrx4D[2][0]*dMtrx4D[3][2] - dMtrx4D[2][2]*dMtrx4D[3][0];
00093     double fB2 = dMtrx4D[2][0]*dMtrx4D[3][3] - dMtrx4D[2][3]*dMtrx4D[3][0];
00094     double fB3 = dMtrx4D[2][1]*dMtrx4D[3][2] - dMtrx4D[2][2]*dMtrx4D[3][1];
00095     double fB4 = dMtrx4D[2][1]*dMtrx4D[3][3] - dMtrx4D[2][3]*dMtrx4D[3][1];
00096     double fB5 = dMtrx4D[2][2]*dMtrx4D[3][3] - dMtrx4D[2][3]*dMtrx4D[3][2];
00097     double fDet = fA0*fB5-fA1*fB4+fA2*fB3+fA3*fB2-fA4*fB1+fA5*fB0;
00098     return fDet;
00099 }
00100 
00101 /*
00102 void Matrix4D::setMoveX (float fMove)
00103 {
00104   Matrix4D clMat;
00105 
00106   clMat.dMtrx4D[0][3] = fMove;
00107   (*this) *= clMat;
00108 }
00109 
00110 void Matrix4D::setMoveY (float fMove)
00111 {
00112   Matrix4D clMat;
00113 
00114   clMat.dMtrx4D[1][3] = fMove;
00115   (*this) *= clMat;
00116 }
00117 
00118 void Matrix4D::setMoveZ (float fMove)
00119 {
00120   Matrix4D clMat;
00121 
00122   clMat.dMtrx4D[2][3] = fMove;
00123   (*this) *= clMat;
00124 }
00125 */
00126 void Matrix4D::move (const Vector3f& rclVct)
00127 {
00128   Matrix4D clMat;
00129 
00130   clMat.dMtrx4D[0][3] = rclVct.x;
00131   clMat.dMtrx4D[1][3] = rclVct.y;
00132   clMat.dMtrx4D[2][3] = rclVct.z;
00133   (*this) *= clMat;
00134 }
00135 void Matrix4D::move (const Vector3d& rclVct)
00136 {
00137   Matrix4D clMat;
00138 
00139   clMat.dMtrx4D[0][3] = rclVct.x;
00140   clMat.dMtrx4D[1][3] = rclVct.y;
00141   clMat.dMtrx4D[2][3] = rclVct.z;
00142   (*this) *= clMat;
00143 }
00144 /*
00145 void Matrix4D::setScaleX (float fScale)
00146 {
00147   Matrix4D clMat;
00148 
00149   clMat.dMtrx4D[0][0] = fScale;
00150   
00151   (*this) *= clMat;
00152 }
00153 
00154 void Matrix4D::setScaleY (float fScale)
00155 {
00156   Matrix4D clMat;
00157 
00158   clMat.dMtrx4D[1][1] = fScale;
00159   (*this) *= clMat;
00160 }
00161 
00162 void Matrix4D::setScaleZ (float fScale)
00163 {
00164   Matrix4D clMat;
00165 
00166   clMat.dMtrx4D[2][2] = fScale;
00167   (*this) *= clMat;
00168 }
00169 */
00170 
00171 void Matrix4D::scale (const Vector3f& rclVct)
00172 {
00173   Matrix4D clMat;
00174 
00175   clMat.dMtrx4D[0][0] = rclVct.x;
00176   clMat.dMtrx4D[1][1] = rclVct.y;
00177   clMat.dMtrx4D[2][2] = rclVct.z;
00178   (*this) *= clMat;
00179 }
00180 void Matrix4D::scale (const Vector3d& rclVct)
00181 {
00182   Matrix4D clMat;
00183 
00184   clMat.dMtrx4D[0][0] = rclVct.x;
00185   clMat.dMtrx4D[1][1] = rclVct.y;
00186   clMat.dMtrx4D[2][2] = rclVct.z;
00187   (*this) *= clMat;
00188 }
00189 
00190 void Matrix4D::rotX (double fAngle)
00191 {
00192   Matrix4D clMat;
00193   double fsin, fcos;
00194  
00195   fsin = sin (fAngle);
00196   fcos = cos (fAngle);
00197   clMat.dMtrx4D[1][1] =  fcos;  clMat.dMtrx4D[2][2] = fcos;
00198   clMat.dMtrx4D[1][2] = -fsin;  clMat.dMtrx4D[2][1] = fsin;
00199   
00200   (*this) *= clMat;
00201 }
00202 
00203 void Matrix4D::rotY (double fAngle)
00204 {
00205   Matrix4D clMat;
00206   double fsin, fcos;
00207  
00208   fsin = sin (fAngle);
00209   fcos = cos (fAngle);
00210   clMat.dMtrx4D[0][0] =  fcos;  clMat.dMtrx4D[2][2] = fcos;
00211   clMat.dMtrx4D[2][0] = -fsin;  clMat.dMtrx4D[0][2] = fsin;
00212   
00213   (*this) *= clMat;
00214 }
00215 
00216 void Matrix4D::rotZ (double fAngle)
00217 {
00218   Matrix4D clMat;
00219   double fsin, fcos;
00220  
00221   fsin = sin (fAngle);
00222   fcos = cos (fAngle);
00223   clMat.dMtrx4D[0][0] =  fcos;  clMat.dMtrx4D[1][1] = fcos;
00224   clMat.dMtrx4D[0][1] = -fsin;  clMat.dMtrx4D[1][0] = fsin;
00225   
00226   (*this) *= clMat;
00227 }
00228 
00229 void Matrix4D::rotLine (const Vector3d& rclVct, double fAngle)
00230 {
00231   // **** algorithm was taken from a math book
00232   Matrix4D  clMA, clMB, clMC, clMRot;
00233   Vector3d  clRotAxis(rclVct);
00234   short iz, is;
00235   double fcos, fsin;
00236 
00237   // set all entries to "0"
00238   for (iz = 0; iz < 4; iz++)
00239     for (is = 0; is < 4; is++)  {
00240       clMA.dMtrx4D[iz][is] = 0;
00241       clMB.dMtrx4D[iz][is] = 0;
00242       clMC.dMtrx4D[iz][is] = 0;
00243     }
00244 
00245   // ** normalize the rotation axis
00246   clRotAxis.Normalize();
00247   
00248   // ** set the rotation matrix (formula taken from a math book) */
00249   fcos = cos(fAngle);
00250   fsin = sin(fAngle);
00251   
00252   clMA.dMtrx4D[0][0] = (1-fcos) * clRotAxis.x * clRotAxis.x;
00253   clMA.dMtrx4D[0][1] = (1-fcos) * clRotAxis.x * clRotAxis.y;
00254   clMA.dMtrx4D[0][2] = (1-fcos) * clRotAxis.x * clRotAxis.z;
00255   clMA.dMtrx4D[1][0] = (1-fcos) * clRotAxis.x * clRotAxis.y;
00256   clMA.dMtrx4D[1][1] = (1-fcos) * clRotAxis.y * clRotAxis.y;
00257   clMA.dMtrx4D[1][2] = (1-fcos) * clRotAxis.y * clRotAxis.z;
00258   clMA.dMtrx4D[2][0] = (1-fcos) * clRotAxis.x * clRotAxis.z;
00259   clMA.dMtrx4D[2][1] = (1-fcos) * clRotAxis.y * clRotAxis.z;
00260   clMA.dMtrx4D[2][2] = (1-fcos) * clRotAxis.z * clRotAxis.z;
00261 
00262   clMB.dMtrx4D[0][0] = fcos;
00263   clMB.dMtrx4D[1][1] = fcos;
00264   clMB.dMtrx4D[2][2] = fcos;
00265 
00266   clMC.dMtrx4D[0][1] = -fsin * clRotAxis.z;
00267   clMC.dMtrx4D[0][2] =  fsin * clRotAxis.y;
00268   clMC.dMtrx4D[1][0] =  fsin * clRotAxis.z;
00269   clMC.dMtrx4D[1][2] = -fsin * clRotAxis.x;
00270   clMC.dMtrx4D[2][0] = -fsin * clRotAxis.y;
00271   clMC.dMtrx4D[2][1] =  fsin * clRotAxis.x;
00272 
00273   for (iz = 0; iz < 3; iz++)
00274     for (is = 0; is < 3; is++)
00275       clMRot.dMtrx4D[iz][is] = clMA.dMtrx4D[iz][is]  + clMB.dMtrx4D[iz][is] +
00276                                clMC.dMtrx4D[iz][is];
00277   (*this) *= clMRot;
00278 }
00279 
00280 void Matrix4D::rotLine (const Vector3f& rclVct, float fAngle)
00281 {
00282     Vector3d tmp(rclVct.x,rclVct.y,rclVct.z);
00283     rotLine(tmp,fAngle);
00284 }
00285 
00286 void Matrix4D::rotLine(const Vector3d& rclBase, const Vector3d& rclDir, double fAngle)
00287 {
00288   Matrix4D  clMT, clMRot, clMInvT, clM;
00289   Vector3d clBase(rclBase);
00290   
00291   clMT.move(clBase);            // Translation
00292   clMInvT.move(clBase *= (-1.0f));  // inverse Translation
00293   clMRot.rotLine(rclDir, fAngle);
00294 
00295   clM = clMRot * clMInvT;
00296   clM = clMT * clM; 
00297   (*this) *= clM;  
00298 }
00299 
00300 void Matrix4D::rotLine   (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle)
00301 {
00302   Matrix4D  clMT, clMRot, clMInvT, clM;
00303   Vector3f clBase(rclBase);
00304   
00305   clMT.move(clBase);            // Translation
00306   clMInvT.move(clBase *= (-1.0f));  // inverse Translation
00307   clMRot.rotLine(rclDir, fAngle);
00308 
00309   clM = clMRot * clMInvT;
00310   clM = clMT * clM; 
00311   (*this) *= clM;  
00312 }
00313 
00325 bool Matrix4D::toAxisAngle (Vector3f& rclBase, Vector3f& rclDir, float& rfAngle, float& fTranslation) const
00326 {
00327   // First check if the 3x3 submatrix is orthogonal
00328   for ( int i=0; i<3; i++ ) {
00329     // length must be one
00330     if ( fabs(dMtrx4D[0][i]*dMtrx4D[0][i]+dMtrx4D[1][i]*dMtrx4D[1][i]+dMtrx4D[2][i]*dMtrx4D[2][i]-1.0) > 0.01 )
00331       return false;
00332     // scalar product with other rows must be zero
00333     if ( fabs(dMtrx4D[0][i]*dMtrx4D[0][(i+1)%3]+dMtrx4D[1][i]*dMtrx4D[1][(i+1)%3]+dMtrx4D[2][i]*dMtrx4D[2][(i+1)%3]) > 0.01 )
00334       return false;
00335   }
00336 
00337   // Okay, the 3x3 matrix is orthogonal.
00338   // Note: The section to get the rotation axis and angle was taken from WildMagic Library.
00339   //
00340   // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
00341   // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 where
00342   // I is the identity and
00343   //
00344   //       +-        -+
00345   //   P = |  0 -z +y |
00346   //       | +z  0 -x |
00347   //       | -y +x  0 |
00348   //       +-        -+
00349   //
00350   // If A > 0, R represents a counterclockwise rotation about the axis in
00351   // the sense of looking from the tip of the axis vector towards the
00352   // origin.  Some algebra will show that
00353   //
00354   //   cos(A) = (trace(R)-1)/2  and  R - R^t = 2*sin(A)*P
00355   //
00356   // In the event that A = pi, R-R^t = 0 which prevents us from extracting
00357   // the axis through P.  Instead note that R = I+2*P^2 when A = pi, so
00358   // P^2 = (R-I)/2.  The diagonal entries of P^2 are x^2-1, y^2-1, and
00359   // z^2-1.  We can solve these for axis (x,y,z).  Because the angle is pi,
00360   // it does not matter which sign you choose on the square roots.
00361   //
00362   // For more details see also http://www.math.niu.edu/~rusin/known-math/97/rotations
00363 
00364   double fTrace = dMtrx4D[0][0] + dMtrx4D[1][1] + dMtrx4D[2][2];
00365   double fCos = 0.5*(fTrace-1.0);
00366   rfAngle = (float)acos(fCos);  // in [0,PI]
00367 
00368   if ( rfAngle > 0.0f )
00369   {
00370     if ( rfAngle < F_PI )
00371     {
00372       rclDir.x = (float)(dMtrx4D[2][1]-dMtrx4D[1][2]);
00373       rclDir.y = (float)(dMtrx4D[0][2]-dMtrx4D[2][0]);
00374       rclDir.z = (float)(dMtrx4D[1][0]-dMtrx4D[0][1]);
00375       rclDir.Normalize();
00376     }
00377     else
00378     {
00379       // angle is PI
00380       double fHalfInverse;
00381       if ( dMtrx4D[0][0] >= dMtrx4D[1][1] )
00382       {
00383         // r00 >= r11
00384         if ( dMtrx4D[0][0] >= dMtrx4D[2][2] )
00385         {
00386           // r00 is maximum diagonal term
00387           rclDir.x = (float)(0.5*sqrt(dMtrx4D[0][0] - dMtrx4D[1][1] - dMtrx4D[2][2] + 1.0));
00388           fHalfInverse = 0.5/rclDir.x;
00389           rclDir.y = (float)(fHalfInverse*dMtrx4D[0][1]);
00390           rclDir.z = (float)(fHalfInverse*dMtrx4D[0][2]);
00391         }
00392         else
00393         {
00394           // r22 is maximum diagonal term
00395           rclDir.z = (float)(0.5*sqrt(dMtrx4D[2][2] - dMtrx4D[0][0] - dMtrx4D[1][1] + 1.0));
00396           fHalfInverse = 0.5/rclDir.z;
00397           rclDir.x = (float)(fHalfInverse*dMtrx4D[0][2]);
00398           rclDir.y = (float)(fHalfInverse*dMtrx4D[1][2]);
00399         }
00400       }
00401       else
00402       {
00403         // r11 > r00
00404         if ( dMtrx4D[1][1] >= dMtrx4D[2][2] )
00405         {
00406           // r11 is maximum diagonal term
00407           rclDir.y = (float)(0.5*sqrt(dMtrx4D[1][1] - dMtrx4D[0][0] - dMtrx4D[2][2] + 1.0));
00408           fHalfInverse  = 0.5/rclDir.y;
00409           rclDir.x = (float)(fHalfInverse*dMtrx4D[0][1]);
00410           rclDir.z = (float)(fHalfInverse*dMtrx4D[1][2]);
00411         }
00412         else
00413         {
00414           // r22 is maximum diagonal term
00415           rclDir.z = (float)(0.5*sqrt(dMtrx4D[2][2] - dMtrx4D[0][0] - dMtrx4D[1][1] + 1.0));
00416           fHalfInverse = 0.5/rclDir.z;
00417           rclDir.x = (float)(fHalfInverse*dMtrx4D[0][2]);
00418           rclDir.y = (float)(fHalfInverse*dMtrx4D[1][2]);
00419         }
00420       }
00421     }
00422   }
00423   else
00424   {
00425     // The angle is 0 and the matrix is the identity.  Any axis will
00426     // work, so just use the x-axis.
00427     rclDir.x = 1.0f;
00428     rclDir.y = 0.0f;
00429     rclDir.z = 0.0f;
00430     rclBase.x = 0.0f;
00431     rclBase.y = 0.0f;
00432     rclBase.z = 0.0f;
00433   }
00434 
00435   // This is the translation part in axis direction
00436   fTranslation = (float)(dMtrx4D[0][3]*rclDir.x+dMtrx4D[1][3]*rclDir.y+dMtrx4D[2][3]*rclDir.z);
00437   Vector3f cPnt((float)dMtrx4D[0][3],(float)dMtrx4D[1][3],(float)dMtrx4D[2][3]); 
00438   cPnt = cPnt - fTranslation * rclDir;
00439 
00440   // This is the base point of the rotation axis
00441   if ( rfAngle > 0.0f )
00442   {
00443     double factor = 0.5*(1.0+fTrace)/sin(rfAngle);
00444     rclBase.x = (float)(0.5*(cPnt.x+factor*(rclDir.y*cPnt.z-rclDir.z*cPnt.y)));
00445     rclBase.y = (float)(0.5*(cPnt.y+factor*(rclDir.z*cPnt.x-rclDir.x*cPnt.z)));
00446     rclBase.z = (float)(0.5*(cPnt.z+factor*(rclDir.x*cPnt.y-rclDir.y*cPnt.x)));
00447   }
00448 
00449   return true;
00450 }
00451 
00452 void Matrix4D::transform (const Vector3f& rclVct, const Matrix4D& rclMtrx)
00453 {
00454   move(-rclVct);
00455   (*this) *= rclMtrx;
00456   move(rclVct);
00457 }
00458 void Matrix4D::transform (const Vector3d& rclVct, const Matrix4D& rclMtrx)
00459 {
00460   move(-rclVct);
00461   (*this) *= rclMtrx;
00462   move(rclVct);
00463 }
00464 
00465 void Matrix4D::inverse (void)
00466 {
00467   Matrix4D clInvTrlMat, clInvRotMat;
00468   short  iz, is;
00469 
00470   /**** Herausnehmen und Inversion der TranslationsMatrix
00471   aus der TransformationMatrix                      ****/
00472   for (iz = 0 ;iz < 3; iz++)
00473     clInvTrlMat.dMtrx4D[iz][3] = -dMtrx4D[iz][3];
00474 
00475   /**** Herausnehmen und Inversion der RotationsMatrix
00476   aus der TransformationMatrix                      ****/
00477   for (iz = 0 ;iz < 3; iz++)
00478     for (is = 0 ;is < 3; is++)
00479       clInvRotMat.dMtrx4D[iz][is] = dMtrx4D[is][iz];
00480       
00481   /**** inv(M) = inv(Mtrl * Mrot) = inv(Mrot) * inv(Mtrl) ****/
00482   (*this) = clInvRotMat * clInvTrlMat;
00483 }
00484 
00485 typedef  double * Matrix;
00486 
00487 void Matrix_gauss(Matrix a, Matrix b)
00488 {
00489   int ipiv[4], indxr[4], indxc[4];
00490   int i,j,k,l,ll;
00491   int irow=0, icol=0;
00492   double big, pivinv;
00493   double dum;
00494   for (j = 0; j < 4; j++)
00495     ipiv[j] = 0;
00496   for (i = 0; i < 4; i++) {
00497     big = 0;
00498     for (j = 0; j < 4; j++) {
00499       if (ipiv[j] != 1) {
00500   for (k = 0; k < 4; k++) {
00501     if (ipiv[k] == 0) {
00502       if (fabs(a[4*j+k]) >= big) {
00503         big = fabs(a[4*j+k]);
00504         irow = j;
00505         icol = k;
00506       }
00507     } else if (ipiv[k] > 1)
00508       return;  /* Singular matrix */
00509   }
00510       }
00511     }
00512     ipiv[icol] = ipiv[icol]+1;
00513     if (irow != icol) {
00514       for (l = 0; l < 4; l++) {
00515   dum = a[4*irow+l];
00516   a[4*irow+l] = a[4*icol+l];
00517   a[4*icol+l] = dum;
00518       }
00519       for (l = 0; l < 4; l++) {
00520   dum = b[4*irow+l];
00521   b[4*irow+l] = b[4*icol+l];
00522   b[4*icol+l] = dum;
00523       }
00524     }
00525     indxr[i] = irow;
00526     indxc[i] = icol;
00527     if (a[4*icol+icol] == 0) return;
00528     pivinv = 1.0/a[4*icol+icol];
00529     a[4*icol+icol] = 1.0;
00530     for (l = 0; l < 4; l++)
00531       a[4*icol+l] = a[4*icol+l]*pivinv;
00532     for (l = 0; l < 4; l++)
00533       b[4*icol+l] = b[4*icol+l]*pivinv;
00534     for (ll = 0; ll < 4; ll++) {
00535       if (ll != icol) {
00536   dum = a[4*ll+icol];
00537   a[4*ll+icol] = 0;
00538   for (l = 0; l < 4; l++)
00539     a[4*ll+l] = a[4*ll+l] - a[4*icol+l]*dum;
00540   for (l = 0; l < 4; l++)
00541     b[4*ll+l] = b[4*ll+l] - b[4*icol+l]*dum;
00542       }
00543     }
00544   }
00545   for (l = 3; l >= 0; l--) {
00546     if (indxr[l] != indxc[l]) {
00547       for (k = 0; k < 4; k++) {
00548   dum = a[4*k+indxr[l]];
00549   a[4*k+indxr[l]] = a[4*k+indxc[l]];
00550   a[4*k+indxc[l]] = dum;
00551       }
00552     }
00553   }
00554 }
00555 /* ------------------------------------------------------------------------
00556    Matrix_identity(Matrix a)
00557 
00558    Puts an identity matrix in matrix a
00559    ------------------------------------------------------------------------ */
00560 
00561 void Matrix_identity (Matrix a)
00562 {
00563   int i;
00564   for (i = 0; i < 16; i++) a[i] = 0;
00565   a[0] = 1;
00566   a[5] = 1;
00567   a[10] = 1;
00568   a[15] = 1;
00569 }
00570 
00571 /* ------------------------------------------------------------------------
00572    Matrix_invert(Matrix a, Matrix inva)
00573 
00574    Inverts Matrix a and places the result in inva.
00575    Relies on the Gaussian Elimination code above. (See Numerical recipes).
00576    ------------------------------------------------------------------------ */
00577 void Matrix_invert (Matrix a, Matrix inva)
00578 {
00579 
00580   double  temp[16];
00581   int     i;
00582 
00583   for (i = 0; i < 16; i++)
00584     temp[i] = a[i];
00585   Matrix_identity(inva);
00586   Matrix_gauss(temp,inva);
00587 }
00588 
00589 void Matrix4D::inverseGauss (void)
00590 {
00591   double matrix        [16]; 
00592   double inversematrix [16] = { 1 ,0 ,0 ,0 ,
00593                                 0 ,1 ,0 ,0 ,
00594                                 0 ,0 ,1 ,0 ,
00595                                 0 ,0 ,0 ,1 }; 
00596   getGLMatrix(matrix);
00597 
00598 //  Matrix_invert(matrix, inversematrix);
00599   Matrix_gauss(matrix,inversematrix);
00600 
00601   setGLMatrix(inversematrix);
00602 }
00603 
00604 void Matrix4D::getGLMatrix (double dMtrx[16]) const
00605 {
00606   short iz, is;
00607 
00608   for (iz = 0; iz < 4; iz++)
00609     for (is = 0; is < 4; is++)
00610       dMtrx[ iz + 4*is ] = dMtrx4D[iz][is];
00611 }
00612 
00613 void Matrix4D::setGLMatrix (const double dMtrx[16])
00614 {
00615   short iz, is;
00616 
00617   for (iz = 0; iz < 4; iz++)
00618     for (is = 0; is < 4; is++)
00619       dMtrx4D[iz][is] = dMtrx[ iz + 4*is ];
00620 }
00621 
00622 unsigned long Matrix4D::getMemSpace (void)
00623 {
00624   return sizeof(Matrix4D);
00625 }
00626 
00627 void Matrix4D::Print (void) const
00628 {
00629   short i;
00630 
00631   for (i = 0; i < 4; i++)
00632     printf("%9.3f %9.3f %9.3f %9.3f\n", dMtrx4D[i][0], dMtrx4D[i][1], dMtrx4D[i][2], dMtrx4D[i][3]);
00633 }
00634 
00635 void Matrix4D::transpose (void)
00636 {
00637   double  dNew[4][4];
00638 
00639   for (int i = 0; i < 4; i++)
00640   {
00641     for (int j = 0; j < 4; j++)
00642       dNew[j][i] = dMtrx4D[i][j];
00643   }
00644 
00645   memcpy(dMtrx4D, dNew, sizeof(dMtrx4D));
00646 }
00647 
00648 
00649 
00650 // write the 12 double of the matrix in a stream
00651 std::string Matrix4D::toString(void) const
00652 {
00653   std::stringstream str;
00654   for (int i = 0; i < 4; i++)
00655   {
00656     for (int j = 0; j < 4; j++)
00657       str << dMtrx4D[i][j] << " ";
00658   }
00659     
00660   return str.str();
00661 }
00662 
00663 // read the 12 double of the matrix from a stream
00664 void Matrix4D::fromString(const std::string &str)
00665 {
00666   std::stringstream input;
00667   input.str(str);
00668 
00669   for (int i = 0; i < 4; i++)
00670   {
00671     for (int j = 0; j < 4; j++)
00672       input >> dMtrx4D[i][j];
00673   }    
00674 }

Generated on Wed Nov 23 19:00:21 2011 for FreeCAD by  doxygen 1.6.1