From ad64423b48f19e9d130cfa3b8ef4844af8423c49 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Fri, 10 Dec 2021 17:36:00 +0100 Subject: [PATCH 1/2] ENH: Add TransformedPointLimitedEulerSameAsUnlimitedEuler3D unit test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests that the new limited Euler transform by Žiga Špiclin yields the same point-to-point transformation as the unlimited Euler transform, when there is no limit specified. --- Common/GTesting/elxTransformIOGTest.cxx | 38 +++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Common/GTesting/elxTransformIOGTest.cxx b/Common/GTesting/elxTransformIOGTest.cxx index f53495d44..212857808 100644 --- a/Common/GTesting/elxTransformIOGTest.cxx +++ b/Common/GTesting/elxTransformIOGTest.cxx @@ -46,6 +46,8 @@ #include "TranslationTransform/elxTranslationTransform.h" #include "WeightedCombinationTransform/elxWeightedCombinationTransform.h" +#include "itkAdvancedLimitedEuler3DTransform.h" + #include #include #include @@ -972,3 +974,39 @@ GTEST_TEST(Transform, TransformedPointSameAsITKBSpline3D) Expect_elx_TransformPoint_yields_same_point_as_ITK(itkTransform); } + + +// Tests that the limited Euler transform yields the same point-to-point transformation as the unlimited Euler +// transform, when there is no limit specified. +GTEST_TEST(Transform, TransformedPointLimitedEulerSameAsUnlimitedEuler3D) +{ + std::mt19937 randomNumberEngine; + + // Generated another pseudo-random floating point number with each call. + const auto getRandomNumber = [&randomNumberEngine] { + const std::uniform_real_distribution<> distribution{ -1.0, 1.0 }; + return distribution(randomNumberEngine); + }; + + for (const bool computeZYX : { false, true }) + { + const auto unlimitedTransform = CheckNew>(); + unlimitedTransform->SetCenter(MakePoint(getRandomNumber(), getRandomNumber(), getRandomNumber())); + unlimitedTransform->SetComputeZYX(computeZYX); + unlimitedTransform->SetTranslation(MakeVector(getRandomNumber(), getRandomNumber(), getRandomNumber())); + unlimitedTransform->SetRotation(getRandomNumber(), getRandomNumber(), getRandomNumber()); + + const auto limitedTransform = CheckNew>(); + + // Copy all the relevant properties from the "unlimited" to the "limited" Euler transform. + limitedTransform->SetCenter(unlimitedTransform->GetCenter()); + limitedTransform->SetComputeZYX(unlimitedTransform->GetComputeZYX()); + limitedTransform->SetTranslation(unlimitedTransform->GetTranslation()); + limitedTransform->SetRotation( + unlimitedTransform->GetAngleX(), unlimitedTransform->GetAngleY(), unlimitedTransform->GetAngleZ()); + + const auto inputPoint = MakePoint(getRandomNumber(), getRandomNumber(), getRandomNumber()); + + EXPECT_EQ(limitedTransform->TransformPoint(inputPoint), unlimitedTransform->TransformPoint(inputPoint)); + } +} From c138ff63a403e99bb4a4285da19178ad241fba89 Mon Sep 17 00:00:00 2001 From: Niels Dekker Date: Sat, 11 Dec 2021 13:25:51 +0100 Subject: [PATCH 2/2] ENH: Add TransformedImageLimitedEulerSameAsUnlimitedEuler3D unit test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests that the new limited Euler transform by Žiga Špiclin yields the same image-to-image transformation as the unlimited Euler transform, when there is no limit specified. --- .../GTesting/itkTransformixFilterGTest.cxx | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/Core/Main/GTesting/itkTransformixFilterGTest.cxx b/Core/Main/GTesting/itkTransformixFilterGTest.cxx index 91cb520fb..af8adbd49 100644 --- a/Core/Main/GTesting/itkTransformixFilterGTest.cxx +++ b/Core/Main/GTesting/itkTransformixFilterGTest.cxx @@ -26,6 +26,9 @@ #include "elxDefaultConstructibleSubclass.h" #include "GTesting/elxGTestUtilities.h" +#include "itkAdvancedEuler3DTransform.h" +#include "itkAdvancedLimitedEuler3DTransform.h" + // ITK header files: #include #include @@ -689,3 +692,72 @@ GTEST_TEST(itkTransformixFilter, CombineTranslationAndScale) EXPECT_EQ(DerefSmartPointer(transformixOutput), *(CreateResampleImageFilter(*inputImage, scaleAndTranslationTransform)->GetOutput())); } + + +// Tests that the limited Euler transform yields the same image-to-image transformation as the unlimited Euler +// transform, when there is no limit specified. +GTEST_TEST(itkTransformixFilter, TransformedImageLimitedEulerSameAsUnlimitedEuler3D) +{ + enum + { + ImageDimension = 3 + }; + using TPixel = float; + using ImageType = itk::Image; + + const auto image = CreateImageFilledWithSequenceOfNaturalNumbers({ 7, 8, 9 }); + + const auto transformImage = [&image](const char * const transformName, + const auto & transform) -> itk::SmartPointer { + const auto filter = CheckNew>>(); + + const auto & transformParameters = transform.GetParameters(); + + filter->SetMovingImage(image); + + filter->SetTransformParameterObject( + CreateParameterObject({ // Parameters in alphabetic order: + { "CenterOfRotationPoint", elx::Conversion::ToVectorOfStrings(transform.GetCenter()) }, + { "Direction", CreateDefaultDirectionParameterValues() }, + { "Index", ParameterValuesType(ImageDimension, "0") }, + { "NumberOfParameters", { std::to_string(transformParameters.size()) } }, + { "Origin", ParameterValuesType(ImageDimension, "0") }, + { "ResampleInterpolator", { "FinalLinearInterpolator" } }, + { "Size", ConvertToParameterValues(image->GetRequestedRegion().GetSize()) }, + { "Transform", ParameterValuesType{ transformName } }, + { "TransformParameters", elx::Conversion::ToVectorOfStrings(transformParameters) }, + { "Spacing", ParameterValuesType(ImageDimension, "1") } })); + filter->Update(); + return filter->GetOutput(); + }; + + std::mt19937 randomNumberEngine; + + // Generated another pseudo-random floating point number with each call. + const auto getRandomNumber = [&randomNumberEngine] { + const std::uniform_real_distribution<> distribution{ -1.0, 1.0 }; + return distribution(randomNumberEngine); + }; + + for (const bool computeZYX : { false, true }) + { + const auto unlimitedTransform = CheckNew>(); + unlimitedTransform->SetCenter(MakePoint(getRandomNumber(), getRandomNumber(), getRandomNumber())); + unlimitedTransform->SetComputeZYX(computeZYX); + unlimitedTransform->SetTranslation(MakeVector(getRandomNumber(), getRandomNumber(), getRandomNumber())); + unlimitedTransform->SetRotation(getRandomNumber(), getRandomNumber(), getRandomNumber()); + + const auto limitedTransform = CheckNew>(); + + // Copy all the relevant properties from the "unlimited" to the "limited" Euler transform. + limitedTransform->SetCenter(unlimitedTransform->GetCenter()); + limitedTransform->SetComputeZYX(unlimitedTransform->GetComputeZYX()); + limitedTransform->SetTranslation(unlimitedTransform->GetTranslation()); + limitedTransform->SetRotation( + unlimitedTransform->GetAngleX(), unlimitedTransform->GetAngleY(), unlimitedTransform->GetAngleZ()); + + const auto unlimitedTransformedImage = transformImage("EulerTransform", *unlimitedTransform); + const auto limitedTransformedImage = transformImage("LimitedEulerTransform", *limitedTransform); + EXPECT_EQ(DerefSmartPointer(limitedTransformedImage), DerefSmartPointer(unlimitedTransformedImage)); + } +}