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( T s )
00612 {
00613     m[0] *= s;
00614     m[1] *= s;
00615         
00616     m[2] *= s;
00617     m[3] *= s;
00618 }
00619     
00620 template<typename T>
00621 void MatrixAffine2<T>::scale( const Vec2<T> &s )
00622 {
00623     m[0] *= s.x;
00624     m[1] *= s.x;
00625 
00626     m[2] *= s.y;
00627     m[3] *= s.y;
00628 }
00629 
00630 template<typename T>
00631 MatrixAffine2<T>    MatrixAffine2<T>::makeTranslate( const Vec2<T> &v )
00632 {
00633     MatrixAffine2<T> ret;
00634 
00635     ret.m[0] = 1;
00636     ret.m[1] = 0;
00637 
00638     ret.m[2] = 0;
00639     ret.m[3] = 1;
00640     
00641     ret.m[4] = v.x;
00642     ret.m[5] = v.y;
00643 
00644     return ret; 
00645 }
00646 
00647 template<typename T>
00648 MatrixAffine2<T> MatrixAffine2<T>::makeRotate( T radians )
00649 {
00650     T sine   = math<T>::sin( radians );
00651     T cosine = math<T>::cos( radians );
00652 
00653     MatrixAffine2<T> ret;
00654 
00655     ret.m[0] = cosine;
00656     ret.m[1] = sine;
00657 
00658     ret.m[2] = -sine;
00659     ret.m[3] = cosine;
00660     
00661     ret.m[4] = 0;
00662     ret.m[5] = 0;
00663 
00664     return ret;
00665 }
00666 
00667 template<typename T>
00668 MatrixAffine2<T> MatrixAffine2<T>::makeRotate( T radians, const Vec2<T> &pt )
00669 {
00670     T sine   = math<T>::sin( radians );
00671     T cosine = math<T>::cos( radians );
00672 
00673     MatrixAffine2<T> ret;
00674 
00675     ret.m[0] = cosine;
00676     ret.m[1] = sine;
00677 
00678     ret.m[2] = -sine;
00679     ret.m[3] = cosine;
00680     
00681     ret.m[4] = pt.x - cosine * pt.x + sine * pt.y;
00682     ret.m[5] = pt.y - sine * pt.x - cosine * pt.y;
00683 
00684     return ret;
00685 }
00686 
00687 template<typename T>
00688 MatrixAffine2<T> MatrixAffine2<T>::makeScale( T s )
00689 {
00690     MatrixAffine2<T> ret;
00691 
00692     ret.m[0] = s;
00693     ret.m[1] = 0;
00694 
00695     ret.m[2] = 0;
00696     ret.m[3] = s;
00697     
00698     ret.m[4] = 0;
00699     ret.m[5] = 0;
00700 
00701     return ret;
00702 }
00703 
00704 template<typename T>
00705 MatrixAffine2<T> MatrixAffine2<T>::makeScale( const Vec2<T> &s )
00706 {
00707     MatrixAffine2<T> ret;
00708 
00709     ret.m[0] = s.x;
00710     ret.m[1] = 0;
00711 
00712     ret.m[2] = 0;
00713     ret.m[3] = s.y;
00714     
00715     ret.m[4] = 0;
00716     ret.m[5] = 0;
00717 
00718     return ret;
00719 }
00720 
00721 template<typename T>
00722 MatrixAffine2<T>    MatrixAffine2<T>::makeSkewX( T radians )
00723 {
00724     MatrixAffine2<T> ret;
00725 
00726     ret.m[0] = 1;
00727     ret.m[1] = 0;
00728 
00729     ret.m[2] = math<T>::tan( radians );
00730     ret.m[3] = 1;
00731     
00732     ret.m[4] = 0;
00733     ret.m[5] = 0;
00734 
00735     return ret; 
00736 }
00737 
00738 template<typename T>
00739 MatrixAffine2<T>    MatrixAffine2<T>::makeSkewY( T radians )
00740 {
00741     MatrixAffine2<T> ret;
00742 
00743     ret.m[0] = 1;
00744     ret.m[1] = math<T>::tan( radians );
00745 
00746     ret.m[2] = 0;
00747     ret.m[3] = 1;
00748     
00749     ret.m[4] = 0;
00750     ret.m[5] = 0;
00751 
00752     return ret; 
00753 }
00754 
00755 
00757 // Typedefs
00758 typedef MatrixAffine2<float>    MatrixAffine2f;
00759 typedef MatrixAffine2<double>   MatrixAffine2d;
00760 
00761 } // namespace cinder