include/cinder/MatrixAffine2.h
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2012, The Cinder Project: http://libcinder.org All rights reserved.
00003  This code is intended for use with the Cinder C++ library: http://libcinder.org
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 
00024 #pragma once
00025 
00026 #include "cinder/Cinder.h"
00027 #include "cinder/CinderMath.h"
00028 #include "cinder/Vector.h"
00029 
00030 #include <iomanip>
00031 
00032 namespace cinder { 
00033 
00035 // MatrixAffine2
00037 template<typename T>
00038 class MatrixAffine2
00039 {
00040   public:
00041     typedef T   TYPE;
00042     typedef T   value_type;
00043     //
00044     static const size_t MEM_LEN = sizeof(T)*6;
00045 
00046     //
00047     // This class is OpenGL friendly and stores the m as how OpenGL would expect it.
00048     // m[i,j]:
00049     // | m[0,0] m[0,1] m[0,2] |
00050     // | m[1,0] m[1,1] m[1,2] |
00051     //
00052     // m[idx]
00053     // | m[0] m[2] m[4] |
00054     // | m[1] m[3] m[5] |
00055     //
00056     // mathematically this is:
00057     // | m[0] m[2] m[4] |
00058     // | m[1] m[3] m[5] |
00059     // |  0    0    1   |
00060     union {
00061         T m[6];
00062         struct {
00063             // This looks like it's transposed from the above, but it's really not.
00064             // It just has to be written this way so it follows the right ordering
00065             // in the memory layout as well as being mathematically correct.
00066             T m00, m10;
00067             T m01, m11;
00068             T m02, m12;
00069         };
00070         // [Cols][Rows]
00071         T mcols[3][2];
00072     };
00073     
00074     MatrixAffine2();
00075     MatrixAffine2( T s );
00076     MatrixAffine2( const T *dt );
00077     // m[0]=d0, m[1]=d1, m[2]=d2 ... m[5]=d5
00078     MatrixAffine2( T d0, T d1, T d2, T d3, T d4, T d5 );
00079     // Creates matrix with column vectors vx, vy and z
00080     MatrixAffine2( const Vec2<T> &vx, const Vec2<T> &vy, const Vec2<T> &vz ); 
00081 
00082     template<typename FromT>
00083     MatrixAffine2( const MatrixAffine2<FromT> &src );
00084     MatrixAffine2( const MatrixAffine2<T> &src );
00085 
00086     MatrixAffine2<T>&       operator=( const MatrixAffine2<T>& rhs );
00087     MatrixAffine2<T>&       operator=( T rhs );
00088 
00089     template<typename FromT>
00090     MatrixAffine2<T>&       operator=( const MatrixAffine2<FromT> &rhs );
00091 
00092     bool                equalCompare( const MatrixAffine2<T>& rhs, T epsilon ) const;
00093     bool                operator==( const MatrixAffine2<T> &rhs ) const { return equalCompare( rhs, (T)EPSILON ); }
00094     bool                operator!=( const MatrixAffine2<T> &rhs ) const { return ! ( *this == rhs ); }
00095 
00096     MatrixAffine2<T>&       operator*=( const MatrixAffine2<T> &rhs );
00097     MatrixAffine2<T>&       operator+=( const MatrixAffine2<T> &rhs );
00098     MatrixAffine2<T>&       operator-=( const MatrixAffine2<T> &rhs );
00099 
00100     MatrixAffine2<T>&       operator*=( T s );
00101     MatrixAffine2<T>&       operator/=( T s );
00102     MatrixAffine2<T>&       operator+=( T s );
00103     MatrixAffine2<T>&       operator-=( T s );
00104 
00105     const MatrixAffine2<T>  operator*( const MatrixAffine2<T> &rhs ) const;
00106     const MatrixAffine2<T>  operator+( const MatrixAffine2<T> &rhs ) const;
00107     const MatrixAffine2<T>  operator-( const MatrixAffine2<T> &rhs ) const;
00108 
00110     Vec2<T>             transformPoint( const Vec2<T> &rhs ) const;
00112     const Vec2<T>       operator*( const Vec2<T> &rhs ) const;
00114     Vec2<T>             transformVec( const Vec2<T> &v ) const;
00115 
00116     const MatrixAffine2<T>  operator*( T rhs ) const;
00117     const MatrixAffine2<T>  operator/( T rhs ) const;
00118     const MatrixAffine2<T>  operator+( T rhs ) const;
00119     const MatrixAffine2<T>  operator-( T rhs ) const;
00120 
00121     // Accessors
00122     T&                  at( int row, int col );
00123     const T&            at( int row, int col ) const;
00124 
00125     T&                  operator[]( int idx ) { return m[idx]; }
00126     const T&            operator[]( int idx ) const { return m[idx]; }
00127 
00128 
00129     void                set( const T *dt );
00130     // m[0]=d0, m[1]=d1, m[2]=d2 ... m[5]=d5
00131     void                set( T d0, T d1, T d2, T d3, T d4, T d5 );
00132 
00133     Vec2<T>             getColumn( int col ) const;
00134     void                setColumn( int col, const Vec2<T> &v );
00135 
00136     Vec3<T>             getRow( int row ) const;
00137     void                setRow( int row, const Vec3<T> &v );
00138 
00139     void                getColumns( Vec2<T> *c0, Vec2<T> *c1, Vec2<T> *c2 ) const;
00140     void                setColumns( const Vec2<T> &c0, const Vec2<T> &c1, const Vec2<T> &c2 );
00141 
00142     void                getRows( Vec3<T> *r0, Vec3<T> *r1, Vec3<T> *r2 ) const;
00143     void                setRows( const Vec3<T> &r0, const Vec3<T> &r1, const Vec3<T> &r2 );
00144 
00146     void                setToNull();
00148     void                setToIdentity();
00149 
00151     bool                isSingular() const;
00152 
00154     void                invert(T epsilon = EPSILON ) { *this = invertCopy( epsilon ); }
00156     MatrixAffine2<T>    invertCopy( T epsilon = EPSILON ) const;
00157 
00159     void                translate( const Vec2<T> &v );
00161     MatrixAffine2       translateCopy( const Vec2<T> &v ) const { MatrixAffine2 result = *this; result.translate( v ); return result; }
00162 
00164     void                rotate( T radians ) { *this *= MatrixAffine2<T>::makeRotate( radians ); }
00166     void                rotate( T radians, const Vec2<T> &pt ) { *this *= MatrixAffine2<T>::makeRotate( radians, pt ); }
00168     MatrixAffine2       rotateCopy( const Vec2<T> &v ) const { MatrixAffine2 result = *this; result.rotate( v ); return result; }
00170     MatrixAffine2       rotateCopy( const Vec2<T> &v, const Vec2<T> &pt ) const { MatrixAffine2 result = *this; result.rotate( v, pt ); return result; }
00171 
00173     void                scale( T s );
00175     void                scale( const Vec2<T> &v );
00177     MatrixAffine2       scaleCopy( T s ) const { MatrixAffine2 result = *this; result.scale( s ); return result; }
00179     MatrixAffine2       scaleCopy( const Vec2<T> &v ) const { MatrixAffine2 result = *this; result.scale( v ); return result; }
00180 
00181     // returns an identity matrix
00182     static MatrixAffine2<T> identity() { return MatrixAffine2( 1, 0, 0, 1, 0, 0 ); }
00183     // returns 1 filled matrix
00184     static MatrixAffine2<T>  one() { return MatrixAffine2( (T)1 ); }
00185     // returns 0 filled matrix
00186     static MatrixAffine2<T>  zero() { return MatrixAffine2( (T)0 ); }
00187 
00188     // creates translation matrix
00189     static MatrixAffine2<T> makeTranslate( const Vec2<T> &v );
00190 
00191     // creates rotation matrix by \a radians
00192     static MatrixAffine2<T> makeRotate( T radians );
00193     // creates rotation matrix by \a radians around the point \a pt
00194     static MatrixAffine2<T> makeRotate( T radians, const Vec2<T> &pt );
00195 
00196     // creates scale matrix
00197     static MatrixAffine2<T> makeScale( T s );
00198     static MatrixAffine2<T> makeScale( const Vec2<T> &v );
00199 
00200     static MatrixAffine2<T> makeSkewX( T radians );
00201     static MatrixAffine2<T> makeSkewY( T radians );
00202 
00203     friend std::ostream& operator<<( std::ostream &lhs, const MatrixAffine2<T> &rhs ) 
00204     {
00205         for( int i = 0; i < 2; i++) {
00206             lhs << " |";
00207             for( int j = 0; j < 3; j++) {
00208                 lhs << std::setw( 12 ) << std::setprecision( 5 ) << rhs.m[j*2+i];
00209             }
00210             lhs << "|" << std::endl;
00211         }
00212         
00213         return lhs;
00214     }
00215 };
00216 
00217 template<typename T>
00218 MatrixAffine2<T>::MatrixAffine2()
00219 {
00220     setToIdentity();
00221 }
00222 
00223 template<typename T>
00224 MatrixAffine2<T>::MatrixAffine2( T s )
00225 {
00226     for( int i = 0; i < 6; ++i )
00227         m[i] = s;
00228 }
00229 
00230 template<typename T>
00231 MatrixAffine2<T>::MatrixAffine2( const T *dt )
00232 {
00233     set( dt );
00234 }
00235 
00236 template<typename T>
00237 MatrixAffine2<T>::MatrixAffine2( T d0, T d1, T d2, T d3, T d4, T d5 )
00238 {
00239     set( d0, d1, d2, d3, d4, d5 );
00240 }
00241 
00242 template<typename T>
00243 MatrixAffine2<T>::MatrixAffine2( const Vec2<T> &vx, const Vec2<T> &vy, const Vec2<T> &vz )
00244 {
00245     m00 = vx.x; m01 = vy.x; m02 = vz.x;
00246     m10 = vx.y; m11 = vy.y; m12 = vz.y;
00247 }
00248 
00249 template<typename T>
00250 template<typename FromT >
00251 MatrixAffine2<T>::MatrixAffine2( const MatrixAffine2<FromT> &src )
00252 {
00253     for( int i = 0; i < 6; ++i ) {
00254         m[i] = static_cast<T>( src.m[i] );
00255     }
00256 }
00257 
00258 template<typename T>
00259 MatrixAffine2<T>::MatrixAffine2( const MatrixAffine2<T>& src )
00260 {
00261     std::memcpy( m, src.m, MEM_LEN );
00262 }
00263 
00264 template<typename T>
00265 MatrixAffine2<T>& MatrixAffine2<T>::operator=( const MatrixAffine2<T>& rhs )
00266 {
00267     memcpy( m, rhs.m, MEM_LEN );
00268     return *this;
00269 }
00270 
00271 template<typename T>
00272 MatrixAffine2<T>& MatrixAffine2<T>::operator=( T rhs )
00273 {
00274     for( int i = 0; i < 6; ++i ) {
00275         m[i] = rhs;
00276     }
00277     return *this;
00278 }
00279 
00280 template<typename T>
00281 template<typename FromT >
00282 MatrixAffine2<T>& MatrixAffine2<T>::operator=( const MatrixAffine2<FromT>& rhs )
00283 {
00284     for( int i = 0; i < 6; i++ ) {
00285         m[i] = static_cast<T>(rhs.m[i]);
00286     }
00287     return *this;
00288 }
00289 
00290 template<typename T>
00291 bool MatrixAffine2<T>::equalCompare( const MatrixAffine2<T>& rhs, T epsilon ) const
00292 {
00293     for( int i = 0; i < 6; ++i ) {
00294         if( math<T>::abs(m[i] - rhs.m[i]) >= epsilon )
00295             return false;
00296     }
00297     return true;
00298 }
00299 
00300 template<typename T>
00301 MatrixAffine2<T>& MatrixAffine2<T>::operator*=( const MatrixAffine2<T> &rhs )
00302 {
00303     MatrixAffine2<T> mat;
00304 
00305     mat.m[0] = m[0]*rhs.m[0] + m[2]*rhs.m[1];
00306     mat.m[1] = m[1]*rhs.m[0] + m[3]*rhs.m[1];
00307 
00308     mat.m[2] = m[0]*rhs.m[2] + m[2]*rhs.m[3];
00309     mat.m[3] = m[1]*rhs.m[2] + m[3]*rhs.m[3];
00310 
00311     mat.m[4] = m[0]*rhs.m[4] + m[2]*rhs.m[5] + m[4];
00312     mat.m[5] = m[1]*rhs.m[4] + m[3]*rhs.m[5] + m[5];
00313 
00314     *this = mat;
00315     return *this;
00316 }
00317 
00318 template<typename T>
00319 MatrixAffine2<T>& MatrixAffine2<T>::operator+=( const MatrixAffine2<T> &rhs )
00320 {
00321     for( int i = 0; i < 6; ++i )
00322         m[i] += rhs.m[i];
00323     return *this;
00324 }
00325 
00326 template<typename T>
00327 MatrixAffine2<T>& MatrixAffine2<T>::operator-=( const MatrixAffine2<T> &rhs )
00328 {
00329     for( int i = 0; i < 6; ++i )
00330         m[i] -= rhs.m[i];
00331     return *this;
00332 }
00333 
00334 template<typename T>
00335 MatrixAffine2<T>& MatrixAffine2<T>::operator*=( T s )
00336 {
00337     for( int i = 0; i < 6; ++i )
00338         m[i] *= s;
00339     return *this;
00340 }
00341 
00342 template<typename T>
00343 MatrixAffine2<T>& MatrixAffine2<T>::operator/=( T s )
00344 {
00345     T invS = 1 / s;
00346     for( int i = 0; i < 6; ++i )
00347         m[i] *= invS;
00348     return *this;
00349 }
00350 
00351 template<typename T>
00352 MatrixAffine2<T>& MatrixAffine2<T>::operator+=( T s )
00353 {
00354     for( int i = 0; i < 6; ++i )
00355         m[i] += s;
00356     return *this;
00357 }
00358 
00359 template<typename T>
00360 MatrixAffine2<T>& MatrixAffine2<T>::operator-=( T s )
00361 {
00362     for( int i = 0; i < 6; ++i )
00363         m[i] -= s;
00364     return *this;
00365 }
00366 
00367 template<typename T>
00368 const MatrixAffine2<T> MatrixAffine2<T>::operator*( const MatrixAffine2<T> &rhs ) const
00369 {
00370     MatrixAffine2<T> ret;
00371 
00372     ret.m[0] = m[0]*rhs.m[0] + m[2]*rhs.m[1];
00373     ret.m[1] = m[1]*rhs.m[0] + m[3]*rhs.m[1];
00374 
00375     ret.m[2] = m[0]*rhs.m[2] + m[2]*rhs.m[3];
00376     ret.m[3] = m[1]*rhs.m[2] + m[3]*rhs.m[3];
00377 
00378     ret.m[4] = m[0]*rhs.m[4] + m[2]*rhs.m[5] + m[4];
00379     ret.m[5] = m[1]*rhs.m[4] + m[3]*rhs.m[5] + m[5];
00380 
00381     return ret;
00382 }
00383 
00384 template<typename T>
00385 const MatrixAffine2<T> MatrixAffine2<T>::operator+( const MatrixAffine2<T> &rhs ) const
00386 {
00387     MatrixAffine2<T> ret;
00388     for( int i = 0; i < 6; ++i )
00389         ret.m[i] = m[i] + rhs.m[i];
00390     return ret;
00391 }
00392 
00393 template<typename T>
00394 const MatrixAffine2<T> MatrixAffine2<T>::operator-( const MatrixAffine2<T> &rhs ) const
00395 {
00396     MatrixAffine2<T> ret;
00397     for( int i = 0; i < 6; ++i )
00398         ret.m[i] = m[i] - rhs.m[i];
00399     return ret;
00400 }
00401 
00402 template<typename T>
00403 Vec2<T> MatrixAffine2<T>::transformPoint( const Vec2<T> &rhs ) const
00404 {
00405     return Vec2<T>( rhs.x * m[0] + rhs.y * m[2] + m[4], rhs.x * m[1] + rhs.y * m[3] + m[5] );
00406 }
00407 
00408 template<typename T>
00409 const Vec2<T> MatrixAffine2<T>::operator*( const Vec2<T> &rhs ) const
00410 {
00411     return Vec2<T>( rhs.x * m[0] + rhs.y * m[2] + m[4], rhs.x * m[1] + rhs.y * m[3] + m[5] );
00412 }
00413 
00414 template<typename T>
00415 Vec2<T> MatrixAffine2<T>::transformVec( const Vec2<T> &v ) const
00416 {
00417     return Vec2<T>( v.x * m[0] + v.y * m[2], v.x * m[1] + v.y * m[3] );
00418 }
00419 
00420 template<typename T>
00421 const MatrixAffine2<T> MatrixAffine2<T>::operator*( T rhs ) const
00422 {
00423     MatrixAffine2<T> ret;
00424     for( int i = 0; i < 6; ++i )
00425         ret.m[i] = m[i]*rhs;
00426     return ret;
00427 }
00428 
00429 template<typename T>
00430 const MatrixAffine2<T> MatrixAffine2<T>::operator/( T rhs ) const
00431 {
00432     MatrixAffine2<T> ret;
00433     T invS = 1 / rhs;
00434     for( int i = 0; i < 6; ++i )
00435         ret.m[i] = m[i] * invS;
00436     return ret;
00437 }
00438 
00439 template<typename T>
00440 const MatrixAffine2<T> MatrixAffine2<T>::operator+( T rhs ) const
00441 {
00442     MatrixAffine2<T> ret;
00443     for( int i = 0; i < 6; ++i )
00444         ret.m[i] = m[i] + rhs;
00445     return ret;
00446 }
00447 
00448 template<typename T>
00449 const MatrixAffine2<T> MatrixAffine2<T>::operator-( T rhs ) const
00450 {
00451     MatrixAffine2<T> ret;
00452     for( int i = 0; i < 6; ++i )
00453         ret.m[i] = m[i] - rhs;
00454     return ret;
00455 }
00456 
00457 template<typename T>
00458 T& MatrixAffine2<T>::at( int row, int col ) 
00459 {
00460     assert(row >= 0 && row < 2);
00461     assert(col >= 0 && col < 3);
00462     return m[col*2 + row];
00463 }
00464 
00465 template<typename T>
00466 const T& MatrixAffine2<T>::at( int row, int col ) const 
00467 {
00468     assert(row >= 0 && row < 2);
00469     assert(col >= 0 && col < 3);
00470     return m[col*2 + row];
00471 }
00472 
00473 template<typename T>
00474 void MatrixAffine2<T>::set( const T *d )
00475 {
00476     m[0] = d[0]; m[3] = d[3];
00477     m[1] = d[1]; m[4] = d[4];
00478     m[2] = d[2]; m[5] = d[5];
00479 }
00480 
00481 template<typename T>
00482 void MatrixAffine2<T>::set( T d0, T d1, T d2, T d3, T d4, T d5 )
00483 {
00484     m[0] = d0; m[3] = d3;
00485     m[1] = d1; m[4] = d4;
00486     m[2] = d2; m[5] = d5;
00487 }
00488 
00489 template<typename T>
00490 Vec2<T> MatrixAffine2<T>::getColumn( int col ) const
00491 {
00492     size_t i = col*2;
00493     return Vec2<T>( 
00494         m[i + 0], 
00495         m[i + 1]
00496     );
00497 }
00498 
00499 template<typename T>
00500 void MatrixAffine2<T>::setColumn( int col, const Vec2<T> &v )
00501 {
00502     size_t i = col*2;
00503     m[i + 0] = v.x;
00504     m[i + 1] = v.y;
00505 }
00506 
00507 template<typename T>
00508 Vec3<T> MatrixAffine2<T>::getRow( int row ) const 
00509 { 
00510     return Vec3<T>( 
00511         m[row +  0],
00512         m[row +  3],
00513         m[row +  6]
00514     ); 
00515 }
00516 
00517 template<typename T>
00518 void MatrixAffine2<T>::setRow( int row, const Vec3<T> &v ) 
00519 { 
00520     m[row +  0] = v.x; 
00521     m[row +  3] = v.y; 
00522     m[row +  6] = v.z; 
00523 }
00524 
00525 template<typename T>
00526 void MatrixAffine2<T>::getColumns( Vec2<T> *c0, Vec2<T> *c1, Vec2<T> *c2 ) const
00527 {
00528     *c0 = getColumn( 0 );
00529     *c1 = getColumn( 1 );
00530     *c2 = getColumn( 2 );
00531 }
00532 
00533 template<typename T>
00534 void MatrixAffine2<T>::setColumns( const Vec2<T> &c0, const Vec2<T> &c1, const Vec2<T> &c2 )
00535 {
00536     setColumn( 0, c0 );
00537     setColumn( 1, c1 );
00538     setColumn( 2, c2 );
00539 }
00540 
00541 template<typename T>
00542 void MatrixAffine2<T>::getRows( Vec3<T> *r0, Vec3<T> *r1, Vec3<T> *r2 ) const
00543 {
00544     *r0 = getRow( 0 );
00545     *r1 = getRow( 1 );
00546     *r2 = getRow( 2 );
00547 }
00548 
00549 template<typename T>
00550 void MatrixAffine2<T>::setRows( const Vec3<T> &r0, const Vec3<T> &r1, const Vec3<T> &r2 )
00551 {
00552     setRow( 0, r0 );
00553     setRow( 1, r1 );
00554     setRow( 2, r2 );
00555 }
00556 
00557 template<typename T>
00558 void MatrixAffine2<T>::setToNull()
00559 {
00560     std::memset( m, 0, MEM_LEN );
00561 }
00562 
00563 template<typename T>
00564 void MatrixAffine2<T>::setToIdentity()
00565 {
00566     m[0] = 1; m[2] = 0; m[4] = 0;
00567     m[1] = 0; m[3] = 1; m[5] = 0;
00568 }
00569 
00570 template<typename T>
00571 bool MatrixAffine2<T>::isSingular() const
00572 {
00573     return fabs( m[0] * m[3] - m[2] * m[1] ) <= (T)EPSILON;
00574 }
00575 
00576 template<typename T>
00577 MatrixAffine2<T> MatrixAffine2<T>::invertCopy( T epsilon ) const
00578 {
00579     MatrixAffine2<T> inv;
00580 
00581     inv.m[0] = m[3];
00582     inv.m[1] = -m[1];
00583     inv.m[2] = -m[2];
00584     inv.m[3] = m[0];
00585     inv.m[4] = m[2]*m[5] - m[3]*m[4];
00586     inv.m[5] = m[1]*m[4] - m[0]*m[5];
00587 
00588     T det = m[0]*inv.m[0] + m[1]*inv.m[2];
00589 
00590     if( fabs( det ) > epsilon ) {
00591         T invDet = 1 / det;
00592         inv.m[0] *= invDet;
00593         inv.m[1] *= invDet;
00594         inv.m[2] *= invDet;
00595         inv.m[3] *= invDet;
00596         inv.m[4] *= invDet;
00597         inv.m[5] *= invDet;
00598     }
00599 
00600     return inv;
00601 }
00602 
00603 template<typename T>
00604 void MatrixAffine2<T>::translate( const Vec2<T> &v )
00605 {
00606     m[4] += m[0]*v.x + m[2]*v.y;
00607     m[5] += m[1]*v.x + m[3]*v.y;
00608 }
00609 
00610 template<typename T>
00611 void MatrixAffine2<T>::scale( const Vec2<T> &s )
00612 {
00613     m[0] *= s.x;
00614     m[1] *= s.x;
00615 
00616     m[2] *= s.y;
00617     m[3] *= s.y;
00618 }
00619 
00620 template<typename T>
00621 MatrixAffine2<T>    MatrixAffine2<T>::makeTranslate( const Vec2<T> &v )
00622 {
00623     MatrixAffine2<T> ret;
00624 
00625     ret.m[0] = 1;
00626     ret.m[1] = 0;
00627 
00628     ret.m[2] = 0;
00629     ret.m[3] = 1;
00630     
00631     ret.m[4] = v.x;
00632     ret.m[5] = v.y;
00633 
00634     return ret; 
00635 }
00636 
00637 template<typename T>
00638 MatrixAffine2<T> MatrixAffine2<T>::makeRotate( T radians )
00639 {
00640     T sine   = math<T>::sin( radians );
00641     T cosine = math<T>::cos( radians );
00642 
00643     MatrixAffine2<T> ret;
00644 
00645     ret.m[0] = cosine;
00646     ret.m[1] = sine;
00647 
00648     ret.m[2] = -sine;
00649     ret.m[3] = cosine;
00650     
00651     ret.m[4] = 0;
00652     ret.m[5] = 0;
00653 
00654     return ret;
00655 }
00656 
00657 template<typename T>
00658 MatrixAffine2<T> MatrixAffine2<T>::makeRotate( T radians, const Vec2<T> &pt )
00659 {
00660     T sine   = math<T>::sin( radians );
00661     T cosine = math<T>::cos( radians );
00662 
00663     MatrixAffine2<T> ret;
00664 
00665     ret.m[0] = cosine;
00666     ret.m[1] = sine;
00667 
00668     ret.m[2] = -sine;
00669     ret.m[3] = cosine;
00670     
00671     ret.m[4] = pt.x - cosine * pt.x + sine * pt.y;
00672     ret.m[5] = pt.y - sine * pt.x - cosine * pt.y;
00673 
00674     return ret;
00675 }
00676 
00677 template<typename T>
00678 MatrixAffine2<T> MatrixAffine2<T>::makeScale( T s )
00679 {
00680     MatrixAffine2<T> ret;
00681 
00682     ret.m[0] = s;
00683     ret.m[1] = 0;
00684 
00685     ret.m[2] = 0;
00686     ret.m[3] = s;
00687     
00688     ret.m[4] = 0;
00689     ret.m[5] = 0;
00690 
00691     return ret;
00692 }
00693 
00694 template<typename T>
00695 MatrixAffine2<T> MatrixAffine2<T>::makeScale( const Vec2<T> &s )
00696 {
00697     MatrixAffine2<T> ret;
00698 
00699     ret.m[0] = s.x;
00700     ret.m[1] = 0;
00701 
00702     ret.m[2] = 0;
00703     ret.m[3] = s.y;
00704     
00705     ret.m[4] = 0;
00706     ret.m[5] = 0;
00707 
00708     return ret;
00709 }
00710 
00711 template<typename T>
00712 MatrixAffine2<T>    MatrixAffine2<T>::makeSkewX( T radians )
00713 {
00714     MatrixAffine2<T> ret;
00715 
00716     ret.m[0] = 1;
00717     ret.m[1] = 0;
00718 
00719     ret.m[2] = math<T>::tan( radians );
00720     ret.m[3] = 1;
00721     
00722     ret.m[4] = 0;
00723     ret.m[5] = 0;
00724 
00725     return ret; 
00726 }
00727 
00728 template<typename T>
00729 MatrixAffine2<T>    MatrixAffine2<T>::makeSkewY( T radians )
00730 {
00731     MatrixAffine2<T> ret;
00732 
00733     ret.m[0] = 1;
00734     ret.m[1] = math<T>::tan( radians );
00735 
00736     ret.m[2] = 0;
00737     ret.m[3] = 1;
00738     
00739     ret.m[4] = 0;
00740     ret.m[5] = 0;
00741 
00742     return ret; 
00743 }
00744 
00745 
00747 // Typedefs
00748 typedef MatrixAffine2<float>    MatrixAffine2f;
00749 typedef MatrixAffine2<double>   MatrixAffine2d;
00750 
00751 } // namespace cinder