cmtkSplineWarpXform.h

Go to the documentation of this file.
00001 /*
00002 //
00003 //  Copyright 1997-2010 Torsten Rohlfing
00004 //
00005 //  Copyright 2004-2011 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: 2752 $
00026 //
00027 //  $LastChangedDate: 2011-01-17 11:33:31 -0800 (Mon, 17 Jan 2011) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #ifndef __cmtkSplineWarpXform_h_included_
00034 #define __cmtkSplineWarpXform_h_included_
00035 
00036 #include <cmtkconfig.h>
00037 
00038 #include <Base/cmtkWarpXform.h>
00039 #include <Base/cmtkVector.h>
00040 #include <Base/cmtkAffineXform.h>
00041 #include <Base/cmtkCubicSpline.h>
00042 
00043 #include <cassert>
00044 #include <vector>
00045 #include <algorithm>
00046   
00047 #include <System/cmtkSmartPtr.h>
00048 #include <System/cmtkThreads.h>
00049 
00050 namespace
00051 cmtk
00052 {
00053 
00056 
00059 class SplineWarpXform :
00061   public WarpXform 
00062 {
00063 public:
00065   typedef SplineWarpXform Self;
00066 
00068   typedef WarpXform Superclass;
00069 
00071   typedef SmartPointer<Self> SmartPtr;
00072 
00074   typedef SmartConstPointer<Self> SmartConstPtr;
00075 
00080   SplineWarpXform();
00081 
00084   SplineWarpXform( const FixedVector<3,Types::Coordinate>& domain, const Types::Coordinate delta, const AffineXform *initialXform = NULL, const bool exactDelta = false );
00085 
00088   void Init( const Self::SpaceVectorType& domain, const Types::Coordinate delta, const AffineXform *initialXform = NULL, const bool exactDelta = false );
00089   
00092   SplineWarpXform( const FixedVector<3,Types::Coordinate>& domain, const Self::IndexType& dims, CoordinateVector::SmartPtr& parameters, const AffineXform *initialXform = NULL );
00093 
00095   Self::SmartPtr Clone () const 
00096   {
00097     return Self::SmartPtr( this->CloneVirtual() );
00098   }
00099 
00101   void InitControlPoints( const AffineXform* affineXform = NULL );
00102 
00104   virtual void Update( const bool exactDelta = false );
00105 
00110   virtual SplineWarpXform* MakeInverse() const 
00111   {
00112     return NULL;
00113   }
00114   
00116   virtual void Refine();
00117 
00119   virtual Types::Coordinate GetGridEnergy() const;
00120 
00124   virtual Types::Coordinate GetGridEnergy( const Types::Coordinate *cp ) const;
00125 
00128   virtual Types::Coordinate GetGridEnergy( const Self::SpaceVectorType& v ) const;
00129 
00131   virtual void GetGridEnergyDerivative( double& lower, double& upper, const int param, const Types::Coordinate step ) const;
00132 
00134   virtual Types::Coordinate GetJacobianDeterminant ( const Self::SpaceVectorType& v ) const;
00135 
00137   virtual Types::Coordinate GetJacobianDeterminant ( const int x, const int y, const int z ) const;
00138 
00140   virtual void GetJacobianDeterminantRow( double *const values, const int x, const int y, const int z, const size_t numberOfPoints = 1 ) const;
00141 
00151   Types::Coordinate JacobianDeterminant ( const Types::Coordinate *cp ) const;
00152 
00154   virtual Types::Coordinate GetJacobianConstraint() const;
00155 
00157   virtual Types::Coordinate GetJacobianFoldingConstraint() const;
00158 
00163   virtual void RelaxToUnfold();
00164 
00166   virtual Types::Coordinate GetRigidityConstraint() const;
00167 
00169   virtual Types::Coordinate GetRigidityConstraint( const DataGrid* weightMap ) const;
00170 
00178   virtual Types::Coordinate GetJacobianConstraintSparse() const;
00179 
00182   virtual Types::Coordinate GetRigidityConstraintSparse() const;
00183 
00185   virtual void GetJacobianConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step ) const;
00186 
00188   virtual void GetJacobianFoldingConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step ) const;
00189 
00191   virtual void GetJacobianConstraintDerivative( double& lower, double& upper, const int param, const Types::Coordinate step ) const;
00192   
00194   virtual void GetRigidityConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step ) const;
00195   
00197   virtual void GetRigidityConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step,
00198                                                 const DataGrid* weightMap ) const;
00199 
00201   virtual void GetRigidityConstraintDerivative( double& lower, double& upper, const int param, const Types::Coordinate step ) const;
00202 
00205   virtual Types::Coordinate GetInverseConsistencyError( const WarpXform* inverse, const UniformVolume* volume, const UniformVolume::RegionType* voi = NULL ) const;
00206   
00215   virtual bool ApplyInverse ( const Self::SpaceVectorType& v, Self::SpaceVectorType& u, const Types::Coordinate accuracy = 0.01  ) const;
00216 
00225   virtual bool ApplyInverseInPlace( Self::SpaceVectorType& v, const Types::Coordinate accuracy = 0.01  ) const;
00226 
00241   virtual bool ApplyInverseInPlaceWithInitial( Self::SpaceVectorType& v, const Self::SpaceVectorType& initial, const Types::Coordinate accuracy = 0.01 ) const;
00242 
00244   virtual void ApplyInPlace( Self::SpaceVectorType& v ) const 
00245   {
00246     Types::Coordinate r[3], f[3];
00247     int grid[3];
00248     
00249     // Do some precomputations.
00250     { 
00251     for ( int dim = 0; dim<3; ++dim ) 
00252       {
00253       // This is the (real-valued) index of the control point grid cell the
00254       // given location is in.
00255       r[dim] = this->InverseSpacing[dim] * v[dim];
00256       // This is the actual cell index.
00257       grid[dim] = std::min<int>( static_cast<int>( r[dim] ), this->m_Dims[dim]-4 );
00258       // And here's the relative position within the cell.
00259       f[dim] = r[dim] - grid[dim];
00260       }
00261     }
00262 
00263     // Create a pointer to the front-lower-left corner of the c.p.g. cell.
00264     const Types::Coordinate* coeff = this->m_Parameters + 3 * ( grid[0] + this->m_Dims[0] * (grid[1] + this->m_Dims[1] * grid[2]) );
00265 
00266     for ( int dim = 0; dim<3; ++dim ) 
00267       {
00268       Types::Coordinate mm = 0;
00269       const Types::Coordinate *coeff_mm = coeff;
00270       
00271       // Loop over 4 c.p.g. planes in z-direction.
00272       for ( int m = 0; m < 4; ++m ) 
00273         {
00274         Types::Coordinate ll = 0;
00275         const Types::Coordinate *coeff_ll = coeff_mm;
00276         
00277         // Loop over 4 c.p.g. planes in y-direction.
00278         for ( int l = 0; l < 4; ++l ) 
00279           {
00280           Types::Coordinate kk = 0;
00281           const Types::Coordinate *coeff_kk = coeff_ll;
00282           
00283           // Loop over 4 c.p.g. planes in x-direction.
00284           for ( int k = 0; k < 4; ++k, coeff_kk+=3 ) 
00285             {
00286             kk += CubicSpline::ApproxSpline( k, f[0] ) * (*coeff_kk);
00287             }
00288           ll += CubicSpline::ApproxSpline( l, f[1] ) * kk;
00289           coeff_ll += nextJ;
00290           }     
00291         mm += CubicSpline::ApproxSpline( m, f[2] ) * ll;
00292         coeff_mm += nextK;
00293         }
00294       v[dim] = mm;
00295       ++coeff;
00296       }
00297   }
00298 
00300   virtual void GetVolumeOfInfluence( const size_t idx, const Self::SpaceVectorType&, const Self::SpaceVectorType&, Self::SpaceVectorType&, Self::SpaceVectorType&, const int = -1 ) const;
00301   
00303   void RegisterVolume( const UniformVolume* volume )
00304   {
00305     this->RegisterVolumePoints( volume->m_Dims, volume->m_Delta, volume->m_Offset );
00306   }
00307 
00309   void UnRegisterVolume();
00310   
00312   void GetTransformedGrid( Self::SpaceVectorType& v, const int idxX, const int idxY, const int idxZ ) const;
00313   
00315   void GetTransformedGridRow( const int numPoints, Self::SpaceVectorType *const v, const int idxX, const int idxY, const int idxZ ) const;
00316   
00318   virtual Types::Coordinate GetParamStep( const size_t idx, const Self::SpaceVectorType& volSize, const Types::Coordinate mmStep = 1 ) const 
00319   {
00320     return 4 * WarpXform::GetParamStep( idx, volSize, mmStep );
00321   }
00322   
00330   virtual Self::SpaceVectorType& GetDeformedControlPointPosition( Self::SpaceVectorType&, const int, const int, const int ) const;
00331   
00338   Types::Coordinate* GetPureDeformation( const bool includeScale = false ) const;
00339 
00341   virtual CoordinateMatrix3x3 GetJacobian( const Self::SpaceVectorType& v ) const;
00342 
00344   virtual void GetJacobian( const Self::SpaceVectorType& v, CoordinateMatrix3x3& J ) const;
00345 
00347   virtual void GetJacobianAtControlPoint( const Types::Coordinate* cp, CoordinateMatrix3x3& J ) const;
00348 
00350   virtual void GetJacobianRow( CoordinateMatrix3x3 *const array, const int x, const int y, const int z, const size_t numberOfPoints ) const;
00351   
00352 private:
00354   void RegisterVolumePoints ( const DataGrid::IndexType&, const Self::SpaceVectorType& );
00355 
00357   void RegisterVolumePoints( const DataGrid::IndexType&, const Self::SpaceVectorType&, const Self::SpaceVectorType& );
00358 
00360   void RegisterVolumeAxis ( const DataGrid::IndexType::ValueType, const Types::Coordinate delta, const Types::Coordinate origin, const int, const Types::Coordinate, 
00361                             std::vector<int>& g, std::vector<Types::Coordinate>& spline, std::vector<Types::Coordinate>& dspline );
00362 
00364   Types::Coordinate GetRigidityConstraint( const CoordinateMatrix3x3& J ) const;
00365 
00366 protected:
00368   virtual SplineWarpXform* CloneVirtual () const;
00369 
00371   DataGrid::IndexType VolumeDims;
00372 
00378 
00379   std::vector<int> gX;
00381   std::vector<int> gY;
00383   std::vector<int> gZ;
00385 
00391 
00392   std::vector<Types::Coordinate> splineX;
00394   std::vector<Types::Coordinate> splineY;
00396   std::vector<Types::Coordinate> splineZ;
00398 
00404 
00405   std::vector<Types::Coordinate> dsplineX;
00407   std::vector<Types::Coordinate> dsplineY;
00409   std::vector<Types::Coordinate> dsplineZ;
00411 
00413   int GridPointOffset[48];
00414 
00419   void Init ();
00420 
00426   typedef struct 
00427   {
00429     const SplineWarpXform *thisObject;
00431     int ThisThreadIndex;
00433     int NumberOfThreads;
00435     Types::Coordinate Constraint;
00436   } JacobianConstraintThreadInfo;
00437   
00439   static void GetJacobianConstraintThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t );
00440 
00442   static void GetJacobianFoldingConstraintThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t );
00443 
00445   void FindClosestControlPoint( const Self::SpaceVectorType& v, Self::SpaceVectorType& cp ) const;
00446 
00448   friend class SplineWarpXformUniformVolume;
00449 };
00450 
00451 } // namespace
00452 
00453 #endif // #ifndef __cmtkSplineWarpXform_h_included_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines