Slicer  4.8
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
vtkITKTransformConverter.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: $RCSfile: vtkITKTransformConverter.h,v $
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #ifndef __vtkITKTransformConverter_h
17 #define __vtkITKTransformConverter_h
18 
19 #include "vtkMRMLTransformNode.h"
20 
21 // VTK includes
22 #include <vtkImageData.h>
23 #include <vtkPoints.h>
24 #include <vtkThinPlateSplineTransform.h>
25 #include <vtkTransform.h>
26 
27 // ITK includes
28 #include <itkAffineTransform.h>
29 #include <itkBSplineDeformableTransform.h> // ITKv3 style
30 #include <itkBSplineTransform.h> // ITKv4 style
31 #include <itkCompositeTransform.h>
32 #include <itkCompositeTransformIOHelper.h>
33 #include <itkDisplacementFieldTransform.h>
34 #include <itkIdentityTransform.h>
35 #include <itkTransformFileWriter.h>
36 #include <itkTransformFileReader.h>
37 #include <itkImageFileReader.h>
38 #include <itkImageFileWriter.h>
39 #include <itkTranslationTransform.h>
40 #include <itkScaleTransform.h>
41 #include <itkTransformFactory.h>
42 #include <itkThinPlateSplineKernelTransform.h>
43 
44 // Constants and typedefs
45 
46 static const unsigned int VTKDimension = 3;
47 
48 static const int BSPLINE_TRANSFORM_ORDER = 3;
49 
50 typedef itk::TransformFileWriter TransformWriterType;
51 
52 typedef itk::DisplacementFieldTransform< double, 3 > DisplacementFieldTransformDoubleType;
53 typedef DisplacementFieldTransformDoubleType::DisplacementFieldType GridImageDoubleType;
54 
55 typedef itk::ThinPlateSplineKernelTransform<double,3> ThinPlateSplineTransformDoubleType;
56 
57 #include "vtkITKTransformInverse.h"
58 
60 {
61 public:
62 
63  static void RegisterInverseTransformTypes();
64 
65  template<typename T>
66  static vtkAbstractTransform* CreateVTKTransformFromITK(vtkObject* loggerObject, typename itk::TransformBaseTemplate<T>::Pointer transformItk);
67 
77  static itk::Object::Pointer CreateITKTransformFromVTK(vtkObject* loggerObject, vtkAbstractTransform* transformVtk,
78  itk::Object::Pointer& secondaryTransformItk, int preferITKv3CompatibleTransforms, bool initialize = true);
79 
80  template <typename T> static bool SetVTKBSplineFromITKv3Generic(vtkObject* loggerObject, vtkOrientedBSplineTransform* bsplineVtk, typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk, typename itk::TransformBaseTemplate<T>::Pointer bulkTransformItk);
81 
82  template<typename T>
83  static bool SetVTKOrientedGridTransformFromITKImage(vtkObject* loggerObject, vtkOrientedGridTransform* grid_Ras, typename itk::DisplacementFieldTransform< T, 3 >::DisplacementFieldType::Pointer gridImage_Lps);
84  static bool SetITKImageFromVTKOrientedGridTransform(vtkObject* loggerObject, GridImageDoubleType::Pointer &gridImage_Lps, vtkOrientedGridTransform* grid_Ras);
85 
86 protected:
87 
88  template<typename T>
89  static bool SetVTKLinearTransformFromITK(vtkObject* loggerObject, vtkMatrix4x4* transformVtk_RAS, typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS);
90  static bool SetITKLinearTransformFromVTK(vtkObject* loggerObject, itk::Object::Pointer& transformItk_LPS, vtkMatrix4x4* transformVtk_RAS);
91 
92  template<typename T>
93  static bool SetVTKOrientedGridTransformFromITK(vtkObject* loggerObject, vtkOrientedGridTransform* transformVtk_RAS, typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS);
94  static bool SetITKOrientedGridTransformFromVTK(vtkObject* loggerObject, itk::Object::Pointer& transformItk_LPS, vtkOrientedGridTransform* transformVtk_RAS);
95 
96  static bool SetITKv3BSplineFromVTK(vtkObject* loggerObject, itk::Object::Pointer& warpTransformItk, itk::Object::Pointer& bulkTransformItk, vtkOrientedBSplineTransform* bsplineVtk, bool alwaysAddBulkTransform);
97  static bool SetITKv4BSplineFromVTK(vtkObject* loggerObject, itk::Object::Pointer& warpTransformItk, vtkOrientedBSplineTransform* bsplineVtk);
98 
99  template<typename T>
100  static bool SetVTKThinPlateSplineTransformFromITK(vtkObject* loggerObject, vtkThinPlateSplineTransform* transformVtk_RAS, typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS);
101  static bool SetITKThinPlateSplineTransformFromVTK(vtkObject* loggerObject, itk::Object::Pointer& transformItk_LPS,
102  vtkThinPlateSplineTransform* transformVtk_RAS, bool initialize = true);
103 
104  static bool IsIdentityMatrix(vtkMatrix4x4 *matrix);
105 
106  template <typename BSplineTransformType> static bool SetVTKBSplineParametersFromITKGeneric(vtkObject* loggerObject, vtkOrientedBSplineTransform* bsplineVtk, typename itk::TransformBaseTemplate<typename BSplineTransformType::ScalarType>::Pointer warpTransformItk);
107  template <typename T> static bool SetVTKBSplineFromITKv4Generic(vtkObject* loggerObject, vtkOrientedBSplineTransform* bsplineVtk, typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk);
108 
109  template <typename BSplineTransformType> static bool SetITKBSplineParametersFromVTKGeneric(vtkObject* loggerObject, typename itk::Transform< typename BSplineTransformType::ScalarType,VTKDimension,VTKDimension>::Pointer& warpTransformItk, vtkOrientedBSplineTransform* bsplineVtk);
110  template <typename T> static bool SetITKv3BSplineFromVTKGeneric(vtkObject* loggerObject, typename itk::Transform<T,VTKDimension,VTKDimension>::Pointer& warpTransformItk, typename itk::Transform<T,VTKDimension,VTKDimension>::Pointer& bulkTransformItk, vtkOrientedBSplineTransform* bsplineVtk, bool alwaysAddBulkTransform);
111  template <typename T> static bool SetITKv4BSplineFromVTKGeneric(vtkObject* loggerObject, typename itk::Transform<T,VTKDimension,VTKDimension>::Pointer& warpTransformItk, vtkOrientedBSplineTransform* bsplineVtk);
112 
113 };
114 
115 //----------------------------------------------------------------------------
117 {
118  itk::TransformFactory<InverseDisplacementFieldTransformFloatType>::RegisterTransform();
119  itk::TransformFactory<InverseDisplacementFieldTransformDoubleType>::RegisterTransform();
120 
121  itk::TransformFactory<InverseBSplineTransformFloatITKv3Type>::RegisterTransform();
122  itk::TransformFactory<InverseBSplineTransformFloatITKv4Type>::RegisterTransform();
123  itk::TransformFactory<InverseBSplineTransformDoubleITKv3Type>::RegisterTransform();
124  itk::TransformFactory<InverseBSplineTransformDoubleITKv4Type>::RegisterTransform();
125 
126  itk::TransformFactory<InverseThinPlateSplineTransformFloatType>::RegisterTransform();
127  itk::TransformFactory<InverseThinPlateSplineTransformDoubleType>::RegisterTransform();
128 
129  typedef itk::ThinPlateSplineKernelTransform<float,3> ThinPlateSplineTransformFloatType;
130  typedef itk::ThinPlateSplineKernelTransform<double,3> ThinPlateSplineTransformDoubleType;
131 
132  // by default they are not registered
133  itk::TransformFactory<ThinPlateSplineTransformFloatType>::RegisterTransform();
134  itk::TransformFactory<ThinPlateSplineTransformDoubleType>::RegisterTransform();
135 }
136 
137 //----------------------------------------------------------------------------
138 template<typename T>
140  vtkObject* /*loggerObject*/,
141  vtkMatrix4x4* transformVtk_RAS,
142  typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
143 {
144  static const unsigned int D = VTKDimension;
145  typedef itk::MatrixOffsetTransformBase<T,D,D> LinearTransformType;
146  typedef itk::ScaleTransform<T, D> ScaleTransformType;
147  typedef itk::TranslationTransform<T, D> TranslateTransformType;
148 
149  vtkSmartPointer<vtkMatrix4x4> transformVtk_LPS = vtkSmartPointer<vtkMatrix4x4>::New();
150 
151  bool convertedToVtkMatrix=false;
152 
153  std::string itkTransformClassName = transformItk_LPS->GetNameOfClass();
154 
155  // Linear transform of doubles or floats, dimension 3
156 
157  // ITKIO transform libraries are build as shared and dynamic_cast
158  // can NOT be used with templated classes that are
159  // instantiated in a translation unit different than the one where they are
160  // defined. It will work only if the classes are explicitly instantiated
161  // and exported.
162  // To workaround the issue, instead of using dynamic_cast:
163  // (1) to ensure the objects are of the right type string comparison is done
164  // (2) static_cast is used instead of dynamic_cast.
165  // See InsightSoftwareConsortium/ITK@d1e9fe2
166  // and see http://stackoverflow.com/questions/8024010/why-do-template-class-functions-have-to-be-declared-in-the-same-translation-unit
167  //
168  // The disadvantage of this approach is that each supported class name has to be explicitly listed here and if the class hierarchy changes in ITK
169  // then the static cast may produce invalid results. Also, even if the transform class name is matching,
170  // we may cast the transform to a wrong type due to mismatch in dimensions (not 3) or data type (not double or float).
171 
172  if (itkTransformClassName.find( "AffineTransform" ) != std::string::npos ||
173  itkTransformClassName == "MatrixOffsetTransformBase" ||
174  itkTransformClassName == "Rigid3DTransform" ||
175  itkTransformClassName == "Euler3DTransform" ||
176  itkTransformClassName == "CenteredEuler3DTransform" ||
177  itkTransformClassName == "QuaternionRigidTransform" ||
178  itkTransformClassName == "VersorTransform" ||
179  itkTransformClassName == "VersorRigid3DTransform" ||
180  itkTransformClassName == "ScaleSkewVersor3DTransform" ||
181  itkTransformClassName == "ScaleVersor3DTransform" ||
182  itkTransformClassName == "Similarity3DTransform" ||
183  itkTransformClassName == "ScaleTransform" ||
184  itkTransformClassName == "ScaleLogarithmicTransform")
185  {
186  typename LinearTransformType::Pointer dlt
187  = static_cast<LinearTransformType*>( transformItk_LPS.GetPointer() );
188  convertedToVtkMatrix=true;
189  for (unsigned int i=0; i < D; i++)
190  {
191  for (unsigned int j=0; j < D; j++)
192  {
193  transformVtk_LPS->SetElement(i, j, dlt->GetMatrix()[i][j]);
194  }
195  transformVtk_LPS->SetElement(i, D, dlt->GetOffset()[i]);
196  }
197  }
198 
199  // Identity transform of doubles or floats, dimension 3
200  if (itkTransformClassName == "IdentityTransform")
201  {
202  // nothing to do, matrix is already the identity
203  convertedToVtkMatrix=true;
204  }
205 
206  // Scale transform of doubles or floats, dimension 3
207  if (itkTransformClassName == "ScaleTransform")
208  {
209  typename ScaleTransformType::Pointer dst
210  = static_cast<ScaleTransformType*>( transformItk_LPS.GetPointer() );
211  convertedToVtkMatrix=true;
212  for (unsigned int i=0; i < D; i++)
213  {
214  transformVtk_LPS->SetElement(i, i, dst->GetScale()[i]);
215  }
216  }
217 
218  // Translate transform of doubles or floats, dimension 3
219  if (itkTransformClassName == "TranslationTransform")
220  {
221  typename TranslateTransformType::Pointer dtt
222  = static_cast<TranslateTransformType*>( transformItk_LPS.GetPointer());
223  convertedToVtkMatrix=true;
224  for (unsigned int i=0; i < D; i++)
225  {
226  transformVtk_LPS->SetElement(i, D, dtt->GetOffset()[i]);
227  }
228  }
229 
230  // Convert from LPS (ITK) to RAS (Slicer)
231  //
232  // Tras = lps2ras * Tlps * ras2lps
233  //
234 
235  vtkSmartPointer<vtkMatrix4x4> lps2ras = vtkSmartPointer<vtkMatrix4x4>::New();
236  lps2ras->SetElement(0,0,-1);
237  lps2ras->SetElement(1,1,-1);
238  vtkMatrix4x4* ras2lps = lps2ras; // lps2ras is diagonal therefore the inverse is identical
239 
240  vtkMatrix4x4::Multiply4x4(lps2ras, transformVtk_LPS, transformVtk_LPS);
241  vtkMatrix4x4::Multiply4x4(transformVtk_LPS, ras2lps, transformVtk_RAS);
242 
243  return convertedToVtkMatrix;
244 }
245 
246 //----------------------------------------------------------------------------
247 bool vtkITKTransformConverter::SetITKLinearTransformFromVTK(vtkObject* loggerObject, itk::Object::Pointer& transformItk_LPS, vtkMatrix4x4* transformVtk_RAS)
248 {
249  typedef itk::AffineTransform<double, VTKDimension> AffineTransformType;
250 
251  if (transformVtk_RAS==NULL)
252  {
253  vtkErrorWithObjectMacro(loggerObject,"vtkITKTransformConverter::SetITKLinearTransformFromVTK failed: invalid input transform");
254  return false;
255  }
256 
257  vtkSmartPointer<vtkMatrix4x4> lps2ras = vtkSmartPointer<vtkMatrix4x4>::New();
258  lps2ras->SetElement(0,0,-1);
259  lps2ras->SetElement(1,1,-1);
260  vtkMatrix4x4* ras2lps = lps2ras; // lps2ras is diagonal therefore the inverse is identical
261 
262  // Convert from RAS (Slicer) to LPS (ITK)
263  //
264  // Tlps = ras2lps * Tras * lps2ras
265  //
266  vtkSmartPointer<vtkMatrix4x4> vtkmat = vtkSmartPointer<vtkMatrix4x4>::New();
267 
268  vtkMatrix4x4::Multiply4x4(ras2lps, transformVtk_RAS, vtkmat);
269  vtkMatrix4x4::Multiply4x4(vtkmat, lps2ras, vtkmat);
270 
271  typedef AffineTransformType::MatrixType MatrixType;
272  typedef AffineTransformType::OutputVectorType OffsetType;
273 
274  MatrixType itkmat;
275  OffsetType itkoffset;
276 
277  for (unsigned int i=0; i < VTKDimension; i++)
278  {
279  for (unsigned int j=0; j < VTKDimension; j++)
280  {
281  itkmat[i][j] = vtkmat->GetElement(i, j);
282  }
283  itkoffset[i] = vtkmat->GetElement(i, VTKDimension);
284  }
285 
286  AffineTransformType::Pointer affine = AffineTransformType::New();
287  affine->SetMatrix(itkmat);
288  affine->SetOffset(itkoffset);
289 
290  transformItk_LPS = affine;
291  return true;
292 }
293 
294 //----------------------------------------------------------------------------
296 {
297  static double identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
298  int i,j;
299 
300  for (i = 0; i < 4; i++)
301  {
302  for (j = 0; j < 4; j++)
303  {
304  if (matrix->GetElement(i,j) != identity[4*i+j])
305  {
306  return false;
307  }
308  }
309  }
310  return true;
311 }
312 
313 //----------------------------------------------------------------------------
314 template <typename BSplineTransformType>
316  vtkObject* loggerObject,
317  vtkOrientedBSplineTransform* bsplineVtk,
318  typename itk::TransformBaseTemplate<typename BSplineTransformType::ScalarType>::Pointer warpTransformItk)
319 {
320  //
321  // this version uses the itk::BSplineTransform not the itk::BSplineDeformableTransform
322  //
323  typedef typename BSplineTransformType::ScalarType T;
324  if (bsplineVtk==NULL)
325  {
326  vtkErrorWithObjectMacro(loggerObject, "vtkMRMLTransformStorageNode::SetVTKBSplineFromITKv4 failed: bsplineVtk is invalid");
327  return false;
328  }
329  bool isDoublePrecisionInput=true;
330  if (sizeof(T)==sizeof(float))
331  {
332  isDoublePrecisionInput=false;
333  }
334  else if (sizeof(T)==sizeof(double))
335  {
336  isDoublePrecisionInput=true;
337  }
338  else
339  {
340  vtkErrorWithObjectMacro(loggerObject,"Unsupported scalar type in BSpline transform file (only float and double are supported)");
341  return false;
342  }
343 
344  typename BSplineTransformType::Pointer bsplineItk = BSplineTransformType::New();
345  std::string warpTransformItkName = warpTransformItk->GetNameOfClass();
346  std::string requestedWarpTransformItkName = bsplineItk->GetNameOfClass();
347  if (warpTransformItkName != requestedWarpTransformItkName)
348  {
349  return false;
350  }
351  if (warpTransformItk->GetOutputSpaceDimension() != VTKDimension)
352  {
353  vtkErrorWithObjectMacro(loggerObject, "Unsupported number of dimensions in BSpline transform file (expected = "
354  << VTKDimension << ", actual = " << warpTransformItk->GetOutputSpaceDimension() << ")");
355  return false;
356  }
357  bsplineItk = static_cast< BSplineTransformType* >( warpTransformItk.GetPointer() );
358 
359  // now get the fixed parameters and map them to the vtk analogs
360 
361  // it turns out that for a BSplineTransform, the TransformDomain information
362  // is not populated when reading from a file, so instead we access these
363  // fields from one of the coefficient images (they are assumed to be
364  // identical)
365  const typename BSplineTransformType::CoefficientImageArray coefficientImages =
366  bsplineItk->GetCoefficientImages();
367 
368  // * mesh size X, Y, Z (including the BSPLINE_TRANSFORM_ORDER=3 boundary nodes,
369  // 1 before and 2 after the grid)
370  typename BSplineTransformType::MeshSizeType meshSize =
371  coefficientImages[0]->GetLargestPossibleRegion().GetSize();
372 
373  // * mesh origin X, Y, Z (position of the boundary node before the grid)
374  typename BSplineTransformType::OriginType origin =
375  coefficientImages[0]->GetOrigin();
376 
377  // * mesh spacing X, Y, Z
378  typename BSplineTransformType::SpacingType spacing =
379  coefficientImages[0]->GetSpacing();
380 
381  // * mesh direction 3x3 matrix (first row, second row, third row)
382  typename BSplineTransformType::DirectionType direction =
383  coefficientImages[0]->GetDirection();
384 
385  vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
386  for (unsigned int row=0; row<VTKDimension; row++)
387  {
388  for (unsigned int column=0; column<VTKDimension; column++)
389  {
390  gridDirectionMatrix_LPS->SetElement(row,column,direction[row][column]);
391  }
392  }
393 
394  // Set bspline grid and coefficients
395  bsplineVtk->SetBorderModeToZero();
396 
397  vtkNew<vtkImageData> bsplineCoefficients;
398 
399  bsplineCoefficients->SetExtent(0, meshSize[0]-1, 0, meshSize[1]-1, 0, meshSize[2]-1);
400  bsplineCoefficients->SetSpacing(spacing[0], spacing[1], spacing[2]);
401 
402  // convert the direction matrix from LPS (itk) to RAS (slicer)
403  vtkNew<vtkMatrix4x4> lpsToRas;
404  lpsToRas->SetElement(0,0,-1);
405  lpsToRas->SetElement(1,1,-1);
406 
407  vtkNew<vtkMatrix4x4> rasToLps;
408  rasToLps->SetElement(0,0,-1);
409  rasToLps->SetElement(1,1,-1);
410 
411  vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
412  vtkMatrix4x4::Multiply4x4(
413  lpsToRas.GetPointer(),
414  gridDirectionMatrix_LPS.GetPointer(),
415  gridDirectionMatrix_RAS.GetPointer());
416  bsplineVtk->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
417 
418  // convert the origin from LPS (itk) to RAS (slicer)
419  double gridOrigin_RAS[3]={-origin[0], -origin[1], origin[2]};
420  bsplineCoefficients->SetOrigin(gridOrigin_RAS);
421 
422  int bsplineCoefficientsScalarType=VTK_FLOAT;
423  if (isDoublePrecisionInput)
424  {
425  bsplineCoefficientsScalarType=VTK_DOUBLE;
426  }
427 
428  bsplineCoefficients->AllocateScalars(bsplineCoefficientsScalarType, 3);
429 
430  const unsigned int expectedNumberOfVectors = meshSize[0]*meshSize[1]*meshSize[2];
431  const unsigned int expectedNumberOfParameters = expectedNumberOfVectors*VTKDimension;
432  const unsigned int actualNumberOfParameters = bsplineItk->GetNumberOfParameters();
433 
434  if( actualNumberOfParameters != expectedNumberOfParameters )
435  {
436  vtkErrorWithObjectMacro(loggerObject,"Mismatch in number of BSpline parameters in the transform file and the MRML node");
437  return false;
438  }
439  const T* itkBSplineParams_LPS = static_cast<const T*>(bsplineItk->GetParameters().data_block());
440  T* vtkBSplineParams_RAS=static_cast<T*>(bsplineCoefficients->GetScalarPointer());
441  for (unsigned int i=0; i<expectedNumberOfVectors; i++)
442  {
443  *(vtkBSplineParams_RAS++) = - (*(itkBSplineParams_LPS ));
444  *(vtkBSplineParams_RAS++) = - (*(itkBSplineParams_LPS+expectedNumberOfVectors ));
445  *(vtkBSplineParams_RAS++) = (*(itkBSplineParams_LPS+expectedNumberOfVectors*2));
446  itkBSplineParams_LPS++;
447  }
448  bsplineVtk->SetCoefficientData(bsplineCoefficients.GetPointer());
449 
450  // Success
451  return true;
452 }
453 
454 //----------------------------------------------------------------------------
455 template <typename T> bool vtkITKTransformConverter::SetVTKBSplineFromITKv3Generic(vtkObject* loggerObject,
456  vtkOrientedBSplineTransform* bsplineVtk,
457  typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk, typename itk::TransformBaseTemplate<T>::Pointer bulkTransformItk)
458 {
459  if (bsplineVtk==NULL)
460  {
461  vtkErrorWithObjectMacro(loggerObject, "vtkMRMLTransformStorageNode::SetVTKBSplineFromITK failed: bsplineVtk is invalid");
462  return false;
463  }
464 
465  bool inverse = false;
466  // inverse class is derived from forward class, so it has to be checked first
468  {
469  inverse = true;
470  }
471  else if (SetVTKBSplineParametersFromITKGeneric< itk::BSplineDeformableTransform< T, VTKDimension, VTKDimension > >(loggerObject, bsplineVtk, warpTransformItk))
472  {
473  inverse = false;
474  }
475  else
476  {
477  vtkDebugWithObjectMacro(loggerObject, "Not an ITKv3 BSpline transform");
478  return false;
479  }
480 
481  // Set the bulk transform
482  if( bulkTransformItk )
483  {
484  std::string bulkTransformItkTransformName = bulkTransformItk->GetNameOfClass();
485 
486  typedef itk::AffineTransform<T,3> BulkTransformType;
487 
488  if (bulkTransformItkTransformName == "AffineTransform")
489  {
490  BulkTransformType* bulkItkAffine = static_cast<BulkTransformType*> (bulkTransformItk.GetPointer());
491  vtkNew<vtkMatrix4x4> bulkMatrix_LPS;
492  for (unsigned int i=0; i < VTKDimension; i++)
493  {
494  for (unsigned int j=0; j < VTKDimension; j++)
495  {
496  bulkMatrix_LPS->SetElement(i,j, bulkItkAffine->GetMatrix()[i][j]);
497  }
498  bulkMatrix_LPS->SetElement(i,VTKDimension, bulkItkAffine->GetOffset()[i]);
499  }
500  vtkNew<vtkMatrix4x4> lpsToRas;
501  lpsToRas->SetElement(0,0,-1);
502  lpsToRas->SetElement(1,1,-1);
503  vtkNew<vtkMatrix4x4> rasToLps;
504  rasToLps->SetElement(0,0,-1);
505  rasToLps->SetElement(1,1,-1);
506  vtkNew<vtkMatrix4x4> bulkMatrix_RAS; // bulk_RAS = lpsToRas * bulk_LPS * rasToLps
507  vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), bulkMatrix_LPS.GetPointer(), bulkMatrix_RAS.GetPointer());
508  vtkMatrix4x4::Multiply4x4(bulkMatrix_RAS.GetPointer(), rasToLps.GetPointer(), bulkMatrix_RAS.GetPointer());
509  bsplineVtk->SetBulkTransformMatrix(bulkMatrix_RAS.GetPointer());
510  }
511  else if (bulkTransformItkTransformName == "IdentityTransform")
512  {
513  // bulk transform is identity, which is equivalent to no bulk transform
514  }
515  else
516  {
517  vtkErrorWithObjectMacro(loggerObject,"Cannot read the 2nd transform in BSplineTransform (expected AffineTransform_double_3_3 or IdentityTransform)" );
518  return false;
519  }
520  }
521 
522  if (inverse)
523  {
524  bsplineVtk->Inverse();
525  }
526 
527  // Success
528  return true;
529 }
530 
531 //----------------------------------------------------------------------------
532 template <typename T> bool vtkITKTransformConverter::SetVTKBSplineFromITKv4Generic(vtkObject* loggerObject,
533  vtkOrientedBSplineTransform* bsplineVtk, typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk)
534 {
535  bool inverse = false;
536  // inverse class is derived from forward class, so it has to be checked first
538  {
539  inverse = true;
540  }
541  else if (SetVTKBSplineParametersFromITKGeneric< itk::BSplineTransform< T, VTKDimension, VTKDimension > >(loggerObject, bsplineVtk, warpTransformItk))
542  {
543  inverse = false;
544  }
545  else
546  {
547  vtkDebugWithObjectMacro(loggerObject, "Not an ITKv4 BSpline transform");
548  return false;
549  }
550  if (inverse)
551  {
552  bsplineVtk->Inverse();
553  }
554  return true;
555 }
556 
557 //----------------------------------------------------------------------------
558 template <typename BSplineTransformType> bool vtkITKTransformConverter::SetITKBSplineParametersFromVTKGeneric(vtkObject* loggerObject,
559  typename itk::Transform< typename BSplineTransformType::ScalarType,VTKDimension,VTKDimension>::Pointer& warpTransformItk, vtkOrientedBSplineTransform* bsplineVtk)
560 {
561  typedef typename BSplineTransformType::ScalarType T;
562  if (bsplineVtk==NULL)
563  {
564  vtkErrorWithObjectMacro(loggerObject, "vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: bsplineVtk is invalid");
565  return false;
566  }
567  vtkImageData* bsplineCoefficients_RAS=bsplineVtk->GetCoefficientData();
568  if (bsplineCoefficients_RAS==NULL)
569  {
570  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file: coefficients are not specified");
571  return false;
572  }
573 
574  typename BSplineTransformType::Pointer bsplineItk = BSplineTransformType::New();
575  warpTransformItk = bsplineItk;
576 
577  // Fixed parameters:
578  // * mesh size X, Y, Z (including the BSPLINE_TRANSFORM_ORDER=3 boundary nodes, 1 before and 2 after the grid)
579  // * mesh origin X, Y, Z (position of the boundary node before the grid)
580  // * mesh spacing X, Y, Z
581  // * mesh direction 3x3 matrix (first row, second row, third row)
582 #if defined(ITK_FIXED_PARAMETERS_ARE_DOUBLE) // After 4.8.1
583  typename BSplineTransformType::FixedParametersType transformFixedParamsItk;
584 #else //Pre 4.8.1
585  typename BSplineTransformType::ParametersType transformFixedParamsItk;
586 #endif
587  const unsigned int numberOfFixedParameters=VTKDimension*(VTKDimension+3);
588  transformFixedParamsItk.SetSize(numberOfFixedParameters);
589 
590  int *gridExtent=bsplineCoefficients_RAS->GetExtent();
591  int gridSize[3]={gridExtent[1]-gridExtent[0]+1, gridExtent[3]-gridExtent[2]+1, gridExtent[5]-gridExtent[4]+1};
592  transformFixedParamsItk[0]=gridSize[0];
593  transformFixedParamsItk[1]=gridSize[1];
594  transformFixedParamsItk[2]=gridSize[2];
595 
596  double* gridOrigin_RAS=bsplineCoefficients_RAS->GetOrigin();
597  double gridOrigin_LPS[3]={-gridOrigin_RAS[0], -gridOrigin_RAS[1], gridOrigin_RAS[2]};
598  transformFixedParamsItk[3]=gridOrigin_LPS[0];
599  transformFixedParamsItk[4]=gridOrigin_LPS[1];
600  transformFixedParamsItk[5]=gridOrigin_LPS[2];
601 
602  double* gridSpacing=bsplineCoefficients_RAS->GetSpacing();
603  transformFixedParamsItk[6]=gridSpacing[0];
604  transformFixedParamsItk[7]=gridSpacing[1];
605  transformFixedParamsItk[8]=gridSpacing[2];
606 
607  vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
608  if (bsplineVtk->GetGridDirectionMatrix()!=NULL)
609  {
610  gridDirectionMatrix_RAS->DeepCopy(bsplineVtk->GetGridDirectionMatrix());
611  }
612  vtkNew<vtkMatrix4x4> lpsToRas;
613  lpsToRas->SetElement(0,0,-1);
614  lpsToRas->SetElement(1,1,-1);
615  vtkNew<vtkMatrix4x4> rasToLps;
616  rasToLps->SetElement(0,0,-1);
617  rasToLps->SetElement(1,1,-1);
618  vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
619  vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), gridDirectionMatrix_RAS.GetPointer(), gridDirectionMatrix_LPS.GetPointer());
620  int fpIndex=9;
621  for (unsigned int row=0; row<VTKDimension; row++)
622  {
623  for (unsigned int column=0; column<VTKDimension; column++)
624  {
625  transformFixedParamsItk[fpIndex++]=gridDirectionMatrix_LPS->GetElement(row,column);
626  }
627  }
628 
629  bsplineItk->SetFixedParameters(transformFixedParamsItk);
630 
631  // BSpline coefficients
632 
633  const unsigned int expectedNumberOfVectors = gridSize[0]*gridSize[1]*gridSize[2];
634  const unsigned int expectedNumberOfParameters = expectedNumberOfVectors*VTKDimension;
635  if( bsplineItk->GetNumberOfParameters() != expectedNumberOfParameters )
636  {
637  vtkErrorWithObjectMacro(loggerObject,"Mismatch in number of BSpline parameters in the ITK transform and the VTK transform");
638  return false;
639  }
640 
641  typename BSplineTransformType::ParametersType transformParamsItk(expectedNumberOfParameters);
642  T* itkBSplineParams_LPS = static_cast<T*>(transformParamsItk.data_block());
643  T* vtkBSplineParams_RAS=static_cast<T*>(bsplineCoefficients_RAS->GetScalarPointer());
644  double coefficientScale = bsplineVtk->GetDisplacementScale();
645  for (unsigned int i=0; i<expectedNumberOfVectors; i++)
646  {
647  *(itkBSplineParams_LPS ) = -coefficientScale * (*(vtkBSplineParams_RAS++));
648  *(itkBSplineParams_LPS+expectedNumberOfVectors ) = -coefficientScale * (*(vtkBSplineParams_RAS++));
649  *(itkBSplineParams_LPS+expectedNumberOfVectors*2) = coefficientScale * (*(vtkBSplineParams_RAS++));
650  itkBSplineParams_LPS++;
651  }
652 
653  bsplineItk->SetParameters(transformParamsItk);
654  return true;
655 }
656 
657 //----------------------------------------------------------------------------
658 template <typename T> bool vtkITKTransformConverter::SetITKv3BSplineFromVTKGeneric(vtkObject* loggerObject,
659  typename itk::Transform<T,VTKDimension,VTKDimension>::Pointer& warpTransformItk,
660  typename itk::Transform<T,VTKDimension,VTKDimension>::Pointer& bulkTransformItk,
661  vtkOrientedBSplineTransform* bsplineVtk, bool alwaysAddBulkTransform)
662 {
663  if (bsplineVtk==NULL)
664  {
665  vtkErrorWithObjectMacro(loggerObject, "vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: bsplineVtk is invalid");
666  return false;
667  }
668  // Update is needed because it refreshes the inverse flag (the flag may be out-of-date if the transform depends on its inverse)
669  bsplineVtk->Update();
670  bool itkTransformSetSuccessfully = false;
671  if (bsplineVtk->GetInverseFlag())
672  {
673  itkTransformSetSuccessfully = SetITKBSplineParametersFromVTKGeneric< itk::InverseBSplineDeformableTransform< T, VTKDimension, VTKDimension > >(loggerObject, warpTransformItk, bsplineVtk);
674  }
675  else
676  {
677  itkTransformSetSuccessfully = SetITKBSplineParametersFromVTKGeneric< itk::BSplineDeformableTransform< T, VTKDimension, VTKDimension > >(loggerObject, warpTransformItk, bsplineVtk);
678  }
679  if (!itkTransformSetSuccessfully)
680  {
681  vtkErrorWithObjectMacro(loggerObject, "vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: cannot determine BSpline parameters");
682  return false;
683  }
684 
685  vtkMatrix4x4* bulkMatrix_RAS=bsplineVtk->GetBulkTransformMatrix();
686  if (bulkMatrix_RAS || alwaysAddBulkTransform)
687  {
688  vtkNew<vtkMatrix4x4> lpsToRas;
689  lpsToRas->SetElement(0,0,-1);
690  lpsToRas->SetElement(1,1,-1);
691  vtkNew<vtkMatrix4x4> rasToLps;
692  rasToLps->SetElement(0,0,-1);
693  rasToLps->SetElement(1,1,-1);
694  vtkNew<vtkMatrix4x4> bulkMatrix_LPS; // bulk_LPS = rasToLps * bulk_RAS * lpsToRas
695  // If bulk transform is available then use it, otherwise just write an identity matrix (we just write it because
696  // alwaysAddBulkTransform was requested, due to backward compatibility reasons)
697  if (bulkMatrix_RAS!=NULL)
698  {
699  vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), bulkMatrix_RAS, bulkMatrix_LPS.GetPointer());
700  vtkMatrix4x4::Multiply4x4(bulkMatrix_LPS.GetPointer(), lpsToRas.GetPointer(), bulkMatrix_LPS.GetPointer());
701  }
702  typedef itk::AffineTransform<T,VTKDimension> BulkTransformType;
703  typename BulkTransformType::Pointer affineItk = BulkTransformType::New();
704  bulkTransformItk = affineItk;
705 
706  typename BulkTransformType::MatrixType affineMatrix;
707  typename BulkTransformType::OffsetType affineOffset;
708  for (unsigned int i=0; i < VTKDimension; i++)
709  {
710  for (unsigned int j=0; j < VTKDimension; j++)
711  {
712  affineMatrix[i][j]=bulkMatrix_LPS->GetElement(i,j);
713  }
714  affineOffset[i]=bulkMatrix_LPS->GetElement(i,VTKDimension);
715  }
716 
717  affineItk->SetMatrix(affineMatrix);
718  affineItk->SetOffset(affineOffset);
719  }
720  else
721  {
722  bulkTransformItk=NULL;
723  }
724 
725  return true;
726 }
727 
728 //----------------------------------------------------------------------------
729 template <typename T> bool vtkITKTransformConverter::SetITKv4BSplineFromVTKGeneric(vtkObject* loggerObject,
730  typename itk::Transform<T,VTKDimension,VTKDimension>::Pointer& warpTransformItk,
731  vtkOrientedBSplineTransform* bsplineVtk)
732 {
733  // Update is needed because it refreshes the inverse flag (the flag may be out-of-date if the transform depends on its inverse)
734  bsplineVtk->Update();
735  bool itkTransformSetSuccessfully = false;
736  if (bsplineVtk->GetInverseFlag())
737  {
738  itkTransformSetSuccessfully = SetITKBSplineParametersFromVTKGeneric< itk::InverseBSplineTransform< T, VTKDimension, VTKDimension > >(loggerObject, warpTransformItk, bsplineVtk);
739  }
740  else
741  {
742  itkTransformSetSuccessfully = SetITKBSplineParametersFromVTKGeneric< itk::BSplineTransform< T, VTKDimension, VTKDimension > >(loggerObject, warpTransformItk, bsplineVtk);
743  }
744  if (!itkTransformSetSuccessfully)
745  {
746  vtkErrorWithObjectMacro(loggerObject, "vtkMRMLTransformStorageNode::SetITKv4BSplineFromVTKGeneric failed: cannot determine BSpline parameters");
747  return false;
748  }
749  return true;
750 }
751 
752 //----------------------------------------------------------------------------
753 bool vtkITKTransformConverter::SetITKv3BSplineFromVTK(vtkObject* loggerObject, itk::Object::Pointer& warpTransformItk,
754  itk::Object::Pointer& bulkTransformItk, vtkOrientedBSplineTransform* bsplineVtk, bool alwaysAddBulkTransform)
755 {
756  if (bsplineVtk==NULL)
757  {
758  vtkErrorWithObjectMacro(loggerObject, "Cannot retrieve BSpline transform from node");
759  return false;
760  }
761 
762  vtkImageData* bsplineCoefficients=bsplineVtk->GetCoefficientData();
763 
764  if (bsplineCoefficients==NULL)
765  {
766  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file: coefficients are not specified");
767  return false;
768  }
769 
770  if (bsplineCoefficients->GetScalarType()==VTK_FLOAT)
771  {
772  typedef itk::Transform<float, VTKDimension, VTKDimension > ITKTransformType;
773  ITKTransformType::Pointer floatWarpTransformItk;
774  ITKTransformType::Pointer floatBulkTransformItk;
775  if (!SetITKv3BSplineFromVTKGeneric<float>(loggerObject, floatWarpTransformItk, floatBulkTransformItk, bsplineVtk, alwaysAddBulkTransform))
776  {
777  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file");
778  return false;
779  }
780  warpTransformItk = floatWarpTransformItk.GetPointer();
781  bulkTransformItk = floatBulkTransformItk.GetPointer();
782  }
783  else if (bsplineCoefficients->GetScalarType()==VTK_DOUBLE)
784  {
785  typedef itk::Transform<double, VTKDimension, VTKDimension > ITKTransformType;
786  ITKTransformType::Pointer doubleWarpTransformItk;
787  ITKTransformType::Pointer doubleBulkTransformItk;
788  if (!SetITKv3BSplineFromVTKGeneric<double>(loggerObject, doubleWarpTransformItk, doubleBulkTransformItk, bsplineVtk, alwaysAddBulkTransform))
789  {
790  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file");
791  return false;
792  }
793  warpTransformItk = doubleWarpTransformItk;
794  bulkTransformItk = doubleBulkTransformItk;
795  }
796  else
797  {
798  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file: only float and double coefficient types are supported");
799  return false;
800  }
801 
802  return true;
803 }
804 
805 //----------------------------------------------------------------------------
806 bool vtkITKTransformConverter::SetITKv4BSplineFromVTK(vtkObject* loggerObject, itk::Object::Pointer& warpTransformItk, vtkOrientedBSplineTransform* bsplineVtk)
807 {
808  if (bsplineVtk==NULL)
809  {
810  vtkErrorWithObjectMacro(loggerObject, "Cannot retrieve BSpline transform from node");
811  return false;
812  }
813 
814  vtkImageData* bsplineCoefficients=bsplineVtk->GetCoefficientData();
815 
816  if (bsplineCoefficients==NULL)
817  {
818  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file: coefficients are not specified");
819  return false;
820  }
821 
822  if (bsplineCoefficients->GetScalarType()==VTK_FLOAT)
823  {
824  typedef itk::Transform<float, VTKDimension, VTKDimension > ITKTransformType;
825  ITKTransformType::Pointer floatWarpTransformItk;
826  if (!SetITKv4BSplineFromVTKGeneric<float>(loggerObject, floatWarpTransformItk, bsplineVtk))
827  {
828  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file");
829  return false;
830  }
831  warpTransformItk = floatWarpTransformItk.GetPointer();
832  }
833  else if (bsplineCoefficients->GetScalarType()==VTK_DOUBLE)
834  {
835  typedef itk::Transform<double, VTKDimension, VTKDimension > ITKTransformType;
836  ITKTransformType::Pointer doubleWarpTransformItk;
837  if (!SetITKv4BSplineFromVTKGeneric<double>(loggerObject, doubleWarpTransformItk, bsplineVtk))
838  {
839  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file");
840  return false;
841  }
842  warpTransformItk = doubleWarpTransformItk;
843  }
844  else
845  {
846  vtkErrorWithObjectMacro(loggerObject, "Cannot write BSpline transform to file: only float and double coefficient types are supported");
847  return false;
848  }
849 
850  return true;
851 }
852 
853 //----------------------------------------------------------------------------
854 template<typename T>
855 bool vtkITKTransformConverter::SetVTKOrientedGridTransformFromITK(vtkObject* loggerObject, vtkOrientedGridTransform* transformVtk_RAS, typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
856 {
857  typedef itk::DisplacementFieldTransform< T, 3 > DisplacementFieldTransformType;
858  typedef itk::InverseDisplacementFieldTransform< T, 3 > InverseDisplacementFieldTransformType;
859 
860  if (!transformItk_LPS)
861  {
862  vtkErrorWithObjectMacro(loggerObject, "Cannot set VTK oriented grid transform from ITK: the input transform is NULL");
863  return false;
864  }
865  if (transformItk_LPS->GetOutputSpaceDimension() != VTKDimension)
866  {
867  vtkErrorWithObjectMacro(loggerObject, "Unsupported number of dimensions in oriented grid transform file (expected = "
868  << VTKDimension << ", actual = " << transformItk_LPS->GetOutputSpaceDimension() << ")");
869  return false;
870  }
871 
872  std::string transformItkClassName = transformItk_LPS->GetNameOfClass();
873 
874  bool inverse = false;
875  typename DisplacementFieldTransformType::DisplacementFieldType* gridImageItk_Lps = NULL;
876  if (transformItkClassName == "InverseDisplacementFieldTransform") // inverse class is derived from forward class, so it has to be checked first
877  {
878  DisplacementFieldTransformType* inverseDisplacementFieldTransform = static_cast<InverseDisplacementFieldTransformType*>( transformItk_LPS.GetPointer() );
879  inverse = true;
880  gridImageItk_Lps = inverseDisplacementFieldTransform->GetDisplacementField();
881  }
882  else if (transformItkClassName == "DisplacementFieldTransform")
883  {
884  DisplacementFieldTransformType* displacementFieldTransform = static_cast<DisplacementFieldTransformType*>( transformItk_LPS.GetPointer() );
885  inverse = false;
886  gridImageItk_Lps = displacementFieldTransform->GetDisplacementField();
887  }
888  else
889  {
890  vtkDebugWithObjectMacro(loggerObject, "Not a grid transform");
891  return false;
892  }
893  if (!SetVTKOrientedGridTransformFromITKImage<T>(loggerObject, transformVtk_RAS, gridImageItk_Lps))
894  {
895  return false;
896  }
897  if (inverse)
898  {
899  transformVtk_RAS->Inverse();
900  }
901  return true;
902 }
903 
904 //----------------------------------------------------------------------------
905 bool vtkITKTransformConverter::SetITKOrientedGridTransformFromVTK(vtkObject* loggerObject, itk::Object::Pointer& transformItk_LPS, vtkOrientedGridTransform* transformVtk_RAS)
906 {
907  GridImageDoubleType::Pointer gridImageItk_Lps;
908  if (!SetITKImageFromVTKOrientedGridTransform(loggerObject, gridImageItk_Lps, transformVtk_RAS))
909  {
910  vtkErrorWithObjectMacro(loggerObject, "vtkITKTransformConverter::SetITKOrientedGridTransformFromVTK failed: input transform is invalid");
911  return false;
912  }
913  // Update is needed because it refreshes the inverse flag (the flag may be out-of-date if the transform depends on its inverse)
914  transformVtk_RAS->Update();
915  if (transformVtk_RAS->GetInverseFlag())
916  {
917  InverseDisplacementFieldTransformDoubleType::Pointer gridTransformItk = InverseDisplacementFieldTransformDoubleType::New();
918  gridTransformItk->SetDisplacementField(gridImageItk_Lps);
919  transformItk_LPS = gridTransformItk;
920  }
921  else
922  {
923  DisplacementFieldTransformDoubleType::Pointer gridTransformItk = DisplacementFieldTransformDoubleType::New();
924  gridTransformItk->SetDisplacementField(gridImageItk_Lps);
925  transformItk_LPS = gridTransformItk;
926  }
927  return true;
928 }
929 
930 //----------------------------------------------------------------------------
931 template<typename T>
932 bool vtkITKTransformConverter::SetVTKOrientedGridTransformFromITKImage(vtkObject* loggerObject, vtkOrientedGridTransform* grid_Ras, typename itk::DisplacementFieldTransform< T, 3 >::DisplacementFieldType::Pointer gridImage_Lps)
933 {
934  typedef itk::DisplacementFieldTransform< T, 3 > DisplacementFieldTransformType;
935  typedef typename DisplacementFieldTransformType::DisplacementFieldType GridImageType;
936 
937  vtkNew<vtkImageData> gridImage_Ras;
938 
939  // Origin
940  gridImage_Ras->SetOrigin( -gridImage_Lps->GetOrigin()[0], -gridImage_Lps->GetOrigin()[1], gridImage_Lps->GetOrigin()[2] );
941 
942  // Spacing
943  gridImage_Ras->SetSpacing( gridImage_Lps->GetSpacing()[0], gridImage_Lps->GetSpacing()[1], gridImage_Lps->GetSpacing()[2] );
944 
945  // Direction
946  vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
947  for (unsigned int row=0; row<VTKDimension; row++)
948  {
949  for (unsigned int column=0; column<VTKDimension; column++)
950  {
951  gridDirectionMatrix_LPS->SetElement(row,column,gridImage_Lps->GetDirection()(row,column));
952  }
953  }
954  vtkNew<vtkMatrix4x4> lpsToRas;
955  lpsToRas->SetElement(0,0,-1);
956  lpsToRas->SetElement(1,1,-1);
957  vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
958  vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
959  grid_Ras->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
960 
961  // Vectors
962  typename GridImageType::SizeType size = gridImage_Lps->GetBufferedRegion().GetSize();
963  gridImage_Ras->SetDimensions( size[0], size[1], size[2] );
964  unsigned int numberOfScalarComponents = GridImageType::PixelType::Dimension;
965  if (numberOfScalarComponents!=VTKDimension)
966  {
967  vtkErrorWithObjectMacro(loggerObject, "Cannot load grid transform: the input displacement field expected to contain "
968  << VTKDimension << " components but it actually contains " << numberOfScalarComponents );
969  return false;
970  }
971  gridImage_Ras->AllocateScalars(VTK_DOUBLE, 3);
972 
973  double* displacementVectors_Ras = reinterpret_cast<double*>(gridImage_Ras->GetScalarPointer());
974  itk::ImageRegionConstIterator<GridImageType> inputIt(gridImage_Lps, gridImage_Lps->GetRequestedRegion());
975  inputIt.GoToBegin();
976  while( !inputIt.IsAtEnd() )
977  {
978  typename GridImageType::PixelType displacementVectorLps=inputIt.Get();
979  *(displacementVectors_Ras++) = -displacementVectorLps[0];
980  *(displacementVectors_Ras++) = -displacementVectorLps[1];
981  *(displacementVectors_Ras++) = displacementVectorLps[2];
982  ++inputIt;
983  }
984 
985  grid_Ras->SetDisplacementGridData( gridImage_Ras.GetPointer() );
986 
987  // Set the interpolation to cubic to have smooth derivatives
988  grid_Ras->SetInterpolationModeToCubic();
989 
990  return true;
991 }
992 
993 //----------------------------------------------------------------------------
994 bool vtkITKTransformConverter::SetITKImageFromVTKOrientedGridTransform(vtkObject* loggerObject, GridImageDoubleType::Pointer &gridImage_Lps, vtkOrientedGridTransform* grid_Ras)
995 {
996  if (grid_Ras==NULL)
997  {
998  vtkErrorWithObjectMacro(loggerObject, "Cannot save grid transform: the input vtkOrientedGridTransform is invalid");
999  return false;
1000  }
1001 
1002  // Update is needed because DisplacementGrid may be out-of-date if the transform depends on its inverse
1003  grid_Ras->Update();
1004 
1005  vtkImageData* gridImage_Ras = grid_Ras->GetDisplacementGrid();
1006  if (gridImage_Ras==NULL)
1007  {
1008  vtkErrorWithObjectMacro(loggerObject, "Cannot save grid transform: the input vtkOrientedGridTransform does not contain a valid displacement grid");
1009  return false;
1010  }
1011  if (gridImage_Ras->GetNumberOfScalarComponents() != static_cast<int>(VTKDimension))
1012  {
1013  vtkErrorWithObjectMacro(loggerObject, "Cannot save grid transform: the input vtkOrientedGridTransform expected to contain "
1014  << VTKDimension << " components but it actually contains " << gridImage_Ras->GetNumberOfScalarComponents() );
1015  return false;
1016  }
1017 
1018  gridImage_Lps = GridImageDoubleType::New();
1019 
1020  // Origin
1021  double* origin_Ras = gridImage_Ras->GetOrigin();
1022  double origin_Lps[3] = { -origin_Ras[0], -origin_Ras[1], origin_Ras[2] };
1023  gridImage_Lps->SetOrigin( origin_Lps );
1024 
1025  // Spacing
1026  double* spacing = gridImage_Ras->GetSpacing();
1027  //GridType::SpacingType spacing( spacing );
1028  gridImage_Lps->SetSpacing( spacing );
1029 
1030  // Direction
1031  vtkNew<vtkMatrix4x4> gridDirectionMatrix_Ras;
1032  if (grid_Ras->GetGridDirectionMatrix()!=NULL)
1033  {
1034  gridDirectionMatrix_Ras->DeepCopy(grid_Ras->GetGridDirectionMatrix());
1035  }
1036  vtkNew<vtkMatrix4x4> rasToLps;
1037  rasToLps->SetElement(0,0,-1);
1038  rasToLps->SetElement(1,1,-1);
1039  vtkNew<vtkMatrix4x4> gridDirectionMatrix_Lps;
1040  vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), gridDirectionMatrix_Ras.GetPointer(), gridDirectionMatrix_Lps.GetPointer());
1041  GridImageDoubleType::DirectionType gridDirectionMatrixItk_Lps;
1042  for (unsigned int row=0; row<VTKDimension; row++)
1043  {
1044  for (unsigned int column=0; column<VTKDimension; column++)
1045  {
1046  gridDirectionMatrixItk_Lps(row,column) = gridDirectionMatrix_Lps->GetElement(row,column);
1047  }
1048  }
1049  gridImage_Lps->SetDirection(gridDirectionMatrixItk_Lps);
1050 
1051  // Vectors
1052  GridImageDoubleType::IndexType start;
1053  start[0] = start[1] = start[2] = 0;
1054  int* Nijk = gridImage_Ras->GetDimensions();
1055  GridImageDoubleType::SizeType size;
1056  size[0] = Nijk[0]; size[1] = Nijk[1]; size[2] = Nijk[2];
1057  GridImageDoubleType::RegionType region;
1058  region.SetSize( size );
1059  region.SetIndex( start );
1060  gridImage_Lps->SetRegions( region );
1061  gridImage_Lps->Allocate();
1062  itk::ImageRegionIterator<GridImageDoubleType> gridImageIt_Lps(gridImage_Lps, region);
1063  gridImageIt_Lps.GoToBegin();
1064  GridImageDoubleType::PixelType displacementVectorLps;
1065  double displacementScale = grid_Ras->GetDisplacementScale();
1066  double displacementShift = grid_Ras->GetDisplacementShift();
1067 
1068  if (gridImage_Ras->GetScalarType()==VTK_DOUBLE)
1069  {
1070  double* displacementVectors_Ras = reinterpret_cast<double*>(gridImage_Ras->GetScalarPointer());
1071  while( !gridImageIt_Lps.IsAtEnd() )
1072  {
1073  displacementVectorLps[0] = -( displacementScale * (*(displacementVectors_Ras++)) + displacementShift );
1074  displacementVectorLps[1] = -( displacementScale * (*(displacementVectors_Ras++)) + displacementShift );
1075  displacementVectorLps[2] = ( displacementScale * (*(displacementVectors_Ras++)) + displacementShift );
1076  gridImageIt_Lps.Set(displacementVectorLps);
1077  ++gridImageIt_Lps;
1078  }
1079  }
1080  else if (gridImage_Ras->GetScalarType()==VTK_FLOAT)
1081  {
1082  float* displacementVectors_Ras = reinterpret_cast<float*>(gridImage_Ras->GetScalarPointer());
1083  while( !gridImageIt_Lps.IsAtEnd() )
1084  {
1085  displacementVectorLps[0] = -( displacementScale * (*(displacementVectors_Ras++)) + displacementShift );
1086  displacementVectorLps[1] = -( displacementScale * (*(displacementVectors_Ras++)) + displacementShift );
1087  displacementVectorLps[2] = ( displacementScale * (*(displacementVectors_Ras++)) + displacementShift );
1088  gridImageIt_Lps.Set(displacementVectorLps);
1089  ++gridImageIt_Lps;
1090  }
1091  }
1092  else
1093  {
1094  vtkErrorWithObjectMacro(loggerObject, "Cannot save grid transform: only float and double scalar types are supported");
1095  return false;
1096  }
1097  return true;
1098 }
1099 
1100 //----------------------------------------------------------------------------
1101 template<typename T>
1102 bool vtkITKTransformConverter::SetVTKThinPlateSplineTransformFromITK(vtkObject* loggerObject, vtkThinPlateSplineTransform* transformVtk_RAS, typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
1103 {
1104  typedef itk::ThinPlateSplineKernelTransform<T,3> ThinPlateSplineTransformType;
1105  typedef itk::InverseThinPlateSplineKernelTransform< T, 3 > InverseThinPlateSplineTransformType;
1106 
1107  if (transformVtk_RAS==NULL)
1108  {
1109  vtkErrorWithObjectMacro(loggerObject, "Cannot set VTK thin-plate spline transform from ITK: the output vtkThinPlateSplineTransform is invalid");
1110  return false;
1111  }
1112 
1113  if (!transformItk_LPS)
1114  {
1115  vtkErrorWithObjectMacro(loggerObject, "Cannot set VTK thin-plate spline transform from ITK: the input transform is NULL");
1116  return false;
1117  }
1118 
1119  if (transformItk_LPS->GetOutputSpaceDimension() != VTKDimension)
1120  {
1121  vtkErrorWithObjectMacro(loggerObject, "Unsupported number of dimensions in thin-plate spline transform file (expected = "
1122  << VTKDimension << ", actual = " << transformItk_LPS->GetOutputSpaceDimension() << ")");
1123  return false;
1124  }
1125 
1126  std::string transformItkClassName = transformItk_LPS->GetNameOfClass();
1127 
1128  bool inverse = false;
1129  typename ThinPlateSplineTransformType::PointSetType::Pointer sourceLandmarksItk_Lps;
1130  typename ThinPlateSplineTransformType::PointSetType::Pointer targetLandmarksItk_Lps;
1131  if (transformItkClassName == "InverseThinPlateSplineKernelTransform") // inverse class is derived from forward class, so it has to be checked first
1132  {
1133  ThinPlateSplineTransformType* inverseTpsTransform = static_cast<InverseThinPlateSplineTransformType*>( transformItk_LPS.GetPointer() );
1134  inverse = true;
1135  sourceLandmarksItk_Lps = inverseTpsTransform->GetSourceLandmarks();
1136  targetLandmarksItk_Lps = inverseTpsTransform->GetTargetLandmarks();
1137  }
1138  else if (transformItkClassName == "ThinPlateSplineKernelTransform")
1139  {
1140  ThinPlateSplineTransformType* tpsTransform = static_cast<ThinPlateSplineTransformType*>( transformItk_LPS.GetPointer() );
1141  inverse = false;
1142  sourceLandmarksItk_Lps = tpsTransform->GetSourceLandmarks();
1143  targetLandmarksItk_Lps = tpsTransform->GetTargetLandmarks();
1144  }
1145  else
1146  {
1147  vtkDebugWithObjectMacro(loggerObject, "Not a ThinPlateSpline transform");
1148  return false;
1149  }
1150 
1151  vtkNew<vtkPoints> sourceLandmarksVtk_Ras;
1152  unsigned int numberOfSourceLandmarks = sourceLandmarksItk_Lps->GetNumberOfPoints();
1153  for(unsigned int i = 0; i < numberOfSourceLandmarks; i++)
1154  {
1155  typename ThinPlateSplineTransformType::InputPointType pointItk_Lps;
1156  bool pointExists = sourceLandmarksItk_Lps->GetPoint(i, &pointItk_Lps);
1157  if (!pointExists)
1158  {
1159  continue;
1160  }
1161  double pointVtk_Ras[3]={0};
1162  pointVtk_Ras[0] = -pointItk_Lps[0];
1163  pointVtk_Ras[1] = -pointItk_Lps[1];
1164  pointVtk_Ras[2] = pointItk_Lps[2];
1165  sourceLandmarksVtk_Ras->InsertNextPoint(pointVtk_Ras);
1166  }
1167 
1168  vtkNew<vtkPoints> targetLandmarksVtk_Ras;
1169  unsigned int numberOfTargetLandmarks = targetLandmarksItk_Lps->GetNumberOfPoints();
1170  for(unsigned int i = 0; i < numberOfTargetLandmarks; i++)
1171  {
1172  typename ThinPlateSplineTransformType::InputPointType pointItk_Lps;
1173  bool pointExists = targetLandmarksItk_Lps->GetPoint(i, &pointItk_Lps);
1174  if (!pointExists)
1175  {
1176  continue;
1177  }
1178  double pointVtk_Ras[3]={0};
1179  pointVtk_Ras[0] = -pointItk_Lps[0];
1180  pointVtk_Ras[1] = -pointItk_Lps[1];
1181  pointVtk_Ras[2] = pointItk_Lps[2];
1182  targetLandmarksVtk_Ras->InsertNextPoint(pointVtk_Ras);
1183  }
1184 
1185  transformVtk_RAS->SetBasisToR(); // need to set this because data is 3D
1186  transformVtk_RAS->SetSourceLandmarks(sourceLandmarksVtk_Ras.GetPointer());
1187  transformVtk_RAS->SetTargetLandmarks(targetLandmarksVtk_Ras.GetPointer());
1188 
1189  if (inverse)
1190  {
1191  transformVtk_RAS->Inverse();
1192  }
1193  return true;
1194 }
1195 
1196 //----------------------------------------------------------------------------
1198  itk::Object::Pointer& transformItk_LPS, vtkThinPlateSplineTransform* transformVtk_RAS, bool initialize /*= true*/)
1199 {
1200  if (transformVtk_RAS==NULL)
1201  {
1202  vtkErrorWithObjectMacro(loggerObject, "Cannot set ITK thin-plate spline transform from VTK: the intput vtkThinPlateSplineTransform is invalid");
1203  return false;
1204  }
1205 
1206  // Update is needed because the Basis value and Inverse flag may be out-of-date if the transform depends on its inverse
1207  transformVtk_RAS->Update();
1208 
1209  if (transformVtk_RAS->GetBasis()!=VTK_RBF_R)
1210  {
1211  vtkErrorWithObjectMacro(loggerObject, "Cannot set ITK thin-plate spline transform from VTK: basis function must be R."
1212  " Call SetBasisToR() method of the vtkThinPlateSplineTransform object before attempting to write it to file.");
1213  return false;
1214  }
1215 
1216  ThinPlateSplineTransformDoubleType::PointSetType::Pointer sourceLandmarksItk_Lps = ThinPlateSplineTransformDoubleType::PointSetType::New();
1217  vtkPoints* sourceLandmarksVtk_Ras=transformVtk_RAS->GetSourceLandmarks();
1218  if (sourceLandmarksVtk_Ras!=NULL)
1219  {
1220  for (int i=0; i<sourceLandmarksVtk_Ras->GetNumberOfPoints(); i++)
1221  {
1222  double posVtk_Ras[3]={0};
1223  sourceLandmarksVtk_Ras->GetPoint(i, posVtk_Ras);
1224  ThinPlateSplineTransformDoubleType::InputPointType posItk_Lps;
1225  posItk_Lps[0] = -posVtk_Ras[0];
1226  posItk_Lps[1] = -posVtk_Ras[1];
1227  posItk_Lps[2] = posVtk_Ras[2];
1228  sourceLandmarksItk_Lps->GetPoints()->InsertElement(i,posItk_Lps);
1229  }
1230  }
1231  ThinPlateSplineTransformDoubleType::PointSetType::Pointer targetLandmarksItk_Lps = ThinPlateSplineTransformDoubleType::PointSetType::New();
1232  vtkPoints* targetLandmarksVtk_Ras=transformVtk_RAS->GetTargetLandmarks();
1233  if (targetLandmarksVtk_Ras!=NULL)
1234  {
1235  for (int i=0; i<targetLandmarksVtk_Ras->GetNumberOfPoints(); i++)
1236  {
1237  double posVtk_Ras[3]={0};
1238  targetLandmarksVtk_Ras->GetPoint(i, posVtk_Ras);
1239  ThinPlateSplineTransformDoubleType::InputPointType posItk_Lps;
1240  posItk_Lps[0] = -posVtk_Ras[0];
1241  posItk_Lps[1] = -posVtk_Ras[1];
1242  posItk_Lps[2] = posVtk_Ras[2];
1243  targetLandmarksItk_Lps->GetPoints()->InsertElement(i,posItk_Lps);
1244  }
1245  }
1246 
1247  if (transformVtk_RAS->GetInverseFlag())
1248  {
1249  InverseThinPlateSplineTransformDoubleType::Pointer tpsTransformItk = InverseThinPlateSplineTransformDoubleType::New();
1250  tpsTransformItk->SetSourceLandmarks(sourceLandmarksItk_Lps);
1251  tpsTransformItk->SetTargetLandmarks(targetLandmarksItk_Lps);
1252  if (initialize)
1253  {
1254  tpsTransformItk->ComputeWMatrix();
1255  }
1256  transformItk_LPS = tpsTransformItk;
1257  }
1258  else
1259  {
1260  ThinPlateSplineTransformDoubleType::Pointer tpsTransformItk = ThinPlateSplineTransformDoubleType::New();
1261  tpsTransformItk->SetSourceLandmarks(sourceLandmarksItk_Lps);
1262  tpsTransformItk->SetTargetLandmarks(targetLandmarksItk_Lps);
1263  if (initialize)
1264  {
1265  tpsTransformItk->ComputeWMatrix();
1266  }
1267  transformItk_LPS = tpsTransformItk;
1268  }
1269  return true;
1270 }
1271 
1272 
1273 //----------------------------------------------------------------------------
1274 template <typename T>
1276  vtkObject* loggerObject,
1277  typename itk::TransformBaseTemplate<T>::Pointer transformItk)
1278 {
1279  bool conversionSuccess = false;
1280 
1281  // Linear
1282  vtkNew<vtkMatrix4x4> transformMatrixVtk;
1283  conversionSuccess = SetVTKLinearTransformFromITK<T>(loggerObject, transformMatrixVtk.GetPointer(), transformItk);
1284  std::cout << "CreateVTKTransformFromITK - SetVTKLinearTransformFromITK conversionSuccess:" << conversionSuccess << std::endl;
1285  if (conversionSuccess)
1286  {
1287  vtkNew<vtkTransform> linearTransformVtk;
1288  linearTransformVtk->SetMatrix(transformMatrixVtk.GetPointer());
1289  linearTransformVtk->Register(NULL);
1290  return linearTransformVtk.GetPointer();
1291  }
1292  // Grid
1293  vtkNew<vtkOrientedGridTransform> gridTransformVtk;
1294  conversionSuccess = SetVTKOrientedGridTransformFromITK<T>(loggerObject, gridTransformVtk.GetPointer(), transformItk);
1295  if (conversionSuccess)
1296  {
1297  gridTransformVtk->Register(NULL);
1298  return gridTransformVtk.GetPointer();
1299  }
1300  // BSpline
1301  vtkNew<vtkOrientedBSplineTransform> bsplineTransformVtk;
1302  conversionSuccess = SetVTKBSplineFromITKv4Generic<T>(loggerObject, bsplineTransformVtk.GetPointer(), transformItk);
1303  if (conversionSuccess)
1304  {
1305  bsplineTransformVtk->Register(NULL);
1306  return bsplineTransformVtk.GetPointer();
1307  }
1308  // ThinPlateSpline
1309  vtkNew<vtkThinPlateSplineTransform> tpsTransformVtk;
1310  conversionSuccess = SetVTKThinPlateSplineTransformFromITK<T>(loggerObject, tpsTransformVtk.GetPointer(), transformItk);
1311  if (conversionSuccess)
1312  {
1313  tpsTransformVtk->Register(NULL);
1314  return tpsTransformVtk.GetPointer();
1315  }
1316 
1317  return 0;
1318 }
1319 
1320 //----------------------------------------------------------------------------
1321 itk::Object::Pointer vtkITKTransformConverter::CreateITKTransformFromVTK(vtkObject* loggerObject,
1322  vtkAbstractTransform* transformVtk, itk::Object::Pointer& secondaryTransformItk, int preferITKv3CompatibleTransforms, bool initialize /*= true*/)
1323 {
1324  typedef itk::CompositeTransform< double > CompositeTransformType;
1325 
1326  if (transformVtk==NULL)
1327  {
1328  vtkErrorWithObjectMacro(loggerObject, "CreateITKTransformFromVTK failed: invalid VTK transform");
1329  return 0;
1330  }
1331  vtkNew<vtkCollection> transformList;
1332  vtkMRMLTransformNode::FlattenGeneralTransform(transformList.GetPointer(), transformVtk);
1333  if (transformList->GetNumberOfItems()==0)
1334  {
1335  // no transformation means identity transform
1336  vtkNew<vtkTransform> identity;
1337  transformList->AddItem(identity.GetPointer());
1338  }
1339 
1340  itk::Object::Pointer primaryTransformItk;
1341  if (transformList->GetNumberOfItems()==1)
1342  {
1343  // Simple, non-composite transform (one item in the input transform)
1344  vtkObject* singleTransformVtk = transformList->GetItemAsObject(0);
1345  // Linear
1346  if (vtkHomogeneousTransform::SafeDownCast(singleTransformVtk))
1347  {
1348  vtkHomogeneousTransform* linearTransformVtk = vtkHomogeneousTransform::SafeDownCast(singleTransformVtk);
1349  vtkMatrix4x4* transformMatrix = linearTransformVtk->GetMatrix();
1350  if (!SetITKLinearTransformFromVTK(loggerObject, primaryTransformItk, transformMatrix))
1351  {
1352  // conversion failed
1353  return 0;
1354  }
1355  return primaryTransformItk;
1356  }
1357  // BSpline
1358  else if (vtkOrientedBSplineTransform::SafeDownCast(singleTransformVtk))
1359  {
1360  vtkOrientedBSplineTransform* bsplineTransformVtk = vtkOrientedBSplineTransform::SafeDownCast(singleTransformVtk);
1361  vtkMatrix4x4* bulkMatrix = bsplineTransformVtk->GetBulkTransformMatrix(); // non-zero for ITKv3 bspline transform only
1362  if (preferITKv3CompatibleTransforms || (bulkMatrix!=NULL && !IsIdentityMatrix(bulkMatrix)))
1363  {
1364  if (!SetITKv3BSplineFromVTK(loggerObject, primaryTransformItk, secondaryTransformItk, bsplineTransformVtk, preferITKv3CompatibleTransforms))
1365  {
1366  // conversion failed
1367  return 0;
1368  }
1369  return primaryTransformItk;
1370  }
1371  else
1372  {
1373  if (!SetITKv4BSplineFromVTK(loggerObject, primaryTransformItk, bsplineTransformVtk))
1374  {
1375  // conversion failed
1376  return 0;
1377  }
1378  return primaryTransformItk;
1379  }
1380  }
1381  // Grid
1382  else if (vtkOrientedGridTransform::SafeDownCast(singleTransformVtk))
1383  {
1384  vtkOrientedGridTransform* gridTransformVtk = vtkOrientedGridTransform::SafeDownCast(singleTransformVtk);
1385  if (!SetITKOrientedGridTransformFromVTK(loggerObject, primaryTransformItk, gridTransformVtk))
1386  {
1387  // conversion failed
1388  return 0;
1389  }
1390  return primaryTransformItk;
1391  }
1392  // ThinPlateSpline
1393  else if (vtkThinPlateSplineTransform::SafeDownCast(singleTransformVtk))
1394  {
1395  vtkThinPlateSplineTransform* tpsTransformVtk = vtkThinPlateSplineTransform::SafeDownCast(singleTransformVtk);
1396  if (!SetITKThinPlateSplineTransformFromVTK(loggerObject, primaryTransformItk, tpsTransformVtk, initialize))
1397  {
1398  // conversion failed
1399  return 0;
1400  }
1401  return primaryTransformItk;
1402  }
1403  else
1404  {
1405  if (singleTransformVtk==NULL)
1406  {
1407  vtkErrorWithObjectMacro(loggerObject, "vtkITKTransformConverter::CreateITKTransformFromVTK failed: invalid input transform");
1408  return 0;
1409  }
1410  vtkErrorWithObjectMacro(loggerObject, "vtkITKTransformConverter::CreateITKTransformFromVTK failed: conversion of transform type "<<singleTransformVtk->GetClassName()<<" is not supported");
1411  return 0;
1412  }
1413  }
1414  else
1415  {
1416  // Composite transform (more than one items in the input transform)
1417  // Create an ITK composite transform from the VTK general transform
1418  CompositeTransformType::Pointer compositeTransformItk = CompositeTransformType::New();
1419  primaryTransformItk = compositeTransformItk;
1420  // We need to iterate through the list in reverse order, as ITK CompositeTransform can only append transform on one side
1421  for (int transformIndex = transformList->GetNumberOfItems()-1; transformIndex>=0; --transformIndex)
1422  {
1423  vtkAbstractTransform* singleTransformVtk = vtkAbstractTransform::SafeDownCast(transformList->GetItemAsObject(transformIndex));
1424  itk::Object::Pointer secondaryTransformItk;
1425  // We use ITKv4 format (PreferITKv3Transform format is set to false), because
1426  // legacy ITKv3 code does not know how to interpret composite transforms,
1427  // and also ITKv3 bspline transform with bulk component cannot be saved in a composite transform
1428  itk::Object::Pointer singleTransformItk = CreateITKTransformFromVTK(loggerObject, singleTransformVtk, secondaryTransformItk, false );
1429  if (secondaryTransformItk.IsNotNull())
1430  {
1431  vtkErrorWithObjectMacro(loggerObject, "vtkITKTransformConverter::CreateITKTransformFromVTK failed: composite transforms cannot contain legacy transforms (that contains secondary transforms). Do not harden transforms on legacy ITK transforms to avoid this error.");
1432  return 0;
1433  }
1434 
1435  if (singleTransformItk.IsNull()
1436  || std::string(singleTransformItk->GetNameOfClass()).find("Transform") == std::string::npos)
1437  {
1438  vtkErrorWithObjectMacro(loggerObject, "vtkITKTransformConverter::CreateITKTransformFromVTK failed: invalid element found while trying to create a composite transform");
1439  return 0;
1440  }
1441  CompositeTransformType::TransformType::Pointer singleTransformItkTypeChecked = static_cast< CompositeTransformType::TransformType* >( singleTransformItk.GetPointer() );
1442  compositeTransformItk->AddTransform(singleTransformItkTypeChecked.GetPointer());
1443  }
1444  return primaryTransformItk;
1445  }
1446  return 0;
1447 }
1448 
1449 #endif // __vtkITKTransformConverter_h
itk::DisplacementFieldTransform< double, 3 > DisplacementFieldTransformDoubleType
static bool SetVTKBSplineFromITKv3Generic(vtkObject *loggerObject, vtkOrientedBSplineTransform *bsplineVtk, typename itk::TransformBaseTemplate< T >::Pointer warpTransformItk, typename itk::TransformBaseTemplate< T >::Pointer bulkTransformItk)
virtual void SetBulkTransformMatrix(vtkMatrix4x4 *)
static bool SetITKv4BSplineFromVTKGeneric(vtkObject *loggerObject, typename itk::Transform< T, VTKDimension, VTKDimension >::Pointer &warpTransformItk, vtkOrientedBSplineTransform *bsplineVtk)
static vtkOrientedBSplineTransform * SafeDownCast(vtkObject *o)
static bool SetITKBSplineParametersFromVTKGeneric(vtkObject *loggerObject, typename itk::Transform< typename BSplineTransformType::ScalarType, VTKDimension, VTKDimension >::Pointer &warpTransformItk, vtkOrientedBSplineTransform *bsplineVtk)
virtual vtkMatrix4x4 * GetBulkTransformMatrix()
itk::ThinPlateSplineKernelTransform< double, 3 > ThinPlateSplineTransformDoubleType
static bool SetITKLinearTransformFromVTK(vtkObject *loggerObject, itk::Object::Pointer &transformItk_LPS, vtkMatrix4x4 *transformVtk_RAS)
vtkOrientedBSplineTransform - arbitrarily oriented cubic b-spline deformation transformation.
static bool SetVTKLinearTransformFromITK(vtkObject *loggerObject, vtkMatrix4x4 *transformVtk_RAS, typename itk::TransformBaseTemplate< T >::Pointer transformItk_LPS)
static vtkOrientedGridTransform * SafeDownCast(vtkObject *o)
static bool SetVTKThinPlateSplineTransformFromITK(vtkObject *loggerObject, vtkThinPlateSplineTransform *transformVtk_RAS, typename itk::TransformBaseTemplate< T >::Pointer transformItk_LPS)
static bool SetITKv3BSplineFromVTKGeneric(vtkObject *loggerObject, typename itk::Transform< T, VTKDimension, VTKDimension >::Pointer &warpTransformItk, typename itk::Transform< T, VTKDimension, VTKDimension >::Pointer &bulkTransformItk, vtkOrientedBSplineTransform *bsplineVtk, bool alwaysAddBulkTransform)
virtual vtkMatrix4x4 * GetGridDirectionMatrix()
static bool SetVTKBSplineFromITKv4Generic(vtkObject *loggerObject, vtkOrientedBSplineTransform *bsplineVtk, typename itk::TransformBaseTemplate< T >::Pointer warpTransformItk)
itk::TransformFileWriter TransformWriterType
static bool SetVTKOrientedGridTransformFromITKImage(vtkObject *loggerObject, vtkOrientedGridTransform *grid_Ras, typename itk::DisplacementFieldTransform< T, 3 >::DisplacementFieldType::Pointer gridImage_Lps)
static bool SetITKv4BSplineFromVTK(vtkObject *loggerObject, itk::Object::Pointer &warpTransformItk, vtkOrientedBSplineTransform *bsplineVtk)
static bool IsIdentityMatrix(vtkMatrix4x4 *matrix)
static bool SetITKv3BSplineFromVTK(vtkObject *loggerObject, itk::Object::Pointer &warpTransformItk, itk::Object::Pointer &bulkTransformItk, vtkOrientedBSplineTransform *bsplineVtk, bool alwaysAddBulkTransform)
static const unsigned int VTKDimension
virtual void SetGridDirectionMatrix(vtkMatrix4x4 *)
static bool SetITKOrientedGridTransformFromVTK(vtkObject *loggerObject, itk::Object::Pointer &transformItk_LPS, vtkOrientedGridTransform *transformVtk_RAS)
virtual vtkMatrix4x4 * GetGridDirectionMatrix()
itk::AffineTransform< TransformRealType, 3 > AffineTransformType
Definition: dtitypes.h:64
static void FlattenGeneralTransform(vtkCollection *outputTransformList, vtkAbstractTransform *inputTransform)
vtkOrientedGridTransform - arbitrarily oriented displacement field deformation transformation.
virtual void SetGridDirectionMatrix(vtkMatrix4x4 *)
static vtkAbstractTransform * CreateVTKTransformFromITK(vtkObject *loggerObject, typename itk::TransformBaseTemplate< T >::Pointer transformItk)
DisplacementFieldTransformDoubleType::DisplacementFieldType GridImageDoubleType
static itk::Object::Pointer CreateITKTransformFromVTK(vtkObject *loggerObject, vtkAbstractTransform *transformVtk, itk::Object::Pointer &secondaryTransformItk, int preferITKv3CompatibleTransforms, bool initialize=true)
static bool SetVTKBSplineParametersFromITKGeneric(vtkObject *loggerObject, vtkOrientedBSplineTransform *bsplineVtk, typename itk::TransformBaseTemplate< typename BSplineTransformType::ScalarType >::Pointer warpTransformItk)
static bool SetVTKOrientedGridTransformFromITK(vtkObject *loggerObject, vtkOrientedGridTransform *transformVtk_RAS, typename itk::TransformBaseTemplate< T >::Pointer transformItk_LPS)
static bool SetITKImageFromVTKOrientedGridTransform(vtkObject *loggerObject, GridImageDoubleType::Pointer &gridImage_Lps, vtkOrientedGridTransform *grid_Ras)
static const int BSPLINE_TRANSFORM_ORDER
static bool SetITKThinPlateSplineTransformFromVTK(vtkObject *loggerObject, itk::Object::Pointer &transformItk_LPS, vtkThinPlateSplineTransform *transformVtk_RAS, bool initialize=true)