68 typename itk::TransformBaseTemplate<T>::Pointer transformItk,
69 double center_LocalRAS[3] =
nullptr);
82 vtkAbstractTransform* transformVtk,
83 itk::Object::Pointer& secondaryTransformItk,
84 int preferITKv3CompatibleTransforms,
85 bool initialize =
true,
86 double center_LocalRAS[3] =
nullptr);
90 vtkOrientedBSplineTransform* bsplineVtk,
91 typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk,
92 typename itk::TransformBaseTemplate<T>::Pointer bulkTransformItk);
96 vtkOrientedGridTransform* grid_Ras,
97 typename itk::DisplacementFieldTransform<T, 3>::DisplacementFieldType::Pointer gridImage_Lps);
104 template <
typename T>
105 static itk::Matrix<T, 3, 3>
Matrix2Dto3D(itk::Matrix<T, 2, 2> m2D);
108 template <
typename T>
110 template <
typename T>
112 vtkMatrix4x4* transformVtk_RAS,
113 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS,
114 double center_LocalRAS[3] =
nullptr);
115 static bool SetITKLinearTransformFromVTK(vtkObject* loggerObject, itk::Object::Pointer& transformItk_LPS, vtkMatrix4x4* transformVtk_RAS,
double center_LocalRAS[3] =
nullptr);
117 template <
typename T>
119 vtkOrientedGridTransform* grid_Ras,
120 typename itk::DisplacementFieldTransform<T, 2>::DisplacementFieldType::Pointer gridImage_Lps);
122 template <
typename T,
unsigned Dimension>
124 vtkOrientedGridTransform* transformVtk_RAS,
125 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS);
129 itk::Object::Pointer& warpTransformItk,
130 itk::Object::Pointer& bulkTransformItk,
131 vtkOrientedBSplineTransform* bsplineVtk,
132 bool alwaysAddBulkTransform);
133 static bool SetITKv4BSplineFromVTK(vtkObject* loggerObject, itk::Object::Pointer& warpTransformItk, vtkOrientedBSplineTransform* bsplineVtk);
135 template <
typename T,
unsigned VDimension>
137 vtkThinPlateSplineTransform* transformVtk_RAS,
138 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS);
140 itk::Object::Pointer& transformItk_LPS,
141 vtkThinPlateSplineTransform* transformVtk_RAS,
142 bool initialize =
true);
146 template <
typename BSplineTransformType>
148 vtkOrientedBSplineTransform* bsplineVtk,
149 typename itk::TransformBaseTemplate<typename BSplineTransformType::ScalarType>::Pointer warpTransformItk);
150 template <
typename T>
151 static bool SetVTKBSplineFromITKv4Generic(vtkObject* loggerObject, vtkOrientedBSplineTransform* bsplineVtk,
typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk);
153 template <
typename BSplineTransformType>
155 typename itk::Transform<typename BSplineTransformType::ScalarType, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
156 vtkOrientedBSplineTransform* bsplineVtk);
157 template <
typename T>
159 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
160 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& bulkTransformItk,
161 vtkOrientedBSplineTransform* bsplineVtk,
162 bool alwaysAddBulkTransform);
163 template <
typename T>
165 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
166 vtkOrientedBSplineTransform* bsplineVtk);
172 itk::TransformFactory<InverseDisplacementFieldTransformFloatType>::RegisterTransform();
173 itk::TransformFactory<InverseDisplacementFieldTransformDoubleType>::RegisterTransform();
175 itk::TransformFactory<InverseBSplineTransformFloatITKv3Type>::RegisterTransform();
176 itk::TransformFactory<InverseBSplineTransformFloatITKv4Type>::RegisterTransform();
177 itk::TransformFactory<InverseBSplineTransformDoubleITKv3Type>::RegisterTransform();
178 itk::TransformFactory<InverseBSplineTransformDoubleITKv4Type>::RegisterTransform();
180 itk::TransformFactory<InverseThinPlateSplineTransformFloatType>::RegisterTransform();
181 itk::TransformFactory<InverseThinPlateSplineTransformDoubleType>::RegisterTransform();
183 itk::TransformFactory<itk::InverseThinPlateSplineKernelTransform<float, 2>>::RegisterTransform();
184 itk::TransformFactory<itk::InverseThinPlateSplineKernelTransform<double, 2>>::RegisterTransform();
186 typedef itk::ThinPlateSplineKernelTransform<float, 3> ThinPlateSplineTransformFloatType;
190 itk::TransformFactory<ThinPlateSplineTransformFloatType>::RegisterTransform();
191 itk::TransformFactory<ThinPlateSplineTransformDoubleType>::RegisterTransform();
193 itk::TransformFactory<itk::ThinPlateSplineKernelTransform<float, 2>>::RegisterTransform();
194 itk::TransformFactory<itk::ThinPlateSplineKernelTransform<double, 2>>::RegisterTransform();
201 itk::Matrix<T, 3, 3> direction3d;
202 direction3d.SetIdentity();
203 for (
unsigned int i = 0; i < 2; i++)
205 for (
unsigned int j = 0; j < 2; j++)
207 direction3d[i][j] = m2D(i, j);
212 itk::Vector<T, VTKDimension> directionCosine{};
213 directionCosine[0] = direction3d[0][0];
214 directionCosine[1] = direction3d[0][1];
215 auto scaleX = directionCosine.GetNorm();
216 directionCosine[0] = direction3d[1][0];
217 directionCosine[1] = direction3d[1][1];
218 auto scaleY = directionCosine.GetNorm();
219 T scaleZ = std::sqrt(scaleX * scaleY);
220 auto det = vnl_determinant(m2D.GetVnlMatrix());
221 direction3d(2, 2) = (det < 0.0) ? -scaleZ : scaleZ;
261 vtkMatrix4x4* transformVtk_RAS,
262 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS,
263 double center_LocalRAS[3] )
266 typedef itk::MatrixOffsetTransformBase<T, D, D> LinearTransformType;
267 typedef itk::TranslationTransform<T, D> TranslateTransformType;
269 vtkSmartPointer<vtkMatrix4x4> transformVtk_LPS = vtkSmartPointer<vtkMatrix4x4>::New();
270 const unsigned itkDim = transformItk_LPS->GetOutputSpaceDimension();
272 bool convertedToVtkMatrix =
false;
274 std::string itkTransformClassName = transformItk_LPS->GetNameOfClass();
293 if (itkTransformClassName.find(
"AffineTransform") != std::string::npos ||
294 itkTransformClassName ==
"MatrixOffsetTransformBase" ||
295 itkTransformClassName ==
"Rigid3DTransform" ||
296 itkTransformClassName ==
"Euler3DTransform" ||
297 itkTransformClassName ==
"CenteredEuler3DTransform" ||
298 itkTransformClassName ==
"QuaternionRigidTransform" ||
299 itkTransformClassName ==
"VersorTransform" ||
300 itkTransformClassName ==
"VersorRigid3DTransform" ||
301 itkTransformClassName ==
"ScaleSkewVersor3DTransform" ||
302 itkTransformClassName ==
"ScaleVersor3DTransform" ||
303 itkTransformClassName ==
"Similarity3DTransform" ||
304 itkTransformClassName ==
"ScaleTransform" ||
305 itkTransformClassName ==
"ScaleLogarithmicTransform")
307 typename LinearTransformType::Pointer dlt;
314 dlt =
static_cast<LinearTransformType*
>(transformItk_LPS.GetPointer());
317 convertedToVtkMatrix =
true;
318 for (
unsigned int i = 0; i < D; i++)
320 for (
unsigned int j = 0; j < D; j++)
322 transformVtk_LPS->SetElement(i, j, dlt->GetMatrix()[i][j]);
324 transformVtk_LPS->SetElement(i, D, dlt->GetOffset()[i]);
329 auto center_LocalLPS = dlt->GetCenter();
330 center_LocalRAS[0] = -center_LocalLPS[0];
331 center_LocalRAS[1] = -center_LocalLPS[1];
332 center_LocalRAS[2] = center_LocalLPS[2];
337 if (itkTransformClassName ==
"IdentityTransform")
340 convertedToVtkMatrix =
true;
345 if (itkTransformClassName ==
"TranslationTransform")
349 using Translate2DTransformType = itk::TranslationTransform<T, 2>;
350 typename Translate2DTransformType::Pointer dtt =
static_cast<Translate2DTransformType*
>(transformItk_LPS.GetPointer());
351 for (
unsigned int i = 0; i < 2; i++)
353 transformVtk_LPS->SetElement(i, D, dtt->GetOffset()[i]);
359 typename TranslateTransformType::Pointer dtt =
static_cast<TranslateTransformType*
>(transformItk_LPS.GetPointer());
360 for (
unsigned int i = 0; i < D; i++)
362 transformVtk_LPS->SetElement(i, D, dtt->GetOffset()[i]);
365 convertedToVtkMatrix =
true;
373 vtkSmartPointer<vtkMatrix4x4> lps2ras = vtkSmartPointer<vtkMatrix4x4>::New();
374 lps2ras->SetElement(0, 0, -1);
375 lps2ras->SetElement(1, 1, -1);
376 vtkMatrix4x4* ras2lps = lps2ras;
378 vtkMatrix4x4::Multiply4x4(lps2ras, transformVtk_LPS, transformVtk_LPS);
379 vtkMatrix4x4::Multiply4x4(transformVtk_LPS, ras2lps, transformVtk_RAS);
383 for (
int i = 0; i < 3; ++i)
388 double offset_RAS = transformVtk_RAS->GetElement(i, 3);
389 center_LocalRAS[i] = center_LocalRAS[i] + offset_RAS;
393 return convertedToVtkMatrix;
398 itk::Object::Pointer& transformItk_LPS,
399 vtkMatrix4x4* transformVtk_RAS,
400 double center_LocalRAS[3] )
404 if (transformVtk_RAS ==
nullptr)
406 vtkErrorWithObjectMacro(loggerObject,
"vtkITKTransformConverter::SetITKLinearTransformFromVTK failed: invalid input transform");
410 vtkSmartPointer<vtkMatrix4x4> lps2ras = vtkSmartPointer<vtkMatrix4x4>::New();
411 lps2ras->SetElement(0, 0, -1);
412 lps2ras->SetElement(1, 1, -1);
413 vtkMatrix4x4* ras2lps = lps2ras;
419 vtkSmartPointer<vtkMatrix4x4> vtkmat = vtkSmartPointer<vtkMatrix4x4>::New();
421 vtkMatrix4x4::Multiply4x4(ras2lps, transformVtk_RAS, vtkmat);
422 vtkMatrix4x4::Multiply4x4(vtkmat, lps2ras, vtkmat);
424 typedef AffineTransformType::MatrixType MatrixType;
425 typedef AffineTransformType::OutputVectorType OffsetType;
428 OffsetType itkoffset;
434 itkmat[i][j] = vtkmat->GetElement(i, j);
439 AffineTransformType::Pointer affine = AffineTransformType::New();
450 double center_LocalLPS[3] = { -center_LocalRAS[0], -center_LocalRAS[1], center_LocalRAS[2] };
455 vtkMath::Subtract(center_LocalLPS, itkoffset, center_LocalLPS);
456 affine->SetCenter(center_LocalLPS);
458 affine->SetMatrix(itkmat);
459 affine->SetOffset(itkoffset);
461 transformItk_LPS = affine;
487 vtkOrientedBSplineTransform* bsplineVtk,
488 typename itk::TransformBaseTemplate<typename BSplineTransformType::ScalarType>::Pointer warpTransformItk)
493 typedef typename BSplineTransformType::ScalarType T;
494 if (bsplineVtk ==
nullptr)
496 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetVTKBSplineFromITKv4 failed: bsplineVtk is invalid");
499 bool isDoublePrecisionInput =
true;
500 if (
sizeof(T) ==
sizeof(
float))
502 isDoublePrecisionInput =
false;
504 else if (
sizeof(T) ==
sizeof(
double))
506 isDoublePrecisionInput =
true;
510 vtkErrorWithObjectMacro(loggerObject,
"Unsupported scalar type in BSpline transform file (only float and double are supported)");
514 typename BSplineTransformType::Pointer bsplineItk = BSplineTransformType::New();
515 std::string warpTransformItkName = warpTransformItk->GetNameOfClass();
516 std::string requestedWarpTransformItkName = bsplineItk->GetNameOfClass();
517 if (warpTransformItkName != requestedWarpTransformItkName)
521 const unsigned itkDim = warpTransformItk->GetOutputSpaceDimension();
522 constexpr unsigned instDim = BSplineTransformType::SpaceDimension;
523 if (itkDim != instDim)
525 vtkErrorWithObjectMacro(loggerObject,
"Actual and instantiated dimensionality differ: actual = " << itkDim <<
", instantiated = " << instDim);
528 bsplineItk =
static_cast<BSplineTransformType*
>(warpTransformItk.GetPointer());
536 const typename BSplineTransformType::CoefficientImageArray coefficientImages = bsplineItk->GetCoefficientImages();
540 typename BSplineTransformType::MeshSizeType meshSize = coefficientImages[0]->GetLargestPossibleRegion().GetSize();
543 typename BSplineTransformType::OriginType origin = coefficientImages[0]->GetOrigin();
546 typename BSplineTransformType::SpacingType spacing = coefficientImages[0]->GetSpacing();
549 typename BSplineTransformType::DirectionType direction = coefficientImages[0]->GetDirection();
551 itk::Matrix<T, 3, 3> direction3d;
552 if constexpr (instDim == 2)
558 direction3d = direction;
561 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
564 for (
unsigned int column = 0; column <
VTKDimension; column++)
566 gridDirectionMatrix_LPS->SetElement(row, column, direction3d[row][column]);
571 bsplineVtk->SetBorderModeToZero();
573 vtkNew<vtkImageData> bsplineCoefficients;
575 if constexpr (instDim == 2)
577 bsplineCoefficients->SetExtent(0, meshSize[0] - 1, 0, meshSize[1] - 1, 0, 0);
578 bsplineCoefficients->SetSpacing(spacing[0], spacing[1], std::sqrt(spacing[0] * spacing[1]));
582 bsplineCoefficients->SetExtent(0, meshSize[0] - 1, 0, meshSize[1] - 1, 0, meshSize[2] - 1);
583 bsplineCoefficients->SetSpacing(spacing[0], spacing[1], spacing[2]);
587 vtkNew<vtkMatrix4x4> lpsToRas;
588 lpsToRas->SetElement(0, 0, -1);
589 lpsToRas->SetElement(1, 1, -1);
591 vtkNew<vtkMatrix4x4> rasToLps;
592 rasToLps->SetElement(0, 0, -1);
593 rasToLps->SetElement(1, 1, -1);
595 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
596 vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
597 bsplineVtk->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
600 double gridOrigin_RAS[3] = { -origin[0], -origin[1], 0 };
601 if constexpr (instDim == 3)
603 gridOrigin_RAS[2] = origin[2];
605 bsplineCoefficients->SetOrigin(gridOrigin_RAS);
607 int bsplineCoefficientsScalarType = VTK_FLOAT;
608 if (isDoublePrecisionInput)
610 bsplineCoefficientsScalarType = VTK_DOUBLE;
613 bsplineCoefficients->AllocateScalars(bsplineCoefficientsScalarType, 3);
615 const unsigned int expectedNumberOfVectors = meshSize.CalculateProductOfElements();
616 const unsigned int expectedNumberOfParameters = expectedNumberOfVectors * instDim;
617 const unsigned int actualNumberOfParameters = bsplineItk->GetNumberOfParameters();
619 if (actualNumberOfParameters != expectedNumberOfParameters)
621 vtkErrorWithObjectMacro(loggerObject,
"Mismatch in number of BSpline parameters in the transform file and the MRML node");
624 const T* itkBSplineParams_LPS =
static_cast<const T*
>(bsplineItk->GetParameters().data_block());
625 T* vtkBSplineParams_RAS =
static_cast<T*
>(bsplineCoefficients->GetScalarPointer());
626 for (
unsigned int i = 0; i < expectedNumberOfVectors; i++)
628 *(vtkBSplineParams_RAS++) = -(*(itkBSplineParams_LPS));
629 *(vtkBSplineParams_RAS++) = -(*(itkBSplineParams_LPS + expectedNumberOfVectors));
630 if constexpr (instDim == 3)
632 *(vtkBSplineParams_RAS++) = (*(itkBSplineParams_LPS + expectedNumberOfVectors * 2));
636 *(vtkBSplineParams_RAS++) = 0;
638 itkBSplineParams_LPS++;
640 bsplineVtk->SetCoefficientData(bsplineCoefficients.GetPointer());
649 vtkOrientedBSplineTransform* bsplineVtk,
650 typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk,
651 typename itk::TransformBaseTemplate<T>::Pointer bulkTransformItk)
653 if (bsplineVtk ==
nullptr)
655 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetVTKBSplineFromITK failed: bsplineVtk is invalid");
659 const unsigned int itkDim = warpTransformItk->GetOutputSpaceDimension();
660 if (itkDim < 2 || itkDim > 3)
662 vtkErrorWithObjectMacro(loggerObject,
"Unsupported number of dimensions in BSpline transform file (expected = 2 or 3, actual = " << itkDim <<
")");
665 bool inverse =
false;
679 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv3 BSpline transform");
696 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv3 BSpline transform");
702 if (bulkTransformItk)
704 std::string bulkTransformItkTransformName = bulkTransformItk->GetNameOfClass();
706 if (bulkTransformItkTransformName ==
"AffineTransform")
708 vtkNew<vtkMatrix4x4> bulkMatrix_RAS;
711 vtkErrorWithObjectMacro(loggerObject,
"Cannot read the bulk transform in BSplineTransform");
714 bsplineVtk->SetBulkTransformMatrix(bulkMatrix_RAS.GetPointer());
716 else if (bulkTransformItkTransformName ==
"IdentityTransform")
722 vtkErrorWithObjectMacro(loggerObject,
"Cannot read the 2nd transform in BSplineTransform (expected AffineTransform_double_3_3 or IdentityTransform)");
729 bsplineVtk->Inverse();
739 vtkOrientedBSplineTransform* bsplineVtk,
740 typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk)
742 bool inverse =
false;
743 const unsigned int itkDim = warpTransformItk->GetOutputSpaceDimension();
758 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv4 BSpline transform");
775 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv4 BSpline transform");
782 bsplineVtk->Inverse();
790 vtkObject* loggerObject,
791 typename itk::Transform<typename BSplineTransformType::ScalarType, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
792 vtkOrientedBSplineTransform* bsplineVtk)
794 typedef typename BSplineTransformType::ScalarType T;
795 if (bsplineVtk ==
nullptr)
797 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: bsplineVtk is invalid");
800 vtkImageData* bsplineCoefficients_RAS = bsplineVtk->GetCoefficientData();
801 if (bsplineCoefficients_RAS ==
nullptr)
803 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: coefficients are not specified");
807 typename BSplineTransformType::Pointer bsplineItk = BSplineTransformType::New();
808 warpTransformItk = bsplineItk;
815 typename BSplineTransformType::FixedParametersType transformFixedParamsItk;
817 transformFixedParamsItk.SetSize(numberOfFixedParameters);
819 int* gridExtent = bsplineCoefficients_RAS->GetExtent();
820 int gridSize[3] = { gridExtent[1] - gridExtent[0] + 1, gridExtent[3] - gridExtent[2] + 1, gridExtent[5] - gridExtent[4] + 1 };
821 transformFixedParamsItk[0] = gridSize[0];
822 transformFixedParamsItk[1] = gridSize[1];
823 transformFixedParamsItk[2] = gridSize[2];
825 double* gridOrigin_RAS = bsplineCoefficients_RAS->GetOrigin();
826 double gridOrigin_LPS[3] = { -gridOrigin_RAS[0], -gridOrigin_RAS[1], gridOrigin_RAS[2] };
827 transformFixedParamsItk[3] = gridOrigin_LPS[0];
828 transformFixedParamsItk[4] = gridOrigin_LPS[1];
829 transformFixedParamsItk[5] = gridOrigin_LPS[2];
831 double* gridSpacing = bsplineCoefficients_RAS->GetSpacing();
832 transformFixedParamsItk[6] = gridSpacing[0];
833 transformFixedParamsItk[7] = gridSpacing[1];
834 transformFixedParamsItk[8] = gridSpacing[2];
836 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
837 if (bsplineVtk->GetGridDirectionMatrix() !=
nullptr)
839 gridDirectionMatrix_RAS->DeepCopy(bsplineVtk->GetGridDirectionMatrix());
841 vtkNew<vtkMatrix4x4> lpsToRas;
842 lpsToRas->SetElement(0, 0, -1);
843 lpsToRas->SetElement(1, 1, -1);
844 vtkNew<vtkMatrix4x4> rasToLps;
845 rasToLps->SetElement(0, 0, -1);
846 rasToLps->SetElement(1, 1, -1);
847 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
848 vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), gridDirectionMatrix_RAS.GetPointer(), gridDirectionMatrix_LPS.GetPointer());
852 for (
unsigned int column = 0; column <
VTKDimension; column++)
854 transformFixedParamsItk[fpIndex++] = gridDirectionMatrix_LPS->GetElement(row, column);
858 bsplineItk->SetFixedParameters(transformFixedParamsItk);
862 const unsigned int expectedNumberOfVectors = gridSize[0] * gridSize[1] * gridSize[2];
863 const unsigned int expectedNumberOfParameters = expectedNumberOfVectors *
VTKDimension;
864 if (bsplineItk->GetNumberOfParameters() != expectedNumberOfParameters)
866 vtkErrorWithObjectMacro(loggerObject,
"Mismatch in number of BSpline parameters in the ITK transform and the VTK transform");
870 typename BSplineTransformType::ParametersType transformParamsItk(expectedNumberOfParameters);
871 T* itkBSplineParams_LPS =
static_cast<T*
>(transformParamsItk.data_block());
872 T* vtkBSplineParams_RAS =
static_cast<T*
>(bsplineCoefficients_RAS->GetScalarPointer());
873 double coefficientScale = bsplineVtk->GetDisplacementScale();
874 for (
unsigned int i = 0; i < expectedNumberOfVectors; i++)
876 *(itkBSplineParams_LPS) = -coefficientScale * (*(vtkBSplineParams_RAS++));
877 *(itkBSplineParams_LPS + expectedNumberOfVectors) = -coefficientScale * (*(vtkBSplineParams_RAS++));
878 *(itkBSplineParams_LPS + expectedNumberOfVectors * 2) = coefficientScale * (*(vtkBSplineParams_RAS++));
879 itkBSplineParams_LPS++;
882 bsplineItk->SetParameters(transformParamsItk);
889 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
890 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& bulkTransformItk,
891 vtkOrientedBSplineTransform* bsplineVtk,
892 bool alwaysAddBulkTransform)
894 if (bsplineVtk ==
nullptr)
896 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: bsplineVtk is invalid");
900 bsplineVtk->Update();
901 bool itkTransformSetSuccessfully =
false;
902 if (bsplineVtk->GetInverseFlag())
904 itkTransformSetSuccessfully =
911 if (!itkTransformSetSuccessfully)
913 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: cannot determine BSpline parameters");
917 vtkMatrix4x4* bulkMatrix_RAS = bsplineVtk->GetBulkTransformMatrix();
918 if (bulkMatrix_RAS || alwaysAddBulkTransform)
920 vtkNew<vtkMatrix4x4> lpsToRas;
921 lpsToRas->SetElement(0, 0, -1);
922 lpsToRas->SetElement(1, 1, -1);
923 vtkNew<vtkMatrix4x4> rasToLps;
924 rasToLps->SetElement(0, 0, -1);
925 rasToLps->SetElement(1, 1, -1);
926 vtkNew<vtkMatrix4x4> bulkMatrix_LPS;
929 if (bulkMatrix_RAS !=
nullptr)
931 vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), bulkMatrix_RAS, bulkMatrix_LPS.GetPointer());
932 vtkMatrix4x4::Multiply4x4(bulkMatrix_LPS.GetPointer(), lpsToRas.GetPointer(), bulkMatrix_LPS.GetPointer());
934 typedef itk::AffineTransform<T, VTKDimension> BulkTransformType;
935 typename BulkTransformType::Pointer affineItk = BulkTransformType::New();
936 bulkTransformItk = affineItk;
938 typename BulkTransformType::MatrixType affineMatrix;
939 typename BulkTransformType::OffsetType affineOffset;
944 affineMatrix[i][j] = bulkMatrix_LPS->GetElement(i, j);
946 affineOffset[i] = bulkMatrix_LPS->GetElement(i,
VTKDimension);
949 affineItk->SetMatrix(affineMatrix);
950 affineItk->SetOffset(affineOffset);
954 bulkTransformItk =
nullptr;
987 itk::Object::Pointer& warpTransformItk,
988 itk::Object::Pointer& bulkTransformItk,
989 vtkOrientedBSplineTransform* bsplineVtk,
990 bool alwaysAddBulkTransform)
992 if (bsplineVtk ==
nullptr)
994 vtkErrorWithObjectMacro(loggerObject,
"Cannot retrieve BSpline transform from node");
998 vtkImageData* bsplineCoefficients = bsplineVtk->GetCoefficientData();
1000 if (bsplineCoefficients ==
nullptr)
1002 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: coefficients are not specified");
1006 if (bsplineCoefficients->GetScalarType() == VTK_FLOAT)
1008 typedef itk::Transform<float, VTKDimension, VTKDimension> ITKTransformType;
1009 ITKTransformType::Pointer floatWarpTransformItk;
1010 ITKTransformType::Pointer floatBulkTransformItk;
1013 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1016 warpTransformItk = floatWarpTransformItk.GetPointer();
1017 bulkTransformItk = floatBulkTransformItk.GetPointer();
1019 else if (bsplineCoefficients->GetScalarType() == VTK_DOUBLE)
1021 typedef itk::Transform<double, VTKDimension, VTKDimension> ITKTransformType;
1022 ITKTransformType::Pointer doubleWarpTransformItk;
1023 ITKTransformType::Pointer doubleBulkTransformItk;
1026 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1029 warpTransformItk = doubleWarpTransformItk;
1030 bulkTransformItk = doubleBulkTransformItk;
1034 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: only float and double coefficient types are supported");
1044 if (bsplineVtk ==
nullptr)
1046 vtkErrorWithObjectMacro(loggerObject,
"Cannot retrieve BSpline transform from node");
1050 vtkImageData* bsplineCoefficients = bsplineVtk->GetCoefficientData();
1052 if (bsplineCoefficients ==
nullptr)
1054 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: coefficients are not specified");
1058 if (bsplineCoefficients->GetScalarType() == VTK_FLOAT)
1060 typedef itk::Transform<float, VTKDimension, VTKDimension> ITKTransformType;
1061 ITKTransformType::Pointer floatWarpTransformItk;
1064 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1067 warpTransformItk = floatWarpTransformItk.GetPointer();
1069 else if (bsplineCoefficients->GetScalarType() == VTK_DOUBLE)
1071 typedef itk::Transform<double, VTKDimension, VTKDimension> ITKTransformType;
1072 ITKTransformType::Pointer doubleWarpTransformItk;
1075 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1078 warpTransformItk = doubleWarpTransformItk;
1082 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: only float and double coefficient types are supported");
1092 vtkOrientedGridTransform* transformVtk_RAS,
1093 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
1095 typedef itk::DisplacementFieldTransform<T, Dimension> DisplacementFieldTransformType;
1098 std::string transformItkClassName = transformItk_LPS->GetNameOfClass();
1100 bool inverse =
false;
1101 typename DisplacementFieldTransformType::DisplacementFieldType* gridImageItk_Lps =
nullptr;
1102 if (transformItkClassName ==
"InverseDisplacementFieldTransform")
1104 DisplacementFieldTransformType* inverseDisplacementFieldTransform =
static_cast<InverseDisplacementFieldTransformType*
>(transformItk_LPS.GetPointer());
1106 gridImageItk_Lps = inverseDisplacementFieldTransform->GetDisplacementField();
1108 else if (transformItkClassName ==
"DisplacementFieldTransform")
1110 DisplacementFieldTransformType* displacementFieldTransform =
static_cast<DisplacementFieldTransformType*
>(transformItk_LPS.GetPointer());
1112 gridImageItk_Lps = displacementFieldTransform->GetDisplacementField();
1116 vtkDebugWithObjectMacro(loggerObject,
"Not a grid transform");
1135 transformVtk_RAS->Inverse();
1143 GridImageDoubleType::Pointer gridImageItk_Lps;
1146 vtkErrorWithObjectMacro(loggerObject,
"vtkITKTransformConverter::SetITKOrientedGridTransformFromVTK failed: input transform is invalid");
1150 transformVtk_RAS->Update();
1151 if (transformVtk_RAS->GetInverseFlag())
1154 gridTransformItk->SetDisplacementField(gridImageItk_Lps);
1155 transformItk_LPS = gridTransformItk;
1159 DisplacementFieldTransformDoubleType::Pointer gridTransformItk = DisplacementFieldTransformDoubleType::New();
1160 gridTransformItk->SetDisplacementField(gridImageItk_Lps);
1161 transformItk_LPS = gridTransformItk;
1169 vtkOrientedGridTransform* grid_Ras,
1170 typename itk::DisplacementFieldTransform<T, 3>::DisplacementFieldType::Pointer gridImage_Lps)
1172 typedef itk::DisplacementFieldTransform<T, 3> DisplacementFieldTransformType;
1173 typedef typename DisplacementFieldTransformType::DisplacementFieldType GridImageType;
1175 vtkNew<vtkImageData> gridImage_Ras;
1178 gridImage_Ras->SetOrigin(-gridImage_Lps->GetOrigin()[0], -gridImage_Lps->GetOrigin()[1], gridImage_Lps->GetOrigin()[2]);
1181 gridImage_Ras->SetSpacing(gridImage_Lps->GetSpacing()[0], gridImage_Lps->GetSpacing()[1], gridImage_Lps->GetSpacing()[2]);
1184 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
1187 for (
unsigned int column = 0; column <
VTKDimension; column++)
1189 gridDirectionMatrix_LPS->SetElement(row, column, gridImage_Lps->GetDirection()(row, column));
1192 vtkNew<vtkMatrix4x4> lpsToRas;
1193 lpsToRas->SetElement(0, 0, -1);
1194 lpsToRas->SetElement(1, 1, -1);
1195 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
1196 vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
1197 grid_Ras->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
1200 typename GridImageType::SizeType size = gridImage_Lps->GetBufferedRegion().GetSize();
1201 gridImage_Ras->SetDimensions(size[0], size[1], size[2]);
1202 unsigned int numberOfScalarComponents = GridImageType::PixelType::Dimension;
1205 vtkErrorWithObjectMacro(loggerObject,
1206 "Cannot load grid transform: the input displacement field expected to contain " <<
VTKDimension <<
" components but it actually contains "
1207 << numberOfScalarComponents);
1210 gridImage_Ras->AllocateScalars(VTK_DOUBLE, 3);
1212 double* displacementVectors_Ras =
reinterpret_cast<double*
>(gridImage_Ras->GetScalarPointer());
1213 itk::ImageRegionConstIterator<GridImageType> inputIt(gridImage_Lps, gridImage_Lps->GetRequestedRegion());
1214 while (!inputIt.IsAtEnd())
1216 typename GridImageType::PixelType displacementVectorLps = inputIt.Get();
1217 *(displacementVectors_Ras++) = -displacementVectorLps[0];
1218 *(displacementVectors_Ras++) = -displacementVectorLps[1];
1219 *(displacementVectors_Ras++) = displacementVectorLps[2];
1223 grid_Ras->SetDisplacementGridData(gridImage_Ras.GetPointer());
1226 grid_Ras->SetInterpolationModeToCubic();
1234 vtkOrientedGridTransform* grid_Ras,
1235 typename itk::DisplacementFieldTransform<T, 2>::DisplacementFieldType::Pointer gridImage_Lps)
1237 typedef itk::DisplacementFieldTransform<T, 2> DisplacementFieldTransformType;
1238 typedef typename DisplacementFieldTransformType::DisplacementFieldType GridImageType;
1240 vtkNew<vtkImageData> gridImage_Ras;
1243 const auto& itkOrigin = gridImage_Lps->GetOrigin();
1244 double originRasX = -itkOrigin[0];
1245 double originRasY = -itkOrigin[1];
1246 double originRasZ = 0.0;
1247 gridImage_Ras->SetOrigin(originRasX, originRasY, originRasZ);
1250 const auto& itkSpacing = gridImage_Lps->GetSpacing();
1251 gridImage_Ras->SetSpacing(itkSpacing[0], itkSpacing[1], std::sqrt(itkSpacing[0] * itkSpacing[1]));
1255 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
1256 for (
unsigned int row = 0; row < 3; ++row)
1258 for (
unsigned int col = 0; col < 3; ++col)
1260 gridDirectionMatrix_LPS->SetElement(row, col, direction3d(row, col));
1265 vtkNew<vtkMatrix4x4> lpsToRas;
1266 lpsToRas->SetElement(0, 0, -1);
1267 lpsToRas->SetElement(1, 1, -1);
1268 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
1269 vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
1270 grid_Ras->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
1273 typename GridImageType::SizeType size = gridImage_Lps->GetBufferedRegion().GetSize();
1274 int dimX =
static_cast<int>(size[0]);
1275 int dimY =
static_cast<int>(size[1]);
1276 gridImage_Ras->SetDimensions(dimX, dimY, 1);
1278 unsigned int numberOfScalarComponents = GridImageType::PixelType::Dimension;
1279 if (numberOfScalarComponents != 2)
1281 vtkErrorWithObjectMacro(loggerObject,
1282 "Cannot load 2D grid transform: the input displacement field expected to contain 2 components but it actually contains " << numberOfScalarComponents);
1286 if constexpr (std::is_same_v<T, float>)
1288 gridImage_Ras->AllocateScalars(VTK_FLOAT, 3);
1290 else if constexpr (std::is_same_v<T, double>)
1292 gridImage_Ras->AllocateScalars(VTK_DOUBLE, 3);
1296 vtkErrorWithObjectMacro(loggerObject,
"Cannot load 2D grid transform: unsupported pixel type. Only float and double are supported.");
1301 T* displacementVectors_Ras =
reinterpret_cast<T*
>(gridImage_Ras->GetScalarPointer());
1302 itk::ImageRegionConstIterator<GridImageType> inputIt(gridImage_Lps, gridImage_Lps->GetRequestedRegion());
1303 while (!inputIt.IsAtEnd())
1305 typename GridImageType::PixelType displacementVectorLps = inputIt.Get();
1307 *(displacementVectors_Ras++) = -
static_cast<T
>(displacementVectorLps[0]);
1308 *(displacementVectors_Ras++) = -
static_cast<T
>(displacementVectorLps[1]);
1309 *(displacementVectors_Ras++) = 0.0;
1313 grid_Ras->SetDisplacementGridData(gridImage_Ras.GetPointer());
1316 grid_Ras->SetInterpolationModeToCubic();
1324 if (grid_Ras ==
nullptr)
1326 vtkErrorWithObjectMacro(loggerObject,
"Cannot save grid transform: the input vtkOrientedGridTransform is invalid");
1333 vtkImageData* gridImage_Ras = grid_Ras->GetDisplacementGrid();
1334 if (gridImage_Ras ==
nullptr)
1336 vtkErrorWithObjectMacro(loggerObject,
"Cannot save grid transform: the input vtkOrientedGridTransform does not contain a valid displacement grid");
1339 if (gridImage_Ras->GetNumberOfScalarComponents() !=
static_cast<int>(
VTKDimension))
1341 vtkErrorWithObjectMacro(loggerObject,
1342 "Cannot save grid transform: the input vtkOrientedGridTransform expected to contain " <<
VTKDimension <<
" components but it actually contains "
1343 << gridImage_Ras->GetNumberOfScalarComponents());
1347 gridImage_Lps = GridImageDoubleType::New();
1350 double* origin_Ras = gridImage_Ras->GetOrigin();
1351 double origin_Lps[3] = { -origin_Ras[0], -origin_Ras[1], origin_Ras[2] };
1352 gridImage_Lps->SetOrigin(origin_Lps);
1355 double* spacing = gridImage_Ras->GetSpacing();
1357 gridImage_Lps->SetSpacing(spacing);
1360 vtkNew<vtkMatrix4x4> gridDirectionMatrix_Ras;
1361 if (grid_Ras->GetGridDirectionMatrix() !=
nullptr)
1363 gridDirectionMatrix_Ras->DeepCopy(grid_Ras->GetGridDirectionMatrix());
1365 vtkNew<vtkMatrix4x4> rasToLps;
1366 rasToLps->SetElement(0, 0, -1);
1367 rasToLps->SetElement(1, 1, -1);
1368 vtkNew<vtkMatrix4x4> gridDirectionMatrix_Lps;
1369 vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), gridDirectionMatrix_Ras.GetPointer(), gridDirectionMatrix_Lps.GetPointer());
1370 GridImageDoubleType::DirectionType gridDirectionMatrixItk_Lps;
1373 for (
unsigned int column = 0; column <
VTKDimension; column++)
1375 gridDirectionMatrixItk_Lps(row, column) = gridDirectionMatrix_Lps->GetElement(row, column);
1378 gridImage_Lps->SetDirection(gridDirectionMatrixItk_Lps);
1381 GridImageDoubleType::IndexType start;
1382 start[0] = start[1] = start[2] = 0;
1383 int* Nijk = gridImage_Ras->GetDimensions();
1384 GridImageDoubleType::SizeType size;
1388 GridImageDoubleType::RegionType region;
1389 region.SetSize(size);
1390 region.SetIndex(start);
1391 gridImage_Lps->SetRegions(region);
1392 gridImage_Lps->Allocate();
1393 itk::ImageRegionIterator<GridImageDoubleType> gridImageIt_Lps(gridImage_Lps, region);
1394 gridImageIt_Lps.GoToBegin();
1395 GridImageDoubleType::PixelType displacementVectorLps;
1396 double displacementScale = grid_Ras->GetDisplacementScale();
1397 double displacementShift = grid_Ras->GetDisplacementShift();
1399 if (gridImage_Ras->GetScalarType() == VTK_DOUBLE)
1401 double* displacementVectors_Ras =
reinterpret_cast<double*
>(gridImage_Ras->GetScalarPointer());
1402 while (!gridImageIt_Lps.IsAtEnd())
1404 displacementVectorLps[0] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1405 displacementVectorLps[1] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1406 displacementVectorLps[2] = (displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1407 gridImageIt_Lps.Set(displacementVectorLps);
1411 else if (gridImage_Ras->GetScalarType() == VTK_FLOAT)
1413 float* displacementVectors_Ras =
reinterpret_cast<float*
>(gridImage_Ras->GetScalarPointer());
1414 while (!gridImageIt_Lps.IsAtEnd())
1416 displacementVectorLps[0] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1417 displacementVectorLps[1] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1418 displacementVectorLps[2] = (displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1419 gridImageIt_Lps.Set(displacementVectorLps);
1425 vtkErrorWithObjectMacro(loggerObject,
"Cannot save grid transform: only float and double scalar types are supported");
1434 vtkThinPlateSplineTransform* transformVtk_RAS,
1435 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
1437 typedef itk::ThinPlateSplineKernelTransform<T, VDimension> ThinPlateSplineTransformType;
1440 std::string transformItkClassName = transformItk_LPS->GetNameOfClass();
1442 bool inverse =
false;
1443 typename ThinPlateSplineTransformType::PointSetType::Pointer sourceLandmarksItk_Lps;
1444 typename ThinPlateSplineTransformType::PointSetType::Pointer targetLandmarksItk_Lps;
1445 if (transformItkClassName ==
"InverseThinPlateSplineKernelTransform")
1447 ThinPlateSplineTransformType* inverseTpsTransform =
static_cast<InverseThinPlateSplineTransformType*
>(transformItk_LPS.GetPointer());
1449 sourceLandmarksItk_Lps = inverseTpsTransform->GetSourceLandmarks();
1450 targetLandmarksItk_Lps = inverseTpsTransform->GetTargetLandmarks();
1452 else if (transformItkClassName ==
"ThinPlateSplineKernelTransform")
1454 ThinPlateSplineTransformType* tpsTransform =
static_cast<ThinPlateSplineTransformType*
>(transformItk_LPS.GetPointer());
1456 sourceLandmarksItk_Lps = tpsTransform->GetSourceLandmarks();
1457 targetLandmarksItk_Lps = tpsTransform->GetTargetLandmarks();
1461 vtkDebugWithObjectMacro(loggerObject,
"Not a ThinPlateSpline transform");
1465 vtkNew<vtkPoints> sourceLandmarksVtk_Ras;
1466 unsigned int numberOfSourceLandmarks = sourceLandmarksItk_Lps->GetNumberOfPoints();
1467 vtkNew<vtkPoints> targetLandmarksVtk_Ras;
1468 unsigned int numberOfTargetLandmarks = targetLandmarksItk_Lps->GetNumberOfPoints();
1469 if constexpr (std::is_same_v<T, float>)
1471 sourceLandmarksVtk_Ras->SetDataTypeToFloat();
1472 sourceLandmarksVtk_Ras->Allocate(numberOfSourceLandmarks);
1474 targetLandmarksVtk_Ras->SetDataTypeToFloat();
1475 targetLandmarksVtk_Ras->Allocate(numberOfTargetLandmarks);
1477 else if constexpr (std::is_same_v<T, double>)
1479 sourceLandmarksVtk_Ras->SetDataTypeToDouble();
1480 sourceLandmarksVtk_Ras->Allocate(numberOfSourceLandmarks);
1482 targetLandmarksVtk_Ras->SetDataTypeToDouble();
1483 targetLandmarksVtk_Ras->Allocate(numberOfTargetLandmarks);
1487 vtkErrorWithObjectMacro(loggerObject,
"Cannot load 2D TPS transform: unsupported pixel type. Only float and double are supported.");
1491 for (
unsigned int i = 0; i < numberOfSourceLandmarks; i++)
1493 typename ThinPlateSplineTransformType::InputPointType pointItk_Lps;
1494 bool pointExists = sourceLandmarksItk_Lps->GetPoint(i, &pointItk_Lps);
1499 T pointVtk_Ras[3] = { 0 };
1500 pointVtk_Ras[0] = -pointItk_Lps[0];
1501 pointVtk_Ras[1] = -pointItk_Lps[1];
1502 if constexpr (VDimension == 2)
1504 pointVtk_Ras[2] = 0.0;
1508 pointVtk_Ras[2] = pointItk_Lps[2];
1510 sourceLandmarksVtk_Ras->InsertNextPoint(pointVtk_Ras);
1513 for (
unsigned int i = 0; i < numberOfTargetLandmarks; i++)
1515 typename ThinPlateSplineTransformType::InputPointType pointItk_Lps;
1516 bool pointExists = targetLandmarksItk_Lps->GetPoint(i, &pointItk_Lps);
1521 T pointVtk_Ras[3] = { 0 };
1522 pointVtk_Ras[0] = -pointItk_Lps[0];
1523 pointVtk_Ras[1] = -pointItk_Lps[1];
1524 if constexpr (VDimension == 2)
1526 pointVtk_Ras[2] = 0.0;
1530 pointVtk_Ras[2] = pointItk_Lps[2];
1532 targetLandmarksVtk_Ras->InsertNextPoint(pointVtk_Ras);
1535 transformVtk_RAS->SetBasisToR();
1536 transformVtk_RAS->SetSourceLandmarks(sourceLandmarksVtk_Ras.GetPointer());
1537 transformVtk_RAS->SetTargetLandmarks(targetLandmarksVtk_Ras.GetPointer());
1541 transformVtk_RAS->Inverse();
1548 itk::Object::Pointer& transformItk_LPS,
1549 vtkThinPlateSplineTransform* transformVtk_RAS,
1552 if (transformVtk_RAS ==
nullptr)
1554 vtkErrorWithObjectMacro(loggerObject,
"Cannot set ITK thin-plate spline transform from VTK: the input vtkThinPlateSplineTransform is invalid");
1559 transformVtk_RAS->Update();
1561 if (transformVtk_RAS->GetBasis() != VTK_RBF_R)
1563 vtkErrorWithObjectMacro(loggerObject,
1564 "Cannot set ITK thin-plate spline transform from VTK: basis function must be R."
1565 " Call SetBasisToR() method of the vtkThinPlateSplineTransform object before attempting to write it to file.");
1569 ThinPlateSplineTransformDoubleType::PointSetType::Pointer sourceLandmarksItk_Lps = ThinPlateSplineTransformDoubleType::PointSetType::New();
1570 vtkPoints* sourceLandmarksVtk_Ras = transformVtk_RAS->GetSourceLandmarks();
1571 if (sourceLandmarksVtk_Ras !=
nullptr)
1573 for (
int i = 0; i < sourceLandmarksVtk_Ras->GetNumberOfPoints(); i++)
1575 double posVtk_Ras[3] = { 0 };
1576 sourceLandmarksVtk_Ras->GetPoint(i, posVtk_Ras);
1577 ThinPlateSplineTransformDoubleType::InputPointType posItk_Lps;
1578 posItk_Lps[0] = -posVtk_Ras[0];
1579 posItk_Lps[1] = -posVtk_Ras[1];
1580 posItk_Lps[2] = posVtk_Ras[2];
1581 sourceLandmarksItk_Lps->GetPoints()->InsertElement(i, posItk_Lps);
1584 ThinPlateSplineTransformDoubleType::PointSetType::Pointer targetLandmarksItk_Lps = ThinPlateSplineTransformDoubleType::PointSetType::New();
1585 vtkPoints* targetLandmarksVtk_Ras = transformVtk_RAS->GetTargetLandmarks();
1586 if (targetLandmarksVtk_Ras !=
nullptr)
1588 for (
int i = 0; i < targetLandmarksVtk_Ras->GetNumberOfPoints(); i++)
1590 double posVtk_Ras[3] = { 0 };
1591 targetLandmarksVtk_Ras->GetPoint(i, posVtk_Ras);
1592 ThinPlateSplineTransformDoubleType::InputPointType posItk_Lps;
1593 posItk_Lps[0] = -posVtk_Ras[0];
1594 posItk_Lps[1] = -posVtk_Ras[1];
1595 posItk_Lps[2] = posVtk_Ras[2];
1596 targetLandmarksItk_Lps->GetPoints()->InsertElement(i, posItk_Lps);
1600 if (transformVtk_RAS->GetInverseFlag())
1603 tpsTransformItk->SetSourceLandmarks(sourceLandmarksItk_Lps);
1604 tpsTransformItk->SetTargetLandmarks(targetLandmarksItk_Lps);
1607 tpsTransformItk->ComputeWMatrix();
1609 transformItk_LPS = tpsTransformItk;
1613 ThinPlateSplineTransformDoubleType::Pointer tpsTransformItk = ThinPlateSplineTransformDoubleType::New();
1614 tpsTransformItk->SetSourceLandmarks(sourceLandmarksItk_Lps);
1615 tpsTransformItk->SetTargetLandmarks(targetLandmarksItk_Lps);
1618 tpsTransformItk->ComputeWMatrix();
1620 transformItk_LPS = tpsTransformItk;
1628 typename itk::TransformBaseTemplate<T>::Pointer transformItk,
1629 double center_LocalRAS[3] )
1631 bool conversionSuccess =
false;
1636 vtkErrorWithObjectMacro(loggerObject,
"CreateVTKTransformFromITK failed: nullptr provided");
1639 const unsigned itkDim = transformItk->GetOutputSpaceDimension();
1640 if (itkDim != transformItk->GetInputSpaceDimension())
1642 vtkErrorWithObjectMacro(loggerObject,
1643 "We do not support transforms with different number of input and output dimensions, " <<
"input dimension = " << transformItk->GetInputSpaceDimension()
1644 <<
", output dimension = " << itkDim <<
")");
1647 if (itkDim < 2 || itkDim > 3)
1649 vtkErrorWithObjectMacro(loggerObject,
"Unsupported transform dimension: " << itkDim);
1653 std::string itkTransformClassName = transformItk->GetNameOfClass();
1656 if (itkTransformClassName ==
"CompositeTransform")
1663 vtkNew<vtkMatrix4x4> transformMatrixVtk;
1665 if (conversionSuccess)
1667 vtkNew<vtkTransform> linearTransformVtk;
1668 linearTransformVtk->SetMatrix(transformMatrixVtk.GetPointer());
1669 linearTransformVtk->Register(
nullptr);
1670 return linearTransformVtk.GetPointer();
1674 vtkNew<vtkOrientedGridTransform> gridTransformVtk;
1679 else if (itkDim == 2)
1683 if (conversionSuccess)
1685 gridTransformVtk->Register(
nullptr);
1686 return gridTransformVtk.GetPointer();
1690 vtkNew<vtkOrientedBSplineTransform> bsplineTransformVtk;
1692 if (conversionSuccess)
1694 bsplineTransformVtk->Register(
nullptr);
1695 return bsplineTransformVtk.GetPointer();
1699 vtkNew<vtkThinPlateSplineTransform> tpsTransformVtk;
1704 else if (itkDim == 2)
1708 if (conversionSuccess)
1710 tpsTransformVtk->Register(
nullptr);
1711 return tpsTransformVtk.GetPointer();
1719 vtkAbstractTransform* transformVtk,
1720 itk::Object::Pointer& secondaryTransformItk,
1721 int preferITKv3CompatibleTransforms,
1723 double center_LocalRAS[3] )
1725 typedef itk::CompositeTransform<double> CompositeTransformType;
1727 if (transformVtk ==
nullptr)
1729 vtkErrorWithObjectMacro(loggerObject,
"CreateITKTransformFromVTK failed: invalid VTK transform");
1732 vtkNew<vtkCollection> transformList;
1734 if (transformList->GetNumberOfItems() == 0)
1737 vtkNew<vtkTransform> identity;
1738 transformList->AddItem(identity.GetPointer());
1741 itk::Object::Pointer primaryTransformItk;
1742 if (transformList->GetNumberOfItems() == 1)
1745 vtkObject* singleTransformVtk = transformList->GetItemAsObject(0);
1747 if (vtkHomogeneousTransform::SafeDownCast(singleTransformVtk))
1749 vtkHomogeneousTransform* linearTransformVtk = vtkHomogeneousTransform::SafeDownCast(singleTransformVtk);
1750 vtkMatrix4x4* transformMatrix = linearTransformVtk->GetMatrix();
1756 return primaryTransformItk;
1759 else if (vtkOrientedBSplineTransform::SafeDownCast(singleTransformVtk))
1761 vtkOrientedBSplineTransform* bsplineTransformVtk = vtkOrientedBSplineTransform::SafeDownCast(singleTransformVtk);
1762 vtkMatrix4x4* bulkMatrix = bsplineTransformVtk->GetBulkTransformMatrix();
1763 if (preferITKv3CompatibleTransforms || (bulkMatrix !=
nullptr && !
IsIdentityMatrix(bulkMatrix)))
1765 if (!
SetITKv3BSplineFromVTK(loggerObject, primaryTransformItk, secondaryTransformItk, bsplineTransformVtk, preferITKv3CompatibleTransforms))
1770 return primaryTransformItk;
1779 return primaryTransformItk;
1783 else if (vtkOrientedGridTransform::SafeDownCast(singleTransformVtk))
1785 vtkOrientedGridTransform* gridTransformVtk = vtkOrientedGridTransform::SafeDownCast(singleTransformVtk);
1791 return primaryTransformItk;
1794 else if (vtkThinPlateSplineTransform::SafeDownCast(singleTransformVtk))
1796 vtkThinPlateSplineTransform* tpsTransformVtk = vtkThinPlateSplineTransform::SafeDownCast(singleTransformVtk);
1802 return primaryTransformItk;
1806 if (singleTransformVtk ==
nullptr)
1808 vtkErrorWithObjectMacro(loggerObject,
"vtkITKTransformConverter::CreateITKTransformFromVTK failed: invalid input transform");
1811 vtkErrorWithObjectMacro(
1812 loggerObject,
"vtkITKTransformConverter::CreateITKTransformFromVTK failed: conversion of transform type " << singleTransformVtk->GetClassName() <<
" is not supported");
1820 CompositeTransformType::Pointer compositeTransformItk = CompositeTransformType::New();
1821 primaryTransformItk = compositeTransformItk;
1823 for (
int transformIndex = transformList->GetNumberOfItems() - 1; transformIndex >= 0; --transformIndex)
1825 vtkAbstractTransform* singleTransformVtk = vtkAbstractTransform::SafeDownCast(transformList->GetItemAsObject(transformIndex));
1826 itk::Object::Pointer secondaryTransformItkTmp;
1830 itk::Object::Pointer singleTransformItk =
CreateITKTransformFromVTK(loggerObject, singleTransformVtk, secondaryTransformItkTmp,
false);
1831 if (secondaryTransformItkTmp.IsNotNull())
1833 vtkErrorWithObjectMacro(loggerObject,
1834 "vtkITKTransformConverter::CreateITKTransformFromVTK failed:"
1835 " composite transforms cannot contain legacy transforms (that contains secondary transforms)."
1836 " Do not harden transforms on legacy ITK transforms to avoid this error.");
1840 if (singleTransformItk.IsNull()
1841 || std::string(singleTransformItk->GetNameOfClass()).find(
"Transform") == std::string::npos)
1843 vtkErrorWithObjectMacro(loggerObject,
1844 "vtkITKTransformConverter::CreateITKTransformFromVTK failed:"
1845 " invalid element found while trying to create a composite transform");
1848 CompositeTransformType::TransformType::Pointer singleTransformItkTypeChecked =
static_cast<CompositeTransformType::TransformType*
>(singleTransformItk.GetPointer());
1849 compositeTransformItk->AddTransform(singleTransformItkTypeChecked.GetPointer());
1851 return primaryTransformItk;