/vol/vipdata/irtk/packages/transformation/include/irtkFreeFormTransformation3D.h

00001 /*=========================================================================
00002 
00003   Library   : Image Registration Toolkit (IRTK)
00004   Module    : $Id: irtkFreeFormTransformation3D.h 2 2008-12-23 12:40:14Z dr $
00005   Copyright : Imperial College, Department of Computing
00006               Visual Information Processing (VIP), 2008 onwards
00007   Date      : $Date: 2008-12-23 12:40:14 +0000 (Tue, 23 Dec 2008) $
00008   Version   : $Revision: 2 $
00009   Changes   : $Author: dr $
00010 
00011 =========================================================================*/
00012 
00013 #ifndef _IRTKFREEFORMTRANSFORMATION3D_H
00014 
00015 #define _IRTKFREEFORMTRANSFORMATION3D_H
00016 
00017 #include <irtkGeometry.h>
00018 
00019 #define FFDLOOKUPTABLESIZE 1000
00020 
00028 class irtkFreeFormTransformation3D : public irtkFreeFormTransformation
00029 {
00030 
00031 protected:
00032 
00034   int _x;
00035 
00037   int _y;
00038 
00040   int _z;
00041 
00043   double _dx;
00044 
00046   double _dy;
00047 
00049   double _dz;
00050 
00052   double _xaxis[3];
00053 
00055   double _yaxis[3];
00056 
00058   double _zaxis[3];
00059 
00061   irtkPoint _origin;
00062 
00064   irtkMatrix _matL2W;
00065 
00067   irtkMatrix _matW2L;
00068 
00070   double ***_xdata;
00071 
00073   double ***_ydata;
00074 
00076   double ***_zdata;
00077 
00079   static double ***Allocate  (double ***, int, int, int);
00080 
00082   static double ***Deallocate(double ***, int, int, int);
00083 
00085   virtual void UpdateMatrix();
00086 
00087 public:
00088 
00090   virtual int GetX() const;
00091 
00093   virtual int GetY() const;
00094 
00096   virtual int GetZ() const;
00097 
00099   virtual int NumberOfDOFs() const;
00100 
00102   virtual void GetSpacing(double &, double &, double &) const;
00103 
00105   virtual void  PutOrientation(double *, double *, double *);
00106 
00108   virtual void  GetOrientation(double *, double *, double *) const;
00109 
00111   virtual void   Put(int, double);
00112 
00114   virtual void   Put(int, int, int, double, double, double);
00115 
00117   virtual double Get(int) const;
00118 
00120   virtual void   Get(int, int, int, double &, double &, double &) const;
00121 
00123   virtual void   PutStatus(int, int, int, _Status);
00124 
00126   virtual void   PutStatus(int, int, int, _Status, _Status, _Status);
00127 
00129   virtual void   PutStatus(int, _Status);
00130 
00132   virtual void   GetStatus(int, int, int, _Status &, _Status &, _Status &);
00133 
00135   virtual _Status GetStatus(int);
00136 
00138   virtual double Bending(double x, double y, double z) = 0;
00139 
00141   virtual void WorldToLattice(double &, double &, double &) const;
00142 
00144   virtual void WorldToLattice(irtkPoint &) const;
00145 
00147   virtual void LatticeToWorld(double &, double &, double &) const;
00148 
00150   virtual void LatticeToWorld(irtkPoint &) const;
00151 
00153   virtual void IndexToLattice(int index, int& i, int& j, int& k) const;
00154 
00156   virtual int  LatticeToIndex(int i, int j, int k) const;
00157 
00159   virtual void  ControlPointLocation(int, double &, double &, double &) const;
00160 
00162   virtual irtkPoint ControlPointLocation(int) const;
00163 
00165   virtual void PutBoundingBox(irtkPoint, irtkPoint);
00166 
00168   virtual void PutBoundingBox(double, double, double,
00169                               double, double, double);
00170 
00172   virtual void BoundingBox(irtkPoint &, irtkPoint &) const;
00173 
00175   virtual void BoundingBox(double &, double &, double &,
00176                            double &, double &, double &) const;
00177 
00182   virtual void BoundingBox(int, irtkPoint &, irtkPoint &, double = 1) const = 0;
00183 
00188   virtual void BoundingBox(int, double &, double &, double &,
00189                            double &, double &, double &, double = 1) const = 0;
00190 
00195   virtual void BoundingBox(irtkGreyImage *, int, int &, int &, int &,
00196                            int &, int &, int &, double = 1) const = 0;
00197 
00202   virtual double Approximate(double *, double *, double *,
00203                              double *, double *, double *, int) = 0;
00204 
00211   virtual void Interpolate(double* dxs, double* dys, double* dzs) = 0;
00212 
00214   virtual double Inverse(double &, double &, double &, double, double = 0.01);
00215 
00217   virtual Bool IsIdentity();
00218 
00220   virtual const char *NameOfClass();
00221 
00222 };
00223 
00224 inline int irtkFreeFormTransformation3D::GetX() const
00225 {
00226   return _x;
00227 }
00228 
00229 inline int irtkFreeFormTransformation3D::GetY() const
00230 {
00231   return _y;
00232 }
00233 
00234 inline int irtkFreeFormTransformation3D::GetZ() const
00235 {
00236   return _z;
00237 }
00238 
00239 inline int irtkFreeFormTransformation3D::NumberOfDOFs() const
00240 {
00241   return 3*_x*_y*_z;
00242 }
00243 
00244 inline double irtkFreeFormTransformation3D::Get(int index) const
00245 {
00246   int i, j, k;
00247 
00248   if (index >= 3*_x*_y*_z) {
00249     cerr << "irtkFreeFormTransformation3D::Get: No such dof" << endl;
00250     exit(1);
00251   }
00252   if (index < _x*_y*_z) {
00253     i = index/(_y*_z);
00254     j = index%(_y*_z)/_z;
00255     k = index%(_y*_z)%_z;
00256     return _xdata[k][j][i];
00257   } else {
00258     if (index < 2*_x*_y*_z) {
00259       index -= _x*_y*_z;
00260       i = index/(_y*_z);
00261       j = index%(_y*_z)/_z;
00262       k = index%(_y*_z)%_z;
00263       return _ydata[k][j][i];
00264     } else {
00265       index -= 2*_x*_y*_z;
00266       i = index/(_y*_z);
00267       j = index%(_y*_z)/_z;
00268       k = index%(_y*_z)%_z;
00269       return _zdata[k][j][i];
00270     }
00271   }
00272 }
00273 
00274 inline void irtkFreeFormTransformation3D::Get(int i, int j, int k, double &x, double &y, double &z) const
00275 {
00276   if ((i < 0) || (i >= _x) || (j < 0) || (j >= _y) || (k < 0) || (k >= _z)) {
00277     cerr << "irtkFreeFormTransformation3D::Get: No such dof" << endl;
00278     exit(1);
00279   }
00280   x = _xdata[k][j][i];
00281   y = _ydata[k][j][i];
00282   z = _zdata[k][j][i];
00283 }
00284 
00285 inline void irtkFreeFormTransformation3D::Put(int index, double x)
00286 {
00287   irtkPoint p;
00288   int i, j, k;
00289 
00290   if (index >= 3*_x*_y*_z) {
00291     cerr << "irtkFreeFormTransformation3D::Put: No such dof" << endl;
00292     exit(1);
00293   }
00294   if (index < _x*_y*_z) {
00295     i = index/(_y*_z);
00296     j = index%(_y*_z)/_z;
00297     k = index%(_y*_z)%_z;
00298     _xdata[k][j][i] = x;
00299   } else {
00300     if (index < 2*_x*_y*_z) {
00301       index -= _x*_y*_z;
00302       i = index/(_y*_z);
00303       j = index%(_y*_z)/_z;
00304       k = index%(_y*_z)%_z;
00305       _ydata[k][j][i] = x;
00306     } else {
00307       index -= 2*_x*_y*_z;
00308       i = index/(_y*_z);
00309       j = index%(_y*_z)/_z;
00310       k = index%(_y*_z)%_z;
00311       _zdata[k][j][i] = x;
00312     }
00313   }
00314 }
00315 
00316 inline void irtkFreeFormTransformation3D::Put(int i, int j, int k, double x, double y, double z)
00317 {
00318   if ((i < 0) || (i >= _x) || (j < 0) || (j >= _y) || (k < 0) || (k >= _z)) {
00319     cerr << "irtkFreeFormTransformation3D::Put: No such dof" << endl;
00320     exit(1);
00321   }
00322   _xdata[k][j][i] = x;
00323   _ydata[k][j][i] = y;
00324   _zdata[k][j][i] = z;
00325 }
00326 
00327 inline void irtkFreeFormTransformation3D::GetSpacing(double &dx, double &dy, double &dz) const
00328 {
00329   dx = _dx;
00330   dy = _dy;
00331   dz = _dz;
00332 }
00333 
00334 inline void irtkFreeFormTransformation3D::PutOrientation(double *xaxis, double *yaxis, double *zaxis)
00335 {
00336   _xaxis[0] = xaxis[0];
00337   _xaxis[1] = xaxis[1];
00338   _xaxis[2] = xaxis[2];
00339   _yaxis[0] = yaxis[0];
00340   _yaxis[1] = yaxis[1];
00341   _yaxis[2] = yaxis[2];
00342   _zaxis[0] = zaxis[0];
00343   _zaxis[1] = zaxis[1];
00344   _zaxis[2] = zaxis[2];
00345 
00346   this->UpdateMatrix();
00347 }
00348 
00349 inline void irtkFreeFormTransformation3D::GetOrientation(double *xaxis, double *yaxis, double *zaxis) const
00350 {
00351   xaxis[0] = _xaxis[0];
00352   xaxis[1] = _xaxis[1];
00353   xaxis[2] = _xaxis[2];
00354   yaxis[0] = _yaxis[0];
00355   yaxis[1] = _yaxis[1];
00356   yaxis[2] = _yaxis[2];
00357   zaxis[0] = _zaxis[0];
00358   zaxis[1] = _zaxis[1];
00359   zaxis[2] = _zaxis[2];
00360 }
00361 
00362 inline void irtkFreeFormTransformation3D::PutBoundingBox(double x1, double y1, double z1, double x2, double y2, double z2)
00363 {
00364   // Initialize control point domain
00365   _origin._x = (x2 + x1) / 2.0;
00366   _origin._y = (y2 + y1) / 2.0;
00367   _origin._z = (z2 + z1) / 2.0;
00368 
00369   double a = x1 * _xaxis[0] + y1 * _xaxis[1] + z1 * _xaxis[2];
00370   double b = x1 * _yaxis[0] + y1 * _yaxis[1] + z1 * _yaxis[2];
00371   double c = x1 * _zaxis[0] + y1 * _zaxis[1] + z1 * _zaxis[2];
00372   x1 = a;
00373   y1 = b;
00374   z1 = c;
00375   a = x2 * _xaxis[0] + y2 * _xaxis[1] + z2 * _xaxis[2];
00376   b = x2 * _yaxis[0] + y2 * _yaxis[1] + z2 * _yaxis[2];
00377   c = x2 * _zaxis[0] + y2 * _zaxis[1] + z2 * _zaxis[2];
00378   x2 = a;
00379   y2 = b;
00380   z2 = c;
00381 
00382   // Initialize control point spacing
00383   _dx = (x2 - x1) / (_x - 1);
00384   _dy = (y2 - y1) / (_y - 1);
00385   if (z2 > z1) {
00386     _dz = (z2 - z1) / (_z - 1);
00387   } else {
00388     _dz = 1;
00389   }
00390 
00391   this->UpdateMatrix();
00392 }
00393 
00394 inline void irtkFreeFormTransformation3D::PutBoundingBox(irtkPoint p1, irtkPoint p2)
00395 {
00396   this->PutBoundingBox(p1._x, p1._y, p1._z, p2._x, p2._y, p2._z);
00397 }
00398 
00399 inline void irtkFreeFormTransformation3D::WorldToLattice(double &x, double &y, double &z) const
00400 {
00401   double a, b, c;
00402 
00403   // Pre-multiply point with transformation matrix
00404   a = _matW2L(0, 0)*x+_matW2L(0, 1)*y+_matW2L(0, 2)*z+_matW2L(0, 3);
00405   b = _matW2L(1, 0)*x+_matW2L(1, 1)*y+_matW2L(1, 2)*z+_matW2L(1, 3);
00406   c = _matW2L(2, 0)*x+_matW2L(2, 1)*y+_matW2L(2, 2)*z+_matW2L(2, 3);
00407 
00408   // Copy result back
00409   x = a;
00410   y = b;
00411   z = c;
00412 }
00413 
00414 inline void irtkFreeFormTransformation3D::WorldToLattice(irtkPoint &p) const
00415 {
00416   this->WorldToLattice(p._x, p._y, p._z);
00417 }
00418 
00419 inline void irtkFreeFormTransformation3D::LatticeToWorld(double &x, double &y, double &z) const
00420 {
00421   double a, b, c;
00422 
00423   // Pre-multiply point with transformation matrix
00424   a = _matL2W(0, 0)*x+_matL2W(0, 1)*y+_matL2W(0, 2)*z+_matL2W(0, 3);
00425   b = _matL2W(1, 0)*x+_matL2W(1, 1)*y+_matL2W(1, 2)*z+_matL2W(1, 3);
00426   c = _matL2W(2, 0)*x+_matL2W(2, 1)*y+_matL2W(2, 2)*z+_matL2W(2, 3);
00427 
00428   // Copy result back
00429   x = a;
00430   y = b;
00431   z = c;
00432 }
00433 
00434 inline void irtkFreeFormTransformation3D::LatticeToWorld(irtkPoint &p) const
00435 {
00436   this->LatticeToWorld(p._x, p._y, p._z);
00437 }
00438 
00439 inline void irtkFreeFormTransformation3D::IndexToLattice(int index, int& i, int& j, int& k) const
00440 {
00441 
00442   if (index >= _x*_y*_z) {
00443     index -= _x*_y*_z;
00444     if (index >= _x*_y*_z) {
00445       index -= _x*_y*_z;
00446     }
00447   }
00448   i = index/(_y*_z);
00449   j = index%(_y*_z)/_z;
00450   k = index%(_y*_z)%_z;
00451 }
00452 
00453 inline int irtkFreeFormTransformation3D::LatticeToIndex(int i, int j, int k) const
00454 {
00455   return i * _y * _z + j * _z + k;
00456 }
00457 
00458 inline const char *irtkFreeFormTransformation3D::NameOfClass()
00459 {
00460   return "irtkFreeFormTransformation3D";
00461 }
00462 
00463 #endif