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 ==
"Rigid2DTransform" ||
297 itkTransformClassName ==
"Euler3DTransform" ||
298 itkTransformClassName ==
"Euler2DTransform" ||
299 itkTransformClassName ==
"CenteredEuler3DTransform" ||
300 itkTransformClassName ==
"CenteredEuler2DTransform" ||
301 itkTransformClassName ==
"CenteredSimilarity2DTransform" ||
302 itkTransformClassName ==
"QuaternionRigidTransform" ||
303 itkTransformClassName ==
"VersorTransform" ||
304 itkTransformClassName ==
"VersorRigid3DTransform" ||
305 itkTransformClassName ==
"ScaleSkewVersor3DTransform" ||
306 itkTransformClassName ==
"ScaleVersor3DTransform" ||
307 itkTransformClassName ==
"Similarity3DTransform" ||
308 itkTransformClassName ==
"Similarity2DTransform" ||
309 itkTransformClassName ==
"ScaleTransform" ||
310 itkTransformClassName ==
"ScaleLogarithmicTransform")
312 typename LinearTransformType::Pointer dlt;
319 dlt =
static_cast<LinearTransformType*
>(transformItk_LPS.GetPointer());
322 convertedToVtkMatrix =
true;
323 for (
unsigned int i = 0; i < D; i++)
325 for (
unsigned int j = 0; j < D; j++)
327 transformVtk_LPS->SetElement(i, j, dlt->GetMatrix()[i][j]);
329 transformVtk_LPS->SetElement(i, D, dlt->GetOffset()[i]);
334 auto center_LocalLPS = dlt->GetCenter();
335 center_LocalRAS[0] = -center_LocalLPS[0];
336 center_LocalRAS[1] = -center_LocalLPS[1];
337 center_LocalRAS[2] = center_LocalLPS[2];
342 if (itkTransformClassName ==
"IdentityTransform")
345 convertedToVtkMatrix =
true;
350 if (itkTransformClassName ==
"TranslationTransform")
354 using Translate2DTransformType = itk::TranslationTransform<T, 2>;
355 typename Translate2DTransformType::Pointer dtt =
static_cast<Translate2DTransformType*
>(transformItk_LPS.GetPointer());
356 for (
unsigned int i = 0; i < 2; i++)
358 transformVtk_LPS->SetElement(i, D, dtt->GetOffset()[i]);
364 typename TranslateTransformType::Pointer dtt =
static_cast<TranslateTransformType*
>(transformItk_LPS.GetPointer());
365 for (
unsigned int i = 0; i < D; i++)
367 transformVtk_LPS->SetElement(i, D, dtt->GetOffset()[i]);
370 convertedToVtkMatrix =
true;
378 vtkSmartPointer<vtkMatrix4x4> lps2ras = vtkSmartPointer<vtkMatrix4x4>::New();
379 lps2ras->SetElement(0, 0, -1);
380 lps2ras->SetElement(1, 1, -1);
381 vtkMatrix4x4* ras2lps = lps2ras;
383 vtkMatrix4x4::Multiply4x4(lps2ras, transformVtk_LPS, transformVtk_LPS);
384 vtkMatrix4x4::Multiply4x4(transformVtk_LPS, ras2lps, transformVtk_RAS);
388 for (
int i = 0; i < 3; ++i)
393 double offset_RAS = transformVtk_RAS->GetElement(i, 3);
394 center_LocalRAS[i] = center_LocalRAS[i] + offset_RAS;
398 return convertedToVtkMatrix;
403 itk::Object::Pointer& transformItk_LPS,
404 vtkMatrix4x4* transformVtk_RAS,
405 double center_LocalRAS[3] )
409 if (transformVtk_RAS ==
nullptr)
411 vtkErrorWithObjectMacro(loggerObject,
"vtkITKTransformConverter::SetITKLinearTransformFromVTK failed: invalid input transform");
415 vtkSmartPointer<vtkMatrix4x4> lps2ras = vtkSmartPointer<vtkMatrix4x4>::New();
416 lps2ras->SetElement(0, 0, -1);
417 lps2ras->SetElement(1, 1, -1);
418 vtkMatrix4x4* ras2lps = lps2ras;
424 vtkSmartPointer<vtkMatrix4x4> vtkmat = vtkSmartPointer<vtkMatrix4x4>::New();
426 vtkMatrix4x4::Multiply4x4(ras2lps, transformVtk_RAS, vtkmat);
427 vtkMatrix4x4::Multiply4x4(vtkmat, lps2ras, vtkmat);
429 typedef AffineTransformType::MatrixType MatrixType;
430 typedef AffineTransformType::OutputVectorType OffsetType;
433 OffsetType itkoffset;
439 itkmat[i][j] = vtkmat->GetElement(i, j);
444 AffineTransformType::Pointer affine = AffineTransformType::New();
455 double center_LocalLPS[3] = { -center_LocalRAS[0], -center_LocalRAS[1], center_LocalRAS[2] };
460 vtkMath::Subtract(center_LocalLPS, itkoffset, center_LocalLPS);
461 affine->SetCenter(center_LocalLPS);
463 affine->SetMatrix(itkmat);
464 affine->SetOffset(itkoffset);
466 transformItk_LPS = affine;
492 vtkOrientedBSplineTransform* bsplineVtk,
493 typename itk::TransformBaseTemplate<typename BSplineTransformType::ScalarType>::Pointer warpTransformItk)
498 typedef typename BSplineTransformType::ScalarType T;
499 if (bsplineVtk ==
nullptr)
501 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetVTKBSplineFromITKv4 failed: bsplineVtk is invalid");
504 bool isDoublePrecisionInput =
true;
505 if (
sizeof(T) ==
sizeof(
float))
507 isDoublePrecisionInput =
false;
509 else if (
sizeof(T) ==
sizeof(
double))
511 isDoublePrecisionInput =
true;
515 vtkErrorWithObjectMacro(loggerObject,
"Unsupported scalar type in BSpline transform file (only float and double are supported)");
519 typename BSplineTransformType::Pointer bsplineItk = BSplineTransformType::New();
520 std::string warpTransformItkName = warpTransformItk->GetNameOfClass();
521 std::string requestedWarpTransformItkName = bsplineItk->GetNameOfClass();
522 if (warpTransformItkName != requestedWarpTransformItkName)
526 const unsigned itkDim = warpTransformItk->GetOutputSpaceDimension();
527 constexpr unsigned instDim = BSplineTransformType::SpaceDimension;
528 if (itkDim != instDim)
530 vtkErrorWithObjectMacro(loggerObject,
"Actual and instantiated dimensionality differ: actual = " << itkDim <<
", instantiated = " << instDim);
533 bsplineItk =
static_cast<BSplineTransformType*
>(warpTransformItk.GetPointer());
541 const typename BSplineTransformType::CoefficientImageArray coefficientImages = bsplineItk->GetCoefficientImages();
545 typename BSplineTransformType::MeshSizeType meshSize = coefficientImages[0]->GetLargestPossibleRegion().GetSize();
548 typename BSplineTransformType::OriginType origin = coefficientImages[0]->GetOrigin();
551 typename BSplineTransformType::SpacingType spacing = coefficientImages[0]->GetSpacing();
554 typename BSplineTransformType::DirectionType direction = coefficientImages[0]->GetDirection();
556 itk::Matrix<T, 3, 3> direction3d;
557 if constexpr (instDim == 2)
563 direction3d = direction;
566 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
569 for (
unsigned int column = 0; column <
VTKDimension; column++)
571 gridDirectionMatrix_LPS->SetElement(row, column, direction3d[row][column]);
576 bsplineVtk->SetBorderModeToZero();
578 vtkNew<vtkImageData> bsplineCoefficients;
580 if constexpr (instDim == 2)
582 bsplineCoefficients->SetExtent(0, meshSize[0] - 1, 0, meshSize[1] - 1, 0, 0);
583 bsplineCoefficients->SetSpacing(spacing[0], spacing[1], std::sqrt(spacing[0] * spacing[1]));
587 bsplineCoefficients->SetExtent(0, meshSize[0] - 1, 0, meshSize[1] - 1, 0, meshSize[2] - 1);
588 bsplineCoefficients->SetSpacing(spacing[0], spacing[1], spacing[2]);
592 vtkNew<vtkMatrix4x4> lpsToRas;
593 lpsToRas->SetElement(0, 0, -1);
594 lpsToRas->SetElement(1, 1, -1);
596 vtkNew<vtkMatrix4x4> rasToLps;
597 rasToLps->SetElement(0, 0, -1);
598 rasToLps->SetElement(1, 1, -1);
600 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
601 vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
602 bsplineVtk->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
605 double gridOrigin_RAS[3] = { -origin[0], -origin[1], 0 };
606 if constexpr (instDim == 3)
608 gridOrigin_RAS[2] = origin[2];
610 bsplineCoefficients->SetOrigin(gridOrigin_RAS);
612 int bsplineCoefficientsScalarType = VTK_FLOAT;
613 if (isDoublePrecisionInput)
615 bsplineCoefficientsScalarType = VTK_DOUBLE;
618 bsplineCoefficients->AllocateScalars(bsplineCoefficientsScalarType, 3);
620 const unsigned int expectedNumberOfVectors = meshSize.CalculateProductOfElements();
621 const unsigned int expectedNumberOfParameters = expectedNumberOfVectors * instDim;
622 const unsigned int actualNumberOfParameters = bsplineItk->GetNumberOfParameters();
624 if (actualNumberOfParameters != expectedNumberOfParameters)
626 vtkErrorWithObjectMacro(loggerObject,
"Mismatch in number of BSpline parameters in the transform file and the MRML node");
629 const T* itkBSplineParams_LPS =
static_cast<const T*
>(bsplineItk->GetParameters().data_block());
630 T* vtkBSplineParams_RAS =
static_cast<T*
>(bsplineCoefficients->GetScalarPointer());
631 for (
unsigned int i = 0; i < expectedNumberOfVectors; i++)
633 *(vtkBSplineParams_RAS++) = -(*(itkBSplineParams_LPS));
634 *(vtkBSplineParams_RAS++) = -(*(itkBSplineParams_LPS + expectedNumberOfVectors));
635 if constexpr (instDim == 3)
637 *(vtkBSplineParams_RAS++) = (*(itkBSplineParams_LPS + expectedNumberOfVectors * 2));
641 *(vtkBSplineParams_RAS++) = 0;
643 itkBSplineParams_LPS++;
645 bsplineVtk->SetCoefficientData(bsplineCoefficients.GetPointer());
654 vtkOrientedBSplineTransform* bsplineVtk,
655 typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk,
656 typename itk::TransformBaseTemplate<T>::Pointer bulkTransformItk)
658 if (bsplineVtk ==
nullptr)
660 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetVTKBSplineFromITK failed: bsplineVtk is invalid");
664 const unsigned int itkDim = warpTransformItk->GetOutputSpaceDimension();
665 if (itkDim < 2 || itkDim > 3)
667 vtkErrorWithObjectMacro(loggerObject,
"Unsupported number of dimensions in BSpline transform file (expected = 2 or 3, actual = " << itkDim <<
")");
670 bool inverse =
false;
684 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv3 BSpline transform");
701 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv3 BSpline transform");
707 if (bulkTransformItk)
709 std::string bulkTransformItkTransformName = bulkTransformItk->GetNameOfClass();
711 if (bulkTransformItkTransformName ==
"AffineTransform")
713 vtkNew<vtkMatrix4x4> bulkMatrix_RAS;
716 vtkErrorWithObjectMacro(loggerObject,
"Cannot read the bulk transform in BSplineTransform");
719 bsplineVtk->SetBulkTransformMatrix(bulkMatrix_RAS.GetPointer());
721 else if (bulkTransformItkTransformName ==
"IdentityTransform")
727 vtkErrorWithObjectMacro(loggerObject,
"Cannot read the 2nd transform in BSplineTransform (expected AffineTransform_double_3_3 or IdentityTransform)");
734 bsplineVtk->Inverse();
744 vtkOrientedBSplineTransform* bsplineVtk,
745 typename itk::TransformBaseTemplate<T>::Pointer warpTransformItk)
747 bool inverse =
false;
748 const unsigned int itkDim = warpTransformItk->GetOutputSpaceDimension();
763 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv4 BSpline transform");
780 vtkDebugWithObjectMacro(loggerObject,
"Not an ITKv4 BSpline transform");
787 bsplineVtk->Inverse();
795 vtkObject* loggerObject,
796 typename itk::Transform<typename BSplineTransformType::ScalarType, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
797 vtkOrientedBSplineTransform* bsplineVtk)
799 typedef typename BSplineTransformType::ScalarType T;
800 if (bsplineVtk ==
nullptr)
802 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: bsplineVtk is invalid");
805 vtkImageData* bsplineCoefficients_RAS = bsplineVtk->GetCoefficientData();
806 if (bsplineCoefficients_RAS ==
nullptr)
808 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: coefficients are not specified");
812 typename BSplineTransformType::Pointer bsplineItk = BSplineTransformType::New();
813 warpTransformItk = bsplineItk;
820 typename BSplineTransformType::FixedParametersType transformFixedParamsItk;
822 transformFixedParamsItk.SetSize(numberOfFixedParameters);
824 int* gridExtent = bsplineCoefficients_RAS->GetExtent();
825 int gridSize[3] = { gridExtent[1] - gridExtent[0] + 1, gridExtent[3] - gridExtent[2] + 1, gridExtent[5] - gridExtent[4] + 1 };
826 transformFixedParamsItk[0] = gridSize[0];
827 transformFixedParamsItk[1] = gridSize[1];
828 transformFixedParamsItk[2] = gridSize[2];
830 double* gridOrigin_RAS = bsplineCoefficients_RAS->GetOrigin();
831 double gridOrigin_LPS[3] = { -gridOrigin_RAS[0], -gridOrigin_RAS[1], gridOrigin_RAS[2] };
832 transformFixedParamsItk[3] = gridOrigin_LPS[0];
833 transformFixedParamsItk[4] = gridOrigin_LPS[1];
834 transformFixedParamsItk[5] = gridOrigin_LPS[2];
836 double* gridSpacing = bsplineCoefficients_RAS->GetSpacing();
837 transformFixedParamsItk[6] = gridSpacing[0];
838 transformFixedParamsItk[7] = gridSpacing[1];
839 transformFixedParamsItk[8] = gridSpacing[2];
841 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
842 if (bsplineVtk->GetGridDirectionMatrix() !=
nullptr)
844 gridDirectionMatrix_RAS->DeepCopy(bsplineVtk->GetGridDirectionMatrix());
846 vtkNew<vtkMatrix4x4> lpsToRas;
847 lpsToRas->SetElement(0, 0, -1);
848 lpsToRas->SetElement(1, 1, -1);
849 vtkNew<vtkMatrix4x4> rasToLps;
850 rasToLps->SetElement(0, 0, -1);
851 rasToLps->SetElement(1, 1, -1);
852 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
853 vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), gridDirectionMatrix_RAS.GetPointer(), gridDirectionMatrix_LPS.GetPointer());
857 for (
unsigned int column = 0; column <
VTKDimension; column++)
859 transformFixedParamsItk[fpIndex++] = gridDirectionMatrix_LPS->GetElement(row, column);
863 bsplineItk->SetFixedParameters(transformFixedParamsItk);
867 const unsigned int expectedNumberOfVectors = gridSize[0] * gridSize[1] * gridSize[2];
868 const unsigned int expectedNumberOfParameters = expectedNumberOfVectors *
VTKDimension;
869 if (bsplineItk->GetNumberOfParameters() != expectedNumberOfParameters)
871 vtkErrorWithObjectMacro(loggerObject,
"Mismatch in number of BSpline parameters in the ITK transform and the VTK transform");
875 typename BSplineTransformType::ParametersType transformParamsItk(expectedNumberOfParameters);
876 T* itkBSplineParams_LPS =
static_cast<T*
>(transformParamsItk.data_block());
877 T* vtkBSplineParams_RAS =
static_cast<T*
>(bsplineCoefficients_RAS->GetScalarPointer());
878 double coefficientScale = bsplineVtk->GetDisplacementScale();
879 for (
unsigned int i = 0; i < expectedNumberOfVectors; i++)
881 *(itkBSplineParams_LPS) = -coefficientScale * (*(vtkBSplineParams_RAS++));
882 *(itkBSplineParams_LPS + expectedNumberOfVectors) = -coefficientScale * (*(vtkBSplineParams_RAS++));
883 *(itkBSplineParams_LPS + expectedNumberOfVectors * 2) = coefficientScale * (*(vtkBSplineParams_RAS++));
884 itkBSplineParams_LPS++;
887 bsplineItk->SetParameters(transformParamsItk);
894 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& warpTransformItk,
895 typename itk::Transform<T, VTKDimension, VTKDimension>::Pointer& bulkTransformItk,
896 vtkOrientedBSplineTransform* bsplineVtk,
897 bool alwaysAddBulkTransform)
899 if (bsplineVtk ==
nullptr)
901 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: bsplineVtk is invalid");
905 bsplineVtk->Update();
906 bool itkTransformSetSuccessfully =
false;
907 if (bsplineVtk->GetInverseFlag())
909 itkTransformSetSuccessfully =
916 if (!itkTransformSetSuccessfully)
918 vtkErrorWithObjectMacro(loggerObject,
"vtkMRMLTransformStorageNode::SetITKBSplineFromVTK failed: cannot determine BSpline parameters");
922 vtkMatrix4x4* bulkMatrix_RAS = bsplineVtk->GetBulkTransformMatrix();
923 if (bulkMatrix_RAS || alwaysAddBulkTransform)
925 vtkNew<vtkMatrix4x4> lpsToRas;
926 lpsToRas->SetElement(0, 0, -1);
927 lpsToRas->SetElement(1, 1, -1);
928 vtkNew<vtkMatrix4x4> rasToLps;
929 rasToLps->SetElement(0, 0, -1);
930 rasToLps->SetElement(1, 1, -1);
931 vtkNew<vtkMatrix4x4> bulkMatrix_LPS;
934 if (bulkMatrix_RAS !=
nullptr)
936 vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), bulkMatrix_RAS, bulkMatrix_LPS.GetPointer());
937 vtkMatrix4x4::Multiply4x4(bulkMatrix_LPS.GetPointer(), lpsToRas.GetPointer(), bulkMatrix_LPS.GetPointer());
939 typedef itk::AffineTransform<T, VTKDimension> BulkTransformType;
940 typename BulkTransformType::Pointer affineItk = BulkTransformType::New();
941 bulkTransformItk = affineItk;
943 typename BulkTransformType::MatrixType affineMatrix;
944 typename BulkTransformType::OffsetType affineOffset;
949 affineMatrix[i][j] = bulkMatrix_LPS->GetElement(i, j);
951 affineOffset[i] = bulkMatrix_LPS->GetElement(i,
VTKDimension);
954 affineItk->SetMatrix(affineMatrix);
955 affineItk->SetOffset(affineOffset);
959 bulkTransformItk =
nullptr;
992 itk::Object::Pointer& warpTransformItk,
993 itk::Object::Pointer& bulkTransformItk,
994 vtkOrientedBSplineTransform* bsplineVtk,
995 bool alwaysAddBulkTransform)
997 if (bsplineVtk ==
nullptr)
999 vtkErrorWithObjectMacro(loggerObject,
"Cannot retrieve BSpline transform from node");
1003 vtkImageData* bsplineCoefficients = bsplineVtk->GetCoefficientData();
1005 if (bsplineCoefficients ==
nullptr)
1007 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: coefficients are not specified");
1011 if (bsplineCoefficients->GetScalarType() == VTK_FLOAT)
1013 typedef itk::Transform<float, VTKDimension, VTKDimension> ITKTransformType;
1014 ITKTransformType::Pointer floatWarpTransformItk;
1015 ITKTransformType::Pointer floatBulkTransformItk;
1018 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1021 warpTransformItk = floatWarpTransformItk.GetPointer();
1022 bulkTransformItk = floatBulkTransformItk.GetPointer();
1024 else if (bsplineCoefficients->GetScalarType() == VTK_DOUBLE)
1026 typedef itk::Transform<double, VTKDimension, VTKDimension> ITKTransformType;
1027 ITKTransformType::Pointer doubleWarpTransformItk;
1028 ITKTransformType::Pointer doubleBulkTransformItk;
1031 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1034 warpTransformItk = doubleWarpTransformItk;
1035 bulkTransformItk = doubleBulkTransformItk;
1039 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: only float and double coefficient types are supported");
1049 if (bsplineVtk ==
nullptr)
1051 vtkErrorWithObjectMacro(loggerObject,
"Cannot retrieve BSpline transform from node");
1055 vtkImageData* bsplineCoefficients = bsplineVtk->GetCoefficientData();
1057 if (bsplineCoefficients ==
nullptr)
1059 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: coefficients are not specified");
1063 if (bsplineCoefficients->GetScalarType() == VTK_FLOAT)
1065 typedef itk::Transform<float, VTKDimension, VTKDimension> ITKTransformType;
1066 ITKTransformType::Pointer floatWarpTransformItk;
1069 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1072 warpTransformItk = floatWarpTransformItk.GetPointer();
1074 else if (bsplineCoefficients->GetScalarType() == VTK_DOUBLE)
1076 typedef itk::Transform<double, VTKDimension, VTKDimension> ITKTransformType;
1077 ITKTransformType::Pointer doubleWarpTransformItk;
1080 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file");
1083 warpTransformItk = doubleWarpTransformItk;
1087 vtkErrorWithObjectMacro(loggerObject,
"Cannot write BSpline transform to file: only float and double coefficient types are supported");
1097 vtkOrientedGridTransform* transformVtk_RAS,
1098 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
1100 typedef itk::DisplacementFieldTransform<T, Dimension> DisplacementFieldTransformType;
1103 std::string transformItkClassName = transformItk_LPS->GetNameOfClass();
1105 bool inverse =
false;
1106 typename DisplacementFieldTransformType::DisplacementFieldType* gridImageItk_Lps =
nullptr;
1107 if (transformItkClassName ==
"InverseDisplacementFieldTransform")
1109 DisplacementFieldTransformType* inverseDisplacementFieldTransform =
static_cast<InverseDisplacementFieldTransformType*
>(transformItk_LPS.GetPointer());
1111 gridImageItk_Lps = inverseDisplacementFieldTransform->GetDisplacementField();
1113 else if (transformItkClassName ==
"DisplacementFieldTransform")
1115 DisplacementFieldTransformType* displacementFieldTransform =
static_cast<DisplacementFieldTransformType*
>(transformItk_LPS.GetPointer());
1117 gridImageItk_Lps = displacementFieldTransform->GetDisplacementField();
1121 vtkDebugWithObjectMacro(loggerObject,
"Not a grid transform");
1140 transformVtk_RAS->Inverse();
1148 GridImageDoubleType::Pointer gridImageItk_Lps;
1151 vtkErrorWithObjectMacro(loggerObject,
"vtkITKTransformConverter::SetITKOrientedGridTransformFromVTK failed: input transform is invalid");
1155 transformVtk_RAS->Update();
1156 if (transformVtk_RAS->GetInverseFlag())
1159 gridTransformItk->SetDisplacementField(gridImageItk_Lps);
1160 transformItk_LPS = gridTransformItk;
1164 DisplacementFieldTransformDoubleType::Pointer gridTransformItk = DisplacementFieldTransformDoubleType::New();
1165 gridTransformItk->SetDisplacementField(gridImageItk_Lps);
1166 transformItk_LPS = gridTransformItk;
1174 vtkOrientedGridTransform* grid_Ras,
1175 typename itk::DisplacementFieldTransform<T, 3>::DisplacementFieldType::Pointer gridImage_Lps)
1177 typedef itk::DisplacementFieldTransform<T, 3> DisplacementFieldTransformType;
1178 typedef typename DisplacementFieldTransformType::DisplacementFieldType GridImageType;
1180 vtkNew<vtkImageData> gridImage_Ras;
1183 gridImage_Ras->SetOrigin(-gridImage_Lps->GetOrigin()[0], -gridImage_Lps->GetOrigin()[1], gridImage_Lps->GetOrigin()[2]);
1186 gridImage_Ras->SetSpacing(gridImage_Lps->GetSpacing()[0], gridImage_Lps->GetSpacing()[1], gridImage_Lps->GetSpacing()[2]);
1189 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
1192 for (
unsigned int column = 0; column <
VTKDimension; column++)
1194 gridDirectionMatrix_LPS->SetElement(row, column, gridImage_Lps->GetDirection()(row, column));
1197 vtkNew<vtkMatrix4x4> lpsToRas;
1198 lpsToRas->SetElement(0, 0, -1);
1199 lpsToRas->SetElement(1, 1, -1);
1200 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
1201 vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
1202 grid_Ras->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
1205 typename GridImageType::SizeType size = gridImage_Lps->GetBufferedRegion().GetSize();
1206 gridImage_Ras->SetDimensions(size[0], size[1], size[2]);
1207 unsigned int numberOfScalarComponents = GridImageType::PixelType::Dimension;
1210 vtkErrorWithObjectMacro(loggerObject,
1211 "Cannot load grid transform: the input displacement field expected to contain " <<
VTKDimension <<
" components but it actually contains "
1212 << numberOfScalarComponents);
1215 gridImage_Ras->AllocateScalars(VTK_DOUBLE, 3);
1217 double* displacementVectors_Ras =
reinterpret_cast<double*
>(gridImage_Ras->GetScalarPointer());
1218 itk::ImageRegionConstIterator<GridImageType> inputIt(gridImage_Lps, gridImage_Lps->GetRequestedRegion());
1219 while (!inputIt.IsAtEnd())
1221 typename GridImageType::PixelType displacementVectorLps = inputIt.Get();
1222 *(displacementVectors_Ras++) = -displacementVectorLps[0];
1223 *(displacementVectors_Ras++) = -displacementVectorLps[1];
1224 *(displacementVectors_Ras++) = displacementVectorLps[2];
1228 grid_Ras->SetDisplacementGridData(gridImage_Ras.GetPointer());
1231 grid_Ras->SetInterpolationModeToCubic();
1239 vtkOrientedGridTransform* grid_Ras,
1240 typename itk::DisplacementFieldTransform<T, 2>::DisplacementFieldType::Pointer gridImage_Lps)
1242 typedef itk::DisplacementFieldTransform<T, 2> DisplacementFieldTransformType;
1243 typedef typename DisplacementFieldTransformType::DisplacementFieldType GridImageType;
1245 vtkNew<vtkImageData> gridImage_Ras;
1248 const auto& itkOrigin = gridImage_Lps->GetOrigin();
1249 double originRasX = -itkOrigin[0];
1250 double originRasY = -itkOrigin[1];
1251 double originRasZ = 0.0;
1252 gridImage_Ras->SetOrigin(originRasX, originRasY, originRasZ);
1255 const auto& itkSpacing = gridImage_Lps->GetSpacing();
1256 gridImage_Ras->SetSpacing(itkSpacing[0], itkSpacing[1], std::sqrt(itkSpacing[0] * itkSpacing[1]));
1260 vtkNew<vtkMatrix4x4> gridDirectionMatrix_LPS;
1261 for (
unsigned int row = 0; row < 3; ++row)
1263 for (
unsigned int col = 0; col < 3; ++col)
1265 gridDirectionMatrix_LPS->SetElement(row, col, direction3d(row, col));
1270 vtkNew<vtkMatrix4x4> lpsToRas;
1271 lpsToRas->SetElement(0, 0, -1);
1272 lpsToRas->SetElement(1, 1, -1);
1273 vtkNew<vtkMatrix4x4> gridDirectionMatrix_RAS;
1274 vtkMatrix4x4::Multiply4x4(lpsToRas.GetPointer(), gridDirectionMatrix_LPS.GetPointer(), gridDirectionMatrix_RAS.GetPointer());
1275 grid_Ras->SetGridDirectionMatrix(gridDirectionMatrix_RAS.GetPointer());
1278 typename GridImageType::SizeType size = gridImage_Lps->GetBufferedRegion().GetSize();
1279 int dimX =
static_cast<int>(size[0]);
1280 int dimY =
static_cast<int>(size[1]);
1281 gridImage_Ras->SetDimensions(dimX, dimY, 1);
1283 unsigned int numberOfScalarComponents = GridImageType::PixelType::Dimension;
1284 if (numberOfScalarComponents != 2)
1286 vtkErrorWithObjectMacro(loggerObject,
1287 "Cannot load 2D grid transform: the input displacement field expected to contain 2 components but it actually contains " << numberOfScalarComponents);
1291 if constexpr (std::is_same_v<T, float>)
1293 gridImage_Ras->AllocateScalars(VTK_FLOAT, 3);
1295 else if constexpr (std::is_same_v<T, double>)
1297 gridImage_Ras->AllocateScalars(VTK_DOUBLE, 3);
1301 vtkErrorWithObjectMacro(loggerObject,
"Cannot load 2D grid transform: unsupported pixel type. Only float and double are supported.");
1306 T* displacementVectors_Ras =
reinterpret_cast<T*
>(gridImage_Ras->GetScalarPointer());
1307 itk::ImageRegionConstIterator<GridImageType> inputIt(gridImage_Lps, gridImage_Lps->GetRequestedRegion());
1308 while (!inputIt.IsAtEnd())
1310 typename GridImageType::PixelType displacementVectorLps = inputIt.Get();
1312 *(displacementVectors_Ras++) = -
static_cast<T
>(displacementVectorLps[0]);
1313 *(displacementVectors_Ras++) = -
static_cast<T
>(displacementVectorLps[1]);
1314 *(displacementVectors_Ras++) = 0.0;
1318 grid_Ras->SetDisplacementGridData(gridImage_Ras.GetPointer());
1321 grid_Ras->SetInterpolationModeToCubic();
1329 if (grid_Ras ==
nullptr)
1331 vtkErrorWithObjectMacro(loggerObject,
"Cannot save grid transform: the input vtkOrientedGridTransform is invalid");
1338 vtkImageData* gridImage_Ras = grid_Ras->GetDisplacementGrid();
1339 if (gridImage_Ras ==
nullptr)
1341 vtkErrorWithObjectMacro(loggerObject,
"Cannot save grid transform: the input vtkOrientedGridTransform does not contain a valid displacement grid");
1344 if (gridImage_Ras->GetNumberOfScalarComponents() !=
static_cast<int>(
VTKDimension))
1346 vtkErrorWithObjectMacro(loggerObject,
1347 "Cannot save grid transform: the input vtkOrientedGridTransform expected to contain " <<
VTKDimension <<
" components but it actually contains "
1348 << gridImage_Ras->GetNumberOfScalarComponents());
1352 gridImage_Lps = GridImageDoubleType::New();
1355 double* origin_Ras = gridImage_Ras->GetOrigin();
1356 double origin_Lps[3] = { -origin_Ras[0], -origin_Ras[1], origin_Ras[2] };
1357 gridImage_Lps->SetOrigin(origin_Lps);
1360 double* spacing = gridImage_Ras->GetSpacing();
1362 gridImage_Lps->SetSpacing(spacing);
1365 vtkNew<vtkMatrix4x4> gridDirectionMatrix_Ras;
1366 if (grid_Ras->GetGridDirectionMatrix() !=
nullptr)
1368 gridDirectionMatrix_Ras->DeepCopy(grid_Ras->GetGridDirectionMatrix());
1370 vtkNew<vtkMatrix4x4> rasToLps;
1371 rasToLps->SetElement(0, 0, -1);
1372 rasToLps->SetElement(1, 1, -1);
1373 vtkNew<vtkMatrix4x4> gridDirectionMatrix_Lps;
1374 vtkMatrix4x4::Multiply4x4(rasToLps.GetPointer(), gridDirectionMatrix_Ras.GetPointer(), gridDirectionMatrix_Lps.GetPointer());
1375 GridImageDoubleType::DirectionType gridDirectionMatrixItk_Lps;
1378 for (
unsigned int column = 0; column <
VTKDimension; column++)
1380 gridDirectionMatrixItk_Lps(row, column) = gridDirectionMatrix_Lps->GetElement(row, column);
1383 gridImage_Lps->SetDirection(gridDirectionMatrixItk_Lps);
1386 GridImageDoubleType::IndexType start;
1387 start[0] = start[1] = start[2] = 0;
1388 int* Nijk = gridImage_Ras->GetDimensions();
1389 GridImageDoubleType::SizeType size;
1393 GridImageDoubleType::RegionType region;
1394 region.SetSize(size);
1395 region.SetIndex(start);
1396 gridImage_Lps->SetRegions(region);
1397 gridImage_Lps->Allocate();
1398 itk::ImageRegionIterator<GridImageDoubleType> gridImageIt_Lps(gridImage_Lps, region);
1399 gridImageIt_Lps.GoToBegin();
1400 GridImageDoubleType::PixelType displacementVectorLps;
1401 double displacementScale = grid_Ras->GetDisplacementScale();
1402 double displacementShift = grid_Ras->GetDisplacementShift();
1404 if (gridImage_Ras->GetScalarType() == VTK_DOUBLE)
1406 double* displacementVectors_Ras =
reinterpret_cast<double*
>(gridImage_Ras->GetScalarPointer());
1407 while (!gridImageIt_Lps.IsAtEnd())
1409 displacementVectorLps[0] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1410 displacementVectorLps[1] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1411 displacementVectorLps[2] = (displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1412 gridImageIt_Lps.Set(displacementVectorLps);
1416 else if (gridImage_Ras->GetScalarType() == VTK_FLOAT)
1418 float* displacementVectors_Ras =
reinterpret_cast<float*
>(gridImage_Ras->GetScalarPointer());
1419 while (!gridImageIt_Lps.IsAtEnd())
1421 displacementVectorLps[0] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1422 displacementVectorLps[1] = -(displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1423 displacementVectorLps[2] = (displacementScale * (*(displacementVectors_Ras++)) + displacementShift);
1424 gridImageIt_Lps.Set(displacementVectorLps);
1430 vtkErrorWithObjectMacro(loggerObject,
"Cannot save grid transform: only float and double scalar types are supported");
1439 vtkThinPlateSplineTransform* transformVtk_RAS,
1440 typename itk::TransformBaseTemplate<T>::Pointer transformItk_LPS)
1442 typedef itk::ThinPlateSplineKernelTransform<T, VDimension> ThinPlateSplineTransformType;
1445 std::string transformItkClassName = transformItk_LPS->GetNameOfClass();
1447 bool inverse =
false;
1448 typename ThinPlateSplineTransformType::PointSetType::Pointer sourceLandmarksItk_Lps;
1449 typename ThinPlateSplineTransformType::PointSetType::Pointer targetLandmarksItk_Lps;
1450 if (transformItkClassName ==
"InverseThinPlateSplineKernelTransform")
1452 ThinPlateSplineTransformType* inverseTpsTransform =
static_cast<InverseThinPlateSplineTransformType*
>(transformItk_LPS.GetPointer());
1454 sourceLandmarksItk_Lps = inverseTpsTransform->GetSourceLandmarks();
1455 targetLandmarksItk_Lps = inverseTpsTransform->GetTargetLandmarks();
1457 else if (transformItkClassName ==
"ThinPlateSplineKernelTransform")
1459 ThinPlateSplineTransformType* tpsTransform =
static_cast<ThinPlateSplineTransformType*
>(transformItk_LPS.GetPointer());
1461 sourceLandmarksItk_Lps = tpsTransform->GetSourceLandmarks();
1462 targetLandmarksItk_Lps = tpsTransform->GetTargetLandmarks();
1466 vtkDebugWithObjectMacro(loggerObject,
"Not a ThinPlateSpline transform");
1470 vtkNew<vtkPoints> sourceLandmarksVtk_Ras;
1471 unsigned int numberOfSourceLandmarks = sourceLandmarksItk_Lps->GetNumberOfPoints();
1472 vtkNew<vtkPoints> targetLandmarksVtk_Ras;
1473 unsigned int numberOfTargetLandmarks = targetLandmarksItk_Lps->GetNumberOfPoints();
1474 if constexpr (std::is_same_v<T, float>)
1476 sourceLandmarksVtk_Ras->SetDataTypeToFloat();
1477 sourceLandmarksVtk_Ras->Allocate(numberOfSourceLandmarks);
1479 targetLandmarksVtk_Ras->SetDataTypeToFloat();
1480 targetLandmarksVtk_Ras->Allocate(numberOfTargetLandmarks);
1482 else if constexpr (std::is_same_v<T, double>)
1484 sourceLandmarksVtk_Ras->SetDataTypeToDouble();
1485 sourceLandmarksVtk_Ras->Allocate(numberOfSourceLandmarks);
1487 targetLandmarksVtk_Ras->SetDataTypeToDouble();
1488 targetLandmarksVtk_Ras->Allocate(numberOfTargetLandmarks);
1492 vtkErrorWithObjectMacro(loggerObject,
"Cannot load 2D TPS transform: unsupported pixel type. Only float and double are supported.");
1496 for (
unsigned int i = 0; i < numberOfSourceLandmarks; i++)
1498 typename ThinPlateSplineTransformType::InputPointType pointItk_Lps;
1499 bool pointExists = sourceLandmarksItk_Lps->GetPoint(i, &pointItk_Lps);
1504 T pointVtk_Ras[3] = { 0 };
1505 pointVtk_Ras[0] = -pointItk_Lps[0];
1506 pointVtk_Ras[1] = -pointItk_Lps[1];
1507 if constexpr (VDimension == 2)
1509 pointVtk_Ras[2] = 0.0;
1513 pointVtk_Ras[2] = pointItk_Lps[2];
1515 sourceLandmarksVtk_Ras->InsertNextPoint(pointVtk_Ras);
1518 for (
unsigned int i = 0; i < numberOfTargetLandmarks; i++)
1520 typename ThinPlateSplineTransformType::InputPointType pointItk_Lps;
1521 bool pointExists = targetLandmarksItk_Lps->GetPoint(i, &pointItk_Lps);
1526 T pointVtk_Ras[3] = { 0 };
1527 pointVtk_Ras[0] = -pointItk_Lps[0];
1528 pointVtk_Ras[1] = -pointItk_Lps[1];
1529 if constexpr (VDimension == 2)
1531 pointVtk_Ras[2] = 0.0;
1535 pointVtk_Ras[2] = pointItk_Lps[2];
1537 targetLandmarksVtk_Ras->InsertNextPoint(pointVtk_Ras);
1540 transformVtk_RAS->SetBasisToR();
1541 transformVtk_RAS->SetSourceLandmarks(sourceLandmarksVtk_Ras.GetPointer());
1542 transformVtk_RAS->SetTargetLandmarks(targetLandmarksVtk_Ras.GetPointer());
1546 transformVtk_RAS->Inverse();
1553 itk::Object::Pointer& transformItk_LPS,
1554 vtkThinPlateSplineTransform* transformVtk_RAS,
1557 if (transformVtk_RAS ==
nullptr)
1559 vtkErrorWithObjectMacro(loggerObject,
"Cannot set ITK thin-plate spline transform from VTK: the input vtkThinPlateSplineTransform is invalid");
1564 transformVtk_RAS->Update();
1566 if (transformVtk_RAS->GetBasis() != VTK_RBF_R)
1568 vtkErrorWithObjectMacro(loggerObject,
1569 "Cannot set ITK thin-plate spline transform from VTK: basis function must be R."
1570 " Call SetBasisToR() method of the vtkThinPlateSplineTransform object before attempting to write it to file.");
1574 ThinPlateSplineTransformDoubleType::PointSetType::Pointer sourceLandmarksItk_Lps = ThinPlateSplineTransformDoubleType::PointSetType::New();
1575 vtkPoints* sourceLandmarksVtk_Ras = transformVtk_RAS->GetSourceLandmarks();
1576 if (sourceLandmarksVtk_Ras !=
nullptr)
1578 for (
int i = 0; i < sourceLandmarksVtk_Ras->GetNumberOfPoints(); i++)
1580 double posVtk_Ras[3] = { 0 };
1581 sourceLandmarksVtk_Ras->GetPoint(i, posVtk_Ras);
1582 ThinPlateSplineTransformDoubleType::InputPointType posItk_Lps;
1583 posItk_Lps[0] = -posVtk_Ras[0];
1584 posItk_Lps[1] = -posVtk_Ras[1];
1585 posItk_Lps[2] = posVtk_Ras[2];
1586 sourceLandmarksItk_Lps->GetPoints()->InsertElement(i, posItk_Lps);
1589 ThinPlateSplineTransformDoubleType::PointSetType::Pointer targetLandmarksItk_Lps = ThinPlateSplineTransformDoubleType::PointSetType::New();
1590 vtkPoints* targetLandmarksVtk_Ras = transformVtk_RAS->GetTargetLandmarks();
1591 if (targetLandmarksVtk_Ras !=
nullptr)
1593 for (
int i = 0; i < targetLandmarksVtk_Ras->GetNumberOfPoints(); i++)
1595 double posVtk_Ras[3] = { 0 };
1596 targetLandmarksVtk_Ras->GetPoint(i, posVtk_Ras);
1597 ThinPlateSplineTransformDoubleType::InputPointType posItk_Lps;
1598 posItk_Lps[0] = -posVtk_Ras[0];
1599 posItk_Lps[1] = -posVtk_Ras[1];
1600 posItk_Lps[2] = posVtk_Ras[2];
1601 targetLandmarksItk_Lps->GetPoints()->InsertElement(i, posItk_Lps);
1605 if (transformVtk_RAS->GetInverseFlag())
1608 tpsTransformItk->SetSourceLandmarks(sourceLandmarksItk_Lps);
1609 tpsTransformItk->SetTargetLandmarks(targetLandmarksItk_Lps);
1612 tpsTransformItk->ComputeWMatrix();
1614 transformItk_LPS = tpsTransformItk;
1618 ThinPlateSplineTransformDoubleType::Pointer tpsTransformItk = ThinPlateSplineTransformDoubleType::New();
1619 tpsTransformItk->SetSourceLandmarks(sourceLandmarksItk_Lps);
1620 tpsTransformItk->SetTargetLandmarks(targetLandmarksItk_Lps);
1623 tpsTransformItk->ComputeWMatrix();
1625 transformItk_LPS = tpsTransformItk;
1633 typename itk::TransformBaseTemplate<T>::Pointer transformItk,
1634 double center_LocalRAS[3] )
1636 bool conversionSuccess =
false;
1641 vtkErrorWithObjectMacro(loggerObject,
"CreateVTKTransformFromITK failed: nullptr provided");
1644 const unsigned itkDim = transformItk->GetOutputSpaceDimension();
1645 if (itkDim != transformItk->GetInputSpaceDimension())
1647 vtkErrorWithObjectMacro(loggerObject,
1648 "We do not support transforms with different number of input and output dimensions, " <<
"input dimension = " << transformItk->GetInputSpaceDimension()
1649 <<
", output dimension = " << itkDim <<
")");
1652 if (itkDim < 2 || itkDim > 3)
1654 vtkErrorWithObjectMacro(loggerObject,
"Unsupported transform dimension: " << itkDim);
1658 std::string itkTransformClassName = transformItk->GetNameOfClass();
1661 if (itkTransformClassName ==
"CompositeTransform")
1668 vtkNew<vtkMatrix4x4> transformMatrixVtk;
1670 if (conversionSuccess)
1672 vtkNew<vtkTransform> linearTransformVtk;
1673 linearTransformVtk->SetMatrix(transformMatrixVtk.GetPointer());
1674 linearTransformVtk->Register(
nullptr);
1675 return linearTransformVtk.GetPointer();
1679 vtkNew<vtkOrientedGridTransform> gridTransformVtk;
1684 else if (itkDim == 2)
1688 if (conversionSuccess)
1690 gridTransformVtk->Register(
nullptr);
1691 return gridTransformVtk.GetPointer();
1695 vtkNew<vtkOrientedBSplineTransform> bsplineTransformVtk;
1697 if (conversionSuccess)
1699 bsplineTransformVtk->Register(
nullptr);
1700 return bsplineTransformVtk.GetPointer();
1704 vtkNew<vtkThinPlateSplineTransform> tpsTransformVtk;
1709 else if (itkDim == 2)
1713 if (conversionSuccess)
1715 tpsTransformVtk->Register(
nullptr);
1716 return tpsTransformVtk.GetPointer();
1724 vtkAbstractTransform* transformVtk,
1725 itk::Object::Pointer& secondaryTransformItk,
1726 int preferITKv3CompatibleTransforms,
1728 double center_LocalRAS[3] )
1730 typedef itk::CompositeTransform<double> CompositeTransformType;
1732 if (transformVtk ==
nullptr)
1734 vtkErrorWithObjectMacro(loggerObject,
"CreateITKTransformFromVTK failed: invalid VTK transform");
1737 vtkNew<vtkCollection> transformList;
1739 if (transformList->GetNumberOfItems() == 0)
1742 vtkNew<vtkTransform> identity;
1743 transformList->AddItem(identity.GetPointer());
1746 itk::Object::Pointer primaryTransformItk;
1747 if (transformList->GetNumberOfItems() == 1)
1750 vtkObject* singleTransformVtk = transformList->GetItemAsObject(0);
1752 if (vtkHomogeneousTransform::SafeDownCast(singleTransformVtk))
1754 vtkHomogeneousTransform* linearTransformVtk = vtkHomogeneousTransform::SafeDownCast(singleTransformVtk);
1755 vtkMatrix4x4* transformMatrix = linearTransformVtk->GetMatrix();
1761 return primaryTransformItk;
1764 else if (vtkOrientedBSplineTransform::SafeDownCast(singleTransformVtk))
1766 vtkOrientedBSplineTransform* bsplineTransformVtk = vtkOrientedBSplineTransform::SafeDownCast(singleTransformVtk);
1767 vtkMatrix4x4* bulkMatrix = bsplineTransformVtk->GetBulkTransformMatrix();
1768 if (preferITKv3CompatibleTransforms || (bulkMatrix !=
nullptr && !
IsIdentityMatrix(bulkMatrix)))
1770 if (!
SetITKv3BSplineFromVTK(loggerObject, primaryTransformItk, secondaryTransformItk, bsplineTransformVtk, preferITKv3CompatibleTransforms))
1775 return primaryTransformItk;
1784 return primaryTransformItk;
1788 else if (vtkOrientedGridTransform::SafeDownCast(singleTransformVtk))
1790 vtkOrientedGridTransform* gridTransformVtk = vtkOrientedGridTransform::SafeDownCast(singleTransformVtk);
1796 return primaryTransformItk;
1799 else if (vtkThinPlateSplineTransform::SafeDownCast(singleTransformVtk))
1801 vtkThinPlateSplineTransform* tpsTransformVtk = vtkThinPlateSplineTransform::SafeDownCast(singleTransformVtk);
1807 return primaryTransformItk;
1811 if (singleTransformVtk ==
nullptr)
1813 vtkErrorWithObjectMacro(loggerObject,
"vtkITKTransformConverter::CreateITKTransformFromVTK failed: invalid input transform");
1816 vtkErrorWithObjectMacro(
1817 loggerObject,
"vtkITKTransformConverter::CreateITKTransformFromVTK failed: conversion of transform type " << singleTransformVtk->GetClassName() <<
" is not supported");
1825 CompositeTransformType::Pointer compositeTransformItk = CompositeTransformType::New();
1826 primaryTransformItk = compositeTransformItk;
1828 for (
int transformIndex = transformList->GetNumberOfItems() - 1; transformIndex >= 0; --transformIndex)
1830 vtkAbstractTransform* singleTransformVtk = vtkAbstractTransform::SafeDownCast(transformList->GetItemAsObject(transformIndex));
1831 itk::Object::Pointer secondaryTransformItkTmp;
1835 itk::Object::Pointer singleTransformItk =
CreateITKTransformFromVTK(loggerObject, singleTransformVtk, secondaryTransformItkTmp,
false);
1836 if (secondaryTransformItkTmp.IsNotNull())
1838 vtkErrorWithObjectMacro(loggerObject,
1839 "vtkITKTransformConverter::CreateITKTransformFromVTK failed:"
1840 " composite transforms cannot contain legacy transforms (that contains secondary transforms)."
1841 " Do not harden transforms on legacy ITK transforms to avoid this error.");
1845 if (singleTransformItk.IsNull()
1846 || std::string(singleTransformItk->GetNameOfClass()).find(
"Transform") == std::string::npos)
1848 vtkErrorWithObjectMacro(loggerObject,
1849 "vtkITKTransformConverter::CreateITKTransformFromVTK failed:"
1850 " invalid element found while trying to create a composite transform");
1853 CompositeTransformType::TransformType::Pointer singleTransformItkTypeChecked =
static_cast<CompositeTransformType::TransformType*
>(singleTransformItk.GetPointer());
1854 compositeTransformItk->AddTransform(singleTransformItkTypeChecked.GetPointer());
1856 return primaryTransformItk;