Game Accessibility Library logo SourceForge.net Logo
Game Accessibility Suite: CAT/CATMatrix.cpp Source File

CATMatrix.cpp

Go to the documentation of this file.
00001 /// \file CATMatrix.h
00002 /// \brief Simple class for matrix operations
00003 /// \ingroup CAT
00004 ///
00005 /// Copyright (c) 2002-2008 by Michael Ellison.
00006 /// See COPYING.txt for the \ref gaslicense License (MIT License).
00007 ///
00008 // $Author: mikeellison $
00009 // $Date: 2008-01-19 19:19:35 -0600 (Sat, 19 Jan 2008) $
00010 // $Revision:   $
00011 // $NoKeywords: $
00012 
00013 #include "CATMatrix.h"
00014 
00015 // Generate a matrix of width and height
00016 CATMatrix::CATMatrix(CATUInt32 w, CATUInt32 h)
00017 {
00018     fWidth      = w;
00019     fHeight     = h;
00020     fMatrix     = new CATFloat64[w*h];
00021     this->ZeroMatrix(); 
00022 }
00023 
00024 // Copy constructor
00025 CATMatrix::CATMatrix(const CATMatrix& matrix)
00026 {
00027     this->fWidth    = matrix.fWidth;
00028     this->fHeight   = matrix.fHeight;
00029     fMatrix = new CATFloat64[this->fWidth * this->fHeight];
00030     for (CATUInt32 x = 0; x < fWidth; x++)
00031     {
00032         for (CATUInt32 y=0; y < fHeight; y++)
00033         {
00034             this->Val(x,y) = matrix.cVal(x,y);
00035         }
00036     }
00037 }
00038 
00039 // Destructor
00040 CATMatrix::~CATMatrix()
00041 {
00042     if (fMatrix != 0)
00043     {
00044         delete [] fMatrix;
00045         fMatrix = 0;
00046     }
00047 }
00048 
00049 // Retrieve the value by reference
00050 CATFloat64& CATMatrix::Val(CATUInt32 x, CATUInt32 y)
00051 {
00052     CATASSERT( (y < fHeight) && (y >= 0) && (x >= 0) && (x < fWidth), "Invalid position in matrix!");
00053     return fMatrix[x+y*fWidth];
00054 }
00055 
00056 // Const version of value
00057 CATFloat64 CATMatrix::cVal(CATUInt32 x, CATUInt32 y) const
00058 {
00059     CATASSERT( (y < fHeight) && (y >= 0) && (x >= 0) && (x < fWidth), "Invalid position in matrix!");
00060     return fMatrix[x+y*fWidth];
00061 }
00062 
00063 
00064 // Set the matrix to the identity matrix
00065 void CATMatrix::SetToIdentity()
00066 {
00067     for (CATUInt32 x=0; x<fWidth; x++)
00068     {
00069         for (CATUInt32 y=0; y<fHeight; y++)
00070         {
00071             if (x == y)
00072             {
00073                 this->Val(x,y) = 1;
00074             }
00075             else
00076             {
00077                 this->Val(x,y) = 0.0;
00078             }
00079         }
00080     }   
00081 }
00082 
00083 // Zero the matrix
00084 void CATMatrix::ZeroMatrix()
00085 {
00086     for (CATUInt32 x=0; x<fWidth; x++)
00087     {
00088         for (CATUInt32 y=0; y<fHeight; y++)
00089         {
00090             this->Val(x,y) = 0.0;
00091         }
00092     }
00093 }
00094 
00095 // Check for null
00096 bool CATMatrix::IsNullMatrix() const
00097 {
00098     for (CATUInt32 x=0; x<fWidth; x++)
00099     {
00100         for (CATUInt32 y=0; y< fHeight; y++)
00101         {
00102             if (this->cVal(x,y) != 0)
00103             {
00104                 return false;
00105             }
00106         }
00107     }
00108     return true;
00109 }
00110 
00111 // Check for identity
00112 bool CATMatrix::IsIdentityMatrix() const
00113 {
00114     for (CATUInt32 x=0; x<fWidth; x++)
00115     {
00116         for (CATUInt32 y=0; y<fHeight; y++)
00117         {
00118             if (x == y)
00119             {
00120                 if (this->cVal(x,y) != 1)
00121                 {
00122                     return false;
00123                 }
00124             }
00125             else
00126             {
00127                 if (this->cVal(x,y) != 0.0)
00128                 {
00129                     return false;
00130                 }
00131             }
00132         }
00133     }   
00134 
00135     return true;
00136 }
00137 
00138 // Compare two matricies for equality
00139 bool CATMatrix::operator==(const CATMatrix& matrix) const
00140 {
00141     if ((matrix.fWidth  != this->fWidth) || 
00142          (matrix.fHeight != this->fHeight))
00143     {
00144         return false;
00145     }
00146 
00147     for (CATUInt32 x=0; x < fWidth; x++)
00148     {
00149         for (CATUInt32 y=0; y < fHeight; y++)
00150         {
00151             if (this->cVal(x,y) != matrix.cVal(x,y))
00152             {
00153                 return false;
00154             }
00155         }
00156     }
00157 
00158     return true;
00159 }
00160 
00161 // Add two matricies
00162 CATMatrix       CATMatrix::operator+	(const CATMatrix& matrix) const
00163 {   
00164     if (!this->SameOrder(matrix))
00165     {
00166         CATASSERT(false,"Can't add two matricies of differing orders.");
00167         throw;
00168     }
00169     
00170     CATMatrix sum(fWidth,fHeight);
00171     sum.ZeroMatrix();
00172 
00173     for (CATUInt32 i = 0; i < this->fWidth; i++)
00174     {
00175         for (CATUInt32 j = 0; j < this->fHeight; j++)
00176         {
00177             sum.Val(i,j) = this->cVal(i,j) + matrix.cVal(i,j);
00178         }
00179     }
00180 
00181     return sum;
00182 }
00183 
00184 
00185 // Subtract two matricies (this - matrix)
00186 CATMatrix       CATMatrix::operator-	(const CATMatrix& matrix) const
00187 {
00188 
00189     if (!this->SameOrder(matrix))
00190     {
00191         CATASSERT(false,"Can't add two matricies of differing orders.");
00192         throw;
00193     }
00194     
00195     CATMatrix sum(fWidth,fHeight);
00196 
00197     for (CATUInt32 i = 0; i < this->fWidth; i++)
00198     {
00199         for (CATUInt32 j = 0; j < this->fHeight; j++)
00200         {
00201             sum.Val(i,j) = this->cVal(i,j) - matrix.cVal(i,j);
00202         }
00203     }
00204 
00205     return sum;
00206 }
00207 
00208 //  Check to see if the two matricies may be multiplied
00209 bool CATMatrix::IsConformable(const CATMatrix& matrix) const
00210 {
00211     if (this->fWidth != matrix.fHeight)
00212     {
00213         return false;
00214     }
00215 
00216     return true;
00217 }   
00218     
00219 // Find the product of two matricies (this*matrix)
00220 CATMatrix       CATMatrix::operator*	(const CATMatrix& matrix) const
00221 {
00222     CATMatrix product(matrix.fWidth, this->fHeight);
00223     product.ZeroMatrix();
00224 
00225     CATASSERT( this->fWidth == matrix.fHeight, "Can only multiply matricies where 1st matrix's width == 2nd matrix's height");
00226     if (fWidth != matrix.fHeight)
00227     {
00228         return product;
00229     }
00230 
00231     for (CATUInt32 x = 0; x < matrix.fWidth; x++)
00232     {
00233         for (CATUInt32 y=0; y < this->fHeight; y++)
00234         {
00235             for (CATUInt32 i = 0; i < this->fWidth; i++)
00236             {
00237                 product.Val(x,y) = product.cVal(x,y) + this->cVal(i,y) * matrix.cVal(x,i);
00238             }
00239         }
00240     }
00241 
00242     return product;
00243 }
00244 
00245 // Find the product of this matrix and a scalar
00246 CATMatrix       CATMatrix::operator*	(const CATFloat64 scalar) const
00247 {
00248 
00249     CATMatrix product(fWidth,fHeight);
00250 
00251     for (CATUInt32 i = 0; i < this->fWidth; i++)
00252     {
00253         for (CATUInt32 j = 0; j < this->fHeight; j++)
00254         {
00255             product.Val(i,j) = this->cVal(i,j) * scalar;
00256         }
00257     }
00258 
00259     return product;
00260 }
00261 
00262 // Check if the two matricies are of the same order
00263 bool CATMatrix::SameOrder(const CATMatrix& matrix) const
00264 {
00265     if ((this->fWidth != matrix.fWidth) || (this->fHeight != matrix.fHeight))
00266     {
00267         return false;
00268     }
00269 
00270     return true;
00271 }
00272 
00273 CATFloat64 CATMatrix::GetDeterminant() const
00274 {
00275 
00276     CATASSERT(fWidth == fHeight, "Determinants may only be gotten from square matricies...");
00277     CATASSERT(fWidth > 1, "Determinants may only be gotten from square matricies of at least 2x2");
00278     
00279     // Bail on invalid width/height
00280     if (fWidth != fHeight)
00281     {
00282         return 0.0;
00283     }
00284     if (fWidth < 2)
00285     {
00286         return 0.0;
00287     }
00288 
00289     CATUInt32 n = fWidth;
00290         
00291 
00292     // If we've got a 2x2 matrix, we can calculate it directly.
00293     if (n == 2)
00294     {
00295         return (this->cVal(0,0) * this->cVal(1,1)) - 
00296                  (this->cVal(1,0) * this->cVal(0,1));
00297     }
00298 
00299     // Otherwise, go across the columns and calc sub matricies recursively
00300     CATFloat64 determ = 0;
00301     
00302     for ( CATUInt32 j1 = 0; j1 < n; j1++) 
00303     {
00304         CATMatrix m(n-1,n-1);
00305 
00306         for (CATUInt32 i=1; i < n; i++) 
00307         {
00308             CATUInt32 j2 = 0;
00309             
00310             for (CATUInt32 j=0;j<n;j++) 
00311             {
00312                 if (j != j1)
00313                 {               
00314                     m.Val(i - 1, j2) = this->cVal(i,j);             
00315                     j2++;
00316                 }
00317             }
00318         }
00319         // Calc each sub matricies' determinant 
00320         determ += pow(-1.0,(CATFloat64)j1) * this->cVal(0,j1) * m.GetDeterminant();
00321     }
00322 
00323    return(determ);
00324 }
00325 
00326 
00327 CATMatrix CATMatrix::GetInverted() const
00328 {
00329     CATMatrix inversion(fWidth,fHeight);
00330     
00331     // Find the determinant of the matrix
00332     CATFloat64 determ = this->GetDeterminant();
00333     CATUInt32 i,j;
00334 
00335     // calc the inversion matrix
00336     for (i = 0; i < fWidth; i++)
00337     {
00338         for (j = 0; j < fHeight; j++)
00339         {
00340             CATUInt32 i1, j1, i2, j2;
00341 
00342             // Build matrix to find minor
00343             CATMatrix m(fWidth-1,fHeight-1);            
00344             i2 = 0;
00345             for (i1 = 0; i1 < fWidth; i1++)
00346             {
00347                 if (i1 != i)
00348                 {
00349                     j2 = 0;
00350                     for (j1 = 0; j1 < fHeight; j1++)
00351                     {
00352                         if (j1 != j)
00353                         {       
00354                             m.Val(i2,j2) = this->cVal(i1,j1);
00355                             j2++;
00356                         }
00357                     }
00358                     i2++;
00359                 }
00360             }
00361             
00362             // Calc inversion
00363             inversion.Val(j,i) = pow(-1.0,(CATFloat64)i+j) *  (m.GetDeterminant() / determ);
00364         }
00365     }
00366 
00367     return inversion;
00368 }
00369 
00370 
00371 // Dump the matrix to debugger
00372 void CATMatrix::DebugDump() const
00373 {
00374     CATWChar matrixTmp[100];
00375     wsprintf(matrixTmp,L"\nMatrix: (%d,%d):\n",fWidth,fHeight);
00376     ::OutputDebugString(matrixTmp);
00377     for (CATUInt32 y=0; y<fHeight; y++)
00378     {
00379         for (CATUInt32 x=0; x<fWidth; x++)
00380         {
00381             wsprintf(matrixTmp,L"%f  ",this->cVal(x,y));
00382             ::OutputDebugString(matrixTmp);
00383         }
00384         ::OutputDebugString(L"\n");
00385     }
00386 }
00387 
00388 
00389 // Create a transposed copy of the matrix
00390 //
00391 // e.g. the following matrix:
00392 //
00393 // 1 2 3
00394 // 4 5 6
00395 //        becomes
00396 //                   1 4
00397 //                   2 5
00398 //                   3 6
00399 //
00400 CATMatrix CATMatrix::GetTransposed() const
00401 {
00402     CATMatrix newMatrix(this->fHeight, this->fWidth);
00403 
00404     for (CATUInt32 x=0; x < this->fWidth; x++)
00405     {
00406         for (CATUInt32 y=0; y<this->fHeight; y++)
00407         {
00408             newMatrix.Val(y,x) = this->cVal(x,y);
00409         }
00410     }
00411 
00412     return newMatrix;
00413 }
00414 
00415 // Pseudo inverse of a matrix is  ((At * A)^-1) * At
00416 // Or, the product of the transposed matrix by the inverted product of the transposed matrix and the original matrix
00417 CATMatrix CATMatrix::GetPseudoInverse() const
00418 {
00419     // Find At
00420     CATMatrix transposed    = this->GetTransposed();
00421 
00422     // (At*A)
00423     CATMatrix product       = transposed * (*this);
00424 
00425     // (At*A)^-1
00426     CATMatrix inverted      = product.GetInverted();
00427 
00428     // (At*A)^-1 * At
00429     CATMatrix result        = inverted * transposed;
00430 
00431     return result;
00432 }

Generated on Mon Feb 11 04:09:45 2008 for Game Accessibility Suite by doxygen 1.5.4