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 #ifndef __cmtkDataGrid_h_included_
00034 #define __cmtkDataGrid_h_included_
00035
00036 #include <cmtkconfig.h>
00037
00038 #include <Base/cmtkMacros.h>
00039 #include <Base/cmtkTypes.h>
00040 #include <Base/cmtkTypedArray.h>
00041 #include <Base/cmtkFixedVector.h>
00042 #include <Base/cmtkScalarImage.h>
00043 #include <Base/cmtkRegion.h>
00044 #include <Base/cmtkMetaInformationObject.h>
00045 #include <Base/cmtkAnatomicalOrientation.h>
00046
00047 #include <System/cmtkSmartPtr.h>
00048 #include <System/cmtkThreads.h>
00049
00050 #include <vector>
00051
00052 namespace
00053 cmtk
00054 {
00055
00058
00066 class DataGrid :
00068 public MetaInformationObject
00069 {
00070 public:
00072 typedef DataGrid Self;
00073
00075 typedef SmartPointer<Self> SmartPtr;
00076
00078 typedef SmartConstPointer<Self> SmartConstPtr;
00079
00081 typedef Region<3,int> RegionType;
00082
00084 typedef RegionType::IndexType IndexType;
00085
00087 typedef FixedVector<3,Types::Coordinate> SpaceVectorType;
00088
00090 Self::IndexType m_Dims;
00091
00093 cmtkGetSetMacro(TypedArray::SmartPtr,Data);
00094
00095 public:
00097 DataGrid() :
00098 m_Data( NULL )
00099 {}
00100
00102 DataGrid( const Self::IndexType& dims, TypedArray::SmartPtr& data = TypedArray::SmartPtr::Null )
00103 : m_Dims( dims ),
00104 m_Data( data )
00105 {
00106 this->m_CropRegion = this->GetWholeImageRegion();
00107 }
00108
00110 virtual ~DataGrid() {}
00111
00113 bool GridMatches( const Self& other ) const
00114 {
00115 return (this->m_Dims == other.m_Dims);
00116 }
00117
00119 virtual DataGrid* GetDownsampledAndAveraged( const int (&downsample)[3] ) const;
00120
00143 const DataGrid::SmartPtr GetReoriented( const char* newOrientation = AnatomicalOrientation::ORIENTATION_STANDARD ) const;
00144
00149 void SetDims( const Self::IndexType& dims );
00150
00152 const Self::IndexType GetDims() const
00153 {
00154 return this->m_Dims;
00155 }
00156
00161 virtual TypedArray::SmartPtr CreateDataArray( const ScalarDataType dataType, const bool setToZero = false );
00162
00164 size_t GetNumberOfPixels () const { return this->m_Dims[0]*this->m_Dims[1]*this->m_Dims[2]; }
00165
00167 bool IndexIsInRange( const int x, const int y, const int z ) const
00168 {
00169 return (x>=0) && (x<this->m_Dims[0]) && (y>=0) && (y<this->m_Dims[1]) && (z>=0) && (z<this->m_Dims[2]);
00170 }
00171
00173 size_t GetOffsetFromIndex( const int x, const int y, const int z ) const
00174 {
00175 return x + nextJ * y + nextK * z;
00176 }
00177
00179 void GetIndexFromOffset( const size_t offset, int& x, int& y, int& z ) const
00180 {
00181 z = offset / nextK;
00182 y = (offset % nextK) / nextJ;
00183 x = (offset % nextK) % nextJ;
00184 }
00185
00187 bool GetDataAt ( Types::DataItem& data, const size_t offset ) const
00188 {
00189 return this->m_Data->Get( data, offset );
00190 }
00191
00193 void SetDataAt ( const Types::DataItem data, const size_t offset )
00194 {
00195 this->m_Data->Set( data, offset );
00196 }
00197
00199 bool GetDataAt ( Types::DataItem& data, const int x, const int y, const int z ) const
00200 {
00201 return this->GetDataAt( data, this->GetOffsetFromIndex( x, y, z ) );
00202 }
00203
00205 void SetDataAt ( const Types::DataItem data, const int x, const int y, const int z )
00206 {
00207 this->SetDataAt( data, this->GetOffsetFromIndex( x, y, z ) );
00208 }
00209
00211 Types::DataItem GetDataAt ( const int x, const int y, const int z, const Types::DataItem defaultValue = 0.0 ) const
00212 {
00213 Types::DataItem value;
00214 if ( this->GetDataAt( value, this->GetOffsetFromIndex( x, y, z ) ) )
00215 return value;
00216 else
00217 return defaultValue;
00218 }
00219
00221 Types::DataItem GetDataAt ( const size_t offset, const Types::DataItem defaultValue = 0.0 ) const
00222 {
00223 Types::DataItem value;
00224 if ( this->GetDataAt( value, offset ) )
00225 return value;
00226 else
00227 return defaultValue;
00228 }
00229
00234 TypedArray::SmartPtr GetDataMirrorPlane( const int axis = AXIS_X ) const;
00235
00237 void ApplyMirrorPlane( const int axis = AXIS_X );
00238
00239 private:
00241 static void MirrorPlaneInPlace( TypedArray& data, const Self::IndexType& dims, const int axis = AXIS_X );
00242
00243 public:
00246 Self::RegionType& CropRegion()
00247 {
00248 return this->m_CropRegion;
00249 }
00250
00255 virtual void SetCropRegion( const Self::RegionType& region );
00256
00259 const Self::RegionType& CropRegion() const
00260 {
00261 return this->m_CropRegion;
00262 }
00263
00266 int GetCropRegionNumVoxels() const;
00267
00269 const RegionType GetWholeImageRegion() const;
00270
00272 const Self::IndexType GetCropRegionIncrements() const;
00273
00281 void AutoCrop( const Types::DataItem threshold, const bool recrop = false, const int margin = 0 );
00282
00284 void FillCropBackground( const Types::DataItem value );
00285
00287 TypedArray::SmartPtr GetCroppedData() const;
00288
00290 int GetNextI() const { return nextI; }
00291 int GetNextJ() const { return nextJ; }
00292 int GetNextK() const { return nextK; }
00293 int GetNextIJ() const { return nextIJ; }
00294 int GetNextIK() const { return nextIK; }
00295 int GetNextJK() const { return nextJK; }
00296 int GetNextIJK() const { return nextIJK; }
00297
00299 virtual FixedVector<3,Types::Coordinate> GetCenterOfMassGrid() const;
00300
00302 virtual FixedVector<3,Types::Coordinate> GetCenterOfMassGrid( FixedVector<3,Types::Coordinate>& firstOrderMoment ) const;
00303
00305 template<class TAccumulator>
00306 ScalarImage* ComputeProjection( const int axis ) const;
00307
00310 virtual ScalarImage* GetOrthoSlice( const int axis, const unsigned int plane ) const;
00311
00314 Self::SmartPtr ExtractSlice( const int axis, const int plane ) const
00315 {
00316 return Self::SmartPtr( this->ExtractSliceVirtual( axis, plane ) );
00317 }
00318
00321 virtual void SetOrthoSlice( const int axis, const unsigned int idx, const ScalarImage* slice );
00322
00324 TypedArray::SmartPtr GetDataMirrored( const int axis = AXIS_X ) const;
00325
00327 void Print() const;
00328
00329 protected:
00346 bool TrilinearInterpolation( Types::DataItem& data, const int x, const int y, const int z, const Self::SpaceVectorType& location, const Types::Coordinate* cellFrom, const Types::Coordinate* cellTo ) const;
00347
00364 template<class TData>
00365 inline TData TrilinearInterpolation
00366 ( const TData* dataPtr, const int x, const int y, const int z, const Self::SpaceVectorType& gridPosition, const Types::Coordinate* cellFrom, const Types::Coordinate* cellTo ) const;
00367
00372 template<class TData,class TOutputIterator>
00373 inline void TrilinearInterpolation
00374 ( TOutputIterator result ,
00375 const std::vector<TData*>& dataPtr ,
00376 const int x ,
00377 const int y ,
00378 const int z ,
00379 const Types::Coordinate fracX ,
00380 const Types::Coordinate fracY ,
00381 const Types::Coordinate fracZ ) const;
00382
00384 int nextI;
00385
00387 int nextJ;
00388
00390 int nextK;
00391
00393 int nextIJ;
00394
00396 int nextIK;
00397
00399 int nextJK;
00400
00402 int nextIJK;
00403
00406 virtual Self* ExtractSliceVirtual( const int axis , const int plane ) const;
00407
00408 private:
00411 Self::RegionType m_CropRegion;
00412 };
00413
00415
00416 }
00417
00418 #include "cmtkDataGrid.txx"
00419
00420 #endif // #ifndef __cmtkDataGrid_h_included_