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
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( ¶ms );
00285 }
00286 break;
00287 case DATACLASS_LABEL:
00288 {
00289 GetTransformedReferenceLabel( ¶ms );
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
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, ¶ms[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;
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
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
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
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
00582
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
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 }
00683
00684 #ifdef CMTK_BUILD_MPI
00685 # include "cmtkReformatVolumeMPI.txx"
00686 #else
00687 # include "cmtkReformatVolume.txx"
00688 #endif