FreeFormTransformation.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2017 Imperial College London
5  * Copyright 2008-2013 Daniel Rueckert, Julia Schnabel
6  * Copyright 2013-2017 Andreas Schuh
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef MIRTK_FreeFormTransformation_H
22 #define MIRTK_FreeFormTransformation_H
23 
24 #include "mirtk/Transformation.h"
25 
26 #include "mirtk/Math.h"
27 #include "mirtk/Memory.h"
28 #include "mirtk/Vector3D.h"
29 #include "mirtk/InterpolateImageFunction.h"
30 #include "mirtk/ExtrapolateImageFunction.h"
31 #include "mirtk/TransformationJacobian.h"
32 #include "mirtk/ImageFunction.h"
33 
34 
35 namespace mirtk {
36 
37 
38 /**
39  * Base class for free-form transformations.
40  */
42 {
43  mirtkAbstractTransformationMacro(FreeFormTransformation);
44 
45 public:
46 
47  /// Default attributes of free-form transformation lattice
48  ///
49  /// \param[in] attr (Target) image attributes.
50  /// \param[in] dx Control point spacing in x.
51  /// \param[in] dy Control point spacing in y.
52  /// \param[in] dz Control point spacing in z.
53  /// \param[in] dt Control point spacing in t.
54  ///
55  /// \note If a control point number/spacing is negative, it is set to the specified number/size.
57  double dx = -1.0,
58  double dy = -1.0,
59  double dz = -1.0,
60  double dt = -1.0);
61 
62  /// Default attributes of free-form transformation lattice
63  static ImageAttributes DefaultAttributes(double, double, double, double,
64  double, double, double, double,
65  double, double, double, double,
66  const double *, const double *,
67  const double *);
68 
69  // ---------------------------------------------------------------------------
70  // Types
71 
72  /// Type of vector storing the coefficients at a control point
74 
75  /// Type of image representation of free-form transformation
77 
78  /// Type of vector storing status of control point coefficients
80 
81  /// Base type used for interpolation of control point data
82  /// \note Subclasses may use a particular specialized interpolation type.
84 
85  /// Base type used for extrapolation of control point data
87 
88  /// Alias for CPValue type which is preferred when referring to any FFD vector,
89  /// not only those at control point locations
90  typedef CPValue Vector;
91 
92  // ---------------------------------------------------------------------------
93  // Attributes
94 
95  /// Mode used for extrapolation of control point image
97 
98  /// Speedup factor for gradient computation
99  mirtkPublicAttributeMacro(double, SpeedupFactor);
100 
101 public:
102 
103  /// Set extrapolation mode
104  virtual void ExtrapolationMode(enum ExtrapolationMode);
105 
106  /// Get access to control point coefficients extrapolator
107  /// Intended for use by non-member auxiliary functions of subclass implementations.
108  const CPExtrapolator *Extrapolator() const;
109 
110 protected:
111 
112  /// Finite discrete representation of free-form transformation coefficients
113  ///
114  /// Note that this image instance stores all the attributes of the control
115  /// point lattice. The actual control point data is stored in the parameters
116  /// of the transformation, the memory of which is managed by the base class.
117  /// The image only wraps this memory and interprets it as an image. This allows
118  /// the use of image functions such as interpolators and efficient image filters.
119  CPImage _CPImage;
120 
121  /// Infinite discrete representation of free-form transformation coefficients
122  CPExtrapolator *_CPValue;
123 
124  /// Infinite continuous function of free-form transformation
125  ///
126  /// Note that the actual interpolator object is (at the moment) attribute of
127  /// the specific FFD implementation. The base class pointer here is only used
128  /// to update the interpolator when necessary, e.g., when the extrapolation
129  /// mode has changed. It is set by the base class constructor to the
130  /// respective interpolate image function attribute of the subclass.
131  CPInterpolator *_CPFunc;
132  CPInterpolator *_CPFunc2D; // TODO: Remove when 2D FFDs are separate classes
133 
134  /// Status of control points
135  ///
136  /// Note that the actual status values are stored by the base class member
137  /// Transformation::_Status in a contiguous memory block.
138  CPStatus ****_CPStatus;
139 
140  const ImageAttributes &_attr; ///< Control point lattice attributes
141 
142  const int &_x; ///< Read-only reference to _x attribute of _CPImage
143  const int &_y; ///< Read-only reference to _y attribute of _CPImage
144  const int &_z; ///< Read-only reference to _z attribute of _CPImage
145  const int &_t; ///< Read-only reference to _t attribute of _CPImage
146 
147  const double &_dx; ///< Read-only reference to _dx attribute of _CPImage
148  const double &_dy; ///< Read-only reference to _dy attribute of _CPImage
149  const double &_dz; ///< Read-only reference to _dz attribute of _CPImage
150  const double &_dt; ///< Read-only reference to _dt attribute of _CPImage
151 
152  const Matrix &_matW2L; ///< Read-only reference to _matW2I of _CPImage
153  const Matrix &_matL2W; ///< Read-only reference to _matI2W of _CPImage
154 
155  // ---------------------------------------------------------------------------
156  // Construction/Destruction
157 
158  /// Initialize interpolator of control points
159  void InitializeInterpolator();
160 
161  /// Initialize status of control points
162  void InitializeStatus();
163 
164  /// Initialize control points
165  void InitializeCPs(const ImageAttributes &, bool = true);
166 
167  /// Copy control points from other transformation
168  void InitializeCPs(const FreeFormTransformation &, bool = true);
169 
170  /// Default constructor
171  FreeFormTransformation(CPInterpolator &, CPInterpolator * = NULL);
172 
173  /// Copy constructor
175  CPInterpolator &, CPInterpolator * = NULL);
176 
177 public:
178 
179  /// Destructor
180  virtual ~FreeFormTransformation();
181 
182  /// Initialize free-form transformation
183  virtual void Initialize(const ImageAttributes &) = 0;
184 
185  /// Initialize free-form transformation
186  void Initialize(const ImageAttributes &, double, double, double = -1.0, double = -1.0);
187 
188  /// Initialize transformation from existing vector field
189  void Initialize(const CPImage &, bool = false);
190 
191  /// Initialize transformation from existing 3D+t vector field
192  void Initialize(const GenericImage<double> &, bool = false);
193 
194  // ---------------------------------------------------------------------------
195  // Parameters (non-DoFs)
196 
197  // Import other Parameter overloads
199 
200  /// Set named (non-DoF) parameter from value as string
201  virtual bool Set(const char *, const char *);
202 
203  /// Get (non-DoF) parameters as key/value as string map
204  virtual ParameterList Parameter() const;
205 
206  // ---------------------------------------------------------------------------
207  // Approximation/Interpolation
208 
213 
214  /// Get image domain on which this free-form transformation should be defined
215  /// in order to reduce the error when the given transformation is approximated
216  /// and the resulting free-form transformation is applied to resample an image
217  /// that is defined on the specified lattice.
219  const Transformation *);
220 
221  /// Evaluates RMS error of transformation at control points compared to another.
222  double EvaluateRMSError(const Transformation *) const;
223 
224  /// Approximate transformation: This function takes a transformation and finds
225  /// a FFD which approximates this transformation at the control point locations.
226  /// Returns the approximation error of the resulting FFD at the control point locations.
227  virtual double Approximate(const Transformation *, int = 1, double = .0);
228 
229  /// Approximate displacements: This function takes a set of points and a set
230  /// of displacements and finds a transformation which approximates these
231  /// displacements. After approximation, the displacements are replaced by the
232  /// residual displacement errors at the points.
233  virtual double Approximate(const ImageAttributes &, double *, double *, double *,
234  int = 1, double = .0);
235 
236  /// Approximate displacements: This function takes a set of points and a set
237  /// of displacements and finds a transformation which approximates these
238  /// displacements. After approximation, the displacements are replaced by the
239  /// residual displacement errors at the points.
240  virtual double Approximate(const double *, const double *, const double *,
241  double *, double *, double *, int,
242  int = 1, double = .0);
243 
244  /// Approximate displacements: This function takes a set of points and a set
245  /// of displacements and finds a transformation which approximates these
246  /// displacements. After approximation, the displacements are replaced by the
247  /// residual displacement errors at the points.
248  virtual double Approximate(const double *, const double *, const double *, const double *,
249  double *, double *, double *, int,
250  int = 1, double = .0);
251 
252  /// Approximate another transformation and return approximation error
253  virtual double ApproximateAsNew(const Transformation *, int = 1, double = .0);
254 
255  /// Approximate displacements: This function takes a set of points and a set
256  /// of displacements and finds a !new! transformation which approximates these
257  /// displacements. After approximation, the displacements are replaced by the
258  /// residual displacement errors at the points.
259  virtual double ApproximateAsNew(const ImageAttributes &, double *, double *, double *,
260  int = 1, double = .0);
261 
262  /// Interpolates displacements: This function takes a set of displacements defined
263  /// at the control points and finds a FFD which interpolates these displacements.
264  virtual void Interpolate(const double *, const double *, const double *) = 0;
265 
266  // ---------------------------------------------------------------------------
267  // Lattice
268 
269  /// Returns attributes of control point grid
270  const ImageAttributes &Attributes() const;
271 
272  /// Actual number of DoFs, i.e.,
273  /// 2 * NumberOfDOFs for 2D FFD or 3 * NumberOfDOFs for 3D(+t) FFD
274  int ActualNumberOfDOFs() const;
275 
276  /// Number of control points
277  int NumberOfCPs() const;
278 
279  /// Number of active control points
280  int NumberOfActiveCPs() const;
281 
282  /// Number of non-active control points
283  int NumberOfPassiveCPs() const;
284 
285  /// Returns the number of control points in x
286  int X() const;
287 
288  /// Returns the number of control points in y
289  int Y() const;
290 
291  /// Returns the number of control points in z
292  int Z() const;
293 
294  /// Returns the number of control points in t
295  int T() const;
296 
297  /// Returns the number of control points in x
298  int GetX() const;
299 
300  /// Returns the number of control points in y
301  int GetY() const;
302 
303  /// Returns the number of control points in z
304  int GetZ() const;
305 
306  /// Returns the number of control points in t
307  int GetT() const;
308 
309  /// Returns the of control point spacing in x
310  double GetXSpacing() const;
311 
312  /// Returns the of control point spacing in y
313  double GetYSpacing() const;
314 
315  /// Returns the of control point spacing in z
316  double GetZSpacing() const;
317 
318  /// Returns the of control point spacing in t
319  double GetTSpacing() const;
320 
321  /// Gets the control point spacing (in mm)
322  void GetSpacing(double &, double &, double &) const;
323 
324  /// Gets the control point spacing (in mm)
325  void GetSpacing(double &, double &, double &, double &) const;
326 
327  /// Puts the orientation of the free-form deformation lattice
328  void PutOrientation(double *, double *, double *);
329 
330  /// Gets the orientation of the free-form deformation lattice
331  void GetOrientation(double *, double *, double *) const;
332 
333  /// Get indices of transformation parameters (DoFs)
334  void IndexToDOFs(int, int &, int &) const;
335 
336  /// Get indices of transformation parameters (DoFs)
337  void IndexToDOFs(int, int &, int &, int &) const;
338 
339  /// Get index of control point corresponding to transformation parameter (DoFs)
340  int DOFToIndex(int) const;
341 
342  /// Get index of dimension corresponding to transformation parameter (DoFs)
343  int DOFToDimension(int) const;
344 
345  /// Get control point index from lattice coordinates
346  int LatticeToIndex(int, int, int = 0, int = 0) const;
347 
348  /// Get control point lattice coordinates from index
349  void IndexToLattice(int, int &, int &) const;
350 
351  /// Get control point lattice coordinates from index
352  void IndexToLattice(int, int &, int &, int &) const;
353 
354  /// Get control point lattice coordinates from index
355  void IndexToLattice(int, int &, int &, int &, int &) const;
356 
357  /// Get world coordinates (in mm) of control point
358  void IndexToWorld(int, double &, double &) const;
359 
360  /// Get world coordinates (in mm) of control point
361  void IndexToWorld(int, double &, double &, double &) const;
362 
363  /// Get world coordinates (in mm) of control point
364  void IndexToWorld(int, Point &) const;
365 
366  /// Get world coordinates (in mm) of control point
367  Point IndexToWorld(int) const;
368 
369  /// Transforms world coordinates (in mm) to lattice coordinates
370  virtual void WorldToLattice(double &, double &) const;
371 
372  /// Transforms world coordinates (in mm) to lattice coordinates
373  virtual void WorldToLattice(double &, double &, double &) const;
374 
375  /// Transforms world coordinates (in mm) to lattice coordinates
376  virtual void WorldToLattice(Point &) const;
377 
378  /// Transforms lattice coordinates to world coordinates (in mm)
379  virtual void LatticeToWorld(double &, double &) const;
380 
381  /// Transforms lattice coordinates to world coordinates (in mm)
382  virtual void LatticeToWorld(double &, double &, double &) const;
383 
384  /// Transforms lattice coordinates to world coordinates (in mm)
385  virtual void LatticeToWorld(Point &) const;
386 
387  /// Gets the location of the given control point (in mm)
388  void ControlPointLocation(int, double &, double &) const;
389 
390  /// Gets the location of the given control point (in mm)
391  void ControlPointLocation(int, double &, double &, double &) const;
392 
393  /// Returns the location of the given control point (in mm)
394  Point ControlPointLocation(int) const;
395 
396  /// Transforms time (in ms) to temporal lattice coordinate
397  virtual double TimeToLattice(double) const;
398 
399  /// Transforms temporal lattice coordinate to time (in ms)
400  virtual double LatticeToTime(double) const;
401 
402  /// Returns the number of control points in x after subdivision
403  virtual int GetXAfterSubdivision() const;
404 
405  /// Returns the number of control points in y after subdivision
406  virtual int GetYAfterSubdivision() const;
407 
408  /// Returns the number of control points in z after subdivision
409  virtual int GetZAfterSubdivision() const;
410 
411  /// Returns the number of control points in t after subdivision
412  virtual int GetTAfterSubdivision() const;
413 
414  /// Returns the control point spacing in x after the subdivision
415  virtual double GetXSpacingAfterSubdivision() const;
416 
417  /// Returns the control point spacing in y after the subdivision
418  virtual double GetYSpacingAfterSubdivision() const;
419 
420  /// Returns the control point spacing in z after the subdivision
421  virtual double GetZSpacingAfterSubdivision() const;
422 
423  /// Returns the control point spacing in t after the subdivision
424  virtual double GetTSpacingAfterSubdivision() const;
425 
426  /// Subdivide lattice of free-form transformation
427  virtual void Subdivide(bool = true, bool = true, bool = true, bool = true);
428 
429  /// Subdivide lattice in first two dimensions
430  void Subdivide2D();
431 
432  /// Subdivide lattice in first three dimensions
433  void Subdivide3D();
434 
435  /// Subdivide lattice in all four dimensions
436  void Subdivide4D();
437 
438  /// Crop/pad lattice to discard passive control points at the boundary,
439  /// keeping only a layer of passive control points of given width.
440  /// The DoF values of passive control points are optionally reset to zero.
441  bool CropPadPassiveCPs(int = 0, bool = false);
442 
443  /// Crop/pad lattice to discard passive control points at the boundary,
444  /// keeping only a layer of passive control points of given width.
445  /// The DoF values of passive control points are optionally reset to zero.
446  virtual bool CropPadPassiveCPs(int, int, int = 0, int = 0, bool = false);
447 
448  // ---------------------------------------------------------------------------
449  // Bounding box
450 
451  /// Size of support region of the used kernel
452  virtual int KernelSize() const = 0;
453 
454  /// Radius of support region of the used kernel
455  int KernelRadius() const;
456 
457  /// Puts the spatial bounding box for the free-form deformation (in mm)
458  void PutBoundingBox(double, double, double,
459  double, double, double);
460 
461  /// Puts the temporal bounding box for the free-form deformation (in mm)
462  void PutBoundingBox(const Point &, const Point &);
463 
464  /// Puts the temporal bounding box of the free-form deformation (in ms)
465  void PutBoundingBox(double, double);
466 
467  /// Puts the spatio-temporal bounding box for the free-form deformation (in mm)
468  void PutBoundingBox(double, double, double, double,
469  double, double, double, double);
470 
471  /// Gets the temporal bounding box of the free-form deformation (in ms)
472  void BoundingBox(double &, double &) const;
473 
474  /// Gets the spatial bounding box of the free-form deformation (in mm)
475  void BoundingBox(double &, double &, double &,
476  double &, double &, double &) const;
477 
478  /// Gets the spatial bounding box of the free-form deformation (in mm)
479  void BoundingBox(Point &, Point &) const;
480 
481  /// Gets the spatio-temporal bounding box of the free-form deformation (in mm and ms)
482  void BoundingBox(double &, double &, double &, double &,
483  double &, double &, double &, double &) const;
484 
485  /// Gets the spatio-temporal bounding box of the free-form deformation (in mm and ms)
486  void BoundingBox(Point &, double &, Point &, double &) const;
487 
488  /// Gets the temporal bounding box for a control point. The last parameter
489  /// specifies what fraction of the bounding box to return. The default
490  /// is 1 which equals 100% of the bounding box.
491  virtual void BoundingBox(int, double &, double &, double = 1) const;
492 
493  /// Gets the spatial bounding box for a control point. The last parameter
494  /// specifies what fraction of the bounding box to return. The default
495  /// is 1 which equals 100% of the bounding box.
496  virtual void BoundingBox(int, double &, double &, double &,
497  double &, double &, double &, double = 1) const = 0;
498 
499  /// Gets the spatio-temporal bounding box for a control point. The last parameter
500  /// specifies what fraction of the bounding box to return. The default
501  /// is 1 which equals 100% of the bounding box.
502  virtual void BoundingBox(int, double &, double &, double &, double &,
503  double &, double &, double &, double &, double = 1) const;
504 
505  /// Gets the spatial bounding box for a control point. The last parameter
506  /// specifies what fraction of the bounding box to return. The default
507  /// is 1 which equals 100% of the bounding box.
508  void BoundingBox(int, Point &, Point &, double = 1) const;
509 
510  /// Gets the spatial bounding box for a control point in lattice coordinates.
511  /// The last parameter specifies what fraction of the bounding box to return.
512  /// The default is 1 which equals 100% of the bounding box.
513  bool BoundingBox(const ImageAttributes &, int, int &, int &, int &,
514  int &, int &, int &, double = 1) const;
515 
516  /// Gets the spatio-temporal bounding box for a control point in lattice coordinates.
517  /// The last parameter specifies what fraction of the bounding box to return.
518  /// The default is 1 which equals 100% of the bounding box.
519  bool BoundingBox(const ImageAttributes &, int, int &, int &, int &, int &,
520  int &, int &, int &, int &, double = 1) const;
521 
522  /// Gets the spatial bounding box for a transformation parameter in lattice coordinates.
523  /// The last parameter specifies what fraction of the bounding box to return.
524  /// The default is 1 which equals 100% of the bounding box.
525  bool DOFBoundingBox(const ImageAttributes &, int, int &, int &, int &,
526  int &, int &, int &, double = 1) const;
527 
528  /// Gets the spatial bounding box for a control point in image coordinates.
529  /// The last parameter specifies what fraction of the bounding box to return.
530  /// The default is 1 which equals 100% of the bounding box.
531  bool BoundingBox(const Image *, int, int &, int &, int &,
532  int &, int &, int &, double = 1) const;
533 
534  /// Gets the spatio-temporal bounding box for a control point in image coordinates.
535  /// The last parameter specifies what fraction of the bounding box to return.
536  /// The default is 1 which equals 100% of the bounding box.
537  bool BoundingBox(const Image *, int, int &, int &, int &, int &,
538  int &, int &, int &, int &, double = 1) const;
539 
540  /// Gets the spatial bounding box for a transformation parameter in image coordinates.
541  /// The last parameter specifies what fraction of the bounding box to return.
542  /// The default is 1 which equals 100% of the bounding box.
543  bool DOFBoundingBox(const Image *, int, int &, int &, int &,
544  int &, int &, int &, double = 1) const;
545 
546  // ---------------------------------------------------------------------------
547  // Transformation parameters (DoFs)
548  using Transformation::Put;
549  using Transformation::Get;
552 
553  /// Get norm of the gradient vector
554  virtual double DOFGradientNorm(const double *) const;
555 
556  /// Copy active transformation parameters (DoFs) from given
557  /// transformation if possible and return \c false, otherwise
558  virtual bool CopyFrom(const Transformation *);
559 
560  /// Puts values of the parameters at a control point
561  void Put(int, const Vector &);
562 
563  /// Puts values of the parameters at a control point
564  void Put(int, double, double, double);
565 
566  /// Puts values of the parameters at a control point
567  void Put(int, int, int, double, double, double);
568 
569  /// Puts values of the parameters at a control point
570  void Put(int, int, int, int, double, double, double);
571 
572  /// Gets values of the parameters at a control point
573  void Get(int, Vector &) const;
574 
575  /// Gets values of the parameters at a control point
576  void Get(int, double &, double &, double &) const;
577 
578  /// Gets values of the parameters at a control point
579  void Get(int, int, int, double &, double &, double &) const;
580 
581  /// Gets values of the parameters at a control point
582  void Get(int, int, int, int, double &, double &, double &) const;
583 
584  /// Puts status of the parameters at a control point
585  void PutStatus(int, const CPStatus &);
586 
587  /// Puts status of the parameters at a control point
588  void PutStatus(int, int, int, DOFStatus, DOFStatus, DOFStatus);
589 
590  /// Puts status of the parameters at a control point
591  void PutStatus(int, int, int, int, DOFStatus, DOFStatus, DOFStatus);
592 
593  /// Gets status of the parameters at a control point
594  void GetStatus(int, CPStatus &) const;
595 
596  /// Gets status of the parameters at a control point
597  void GetStatus(int, int, int, DOFStatus &, DOFStatus &, DOFStatus &) const;
598 
599  /// Gets status of the parameters at a control point
600  void GetStatus(int, int, int, int, DOFStatus &, DOFStatus &, DOFStatus &) const;
601 
602  /// Whether the control point at given lattice index is active
603  virtual bool IsActive(int) const;
604 
605  /// Whether the control point at given lattice coordinates is active
606  virtual bool IsActive(int, int, int = 0, int = 0) const;
607 
608  // ---------------------------------------------------------------------------
609  // Point transformation
612 
613  /// Transforms a single point using the global transformation component only
614  virtual void GlobalTransform(double &, double &, double &, double = 0, double = NaN) const;
615 
616  /// Transforms a single point
617  virtual void Transform(double &, double &, double &, double = 0, double = NaN) const;
618 
619  /// Transforms a single point using the inverse of the global transformation only
620  virtual void GlobalInverse(double &, double &, double &, double = 0, double = NaN) const;
621 
622  /// Transforms a single point using the inverse of the transformation
623  virtual bool Inverse(double &, double &, double &, double = 0, double = NaN) const;
624 
625  // ---------------------------------------------------------------------------
626  // Derivatives
631 
632  /// Convert 1st order derivatives computed w.r.t 2D lattice coordinates to
633  /// derivatives w.r.t world coordinates
634  void JacobianToWorld(double &, double &) const;
635 
636  /// Convert 1st order derivatives computed w.r.t 3D lattice coordinates to
637  /// derivatives w.r.t world coordinates
638  void JacobianToWorld(double &, double &, double &) const;
639 
640  /// Convert 1st order derivatives computed w.r.t lattice coordinates to
641  /// derivatives w.r.t world coordinates
642  void JacobianToWorld(Matrix &) const;
643 
644  /// Reorient 1st order derivatives computed w.r.t 2D lattice coordinates
645  void JacobianToWorldOrientation(double &, double &) const;
646 
647  /// Reorient 1st order derivatives computed w.r.t 2D lattice coordinates
648  void JacobianToWorldOrientation(double &, double &, double &) const;
649 
650  /// Convert 2nd order derivatives computed w.r.t 2D lattice coordinates to
651  /// derivatives w.r.t world coordinates
652  void HessianToWorld(double &, double &, double &) const;
653 
654  /// Convert 2nd order derivatives computed w.r.t 3D lattice coordinates to
655  /// derivatives w.r.t world coordinates
656  void HessianToWorld(double &, double &, double &, double &, double &, double &) const;
657 
658  /// Convert 2nd order derivatives of single transformed coordinate computed
659  /// w.r.t lattice coordinates to derivatives w.r.t world coordinates
660  void HessianToWorld(Matrix &) const;
661 
662  /// Convert 2nd order derivatives computed w.r.t lattice coordinates to
663  /// derivatives w.r.t world coordinates
664  void HessianToWorld(Matrix [3]) const;
665 
666  /// Calculates the Jacobian of the transformation w.r.t either control point displacements or velocities
667  virtual void FFDJacobianWorld(Matrix &, double, double, double, double = 0, double = NaN) const;
668 
669  /// Calculates the Jacobian of the global transformation w.r.t world coordinates
670  virtual void GlobalJacobian(Matrix &, double, double, double, double = 0, double = NaN) const;
671 
672  /// Calculates the Jacobian of the transformation w.r.t world coordinates
673  virtual void Jacobian(Matrix &, double, double, double, double = 0, double = NaN) const;
674 
675  /// Calculates the Hessian for each component of the global transformation w.r.t world coordinates
676  virtual void GlobalHessian(Matrix [3], double, double, double, double = 0, double = NaN) const;
677 
678  /// Calculates the Hessian for each component of the transformation w.r.t world coordinates
679  virtual void Hessian(Matrix [3], double, double, double, double = 0, double = NaN) const;
680 
681  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters of a control point
682  virtual void JacobianDOFs(Matrix &, int, double, double, double, double = 0, double = NaN) const;
683 
684  /// Calculates the Jacobian of the transformation w.r.t the transformation parameters
685  virtual void JacobianDOFs(TransformationJacobian &, double, double, double, double = 0, double = NaN) const;
686 
687  /// Calculates derivatives of the Jacobian determinant of spline function w.r.t. DoFs of a control point
688  ///
689  /// This function is identical to JacobianDetDerivative when the DoFs of the control points are displacements.
690  /// When the DoFs are velocities, however, this function computes the derivatives of the Jacobian determinant
691  /// of the velocity field instead.
692  ///
693  /// \param[out] dJ Partial derivatives of Jacobian determinant at (x, y, z) w.r.t. DoFs of control point.
694  /// \param[in] cp Index of control point w.r.t. whose DoFs the derivatives are computed.
695  /// \param[in] x World coordinate along x axis at which to evaluate derivatives.
696  /// \param[in] y World coordinate along y axis at which to evaluate derivatives.
697  /// \param[in] z World coordinate along z axis at which to evaluate derivatives.
698  /// \param[in] adj Adjugate of Jacobian matrix evaluated at (x, y, z).
699  /// \param[in] wrt_world Whether derivatives are computed w.r.t. world coordinate system.
700  /// \param[in] use_spacing Whether to use grid spacing when \p wrt_world is \c true.
701  virtual void FFDJacobianDetDerivative(double dJ[3], const Matrix &adj,
702  int cp, double x, double y, double z, double = 0, double = NaN,
703  bool wrt_world = true, bool use_spacing = true) const;
704 
705  /// Calculates derivatives of the Jacobian determinant at world point w.r.t. DoFs of a control point
706  ///
707  /// \param[out] dJ Partial derivatives of Jacobian determinant w.r.t. DoFs of control point.
708  /// \param[in] adj Pre-computed adjugate of Jacobian matrix at this world point.
709  /// \param[in] cp Index of control point w.r.t. whose DoFs the derivatives are computed.
710  /// \param[in] x World coordinate along x axis at which to evaluate derivatives.
711  /// \param[in] y World coordinate along y axis at which to evaluate derivatives.
712  /// \param[in] z World coordinate along z axis at which to evaluate derivatives.
713  /// \param[in] t Temporal coordinate of point at which to evaluate derivatives.
714  /// \param[in] t0 Temporal coordinate of co-domain (target). Used by velocity-based models.
715  /// \param[in] wrt_world Whether derivatives are computed w.r.t. world coordinate system.
716  /// \param[in] use_spacing Whether to use grid spacing when \p wrt_world is \c true.
717  virtual void JacobianDetDerivative(double dJ[3], const Matrix &adj,
718  int cp, double x, double y, double z, double t = 0, double t0 = NaN,
719  bool wrt_world = true, bool use_spacing = true) const;
720 
721  /// Applies the chain rule to convert spatial non-parametric gradient
722  /// to a gradient w.r.t the parameters of this transformation.
723  ///
724  /// If the transformation itself is non-parametric, the gradient will be passed through
725  /// unchanged. The default implementation uses the full Jacobian matrix computed for each
726  /// DoF separately (i.e., calls JacobianDOFs for each DoF).
727  ///
728  /// For 4D transformations, the temporal coordinate t used for the computation of the Jacobian
729  /// of the transformation w.r.t the transformation parameters for all spatial (x, y, z) voxel
730  /// coordinates in world units, is assumed to correspond to the temporal origin of the given
731  /// gradient image. For 4D transformations parameterized by velocities, a second time for the
732  /// upper integration bound can be provided as last argument to this method. This last
733  /// argument is ignored by transformations parameterized by displacements.
734  ///
735  /// \sa ImageSimilarityMetric::EvaluateGradient
736  virtual void ParametricGradient(const GenericImage<double> *, double *,
737  const WorldCoordsImage *,
738  const WorldCoordsImage *,
739  double = NaN, double = 1) const;
740 
741  /// Applies the chain rule to convert point-wise non-parametric gradient
742  /// to a gradient w.r.t the parameters of this transformation.
743  virtual void ParametricGradient(const PointSet &, const Vector3D<double> *,
744  double *, double = 0, double = NaN, double = 1) const;
745 
746  // ---------------------------------------------------------------------------
747  // Properties
748 
749  /// Calculates the bending of the transformation given the 2nd order derivatives
750  static double Bending3D(const Matrix [3]);
751 
752  /// Calculates the bending of the transformation
753  virtual double BendingEnergy(double, double, double, double = 0, double = NaN, bool = true) const;
754 
755  /// Approximates the bending energy on the control point lattice
756  virtual double BendingEnergy(bool = false, bool = true) const;
757 
758  /// Approximates the bending energy on the specified discrete domain
759  virtual double BendingEnergy(const ImageAttributes &attr, double = NaN, bool = true) const;
760 
761  /// Approximates the gradient of the bending energy on the control point
762  /// lattice w.r.t the transformation parameters and adds it with the given weight
763  virtual void BendingEnergyGradient(double *, double = 1.0, bool = false, bool = true, bool = true) const;
764 
765  // ---------------------------------------------------------------------------
766  // I/O
767 
768  // Do not hide methods of base class
769  using Transformation::Print;
770 
771  /// Prints the parameters of the transformation
772  virtual void Print(ostream &, Indent = 0) const;
773 
774 protected:
775 
776  /// Writes the control point and status information to a file stream
777  Cofstream &WriteCPs(Cofstream &) const;
778 
779 };
780 
781 ////////////////////////////////////////////////////////////////////////////////
782 // Inline definitions
783 ////////////////////////////////////////////////////////////////////////////////
784 
785 // -----------------------------------------------------------------------------
787 {
788  return _CPValue;
789 }
790 
791 // =============================================================================
792 // Lattice
793 // =============================================================================
794 
795 // -----------------------------------------------------------------------------
797 {
798  return this->KernelSize() / 2;
799 }
800 
801 // -----------------------------------------------------------------------------
803 {
804  return _CPImage.Attributes();
805 }
806 
807 // -----------------------------------------------------------------------------
809 {
810  return _x * _y * _z * _t;
811 }
812 
813 // -----------------------------------------------------------------------------
815 {
816  int nactive = 0;
817  for (int cp = 0; cp < NumberOfCPs(); ++cp) {
818  if (this->IsActive(cp)) ++nactive;
819  }
820  return nactive;
821 }
822 
823 // -----------------------------------------------------------------------------
825 {
826  return NumberOfCPs() - NumberOfActiveCPs();
827 }
828 
829 // -----------------------------------------------------------------------------
831 {
832  if (_z == 1) return 2 * NumberOfCPs();
833  else return 3 * NumberOfCPs();
834 }
835 
836 // -----------------------------------------------------------------------------
837 inline int FreeFormTransformation::X() const
838 {
839  return _x;
840 }
841 
842 // -----------------------------------------------------------------------------
843 inline int FreeFormTransformation::Y() const
844 {
845  return _y;
846 }
847 
848 // -----------------------------------------------------------------------------
849 inline int FreeFormTransformation::Z() const
850 {
851  return _z;
852 }
853 
854 // -----------------------------------------------------------------------------
855 inline int FreeFormTransformation::T() const
856 {
857  return _t;
858 }
859 
860 // -----------------------------------------------------------------------------
862 {
863  return X();
864 }
865 
866 // -----------------------------------------------------------------------------
868 {
869  return Y();
870 }
871 
872 // -----------------------------------------------------------------------------
874 {
875  return Z();
876 }
877 
878 // -----------------------------------------------------------------------------
880 {
881  return T();
882 }
883 
884 // -----------------------------------------------------------------------------
886 {
887  return _dx;
888 }
889 
890 // -----------------------------------------------------------------------------
892 {
893  return _dy;
894 }
895 
896 // -----------------------------------------------------------------------------
898 {
899  return _dz;
900 }
901 
902 // -----------------------------------------------------------------------------
904 {
905  return _dt;
906 }
907 
908 // ---------------------------------------------------------------------------
909 inline void FreeFormTransformation::GetSpacing(double &dx, double &dy, double &dz) const
910 {
911  dx = _dx;
912  dy = _dy;
913  dz = _dz;
914 }
915 
916 // ---------------------------------------------------------------------------
917 inline void FreeFormTransformation::GetSpacing(double &dx, double &dy, double &dz, double &dt) const
918 {
919  dx = _dx;
920  dy = _dy;
921  dz = _dz;
922  dt = _dt;
923 }
924 
925 // ---------------------------------------------------------------------------
926 inline void FreeFormTransformation::PutOrientation(double *xaxis, double *yaxis, double *zaxis)
927 {
928  _CPImage.PutOrientation(xaxis, yaxis, zaxis);
929 }
930 
931 // ---------------------------------------------------------------------------
932 inline void FreeFormTransformation::GetOrientation(double *xaxis, double *yaxis, double *zaxis) const
933 {
934  _CPImage.GetOrientation(xaxis, yaxis, zaxis);
935 }
936 
937 // -----------------------------------------------------------------------------
938 inline void FreeFormTransformation::IndexToDOFs(int cp, int &x, int &y) const
939 {
940  x = 3 * cp;
941  y = x + 1;
942 }
943 
944 // -----------------------------------------------------------------------------
945 inline void FreeFormTransformation::IndexToDOFs(int cp, int &x, int &y, int &z) const
946 {
947  x = 3 * cp;
948  y = x + 1;
949  z = x + 2;
950 }
951 
952 // -----------------------------------------------------------------------------
953 inline int FreeFormTransformation::DOFToIndex(int dof) const
954 {
955  return dof / 3;
956 }
957 
958 // -----------------------------------------------------------------------------
959 inline int FreeFormTransformation::DOFToDimension(int dof) const
960 {
961  return dof % 3;
962 }
963 
964 // -----------------------------------------------------------------------------
965 inline int FreeFormTransformation::LatticeToIndex(int i, int j, int k, int l) const
966 {
967  return _CPImage.VoxelToIndex(i, j, k, l);
968 }
969 
970 // -----------------------------------------------------------------------------
971 inline void FreeFormTransformation::IndexToLattice(int index, int &i, int &j) const
972 {
973  _CPImage.IndexToVoxel(index, i, j);
974 }
975 
976 // -----------------------------------------------------------------------------
977 inline void FreeFormTransformation::IndexToLattice(int index, int &i, int &j, int &k) const
978 {
979  _CPImage.IndexToVoxel(index, i, j, k);
980 }
981 
982 // -----------------------------------------------------------------------------
983 inline void FreeFormTransformation::IndexToLattice(int index, int &i, int &j, int &k, int &l) const
984 {
985  _CPImage.IndexToVoxel(index, i, j, k, l);
986 }
987 
988 // -----------------------------------------------------------------------------
989 inline void FreeFormTransformation::IndexToWorld(int index, double &x, double &y) const
990 {
991  _CPImage.IndexToWorld(index, x, y);
992 }
993 
994 // -----------------------------------------------------------------------------
995 inline void FreeFormTransformation::IndexToWorld(int index, double &x, double &y, double &z) const
996 {
997  _CPImage.IndexToWorld(index, x, y, z);
998 }
999 
1000 // -----------------------------------------------------------------------------
1001 inline void FreeFormTransformation::IndexToWorld(int index, Point &p) const
1002 {
1003  _CPImage.IndexToWorld(index, p);
1004 }
1005 
1006 // -----------------------------------------------------------------------------
1008 {
1009  return _CPImage.IndexToWorld(index);
1010 }
1011 
1012 // -----------------------------------------------------------------------------
1013 inline void FreeFormTransformation::WorldToLattice(double &x, double &y) const
1014 {
1015  _CPImage.WorldToImage(x, y);
1016 }
1017 
1018 // -----------------------------------------------------------------------------
1019 inline void FreeFormTransformation::WorldToLattice(double &x, double &y, double &z) const
1020 {
1021  _CPImage.WorldToImage(x, y, z);
1022 }
1023 
1024 // -----------------------------------------------------------------------------
1026 {
1027  this->WorldToLattice(p._x, p._y, p._z);
1028 }
1029 
1030 // -----------------------------------------------------------------------------
1031 inline void FreeFormTransformation::LatticeToWorld(double &x, double &y) const
1032 {
1033  _CPImage.ImageToWorld(x, y);
1034 }
1035 
1036 // -----------------------------------------------------------------------------
1037 inline void FreeFormTransformation::LatticeToWorld(double &x, double &y, double &z) const
1038 {
1039  _CPImage.ImageToWorld(x, y, z);
1040 }
1041 
1042 // -----------------------------------------------------------------------------
1044 {
1045  this->LatticeToWorld(p._x, p._y, p._z);
1046 }
1047 
1048 // -----------------------------------------------------------------------------
1050 {
1051  int i, j, k;
1052  IndexToLattice(cp, i, j, k);
1053  Point p(i, j, k);
1054  this->LatticeToWorld(p);
1055  return p;
1056 }
1057 
1058 // -----------------------------------------------------------------------------
1059 inline void FreeFormTransformation::ControlPointLocation(int cp, double &x, double &y) const
1060 {
1061  int i, j;
1062  IndexToLattice(cp, i, j);
1063  x = i, y = j;
1064  this->LatticeToWorld(x, y);
1065 }
1066 
1067 // -----------------------------------------------------------------------------
1068 inline void FreeFormTransformation::ControlPointLocation(int cp, double &x, double &y, double &z) const
1069 {
1070  int i, j, k;
1071  IndexToLattice(cp, i, j, k);
1072  x = i, y = j, z = k;
1073  this->LatticeToWorld(x, y, z);
1074 }
1075 
1076 // -----------------------------------------------------------------------------
1077 inline double FreeFormTransformation::TimeToLattice(double t) const
1078 {
1079  return _CPImage.TimeToImage(t);
1080 }
1081 
1082 // -----------------------------------------------------------------------------
1083 inline double FreeFormTransformation::LatticeToTime(double t) const
1084 {
1085  return _CPImage.ImageToTime(t);
1086 }
1087 
1088 // -----------------------------------------------------------------------------
1090 {
1091  return this->GetX();
1092 }
1093 
1094 // -----------------------------------------------------------------------------
1096 {
1097  return this->GetY();
1098 }
1099 
1100 // -----------------------------------------------------------------------------
1102 {
1103  return this->GetZ();
1104 }
1105 
1106 // -----------------------------------------------------------------------------
1108 {
1109  return this->GetT();
1110 }
1111 
1112 // -----------------------------------------------------------------------------
1114 {
1115  return this->GetXSpacing();
1116 }
1117 
1118 // -----------------------------------------------------------------------------
1120 {
1121  return this->GetYSpacing();
1122 }
1123 
1124 // -----------------------------------------------------------------------------
1126 {
1127  return this->GetZSpacing();
1128 }
1129 
1130 // -----------------------------------------------------------------------------
1132 {
1133  return this->GetTSpacing();
1134 }
1135 
1136 // -----------------------------------------------------------------------------
1137 inline void FreeFormTransformation::Subdivide(bool subdivide_x, bool subdivide_y, bool subdivide_z, bool subdivide_t)
1138 {
1139  if (subdivide_x || subdivide_y || subdivide_z || subdivide_t) {
1140  cerr << this->NameOfClass() << "::Subdivide: Not implemented (or not possible?)" << endl;
1141  exit(1);
1142  }
1143 }
1144 
1145 // -----------------------------------------------------------------------------
1147 {
1148  this->Subdivide(true, true, false, false);
1149 }
1150 
1151 // -----------------------------------------------------------------------------
1153 {
1154  this->Subdivide(true, true, true, false);
1155 }
1156 
1157 // -----------------------------------------------------------------------------
1159 {
1160  this->Subdivide(true, true, true, true);
1161 }
1162 
1163 // =============================================================================
1164 // Bounding box
1165 // =============================================================================
1166 
1167 // -----------------------------------------------------------------------------
1168 inline void FreeFormTransformation::BoundingBox(double &t1, double &t2) const
1169 {
1170  t1 = this->LatticeToTime(.0);
1171  t2 = this->LatticeToTime(_t - 1);
1172  if (t1 > t2) swap(t1, t2);
1173 }
1174 
1175 // -----------------------------------------------------------------------------
1176 inline void FreeFormTransformation::BoundingBox(double &x1, double &y1, double &z1,
1177  double &x2, double &y2, double &z2) const
1178 {
1179  x1 = y1 = z1 = .0;
1180  this->LatticeToWorld(x1, y1, z1);
1181  x2 = _x - 1, y2 = _y - 1, z2 = _z - 1;
1182  this->LatticeToWorld(x2, y2, z2);
1183  if (x1 > x2) swap(x1, x2);
1184  if (y1 > y2) swap(y1, y2);
1185  if (z1 > z2) swap(z1, z2);
1186 }
1187 
1188 // -----------------------------------------------------------------------------
1190 {
1191  BoundingBox(p1._x, p1._y, p1._z, p2._x, p2._y, p2._z);
1192 }
1193 
1194 // -----------------------------------------------------------------------------
1195 inline void FreeFormTransformation::BoundingBox(double &x1, double &y1, double &z1, double &t1,
1196  double &x2, double &y2, double &z2, double &t2) const
1197 {
1198  BoundingBox(x1, y1, z1, x2, y2, z2);
1199  BoundingBox(t1, t2);
1200 }
1201 
1202 // -----------------------------------------------------------------------------
1203 inline void FreeFormTransformation::BoundingBox(Point &p1, double &t1, Point &p2, double &t2) const
1204 {
1205  BoundingBox(p1._x, p1._y, p1._z, t1, p2._x, p2._y, p2._z, t2);
1206 }
1207 
1208 // -----------------------------------------------------------------------------
1209 inline void FreeFormTransformation::BoundingBox(int, double &t1, double &t2, double) const
1210 {
1211  t1 = this->LatticeToTime(0);
1212  t2 = this->LatticeToTime(_t - 1);
1213  if (t1 > t2) swap(t1, t2);
1214 }
1215 
1216 // -----------------------------------------------------------------------------
1217 inline void FreeFormTransformation::BoundingBox(int, double &x1, double &y1, double &z1,
1218  double &x2, double &y2, double &z2, double) const
1219 {
1220  x1 = 0, y1 = 0, z1 = 0;
1221  x2 = _x - 1, y2 = _y - 1, z2 = _z - 1;
1222  this->LatticeToWorld(x1, y1, z1);
1223  this->LatticeToWorld(x2, y2, z2);
1224  if (x1 > x2) swap(x1, x2);
1225  if (y1 > y2) swap(y1, y2);
1226  if (z1 > z2) swap(z1, z2);
1227 }
1228 
1229 // -----------------------------------------------------------------------------
1230 inline void FreeFormTransformation::BoundingBox(int cp, double &x1, double &y1, double &z1, double &t1,
1231  double &x2, double &y2, double &z2, double &t2,
1232  double fraction) const
1233 {
1234  this->BoundingBox(cp, x1, y1, z1, x2, y2, z2, fraction);
1235  this->BoundingBox(cp, t1, t2, fraction);
1236 }
1237 
1238 // -----------------------------------------------------------------------------
1239 inline void FreeFormTransformation::BoundingBox(int cp, Point &p1, Point &p2, double fraction) const
1240 {
1241  BoundingBox(cp, p1._x, p1._y, p1._z, p2._x, p2._y, p2._z, fraction);
1242 }
1243 
1244 // -----------------------------------------------------------------------------
1245 inline bool FreeFormTransformation::BoundingBox(const ImageAttributes &domain, int cp,
1246  int &i1, int &j1, int &k1,
1247  int &i2, int &j2, int &k2,
1248  double fraction) const
1249 {
1250  // Calculate bounding box in world coordinates parallel to world axes
1251  double x[2], y[2], z[2];
1252  this->BoundingBox(cp, x[0], y[0], z[0], x[1], y[1], z[1], fraction);
1253 
1254  // Map bounding box into image space and calculate minimal axes-alinged
1255  // bounding box parallel to image axes which need not coincide with world axes
1256  Point p;
1257  double x1, y1, z1, x2, y2, z2;
1258  x1 = y1 = z1 = + inf;
1259  x2 = y2 = z2 = - inf;
1260 
1261  for (int c = 0; c <= 1; ++c)
1262  for (int b = 0; b <= 1; ++b)
1263  for (int a = 0; a <= 1; ++a) {
1264  p = Point(x[a], y[b], z[c]);
1265  domain.WorldToLattice(p);
1266  if (p._x < x1) x1 = p._x;
1267  if (p._x > x2) x2 = p._x;
1268  if (p._y < y1) y1 = p._y;
1269  if (p._y > y2) y2 = p._y;
1270  if (p._z < z1) z1 = p._z;
1271  if (p._z > z2) z2 = p._z;
1272  }
1273 
1274  // Round to nearest voxel in image domain
1275  i1 = iround(x1);
1276  i2 = iround(x2);
1277  j1 = iround(y1);
1278  j2 = iround(y2);
1279  k1 = iround(z1);
1280  k2 = iround(z2);
1281 
1282  // When both indices are outside in opposite directions,
1283  // use the full range [0, N[. If they are both outside in
1284  // the same direction, the condition i1 <= i2 is false which
1285  // indicates that the bounding box is empty in this case
1286  i1 = (i1 < 0 ? 0 : (i1 >= domain.X() ? domain.X() : i1));
1287  i2 = (i2 < 0 ? -1 : (i2 >= domain.X() ? domain.X() - 1 : i2));
1288  j1 = (j1 < 0 ? 0 : (j1 >= domain.Y() ? domain.Y() : j1));
1289  j2 = (j2 < 0 ? -1 : (j2 >= domain.Y() ? domain.Y() - 1 : j2));
1290  k1 = (k1 < 0 ? 0 : (k1 >= domain.Z() ? domain.Z() : k1));
1291  k2 = (k2 < 0 ? -1 : (k2 >= domain.Z() ? domain.Z() - 1 : k2));
1292  return i1 <= i2 && j1 <= j2 && k1 <= k2;
1293 }
1294 
1295 // -----------------------------------------------------------------------------
1296 inline bool FreeFormTransformation::BoundingBox(const Image *image, int cp,
1297  int &i1, int &j1, int &k1,
1298  int &i2, int &j2, int &k2,
1299  double fraction) const
1300 {
1301  return BoundingBox(image->Attributes(), cp, i1, j1, k1, i2, j2, k2, fraction);
1302 }
1303 
1304 // -----------------------------------------------------------------------------
1305 inline bool FreeFormTransformation::BoundingBox(const ImageAttributes &domain, int cp,
1306  int &i1, int &j1, int &k1, int &l1,
1307  int &i2, int &j2, int &k2, int &l2,
1308  double fraction) const
1309 {
1310  // Calculate spatial bounding box in image coordinates
1311  bool bbvalid = BoundingBox(domain, cp, i1, j1, k1, i2, j2, k2, fraction);
1312 
1313  // Calculate temporal bounding box
1314  double t1, t2;
1315  this->BoundingBox(cp, t1, t2, fraction);
1316 
1317  // Convert to image coordinates
1318  t1 = domain.TimeToLattice(t1);
1319  t2 = domain.TimeToLattice(t2);
1320  if (t2 < t1) swap(t1, t2);
1321 
1322  // Round to nearest voxel in image domain
1323  l1 = iround(t1);
1324  l2 = iround(t2);
1325 
1326  // When both indices are outside in opposite directions,
1327  // use the full range [0, N[. If they are both outside in
1328  // the same direction, the condition l1 <= l2 is false which
1329  // indicates that the bounding box is empty in this case
1330  l1 = (l1 < 0 ? 0 : (l1 >= domain.T() ? domain.T() : l1));
1331  l2 = (l2 < 0 ? -1 : (l2 >= domain.T() ? domain.T() - 1 : l2));
1332  return bbvalid && l1 <= l2;
1333 }
1334 
1335 // -----------------------------------------------------------------------------
1336 inline bool FreeFormTransformation::BoundingBox(const Image *image, int cp,
1337  int &i1, int &j1, int &k1, int &l1,
1338  int &i2, int &j2, int &k2, int &l2,
1339  double fraction) const
1340 {
1341  return BoundingBox(image->Attributes(), cp, i1, j1, k1, l1, i2, j2, k2, l2, fraction);
1342 }
1343 
1344 // -----------------------------------------------------------------------------
1345 inline bool FreeFormTransformation::DOFBoundingBox(const ImageAttributes &domain, int dof,
1346  int &i1, int &j1, int &k1,
1347  int &i2, int &j2, int &k2,
1348  double fraction) const
1349 {
1350  return BoundingBox(domain, this->DOFToIndex(dof), i1, j1, k1, i2, j2, k2, fraction);
1351 }
1352 
1353 // -----------------------------------------------------------------------------
1354 inline bool FreeFormTransformation::DOFBoundingBox(const Image *image, int dof,
1355  int &i1, int &j1, int &k1,
1356  int &i2, int &j2, int &k2,
1357  double fraction) const
1358 {
1359  return BoundingBox(image->Attributes(), dof, i1, j1, k1, i2, j2, k2, fraction);
1360 }
1361 
1362 // =============================================================================
1363 // Transformation parameters (DoFs)
1364 // =============================================================================
1365 
1366 // -----------------------------------------------------------------------------
1367 inline double FreeFormTransformation::DOFGradientNorm(const double *gradient) const
1368 {
1369  double norm, max = .0;
1370  int x, y, z;
1371  const int ncps = this->NumberOfCPs();
1372  for (int cp = 0; cp < ncps; ++cp) {
1373  this->IndexToDOFs(cp, x, y, z);
1374  norm = sqrt(gradient[x] * gradient[x] + gradient[y] * gradient[y] + gradient[z] * gradient[z]);
1375  if (norm > max) max = norm;
1376  }
1377  return max;
1378 }
1379 
1380 // -----------------------------------------------------------------------------
1382 {
1383  const FreeFormTransformation *ffd;
1384  ffd = dynamic_cast<const FreeFormTransformation *>(other);
1385  if (ffd && typeid(*ffd) == typeid(*this) && ffd->Attributes() == this->Attributes()) {
1386  return Transformation::CopyFrom(other);
1387  } else {
1388  return false;
1389  }
1390 }
1391 
1392 // -----------------------------------------------------------------------------
1393 inline void FreeFormTransformation::Put(int cp, const Vector &x)
1394 {
1395  _CPImage(cp) = x;
1396 }
1397 
1398 // -----------------------------------------------------------------------------
1399 inline void FreeFormTransformation::Put(int cp, double x, double y, double z)
1400 {
1401  _CPImage(cp) = Vector(x, y, z);
1402 }
1403 
1404 // -----------------------------------------------------------------------------
1405 inline void FreeFormTransformation::Put(int i, int j, int k, int l,
1406  double x, double y, double z)
1407 {
1408  _CPImage(i, j, k, l) = Vector(x, y, z);
1409 }
1410 
1411 // -----------------------------------------------------------------------------
1412 inline void FreeFormTransformation::Put(int i, int j, int k,
1413  double x, double y, double z)
1414 {
1415  Put(i, j, k, 0, x, y, z);
1416 }
1417 
1418 // -----------------------------------------------------------------------------
1419 inline void FreeFormTransformation::Get(int cp, Vector &x) const
1420 {
1421  x = _CPImage(cp);
1422 }
1423 
1424 // -----------------------------------------------------------------------------
1425 inline void FreeFormTransformation::Get(int cp, double &x, double &y, double &z) const
1426 {
1427  const Vector &param = _CPImage(cp);
1428  x = param._x, y = param._y, z = param._z;
1429 }
1430 
1431 // -----------------------------------------------------------------------------
1432 inline void FreeFormTransformation::Get(int i, int j, int k, int l,
1433  double &x, double &y, double &z) const
1434 {
1435  const Vector &param = _CPImage(i, j, k, l);
1436  x = param._x, y = param._y, z = param._z;
1437 }
1438 
1439 // -----------------------------------------------------------------------------
1440 inline void FreeFormTransformation::Get(int i, int j, int k,
1441  double &x, double &y, double &z) const
1442 {
1443  Get(i, j, k, 0, x, y, z);
1444 }
1445 
1446 // -----------------------------------------------------------------------------
1447 inline void FreeFormTransformation::PutStatus(int cp, const CPStatus &status)
1448 {
1449  _CPStatus[0][0][0][cp] = status;
1450 }
1451 
1452 // -----------------------------------------------------------------------------
1453 inline void FreeFormTransformation::PutStatus(int i, int j, int k, int l,
1454  DOFStatus sx, DOFStatus sy, DOFStatus sz)
1455 {
1456  CPStatus &status = _CPStatus[l][k][j][i];
1457  status._x = sx;
1458  status._y = sy;
1459  status._z = sz;
1460 }
1461 
1462 // -----------------------------------------------------------------------------
1463 inline void FreeFormTransformation::PutStatus(int i, int j, int k,
1464  DOFStatus sx, DOFStatus sy, DOFStatus sz)
1465 {
1466  PutStatus(i, j, k, 0, sx, sy, sz);
1467 }
1468 
1469 // -----------------------------------------------------------------------------
1470 inline void FreeFormTransformation::GetStatus(int cp, CPStatus &status) const
1471 {
1472  const CPStatus &s = _CPStatus[0][0][0][cp];
1473  status._x = s._x;
1474  status._y = s._y;
1475  status._z = s._z;
1476 }
1477 
1478 // -----------------------------------------------------------------------------
1479 inline void FreeFormTransformation::GetStatus(int i, int j, int k, int l,
1480  DOFStatus &sx, DOFStatus &sy, DOFStatus &sz) const
1481 {
1482  const CPStatus &status = _CPStatus[l][k][j][i];
1483  sx = status._x;
1484  sy = status._y;
1485  sz = status._z;
1486 }
1487 
1488 // -----------------------------------------------------------------------------
1489 inline void FreeFormTransformation::GetStatus(int i, int j, int k,
1490  DOFStatus &sx, DOFStatus &sy, DOFStatus &sz) const
1491 {
1492  GetStatus(i, j, k, 0, sx, sy, sz);
1493 }
1494 
1495 // -----------------------------------------------------------------------------
1496 inline bool FreeFormTransformation::IsActive(int cp) const
1497 {
1498  const CPStatus &status = _CPStatus[0][0][0][cp];
1499  return status._x == Active || status._y == Active || status._z == Active;
1500 }
1501 
1502 // -----------------------------------------------------------------------------
1503 inline bool FreeFormTransformation::IsActive(int i, int j, int k, int l) const
1504 {
1505  const CPStatus &status = _CPStatus[l][k][j][i];
1506  return status._x == Active || status._y == Active || status._z == Active;
1507 }
1508 
1509 // =============================================================================
1510 // Point transformation
1511 // =============================================================================
1512 
1513 // -----------------------------------------------------------------------------
1514 inline void FreeFormTransformation::GlobalTransform(double &, double &, double &, double, double) const
1515 {
1516  // T_global(x) = x
1517 }
1518 
1519 // -----------------------------------------------------------------------------
1520 inline void FreeFormTransformation::GlobalInverse(double &, double &, double &, double, double) const
1521 {
1522  // T_global(x) = x
1523 }
1524 
1525 // -----------------------------------------------------------------------------
1526 inline void FreeFormTransformation::Transform(double &x, double &y, double &z, double t, double t0) const
1527 {
1528  this->LocalTransform(x, y, z, t, t0);
1529 }
1530 
1531 // -----------------------------------------------------------------------------
1532 inline bool FreeFormTransformation::Inverse(double &x, double &y, double &z, double t, double t0) const
1533 {
1534  return this->LocalInverse(x, y, z, t, t0);
1535 }
1536 
1537 // =============================================================================
1538 // Derivatives
1539 // =============================================================================
1540 
1541 // -----------------------------------------------------------------------------
1542 inline void FreeFormTransformation::JacobianToWorld(double &du, double &dv) const
1543 {
1544  double dx = du * _matW2L(0, 0) + dv * _matW2L(1, 0);
1545  double dy = du * _matW2L(0, 1) + dv * _matW2L(1, 1);
1546  du = dx, dv = dy;
1547 }
1548 
1549 // -----------------------------------------------------------------------------
1550 inline void FreeFormTransformation::JacobianToWorld(double &du, double &dv, double &dw) const
1551 {
1552  double dx = du * _matW2L(0, 0) + dv * _matW2L(1, 0) + dw * _matW2L(2, 0);
1553  double dy = du * _matW2L(0, 1) + dv * _matW2L(1, 1) + dw * _matW2L(2, 1);
1554  double dz = du * _matW2L(0, 2) + dv * _matW2L(1, 2) + dw * _matW2L(2, 2);
1555  du = dx, dv = dy, dw = dz;
1556 }
1557 
1558 // -----------------------------------------------------------------------------
1560 {
1561  if (jac.Rows() == 2) {
1562  JacobianToWorld(jac(0, 0), jac(0, 1));
1563  JacobianToWorld(jac(1, 0), jac(1, 1));
1564  } else {
1565  JacobianToWorld(jac(0, 0), jac(0, 1), jac(0, 2));
1566  JacobianToWorld(jac(1, 0), jac(1, 1), jac(1, 2));
1567  JacobianToWorld(jac(2, 0), jac(2, 1), jac(2, 2));
1568  }
1569 }
1570 
1571 // -----------------------------------------------------------------------------
1572 inline void FreeFormTransformation::JacobianToWorldOrientation(double &du, double &dv) const
1573 {
1574  double dx = du * _attr._xaxis[0] + dv * _attr._yaxis[0];
1575  double dy = du * _attr._xaxis[1] + dv * _attr._yaxis[1];
1576  du = dx, dv = dy;
1577 }
1578 
1579 // -----------------------------------------------------------------------------
1580 inline void FreeFormTransformation::JacobianToWorldOrientation(double &du, double &dv, double &dw) const
1581 {
1582  double dx = du * _attr._xaxis[0] + dv * _attr._yaxis[0] + dw * _attr._zaxis[0];
1583  double dy = du * _attr._xaxis[1] + dv * _attr._yaxis[1] + dw * _attr._zaxis[1];
1584  double dz = du * _attr._xaxis[2] + dv * _attr._yaxis[2] + dw * _attr._zaxis[2];
1585  du = dx, dv = dy, dw = dz;
1586 }
1587 
1588 // -----------------------------------------------------------------------------
1589 inline void
1590 FreeFormTransformation::HessianToWorld(double &duu, double &duv, double &dvv) const
1591 {
1592  // The derivatives of the world to lattice coordinate transformation
1593  // w.r.t the world coordinates which are needed for the chain rule below
1594  const double &dudx = _matW2L(0, 0);
1595  const double &dudy = _matW2L(0, 1);
1596  const double &dvdx = _matW2L(1, 0);
1597  const double &dvdy = _matW2L(1, 1);
1598  // Expression computed here is transpose(R) * Hessian * R = transpose(Hessian * R) * R
1599  // where R is the 2x2 world to lattice reorientation and scaling matrix
1600  double du, dv, dxx, dxy, dyy;
1601  du = duu * dudx + duv * dvdx;
1602  dv = duv * dudx + dvv * dvdx;
1603  dxx = du * dudx + dv * dvdx;
1604  dxy = du * dudy + dv * dvdy;
1605  du = duu * dudy + duv * dvdy;
1606  dv = duv * dudy + dvv * dvdy;
1607  dyy = du * dudy + dv * dvdy;
1608  // Return computed derivatives
1609  duu = dxx, duv = dxy, dvv = dyy;
1610 }
1611 
1612 // -----------------------------------------------------------------------------
1613 inline void
1614 FreeFormTransformation::HessianToWorld(double &duu, double &duv, double &duw,
1615  double &dvv, double &dvw,
1616  double &dww) const
1617 {
1618  // The derivatives of the world to lattice coordinate transformation
1619  // w.r.t the world coordinates which are needed for the chain rule below
1620  const double &dudx = _matW2L(0, 0);
1621  const double &dudy = _matW2L(0, 1);
1622  const double &dudz = _matW2L(0, 2);
1623  const double &dvdx = _matW2L(1, 0);
1624  const double &dvdy = _matW2L(1, 1);
1625  const double &dvdz = _matW2L(1, 2);
1626  const double &dwdx = _matW2L(2, 0);
1627  const double &dwdy = _matW2L(2, 1);
1628  const double &dwdz = _matW2L(2, 2);
1629  // Expression computed here is transpose(R) * Hessian * R = transpose(Hessian * R) * R
1630  // where R is the 3x3 world to lattice reorientation and scaling matrix
1631  double du, dv, dw, dxx, dxy, dxz, dyy, dyz, dzz;
1632  du = duu * dudx + duv * dvdx + duw * dwdx;
1633  dv = duv * dudx + dvv * dvdx + dvw * dwdx;
1634  dw = duw * dudx + dvw * dvdx + dww * dwdx;
1635  dxx = du * dudx + dv * dvdx + dw * dwdx;
1636  dxy = du * dudy + dv * dvdy + dw * dwdy;
1637  dxz = du * dudz + dv * dvdz + dw * dwdz;
1638  du = duu * dudy + duv * dvdy + duw * dwdy;
1639  dv = duv * dudy + dvv * dvdy + dvw * dwdy;
1640  dw = duw * dudy + dvw * dvdy + dww * dwdy;
1641  dyy = du * dudy + dv * dvdy + dw * dwdy;
1642  dyz = du * dudz + dv * dvdz + dw * dwdz;
1643  du = duu * dudz + duv * dvdz + duw * dwdz;
1644  dv = duv * dudz + dvv * dvdz + dvw * dwdz;
1645  dw = duw * dudz + dvw * dvdz + dww * dwdz;
1646  dzz = du * dudz + dv * dvdz + dw * dwdz;
1647  // Return computed derivatives
1648  duu = dxx, duv = dxy, duw = dxz, dvv = dyy, dvw = dyz, dww = dzz;
1649 }
1650 
1651 // -----------------------------------------------------------------------------
1653 {
1654  if (hessian.Rows() == 2) {
1655  HessianToWorld(hessian(0, 0), hessian(0, 1), hessian(1, 1));
1656  hessian(1, 0) = hessian(0, 1);
1657  } else {
1658  HessianToWorld(hessian(0, 0), hessian(0, 1), hessian(0, 2),
1659  hessian(1, 1), hessian(1, 2),
1660  hessian(2, 2));
1661  hessian(1, 0) = hessian(0, 1);
1662  hessian(2, 0) = hessian(0, 2);
1663  hessian(2, 1) = hessian(1, 2);
1664  }
1665 }
1666 
1667 // -----------------------------------------------------------------------------
1668 inline void FreeFormTransformation::HessianToWorld(Matrix hessian[3]) const
1669 {
1670  HessianToWorld(hessian[0]);
1671  HessianToWorld(hessian[1]);
1672  HessianToWorld(hessian[2]);
1673 }
1674 
1675 // -----------------------------------------------------------------------------
1676 inline void FreeFormTransformation::FFDJacobianWorld(Matrix &, double, double, double, double, double) const
1677 {
1678  Throw(ERR_NotImplemented, __FUNCTION__, "Not implemented");
1679 }
1680 
1681 // -----------------------------------------------------------------------------
1682 inline void FreeFormTransformation::GlobalJacobian(Matrix &jac, double, double, double, double, double) const
1683 {
1684  // T_global(x) = x
1685  jac.Initialize(3, 3);
1686  jac(0, 0) = 1;
1687  jac(1, 1) = 1;
1688  jac(2, 2) = 1;
1689 }
1690 
1691 // -----------------------------------------------------------------------------
1692 inline void FreeFormTransformation::Jacobian(Matrix &jac, double x, double y, double z, double t, double t0) const
1693 {
1694  this->LocalJacobian(jac, x, y, z, t, t0);
1695 }
1696 
1697 // -----------------------------------------------------------------------------
1698 inline void FreeFormTransformation::GlobalHessian(Matrix hessian[3], double, double, double, double, double) const
1699 {
1700  // T_global(x) = x
1701  hessian[0].Initialize(3, 3);
1702  hessian[1].Initialize(3, 3);
1703  hessian[2].Initialize(3, 3);
1704 }
1705 
1706 // -----------------------------------------------------------------------------
1707 inline void FreeFormTransformation::Hessian(Matrix hessian[3], double x, double y, double z, double t, double t0) const
1708 {
1709  this->LocalHessian(hessian, x, y, z, t, t0);
1710 }
1711 
1712 // -----------------------------------------------------------------------------
1713 inline void FreeFormTransformation::JacobianDOFs(Matrix &jac, int cp, double x, double y, double z, double t, double t0) const
1714 {
1715  int xdof, ydof, zdof;
1716  double dofgrad[3];
1717 
1718  // initialize 3x3 Jacobian matrix
1719  jac.Initialize(3, 3);
1720  // compute indices of control point DoFs
1721  this->IndexToDOFs(cp, xdof, ydof, zdof);
1722  // derivatives w.r.t. x component of control point
1723  if (this->GetStatus(xdof) == Active) {
1724  this->JacobianDOFs(dofgrad, xdof, x, y, z, t, t0);
1725  jac(0, 0) = dofgrad[0];
1726  jac(1, 0) = dofgrad[1];
1727  jac(2, 0) = dofgrad[2];
1728  }
1729  // derivatives w.r.t. y component of control point
1730  if (this->GetStatus(ydof) == Active) {
1731  this->JacobianDOFs(dofgrad, ydof, x, y, z, t, t0);
1732  jac(0, 1) = dofgrad[0];
1733  jac(1, 1) = dofgrad[1];
1734  jac(2, 1) = dofgrad[2];
1735  }
1736  // derivatives w.r.t. z component of control point
1737  if (this->GetStatus(zdof) == Active) {
1738  this->JacobianDOFs(dofgrad, zdof, x, y, z, t, t0);
1739  jac(0, 2) = dofgrad[0];
1740  jac(1, 2) = dofgrad[1];
1741  jac(2, 2) = dofgrad[2];
1742  }
1743 }
1744 
1745 // -----------------------------------------------------------------------------
1746 inline void FreeFormTransformation::JacobianDOFs(TransformationJacobian &jac, double x, double y, double z, double t, double t0) const
1747 {
1748  int xdof, ydof, zdof;
1749  double dofgrad[3];
1750 
1751  for (int cp = 0; cp < NumberOfCPs(); ++cp) {
1752  // compute indices of control point DoFs
1753  this->IndexToDOFs(cp, xdof, ydof, zdof);
1754  // derivatives w.r.t. x component of control point
1755  if (this->GetStatus(xdof) == Active) {
1756  this->JacobianDOFs(dofgrad, xdof, x, y, z, t, t0);
1757  if (dofgrad[0] != .0 && dofgrad[1] != .0 && dofgrad[2] != .0) {
1758  TransformationJacobian::ColumnType &xdofgrad = jac(xdof);
1759  xdofgrad._x = dofgrad[0];
1760  xdofgrad._y = dofgrad[1];
1761  xdofgrad._z = dofgrad[2];
1762  }
1763  }
1764  // derivatives w.r.t. y component of control point
1765  if (this->GetStatus(ydof) == Active) {
1766  this->JacobianDOFs(dofgrad, ydof, x, y, z, t, t0);
1767  if (dofgrad[0] != .0 && dofgrad[1] != .0 && dofgrad[2] != .0) {
1768  TransformationJacobian::ColumnType &ydofgrad = jac(ydof);
1769  ydofgrad._x = dofgrad[0];
1770  ydofgrad._y = dofgrad[1];
1771  ydofgrad._z = dofgrad[2];
1772  }
1773  }
1774  // derivatives w.r.t. z component of control point
1775  if (this->GetStatus(zdof) == Active) {
1776  this->JacobianDOFs(dofgrad, zdof, x, y, z, t, t0);
1777  if (dofgrad[0] != .0 && dofgrad[1] != .0 && dofgrad[2] != .0) {
1778  TransformationJacobian::ColumnType &zdofgrad = jac(zdof);
1779  zdofgrad._x = dofgrad[0];
1780  zdofgrad._y = dofgrad[1];
1781  zdofgrad._z = dofgrad[2];
1782  }
1783  }
1784  }
1785 }
1786 
1787 // -----------------------------------------------------------------------------
1788 inline void FreeFormTransformation
1789 ::JacobianDetDerivative(double dJ[3], const Matrix &adj,
1790  int cp, double x, double y, double z, double t, double t0,
1791  bool wrt_world, bool use_spacing) const
1792 {
1793  this->FFDJacobianDetDerivative(dJ, adj, cp, x, y, z, t, t0, wrt_world, use_spacing);
1794 }
1795 
1796 // =============================================================================
1797 // Properties
1798 // =============================================================================
1799 
1800 // -----------------------------------------------------------------------------
1801 inline double FreeFormTransformation::Bending3D(const Matrix hessian[3])
1802 {
1803  const Matrix &hx = hessian[0];
1804  const Matrix &hy = hessian[1];
1805  const Matrix &hz = hessian[2];
1806 
1807  const double &x_ii = hx(0, 0);
1808  const double &x_ij = hx(0, 1);
1809  const double &x_ik = hx(0, 2);
1810  const double &x_jj = hx(1, 1);
1811  const double &x_jk = hx(1, 2);
1812  const double &x_kk = hx(2, 2);
1813 
1814  const double &y_ii = hy(0, 0);
1815  const double &y_ij = hy(0, 1);
1816  const double &y_ik = hy(0, 2);
1817  const double &y_jj = hy(1, 1);
1818  const double &y_jk = hy(1, 2);
1819  const double &y_kk = hy(2, 2);
1820 
1821  const double &z_ii = hz(0, 0);
1822  const double &z_ij = hz(0, 1);
1823  const double &z_ik = hz(0, 2);
1824  const double &z_jj = hz(1, 1);
1825  const double &z_jk = hz(1, 2);
1826  const double &z_kk = hz(2, 2);
1827 
1828  return ( x_ii * x_ii + x_jj * x_jj + x_kk * x_kk
1829  + y_ii * y_ii + y_jj * y_jj + y_kk * y_kk
1830  + z_ii * z_ii + z_jj * z_jj + z_kk * z_kk)
1831  + 2.0 * ( x_ij * x_ij + x_ik * x_ik + x_jk * x_jk
1832  + y_ij * y_ij + y_ik * y_ik + y_jk * y_jk
1833  + z_ij * z_ij + z_ik * z_ik + z_jk * z_jk);
1834 }
1835 
1836 
1837 } // namespace mirtk
1838 
1839 #endif // MIRTK_FreeFormTransformation_H
virtual void BendingEnergyGradient(double *, double=1.0, bool=false, bool=true, bool=true) const
double GetXSpacing() const
Returns the of control point spacing in x.
double _xaxis[3]
Direction of x-axis.
virtual void GlobalHessian(Matrix [3], double, double, double, double=0, double=NaN) const
Calculates the Hessian for each component of the global transformation w.r.t world coordinates...
virtual void GlobalJacobian(Matrix &, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the global transformation w.r.t world coordinates.
void WorldToLattice(double &, double &, double &) const
Convert world to lattice coordinate.
virtual int GetTAfterSubdivision() const
Returns the number of control points in t after subdivision.
virtual void JacobianDetDerivative(double dJ[3], const Matrix &adj, int cp, double x, double y, double z, double t=0, double t0=NaN, bool wrt_world=true, bool use_spacing=true) const
virtual ParameterList Parameter() const
Get (non-DoF) parameters as key/value as string map.
virtual void JacobianDOFs(Matrix &, int, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the transformation w.r.t the transformation parameters of a control point...
bool CropPadPassiveCPs(int=0, bool=false)
virtual double GetYSpacingAfterSubdivision() const
Returns the control point spacing in y after the subdivision.
int VoxelToIndex(int, int, int=0, int=0) const
Function to convert pixel to index.
Definition: BaseImage.h:1132
double EvaluateRMSError(const ImageAttributes &, const Transformation *) const
Evaluates RMS error of transformation compared to another.
void Subdivide2D()
Subdivide lattice in first two dimensions.
bool DOFBoundingBox(const ImageAttributes &, int, int &, int &, int &, int &, int &, int &, double=1) const
CPExtrapolator * _CPValue
Infinite discrete representation of free-form transformation coefficients.
static ImageAttributes DefaultAttributes(const ImageAttributes &attr, double dx=-1.0, double dy=-1.0, double dz=-1.0, double dt=-1.0)
virtual void GlobalTransform(double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the global transformation component only.
virtual double LatticeToTime(double) const
Transforms temporal lattice coordinate to time (in ms)
const ImageAttributes & Attributes() const
Gets the image attributes.
Definition: BaseImage.h:856
FreeFormTransformation(CPInterpolator &, CPInterpolator *=NULL)
Default constructor.
virtual void PutStatus(int, DOFStatus)
Put status of transformation parameter.
GenericInterpolateImageFunction< CPImage > CPInterpolator
void Get(int, Vector &) const
Gets values of the parameters at a control point.
virtual DOFStatus GetStatus(int) const
Get status of transformation parameter.
virtual bool CopyFrom(const Transformation *)
virtual double TimeToLattice(double) const
Transforms time (in ms) to temporal lattice coordinate.
virtual void ApproximateGradient(const ImageAttributes &, const double *, const double *, const double *, double *, double=1.0) const
void IndexToDOFs(int, int &, int &) const
Get indices of transformation parameters (DoFs)
void PutOrientation(double *, double *, double *=NULL)
Put image x- and y-axis and z-axis.
Definition: BaseImage.h:1088
void JacobianToWorld(double &, double &) const
void WorldToImage(double &, double &) const
World to image coordinate conversion with two doubles.
Definition: BaseImage.h:1212
virtual double DOFGradientNorm(const double *) const
Get norm of the gradient vector.
void PutBoundingBox(double, double, double, double, double, double)
Puts the spatial bounding box for the free-form deformation (in mm)
const Matrix & _matW2L
Read-only reference to _matW2I of _CPImage.
virtual bool CopyFrom(const Transformation *)
virtual void JacobianDOFs(double [3], int, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the transformation w.r.t a transformation parameter.
const double & _dy
Read-only reference to _dy attribute of _CPImage.
int Z() const
Returns the number of control points in z.
const CPExtrapolator * Extrapolator() const
double _x
x coordinate of Point
Definition: Point.h:46
double EvaluateRMSError(const Transformation *) const
Evaluates RMS error of transformation at control points compared to another.
virtual double BendingEnergy(double, double, double, double=0, double=NaN, bool=true) const
Calculates the bending of the transformation.
int DOFToDimension(int) const
Get index of dimension corresponding to transformation parameter (DoFs)
const int & _x
Read-only reference to _x attribute of _CPImage.
int Z() const
Get number of lattice points in z dimension.
static double Bending3D(const Matrix [3])
Calculates the bending of the transformation given the 2nd order derivatives.
virtual double GetTSpacingAfterSubdivision() const
Returns the control point spacing in t after the subdivision.
virtual void Print(ostream &, Indent=0) const
Prints the parameters of the transformation.
virtual void LocalHessian(Matrix [3], double, double, double, double=0, double=NaN) const
Calculates the Hessian for each component of the local transformation w.r.t world coordinates...
int Y() const
Returns the number of control points in y.
void JacobianToWorldOrientation(double &, double &) const
Reorient 1st order derivatives computed w.r.t 2D lattice coordinates.
void IndexToWorld(int, double &, double &) const
Get world coordinates (in mm) of control point.
int T() const
Returns the number of control points in t.
virtual int GetYAfterSubdivision() const
Returns the number of control points in y after subdivision.
virtual void Initialize(const ImageAttributes &)=0
Initialize free-form transformation.
Array< Pair< string, string > > ParameterList
Ordered list of parameter name/value pairs.
Definition: Object.h:38
GenericImage< CPValue > CPImage
Type of image representation of free-form transformation.
const double & _dz
Read-only reference to _dz attribute of _CPImage.
virtual void Put(int, double)
Put value of transformation parameter.
void PutOrientation(double *, double *, double *)
Puts the orientation of the free-form deformation lattice.
void GetSpacing(double &, double &, double &) const
Gets the control point spacing (in mm)
virtual void LocalTransform(double &, double &, double &, double=0, double=NaN) const =0
Transforms a single point using the local transformation component only.
int GetZ() const
Returns the number of control points in z.
virtual bool Set(const char *, const char *)
Set named (non-DoF) parameter from value as string.
virtual double ApproximateAsNew(const Transformation *, int=1, double=.0)
Approximate another transformation and return approximation error.
void Subdivide3D()
Subdivide lattice in first three dimensions.
void Initialize(int, int=-1, double *=NULL)
Initialize matrix with number of rows and columns.
Status
Enumeration of common states for entities such as objective function parameters.
Definition: Status.h:28
int GetX() const
Returns the number of control points in x.
Definition: IOConfig.h:41
double GetYSpacing() const
Returns the of control point spacing in y.
virtual double Approximate(const ImageAttributes &, const Transformation *, int=1, double=.0)
Approximate another transformation and return approximation error.
virtual void Jacobian(Matrix &, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the transformation w.r.t world coordinates.
virtual void Hessian(Matrix [3], double, double, double, double=0, double=NaN) const
Calculates the Hessian for each component of the transformation w.r.t world coordinates.
void Subdivide4D()
Subdivide lattice in all four dimensions.
mirtkPublicAttributeMacro(double, SpeedupFactor)
Speedup factor for gradient computation.
void ImageToWorld(double &, double &) const
Image to world coordinate conversion with two doubles.
Definition: BaseImage.h:1180
void InitializeStatus()
Initialize status of control points.
virtual void Interpolate(const double *, const double *, const double *)=0
virtual void Jacobian(Matrix &, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the transformation w.r.t world coordinates.
int NumberOfPassiveCPs() const
Number of non-active control points.
int T() const
Get number of lattice points in t dimension.
virtual double GetXSpacingAfterSubdivision() const
Returns the control point spacing in x after the subdivision.
virtual void Transform(double &, double &, double &, double=0, double=NaN) const
Transforms a single point.
void ControlPointLocation(int, double &, double &) const
Gets the location of the given control point (in mm)
int GetY() const
Returns the number of control points in y.
int Y() const
Get number of lattice points in y dimension.
double TimeToImage(double) const
Time to image coordinate conversion.
Definition: BaseImage.h:1262
virtual int KernelSize() const =0
Size of support region of the used kernel.
int NumberOfActiveCPs() const
Number of active control points.
virtual int GetZAfterSubdivision() const
Returns the number of control points in z after subdivision.
virtual void Subdivide(bool=true, bool=true, bool=true, bool=true)
Subdivide lattice of free-form transformation.
int LatticeToIndex(int, int, int=0, int=0) const
Get control point index from lattice coordinates.
int KernelRadius() const
Radius of support region of the used kernel.
virtual void FFDJacobianDetDerivative(double dJ[3], const Matrix &adj, int cp, double x, double y, double z, double=0, double=NaN, bool wrt_world=true, bool use_spacing=true) const
const double & _dx
Read-only reference to _dx attribute of _CPImage.
void BoundingBox(double &, double &) const
Gets the temporal bounding box of the free-form deformation (in ms)
void PutStatus(int, const CPStatus &)
Puts status of the parameters at a control point.
const int & _t
Read-only reference to _t attribute of _CPImage.
mirtkReadOnlyAttributeMacro(enum ExtrapolationMode, ExtrapolationMode)
Mode used for extrapolation of control point image.
const Matrix & _matL2W
Read-only reference to _matI2W of _CPImage.
virtual double Approximate(const Transformation *, int=1, double=.0)
double ImageToTime(double) const
Image to time coordinate conversion.
Definition: BaseImage.h:1256
int X() const
Returns the number of control points in x.
virtual bool IsActive(int) const
Whether the control point at given lattice index is active.
void InitializeCPs(const ImageAttributes &, bool=true)
Initialize control points.
virtual ImageAttributes ApproximationDomain(const ImageAttributes &, const Transformation *)
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1) const
void GetOrientation(double *, double *, double *) const
Gets the orientation of the free-form deformation lattice.
const int & _z
Read-only reference to _z attribute of _CPImage.
void IndexToWorld(int, double &, double &) const
Get world coordinates (in mm) of pixl.
Definition: BaseImage.h:1156
double _zaxis[3]
Direction of z-axis.
ExtrapolationMode
Image extrapolation modes.
virtual void Transform(double &, double &, double &, double=0, double=NaN) const =0
Transforms a single point.
int GetT() const
Returns the number of control points in t.
void Throw(ErrorType err, const char *func, Args... args) const
Definition: Object.h:166
void GetStatus(int, CPStatus &) const
Gets status of the parameters at a control point.
virtual double ApproximateAsNew(const ImageAttributes &, const Transformation *, int=1, double=.0)
Approximate another transformation and return approximation error.
virtual void ExtrapolationMode(enum ExtrapolationMode)
Set extrapolation mode.
virtual const char * NameOfClass() const =0
Get name of class, which this object is an instance of.
void IndexToLattice(int, int &, int &) const
Get control point lattice coordinates from index.
double TimeToLattice(double) const
Convert time to lattice coordinate.
T _z
The z component.
Definition: Vector3D.h:60
virtual bool LocalInverse(double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the inverse of the local transformation only.
int X() const
Get number of lattice points in x dimension.
T _y
The y component.
Definition: Vector3D.h:59
void InitializeInterpolator()
Initialize interpolator of control points.
void Put(int, const Vector &)
Puts values of the parameters at a control point.
virtual ParameterList Parameter() const
Get (non-DoF) parameters as key/value as string map.
double GetTSpacing() const
Returns the of control point spacing in t.
virtual void GlobalInverse(double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the inverse of the global transformation only.
virtual void LatticeToWorld(double &, double &) const
Transforms lattice coordinates to world coordinates (in mm)
double _z
z coordinate of Point
Definition: Point.h:48
MIRTKCU_API int iround(T x)
Round floating-point value and cast to int.
Definition: Math.h:170
virtual bool Inverse(double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the inverse of the transformation.
void IndexToVoxel(int, int &, int &) const
Function to convert index to pixel coordinates.
Definition: BaseImage.h:1138
Cofstream & WriteCPs(Cofstream &) const
Writes the control point and status information to a file stream.
virtual bool Inverse(double &, double &, double &, double=0, double=NaN) const
Transforms a single point using the inverse of the transformation.
const ImageAttributes & _attr
Control point lattice attributes.
double GetZSpacing() const
Returns the of control point spacing in z.
T _x
The x component.
Definition: Vector3D.h:58
virtual ~FreeFormTransformation()
Destructor.
double _y
y coordinate of Point
Definition: Point.h:47
virtual void LocalJacobian(Matrix &, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the local transformation w.r.t world coordinates.
int Rows() const
Get number of rows.
Definition: Matrix.h:555
void GetOrientation(double *, double *, double *=NULL) const
Get image x- and y-axis and z-axis.
Definition: BaseImage.h:1103
Vector3D< DOFStatus > CPStatus
Type of vector storing status of control point coefficients.
virtual int GetXAfterSubdivision() const
Returns the number of control points in x after subdivision.
Vector3D< DOFValue > CPValue
Type of vector storing the coefficients at a control point.
void HessianToWorld(double &, double &, double &) const
GenericExtrapolateImageFunction< CPImage > CPExtrapolator
Base type used for extrapolation of control point data.
virtual void GlobalJacobian(Matrix &, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the global transformation w.r.t world coordinates.
int DOFToIndex(int) const
Get index of control point corresponding to transformation parameter (DoFs)
const int & _y
Read-only reference to _y attribute of _CPImage.
int NumberOfCPs() const
Number of control points.
void Print(Indent=0) const
Prints information about the transformation.
MIRTK_Common_EXPORT const double inf
Positive infinity.
const ImageAttributes & Attributes() const
Returns attributes of control point grid.
virtual double Get(int) const
Get value of transformation parameter.
virtual double GetZSpacingAfterSubdivision() const
Returns the control point spacing in z after the subdivision.
virtual void FFDJacobianWorld(Matrix &, double, double, double, double=0, double=NaN) const
Calculates the Jacobian of the transformation w.r.t either control point displacements or velocities...
const double & _dt
Read-only reference to _dt attribute of _CPImage.
virtual void ParametricGradient(const GenericImage< double > *, double *, const WorldCoordsImage *, const WorldCoordsImage *, double=NaN, double=1) const
virtual void WorldToLattice(double &, double &) const
Transforms world coordinates (in mm) to lattice coordinates.
double _yaxis[3]
Direction of y-axis.