cmtkSplineWarpXform_Inverse.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: 2671 $
00026 //
00027 //  $LastChangedDate: 2010-12-15 14:37:08 -0800 (Wed, 15 Dec 2010) $
00028 //
00029 //  $LastChangedBy: torstenrohlfing $
00030 //
00031 */
00032 
00033 #include "cmtkSplineWarpXform.h"
00034 
00035 #include <Base/cmtkMathUtil.h>
00036 
00037 namespace
00038 cmtk
00039 {
00040 
00043 
00044 bool
00045 SplineWarpXform::ApplyInverse
00046 ( const Self::SpaceVectorType& v, Self::SpaceVectorType& u, const Types::Coordinate accuracy ) const
00047 {
00048   u = v;
00049   return this->ApplyInverseInPlace( u, accuracy );
00050 }
00051 
00052 bool
00053 SplineWarpXform::ApplyInverseInPlace 
00054 ( Self::SpaceVectorType& v, const Types::Coordinate accuracy ) const
00055 {
00056   Self::SpaceVectorType u;
00057   this->FindClosestControlPoint( v, u );
00058   return this->ApplyInverseInPlaceWithInitial( v, u, accuracy );
00059 }
00060 
00061 void
00062 SplineWarpXform::FindClosestControlPoint
00063 ( const Self::SpaceVectorType& v, Self::SpaceVectorType& cp ) const
00064 {
00065   // find closest control point -- we'll go from there.
00066   Types::Coordinate closestDistance = FLT_MAX;
00067   Types::Coordinate idx[3];
00068   for ( int dim = 0; dim < 3; ++dim ) 
00069     idx[dim] = 0.5 * this->m_Dims[dim];
00070 
00071   for ( Types::Coordinate step = 0.25 * MathUtil::Min( 3, idx ); step > 0.01; step *= 0.5 )
00072     {
00073     bool improved = true;
00074     while ( improved ) 
00075       {
00076       improved = false;
00077       int closestDim = 0, closestDir = 0;
00078       
00079       for ( int dim = 0; dim < 3; ++dim ) 
00080         {
00081         for ( int dir = -1; dir < 2; dir +=2 )
00082           {
00083           const Types::Coordinate oldIdx = idx[dim];
00084           idx[dim] += dir * step;
00085           if ( (idx[dim] > 0) && (idx[dim] <= this->m_Dims[dim]-2) ) 
00086             {
00087             this->GetOriginalControlPointPosition( cp, idx[0], idx[1], idx[2] );
00088             this->ApplyInPlace( cp );
00089             cp -= v;
00090             const Types::Coordinate distance = cp.RootSumOfSquares();
00091             if ( distance < closestDistance ) 
00092               {
00093               closestDistance = distance;
00094               closestDim = dim;
00095               closestDir = dir;
00096               improved = true;
00097               } 
00098             }
00099           idx[dim] = oldIdx;
00100           }
00101         }
00102       
00103       if ( improved )
00104         {
00105         idx[closestDim] += closestDir * step;
00106         }
00107       }
00108     }
00109   
00110   assert( (idx[0] <= this->m_Dims[0]-1) && (idx[1] <= this->m_Dims[1]-1 ) && (idx[2] <= this->m_Dims[2]-1) );
00111   assert( idx[0] >= 0 && idx[1] >= 0 && idx[2] >= 0 );
00112 
00113   this->GetOriginalControlPointPosition( cp, idx[0], idx[1], idx[2] );
00114 }
00115 
00116 bool
00117 SplineWarpXform::ApplyInverseInPlaceWithInitial
00118 ( Self::SpaceVectorType& target, const Self::SpaceVectorType& initial, const Types::Coordinate accuracy ) 
00119   const
00120 {
00121   Self::SpaceVectorType u( initial );
00122 
00123   // project into domain
00124   for ( int dim = 0; dim < 3; ++dim )
00125     {
00126     u[dim] = std::max<Types::Coordinate>( 0, std::min<Types::Coordinate>( u[dim], this->Domain[dim] ) );
00127     }
00128 
00129   Self::SpaceVectorType vu( initial ), delta;
00130   this->ApplyInPlace( vu );
00131   ((delta = vu) -= target);
00132 
00133   Types::Coordinate error = delta.RootSumOfSquares();
00134 
00135   Types::Coordinate step = 1.0;
00136   while ( ( error > accuracy) && (step > 0.001) ) 
00137     {
00138     // transform difference vector into original coordinate system using inverse Jacobian.
00139     CoordinateMatrix3x3 J;
00140     this->GetJacobian( u, J );
00141     J.Invert3x3();
00142     J.GetTranspose().Multiply( delta );
00143     
00144     // initialize line search
00145     (vu = u) -= (delta *= step);
00146     
00147     // line search along transformed error direction
00148     if ( !this->InDomain( vu ) ) 
00149       {
00150       // project into domain
00151       for ( int dim = 0; dim < 3; ++dim )
00152         {
00153         vu[dim] = std::max<Types::Coordinate>( 0, std::min<Types::Coordinate>( vu[dim], this->Domain[dim] ) );
00154         }
00155       }
00156     
00157     Self::SpaceVectorType uNext( vu );
00158     this->ApplyInPlace( vu );
00159     
00160     (delta = vu) -= target;
00161     if ( error > delta.RootSumOfSquares() ) 
00162       {
00163       error = delta.RootSumOfSquares();
00164       u = uNext;
00165       } 
00166     else
00167       {
00168       step *= 0.5;
00169       }
00170     }
00171 
00172   target = u;
00173   return !(error > accuracy);
00174 }
00175 
00176 } // namespace cmtk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines