Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   Related Pages  

sglMat2.hpp

00001 /*****************************************************************************
00002  * SGL: A Scene Graph Library
00003  *
00004  * Copyright (C) 1997-2001  Scott McMillan   All Rights Reserved.
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 GNU
00014  * 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; if not, write to the Free
00018  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  *****************************************************************************
00020  *     File: sglMat2.hpp
00021  *  Created: 28 February 1999
00022  *  Summary: 2x2 templated matrix class
00023  *****************************************************************************/
00024 
00025 #ifndef __SGL_MAT2_HPP
00026 #define __SGL_MAT2_HPP
00027 
00028 #include <sgl.h>
00029 #include <string.h> // memcpy
00030 #include <sglVector.hpp>
00031 #include <sglVec2.hpp>
00032 
00033 // ===========================================================================
00034 
00035 template <class T>
00036 class sglMat2
00037 {
00038 public:
00039    // constructors
00040    sglMat2() {};
00041 
00042    sglMat2(T m00, T m01, T m10, T m11) { set(m00, m01, m10, m11); }
00043 
00044    template <class S>
00045    sglMat2(const sglMat2<S>& mat)
00046       {
00047          set(mat[0][0], mat[0][1], mat[1][0], mat[1][1]);
00048       }
00049 
00050    template <class S>
00051    sglMat2(S mat[2][2])
00052       {
00053          set(mat[0][0], mat[0][1], mat[1][0], mat[1][1]);
00054       }
00055 
00056    // destructor
00057    ~sglMat2() {};  // not virtual, do not subclass
00058 
00059    inline T *getPtr() const { return (T *)m_matrix; }
00060 
00061    // indexing operator
00062    inline sglVec2<T>& operator[](unsigned int i)
00063       { 
00064          return *(sglVec2<T> *) m_matrix[i]; 
00065       }
00066    inline const sglVec2<T>& operator[](unsigned int i) const
00067       {
00068          return *(sglVec2<T> *) m_matrix[i];
00069       }
00070 
00071    // set/get
00072    template <class S>
00073    inline void set(S m00, S m01, S m10, S m11)
00074       {
00075          m_matrix[0][0] = (T)m00; m_matrix[0][1] = (T)m01;
00076          m_matrix[1][0] = (T)m10; m_matrix[1][1] = (T)m11;
00077       }
00078 
00079    template <class S>
00080    inline void setRow(const sglVec2<S>& v, unsigned int i)
00081       {
00082          m_matrix[i][0] = (T)v[0]; m_matrix[i][1] = (T)v[1];
00083       }
00084 
00085    template <class S>
00086    inline void setCol(const sglVec2<S>& v, unsigned int i)
00087       {
00088          m_matrix[0][i] = (T)v[0]; m_matrix[1][i] = (T)v[1];
00089       }
00090 
00091    template <class S>
00092    inline void getRow(sglVec2<S>& v, unsigned int i)
00093       {
00094         v[0] = (S)m_matrix[i][0]; v[1] = (S)m_matrix[i][1];
00095       }
00096 
00097    template <class S>
00098    inline void getCol(sglVec2<S>& v, unsigned int i)
00099       {
00100         v[0] = (S)m_matrix[0][i]; v[1] = (S)m_matrix[1][i];
00101       }
00102 
00103    // assignment operator
00104    template <class S>
00105    inline sglMat2 &operator=(const sglMat2<S>& mat)
00106       {
00107          set(mat[0][0], mat[0][1], mat[1][0], mat[1][1]);
00108          return *this;
00109       }
00110 
00111    // boolean operators
00112    template <class S>
00113    inline bool almostEqual(const sglMat2<S>& mat, double eps) const
00114       {
00115          return ((*this)[0].almostEqual(mat[0], eps) &&
00116                  (*this)[1].almostEqual(mat[1], eps));
00117       }
00118 
00119    template <class S>
00120    inline bool operator==(const sglMat2<S>& mat) const
00121       {
00122          return (*this)[0] == mat[0] && (*this)[1] == mat[1];
00123       }
00124 
00125    template <class S>
00126    inline bool operator!=(const sglMat2<S>& mat) const
00127       {
00128          return (*this)[0] != mat[0] || (*this)[1] != mat[1];
00129       }
00130 
00131    // math operators
00132    template <class S>
00133    inline sglMat2& operator+=(const sglMat2<S>& mat)
00134       {
00135          (*this)[0] += mat[0], (*this)[1] += mat[1]; return *this;
00136       }
00137    template <class S>
00138    inline sglMat2& operator-=(const sglMat2<S>& mat)
00139       {
00140          (*this)[0] -= mat[0], (*this)[1] -= mat[1]; return *this;
00141       }
00142    template <class S>
00143    inline sglMat2& operator*=(const sglMat2<S>& mat)
00144       {
00145          mul(*this, mat); return *this;
00146       }
00147    inline sglMat2& operator*=(const T s)
00148       {
00149          scale(*this, s, s); return *this;
00150       }
00151 
00152    template <class S>
00153    inline const sglMat2<T> operator+(const sglMat2<S> &rhs) const
00154       {
00155          return sglMat2(m_matrix[0][0] + rhs[0][0],
00156                         m_matrix[0][1] + rhs[0][1],
00157                         m_matrix[1][0] + rhs[1][0],
00158                         m_matrix[1][1] + rhs[1][1]);
00159       }
00160    template <class S>
00161    inline const sglMat2<T> operator-(const sglMat2<S> &rhs) const
00162       {
00163          return sglMat2(m_matrix[0][0] - rhs[0][0],
00164                         m_matrix[0][1] - rhs[0][1],
00165                         m_matrix[1][0] - rhs[1][0],
00166                         m_matrix[1][1] - rhs[1][1]);
00167       }
00168    template <class S>
00169    inline const sglMat2<T> operator*(const sglMat2<S> &rhs) const
00170       {
00171          return sglMat2(m_matrix[0][0]*rhs[0][0] + m_matrix[0][1]*rhs[1][0],
00172                         m_matrix[0][0]*rhs[0][1] + m_matrix[0][1]*rhs[1][1],
00173                         m_matrix[1][0]*rhs[0][0] + m_matrix[1][1]*rhs[1][0],
00174                         m_matrix[1][0]*rhs[0][1] + m_matrix[1][1]*rhs[1][1]);
00175       }
00176    inline const sglMat2<T> operator*(T scalar) const
00177       {
00178          return sglMat2(m_matrix[0][0]*scalar,
00179                         m_matrix[0][1]*scalar,
00180                         m_matrix[1][0]*scalar,
00181                         m_matrix[1][1]*scalar);
00182       }
00183 
00184    // explicit math operations (for backward compatibility)
00185    template <class S1, class S2>
00186    inline void add(const sglMat2<S1>& mat1, const sglMat2<S2>& mat2)
00187       {
00188          (*this)[0].add(mat1[0],mat2[0]);
00189          (*this)[1].add(mat1[1],mat2[1]);
00190       }
00191    template <class S1, class S2>
00192    inline void sub(const sglMat2<S1>& mat1, const sglMat2<S2>& mat2)
00193       {
00194          (*this)[0].sub(mat1[0],mat2[0]);
00195          (*this)[1].sub(mat1[1],mat2[1]);
00196       }
00197    template <class S>
00198    inline void scale(const sglMat2<S>& mat, T sx, T sy)
00199       {
00200          (*this)[0].scale(mat[0],sx);
00201          (*this)[1].scale(mat[1],sy);
00202       }
00203    // matrix multiply
00204    template <class S1, class S2>
00205    inline void mul(const sglMat2<S1>& mat1, const sglMat2<S2>& mat2)
00206       {
00207          T t[2][2];
00208          t[0][0] = mat1[0][0]*mat2[0][0] + mat1[0][1]*mat2[1][0];
00209          t[0][1] = mat1[0][0]*mat2[0][1] + mat1[0][1]*mat2[1][1];
00210          t[1][0] = mat1[1][0]*mat2[0][0] + mat1[1][1]*mat2[1][0];
00211          t[1][1] = mat1[1][0]*mat2[0][1] + mat1[1][1]*mat2[1][1];
00212          memcpy(m_matrix, t, sizeof(m_matrix));
00213       }
00214 
00215    // methods to build a matrix
00216    inline void buildIdentity()
00217       {
00218          set(1, 0,  0, 1);
00219       }
00220 
00221    inline void buildRotation(double angle) // in radians
00222       {
00223          T s = (T) sin(angle);
00224          T c = (T) cos(angle);
00225          m_matrix[0][0] =  c; m_matrix[0][1] = s;
00226          m_matrix[1][0] = -s; m_matrix[1][1] = c;
00227       }
00228 
00229    inline void buildScale(T sx, T sy)
00230       {
00231          m_matrix[0][0] = sx;  m_matrix[0][1] = 0;
00232          m_matrix[1][0] = 0;   m_matrix[1][1] = sy;
00233       }
00234 
00235 
00236    // other operations
00237    inline void transpose()
00238       {
00239          // then upper triangle - use tmp -- transposing self
00240          T tmp = m_matrix[0][1];
00241          m_matrix[0][1] = m_matrix[1][0];
00242          m_matrix[1][0] = tmp;
00243       }
00244 
00245    template <class S>
00246    inline void transpose(const sglMat2<S>& mat)
00247       {
00248          m_matrix[0][0] = mat[0][0]; m_matrix[1][1] = mat[1][1];
00249 
00250          // then upper triangle - use tmp just in case transposing self
00251          T tmp = mat[0][1]; m_matrix[0][1] = mat[1][0]; m_matrix[1][0] = tmp;
00252       }
00253 
00254    // cofactors, determinants, inverse
00255    inline T cofactor(unsigned int r, unsigned int c) const
00256       {
00257          return (((r+c)&1) ? -1:1) * m_matrix[(r ? 0:1)][(c ? 0:1)];
00258       }
00259 
00260    inline T det() const
00261       {
00262          return m_matrix[0][0]*cofactor(0,0) + m_matrix[0][1]*cofactor(0,1);
00263       }
00264 
00265    template <class S>
00266    inline void adjoint(const sglMat2<S>& mat)
00267       {
00268          T t[2][2];
00269          t[0][0] = mat.cofactor(0,0);
00270          t[0][1] = mat.cofactor(1,0);
00271          t[1][0] = mat.cofactor(0,1);
00272          t[1][1] = mat.cofactor(1,1);
00273          set(t[0][0], t[0][1], t[1][0], t[1][1]);
00274       }
00275    // adjoint divided by deteminant
00276    template <class S>
00277    inline bool inverse(const sglMat2<S>& mat)
00278       {
00279          T d = mat.det();
00280          if (SGL_ABS(d) < FLT_MIN) return false;
00281          adjoint(mat);
00282          *this *= (T)(1.0/d);
00283          return true;
00284       }
00285 
00286    // stream operators
00287 #if defined(TEMPLATE_OSTREAM_HACK)
00288    template <class S>
00289    friend ostream& operator<<(ostream& ostrm, const sglMat2<S>& mat);
00290 
00291    template <class S>
00292    friend istream& operator>>(istream& istrm, sglMat2<S>& mat);
00293 #else
00294    friend ostream& operator<<(ostream& ostrm, const sglMat2<T>& mat)
00295         {
00296             ostrm << '(';
00297             for (unsigned int i=0; i<2; i++)
00298                 ostrm << '(' << mat[i][0] << ',' << mat[i][1] << ')';
00299             return (ostrm << ')');
00300         }
00301 
00302    friend istream& operator>>(istream& istrm, sglMat2<T>& mat)
00303         {
00304             return (istrm >> mat[0][0] >> mat[0][1] >> mat[1][0] >> mat[1][1]);
00305         }
00306 #endif
00307 
00308 private:
00309    T m_matrix[2][2];
00310 };
00311 
00312 //----------------------------------------------------------------------------
00313 #if defined(TEMPLATE_OSTREAM_HACK)
00314 template <class T>
00315 inline ostream& operator<<(ostream& ostrm, const sglMat2<T>& mat)
00316 {
00317     return (ostrm << '(' << mat[0] << ", " << mat[1] << ')');
00318 }
00319 
00320 template <class T>
00321 inline istream& operator>>(istream& istrm, sglMat2<T>& mat)
00322 {
00323     return (istrm >> mat[0][0] >> mat[0][1] >> mat[1][0] >> mat[1][1]);
00324 }
00325 #endif
00326 //----------------------------------------------------------------------------
00327 
00328 
00329 //----------------------------------------------------------------------------
00330 // vector/matrix2x2 operations
00331 //----------------------------------------------------------------------------
00332 
00333 // ---------------------------------------------------------------------------
00334 // v' = v' * m (or v = m' * v)
00335 // ---------------------------------------------------------------------------
00336 template <class S, class T>
00337 inline void mul(sglVec2<T>& vec, const sglMat2<S>& mat)
00338 {
00339    T x    = (T)(vec[0]*mat[0][0] + vec[1]*mat[1][0]);
00340    vec[1] = (T)(vec[0]*mat[0][1] + vec[1]*mat[1][1]);
00341    vec[0] = x;
00342 }
00343 
00344 
00345 // ---------------------------------------------------------------------------
00346 // dest' = v' * m (or dest = m' * v)
00347 // ---------------------------------------------------------------------------
00348 template <class R, class S, class T>
00349 inline void mul(const sglVec2<R>& vec, const sglMat2<S>& mat,
00350                 sglVec2<T>& dest)
00351 {
00352    T x     = (T)(vec[0]*mat[0][0] + vec[1]*mat[1][0]);
00353    dest[1] = (T)(vec[0]*mat[0][1] + vec[1]*mat[1][1]);
00354    dest[0] = x;
00355 }
00356 
00357 
00358 // ---------------------------------------------------------------------------
00359 // v = m * v (or v' = v' * m')
00360 // ---------------------------------------------------------------------------
00361 template <class S, class T>
00362 inline void mulTranspose(sglVec2<T>& vec, const sglMat2<S>& mat)
00363 {
00364    T x    = (T)(vec[0]*mat[0][0] + vec[1]*mat[0][1]);
00365    vec[1] = (T)(vec[0]*mat[1][0] + vec[1]*mat[1][1]);
00366    vec[0] = x;
00367 }
00368 
00369 // ---------------------------------------------------------------------------
00370 // dest = m * v (or dest' = v' * m')
00371 // ---------------------------------------------------------------------------
00372 template <class R, class S, class T>
00373 inline void mulTranspose(const sglVec2<R>& vec, const sglMat2<S>& mat,
00374                          sglVec2<T>& dest)
00375 {
00376    T x     = (T)(vec[0]*mat[0][0] + vec[1]*mat[0][1]);
00377    dest[1] = (T)(vec[0]*mat[1][0] + vec[1]*mat[1][1]);
00378    dest[0] = x;
00379 }
00380 
00381 
00382 #endif

Generated at Mon Jul 1 18:00:05 2002 for SGL by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001