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 "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
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
00132
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
00143 const int numberOfCells = (gX[idxX + numPoints - 1] - gX[idxX]) / xform.nextI + 4;
00144
00145
00146
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
00168 int cellIdx = 0;
00169
00170
00171 int i = idxX;
00172 for ( const int lastPoint = idxX + numPoints; i < lastPoint; )
00173 {
00174
00175 const Types::Coordinate* phiPtr = &phiHat[3*cellIdx];
00176
00177
00178 do
00179 {
00180 Vector3D& vRef = *v;
00181
00182
00183
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
00189 ++i;
00190 spX += 4;
00191 ++v;
00192
00193 }
00194 while ( ( gX[i-1] == gX[i] ) && ( i < lastPoint ) );
00195
00196
00197
00198 ++cellIdx;
00199 }
00200 }
00201