Go to the documentation of this file.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 #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
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
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
00139 CoordinateMatrix3x3 J;
00140 this->GetJacobian( u, J );
00141 J.Invert3x3();
00142 J.GetTranspose().Multiply( delta );
00143
00144
00145 (vu = u) -= (delta *= step);
00146
00147
00148 if ( !this->InDomain( vu ) )
00149 {
00150
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 }