cmtkParametricPlane.cxx

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2009 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2010 SRI International
00006 //
00007 //  This file is part of the Computational Morphometry Toolkit.
00008 //
00009 //  http://www.nitrc.org/projects/cmtk/
00010 //
00011 //  The Computational Morphometry Toolkit is free software: you can
00012 //  redistribute it and/or modify it under the terms of the GNU General Public
00013 //  License as published by the Free Software Foundation, either version 3 of
00014 //  the License, or (at your option) any later version.
00015 //
00016 //  The Computational Morphometry Toolkit is distributed in the hope that it
00017 //  will be useful, but WITHOUT ANY WARRANTY; without even the implied
00018 //  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 //  GNU General Public License for more details.
00020 //
00021 //  You should have received a copy of the GNU General Public License along
00022 //  with the Computational Morphometry Toolkit.  If not, see
00023 //  <http://www.gnu.org/licenses/>.
00024 //
00025 //  $Revision: 2401 $
00026 //
00027 //  $LastChangedDate: 2010-10-05 16:09:13 -0700 (Tue, 05 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkParametricPlane.h"
00034 
00035 #include <Base/cmtkMathUtil.h>
00036 
00037 #include <math.h>
00038 
00039 namespace
00040 cmtk
00041 {
00042 
00045 
00046 ParametricPlane::ParametricPlane()
00047   : Rho( 0 ),
00048     Theta( 0 ),
00049     Phi( 0 )
00050 {
00051   this->m_Origin = Self::CoordinateVectorType( Self::CoordinateVectorType::Init( 0 ) );
00052   this->Update();
00053 }
00054 
00055 void
00056 ParametricPlane::Update()
00057 {
00058   Normal[0] = MathUtil::Cos( Theta ) * MathUtil::Sin( Phi );
00059   Normal[1] = MathUtil::Sin( Theta ) * MathUtil::Sin( Phi );
00060   Normal[2] = MathUtil::Cos( Phi );
00061   
00062   this->SquareNormal = Normal * Normal;
00063 }
00064 
00065 void
00066 ParametricPlane::SetNormal( const Self::CoordinateVectorType& normal )
00067 {
00068   this->Normal = (1.0 / normal.RootSumOfSquares()) * normal;
00069   
00070   this->Phi = MathUtil::ArcCos( this->Normal[2] );
00071 
00072   const Types::Coordinate sinPhi = MathUtil::Sin( this->Phi );
00073   if ( sinPhi != 0 )
00074     this->Theta = MathUtil::ArcSin( this->Normal[1] / sinPhi );
00075   else
00076     this->Theta = Units::Degrees( 0 );
00077 
00078   this->SquareNormal = this->Normal * this->Normal;
00079 }
00080 
00081 AffineXform* 
00082 ParametricPlane::GetAlignmentXform( const byte normalAxis ) const
00083 {
00084   Types::Coordinate angles[3] = { 0, 0, 0 };
00085   Types::Coordinate xlate[3] = { 0, 0, 0 };
00086   
00087   AffineXform *alignment = new AffineXform;
00088 
00089   switch ( normalAxis ) 
00090     {
00091     // YZ plane, i.e., normal to X
00092     case 0:
00093     {
00094     // first make y component zero.
00095     angles[2] = -1.0 * Units::Degrees( MathUtil::ArcTan2( Normal[1], Normal[0] ) ).Value();
00096     
00097     // compute x component of normal vector after first rotation; remember that y component will be zero after this rotation.
00098     const Types::Coordinate newNormal0 = MathUtil::Sign( Normal[0] ) * sqrt( 1 - Normal[2]*Normal[2] );
00099     angles[1] = -1.0 * Units::Degrees( MathUtil::ArcTan2( Normal[2], newNormal0 ) ).Value();
00100     break;
00101     }
00102 
00103     // XZ plane, normal to Y
00104     case 1:
00105     {
00106     // first make x component zero.
00107     angles[2] = -1.0 * Units::Degrees( MathUtil::ArcTan2( Normal[0], Normal[1] ) ).Value();
00108     
00109     // compute y component of normal vector after first rotation; remember that x component will be zero after this rotation.
00110     const Types::Coordinate newNormal1 = MathUtil::Sign( Normal[1] ) * sqrt( 1 - Normal[2]*Normal[2] );
00111     angles[0] = -1.0 * Units::Degrees( MathUtil::ArcTan2( Normal[2], newNormal1 ) ).Value();
00112     break;
00113     }
00114 
00115     // XY plane, normal to Z
00116     case 2:
00117     {
00118     // first make x component zero.
00119     angles[1] = -1.0 * Units::Degrees( MathUtil::ArcTan2( Normal[0], Normal[2] ) ).Value();
00120     
00121     // compute z component of normal vector after first rotation; remember that x component will be zero after this rotation.
00122     const Types::Coordinate newNormal2 = MathUtil::Sign( Normal[2] ) * sqrt( 1 - Normal[1]*Normal[1] );
00123     angles[0] = -1.0 * Units::Degrees( MathUtil::ArcTan2( Normal[1], newNormal2 ) ).Value();
00124     break;
00125     }
00126     }
00127   
00128   alignment->ChangeCenter( this->GetOrigin() );
00129   alignment->SetAngles( angles );
00130   
00131   xlate[normalAxis] = Rho;
00132   alignment->SetXlate( xlate );
00133 
00134   return alignment;
00135 }
00136 
00137 AffineXform::MatrixType
00138 ParametricPlane::GetMirrorXformMatrix() const
00139 {
00140   // put together zero-offset mirror matrix
00141   AffineXform::MatrixType M = AffineXform::MatrixType::IdentityMatrix;
00142 
00143   for ( int i = 0; i < 3; ++i ) 
00144     {
00145     for ( int j = 0; j < 3; ++j ) 
00146       {
00147       M[i][j] -= 2.0 * this->Normal[i]*this->Normal[j] / this->SquareNormal;
00148       }
00149     }
00150 
00151   FixedVector<3,Types::Coordinate> mo = this->m_Origin;
00152   mo *= M;
00153 
00154   for ( int j = 0; j < 3; ++j ) 
00155     {
00156     M[3][j] = this->m_Origin[j] - mo[j] + 2 * this->Rho * this->Normal[j] / this->SquareNormal;
00157     }
00158 
00159   return M;
00160 }
00161 
00162 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines