cmtkUniformVolumeInterpolatorPartialVolume.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: 2237 $
00026 //
00027 //  $LastChangedDate: 2010-08-18 10:18:59 -0700 (Wed, 18 Aug 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkUniformVolumeInterpolatorPartialVolume.h"
00034 
00035 #include <math.h>
00036 
00037 #ifdef HAVE_IEEEFP_H
00038 #  include <ieeefp.h>
00039 #endif
00040 
00041 namespace cmtk
00042 {
00043 
00046 
00047 bool
00048 UniformVolumeInterpolatorPartialVolume
00049 ::GetDataAt(const Vector3D& v, Types::DataItem& value) const
00050 {
00051   value=0;
00052 
00053   Types::Coordinate lScaled[3];
00054   int imageGridPoint[3];
00055   for ( int n = 0; n < 3; ++n )
00056     {
00057     lScaled[n] = (v[n]-this->m_VolumeOffset[n]) / this->m_VolumeDeltas[n];
00058     imageGridPoint[n] = (int) floor( lScaled[n] );
00059     if ( ( imageGridPoint[n] < 0 ) || ( imageGridPoint[n] >= this->m_VolumeDims[n]-1 ) )
00060       return false;
00061     }
00062   
00063   const size_t offset = this->GetOffsetFromIndex( imageGridPoint[0], imageGridPoint[1], imageGridPoint[2] );
00064   
00065   bool done[8];
00066   Types::DataItem corners[8];
00067   bool dataPresent = false;
00068 
00069   size_t idx = 0;
00070   for ( int k = 0; k < 2; ++k )
00071     {
00072     for ( int j = 0; j < 2; ++j )
00073       {
00074       for ( int i = 0; i < 2; ++i, ++idx )
00075         {
00076         corners[idx] = this->m_VolumeDataArray[offset + this->GetOffsetFromIndex( i, j, k )];
00077         const bool dataHere = finite( corners[idx] );
00078         done[idx] = !dataHere;
00079         dataPresent |= dataHere;
00080         }
00081       }
00082     }
00083   
00084   if (dataPresent) 
00085     {
00086     const Types::Coordinate revX = lScaled[0]-imageGridPoint[0];
00087     const Types::Coordinate revY = lScaled[1]-imageGridPoint[1];
00088     const Types::Coordinate revZ = lScaled[2]-imageGridPoint[2];
00089     const Types::Coordinate offsX = 1-revX;
00090     const Types::Coordinate offsY = 1-revY;
00091     const Types::Coordinate offsZ = 1-revZ;
00092 
00093     const Types::Coordinate weights[8] = 
00094       { offsX * offsY * offsZ, revX * offsY * offsZ, offsX * revY * offsZ, revX * revY * offsZ,
00095         offsX * offsY * revZ, revX * offsY * revZ, offsX * revY * revZ, revX * revY * revZ 
00096       };
00097 
00098     bool done[8];
00099     memset( done, 0, sizeof( done ) );
00100     
00101     Types::Coordinate maxWeight = 0;
00102     for ( unsigned int j = 0; j < 8; ++j ) 
00103       {
00104       if ( done[j] ) continue;
00105       Types::Coordinate weight = weights[j];
00106       for ( unsigned int i = j+1; i < 8; ++i ) 
00107         {
00108         if ( done[i] ) continue;
00109         if ( corners[i] == corners[j] ) 
00110           {
00111           weight += weights[i];
00112           done[i] = true;
00113           }
00114         }
00115       if ( weight > maxWeight ) 
00116         {
00117         value = corners[j];
00118         maxWeight = weight;
00119         }
00120       }
00121     
00122     return true;
00123     }
00124   
00125   return false;
00126 }
00127 
00128 Types::DataItem
00129 UniformVolumeInterpolatorPartialVolume
00130 ::GetDataDirect( const int* imageGridPoint, const Types::Coordinate* insidePixel ) const
00131 {
00132   Types::DataItem value = 0;
00133 
00134   const size_t offset = this->GetOffsetFromIndex( imageGridPoint[0], imageGridPoint[1], imageGridPoint[2] );
00135   
00136   bool done[8];
00137   Types::DataItem corners[8];
00138   bool dataPresent = false;
00139 
00140   size_t idx = 0;
00141   for ( int k = 0; k < 2; ++k )
00142     {
00143     for ( int j = 0; j < 2; ++j )
00144       {
00145       for ( int i = 0; i < 2; ++i, ++idx )
00146         {
00147         corners[idx] = this->m_VolumeDataArray[offset + this->GetOffsetFromIndex( i, j, k )];
00148         const bool dataHere = finite( corners[idx] );
00149         done[idx] = !dataHere;
00150         dataPresent |= dataHere;
00151         }
00152       }
00153     }
00154   
00155   if (dataPresent) 
00156     {
00157     const Types::Coordinate offsX = 1-insidePixel[0];
00158     const Types::Coordinate offsY = 1-insidePixel[1];
00159     const Types::Coordinate offsZ = 1-insidePixel[2];
00160 
00161     const Types::Coordinate weights[8] = 
00162       { offsX * offsY * offsZ, 
00163         insidePixel[0] * offsY * offsZ, 
00164         offsX * insidePixel[1] * offsZ, 
00165         insidePixel[0] * insidePixel[1] * offsZ,
00166         offsX * offsY * insidePixel[2], 
00167         insidePixel[0] * offsY * insidePixel[2], 
00168         offsX * insidePixel[1] * insidePixel[2], 
00169         insidePixel[0] * insidePixel[1] * insidePixel[2] 
00170       };
00171 
00172     Types::Coordinate maxWeight = 0;
00173     for ( unsigned int j = 0; j < 8; ++j ) 
00174       {
00175       if ( done[j] ) continue;
00176       Types::Coordinate weight = weights[j];
00177       for ( unsigned int i = j+1; i < 8; ++i ) 
00178         {
00179         if ( done[i] ) continue;
00180         if ( corners[i] == corners[j] ) 
00181           {
00182           weight += weights[i];
00183           done[i] = true;
00184           }
00185         }
00186       if ( weight > maxWeight ) 
00187         {
00188         value = corners[j];
00189         maxWeight = weight;
00190         }
00191       }
00192     }
00193   
00194   return value;
00195 };
00196 
00197 } // namespace cmtk
00198 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines