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 #ifndef __cmtkSplineWarpXform_h_included_
00034 #define __cmtkSplineWarpXform_h_included_
00035
00036 #include <cmtkconfig.h>
00037
00038 #include <Base/cmtkWarpXform.h>
00039 #include <Base/cmtkVector.h>
00040 #include <Base/cmtkAffineXform.h>
00041 #include <Base/cmtkCubicSpline.h>
00042
00043 #include <cassert>
00044 #include <vector>
00045 #include <algorithm>
00046
00047 #include <System/cmtkSmartPtr.h>
00048 #include <System/cmtkThreads.h>
00049
00050 namespace
00051 cmtk
00052 {
00053
00056
00059 class SplineWarpXform :
00061 public WarpXform
00062 {
00063 public:
00065 typedef SplineWarpXform Self;
00066
00068 typedef WarpXform Superclass;
00069
00071 typedef SmartPointer<Self> SmartPtr;
00072
00074 typedef SmartConstPointer<Self> SmartConstPtr;
00075
00080 SplineWarpXform();
00081
00084 SplineWarpXform( const FixedVector<3,Types::Coordinate>& domain, const Types::Coordinate delta, const AffineXform *initialXform = NULL, const bool exactDelta = false );
00085
00088 void Init( const Self::SpaceVectorType& domain, const Types::Coordinate delta, const AffineXform *initialXform = NULL, const bool exactDelta = false );
00089
00092 SplineWarpXform( const FixedVector<3,Types::Coordinate>& domain, const Self::IndexType& dims, CoordinateVector::SmartPtr& parameters, const AffineXform *initialXform = NULL );
00093
00095 Self::SmartPtr Clone () const
00096 {
00097 return Self::SmartPtr( this->CloneVirtual() );
00098 }
00099
00101 void InitControlPoints( const AffineXform* affineXform = NULL );
00102
00104 virtual void Update( const bool exactDelta = false );
00105
00110 virtual SplineWarpXform* MakeInverse() const
00111 {
00112 return NULL;
00113 }
00114
00116 virtual void Refine();
00117
00119 virtual Types::Coordinate GetGridEnergy() const;
00120
00124 virtual Types::Coordinate GetGridEnergy( const Types::Coordinate *cp ) const;
00125
00128 virtual Types::Coordinate GetGridEnergy( const Self::SpaceVectorType& v ) const;
00129
00131 virtual void GetGridEnergyDerivative( double& lower, double& upper, const int param, const Types::Coordinate step ) const;
00132
00134 virtual Types::Coordinate GetJacobianDeterminant ( const Self::SpaceVectorType& v ) const;
00135
00137 virtual Types::Coordinate GetJacobianDeterminant ( const int x, const int y, const int z ) const;
00138
00140 virtual void GetJacobianDeterminantRow( double *const values, const int x, const int y, const int z, const size_t numberOfPoints = 1 ) const;
00141
00151 Types::Coordinate JacobianDeterminant ( const Types::Coordinate *cp ) const;
00152
00154 virtual Types::Coordinate GetJacobianConstraint() const;
00155
00157 virtual Types::Coordinate GetJacobianFoldingConstraint() const;
00158
00163 virtual void RelaxToUnfold();
00164
00166 virtual Types::Coordinate GetRigidityConstraint() const;
00167
00169 virtual Types::Coordinate GetRigidityConstraint( const DataGrid* weightMap ) const;
00170
00178 virtual Types::Coordinate GetJacobianConstraintSparse() const;
00179
00182 virtual Types::Coordinate GetRigidityConstraintSparse() const;
00183
00185 virtual void GetJacobianConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step ) const;
00186
00188 virtual void GetJacobianFoldingConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step ) const;
00189
00191 virtual void GetJacobianConstraintDerivative( double& lower, double& upper, const int param, const Types::Coordinate step ) const;
00192
00194 virtual void GetRigidityConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step ) const;
00195
00197 virtual void GetRigidityConstraintDerivative( double& lower, double& upper, const int param, const UniformVolume::RegionType&, const Types::Coordinate step,
00198 const DataGrid* weightMap ) const;
00199
00201 virtual void GetRigidityConstraintDerivative( double& lower, double& upper, const int param, const Types::Coordinate step ) const;
00202
00205 virtual Types::Coordinate GetInverseConsistencyError( const WarpXform* inverse, const UniformVolume* volume, const UniformVolume::RegionType* voi = NULL ) const;
00206
00215 virtual bool ApplyInverse ( const Self::SpaceVectorType& v, Self::SpaceVectorType& u, const Types::Coordinate accuracy = 0.01 ) const;
00216
00225 virtual bool ApplyInverseInPlace( Self::SpaceVectorType& v, const Types::Coordinate accuracy = 0.01 ) const;
00226
00241 virtual bool ApplyInverseInPlaceWithInitial( Self::SpaceVectorType& v, const Self::SpaceVectorType& initial, const Types::Coordinate accuracy = 0.01 ) const;
00242
00244 virtual void ApplyInPlace( Self::SpaceVectorType& v ) const
00245 {
00246 Types::Coordinate r[3], f[3];
00247 int grid[3];
00248
00249
00250 {
00251 for ( int dim = 0; dim<3; ++dim )
00252 {
00253
00254
00255 r[dim] = this->InverseSpacing[dim] * v[dim];
00256
00257 grid[dim] = std::min<int>( static_cast<int>( r[dim] ), this->m_Dims[dim]-4 );
00258
00259 f[dim] = r[dim] - grid[dim];
00260 }
00261 }
00262
00263
00264 const Types::Coordinate* coeff = this->m_Parameters + 3 * ( grid[0] + this->m_Dims[0] * (grid[1] + this->m_Dims[1] * grid[2]) );
00265
00266 for ( int dim = 0; dim<3; ++dim )
00267 {
00268 Types::Coordinate mm = 0;
00269 const Types::Coordinate *coeff_mm = coeff;
00270
00271
00272 for ( int m = 0; m < 4; ++m )
00273 {
00274 Types::Coordinate ll = 0;
00275 const Types::Coordinate *coeff_ll = coeff_mm;
00276
00277
00278 for ( int l = 0; l < 4; ++l )
00279 {
00280 Types::Coordinate kk = 0;
00281 const Types::Coordinate *coeff_kk = coeff_ll;
00282
00283
00284 for ( int k = 0; k < 4; ++k, coeff_kk+=3 )
00285 {
00286 kk += CubicSpline::ApproxSpline( k, f[0] ) * (*coeff_kk);
00287 }
00288 ll += CubicSpline::ApproxSpline( l, f[1] ) * kk;
00289 coeff_ll += nextJ;
00290 }
00291 mm += CubicSpline::ApproxSpline( m, f[2] ) * ll;
00292 coeff_mm += nextK;
00293 }
00294 v[dim] = mm;
00295 ++coeff;
00296 }
00297 }
00298
00300 virtual void GetVolumeOfInfluence( const size_t idx, const Self::SpaceVectorType&, const Self::SpaceVectorType&, Self::SpaceVectorType&, Self::SpaceVectorType&, const int = -1 ) const;
00301
00303 void RegisterVolume( const UniformVolume* volume )
00304 {
00305 this->RegisterVolumePoints( volume->m_Dims, volume->m_Delta, volume->m_Offset );
00306 }
00307
00309 void UnRegisterVolume();
00310
00312 void GetTransformedGrid( Self::SpaceVectorType& v, const int idxX, const int idxY, const int idxZ ) const;
00313
00315 void GetTransformedGridRow( const int numPoints, Self::SpaceVectorType *const v, const int idxX, const int idxY, const int idxZ ) const;
00316
00318 virtual Types::Coordinate GetParamStep( const size_t idx, const Self::SpaceVectorType& volSize, const Types::Coordinate mmStep = 1 ) const
00319 {
00320 return 4 * WarpXform::GetParamStep( idx, volSize, mmStep );
00321 }
00322
00330 virtual Self::SpaceVectorType& GetDeformedControlPointPosition( Self::SpaceVectorType&, const int, const int, const int ) const;
00331
00338 Types::Coordinate* GetPureDeformation( const bool includeScale = false ) const;
00339
00341 virtual CoordinateMatrix3x3 GetJacobian( const Self::SpaceVectorType& v ) const;
00342
00344 virtual void GetJacobian( const Self::SpaceVectorType& v, CoordinateMatrix3x3& J ) const;
00345
00347 virtual void GetJacobianAtControlPoint( const Types::Coordinate* cp, CoordinateMatrix3x3& J ) const;
00348
00350 virtual void GetJacobianRow( CoordinateMatrix3x3 *const array, const int x, const int y, const int z, const size_t numberOfPoints ) const;
00351
00352 private:
00354 void RegisterVolumePoints ( const DataGrid::IndexType&, const Self::SpaceVectorType& );
00355
00357 void RegisterVolumePoints( const DataGrid::IndexType&, const Self::SpaceVectorType&, const Self::SpaceVectorType& );
00358
00360 void RegisterVolumeAxis ( const DataGrid::IndexType::ValueType, const Types::Coordinate delta, const Types::Coordinate origin, const int, const Types::Coordinate,
00361 std::vector<int>& g, std::vector<Types::Coordinate>& spline, std::vector<Types::Coordinate>& dspline );
00362
00364 Types::Coordinate GetRigidityConstraint( const CoordinateMatrix3x3& J ) const;
00365
00366 protected:
00368 virtual SplineWarpXform* CloneVirtual () const;
00369
00371 DataGrid::IndexType VolumeDims;
00372
00378
00379 std::vector<int> gX;
00381 std::vector<int> gY;
00383 std::vector<int> gZ;
00385
00391
00392 std::vector<Types::Coordinate> splineX;
00394 std::vector<Types::Coordinate> splineY;
00396 std::vector<Types::Coordinate> splineZ;
00398
00404
00405 std::vector<Types::Coordinate> dsplineX;
00407 std::vector<Types::Coordinate> dsplineY;
00409 std::vector<Types::Coordinate> dsplineZ;
00411
00413 int GridPointOffset[48];
00414
00419 void Init ();
00420
00426 typedef struct
00427 {
00429 const SplineWarpXform *thisObject;
00431 int ThisThreadIndex;
00433 int NumberOfThreads;
00435 Types::Coordinate Constraint;
00436 } JacobianConstraintThreadInfo;
00437
00439 static void GetJacobianConstraintThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t );
00440
00442 static void GetJacobianFoldingConstraintThread( void *const args, const size_t taskIdx, const size_t taskCnt, const size_t, const size_t );
00443
00445 void FindClosestControlPoint( const Self::SpaceVectorType& v, Self::SpaceVectorType& cp ) const;
00446
00448 friend class SplineWarpXformUniformVolume;
00449 };
00450
00451 }
00452
00453 #endif // #ifndef __cmtkSplineWarpXform_h_included_