MultipleVoxelTransformation.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_MultipleVoxelTransformation_H
21 #define MIRTK_MultipleVoxelTransformation_H
22 
23 #include "mirtk/Float.h"
24 #include "mirtk/GenericImage.h"
25 #include "mirtk/VoxelFunction.h"
26 #include "mirtk/InterpolateImageFunction.h"
27 
28 #include <cstdlib>
29 #include <limits>
30 #include <iostream>
31 
32 
33 namespace mirtk {
34 
35 
36 /**
37  * These voxel functions are used by MultipleImageTransformation
38  * to efficiently transform one or more input images at once
39  */
40 namespace MultipleVoxelTransformation {
41 
42 
43 ////////////////////////////////////////////////////////////////////////////////
44 // Base class for voxel transformation functions
45 ////////////////////////////////////////////////////////////////////////////////
46 
47 // -----------------------------------------------------------------------------
48 /// Base class for voxel transformation functions
49 class Base : public VoxelFunction
50 {
51 protected:
52 
53  /// Default constructor
54  Base(int numvox = 0)
55  :
56  _NumberOfVoxels (numvox),
57  _TwiceNumberOfVoxels(numvox<<1)
58  {}
59 
60  /// Copy constructor
61  Base(const Base &other)
62  :
65  {}
66 
67  int _NumberOfVoxels; ///< Number of voxels per vector component
68  int _TwiceNumberOfVoxels; ///< Offset of z component
69 
70 public:
71 
72  /// Get reference to x component of vector field
73  template <class T>
74  inline T &x_( T *p) const { return p[0]; }
75 
76  /// Get const reference to x component of vector field
77  template <class T>
78  inline const T &x_(const T *p) const { return p[0]; }
79 
80  /// Get reference to y component of vector field
81  template <class T>
82  inline T &y_( T *p) const { return p[_NumberOfVoxels]; }
83 
84  /// Get const reference to y component of vector field
85  template <class T>
86  inline const T &y_(const T *p) const { return p[_NumberOfVoxels]; }
87 
88  /// Get reference to z component of vector field
89  template <class T>
90  inline T &z_( T *p) const { return p[_TwiceNumberOfVoxels]; }
91 
92  /// Get const reference to z component of vector field
93  template <class T>
94  inline const T &z_(const T *p) const { return p[_TwiceNumberOfVoxels]; }
95 };
96 
97 // -----------------------------------------------------------------------------
98 /// Input/output data members of voxel transformation functions
100 {
101  int _NumberOfImages; ///< Number of input images
102  int _MaxNumberOfComponents; ///< Maximum number of image components/channels (_t)
103  const BaseImage **_Inputs; ///< Input images
104  const BaseImage *_Input; ///< Single/reference input
105  InterpolateImageFunction **_Interpolators; ///< Input interpolators
106  InterpolateImageFunction *_Interpolator; ///< Single/reference interpolator
107  double *_PaddingValues; ///< Outside padding values
108  double _PaddingValue; ///< Default padding value
109  const Transformation *_Transformation1; ///< First transformation
110  const Transformation *_Transformation2; ///< Second transformation (optional)
111  bool _Invert; ///< Whether to invert the transformations
112  double _ScaleFactor; ///< Output intensity scale factor
113  double _Offset; ///< Output intensity offset
114  Image **_Outputs; ///< Output images
115  Image *_Output; ///< Single/reference output image
116  BinaryImage *_Mask; ///< Output foreground mask
117  int _Begin; ///< Index of first image to process
118  int _End; ///< Index of last image to process + 1
119 
120  /// Default constructor
122  :
123  _NumberOfImages (0),
124  _MaxNumberOfComponents(0),
125  _Inputs (NULL),
126  _Input (NULL),
127  _Interpolators (NULL),
128  _Interpolator (NULL),
129  _PaddingValues (NULL),
130  _PaddingValue (.0),
131  _Transformation1 (NULL),
132  _Transformation2 (NULL),
133  _Invert (false),
134  _ScaleFactor (1.0),
135  _Offset (0.0),
136  _Outputs (NULL),
137  _Output (NULL),
138  _Mask (NULL),
139  _Begin (-1),
140  _End (-1)
141  {}
142 };
143 
144 // -----------------------------------------------------------------------------
145 /**
146  * Base class for voxel transformation functions with various transformation methods
147  *
148  * Using an explicit interpolate image function type helps the compiler to deduce
149  * which virtual methods are being called and thus inline the code for better
150  * performance. If the actual type of the interpolator is not known when
151  * instantiating this class, use the default InterpolateImageFunction base
152  * interpolate image function type.
153  */
155  class InputDomain = InterpolationDomain::Foreground>
156 struct BaseTransform : public TransformData, public Base
157 {
158  // ---------------------------------------------------------------------------
159  /// Get (casted) pointer to interpolator of type InterpolateImageFunction
161  {
162  return reinterpret_cast<InterpolateImageFunction *>(_Interpolators[n]);
163  }
164 
165  // ---------------------------------------------------------------------------
166  /// Get (casted) pointer to reference interpolator of type InterpolateImageFunction
168  {
169  return reinterpret_cast<InterpolateImageFunction *>(_Interpolator);
170  }
171 
172  // ===========================================================================
173  // Construction/Destruction
174  // ===========================================================================
175 
176 protected:
177 
178  // -------------------------------------------------------------------------
179  /// Constructor
181  :
182  TransformData(data), Base()
183  {
184  // Allow user to specify only the main input/output if only one image to process
185  if (!_Inputs || !_Interpolators || !_Outputs) {
186  if (_NumberOfImages > 1) {
187  cerr << "MultipleVoxelTransformation::BaseTransform: Invalid TransformData" << endl;
188  exit(1);
189  }
190  if (!_Inputs) {
191  if (!_Input) {
192  cerr << "MultipleVoxelTransformation::BaseTransform: Missing input image" << endl;
193  exit(1);
194  }
195  _Inputs = &_Input;
196  }
197  if (!_Interpolators) {
198  if (!_Interpolator) {
199  cerr << "MultipleVoxelTransformation::BaseTransform: Missing input interpolator" << endl;
200  exit(1);
201  }
202  _Interpolators = &_Interpolator;
203  }
204  if (!_Outputs) {
205  if (!_Output) {
206  cerr << "MultipleVoxelTransformation::BaseTransform: Missing output image" << endl;
207  exit(1);
208  }
209  _Outputs = &_Output;
210  }
211  _NumberOfImages = 1;
212  }
213  // Set main input/output if not set yet
214  if (!_Input) _Input = _Inputs [0];
215  if (!_Interpolator) _Interpolator = _Interpolators[0];
216  if (!_Output) _Output = _Outputs [0];
217  // Set offsets for vector component access
218  _NumberOfVoxels = _Output->GetX() * _Output->GetY() * _Output->GetZ();
220  // Range of output images to process
221  if (_Begin < 0) { _Begin = 0; _End = -1; }
222  if (_End < 0) /*_Begin = x*/ _End = _NumberOfImages;
223  if (_End < _Begin) _End = _Begin;
224  // Determine maximum number of components
225  if (_MaxNumberOfComponents < 1) {
226  _MaxNumberOfComponents = _Inputs[0]->GetT();
227  for (int n = 1; n < _NumberOfImages; ++n) {
228  _MaxNumberOfComponents = max(_MaxNumberOfComponents, _Inputs[n]->GetT());
229  }
230  }
231  // Allocate memory for interpolated values
232  _v = new double[_MaxNumberOfComponents];
233  }
234 
235  // -------------------------------------------------------------------------
236  /// Copy constructor
238  :
239  TransformData(other), Base(other)
240  {
241  _v = new double[_MaxNumberOfComponents];
242  }
243 
244 public:
245 
246  // ---------------------------------------------------------------------------
247  /// Destructor
248  virtual ~BaseTransform()
249  {
250  delete[] _v;
251  }
252 
253  // ===========================================================================
254  // 1. Output voxel indices to world coordinates
255  // ===========================================================================
256 
257  // ---------------------------------------------------------------------------
258  /// Convert output voxel indices to world coordinates
259  inline void OutputToWorld(int i, int j, int k)
260  {
261  _x = static_cast<double>(i);
262  _y = static_cast<double>(j);
263  _z = static_cast<double>(k);
264  _Output->ImageToWorld(_x, _y, _z);
265  }
266 
267  // ---------------------------------------------------------------------------
268  /// Convert output voxel indices to world coordinates given pointer to lookup table
269  inline void OutputToWorld(const double *i2w)
270  {
271  _x = x_(i2w);
272  _y = y_(i2w);
273  _z = z_(i2w);
274  }
275 
276  // ===========================================================================
277  // 2. World coordinate transformation
278  // ===========================================================================
279 
280  // ---------------------------------------------------------------------------
281  /// Transform indices using single transformation
282  ///
283  /// Ignores the second transformation assuming it to be unused.
284  inline void ApplyTransformation()
285  {
286  if (_Invert) _Transformation1->Inverse (_x, _y, _z);
287  else _Transformation1->Transform(_x, _y, _z);
288  }
289 
290  // ---------------------------------------------------------------------------
291  /// Transform indices using single dense displacement field
292  ///
293  /// Requires dense displacement field computed from _Transformation1 and
294  /// ignores the second transformation, assuming it to be unused.
295  inline void ApplyDisplacement(const double *disp1)
296  {
297  _x += x_(disp1);
298  _y += y_(disp1);
299  _z += z_(disp1);
300  }
301 
302  // ---------------------------------------------------------------------------
303  /// Transform using fluid composition of transformations
304  inline void ApplyTransformations()
305  {
306  if (_Invert) {
307  _Transformation1->Inverse (_x, _y, _z);
308  _Transformation2->Inverse (_x, _y, _z);
309  } else {
310  _Transformation1->Transform(_x, _y, _z);
311  _Transformation2->Transform(_x, _y, _z);
312  }
313  }
314 
315  // ---------------------------------------------------------------------------
316  /// Transform indices using fluid composition of dense displacement field and transformation
317  ///
318  /// Requires dense displacement field computed from _Transformation1.
319  inline void ApplyDisplacementAndTransformation(const double *disp1)
320  {
321  _x += x_(disp1);
322  _y += y_(disp1);
323  _z += z_(disp1);
324  if (_Invert) _Transformation2->Inverse (_x, _y, _z);
325  else _Transformation2->Transform(_x, _y, _z);
326  }
327 
328  // ---------------------------------------------------------------------------
329  /// Transform indices using additive composition of dense displacement fields
330  ///
331  /// Requires dense displacement fields computed from _Transformation1 and _Transformation2.
332  inline void ApplyDisplacements(const double *disp1, const double *disp2)
333  {
334  _x += x_(disp1) + x_(disp2);
335  _y += y_(disp1) + y_(disp2);
336  _z += z_(disp1) + z_(disp2);
337  }
338 
339  // ===========================================================================
340  // 3. World coordinates to input voxel indices
341  // ===========================================================================
342 
343  // ---------------------------------------------------------------------------
344  /// Convert world coordinates to input voxel indices
345  inline void WorldToInput()
346  {
347  _Input->WorldToImage(_x, _y, _z);
348  }
349 
350  // ===========================================================================
351  // 4. i) Either store voxel transformation in dense vector field...
352  //
353  // Note: Faster if output images have varying scalar type as then each output
354  // can be updated separately using the pre-computed voxel index
355  // index transformation map and an update voxel function which is
356  // specialized for each output's particular scalar type.
357  // ===========================================================================
358 
359  // ---------------------------------------------------------------------------
360  /// Update map from output to input voxel indices with inside check
361  inline void PutVoxelTransformation(int i, int j, int k, double *o2i)
362  {
363  if (InputDomain::IsInside(GetInterpolator(), _x, _y, _z)) {
364  x_(o2i) = _x;
365  y_(o2i) = _y;
366  z_(o2i) = _z;
367  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(true));
368  } else {
369  x_(o2i) = numeric_limits<double>::quiet_NaN();
370  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(false));
371  }
372  }
373 
374  // ===========================================================================
375  // 4. ii) ...or set directly all output voxels at once to interpolated values
376  //
377  // Note: Faster and more memory efficient when all output images have the
378  // same scalar type as no intermediate storage and lookup of the
379  // transformed voxel coordinates is required. This is in particular the
380  // case when only a single input image is transformed.
381  // ===========================================================================
382 
383  // ---------------------------------------------------------------------------
384  /// Set outputs to dedicated outside value
385  ///
386  /// Efficient and applicable when all output images have a known unique scalar type.
387  template <class OutputVoxelType>
388  inline void PutOutsideValue(int i, int j, int k)
389  {
390  // Set output voxel to outside value
391  OutputVoxelType *p;
392  for (int n = _Begin; n != _End; ++n) {
393  p = reinterpret_cast<OutputVoxelType *>(_Outputs[n]->GetScalarPointer(i, j, k));
394  for (int l = 0; l < _Outputs[n]->GetT(); ++l, p += _NumberOfVoxels) {
395  *p = static_cast<OutputVoxelType>(_PaddingValues ? _PaddingValues[n] : _PaddingValue);
396  }
397  }
398  // Update foreground mask
399  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(false));
400  }
401 
402  // ---------------------------------------------------------------------------
403  /// Set outputs to dedicated outside value
404  ///
405  /// Less efficient than PutOutsideValue but can also be used when output
406  /// images have not a known unique scalar type.
407  inline void PutOutsideValueAsDouble(int i, int j, int k)
408  {
409  // Set output voxel to outside value
410  for (int n = _Begin; n != _End; ++n) {
411  for (int l = 0; l < _Outputs[n]->GetT(); ++l) {
412  _Outputs[n]->PutAsDouble(i, j, k, l, _PaddingValues ? _PaddingValues[n] : _PaddingValue);
413  }
414  }
415  // Update foreground mask
416  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(false));
417  }
418 
419  // ---------------------------------------------------------------------------
420  /// Set outputs to interpolated input values
421  ///
422  /// Most efficient implementation. Only applicable when all output images have
423  /// double as scalar type and thus also no intensity rescaling is required.
424  inline void InterpolatePut(int i, int j, int k, double *)
425  {
426  if (InputDomain::IsInside(GetInterpolator(), _x, _y, _z)) {
427  // Set to interpolated value
428  for (int n = _Begin; n != _End; ++n) {
429  GetInterpolator(n)->EvaluateInside(
430  reinterpret_cast<double *>(_Outputs[n]->GetScalarPointer(i, j, k)), _x, _y, _z, _NumberOfVoxels);
431  }
432  // Update foreground mask
433  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(true));
434  } else {
435  // Set to outside value
436  PutOutsideValue<double>(i, j, k);
437  }
438  }
439 
440  // ---------------------------------------------------------------------------
441  /// Set outputs to interpolated input values
442  ///
443  /// Slightly less efficient implementation. Applicable when all output images
444  /// have a known unique scalar type and no intensity rescaling is used.
445  template <class OutputVoxelType>
446  inline void InterpolatePut(int i, int j, int k, OutputVoxelType *)
447  {
448  if (InputDomain::IsInside(GetInterpolator(), _x, _y, _z)) {
449  // Set to interpolated value
450  OutputVoxelType *p;
451  for (int n = _Begin; n != _End; ++n) {
452  GetInterpolator(n)->EvaluateInside(_v, _x, _y, _z);
453  p = reinterpret_cast<OutputVoxelType *>(_Outputs[n]->GetScalarPointer(i, j, k));
454  for (int l = 0; l < _Outputs[n]->GetT(); ++l, p += _NumberOfVoxels) {
455  *p = static_cast<OutputVoxelType>(_v[l]);
456  }
457  }
458  // Update foreground mask
459  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(true));
460  } else {
461  // Set to outside value
462  PutOutsideValue<OutputVoxelType>(i, j, k);
463  }
464  }
465 
466  // ---------------------------------------------------------------------------
467  /// Set outputs to interpolated input values
468  ///
469  /// Least efficient method without rescaling. Does not imply any particular
470  /// output scalar type or interpolator type. In this case it is better to
471  /// first store the voxel index transformation in the _Output2Input map and
472  /// then update each output image separately.
473  inline void InterpolatePutAsDouble(int i, int j, int k)
474  {
475  if (InputDomain::IsInside(GetInterpolator(), _x, _y, _z)) {
476  // Set to interpolated value
477  for (int n = _Begin; n != _End; ++n) {
478  GetInterpolator(n)->EvaluateInside(_v, _x, _y, _z);
479  for (int l = 0; l < _Outputs[n]->GetT(); ++l) {
480  _Outputs[n]->PutAsDouble(i, j, k, l, _v[k]);
481  }
482  }
483  // Update foreground mask
484  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(true));
485  } else {
486  // Set to outside value
487  PutOutsideValueAsDouble(i, j, k);
488  }
489  }
490 
491  // ---------------------------------------------------------------------------
492  /// Set outputs to interpolated and rescaled input values
493  ///
494  /// Efficient and applicable when all output images have a known unique scalar type.
495  template <class OutputVoxelType>
496  inline void InterpolateRescalePut(int i, int j, int k, OutputVoxelType *)
497  {
498  if (InputDomain::IsInside(GetInterpolator(), _x, _y, _z)) {
499  // Set to interpolated and rescaled value
500  OutputVoxelType *p;
501  for (int n = _Begin; n != _End; ++n) {
502  GetInterpolator(n)->EvaluateInside(_v, _x, _y, _z);
503  p = reinterpret_cast<OutputVoxelType *>(_Outputs[n]->GetScalarPointer(i, j, k));
504  for (int l = 0; l < _Outputs[n]->GetT(); ++l, p += _NumberOfVoxels) {
505  *p = static_cast<OutputVoxelType>(_ScaleFactor * _v[l] + _Offset);
506  }
507  }
508  // Update foreground mask
509  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(true));
510  } else {
511  // Set to outside value
512  PutOutsideValue<OutputVoxelType>(i, j, k);
513  }
514  }
515 
516  // ---------------------------------------------------------------------------
517  /// Set outputs to interpolated and rescaled input values
518  ///
519  /// Least efficient but most general interpolation method. Does not imply any
520  /// particular output scalar type or interpolator type. In this case it is
521  /// better, however, to first store the voxel index transformation in the
522  /// _Output2Input map and then update each output image separately if the
523  /// additional required memory is not an issue.
524  inline void InterpolateRescalePutAsDouble(int i, int j, int k)
525  {
526  if (InputDomain::IsInside(GetInterpolator(), _x, _y, _z)) {
527  // Set to interpolated and rescaled value
528  for (int n = _Begin; n != _End; ++n) {
529  GetInterpolator(n)->EvaluateInside(_v, _x, _y, _z);
530  for (int l = 0; l < _Outputs[n]->GetT(); ++l) {
531  _Outputs[n]->PutAsDouble(i, j, k, l, _ScaleFactor * _v[l] + _Offset);
532  }
533  }
534  // Update foreground mask
535  if (_Mask) _Mask->Put(i, j, k, static_cast<BinaryPixel>(true));
536  } else {
537  // Set to outside value
538  PutOutsideValueAsDouble(i, j, k);
539  }
540  }
541 
542 private:
543 
544  double _x, _y, _z; ///< (Intermediate) Transformed world/image coordinates
545  double *_v; ///< Pre-allocated memory for interpolated values
546 
547 };
548 
549 ////////////////////////////////////////////////////////////////////////////////
550 // Voxel transformation functions
551 ////////////////////////////////////////////////////////////////////////////////
552 
553 // -----------------------------------------------------------------------------
554 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
555 struct MapIndices : public BaseTransform<InterpolateImageFunction, InputDomain>
556 {
557  MapIndices(const TransformData &data)
559  {}
560 
561  void operator ()(int i, int j, int k, int, double *o2i)
562  {
563  this->OutputToWorld(i, j, k);
564  this->WorldToInput();
565  this->PutVoxelTransformation(i, j, k, o2i);
566  }
567 
568  void operator ()(int i, int j, int k, int, const double *o2w, double *o2i)
569  {
570  this->OutputToWorld(o2w);
571  this->WorldToInput();
572  this->PutVoxelTransformation(i, j, k, o2i);
573  }
574 };
575 
576 // -----------------------------------------------------------------------------
577 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
578 struct Transform : public BaseTransform<InterpolateImageFunction, InputDomain>
579 {
580  Transform(const TransformData &data)
582  {}
583 
584  void operator ()(int i, int j, int k, int, double *o2i)
585  {
586  this->OutputToWorld(i, j, k);
587  this->ApplyTransformation();
588  this->WorldToInput();
589  this->PutVoxelTransformation(i, j, k, o2i);
590  }
591 
592  void operator ()(int i, int j, int k, int, const double *o2w, double *o2i)
593  {
594  this->OutputToWorld(o2w);
595  this->ApplyTransformation();
596  this->WorldToInput();
597  this->PutVoxelTransformation(i, j, k, o2i);
598  }
599 };
600 
601 // -----------------------------------------------------------------------------
602 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
603 struct Displace : public BaseTransform<InterpolateImageFunction, InputDomain>
604 {
605  Displace(const TransformData &data)
607  {}
608 
609  void operator ()(int i, int j, int k, int, const double *disp1, double *o2i)
610  {
611  this->OutputToWorld(i, j, k);
612  this->ApplyDisplacement(disp1);
613  this->WorldToInput();
614  this->PutVoxelTransformation(i, j, k, o2i);
615  }
616 
617  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, double *o2i)
618  {
619  this->OutputToWorld(o2w);
620  this->ApplyDisplacement(disp1);
621  this->WorldToInput();
622  this->PutVoxelTransformation(i, j, k, o2i);
623  }
624 };
625 
626 // -----------------------------------------------------------------------------
627 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
628 struct FluidTransform : public BaseTransform<InterpolateImageFunction, InputDomain>
629 {
630  FluidTransform(const TransformData &data)
632  {}
633 
634  void operator ()(int i, int j, int k, int, double *o2i)
635  {
636  this->OutputToWorld(i, j, k);
637  this->ApplyTransformations();
638  this->WorldToInput();
639  this->PutVoxelTransformation(i, j, k, o2i);
640  }
641 
642  void operator ()(int i, int j, int k, int, const double *o2w, double *o2i)
643  {
644  this->OutputToWorld(o2w);
645  this->ApplyTransformations();
646  this->WorldToInput();
647  this->PutVoxelTransformation(i, j, k, o2i);
648  }
649 };
650 
651 // -----------------------------------------------------------------------------
652 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
653 struct DisplaceTransform : public BaseTransform<InterpolateImageFunction, InputDomain>
654 {
655  DisplaceTransform(const TransformData &data)
657  {}
658 
659  void operator ()(int i, int j, int k, int, const double *disp1, double *o2i)
660  {
661  this->OutputToWorld(i, j, k);
662  this->ApplyDisplacementAndTransformation(disp1);
663  this->WorldToInput();
664  this->PutVoxelTransformation(i, j, k, o2i);
665  }
666 
667  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, double *o2i)
668  {
669  this->OutputToWorld(o2w);
670  this->ApplyDisplacementAndTransformation(disp1);
671  this->WorldToInput();
672  this->PutVoxelTransformation(i, j, k, o2i);
673  }
674 };
675 
676 // -----------------------------------------------------------------------------
677 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
678 struct AddDisplacements : public BaseTransform<InterpolateImageFunction, InputDomain>
679 {
680  AddDisplacements(const TransformData &data)
682  {}
683 
684  void operator ()(int i, int j, int k, int, const double *disp1, const double *disp2, double *o2i)
685  {
686  this->OutputToWorld(i, j, k);
687  this->ApplyDisplacements(disp1, disp2);
688  this->WorldToInput();
689  this->PutVoxelTransformation(i, j, k, o2i);
690  }
691 
692  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, const double *disp2, double *o2i)
693  {
694  this->OutputToWorld(o2w);
695  this->ApplyDisplacements(disp1, disp2);
696  this->WorldToInput();
697  this->PutVoxelTransformation(i, j, k, o2i);
698  }
699 };
700 
701 ////////////////////////////////////////////////////////////////////////////////
702 // Voxel interpolation functions
703 ////////////////////////////////////////////////////////////////////////////////
704 
705 // -----------------------------------------------------------------------------
706 /// Set output image of known scalar type to interpolated value using pre-computed
707 /// map from output voxel indices to input indices
708 template <class InterpolateImageFunction = InterpolateImageFunction>
709 struct Interpolate : public Base
710 {
711  InterpolateImageFunction *_Interpolator;
712  int _NumberOfComponents;
713  double _PaddingValue;
714 
715  /// Default constructor
716  Interpolate() : Base(), _v(NULL) {}
717 
718  /// Copy constructor
719  Interpolate(const Interpolate &) : _v(NULL) {}
720 
721  /// Destructor
722  virtual ~Interpolate()
723  {
724  delete[] _v;
725  }
726 
727  /// Allocate memory for interpolated values the first time
728  inline void InitializeMemory()
729  {
730  if (!_v) _v = new double[_NumberOfComponents];
731  }
732 
733  template <class OutputVoxelType>
734  void operator ()(int, int, int, int, const double *o2i, OutputVoxelType *out)
735  {
736  if (IsNaN(*o2i)) {
737  for (int l = 0; l < _NumberOfComponents; ++l, out += _NumberOfVoxels) {
738  *out = static_cast<OutputVoxelType>(_PaddingValue);
739  }
740  } else {
741  if (!_v) _v = new double[_NumberOfComponents];
742  _Interpolator->EvaluateInside(_v, x_(o2i), y_(o2i), z_(o2i));
743  for (int l = 0; l < _NumberOfComponents; ++l, out += _NumberOfVoxels) {
744  *out = static_cast<OutputVoxelType>(_v[l]);
745  }
746  }
747  }
748 
749  void operator ()(int, int, int, int, const double *o2i, double *out)
750  {
751  if (IsNaN(*o2i)) {
752  for (int l = 0; l < _NumberOfComponents; ++l, out += _NumberOfVoxels) {
753  *out = _PaddingValue;
754  }
755  } else {
756  _Interpolator->EvaluateInside(out, x_(o2i), y_(o2i), z_(o2i), _NumberOfVoxels);
757  }
758  }
759 
760 protected:
761  double *_v; ///< Pre-allocated memory for interpolated values
762 };
763 
764 // -----------------------------------------------------------------------------
765 /// Set output image of known scalar type to interpolated and rescaled value
766 /// using pre-computed map from output voxel indices to input indices
767 template <class InterpolateImageFunction = InterpolateImageFunction>
768 struct InterpolateRescale : public Interpolate<InterpolateImageFunction>
769 {
770  double _ScaleFactor;
771  double _Offset;
772 
773  template <class OutputVoxelType>
774  void operator ()(int, int, int, int, const double *o2i, OutputVoxelType *out)
775  {
776  if (IsNaN(*o2i)) {
777  for (int l = 0; l < this->_NumberOfComponents; ++l, out += this->_NumberOfVoxels) {
778  *out = static_cast<OutputVoxelType>(this->_PaddingValue);
779  }
780  } else {
781  this->InitializeMemory();
782  this->_Interpolator->EvaluateInside(this->_v, this->x_(o2i), this->y_(o2i), this->z_(o2i));
783  for (int l = 0; l < this->_NumberOfComponents; ++l, out += this->_NumberOfVoxels) {
784  *out = static_cast<OutputVoxelType>(_ScaleFactor * this->_v[l] + _Offset);
785  }
786  }
787  }
788 };
789 
790 // -----------------------------------------------------------------------------
791 /// Set output image of unknown scalar type to interpolated and rescaled value
792 /// using pre-computed map from output voxel indices to input indices
793 template <class InterpolateImageFunction = InterpolateImageFunction>
794 struct InterpolateRescaleAsDouble : public InterpolateRescale<InterpolateImageFunction>
795 {
796  Image *_Output;
797 
798  void operator ()(int i, int j, int k, int, const double *o2i)
799  {
800  if (IsNaN(*o2i)) {
801  for (int l = 0; l < this->_NumberOfComponents; ++l) {
802  this->_Output->PutAsDouble(i, j, k, l, this->_PaddingValue);
803  }
804  } else {
805  this->InitializeMemory();
806  this->_Interpolator->EvaluateInside(this->_v, this->x_(o2i), this->y_(o2i), this->z_(o2i));
807  for (int l = 0; l < this->_NumberOfComponents; ++l) {
808  _Output->PutAsDouble(i, j, k, l, this->_ScaleFactor * this->_v[l] + this->_Offset);
809  }
810  }
811  }
812 };
813 
814 ////////////////////////////////////////////////////////////////////////////////
815 // Voxel transformation and interpolation functions
816 ////////////////////////////////////////////////////////////////////////////////
817 
818 // -----------------------------------------------------------------------------
819 // Apply world coordinates
820 // -----------------------------------------------------------------------------
821 
822 // -----------------------------------------------------------------------------
823 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
824 struct MapIndicesInterpolatePut : public BaseTransform<InterpolateImageFunction, InputDomain>
825 {
826  MapIndicesInterpolatePut(const TransformData &data)
828  {}
829 
830  template <class OutputVoxelType>
831  void operator ()(int i, int j, int k, int, OutputVoxelType *out)
832  {
833  this->OutputToWorld(i, j, k);
834  this->WorldToInput();
835  this->template InterpolatePut(i, j, k, out);
836  }
837 
838  template <class OutputVoxelType>
839  void operator ()(int i, int j, int k, int, const double *o2w, OutputVoxelType *out)
840  {
841  this->OutputToWorld(o2w);
842  this->WorldToInput();
843  this->template InterpolatePut(i, j, k, out);
844  }
845 };
846 
847 // -----------------------------------------------------------------------------
848 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
849 struct MapIndicesInterpolatePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
850 {
851  MapIndicesInterpolatePutAsDouble(const TransformData &data)
853  {}
854 
855  void operator ()(int i, int j, int k, int, void *)
856  {
857  this->OutputToWorld(i, j, k);
858  this->WorldToInput();
859  this->InterpolatePutAsDouble(i, j, k);
860  }
861 
862  void operator ()(int i, int j, int k, int, const double *o2w, void *)
863  {
864  this->OutputToWorld(o2w);
865  this->WorldToInput();
866  this->InterpolatePutAsDouble(i, j, k);
867  }
868 };
869 
870 // -----------------------------------------------------------------------------
871 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
872 struct MapIndicesInterpolateRescalePut : public BaseTransform<InterpolateImageFunction, InputDomain>
873 {
874  MapIndicesInterpolateRescalePut(const TransformData &data)
876  {}
877 
878  template <class OutputVoxelType>
879  void operator ()(int i, int j, int k, int, OutputVoxelType *out)
880  {
881  this->OutputToWorld(i, j, k);
882  this->WorldToInput();
883  this->template InterpolateRescalePut(i, j, k, out);
884  }
885 
886  template <class OutputVoxelType>
887  void operator ()(int i, int j, int k, int, const double *o2w, OutputVoxelType *out)
888  {
889  this->OutputToWorld(o2w);
890  this->WorldToInput();
891  this->template InterpolateRescalePut(i, j, k, out);
892  }
893 };
894 
895 // -----------------------------------------------------------------------------
896 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
897 struct MapIndicesInterpolateRescalePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
898 {
899  MapIndicesInterpolateRescalePutAsDouble(const TransformData &data)
901  {}
902 
903  void operator ()(int i, int j, int k, int, void *)
904  {
905  this->OutputToWorld(i, j, k);
906  this->WorldToInput();
907  this->InterpolateRescalePutAsDouble(i, j, k);
908  }
909 
910  void operator ()(int i, int j, int k, int, const double *o2w, void *)
911  {
912  this->OutputToWorld(o2w);
913  this->WorldToInput();
914  this->InterpolateRescalePutAsDouble(i, j, k);
915  }
916 };
917 
918 // -----------------------------------------------------------------------------
919 // Apply single transformation
920 // -----------------------------------------------------------------------------
921 
922 // -----------------------------------------------------------------------------
923 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
924 struct TransformInterpolatePut : public BaseTransform<InterpolateImageFunction, InputDomain>
925 {
926  TransformInterpolatePut(const TransformData &data)
928  {}
929 
930  template <class OutputVoxelType>
931  void operator ()(int i, int j, int k, int, OutputVoxelType *out)
932  {
933  this->OutputToWorld(i, j, k);
934  this->ApplyTransformation();
935  this->WorldToInput();
936  this->template InterpolatePut(i, j, k, out);
937  }
938 
939  template <class OutputVoxelType>
940  void operator ()(int i, int j, int k, int, const double *o2w, OutputVoxelType *out)
941  {
942  this->OutputToWorld(o2w);
943  this->ApplyTransformation();
944  this->WorldToInput();
945  this->template InterpolatePut(i, j, k, out);
946  }
947 };
948 
949 // -----------------------------------------------------------------------------
950 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
951 struct TransformInterpolatePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
952 {
953  TransformInterpolatePutAsDouble(const TransformData &data)
955  {}
956 
957  void operator ()(int i, int j, int k, int, void *)
958  {
959  this->OutputToWorld(i, j, k);
960  this->ApplyTransformation();
961  this->WorldToInput();
962  this->InterpolatePutAsDouble(i, j, k);
963  }
964 
965  void operator ()(int i, int j, int k, int, const double *o2w, void *)
966  {
967  this->OutputToWorld(o2w);
968  this->ApplyTransformation();
969  this->WorldToInput();
970  this->InterpolatePutAsDouble(i, j, k);
971  }
972 };
973 
974 // -----------------------------------------------------------------------------
975 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
976 struct TransformInterpolateRescalePut : public BaseTransform<InterpolateImageFunction, InputDomain>
977 {
978  TransformInterpolateRescalePut(const TransformData &data)
980  {}
981 
982  template <class OutputVoxelType>
983  void operator ()(int i, int j, int k, int, OutputVoxelType *out)
984  {
985  this->OutputToWorld(i, j, k);
986  this->ApplyTransformation();
987  this->WorldToInput();
988  this->template InterpolateRescalePut(i, j, k, out);
989  }
990 
991  template <class OutputVoxelType>
992  void operator ()(int i, int j, int k, int, const double *o2w, OutputVoxelType *out)
993  {
994  this->OutputToWorld(o2w);
995  this->ApplyTransformation();
996  this->WorldToInput();
997  this->template InterpolateRescalePut(i, j, k, out);
998  }
999 };
1000 
1001 // -----------------------------------------------------------------------------
1002 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1003 struct TransformInterpolateRescalePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1004 {
1005  TransformInterpolateRescalePutAsDouble(const TransformData &data)
1007  {}
1008 
1009  void operator ()(int i, int j, int k, int, void *)
1010  {
1011  this->OutputToWorld(i, j, k);
1012  this->ApplyTransformation();
1013  this->WorldToInput();
1014  this->InterpolateRescalePutAsDouble(i, j, k);
1015  }
1016 
1017  void operator ()(int i, int j, int k, int, const double *o2w, void *)
1018  {
1019  this->OutputToWorld(o2w);
1020  this->ApplyTransformation();
1021  this->WorldToInput();
1022  this->InterpolateRescalePutAsDouble(i, j, k);
1023  }
1024 };
1025 
1026 // -----------------------------------------------------------------------------
1027 // Apply single displacement
1028 // -----------------------------------------------------------------------------
1029 
1030 // -----------------------------------------------------------------------------
1031 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1032 struct DisplaceInterpolatePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1033 {
1034  DisplaceInterpolatePut(const TransformData &data)
1036  {}
1037 
1038  template <class OutputVoxelType>
1039  void operator ()(int i, int j, int k, int, const double *disp1, OutputVoxelType *out)
1040  {
1041  this->OutputToWorld(i, j, k);
1042  this->ApplyDisplacement(disp1);
1043  this->WorldToInput();
1044  this->template InterpolatePut(i, j, k, out);
1045  }
1046 
1047  template <class OutputVoxelType>
1048  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, OutputVoxelType *out)
1049  {
1050  this->OutputToWorld(o2w);
1051  this->ApplyDisplacement(disp1);
1052  this->WorldToInput();
1053  this->template InterpolatePut(i, j, k, out);
1054  }
1055 };
1056 
1057 // -----------------------------------------------------------------------------
1058 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1059 struct DisplaceInterpolatePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1060 {
1061  DisplaceInterpolatePutAsDouble(const TransformData &data)
1063  {}
1064 
1065  void operator ()(int i, int j, int k, int, const double *disp1, void *)
1066  {
1067  this->OutputToWorld(i, j, k);
1068  this->ApplyDisplacement(disp1);
1069  this->WorldToInput();
1070  this->InterpolatePutAsDouble(i, j, k);
1071  }
1072 
1073  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, void *)
1074  {
1075  this->OutputToWorld(o2w);
1076  this->ApplyDisplacement(disp1);
1077  this->WorldToInput();
1078  this->InterpolatePutAsDouble(i, j, k);
1079  }
1080 };
1081 
1082 // -----------------------------------------------------------------------------
1083 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1084 struct DisplaceInterpolateRescalePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1085 {
1086  DisplaceInterpolateRescalePut(const TransformData &data)
1088  {}
1089 
1090  template <class OutputVoxelType>
1091  void operator ()(int i, int j, int k, int, const double *disp1, OutputVoxelType *out)
1092  {
1093  this->OutputToWorld(i, j, k);
1094  this->ApplyDisplacement(disp1);
1095  this->WorldToInput();
1096  this->template InterpolateRescalePut(i, j, k, out);
1097  }
1098 
1099  template <class OutputVoxelType>
1100  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, OutputVoxelType *out)
1101  {
1102  this->OutputToWorld(o2w);
1103  this->ApplyDisplacement(disp1);
1104  this->WorldToInput();
1105  this->template InterpolateRescalePut(i, j, k, out);
1106  }
1107 };
1108 
1109 // -----------------------------------------------------------------------------
1110 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1111 struct DisplaceInterpolateRescalePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1112 {
1113  DisplaceInterpolateRescalePutAsDouble(const TransformData &data)
1115  {}
1116 
1117  void operator ()(int i, int j, int k, int, const double *disp1, void *)
1118  {
1119  this->OutputToWorld(i, j, k);
1120  this->ApplyDisplacement(disp1);
1121  this->WorldToInput();
1122  this->InterpolateRescalePutAsDouble(i, j, k);
1123  }
1124 
1125  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, void *)
1126  {
1127  this->OutputToWorld(o2w);
1128  this->ApplyDisplacement(disp1);
1129  this->WorldToInput();
1130  this->InterpolateRescalePutAsDouble(i, j, k);
1131  }
1132 };
1133 
1134 // -----------------------------------------------------------------------------
1135 // Using composition of transformations
1136 // -----------------------------------------------------------------------------
1137 
1138 // -----------------------------------------------------------------------------
1139 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1140 struct FluidTransformInterpolatePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1141 {
1142  FluidTransformInterpolatePut(const TransformData &data)
1144  {}
1145 
1146  template <class OutputVoxelType>
1147  void operator ()(int i, int j, int k, int, OutputVoxelType *out)
1148  {
1149  this->OutputToWorld(i, j, k);
1150  this->ApplyTransformations();
1151  this->WorldToInput();
1152  this->template InterpolatePut(i, j, k, out);
1153  }
1154 
1155  template <class OutputVoxelType>
1156  void operator ()(int i, int j, int k, int, const double *o2w, OutputVoxelType *out)
1157  {
1158  this->OutputToWorld(o2w);
1159  this->ApplyTransformations();
1160  this->WorldToInput();
1161  this->template InterpolatePut(i, j, k, out);
1162  }
1163 };
1164 
1165 // -----------------------------------------------------------------------------
1166 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1167 struct FluidTransformInterpolatePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1168 {
1169  FluidTransformInterpolatePutAsDouble(const TransformData &data)
1171  {}
1172 
1173  void operator ()(int i, int j, int k, int, void *)
1174  {
1175  this->OutputToWorld(i, j, k);
1176  this->ApplyTransformations();
1177  this->WorldToInput();
1178  this->InterpolatePutAsDouble(i, j, k);
1179  }
1180 
1181  void operator ()(int i, int j, int k, int, const double *o2w, void *)
1182  {
1183  this->OutputToWorld(o2w);
1184  this->ApplyTransformations();
1185  this->WorldToInput();
1186  this->InterpolatePutAsDouble(i, j, k);
1187  }
1188 };
1189 
1190 // -----------------------------------------------------------------------------
1191 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1192 struct FluidTransformInterpolateRescalePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1193 {
1194  FluidTransformInterpolateRescalePut(const TransformData &data)
1196  {}
1197 
1198  template <class OutputVoxelType>
1199  void operator ()(int i, int j, int k, int, OutputVoxelType *out)
1200  {
1201  this->OutputToWorld(i, j, k);
1202  this->ApplyTransformations();
1203  this->WorldToInput();
1204  this->template InterpolateRescalePut(i, j, k, out);
1205  }
1206 
1207  template <class OutputVoxelType>
1208  void operator ()(int i, int j, int k, int, const double *o2w, OutputVoxelType *out)
1209  {
1210  this->OutputToWorld(o2w);
1211  this->ApplyTransformations();
1212  this->WorldToInput();
1213  this->template InterpolateRescalePut(i, j, k, out);
1214  }
1215 };
1216 
1217 // -----------------------------------------------------------------------------
1218 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1219 struct FluidTransformInterpolateRescalePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1220 {
1221  FluidTransformInterpolateRescalePutAsDouble(const TransformData &data)
1223  {}
1224 
1225  void operator ()(int i, int j, int k, int, void *)
1226  {
1227  this->OutputToWorld(i, j, k);
1228  this->ApplyTransformations();
1229  this->WorldToInput();
1230  this->InterpolateRescalePutAsDouble(i, j, k);
1231  }
1232 
1233  void operator ()(int i, int j, int k, int, const double *o2w, void *)
1234  {
1235  this->OutputToWorld(o2w);
1236  this->ApplyTransformations();
1237  this->WorldToInput();
1238  this->InterpolateRescalePutAsDouble(i, j, k);
1239  }
1240 };
1241 
1242 // -----------------------------------------------------------------------------
1243 // Using composition of displacement and transformation
1244 // -----------------------------------------------------------------------------
1245 
1246 // -----------------------------------------------------------------------------
1247 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1248 struct DisplaceTransformInterpolatePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1249 {
1250  DisplaceTransformInterpolatePut(const TransformData &data)
1252  {
1253  if (this->_Transformation1 && !this->_Transformation2) {
1254  this->_Transformation2 = this->_Transformation1;
1255  }
1256  }
1257 
1258  template <class OutputVoxelType>
1259  void operator ()(int i, int j, int k, int, const double *disp1, OutputVoxelType *out)
1260  {
1261  this->OutputToWorld(i, j, k);
1262  this->ApplyDisplacementAndTransformation(disp1);
1263  this->WorldToInput();
1264  this->template InterpolatePut(i, j, k, out);
1265  }
1266 
1267  template <class OutputVoxelType>
1268  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, OutputVoxelType *out)
1269  {
1270  this->OutputToWorld(o2w);
1271  this->ApplyDisplacementAndTransformation(disp1);
1272  this->WorldToInput();
1273  this->template InterpolatePut(i, j, k, out);
1274  }
1275 };
1276 
1277 // -----------------------------------------------------------------------------
1278 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1279 struct DisplaceTransformInterpolatePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1280 {
1281  DisplaceTransformInterpolatePutAsDouble(const TransformData &data)
1283  {
1284  if (this->_Transformation1 && !this->_Transformation2) {
1285  this->_Transformation2 = this->_Transformation1;
1286  }
1287  }
1288 
1289  void operator ()(int i, int j, int k, int, const double *disp1, void *)
1290  {
1291  this->OutputToWorld(i, j, k);
1292  this->ApplyDisplacementAndTransformation(disp1);
1293  this->WorldToInput();
1294  this->InterpolatePutAsDouble(i, j, k);
1295  }
1296 
1297  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, void *)
1298  {
1299  this->OutputToWorld(o2w);
1300  this->ApplyDisplacementAndTransformation(disp1);
1301  this->WorldToInput();
1302  this->InterpolatePutAsDouble(i, j, k);
1303  }
1304 };
1305 
1306 // -----------------------------------------------------------------------------
1307 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1308 struct DisplaceTransformInterpolateRescalePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1309 {
1310  DisplaceTransformInterpolateRescalePut(const TransformData &data)
1312  {
1313  if (this->_Transformation1 && !this->_Transformation2) {
1314  this->_Transformation2 = this->_Transformation1;
1315  }
1316  }
1317 
1318  template <class OutputVoxelType>
1319  void operator ()(int i, int j, int k, int, const double *disp1, OutputVoxelType *out)
1320  {
1321  this->OutputToWorld(i, j, k);
1322  this->ApplyDisplacementAndTransformation(disp1);
1323  this->WorldToInput();
1324  this->template InterpolateRescalePut(i, j, k, out);
1325  }
1326 
1327  template <class OutputVoxelType>
1328  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, OutputVoxelType *out)
1329  {
1330  this->OutputToWorld(o2w);
1331  this->ApplyDisplacementAndTransformation(disp1);
1332  this->WorldToInput();
1333  this->template InterpolateRescalePut(i, j, k, out);
1334  }
1335 };
1336 
1337 // -----------------------------------------------------------------------------
1338 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1339 struct DisplaceTransformInterpolateRescalePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1340 {
1341  DisplaceTransformInterpolateRescalePutAsDouble(const TransformData &data)
1343  {
1344  if (this->_Transformation1 && !this->_Transformation2) {
1345  this->_Transformation2 = this->_Transformation1;
1346  }
1347  }
1348 
1349  void operator ()(int i, int j, int k, int, const double *disp1, void *)
1350  {
1351  this->OutputToWorld(i, j, k);
1352  this->ApplyDisplacementAndTransformation(disp1);
1353  this->WorldToInput();
1354  this->InterpolateRescalePutAsDouble(i, j, k);
1355  }
1356 
1357  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, void *)
1358  {
1359  this->OutputToWorld(o2w);
1360  this->ApplyDisplacementAndTransformation(disp1);
1361  this->WorldToInput();
1362  this->InterpolateRescalePutAsDouble(i, j, k);
1363  }
1364 };
1365 
1366 // -----------------------------------------------------------------------------
1367 // Using additive composition of displacements
1368 // -----------------------------------------------------------------------------
1369 
1370 // -----------------------------------------------------------------------------
1371 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1372 struct AddDisplacementsInterpolatePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1373 {
1374  AddDisplacementsInterpolatePut(const TransformData &data)
1376  {}
1377 
1378  template <class OutputVoxelType>
1379  void operator ()(int i, int j, int k, int, const double *disp1, const double *disp2, OutputVoxelType *out)
1380  {
1381  this->OutputToWorld(i, j, k);
1382  this->ApplyDisplacements(disp1, disp2);
1383  this->WorldToInput();
1384  this->template InterpolatePut(i, j, k, out);
1385  }
1386 
1387  template <class OutputVoxelType>
1388  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, const double *disp2, OutputVoxelType *out)
1389  {
1390  this->OutputToWorld(o2w);
1391  this->ApplyDisplacements(disp1, disp2);
1392  this->WorldToInput();
1393  this->template InterpolatePut(i, j, k, out);
1394  }
1395 };
1396 
1397 // -----------------------------------------------------------------------------
1398 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1399 struct AddDisplacementsInterpolatePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1400 {
1401  AddDisplacementsInterpolatePutAsDouble(const TransformData &data)
1403  {}
1404 
1405  void operator ()(int i, int j, int k, int, const double *disp1, const double *disp2, void *)
1406  {
1407  this->OutputToWorld(i, j, k);
1408  this->ApplyDisplacements(disp1, disp2);
1409  this->WorldToInput();
1410  this->InterpolatePutAsDouble(i, j, k);
1411  }
1412 
1413  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, const double *disp2, void *)
1414  {
1415  this->OutputToWorld(o2w);
1416  this->ApplyDisplacements(disp1, disp2);
1417  this->WorldToInput();
1418  this->InterpolatePutAsDouble(i, j, k);
1419  }
1420 };
1421 
1422 // -----------------------------------------------------------------------------
1423 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1424 struct AddDisplacementsInterpolateRescalePut : public BaseTransform<InterpolateImageFunction, InputDomain>
1425 {
1426  AddDisplacementsInterpolateRescalePut(const TransformData &data)
1428  {}
1429 
1430  template <class OutputVoxelType>
1431  void operator ()(int i, int j, int k, int, const double *disp1, const double *disp2, OutputVoxelType *out)
1432  {
1433  this->OutputToWorld(i, j, k);
1434  this->ApplyDisplacements(disp1, disp2);
1435  this->WorldToInput();
1436  this->template InterpolateRescalePut(i, j, k, out);
1437  }
1438 
1439  template <class OutputVoxelType>
1440  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, const double *disp2, OutputVoxelType *out)
1441  {
1442  this->OutputToWorld(o2w);
1443  this->ApplyDisplacements(disp1, disp2);
1444  this->WorldToInput();
1445  this->template InterpolateRescalePut(i, j, k, out);
1446  }
1447 };
1448 
1449 // -----------------------------------------------------------------------------
1450 template <class InterpolateImageFunction = InterpolateImageFunction, class InputDomain = InterpolationDomain::Foreground>
1451 struct AddDisplacementsInterpolateRescalePutAsDouble : public BaseTransform<InterpolateImageFunction, InputDomain>
1452 {
1453  AddDisplacementsInterpolateRescalePutAsDouble(const TransformData &data)
1455  {}
1456 
1457  void operator ()(int i, int j, int k, int, const double *disp1, const double *disp2, void *)
1458  {
1459  this->OutputToWorld(i, j, k);
1460  this->ApplyDisplacements(disp1, disp2);
1461  this->WorldToInput();
1462  this->InterpolateRescalePutAsDouble(i, j, k);
1463  }
1464 
1465  void operator ()(int i, int j, int k, int, const double *o2w, const double *disp1, const double *disp2, void *)
1466  {
1467  this->OutputToWorld(o2w);
1468  this->ApplyDisplacements(disp1, disp2);
1469  this->WorldToInput();
1470  this->InterpolateRescalePutAsDouble(i, j, k);
1471  }
1472 };
1473 
1474 
1475 } } // namespace mirtk::MultipleVoxelTransformation
1476 
1477 #endif // MIRTK_MultipleVoxelTransformation_H
Base class for voxel transformation functions.
void InterpolateRescalePut(int i, int j, int k, OutputVoxelType *)
const T & z_(const T *p) const
Get const reference to z component of vector field.
InterpolateImageFunction * _Interpolator
Single/reference interpolator.
void OutputToWorld(const double *i2w)
Convert output voxel indices to world coordinates given pointer to lookup table.
void InitializeMemory()
Allocate memory for interpolated values the first time.
const T & x_(const T *p) const
Get const reference to x component of vector field.
const BaseImage * _Input
Single/reference input.
MIRTKCU_API bool IsNaN(double x)
Check if floating point value is not a number (NaN)
Definition: Math.h:91
InterpolateImageFunction * GetInterpolator(int n)
Get (casted) pointer to interpolator of type InterpolateImageFunction.
T & z_(T *p) const
Get reference to z component of vector field.
virtual double EvaluateInside(double, double, double=0, double=0) const =0
void WorldToInput()
Convert world coordinates to input voxel indices.
void InterpolatePut(int i, int j, int k, OutputVoxelType *)
const T & y_(const T *p) const
Get const reference to y component of vector field.
int _NumberOfVoxels
Number of voxels per vector component.
BaseTransform(const BaseTransform &other)
Copy constructor.
InterpolateImageFunction * GetInterpolator()
Get (casted) pointer to reference interpolator of type InterpolateImageFunction.
Definition: IOConfig.h:41
T & x_(T *p) const
Get reference to x component of vector field.
BaseTransform(const TransformData &data)
Constructor.
bool _Invert
Whether to invert the transformations.
const Transformation * _Transformation1
First transformation.
int _MaxNumberOfComponents
Maximum number of image components/channels (_t)
void ApplyTransformations()
Transform using fluid composition of transformations.
T & y_(T *p) const
Get reference to y component of vector field.
virtual void PutAsDouble(int, double)
Function for pixel put access.
Definition: BaseImage.h:1301
Base(const Base &other)
Copy constructor.
InterpolateImageFunction ** _Interpolators
Input interpolators.
void OutputToWorld(int i, int j, int k)
Convert output voxel indices to world coordinates.
const Transformation * _Transformation2
Second transformation (optional)
Interpolate(const Interpolate &)
Copy constructor.
double * _v
Pre-allocated memory for interpolated values.
void ApplyDisplacements(const double *disp1, const double *disp2)
void Transform(Array< T > &values, UnaryOperation op)
Apply unary operation for each array element in-place.
Definition: Algorithm.h:91
Input/output data members of voxel transformation functions.
void PutVoxelTransformation(int i, int j, int k, double *o2i)
Update map from output to input voxel indices with inside check.