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 "cmtkMatrix4x4.h"
00034
00035 #include <Base/cmtkMathUtil.h>
00036 #include <Base/cmtkMatrix.h>
00037 #include <Base/cmtkQRDecomposition.h>
00038
00039 #include <System/cmtkConsole.h>
00040
00041 #include <string.h>
00042 #include <math.h>
00043 #include <vector>
00044
00045 namespace
00046 cmtk
00047 {
00048
00051
00052 template<class T>
00053 Matrix4x4<T>::Matrix4x4()
00054 {
00055 memset( Matrix, 0, sizeof( Matrix ) );
00056 Matrix[0][0] = Matrix[1][1] = Matrix[2][2] = Matrix[3][3] = 1.0;
00057 }
00058
00059 template<class T>
00060 Matrix4x4<T>::Matrix4x4( const Matrix3x3<T>& other )
00061 {
00062 for ( int j=0; j<3; ++j )
00063 {
00064 for ( int i=0; i<3; ++i )
00065 {
00066 this->Matrix[i][j] = other[i][j];
00067 }
00068 }
00069
00070 for ( int j=0; j<3; ++j )
00071 {
00072 this->Matrix[3][j] = this->Matrix[j][3] = 0.0;
00073 }
00074 this->Matrix[3][3] = 1.0;
00075 }
00076
00077 template<class T>
00078 Matrix4x4<T>&
00079 Matrix4x4<T>::Set( const T *const values )
00080 {
00081 memcpy( this->Matrix, values, sizeof( this->Matrix ) );
00082 return *this;
00083 }
00084
00085 template<class T>
00086 Matrix4x4<T>
00087 Matrix4x4<T>::GetTranspose() const
00088 {
00089 Self transpose;
00090 for ( int i = 0; i < 4; ++i )
00091 {
00092 for ( int j = 0; j < 4; ++j )
00093 transpose[i][j] = this->Matrix[j][i];
00094 }
00095 return transpose;
00096 }
00097
00098 template<class T>
00099 Matrix4x4<T>&
00100 Matrix4x4<T>::Compose
00101 ( const Types::Coordinate params[15], const bool logScaleFactors )
00102 {
00103 const Units::Radians alpha = Units::Degrees( params[3] );
00104 const Units::Radians theta = Units::Degrees( params[4] );
00105 const Units::Radians phi = Units::Degrees( params[5] );
00106
00107 const double cos0 = MathUtil::Cos(alpha), sin0 = MathUtil::Sin(alpha);
00108 const double cos1 = MathUtil::Cos(theta), sin1 = MathUtil::Sin(theta);
00109 const double cos2 = MathUtil::Cos( phi), sin2 = MathUtil::Sin( phi);
00110
00111 const double sin0xsin1 = sin0 * sin1;
00112 const double cos0xsin1 = cos0 * sin1;
00113
00114 const double scaleX = (logScaleFactors) ? exp( params[6] ) : params[6];
00115 const double scaleY = (logScaleFactors) ? exp( params[7] ) : params[7];
00116 const double scaleZ = (logScaleFactors) ? exp( params[8] ) : params[8];
00117
00118 Matrix[0][0] = static_cast<T>( cos1*cos2 * scaleX );
00119 Matrix[0][1] = static_cast<T>( -cos1*sin2 * scaleX );
00120 Matrix[0][2] = static_cast<T>( -sin1 * scaleX );
00121 Matrix[0][3] = static_cast<T>( 0 );
00122 Matrix[1][0] = static_cast<T>( (sin0xsin1*cos2 + cos0*sin2) * scaleY );
00123 Matrix[1][1] = static_cast<T>( (-sin0xsin1*sin2 + cos0*cos2) * scaleY );
00124 Matrix[1][2] = static_cast<T>( sin0*cos1 * scaleY );
00125 Matrix[1][3] = static_cast<T>( 0 );
00126 Matrix[2][0] = static_cast<T>( (cos0xsin1*cos2 - sin0*sin2) * scaleZ );
00127 Matrix[2][1] = static_cast<T>( (-cos0xsin1*sin2 - sin0*cos2) * scaleZ );
00128 Matrix[2][2] = static_cast<T>( cos0*cos1 * scaleZ );
00129 Matrix[2][3] = static_cast<T>( 0 );
00130
00131 Matrix[3][0] = Matrix[3][1] = Matrix[3][2] = static_cast<T>( 0 );
00132 Matrix[3][3] = static_cast<T>( 1.0 );
00133
00134
00135 for ( int i = 2; i >= 0; --i )
00136 {
00137 Self shear;
00138 shear[i/2][(i/2)+(i%2)+1] = params[9+i];
00139 *this *= shear;
00140 }
00141
00142
00143 const Types::Coordinate cM[3] =
00144 {
00145 params[12]*Matrix[0][0] + params[13]*Matrix[1][0] + params[14]*Matrix[2][0],
00146 params[12]*Matrix[0][1] + params[13]*Matrix[1][1] + params[14]*Matrix[2][1],
00147 params[12]*Matrix[0][2] + params[13]*Matrix[1][2] + params[14]*Matrix[2][2]
00148 };
00149
00150
00151 Matrix[3][0] = params[0] - cM[0] + params[12];
00152 Matrix[3][1] = params[1] - cM[1] + params[13];
00153 Matrix[3][2] = params[2] - cM[2] + params[14];
00154
00155 return *this;
00156 }
00157
00158 template<class T>
00159 bool
00160 Matrix4x4<T>::Decompose
00161 ( Types::Coordinate params[12], const Types::Coordinate *center, const bool logScaleFactor ) const
00162 {
00163
00164 Self matrix( *this );
00165
00166
00167 params[0] = matrix[3][0];
00168 params[1] = matrix[3][1];
00169 params[2] = matrix[3][2];
00170
00171 if ( center )
00172 {
00173 const Types::Coordinate cM[3] =
00174 {
00175 center[0]*matrix[0][0] + center[1]*matrix[1][0] + center[2]*matrix[2][0],
00176 center[0]*matrix[0][1] + center[1]*matrix[1][1] + center[2]*matrix[2][1],
00177 center[0]*matrix[0][2] + center[1]*matrix[1][2] + center[2]*matrix[2][2],
00178 };
00179
00180 params[0] += cM[0] - center[0];
00181 params[1] += cM[1] - center[1];
00182 params[2] += cM[2] - center[2];
00183
00184 if ( center != params+12)
00185 {
00186
00187 memcpy( params+12, center, 3*sizeof( Types::Coordinate ) );
00188 }
00189 }
00190 else
00191 {
00192 memset( params+12, 0, 3*sizeof( Types::Coordinate ) );
00193 }
00194
00195
00196
00197 Matrix2D<T> matrix2d( 3, 3 );
00198 for ( int i = 0; i < 3; ++i )
00199 for ( int j = 0; j < 3; ++j )
00200 matrix2d[i][j] = matrix[i][j];
00201
00202 QRDecomposition<T> qr( matrix2d );
00203 const Matrix2D<T> R = qr.GetR();
00204
00205
00206 for ( int k = 0; k<3; ++k )
00207 {
00208 const int i = k / 2;
00209 const int j = i + (k%2) + 1;
00210 params[9+k] = R[i][j] / R[i][i];
00211
00212
00213 Self shear;
00214 shear[i][j] = params[9+k];
00215 matrix *= shear.GetInverse();
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 #define VTK_AXIS_EPSILON 0.001
00261 double d;
00262 double d1;
00263 double d2;
00264 double dot;
00265 double cosPhi, sinPhi;
00266 double cosTheta, sinTheta;
00267 double cosAlpha, sinAlpha;
00268 double x2, y2, z2;
00269 double x3, y3, z3;
00270 double x3p, y3p;
00271
00272 for ( int i=0; i<3; ++i )
00273 {
00274
00275 params[6 + i] = sqrt( MathUtil::Square( matrix[i][0] ) + MathUtil::Square( matrix[i][1] ) + MathUtil::Square( matrix[i][2] ) );
00276
00277
00278 if ( fabs(params[6+i]) < VTK_AXIS_EPSILON )
00279 {
00280 StdErr <<"Matrxi4x4::Decompose encountered singular matrix.";
00281 return false;
00282 }
00283 }
00284
00285
00286 const Types::Coordinate determinant =
00287 this->Matrix[0][0]*this->Matrix[1][1]*this->Matrix[2][2] +
00288 this->Matrix[0][1]*this->Matrix[1][2]*this->Matrix[2][0] +
00289 this->Matrix[0][2]*this->Matrix[1][0]*this->Matrix[2][1] -
00290 this->Matrix[0][2]*this->Matrix[1][1]*this->Matrix[2][0] -
00291 this->Matrix[0][0]*this->Matrix[1][2]*this->Matrix[2][1] -
00292 this->Matrix[0][1]*this->Matrix[1][0]*this->Matrix[2][2];
00293
00294 if ( determinant < 0 )
00295 params[6] = -params[6];
00296
00297
00298
00299 x2 = matrix[0][1] / params[6];
00300 y2 = matrix[0][2] / params[6];
00301 z2 = matrix[0][0] / params[6];
00302
00303 x3 = matrix[2][1] / params[8];
00304 y3 = matrix[2][2] / params[8];
00305 z3 = matrix[2][0] / params[8];
00306
00307 dot = x2 * x2 + z2 * z2;
00308 d1 = sqrt (dot);
00309
00310 if (d1 < VTK_AXIS_EPSILON)
00311 {
00312 cosTheta = 1.0;
00313 sinTheta = 0.0;
00314 }
00315 else
00316 {
00317 cosTheta = z2 / d1;
00318 sinTheta = x2 / d1;
00319 }
00320
00321 params[5] = Units::Degrees( -MathUtil::ArcTan2( sinTheta, cosTheta ) ).Value();
00322
00323
00324 dot = x2 * x2 + y2 * y2 + z2 * z2;
00325 d = sqrt (dot);
00326
00327 if (d < VTK_AXIS_EPSILON)
00328 {
00329 sinPhi = 0.0;
00330 cosPhi = 1.0;
00331 }
00332 else
00333 if (d1 < VTK_AXIS_EPSILON)
00334 {
00335 sinPhi = y2 / d;
00336 cosPhi = z2 / d;
00337 }
00338 else
00339 {
00340 sinPhi = y2 / d;
00341 cosPhi = ( x2 * x2 + z2 * z2) / (d1 * d);
00342 }
00343
00344 params[4] = Units::Degrees( -MathUtil::ArcTan2( sinPhi, cosPhi ) ).Value();
00345
00346
00347 x3p = x3 * cosTheta - z3 * sinTheta;
00348 y3p = - sinPhi * sinTheta * x3 + cosPhi * y3 - sinPhi * cosTheta * z3;
00349 dot = x3p * x3p + y3p * y3p;
00350
00351 d2 = sqrt (dot);
00352 if (d2 < VTK_AXIS_EPSILON)
00353 {
00354 cosAlpha = 1.0;
00355 sinAlpha = 0.0;
00356 }
00357 else
00358 {
00359 cosAlpha = y3p / d2;
00360 sinAlpha = x3p / d2;
00361 }
00362
00363 params[3] = Units::Degrees( -MathUtil::ArcTan2( sinAlpha, cosAlpha ) ).Value();
00364
00365 if ( logScaleFactor )
00366 {
00367 for ( int i = 6; i < 9; ++i )
00368 params[i] = log( params[i] );
00369 }
00370
00371 return true;
00372
00374 }
00375
00376 template<class T>
00377 const Matrix4x4<T>
00378 Matrix4x4<T>::GetInverse() const
00379 {
00380 Self inverse;
00381 Self temp = *this;
00382
00383 T rowBuff[4];
00384 for ( int col = 0; col<4; ++col )
00385 {
00386 int pivIdx = col;
00387 T pivAbs = fabs( temp.Matrix[col][col] );
00388
00389 for ( int row = col+1; row<3; ++row )
00390 {
00391 T nextAbs = fabs( temp.Matrix[row][col] );
00392 if (nextAbs > pivAbs )
00393 {
00394 pivIdx = row;
00395 pivAbs = nextAbs;
00396 }
00397 }
00398
00399 if ( col != pivIdx )
00400 {
00401 memcpy( rowBuff, temp.Matrix[col], sizeof(rowBuff) );
00402 memcpy( temp.Matrix[col], temp.Matrix[pivIdx], sizeof(rowBuff) );
00403 memcpy( temp.Matrix[pivIdx], rowBuff, sizeof(rowBuff) );
00404
00405 memcpy( rowBuff, inverse.Matrix[col],sizeof(rowBuff));
00406 memcpy( inverse.Matrix[col], inverse.Matrix[pivIdx], sizeof(rowBuff) );
00407 memcpy( inverse.Matrix[pivIdx], rowBuff, sizeof(rowBuff) );
00408 }
00409
00410 for ( int c=0; c<4; ++c )
00411 {
00412 if (c>col )
00413 temp.Matrix[col][c] /= temp.Matrix[col][col];
00414 inverse.Matrix[col][c] /= temp.Matrix[col][col];
00415 }
00416 temp.Matrix[col][col] = 1.0;
00417
00418 for ( int row = 0; row<4; ++row )
00419 {
00420 if (row != col )
00421 {
00422 for ( int c=0; c<4; ++c )
00423 {
00424 if ( c>col )
00425 temp.Matrix[row][c] -= temp.Matrix[row][col] * temp.Matrix[col][c];
00426 inverse.Matrix[row][c] -= temp.Matrix[row][col] * inverse.Matrix[col][c];
00427 }
00428 temp.Matrix[row][col] = 0;
00429 }
00430 }
00431 }
00432
00433 return inverse;
00434 }
00435
00436 template<class T>
00437 Matrix4x4<T>&
00438 Matrix4x4<T>::operator*=( const Self& other )
00439 {
00440 return (*this = ((*this) * other));
00441 }
00442
00443 template<class T>
00444 const Matrix4x4<T>
00445 Matrix4x4<T>::operator*
00446 ( const Self& other ) const
00447 {
00448 Self result( NULL );
00449
00450 for ( int j=0; j<4; ++j )
00451 {
00452 for ( int i=0; i<4; ++i )
00453 {
00454 result[i][j] = 0;
00455 for ( int k=0; k<4; ++k )
00456 result[i][j] += this->Matrix[i][k] * other.Matrix[k][j];
00457 }
00458 }
00459
00460 return result;
00461 }
00462
00463 template<class T>
00464 Matrix4x4<T>&
00465 Matrix4x4<T>::operator=( const Matrix3x3<T>& other )
00466 {
00467 for ( int j=0; j<3; ++j )
00468 {
00469 for ( int i=0; i<3; ++i )
00470 {
00471 this->Matrix[i][j] = other[i][j];
00472 }
00473 }
00474
00475 for ( int j=0; j<3; ++j )
00476 {
00477 this->Matrix[3][j] = this->Matrix[j][3] = 0.0;
00478 }
00479 this->Matrix[3][3] = 1.0;
00480
00481 return *this;
00482 }
00483
00484 template<class T>
00485 Matrix4x4<T>&
00486 Matrix4x4<T>::ChangeCoordinateSystem
00487 ( const FixedVector<3,T>& newX, const FixedVector<3,T>& newY )
00488 {
00489
00490 Self rotate = RotateX( -atan2( newX[1], newX[2] ) );
00491 rotate *= RotateY( acos( newX[0] ) );
00492
00493
00494 const FixedVector<3,T> newYrot = newY * rotate;
00495 rotate *= RotateX( atan2( newYrot[2], newYrot[1] ) );
00496
00497
00498
00499
00500
00501 *this *= rotate;
00502 *this = rotate.GetInverse() * *this;
00503
00504 return *this;
00505 }
00506
00507
00508 template<class T>
00509 Matrix4x4<T>
00510 Matrix4x4<T>::RotateX( const T angle )
00511 {
00512 Self rot;
00513 rot[1][1] = rot[2][2] = cos( angle );
00514 rot[1][2] = -1.0 * (rot[2][1] = sin( angle ) );
00515
00516 return rot;
00517 }
00518
00519 template<class T>
00520 Matrix4x4<T>
00521 Matrix4x4<T>::RotateY( const T angle )
00522 {
00523 Self rot;
00524 rot[0][0] = rot[2][2] = cos( angle );
00525 rot[0][2] = -1.0 * (rot[2][0] = sin( angle ) );
00526
00527 return rot;
00528 }
00529
00530 template<class T>
00531 Matrix4x4<T>
00532 Matrix4x4<T>::RotateZ( const T angle )
00533 {
00534 Self rot;
00535 rot[0][0] = rot[1][1] = cos( angle );
00536 rot[0][1] = -1.0 * (rot[1][0] = sin( angle ) );
00537
00538 return rot;
00539 }
00540
00541 template<class T>
00542 T
00543 Matrix4x4<T>::FrobeniusNorm() const
00544 {
00545 T norm = 0.0;
00546 for ( int i = 0; i < 4; ++i )
00547 {
00548 for ( int j = 0; j < 4; ++j )
00549 norm += MathUtil::Square( this->Matrix[i][j] );
00550 }
00551 return sqrt( norm );
00552 }
00553
00554 template class Matrix4x4<Types::Coordinate>;
00555
00556 }