00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00036 template< typename T >
00037 class Matrix22
00038 {
00039 public:
00040 typedef T TYPE;
00041 typedef T value_type;
00042
00043 static const size_t DIM = 2;
00044 static const size_t DIM_SQ = DIM*DIM;
00045 static const size_t MEM_LEN = sizeof(T)*DIM_SQ;
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 union {
00058 T m[4];
00059 struct {
00060
00061
00062
00063 T m00, m10;
00064 T m01, m11;
00065 };
00066
00067 T mcols[2][2];
00068 };
00069
00070 Matrix22();
00071
00072 Matrix22( T s );
00073
00074
00075 Matrix22( const T *dt, bool srcIsRowMajor = false );
00076
00077
00078 Matrix22( T d0, T d1, T d2, T d3, bool srcIsRowMajor = false );
00079
00080
00081 Matrix22( const Vec2<T> &vx, const Vec2<T> &vy );
00082
00083 template< typename FromT >
00084 Matrix22( const Matrix22<FromT>& src );
00085
00086 Matrix22( const Matrix22<T>& src );
00087
00088 operator T*() { return (T*)m; }
00089 operator const T*() const { return (const T*)m; }
00090
00091 Matrix22<T>& operator=( const Matrix22<T>& rhs );
00092 Matrix22<T>& operator=( const T &rhs );
00093
00094 template< typename FromT >
00095 Matrix22<T>& operator=( const Matrix22<FromT>& rhs );
00096
00097 bool equalCompare( const Matrix22<T>& rhs, T epsilon ) const;
00098 bool operator==( const Matrix22<T> &rhs ) const { return equalCompare( rhs, (T)EPSILON ); }
00099 bool operator!=( const Matrix22<T> &rhs ) const { return ! ( *this == rhs ); }
00100
00101 Matrix22<T>& operator*=( const Matrix22<T> &rhs );
00102 Matrix22<T>& operator+=( const Matrix22<T> &rhs );
00103 Matrix22<T>& operator-=( const Matrix22<T> &rhs );
00104
00105 Matrix22<T>& operator*=( T s );
00106 Matrix22<T>& operator/=( T s );
00107 Matrix22<T>& operator+=( T s );
00108 Matrix22<T>& operator-=( T s );
00109
00110 const Matrix22<T> operator*( const Matrix22<T> &rhs ) const;
00111 const Matrix22<T> operator+( const Matrix22<T> &rhs ) const;
00112 const Matrix22<T> operator-( const Matrix22<T> &rhs ) const;
00113
00114
00115 const Vec2<T> operator*( const Vec2<T> &rhs ) const;
00116
00117 const Matrix22<T> operator*( T rhs ) const;
00118 const Matrix22<T> operator/( T rhs ) const;
00119 const Matrix22<T> operator+( T rhs ) const;
00120 const Matrix22<T> operator-( T rhs ) const;
00121
00122
00123 T& at( int row, int col );
00124 const T& at( int row, int col ) const;
00125
00126
00127 void set( const T *dt, bool srcIsRowMajor = false );
00128
00129 void set( T d0, T d1, T d2, T d3, bool srcIsRowMajor = false );
00130
00131 Vec2<T> getColumn( int col ) const;
00132 void setColumn( int col, const Vec2<T> &v );
00133
00134 Vec2<T> getRow( int row ) const;
00135 void setRow( int row, const Vec2<T> &v );
00136
00137 void getColumns( Vec2<T> *c0, Vec2<T> *c1 ) const;
00138 void setColumns( const Vec2<T> &c0, const Vec2<T> &c1 );
00139
00140 void getRows( Vec2<T> *r0, Vec2<T> *r1 ) const;
00141 void setRows( const Vec2<T> &r0, const Vec2<T> &r1 );
00142
00143 void setToNull();
00144 void setToIdentity();
00145
00146 T determinant() const;
00147 T trace() const;
00148
00149 Matrix22<T> diagonal() const;
00150
00151 Matrix22<T> lowerTriangular() const;
00152 Matrix22<T> upperTriangular() const;
00153
00154 void transpose();
00155 Matrix22<T> transposed() const;
00156
00157 void invert (T epsilon = EPSILON ) { *this = inverted( epsilon ); }
00158 Matrix22<T> inverted( T epsilon = EPSILON ) const;
00159
00160
00161 Vec2<T> preMultiply( const Vec2<T> &v ) const;
00162
00163
00164 Vec2<T> postMultiply( const Vec2<T> &v ) const;
00165
00166
00167 Vec2<T> transformVec( const Vec2<T> &v ) const { return postMultiply( v ); }
00168
00169
00170 void rotate( T radians ) { Matrix22 rot = createRotation( radians ); Matrix22 mat = *this; *this = rot*mat; }
00171
00172
00173 void scale( T s ) { Matrix22 sc = createScale( s ); Matrix22 mat = *this; *this = sc*mat; }
00174 void scale( const Vec2<T> &v ) { Matrix22 sc = createScale( v ); Matrix22 mat = *this; *this = sc*mat; }
00175
00176
00177 Matrix22<T> invertTransform() const;
00178
00179
00180 static Matrix22<T> identity() { return Matrix22( 1, 0, 0, 1 ); }
00181
00182 static Matrix22<T> one() { return Matrix22( (T)1 ); }
00183
00184 static Matrix22<T> zero() { return Matrix22( (T)0 ); }
00185
00186
00187 static Matrix22<T> createRotation( T radians );
00188
00189
00190 static Matrix22<T> createScale( T s );
00191 static Matrix22<T> createScale( const Vec2<T> &v );
00192
00193 friend std::ostream& operator<<( std::ostream& lhs, const Matrix22<T>& rhs ) {
00194 for( int i = 0; i < 2; i++ ) {
00195 lhs << "|\t";
00196 for( int j = 0; j < 2; j++ ) {
00197 lhs << rhs.at( i, j ) << "\t";
00198 }
00199 lhs << "|" << std::endl;
00200 }
00201
00202 return lhs;
00203 }
00204
00205 };
00206
00207 template< typename T >
00208 Matrix22<T>::Matrix22()
00209 {
00210 setToIdentity();
00211 }
00212
00213 template< typename T >
00214 Matrix22<T>::Matrix22( T s )
00215 {
00216 for( int i = 0; i < DIM_SQ; ++i ) {
00217 m[i] = s;
00218 }
00219 }
00220
00221 template< typename T >
00222 Matrix22<T>::Matrix22( const T *dt, bool srcIsRowMajor )
00223 {
00224 set( dt, srcIsRowMajor );
00225 }
00226
00227 template< typename T >
00228 Matrix22<T>::Matrix22( T d0, T d1, T d2, T d3, bool srcIsRowMajor )
00229 {
00230 set( d0, d1,
00231 d2, d3, srcIsRowMajor );
00232 }
00233
00234 template< typename T >
00235 Matrix22<T>::Matrix22( const Vec2<T> &vx, const Vec2<T> &vy )
00236 {
00237 m00 = vx.x; m01 = vy.x;
00238 m10 = vx.y; m11 = vy.y;
00239 }
00240
00241 template< typename T >
00242 template< typename FromT >
00243 Matrix22<T>::Matrix22( const Matrix22<FromT>& src )
00244 {
00245 for( int i = 0; i < DIM_SQ; ++i ) {
00246 m[i] = static_cast<T>( src.m[i] );
00247 }
00248 }
00249
00250 template< typename T >
00251 Matrix22<T>::Matrix22( const Matrix22<T>& src )
00252 {
00253 std::memcpy( m, src.m, MEM_LEN );
00254 }
00255
00256 template< typename T >
00257 Matrix22<T>& Matrix22<T>::operator=( const Matrix22<T>& rhs )
00258 {
00259 memcpy( m, rhs.m, MEM_LEN );
00260 return *this;
00261 }
00262
00263 template< typename T >
00264 Matrix22<T>& Matrix22<T>::operator=( const T &rhs )
00265 {
00266 for( int i = 0; i < DIM_SQ; ++i ) {
00267 m[i] = rhs;
00268 }
00269 return *this;
00270 }
00271
00272 template< typename T >
00273 template< typename FromT >
00274 Matrix22<T>& Matrix22<T>::operator=( const Matrix22<FromT>& rhs )
00275 {
00276 for( int i = 0; i < DIM_SQ; i++ ) {
00277 m[i] = static_cast<T>(rhs.m[i]);
00278 }
00279 return *this;
00280 }
00281
00282 template< typename T >
00283 bool Matrix22<T>::equalCompare( const Matrix22<T>& rhs, T epsilon ) const
00284 {
00285 for( int i = 0; i < DIM_SQ; ++i ) {
00286 T diff = fabs( m[i] - rhs.m[i] );
00287 if( diff >= epsilon )
00288 return false;
00289 }
00290 return true;
00291 }
00292
00293 template< typename T >
00294 Matrix22<T>& Matrix22<T>::operator*=( const Matrix22<T> &rhs )
00295 {
00296 Matrix22<T> mat;
00297
00298 mat.m[0] = m[0]*rhs.m[0] + m[2]*rhs.m[1];
00299 mat.m[1] = m[1]*rhs.m[0] + m[3]*rhs.m[1];
00300
00301 mat.m[2] = m[0]*rhs.m[2] + m[2]*rhs.m[3];
00302 mat.m[3] = m[1]*rhs.m[2] + m[3]*rhs.m[3];
00303
00304 *this = mat;
00305
00306 return *this;
00307 }
00308
00309 template< typename T >
00310 Matrix22<T>& Matrix22<T>::operator+=( const Matrix22<T> &rhs )
00311 {
00312 for( int i = 0; i < DIM_SQ; ++i ) {
00313 m[i] += rhs.m[i];
00314 }
00315 return *this;
00316 }
00317
00318 template< typename T >
00319 Matrix22<T>& Matrix22<T>::operator-=( const Matrix22<T> &rhs )
00320 {
00321 for( int i = 0; i < DIM_SQ; ++i ) {
00322 m[i] -= rhs.m[i];
00323 }
00324 return *this;
00325 }
00326
00327 template< typename T >
00328 Matrix22<T>& Matrix22<T>::operator*=( T s )
00329 {
00330 for( int i = 0; i < DIM_SQ; ++i ) {
00331 m[i] *= s;
00332 }
00333 return *this;
00334 }
00335
00336 template< typename T >
00337 Matrix22<T>& Matrix22<T>::operator/=( T s )
00338 {
00339 T invS = (T)1/s;
00340 for( int i = 0; i < DIM_SQ; ++i ) {
00341 m[i] *= invS;
00342 }
00343 return *this;
00344 }
00345
00346 template< typename T >
00347 Matrix22<T>& Matrix22<T>::operator+=( T s )
00348 {
00349 for( int i = 0; i < DIM_SQ; ++i ) {
00350 m[i] += s;
00351 }
00352 return *this;
00353 }
00354
00355 template< typename T >
00356 Matrix22<T>& Matrix22<T>::operator-=( T s )
00357 {
00358 for( int i = 0; i < DIM_SQ; ++i ) {
00359 m[i] -= s;
00360 }
00361 return *this;
00362 }
00363
00364 template< typename T >
00365 const Matrix22<T> Matrix22<T>::operator*( const Matrix22<T> &rhs ) const
00366 {
00367 Matrix22<T> ret;
00368
00369 ret.m[0] = m[0]*rhs.m[0] + m[2]*rhs.m[1];
00370 ret.m[1] = m[1]*rhs.m[0] + m[3]*rhs.m[1];
00371
00372 ret.m[2] = m[0]*rhs.m[2] + m[2]*rhs.m[3];
00373 ret.m[3] = m[1]*rhs.m[2] + m[3]*rhs.m[3];
00374
00375 return ret;
00376 }
00377
00378 template< typename T >
00379 const Matrix22<T> Matrix22<T>::operator+( const Matrix22<T> &rhs ) const
00380 {
00381 Matrix22<T> ret;
00382 for( int i = 0; i < DIM_SQ; ++i ) {
00383 ret.m[i] = m[i] + rhs.m[i];
00384 }
00385 return ret;
00386 }
00387
00388 template< typename T >
00389 const Matrix22<T> Matrix22<T>::operator-( const Matrix22<T> &rhs ) const
00390 {
00391 Matrix22<T> ret;
00392 for( int i = 0; i < DIM_SQ; ++i ) {
00393 ret.m[i] = m[i] - rhs.m[i];
00394 }
00395 return ret;
00396 }
00397
00398 template< typename T >
00399 const Vec2<T> Matrix22<T>::operator*( const Vec2<T> &rhs ) const
00400 {
00401 return Vec2<T>(
00402 m[0]*rhs.x + m[2]*rhs.y,
00403 m[1]*rhs.x + m[3]*rhs.y
00404 );
00405 }
00406
00407
00408 template< typename T >
00409 const Matrix22<T> Matrix22<T>::operator*( T rhs ) const
00410 {
00411 Matrix22<T> ret;
00412 for( int i = 0; i < DIM_SQ; ++i ) {
00413 ret.m[i] = m[i]*rhs;
00414 }
00415 return ret;
00416 }
00417
00418 template< typename T >
00419 const Matrix22<T> Matrix22<T>::operator/( T rhs ) const
00420 {
00421 Matrix22<T> ret;
00422 T s = (T)1/rhs;
00423 for( int i = 0; i < DIM_SQ; ++i ) {
00424 ret.m[i] = m[i]*s;
00425 }
00426 return ret;
00427 }
00428
00429 template< typename T >
00430 const Matrix22<T> Matrix22<T>::operator+( T rhs ) const
00431 {
00432 Matrix22<T> ret;
00433 for( int i = 0; i < DIM_SQ; ++i ) {
00434 ret.m[i] = m[i] + rhs;
00435 }
00436 return ret;
00437 }
00438
00439 template< typename T >
00440 const Matrix22<T> Matrix22<T>::operator-( T rhs ) const
00441 {
00442 Matrix22<T> ret;
00443 for( int i = 0; i < DIM_SQ; ++i ) {
00444 ret.m[i] = m[i] - rhs;
00445 }
00446 return ret;
00447 }
00448
00449 template< typename T >
00450 T& Matrix22<T>::at( int row, int col )
00451 {
00452 assert(row >= 0 && row < DIM);
00453 assert(col >= 0 && col < DIM);
00454 return m[col*DIM + row];
00455 }
00456
00457 template< typename T >
00458 const T& Matrix22<T>::at( int row, int col ) const
00459 {
00460 assert(row >= 0 && row < DIM);
00461 assert(col >= 0 && col < DIM);
00462 return m[col*DIM + row];
00463 }
00464
00465 template< typename T >
00466 void Matrix22<T>::set( const T *dt, bool srcIsRowMajor )
00467 {
00468 if( srcIsRowMajor ) {
00469 m00 = dt[0]; m01 = dt[2];
00470 m10 = dt[1]; m11 = dt[3];
00471 }
00472 else {
00473 std::memcpy( m, dt, MEM_LEN );
00474 }
00475 }
00476
00477 template< typename T >
00478 void Matrix22<T>::set( T d0, T d1, T d2, T d3, bool srcIsRowMajor )
00479 {
00480 if( srcIsRowMajor ) {
00481 m[0] = d0; m[2] = d1;
00482 m[1] = d2; m[3] = d3;
00483 }
00484 else {
00485 m[0] = d0; m[2] = d2;
00486 m[1] = d1; m[3] = d3;
00487 }
00488 }
00489
00490 template< typename T >
00491 Vec2<T> Matrix22<T>::getColumn( int col ) const
00492 {
00493 size_t i = col*DIM;
00494 return Vec2<T>(
00495 m[i + 0],
00496 m[i + 1]
00497 );
00498 }
00499
00500 template< typename T >
00501 void Matrix22<T>::setColumn( int col, const Vec2<T> &v )
00502 {
00503 size_t i = col*DIM;
00504 m[i + 0] = v.x;
00505 m[i + 1] = v.y;
00506 }
00507
00508 template< typename T >
00509 Vec2<T> Matrix22<T>::getRow( int row ) const
00510 {
00511 return Vec2<T>(
00512 m[row + 0],
00513 m[row + 2]
00514 );
00515 }
00516
00517 template< typename T >
00518 void Matrix22<T>::setRow( int row, const Vec2<T> &v )
00519 {
00520 m[row + 0] = v.x;
00521 m[row + 2] = v.y;
00522 }
00523
00524 template< typename T >
00525 void Matrix22<T>::getColumns( Vec2<T> *c0, Vec2<T> *c1 ) const
00526 {
00527 *c0 = getColumn( 0 );
00528 *c1 = getColumn( 1 );
00529 }
00530
00531 template< typename T >
00532 void Matrix22<T>::setColumns( const Vec2<T> &c0, const Vec2<T> &c1 )
00533 {
00534 setColumn( 0, c0 );
00535 setColumn( 1, c1 );
00536 }
00537
00538 template< typename T >
00539 void Matrix22<T>::getRows( Vec2<T> *r0, Vec2<T> *r1 ) const
00540 {
00541 *r0 = getRow( 0 );
00542 *r1 = getRow( 1 );
00543 }
00544
00545 template< typename T >
00546 void Matrix22<T>::setRows( const Vec2<T> &r0, const Vec2<T> &r1 )
00547 {
00548 setRow( 0, r0 );
00549 setRow( 1, r1 );
00550 }
00551
00552 template< typename T >
00553 void Matrix22<T>::setToNull()
00554 {
00555 std::memset( m, 0, MEM_LEN );
00556 }
00557
00558 template< typename T >
00559 void Matrix22<T>::setToIdentity()
00560 {
00561 m00 = 1; m01 = 0;
00562 m10 = 0; m11 = 1;
00563 }
00564
00565 template< typename T >
00566 T Matrix22<T>::determinant() const
00567 {
00568 T det = m[0]*m[3] - m[1]*m[2];
00569 return det;
00570 }
00571
00572 template< typename T >
00573 T Matrix22<T>::trace() const
00574 {
00575 return m00 + m11;
00576 }
00577
00578 template< typename T >
00579 Matrix22<T> Matrix22<T>::diagonal() const
00580 {
00581 Matrix22 ret;
00582 ret.m00 = m00; ret.m01 = 0;
00583 ret.m10 = 0; ret.m11 = m11;
00584 return ret;
00585 }
00586
00587 template< typename T >
00588 Matrix22<T> Matrix22<T>::lowerTriangular() const
00589 {
00590 Matrix22 ret;
00591 ret.m00 = m00; ret.m01 = 0;
00592 ret.m10 = m10; ret.m11 = m11;
00593 return ret;
00594 }
00595
00596 template< typename T >
00597 Matrix22<T> Matrix22<T>::upperTriangular() const
00598 {
00599 Matrix22 ret;
00600 ret.m00 = m00; ret.m01 = m01;
00601 ret.m10 = 0; ret.m11 = m11;
00602 return ret;
00603 }
00604
00605 template< typename T >
00606 void Matrix22<T>::transpose()
00607 {
00608 T t;
00609 t = m01; m01 = m10; m10 = t;
00610 }
00611
00612 template< typename T >
00613 Matrix22<T> Matrix22<T>::transposed() const
00614 {
00615 return Matrix22<T>(
00616 m[ 0], m[ 2],
00617 m[ 1], m[ 3]
00618 );
00619 }
00620
00621 template< typename T >
00622 Matrix22<T> Matrix22<T>::inverted( T epsilon ) const
00623 {
00624 Matrix22<T> inv( (T)0 );
00625
00626 T det = m[0]*m[3] - m[1]*m[2];
00627
00628 if( fabs( det ) > epsilon ) {
00629 T invDet = (T)1/det;
00630 inv.m[0] = m[3]*invDet;
00631 inv.m[1] = -m[1]*invDet;
00632 inv.m[2] = -m[2]*invDet;
00633 inv.m[3] = m[0]*invDet;
00634 }
00635
00636 return inv;
00637 }
00638
00639 template< typename T >
00640 Vec2<T> Matrix22<T>::preMultiply( const Vec2<T> &v ) const
00641 {
00642 return Vec2<T>(
00643 v.x*m00 + v.y*m10,
00644 v.x*m01 + v.y*m11
00645 );
00646 }
00647
00648 template< typename T >
00649 Vec2<T> Matrix22<T>::postMultiply( const Vec2<T> &v ) const
00650 {
00651 return Vec2<T>(
00652 m00*v.x + m01*v.y,
00653 m10*v.x + m11*v.y
00654 );
00655 }
00656
00657 template< typename T >
00658 Matrix22<T> Matrix22<T>::invertTransform() const
00659 {
00660 Matrix22<T> ret;
00661
00662
00663 for( int i = 0; i < DIM; i++ ) {
00664 for( int j = 0; j < DIM; j++ ) {
00665 ret.at( j, i ) = at( i, j );
00666 }
00667 }
00668
00669 return ret;
00670 }
00671
00672 template< typename T >
00673 Matrix22<T> Matrix22<T>::createRotation( T radians )
00674 {
00675 Matrix22<T> ret;
00676 T ac = cos( radians );
00677 T as = sin( radians );
00678 ret.m00 = ac; ret.m01 = as;
00679 ret.m10 = -as; ret.m11 = ac;
00680 return ret;
00681 }
00682
00683 template< typename T >
00684 Matrix22<T> Matrix22<T>::createScale( T s )
00685 {
00686 Matrix22<T> ret;
00687 ret.m00 = s; ret.m01 = 0;
00688 ret.m10 = 0; ret.m11 = s;
00689 return ret;
00690 }
00691
00692 template< typename T >
00693 Matrix22<T> Matrix22<T>::createScale( const Vec2<T> &v )
00694 {
00695 Matrix22<T> ret;
00696 ret.m00 = v.x; ret.m01 = 0;
00697 ret.m10 = 0; ret.m11 = v.y;
00698 return ret;
00699 }
00700
00702
00703 typedef Matrix22<float> Matrix22f;
00704 typedef Matrix22<double> Matrix22d;
00705
00706 }