cmtkReformatVolume.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: 2502 $
00026 //
00027 //  $LastChangedDate: 2010-10-25 14:28:37 -0700 (Mon, 25 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 
00034 #include <System/cmtkProgress.h>
00035 #include <System/cmtkConsole.h>
00036 
00037 #include <Registration/cmtkReformatVolume.h>
00038 
00039 #include <Base/cmtkVector.h>
00040 #include <Base/cmtkAffineXform.h>
00041 #include <Base/cmtkWarpXform.h>
00042 #include <Base/cmtkSplineWarpXform.h>
00043 #include <Base/cmtkSplineWarpXformUniformVolume.h>
00044 #include <Base/cmtkAnatomicalOrientation.h>
00045 #include <Base/cmtkTypedArray.h>
00046 #include <Base/cmtkTemplateArray.h>
00047 #include <Base/cmtkMathUtil.h>
00048 #include <Base/cmtkUniformVolumeInterpolator.h>
00049 #include <Base/cmtkSincInterpolator.h>
00050 #include <Base/cmtkLinearInterpolator.h>
00051 #include <Base/cmtkNearestNeighborInterpolator.h>
00052 #include <Base/cmtkCubicInterpolator.h>
00053 #include <Base/cmtkUniformVolumeInterpolatorPartialVolume.h>
00054 
00055 #include <cassert>
00056 #include <algorithm>
00057 #include <vector>
00058 
00059 namespace
00060 cmtk
00061 {
00062 
00065 ReformatVolume::ReformatVolume() 
00066   : m_UserDataType( TYPE_NONE ),
00067     ReferenceVolume( NULL ),
00068     FloatingVolume( NULL ),
00069     m_AffineXform( NULL ),
00070     m_WarpXform( NULL )
00071 {
00072   Interpolation = cmtk::Interpolators::LINEAR;
00073   this->m_UsePaddingValue = false;
00074 }
00075 
00076 void
00077 ReformatVolume::SetReferenceVolume
00078 ( const UniformVolume::SmartConstPtr& referenceVolume )
00079 {
00080   this->ReferenceVolume = referenceVolume;
00081 }
00082 
00083 void 
00084 ReformatVolume::SetFloatingVolume
00085 ( const UniformVolume::SmartConstPtr& floatingVolume )
00086 {
00087   FloatingVolume = floatingVolume;
00088 }
00089 
00090 void
00091 ReformatVolume::SetAffineXform( const AffineXform::SmartPtr& affineXform )
00092 {
00093   this->m_AffineXform = affineXform;
00094 }
00095 
00096 void
00097 ReformatVolume::SetWarpXform( const WarpXform::SmartPtr& warpXform )
00098 {
00099   this->m_WarpXform = warpXform;
00100 }
00101 
00102 const UniformVolume::SmartPtr
00103 ReformatVolume::MakeTargetVolume() const
00104 {
00105   return UniformVolume::SmartPtr( ReferenceVolume->CloneGrid() );
00106 }
00107 
00108 const UniformVolume::SmartPtr
00109 ReformatVolume::PlainReformat()
00110 {
00111   UniformVolume::SmartPtr targetVolume = this->MakeTargetVolume();
00112 
00113   if ( targetVolume ) 
00114     {
00115     Progress::Begin( 0, targetVolume->GetDims()[AXIS_Z], 1, "Volume reformatting" );
00116     
00117     TypedArray::SmartPtr targetData( TypedArray::Create( FloatingVolume->GetData()->GetType(), targetVolume->GetNumberOfPixels() ) );
00118     if ( this->m_UsePaddingValue )
00119       targetData->SetPaddingValue( this->m_PaddingValue );
00120     
00121     UniformVolumeInterpolatorBase::SmartPtr interpolator( this->CreateInterpolator( this->FloatingVolume ) );
00122     Vector3D pFlt;
00123     
00124     const DataGrid::IndexType dims = targetVolume->GetDims();
00125     
00126     size_t offset = 0;
00127     for ( int pZ = 0; pZ < dims[2]; ++pZ ) 
00128       {
00129       Types::DataItem value = 0;
00130       
00131       const SplineWarpXform::SmartConstPtr& splineWarp = SplineWarpXform::SmartConstPtr::DynamicCastFrom( this->m_WarpXform );
00132       if ( splineWarp ) 
00133         {
00134         SplineWarpXformUniformVolume xformVolume( *(this->ReferenceVolume), splineWarp );
00135         
00136         for ( int pY = 0; pY<dims[1]; ++pY ) 
00137           {
00138           for ( int pX = 0; pX<dims[0]; ++pX, ++offset ) 
00139             {
00140             xformVolume.GetTransformedGrid( pFlt, pX, pY, pZ );
00141             
00142             if ( interpolator->GetDataAt( pFlt, value ) )
00143               targetData->Set( value, offset );       
00144             else
00145               targetData->SetPaddingAt( offset );
00146             }
00147           }
00148         } 
00149       else
00150         {
00151         for ( int pY = 0; pY<dims[1]; ++pY ) 
00152           {
00153           for ( int pX = 0; pX<dims[0]; ++pX, ++offset ) 
00154             {       
00155             pFlt = ReferenceVolume->GetGridLocation( pX, pY, pZ );
00156             this->m_AffineXform->ApplyInPlace( pFlt );
00157             
00158             if ( interpolator->GetDataAt( pFlt, value ) )
00159               targetData->Set( value, offset );
00160             else
00161               targetData->SetPaddingAt( offset );
00162             }
00163           }
00164         }
00165       
00166       Progress::SetProgress( pZ );
00167       }
00168     
00169     targetVolume->SetData( targetData );
00170     }
00171   
00172   return targetVolume;
00173 }
00174 
00175 TypedArray::SmartPtr
00176 ReformatVolume::PlainReformat
00177 ( const int plane, TypedArray::SmartPtr& target, const size_t targetOffset )
00178 {
00179   const DataGrid::IndexType& Dims = ReferenceVolume->GetDims();
00180   const int DimsX = Dims[0], DimsY = Dims[1];
00181   const int DataSize = DimsX * DimsY;
00182 
00183   TypedArray::SmartPtr result = target;
00184   if ( ! result ) 
00185     {
00186     result = TypedArray::Create( FloatingVolume->GetData()->GetType(), DataSize );
00187      
00188     if ( this->m_UsePaddingValue )
00189       result->SetPaddingValue( this->m_PaddingValue );
00190     }
00191   
00192   if ( ! result ) return result;
00193   
00194   Vector3D pMod;
00195 
00196   Types::DataItem value = 0;
00197   int offset = targetOffset;
00198 
00199   UniformVolumeInterpolatorBase::SmartPtr interpolator( this->CreateInterpolator( this->FloatingVolume ) );
00200   
00201   const SplineWarpXform::SmartConstPtr splineWarp = SplineWarpXform::SmartConstPtr::DynamicCastFrom( this->m_WarpXform );
00202   if ( splineWarp ) 
00203     {
00204     const SplineWarpXformUniformVolume xformVolume( *(this->ReferenceVolume), splineWarp );
00205     
00206     for ( int pY = 0; pY<DimsY; ++pY ) 
00207        {
00208       for ( int pX = 0; pX<DimsX; ++pX, ++offset ) 
00209         {
00210         xformVolume.GetTransformedGrid( pMod, pX, pY, plane );
00211         
00212         if ( interpolator->GetDataAt( pMod, value ) )
00213           result->Set( value, offset );       
00214         else
00215           result->SetPaddingAt( offset );
00216         }
00217        }
00218     } 
00219   else
00220     {
00221     if ( ! this->m_AffineXform ) return result;
00222     
00223     for ( int pY = 0; pY<DimsY; ++pY ) 
00224       {
00225       for ( int pX = 0; pX<DimsX; ++pX, ++offset ) 
00226         {           
00227         pMod = ReferenceVolume->GetGridLocation( pX, pY, plane );
00228         this->m_AffineXform->ApplyInPlace( pMod );
00229 
00230         if ( interpolator->GetDataAt( pMod, value ) )
00231           result->Set( value, offset );
00232         else
00233           result->SetPaddingAt( offset );
00234         }
00235       }
00236     }
00237   
00238   return result;
00239 }
00240 
00241 UniformVolume* 
00242 ReformatVolume::GetTransformedReference
00243 ( Types::Coordinate *const volumeOffset )
00244 {
00245   UniformVolume* result = NULL;
00246 
00247   const SplineWarpXform* splineXform = dynamic_cast<const SplineWarpXform*>( this->m_WarpXform.GetConstPtr() );
00248   if ( ! splineXform ) 
00249     {
00250     StdErr << "ERROR: ReformatVolume::GetTransformedReference supports spline warp only.\n";
00251     return NULL;
00252     }
00253 
00254   Types::Coordinate bbFrom[3], delta[3];
00255   result = this->CreateTransformedReference( bbFrom, delta, volumeOffset );
00256 
00257   ScalarDataType dtype = ReferenceVolume->GetData()->GetType();
00258   TypedArray::SmartPtr dataArray( TypedArray::Create( dtype, result->GetNumberOfPixels() ) );
00259 
00260   if ( this->m_UsePaddingValue )
00261     dataArray->SetPaddingValue( this->m_PaddingValue );
00262 
00263   result->SetData( dataArray );
00264 
00265   GetTransformedReferenceTP params;
00266   params.thisObject = this;
00267   params.ThisThreadIndex = 0;
00268   params.NumberOfThreads = 1;
00269   params.dims = result->GetDims();
00270   params.bbFrom = bbFrom;
00271   params.delta = delta;
00272   params.splineXform = splineXform;
00273   params.dataArray = dataArray;
00274 
00275   UniformVolumeInterpolatorBase::SmartPtr interpolator( this->CreateInterpolator( this->FloatingVolume ) );
00276   params.referenceInterpolator = interpolator;
00277   
00278   DataClass dataClass = ReferenceVolume->GetData()->GetDataClass();
00279   switch ( dataClass ) 
00280     {
00281     default:
00282     case DATACLASS_GREY: 
00283     {
00284     GetTransformedReferenceGrey( &params );
00285     }
00286     break;
00287     case DATACLASS_LABEL: 
00288     {
00289     GetTransformedReferenceLabel( &params );
00290     }
00291     break;
00292     }
00293   
00294   return result;
00295 }
00296 
00297 CMTK_THREAD_RETURN_TYPE
00298 ReformatVolume::GetTransformedReferenceGrey( void *const arg )
00299 {
00300   GetTransformedReferenceTP* params = static_cast<GetTransformedReferenceTP*>( arg );
00301 
00302   TypedArray::SmartPtr dataArray = params->dataArray;
00303   const SplineWarpXform* splineXform = params->splineXform;
00304   const UniformVolumeInterpolatorBase* interpolator = params->referenceInterpolator;
00305   const Types::Coordinate* delta = params->delta;
00306   const Types::Coordinate* bbFrom = params->bbFrom;
00307   const DataGrid::IndexType& dims = params->dims;
00308 
00309   const Types::Coordinate minDelta = MathUtil::Min( 3, delta );
00310   
00311   Types::DataItem value;
00312 
00313   UniformVolume::CoordinateVectorType u, v;
00314   v[2] = bbFrom[2];
00315   size_t offset = 0;
00316   for ( int cz = 0; cz < dims[2]; ++cz, v[2] += delta[2] ) 
00317     {
00318     if ( ! params->ThisThreadIndex ) Progress::SetProgress( cz );
00319     v[1] = bbFrom[1];
00320     for ( int cy = 0; cy < dims[1]; ++cy, v[1] += delta[1] ) 
00321       {
00322       v[0] = bbFrom[0];
00323       for ( int cx = 0; cx < dims[0]; ++cx, v[0] += delta[0], ++offset ) 
00324         {
00325         u = v;
00326         const bool success = splineXform->ApplyInverseInPlace( u, 0.1 * minDelta );
00327         
00328         if ( success ) 
00329           {
00330           if ( interpolator->GetDataAt( u, value ) )
00331             dataArray->Set( value, offset );
00332           else
00333             dataArray->SetPaddingAt( offset );
00334           }
00335         }
00336       }
00337     }
00338   
00339   return CMTK_THREAD_RETURN_VALUE;
00340 }
00341 
00342 CMTK_THREAD_RETURN_TYPE
00343 ReformatVolume::GetTransformedReferenceLabel( void *const arg )
00344 {
00345   GetTransformedReferenceTP* params = static_cast<GetTransformedReferenceTP*>( arg );
00346 
00347   const ReformatVolume* thisObject = params->thisObject;
00348   TypedArray::SmartPtr dataArray = params->dataArray;
00349   const SplineWarpXform* splineXform = params->splineXform;
00350   const Types::Coordinate* delta = params->delta;
00351   const Types::Coordinate* bbFrom = params->bbFrom;
00352   const DataGrid::IndexType& dims = params->dims;
00353 
00354   const std::vector<SplineWarpXform::SmartPtr>* xformList = params->xformList;
00355   const std::vector<UniformVolume::SmartPtr>* volumeList = params->volumeList;
00356 
00357   const Types::Coordinate minDelta = MathUtil::Min( 3, delta );
00358   
00359   UniformVolume::CoordinateVectorType u, v, xyz;
00360 
00361   std::vector<ProbeInfo> probe( params->numberOfImages );
00362   std::vector<Types::Coordinate> labelCount( params->maxLabel+1 );
00363     
00364   xyz[2] = bbFrom[2];
00365   size_t offset = 0;
00366   for ( int cz = 0; cz < dims[2]; ++cz, xyz[2] += delta[2] ) 
00367     {
00368     if ( ! params->ThisThreadIndex ) Progress::SetProgress( cz );
00369     xyz[1] = bbFrom[1];
00370     for ( int cy = 0; cy < dims[1]; ++cy, xyz[1] += delta[1] ) 
00371       {
00372       xyz[0] = bbFrom[0];
00373       for ( int cx = 0; cx < dims[0]; ++cx, xyz[0] += delta[0], ++offset ) 
00374         {
00375         v = xyz;
00376         const bool success = splineXform->ApplyInverseInPlace( v, 0.1 * minDelta );
00377         u = v;
00378         
00379         bool valid = false;
00380         unsigned int toIdx = 0;
00381         if ( success ) 
00382           {
00383           if ( params->IncludeReferenceData ) 
00384             {
00385             valid = thisObject->ReferenceVolume->ProbeNoXform( probe[toIdx], v );
00386             if ( valid ) ++toIdx;
00387             }
00388           
00389           for ( unsigned int img = 0; img < params->numberOfImages-1; ++img ) 
00390             {
00391             v = u;
00392             (*xformList)[img]->ApplyInPlace( v );
00393             valid = (*volumeList)[img]->ProbeNoXform( probe[toIdx], v );
00394             if ( valid ) ++toIdx;           
00395             }
00396           }
00397         if ( toIdx && success ) 
00398           {
00399           std::fill( labelCount.begin(), labelCount.end(), 0 );
00400           for ( unsigned int idx = 0; idx < toIdx; ++idx ) 
00401             {
00402             for ( unsigned int corner = 0; corner < 8; ++corner ) 
00403               {
00404               labelCount[static_cast<int>( probe[idx].Values[corner] )] += probe[idx].GetWeight( corner );
00405               }
00406             }
00407           unsigned int winner = 0;
00408           Types::Coordinate winnerWeight = labelCount[0];
00409           for ( int label = 1; label < params->maxLabel; ++label ) 
00410             {
00411             if ( labelCount[label] > winnerWeight ) 
00412               {
00413               winnerWeight = labelCount[label];
00414               winner = label;
00415               }
00416             }
00417           dataArray->Set( static_cast<Types::DataItem>( winner ), offset );
00418           } 
00419         else
00420           dataArray->SetPaddingAt( offset );
00421         }
00422       }
00423     }
00424   
00425   return CMTK_THREAD_RETURN_VALUE;
00426 }
00427 
00428 UniformVolume* 
00429 ReformatVolume::GetTransformedReferenceJacobianAvg
00430 ( const std::vector<SplineWarpXform::SmartPtr>* xformList,
00431   Types::Coordinate *const volumeOffset,
00432   const bool includeReferenceData )
00433 {
00434   const SplineWarpXform* splineXform = dynamic_cast<const SplineWarpXform*>( this->m_WarpXform.GetConstPtr() );
00435   if ( ! splineXform ) 
00436     {
00437     StdErr << "ERROR: ReformatVolume::GetTransformedReferenceJacobian supports spline warp only.\n";
00438     return NULL;
00439     }
00440   
00441   // bounding box for reformatted volume.
00442   Types::Coordinate bbFrom[3], delta[3];
00443   UniformVolume* result = this->CreateTransformedReference( bbFrom, delta, volumeOffset );
00444   
00445   TypedArray::SmartPtr dataArray( TypedArray::Create( TYPE_FLOAT, result->GetNumberOfPixels() ) );
00446 
00447   if ( this->m_UsePaddingValue )
00448     dataArray->SetPaddingValue( this->m_PaddingValue );
00449 
00450   result->SetData( dataArray );
00451 
00452   const size_t numberOfThreads = Threads::GetNumberOfThreads();
00453   std::vector<GetTransformedReferenceTP> params( numberOfThreads );
00454 
00455   for ( size_t thr = 0; thr < numberOfThreads; ++thr ) 
00456     {
00457     params[thr].thisObject = this;
00458     params[thr].ThisThreadIndex = thr;
00459     params[thr].NumberOfThreads = numberOfThreads;
00460     params[thr].dims = result->GetDims();
00461     params[thr].bbFrom = bbFrom;
00462     params[thr].delta = delta;
00463     params[thr].splineXform = splineXform;
00464     params[thr].xformList = xformList;
00465     params[thr].dataArray = dataArray;
00466     params[thr].avgMode = MODE_MEAN;
00467     params[thr].IncludeReferenceData = includeReferenceData;
00468     }
00469   
00470   Threads::RunThreads( GetTransformedReferenceJacobianAvgThread, numberOfThreads, &params[0] );
00471   
00472   return result;
00473 }
00474 
00475 CMTK_THREAD_RETURN_TYPE
00476 ReformatVolume::GetTransformedReferenceJacobianAvgThread
00477 ( void *const arg )
00478 {
00479   GetTransformedReferenceTP* params = static_cast<GetTransformedReferenceTP*>( arg );
00480 
00481   TypedArray::SmartPtr dataArray = params->dataArray;
00482   const SplineWarpXform* splineXform = params->splineXform;
00483   const Types::Coordinate* delta = params->delta;
00484   const Types::Coordinate* bbFrom = params->bbFrom;
00485   const DataGrid::IndexType& dims = params->dims;
00486 
00487   const std::vector<SplineWarpXform::SmartPtr>* xformList = params->xformList;
00488 
00489   const Types::Coordinate minDelta = MathUtil::Min( 3, delta );
00490   
00491   UniformVolume::CoordinateVectorType u, v, xyz;
00492 
00493   const size_t numberOfXforms = xformList->size();
00494   std::vector<const SplineWarpXform*> xforms( numberOfXforms );
00495   for ( unsigned int img = 0; img < numberOfXforms; ++img )
00496     xforms[img] = (*xformList)[img];
00497 
00498   const int czFrom = params->ThisThreadIndex * dims[2] / params->NumberOfThreads;
00499   const int czTo = std::min<int>( dims[2], (1+params->ThisThreadIndex) * dims[2] / params->NumberOfThreads );
00500 
00501   Vector<Types::Coordinate> values( params->IncludeReferenceData ? numberOfXforms+1 : numberOfXforms );
00502   const size_t margin = numberOfXforms / 20; // margin for center 90%
00503 
00504   xyz[2] = bbFrom[2] + czFrom * delta[2];
00505   size_t offset = czFrom * dims[0] * dims[1];
00506 
00507   for ( int cz = czFrom; cz < czTo; ++cz, xyz[2] += delta[2] ) 
00508     {
00509     if ( ! params->ThisThreadIndex ) Progress::SetProgress( cz );
00510     xyz[1] = bbFrom[1];
00511     for ( int cy = 0; cy < dims[1]; ++cy, xyz[1] += delta[1] ) 
00512       {
00513       xyz[0] = bbFrom[0];
00514       for ( int cx = 0; cx < dims[0]; ++cx, xyz[0] += delta[0], ++offset ) 
00515         {
00516         v = xyz;
00517         const bool success = splineXform->ApplyInverseInPlace( v, 0.1 * minDelta );
00518         u = v;
00519         
00520         if ( success ) 
00521           {
00522           const Types::Coordinate refJacobian = splineXform->GetGlobalScaling() / splineXform->GetJacobianDeterminant( u );
00523           
00524           switch ( params->avgMode ) 
00525             {
00526             case MODE_MEAN: 
00527             {
00528             // average
00529                         Types::Coordinate sum = params->IncludeReferenceData ? 1.0 : 0.0;
00530             for ( unsigned int img = 0; img < numberOfXforms; ++img )
00531               sum += xforms[img]->GetJacobianDeterminant( u ) / xforms[img]->GetGlobalScaling();
00532             dataArray->Set( static_cast<Types::DataItem>( refJacobian * sum / numberOfXforms ), offset );
00533             break;
00534             }
00535             case MODE_MEDIAN:
00536             case MODE_ROBUST90: 
00537             {
00538             for ( unsigned int img = 0; img < numberOfXforms; ++img )
00539               values[img] = xforms[img]->GetJacobianDeterminant( u ) / xforms[img]->GetGlobalScaling();
00540             if ( params->IncludeReferenceData )
00541               values[numberOfXforms] = 1.0;
00542             
00543             values.Sort();
00544             
00545             if ( params->avgMode == MODE_MEDIAN ) 
00546               {
00547               // median
00548               if ( numberOfXforms & 1 )
00549                 dataArray->Set( static_cast<Types::DataItem>( refJacobian * values[numberOfXforms/2+1] ), offset );
00550               else
00551                 dataArray->Set( static_cast<Types::DataItem>( 0.5 * refJacobian * (values[numberOfXforms/2]+values[numberOfXforms/2+1]) ), offset );
00552               } 
00553             else
00554               {
00555               // robust average of center 90% average
00556               Types::Coordinate sum = 0;
00557               for ( unsigned int img = margin; img < numberOfXforms - margin; ++img )
00558                 sum += values[img];
00559                   dataArray->Set( static_cast<Types::DataItem>( refJacobian * sum / ( numberOfXforms - 2 * margin ) ), offset );
00560               }
00561             break;
00562             }
00563             }
00564           } 
00565         else
00566           {
00567           dataArray->SetPaddingAt( offset );
00568           }
00569         }
00570       }
00571     }
00572   
00573   return CMTK_THREAD_RETURN_VALUE;
00574 }
00575 
00576 UniformVolume*
00577 ReformatVolume::CreateTransformedReference
00578 ( Types::Coordinate *const bbFrom, Types::Coordinate *const delta, 
00579   Types::Coordinate *const volumeOffset )
00580 {
00581   // default: no offset output desired, 
00582   // that means, reformat to original image domain
00583   UniformVolume::CoordinateVectorType bbTo;
00584   for ( unsigned int axis = 0; axis < 3; ++axis ) 
00585     {
00586     bbFrom[axis] = 0;
00587     bbTo[axis] = this->ReferenceVolume->Size[axis];
00588     }
00589   
00590   if ( volumeOffset ) 
00591     {
00592     Vector3D u, v;
00593     for ( unsigned int z = 0; z < 2; ++z ) 
00594       {
00595       if ( z )
00596         u[AXIS_Z] = this->ReferenceVolume->Size[AXIS_Z];
00597       else
00598         u[AXIS_Z] = 0;
00599       
00600       for ( unsigned int y = 0; y < 2; ++y ) 
00601         {
00602         if ( y )
00603           u[AXIS_Y] = this->ReferenceVolume->Size[AXIS_Y];
00604         else
00605           u[AXIS_Y] = 0;
00606         for ( unsigned int x = 0; x < 2; ++x ) 
00607           {
00608           if ( x )
00609             u[AXIS_X] = this->ReferenceVolume->Size[AXIS_X];
00610           else
00611             u[AXIS_X] = 0;
00612           
00613           v = this->m_WarpXform->Apply( u );
00614           for ( unsigned int axis = 0; axis < 3; ++axis ) 
00615             {
00616             bbFrom[axis] = std::min( bbFrom[axis], v[axis] );
00617             bbTo[axis] = std::max( bbTo[axis], v[axis] );
00618             }
00619           }
00620         }
00621       }
00622     
00623     // report new volume offset, if so desired by the caller
00624     for ( unsigned int axis = 0; axis < 3; ++axis )
00625       volumeOffset[axis] = bbFrom[axis];
00626     }
00627   
00628   UniformVolume::IndexType dims;
00629   for ( int dim = 0; dim < 3; ++dim ) 
00630     {
00631     delta[dim] = this->ReferenceVolume->m_Delta[dim];
00632     bbTo[dim] -= bbFrom[dim];
00633     dims[dim] = 1 + static_cast<int>( bbTo[dim] / delta[dim] );
00634     }
00635   
00636   return new UniformVolume( dims, bbTo );
00637 }
00638 
00639 UniformVolumeInterpolatorBase::SmartPtr
00640 ReformatVolume::CreateInterpolator
00641 ( const cmtk::Interpolators::InterpolationEnum interpolation, const UniformVolume::SmartConstPtr& volume )
00642 {
00643   switch ( interpolation )
00644     {
00645     default:
00646     case cmtk::Interpolators::LINEAR:
00647     {
00648     typedef UniformVolumeInterpolator<cmtk::Interpolators::Linear> TInterpolator;
00649     return TInterpolator::SmartPtr( new TInterpolator( *volume ) );
00650     }
00651     case cmtk::Interpolators::NEAREST_NEIGHBOR:
00652     {
00653     typedef UniformVolumeInterpolator<cmtk::Interpolators::NearestNeighbor> TInterpolator;
00654     return TInterpolator::SmartPtr( new TInterpolator( *volume ) );
00655     }
00656     case cmtk::Interpolators::CUBIC:
00657     {
00658     typedef UniformVolumeInterpolator<cmtk::Interpolators::Cubic> TInterpolator;
00659     return TInterpolator::SmartPtr( new TInterpolator( *volume ) );
00660     }
00661     case cmtk::Interpolators::COSINE_SINC:
00662     {
00663     typedef UniformVolumeInterpolator< cmtk::Interpolators::CosineSinc<> > TInterpolator;
00664     return TInterpolator::SmartPtr( new TInterpolator( *volume ) );
00665     }
00666     case cmtk::Interpolators::PARTIALVOLUME:
00667     {
00668     typedef UniformVolumeInterpolatorPartialVolume TInterpolator;
00669     return TInterpolator::SmartPtr( new TInterpolator( *volume ) );
00670     }
00671     }  
00672   return UniformVolumeInterpolatorBase::SmartPtr( NULL );
00673 }
00674 
00675 UniformVolumeInterpolatorBase::SmartPtr
00676 ReformatVolume::CreateInterpolator
00677 ( const UniformVolume::SmartConstPtr& volume )
00678 {
00679   return Self::CreateInterpolator( this->Interpolation, volume );
00680 }
00681 
00682 } // end namespace cmtk
00683 
00684 #ifdef CMTK_BUILD_MPI
00685 #  include "cmtkReformatVolumeMPI.txx"
00686 #else
00687 #  include "cmtkReformatVolume.txx"
00688 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines