cmtkUniformVolume.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 __cmtkUniformVolume_h_included_
00034 #define __cmtkUniformVolume_h_included_
00035 
00036 #include <cmtkconfig.h>
00037 
00038 #include <Base/cmtkVolume.h>
00039 
00040 #include <System/cmtkSmartPtr.h>
00041 #include <System/cmtkSmartConstPtr.h>
00042 
00043 #include <algorithm>
00044 
00045 namespace
00046 cmtk
00047 {
00048 
00051 
00053 class VolumeGridToGridLookup;
00054 
00058 class UniformVolume : 
00060   public Volume 
00061 {
00062 public:
00064   typedef UniformVolume Self;
00065 
00067   typedef Volume Superclass;
00068 
00070   typedef SmartPointer<Self> SmartPtr;
00071 
00073   typedef SmartConstPointer<Self> SmartConstPtr;
00074 
00076   typedef Superclass:: CoordinateRegionType CoordinateRegionType;
00077 
00079   typedef Superclass::CoordinateVectorType CoordinateVectorType;
00080 
00082   CoordinateVectorType m_Delta; 
00083 
00085   const CoordinateVectorType& Deltas() const
00086   {
00087     return this->m_Delta;
00088   }
00089 
00091   CoordinateVectorType& Deltas()
00092   {
00093     return this->m_Delta;
00094   }
00095 
00097   virtual ~UniformVolume() {}
00098 
00106   UniformVolume( const UniformVolume& other, const Types::Coordinate resolution = 0, const bool allowUpsampling = false );
00107 
00113   UniformVolume( const DataGrid::IndexType& dims, const Self::CoordinateVectorType& size, TypedArray::SmartPtr& data = TypedArray::SmartPtr::Null );
00114 
00122   UniformVolume( const DataGrid::IndexType& dims, const Types::Coordinate deltaX, const Types::Coordinate deltaY, const Types::Coordinate deltaZ, TypedArray::SmartPtr& data = TypedArray::SmartPtr::Null );
00123 
00125   bool GridMatches( const Self& other ) const
00126   {
00127     return Superclass::GridMatches( other ) && ((this->m_Delta-other.m_Delta).MaxAbsValue() < 1e-5) && ((this->m_Offset-other.m_Offset).MaxAbsValue() < 1e-5);
00128   }
00129 
00137   AffineXform::MatrixType m_IndexToPhysicalMatrix;
00138 
00143   virtual void ChangeCoordinateSpace( const std::string& newSpace );
00144   
00147   std::string GetOrientationFromDirections() const;
00148 
00152   virtual void CreateDefaultIndexToPhysicalMatrix();
00153 
00158   virtual AffineXform::MatrixType GetImageToPhysicalMatrix() const;
00159 
00163   Self::SmartPtr Clone( const bool copyData )
00164   {
00165     return Self::SmartPtr( this->CloneVirtual( copyData ) );
00166   }
00167 
00168   Self::SmartPtr Clone() const
00169   {
00170     return Self::SmartPtr( this->CloneVirtual() );
00171   }
00172 
00174   Self::SmartPtr CloneGrid() const
00175   {
00176     return Self::SmartPtr( this->CloneGridVirtual() );
00177   }
00178 
00180   virtual Types::Coordinate GetDelta( const int axis ) const
00181   {
00182     return this->m_Delta[axis];
00183   }
00184 
00189   virtual Types::Coordinate GetMinDelta () const 
00190   {
00191     return this->m_Delta.MinValue();
00192   }
00193   
00198   virtual Types::Coordinate GetMaxDelta () const 
00199   {
00200     return this->m_Delta.MaxValue();
00201   }
00202 
00210   virtual TypedArray::SmartPtr Resample ( const UniformVolume& ) const;
00211 
00213   const UniformVolume::SmartPtr GetReoriented ( const char* newOrientation = AnatomicalOrientation::ORIENTATION_STANDARD ) const;
00214 
00221   virtual UniformVolume* GetDownsampledAndAveraged( const int downsample, const bool approxIsotropic = false ) const;
00222  
00226   virtual UniformVolume* GetDownsampledAndAveraged( const int (&downsample)[3] ) const;
00227 
00233   UniformVolume* GetInterleavedSubVolume( const int axis, const int factor, const int idx ) const;
00234 
00240   UniformVolume* GetInterleavedPaddedSubVolume( const int axis, const int factor, const int idx ) const;
00241 
00243   virtual void Mirror ( const int axis = AXIS_X );
00244 
00251   virtual ScalarImage* GetOrthoSlice( const int axis, const unsigned int plane ) const;
00252 
00255   Self::SmartPtr ExtractSlice( const int axis, const int plane ) const
00256   {
00257     return Self::SmartPtr( this->ExtractSliceVirtual( axis, plane ) );
00258   }
00259 
00266   virtual ScalarImage* GetOrthoSliceInterp( const int axis, const Types::Coordinate location ) const;
00267 
00274   virtual ScalarImage* GetNearestOrthoSlice( const int axis, const Types::Coordinate location ) const;
00275 
00282   virtual const Self::CoordinateVectorType GetGradientAt( const int i, const int j, const int k );
00283 
00290   virtual void GetHessianAt( Matrix3x3<Types::DataItem>& H, const int i, const int j, const int k );
00291 
00293   template<class TData> inline bool ProbeData( TData& result, const TData* dataPtr, const Self::CoordinateVectorType& location ) const;
00294 
00296   inline bool ProbeNoXform ( ProbeInfo&, const Self::CoordinateVectorType& ) const;
00297 
00310   inline bool FindVoxel( const Self::CoordinateVectorType& location, int *const idx, Types::Coordinate *const from, Types::Coordinate *const to ) const;
00311   
00322   inline bool FindVoxel( const Self::CoordinateVectorType& location, int *const idx ) const;
00323 
00331   inline void GetVoxelIndexNoBounds( const Self::CoordinateVectorType& location, int *const idx ) const;
00332 
00341   inline bool FindVoxelByIndex( const Self::CoordinateVectorType& fracIndex, int *const idx, Types::Coordinate *const frac ) const;
00342 
00344   const UniformVolume::RegionType GetGridRange( const Self::CoordinateVectorType& fromVOI, const Self::CoordinateVectorType& toVOI ) const;
00345  
00347   virtual Types::Coordinate GetPlaneCoord( const int axis, const int plane ) const 
00348   {
00349     return this->m_Offset[axis] + plane * this->m_Delta[axis];
00350   }
00351 
00356   virtual int GetCoordIndex( const int axis, const Types::Coordinate location ) const 
00357   {
00358     return std::max<int>( 0, std::min<int>( (int) ((location-this->m_Offset[axis]) / this->m_Delta[axis]), this->m_Dims[axis]-1 ) );
00359   }
00360   
00365   virtual int GetClosestCoordIndex( const int axis, const Types::Coordinate location ) const 
00366   {
00367     const int idx = (int)MathUtil::Round((location-this->m_Offset[axis]) / this->m_Delta[axis]);
00368     return std::max<int>( 0, std::min<int>( idx, this->m_Dims[axis]-1 ) );
00369   }
00370 
00374   virtual bool GetClosestGridPointIndex( const Self::CoordinateVectorType v, int *const xyz ) const 
00375   {
00376     for ( int dim = 0; dim < 3; ++dim )
00377       {
00378       xyz[dim] = (int) MathUtil::Round((v[dim]-this->m_Offset[dim]) / this->m_Delta[dim]);
00379       if ( (xyz[dim] < 0) || ( xyz[dim] > this->m_Dims[dim]-1) )
00380         return false;
00381       }
00382     return true;
00383   }
00384 
00389   virtual int GetTruncCoordIndex( const int axis, const Types::Coordinate location ) const 
00390   {
00391     const int idx = static_cast<int>((location-this->m_Offset[axis]) / this->m_Delta[axis]);
00392     return std::max<int>( 0, std::min<int>( idx, this->m_Dims[axis]-1 ) );
00393   }
00394 
00398   virtual bool GetTruncGridPointIndex( const Self::CoordinateVectorType v , 
00399                                        int *const xyz  ) const 
00400   {
00401     for ( int dim = 0; dim < 3; ++dim )
00402       {
00403       xyz[dim] = static_cast<int>((v[dim]-this->m_Offset[dim]) / this->m_Delta[dim]);
00404       if ( (xyz[dim] < 0) || ( xyz[dim] > this->m_Dims[dim]-1) )
00405         return false;
00406       }
00407     return true;
00408   }
00409 
00415   virtual const Self::CoordinateVectorType GetGridLocation( const int x, const int y, const int z ) const 
00416   {
00417     const Types::Coordinate loc[3] = { this->m_Offset[0] + x * this->m_Delta[0], this->m_Offset[1] + y * this->m_Delta[1], this->m_Offset[2] + z * this->m_Delta[2] };
00418     return Self::CoordinateVectorType( loc );
00419   }
00420   
00426   virtual const Self::CoordinateVectorType IndexToPhysical( const Self::CoordinateVectorType& idxV ) const 
00427   {
00428     const Self::CoordinateVectorType v( idxV );
00429     return v * this->m_IndexToPhysicalMatrix;
00430   }
00431   
00439   virtual const Self::CoordinateVectorType GetGridLocation( const size_t idx ) const 
00440   {
00441     const Types::Coordinate loc[3] = { this->m_Offset[0] +  (idx % this->nextJ) * this->m_Delta[0], 
00442                                        this->m_Offset[1] +  (idx % this->nextK) / this->nextJ * this->m_Delta[1], 
00443                                        this->m_Offset[2] +  (idx / this->nextK) * this->m_Delta[2] };
00444     return Self::CoordinateVectorType( loc );
00445   }
00446 
00448 
00451   void SetHighResCropRegion( const Self::CoordinateRegionType& crop );
00452 
00455   const Self::CoordinateRegionType GetHighResCropRegion() const;
00456 
00458   virtual void SetCropRegion( const Self::RegionType& region )
00459   {
00460     this->m_HighResCropRegion = Self::CoordinateRegionType::SmartPtr( NULL );
00461     Superclass::SetCropRegion( region );
00462   }
00463 
00467   Self::CoordinateVectorType GetCenterCropRegion() const 
00468   {
00469     const Self::CoordinateRegionType region = this->GetHighResCropRegion();
00470     return 0.5 * ( region.From() + region.To() );
00471   }
00472   
00475   Self::SmartPtr GetCroppedVolume() const;
00476 
00483   template<class TAccumulator>
00484   ScalarImage* ComputeProjection( const int axis ) const;
00485   
00487   virtual Self::CoordinateVectorType GetCenterOfMass() const
00488   {
00489     Self::CoordinateVectorType com = this->Superclass::GetCenterOfMassGrid();
00490     for ( int dim = 0; dim < 3; ++dim )
00491       (com[dim] *= this->m_Delta[dim]) += this->m_Offset[dim];
00492     return com;
00493   }
00494   
00496   virtual Self::CoordinateVectorType GetCenterOfMass( Self::CoordinateVectorType& firstOrderMoment ) const
00497   {
00498     Self::CoordinateVectorType com = this->Superclass::GetCenterOfMassGrid( firstOrderMoment );
00499     for ( int dim = 0; dim < 3; ++dim )
00500       {
00501       (com[dim] *= this->m_Delta[dim]) += this->m_Offset[dim];
00502       firstOrderMoment[dim] *= this->m_Delta[dim];
00503       }
00504     return com;
00505   }
00506 
00515   void GetPrincipalAxes( Matrix3x3<Types::Coordinate>& directions, Self::CoordinateVectorType& centerOfMass ) const;
00516 
00517 protected:
00521   virtual Self* CloneVirtual( const bool copyData );
00522   virtual Self* CloneVirtual() const;
00523 
00525   virtual Self* CloneGridVirtual() const;
00526 
00527 private:
00534   Self::CoordinateRegionType::SmartPtr m_HighResCropRegion;
00535 
00540   friend class WarpXform;
00541   
00543   friend class VolumeAxesHash;
00544 
00546   friend class VolumeGridToGridLookup;
00547 
00548   class ResampleThreadInfo;
00549 
00551   friend class ResampleThreadInfo;
00552 
00558   class ResampleTaskInfo :
00559     public ThreadParameters<const Self> 
00560   {
00561   public:
00563     Types::DataItem *ResampledData;
00565     const VolumeGridToGridLookup *GridLookup;
00567     const Self* OtherVolume;
00569     const TypedArray* FromData;
00570   };
00571 
00573   static void ResampleThreadPoolExecuteGrey( void *const arg, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t threadCnt );
00574 
00576   static void ResampleThreadPoolExecuteLabels( void *const arg, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t threadCnt );
00577 
00580   virtual Self* ExtractSliceVirtual( const int axis, const int plane ) const;
00581 };
00582 
00584 
00585 } // namespace cmtk
00586 
00587 #include "cmtkUniformVolume.txx"
00588 
00589 #endif // #ifndef __cmtkUniformVolume_h_included_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines