cmtkSplineWarpXformUniformVolume.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: 2453 $
00026 //
00027 //  $LastChangedDate: 2010-10-18 10:33:06 -0700 (Mon, 18 Oct 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkSplineWarpXformUniformVolume.h"
00034 
00035 cmtk::SplineWarpXformUniformVolume::SplineWarpXformUniformVolume( const UniformVolume& volume, const SplineWarpXform::SmartConstPtr& xform )
00036   : m_Xform( xform )
00037 {
00038   this->RegisterVolume( volume );
00039 }
00040 
00041 void
00042 cmtk::SplineWarpXformUniformVolume::RegisterVolumeAxis 
00043 ( const int dim, const Types::Coordinate delta, const Types::Coordinate origin, const int cpgDim, const Types::Coordinate invCpgSpacing,
00044   std::vector<int>& g, std::vector<Types::Coordinate>& spline, std::vector<Types::Coordinate>& dspline )
00045 {
00046   g.resize( dim+1 );
00047   spline.resize( 4*dim );
00048   dspline.resize( 4*dim );
00049 
00050   for ( int idx=0; idx<dim; ++idx ) 
00051     {
00052     Types::Coordinate r = invCpgSpacing * (origin + delta * idx);
00053     g[idx] = std::min( static_cast<int>( r ), cpgDim-4 );
00054     const Types::Coordinate f = r - g[idx];
00055     for ( int k = 0; k < 4; ++k ) 
00056       {
00057       spline[4*idx+k] = CubicSpline::ApproxSpline( k, f );
00058       dspline[4*idx+k] = CubicSpline::DerivApproxSpline( k, f );
00059       }
00060     }
00061   // guard element
00062   g[dim] = -1;
00063 }
00064 
00065 void
00066 cmtk::SplineWarpXformUniformVolume::RegisterVolume
00067 ( const UniformVolume& volume )
00068 {
00069   const SplineWarpXform& xform = *(this->m_Xform);
00070 
00071   this->RegisterVolumeAxis( volume.m_Dims[0], volume.m_Delta[0], volume.m_Offset[0], xform.m_Dims[0], xform.InverseSpacing[0], this->gX, this->splineX, this->dsplineX );
00072   this->RegisterVolumeAxis( volume.m_Dims[1], volume.m_Delta[1], volume.m_Offset[1], xform.m_Dims[1], xform.InverseSpacing[1], this->gY, this->splineY, this->dsplineY );
00073   this->RegisterVolumeAxis( volume.m_Dims[2], volume.m_Delta[2], volume.m_Offset[2], xform.m_Dims[2], xform.InverseSpacing[2], this->gZ, this->splineZ, this->dsplineZ );
00074   
00075   for ( int idx = 0; idx < volume.m_Dims[0]; ++idx ) 
00076     gX[idx] *= xform.nextI;
00077   for ( int idx = 0; idx < volume.m_Dims[1]; ++idx ) 
00078     gY[idx] *= xform.nextJ;
00079   for ( int idx = 0; idx < volume.m_Dims[2]; ++idx ) 
00080     gZ[idx] *= xform.nextK;
00081 }
00082 
00083 void
00084 cmtk::SplineWarpXformUniformVolume
00085 ::GetTransformedGrid 
00086 ( Vector3D& v, const int idxX, const int idxY, const int idxZ ) const
00087 {
00088   const SplineWarpXform& xform = *(this->m_Xform);
00089 
00090   const Types::Coordinate* coeff = xform.m_Parameters + gX[idxX] + gY[idxY] + gZ[idxZ];
00091   const Types::Coordinate *spX = &splineX[idxX<<2], *spY = &splineY[idxY<<2], *spZ = &splineZ[idxZ<<2];
00092   
00093   for ( int dim = 0; dim<3; ++dim ) 
00094     {
00095     Types::Coordinate mm = 0;
00096     const Types::Coordinate *coeff_mm = coeff;
00097       for ( int m = 0; m < 4; ++m )
00098         {
00099         Types::Coordinate ll = 0;
00100         const Types::Coordinate *coeff_ll = coeff_mm;
00101         for ( int l = 0; l < 4; ++l ) 
00102           {
00103           Types::Coordinate kk = 0;
00104           const Types::Coordinate *coeff_kk = coeff_ll;
00105           for ( int k = 0; k < 4; ++k, coeff_kk+=3 ) 
00106             {
00107             kk += spX[k] * (*coeff_kk);
00108             }
00109           ll += spY[l] * kk;
00110           coeff_ll += xform.nextJ;
00111           }     
00112         mm += spZ[m] * ll;
00113         coeff_mm += xform.nextK;
00114         }
00115       v[ dim ] = mm;
00116       ++coeff;
00117     }
00118 }
00119 
00120 void 
00121 cmtk::SplineWarpXformUniformVolume::GetTransformedGridRow
00122 ( Vector3D *const vIn, const size_t numPoints, const int idxX, const int idxY, const int idxZ ) 
00123   const
00124 {
00125   Vector3D *v = vIn;
00126 
00127   const SplineWarpXform& xform = *(this->m_Xform);
00128   const Types::Coordinate* coeff = xform.m_Parameters + gX[idxX] + gY[idxY] + gZ[idxZ];
00129   const Types::Coordinate *spX = &splineX[idxX<<2], *spY = &splineY[idxY<<2], *spZ = &splineZ[idxZ<<2];
00130   
00131   // precompute the products of B_j(v) and B_k(w) for the 4 x 4 neighborhood
00132   // in y- and z-direction.
00133   Types::Coordinate sml[16], *psml = sml;
00134   for ( int m = 0; m < 4; ++m )
00135     {
00136     for ( int l = 0; l < 4; ++l, ++psml )
00137       {
00138       *psml = spZ[m] * spY[l];
00139       }
00140     }
00141   
00142   // determine the number of CPG cells on our way along the row
00143   const int numberOfCells = (gX[idxX + numPoints - 1] - gX[idxX]) / xform.nextI + 4;
00144   
00145   // pre-compute the contributions of all control points in y- and z-direction
00146   // along the way
00147   Types::Coordinate phiComp;
00148   std::vector<Types::Coordinate> phiHat( 3*numberOfCells );
00149 
00150   const int *gpo;
00151   int phiIdx = 0;
00152   for ( int cell = 0; cell < numberOfCells; ++cell, coeff += xform.nextI ) 
00153     {
00154     gpo = &this->GridPointOffset[0];
00155     for ( int dim = 0; dim < 3; ++dim, ++phiIdx ) 
00156       {
00157       phiComp = coeff[ *gpo ] * sml[0];
00158       ++gpo;
00159       for ( int ml = 1; ml < 16; ++ml, ++gpo ) 
00160         {
00161         phiComp += coeff[ *gpo ] * sml[ml];
00162         }
00163       phiHat[phiIdx] = phiComp;
00164       }
00165     }
00166   
00167   // start at the leftmost precomputed CPG cell
00168   int cellIdx = 0;
00169 
00170   // run over all points we're supposed to transform
00171   int i = idxX;
00172   for ( const int lastPoint = idxX + numPoints; i < lastPoint; ) 
00173     {
00174     // these change only when we enter a new cell
00175     const Types::Coordinate* phiPtr = &phiHat[3*cellIdx];
00176     
00177     // do everything inside one cell
00178     do 
00179       {
00180       Vector3D& vRef = *v;
00181       // compute transformed voxel by taking precomputed y- and z-contributions
00182       // and adding x. The loops to do this have been unrolled for increased
00183       // performance.
00184       vRef[0] = spX[0] * phiPtr[0] + spX[1] * phiPtr[3] + spX[2] * phiPtr[6] + spX[3] * phiPtr[9];
00185       vRef[1] = spX[0] * phiPtr[1] + spX[1] * phiPtr[4] + spX[2] * phiPtr[7] + spX[3] * phiPtr[10];
00186       vRef[2] = spX[0] * phiPtr[2] + spX[1] * phiPtr[5] + spX[2] * phiPtr[8] + spX[3] * phiPtr[11];
00187       
00188       // go to next voxel
00189       ++i;
00190       spX += 4;
00191       ++v;
00192       // repeat this until we leave current CPG cell.
00193       } 
00194     while ( ( gX[i-1] == gX[i] ) && ( i < lastPoint ) );
00195     
00196     // we've just left a cell -- shift index of precomputed control points
00197     // to the next one.
00198     ++cellIdx;
00199     }
00200 }
00201 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines