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