Slicer  4.8
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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)