Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "cmtkMatrix3x3.h"
00034
00035 #include <System/cmtkConsole.h>
00036 #include <Base/cmtkMathUtil.h>
00037
00038 #include <string.h>
00039 #include <math.h>
00040
00041 namespace
00042 cmtk
00043 {
00044
00047
00048 template<class T>
00049 Matrix3x3<T>::Matrix3x3()
00050 {
00051 memset( Matrix, 0, sizeof( Matrix ) );
00052 Matrix[0][0] = Matrix[1][1] = Matrix[2][2] = 1.0;
00053 }
00054
00055 template<class T>
00056 Matrix3x3<T>::Matrix3x3( const Self& other )
00057 {
00058 memcpy( this->Matrix, other.Matrix, sizeof( this->Matrix ) );
00059 }
00060
00061 template<class T>
00062 Matrix3x3<T>&
00063 Matrix3x3<T>::Set( const T *const values )
00064 {
00065 memcpy( this->Matrix, values, sizeof( this->Matrix ) );
00066 return *this;
00067 }
00068
00069 template<class T>
00070 Matrix3x3<T>&
00071 Matrix3x3<T>::Fill( const T value )
00072 {
00073 for ( int i = 0; i < 3; ++i )
00074 for ( int j = 0; j < 3; ++j )
00075 this->Matrix[i][j] = value;
00076 return *this;
00077 }
00078
00079 template<class T>
00080 Matrix3x3<T>&
00081 Matrix3x3<T>::Compose( const Types::Coordinate params[8] )
00082 {
00083 const Units::Radians alpha = Units::Degrees( params[2] );
00084
00085 this->Matrix[0][0] = static_cast<T>( MathUtil::Cos( alpha ) * params[3] );
00086 this->Matrix[0][1] = static_cast<T>( -MathUtil::Sin( alpha ) * params[3] );
00087 this->Matrix[0][2] = static_cast<T>( 0.0 );
00088 this->Matrix[1][0] = static_cast<T>( MathUtil::Sin( alpha ) * params[4] );
00089 this->Matrix[1][1] = static_cast<T>( MathUtil::Cos( alpha ) * params[4] );
00090 this->Matrix[1][2] = static_cast<T>( 0.0 );
00091 this->Matrix[2][0] = static_cast<T>( 0.0 );
00092 this->Matrix[2][1] = static_cast<T>( 0.0 );
00093 this->Matrix[2][2] = static_cast<T>( 1.0 );
00094
00095
00096 Self shearMatrix;
00097 shearMatrix[0][1] = static_cast<T>( params[5] );
00098 *this *= shearMatrix;
00099
00100
00101 Types::Coordinate cM[2] =
00102 {
00103 params[6]*this->Matrix[0][0] + params[7]*this->Matrix[1][0],
00104 params[6]*this->Matrix[0][1] + params[7]*this->Matrix[1][1],
00105 };
00106
00107
00108 this->Matrix[2][0] = static_cast<T>( params[0] - cM[0] + params[6] );
00109 this->Matrix[2][1] = static_cast<T>( params[1] - cM[1] + params[7] );
00110
00111 return *this;
00112 }
00113
00120 template<class T>
00121 bool
00122 Matrix3x3<T>::Decompose
00123 ( Types::Coordinate params[8], const Types::Coordinate *center ) const
00124 {
00125
00126 Types::Coordinate matrix[3][3];
00127 memcpy( matrix, Matrix, sizeof( matrix ) );
00128
00129
00130 params[0] = matrix[2][0];
00131 params[1] = matrix[2][1];
00132
00133 if ( center )
00134 {
00135 Types::Coordinate cM[2] = { center[0]*matrix[0][0] + center[1]*matrix[1][0], center[0]*matrix[0][1] + center[1]*matrix[1][1] };
00136
00137 params[0] += cM[0] - center[0];
00138 params[1] += cM[1] - center[1];
00139
00140 memcpy( params+6, center, 2*sizeof( Types::Coordinate ) );
00141 }
00142 else
00143 {
00144 memset( params+6, 0, 2*sizeof( Types::Coordinate ) );
00145 }
00146
00147 #define IGS_EPSILON 0.001
00148 for ( int i=0; i<2; ++i )
00149 {
00150
00151 params[3+i] = sqrt( MathUtil::Square( matrix[i][0] ) + MathUtil::Square( matrix[i][1] ) );
00152
00153
00154 if ( fabs(params[3+i]) < IGS_EPSILON )
00155 {
00156 StdErr <<"igsMatrxi3x3::Decompose encountered singular matrix.";
00157 return false;
00158 }
00159 }
00160
00161
00162
00163 double x2 = matrix[0][0] / params[3];
00164 double y2 = -matrix[0][1] / params[3];
00165
00166 double dot = x2 * x2 + y2 * y2;
00167 double d1 = sqrt (dot);
00168
00169 double cosTheta, sinTheta;
00170 if (d1 < IGS_EPSILON)
00171 {
00172 cosTheta = 1.0;
00173 sinTheta = 0.0;
00174 }
00175 else
00176 {
00177 cosTheta = x2 / d1;
00178 sinTheta = y2 / d1;
00179 }
00180
00181 params[2] = static_cast<T>( Units::Degrees( MathUtil::ArcTan2 (sinTheta, cosTheta) ).Value() );
00182
00183 return true;
00184 #undef IGS_EPSILON
00185 }
00186
00187 template<class T>
00188 Matrix3x3<T>
00189 Matrix3x3<T>::GetTranspose() const
00190 {
00191 Self transpose;
00192 for ( int i = 0; i < 3; ++i )
00193 {
00194 for ( int j = 0; j < 3; ++j )
00195 transpose[i][j] = this->Matrix[j][i];
00196 }
00197 return transpose;
00198 }
00199
00200 template<class T>
00201 Matrix3x3<T>&
00202 Matrix3x3<T>::Invert2x2()
00203 {
00204 Self inverse;
00205
00206 T rowBuff[3];
00207 for ( int col = 0; col<3; ++col )
00208 {
00209 int pivIdx = col;
00210 T pivAbs = fabs( this->Matrix[col][col] );
00211
00212 for ( int row = col+1; row<2; ++row )
00213 {
00214 T nextAbs = fabs( this->Matrix[row][col] );
00215 if (nextAbs > pivAbs )
00216 {
00217 pivIdx = row;
00218 pivAbs = nextAbs;
00219 }
00220 }
00221
00222 if ( col != pivIdx )
00223 {
00224 memcpy( rowBuff, this->Matrix[col], sizeof(rowBuff) );
00225 memcpy( this->Matrix[col], this->Matrix[pivIdx], sizeof(rowBuff) );
00226 memcpy( this->Matrix[pivIdx], rowBuff, sizeof(rowBuff) );
00227
00228 memcpy( rowBuff, inverse[col],sizeof(rowBuff));
00229 memcpy( inverse[col], inverse[pivIdx], sizeof(rowBuff) );
00230 memcpy( inverse[pivIdx], rowBuff, sizeof(rowBuff) );
00231 }
00232
00233 for ( int c=0; c<3; ++c )
00234 {
00235 if (c>col )
00236 this->Matrix[col][c] /= this->Matrix[col][col];
00237 inverse[col][c] /= this->Matrix[col][col];
00238 }
00239 this->Matrix[col][col] = 1.0;
00240
00241 for ( int row = 0; row<3; ++row )
00242 {
00243 if (row != col )
00244 {
00245 for ( int c=0; c<3; ++c )
00246 {
00247 if ( c>col )
00248 this->Matrix[row][c] -=
00249 this->Matrix[row][col] * this->Matrix[col][c];
00250 inverse[row][c] -= this->Matrix[row][col] * inverse[col][c];
00251 }
00252 this->Matrix[row][col] = 0;
00253 }
00254 }
00255 }
00256
00257
00258 return (*this = inverse);
00259 }
00260
00261 template<class T>
00262 Matrix3x3<T>&
00263 Matrix3x3<T>::Invert3x3()
00264 {
00265 Self inverse;
00266
00267 T rowBuff[3];
00268 for ( int col = 0; col<3; ++col ) {
00269
00270 int pivIdx = col;
00271 T pivAbs = fabs( this->Matrix[col][col] );
00272
00273 for ( int row = col+1; row<3; ++row ) {
00274 T nextAbs = fabs( this->Matrix[row][col] );
00275 if (nextAbs > pivAbs ) {
00276 pivIdx = row;
00277 pivAbs = nextAbs;
00278 }
00279 }
00280
00281 if ( col != pivIdx )
00282 {
00283 memcpy( rowBuff, this->Matrix[col], sizeof(rowBuff) );
00284 memcpy( this->Matrix[col], this->Matrix[pivIdx], sizeof(rowBuff) );
00285 memcpy( this->Matrix[pivIdx], rowBuff, sizeof(rowBuff) );
00286
00287 memcpy( rowBuff, inverse[col],sizeof(rowBuff));
00288 memcpy( inverse[col], inverse[pivIdx], sizeof(rowBuff) );
00289 memcpy( inverse[pivIdx], rowBuff, sizeof(rowBuff) );
00290 }
00291
00292 for ( int c=0; c<3; ++c )
00293 {
00294 if (c>col )
00295 this->Matrix[col][c] /= this->Matrix[col][col];
00296 inverse[col][c] /= this->Matrix[col][col];
00297 }
00298 this->Matrix[col][col] = 1.0;
00299
00300 for ( int row = 0; row<3; ++row )
00301 {
00302 if (row != col )
00303 {
00304 for ( int c=0; c<3; ++c )
00305 {
00306 if ( c>col )
00307 this->Matrix[row][c] -= this->Matrix[row][col] * this->Matrix[col][c];
00308 inverse[row][c] -= this->Matrix[row][col] * inverse[col][c];
00309 }
00310 this->Matrix[row][col] = 0;
00311 }
00312 }
00313 }
00314
00315
00316 return (*this = inverse);
00317 }
00318
00319 template<class T>
00320 Matrix3x3<T>&
00321 Matrix3x3<T>::operator*=( const Self& other )
00322 {
00323 return (*this = ((*this) * other));
00324 }
00325
00326 template<class T>
00327 Matrix3x3<T>&
00328 Matrix3x3<T>::operator*=( const T scalar )
00329 {
00330 for ( int j=0; j<3; ++j )
00331 {
00332 for ( int i=0; i<3; ++i )
00333 {
00334 this->Matrix[i][j] *= scalar;
00335 }
00336 }
00337 return *this;
00338 }
00339
00340 template<class T>
00341 const Matrix3x3<T>
00342 Matrix3x3<T>::operator*
00343 ( const Self& other ) const
00344 {
00345 Self result( NULL );
00346
00347 for ( int j=0; j<3; ++j )
00348 {
00349 for ( int i=0; i<3; ++i )
00350 {
00351 result[i][j] = 0;
00352 for ( int k=0; k<3; ++k )
00353 result[i][j] += this->Matrix[i][k] * other.Matrix[k][j];
00354 }
00355 }
00356
00357 return result;
00358 }
00359
00360 template<class T>
00361 Matrix3x3<T>&
00362 Matrix3x3<T>::operator=( const Self& other )
00363 {
00364 memcpy( this->Matrix, other.Matrix, sizeof( this->Matrix ) );
00365 return *this;
00366 }
00367
00368 template<class T>
00369 T
00370 Matrix3x3<T>::FrobeniusNorm() const
00371 {
00372 T norm = 0.0;
00373 for ( int i = 0; i < 3; ++i )
00374 {
00375 for ( int j = 0; j < 3; ++j )
00376 norm += MathUtil::Square( this->Matrix[i][j] );
00377 }
00378 return sqrt( norm );
00379 }
00380
00381 template<class T>
00382 void
00383 Matrix3x3<T>::ComputeEigenvalues( T (&lambda)[3] ) const
00384 {
00385 const double M11 = this->Matrix[0][0];
00386 const double M12 = this->Matrix[0][1];
00387 const double M13 = this->Matrix[0][2];
00388 const double M22 = this->Matrix[1][1];
00389 const double M23 = this->Matrix[1][2];
00390 const double M33 = this->Matrix[2][2];
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 const double b = -M11-M22-M33;
00428 const double c = M11*M22 +M11*M33 +M22*M33 -M12*M12 -M13*M13 -M23*M23;
00429 const double d = M11*M23*M23 +M12*M12*M33 +M13*M13*M22 -2.0*M12*M13*M23 -M11*M22*M33;
00430
00431 const double b_3 = b/3.0;
00432 const double f = b_3*b_3 - c/3.0 ;
00433 const double g = b*c/6.0 - b_3*b_3*b_3 - 0.5*d;
00434
00435 if (f == 0.0 && g == 0.0)
00436 {
00437 lambda[0] = lambda[1] = lambda[2] = static_cast<T>( - b_3 );
00438 return;
00439 }
00440
00441 const double f3 = f*f*f;
00442 const double g2 = g*g;
00443 const double sqrt_f = -sqrt(f);
00444
00445
00446
00447
00448
00449
00450
00451 if (g2 >= f3)
00452 {
00453 if (g < 0.0)
00454 {
00455 lambda[0] = static_cast<T>( 2.0 * sqrt_f - b_3 );
00456 lambda[1] = lambda[2] = static_cast<T>( - sqrt_f - b_3 );
00457 }
00458 else
00459 {
00460 lambda[0] = lambda[1] = static_cast<T>( sqrt_f - b_3 );
00461 lambda[2] = static_cast<T>( -2.0 * sqrt_f - b_3 );
00462 }
00463 return;
00464 }
00465
00466
00467 const double sqrt_f3 = sqrt_f * sqrt_f * sqrt_f;
00468 const double k = acos(g / sqrt_f3) / 3.0;
00469 const double j = 2.0 * sqrt_f;
00470 lambda[0] = static_cast<T>( j * cos(k) - b_3 );
00471 lambda[1] = static_cast<T>( j * cos(k + M_PI * 2.0 / 3.0) - b_3 );
00472 lambda[2] = static_cast<T>( j * cos(k - M_PI * 2.0 / 3.0) - b_3 );
00473
00474 T tmp;
00475 if (lambda[1] < lambda[0])
00476 {
00477 tmp = lambda[1]; lambda[1] = lambda[0]; lambda[0] = tmp;
00478 }
00479
00480 if (lambda[2] < lambda[1])
00481 {
00482 tmp = lambda[1]; lambda[1] = lambda[2]; lambda[2] = tmp;
00483 if (lambda[1] < lambda[0])
00484 {
00485 tmp = lambda[1]; lambda[1] = lambda[0]; lambda[0] = tmp;
00486 }
00487 }
00488 }
00489
00490 template class Matrix3x3<float>;
00491 template class Matrix3x3<double>;
00492
00493 }