Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkPlaneGeometryTest.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkAffineTransform3D.h"
14 #include "mitkBaseGeometry.h"
15 #include "mitkGeometry3D.h"
16 #include "mitkInteractionConst.h"
17 #include "mitkLine.h"
18 #include "mitkPlaneGeometry.h"
19 #include "mitkRotationOperation.h"
20 #include "mitkSlicedGeometry3D.h"
22 
23 #include <mitkTestFixture.h>
24 #include <mitkTestingMacros.h>
25 
26 #include <vnl/vnl_quaternion.h>
27 #include <vnl/vnl_quaternion.hxx>
28 
29 #include <fstream>
30 #include <iomanip>
31 #include <mitkIOUtil.h>
32 #include <mitkImage.h>
33 
34 static const mitk::ScalarType testEps = 1E-9; // the epsilon used in this test == at least float precision.
35 
36 class mitkPlaneGeometryTestSuite : public mitk::TestFixture
37 {
38  CPPUNIT_TEST_SUITE(mitkPlaneGeometryTestSuite);
39  MITK_TEST(TestInitializeStandardPlane);
40  MITK_TEST(TestProjectPointOntoPlane);
41  MITK_TEST(TestPlaneGeometryCloning);
42  MITK_TEST(TestInheritance);
43  MITK_TEST(TestSetExtendInMM);
44  MITK_TEST(TestRotate);
45  MITK_TEST(TestClone);
46  MITK_TEST(TestPlaneComparison);
47  MITK_TEST(TestAxialInitialization);
48  MITK_TEST(TestFrontalInitialization);
49  MITK_TEST(TestSaggitalInitialization);
50  MITK_TEST(TestLefthandedCoordinateSystem);
51  MITK_TEST(TestDominantAxesError);
52  MITK_TEST(TestCheckRotationMatrix);
53 
54  // Currently commented out, see See bug 15990
55  // MITK_TEST(testPlaneGeometryInitializeOrder);
56  MITK_TEST(TestIntersectionPoint);
57  MITK_TEST(TestCase1210);
58 
59  CPPUNIT_TEST_SUITE_END();
60 
61 private:
62  // private test members that are initialized by setUp()
63  mitk::PlaneGeometry::Pointer planegeometry;
64  mitk::Point3D origin;
65  mitk::Vector3D right, bottom, normal, spacing;
66  mitk::ScalarType width, height;
67  mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
68 
69 public:
70  void setUp() override
71  {
72  planegeometry = mitk::PlaneGeometry::New();
73  width = 100;
74  widthInMM = width;
75  height = 200;
76  heightInMM = height;
77  thicknessInMM = 1.0;
78  mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
79  mitk::FillVector3D(right, widthInMM, 0, 0);
80  mitk::FillVector3D(bottom, 0, heightInMM, 0);
81  mitk::FillVector3D(normal, 0, 0, thicknessInMM);
82  mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
83 
84  planegeometry->InitializeStandardPlane(right, bottom);
85  planegeometry->SetOrigin(origin);
86  planegeometry->SetSpacing(spacing);
87  }
88 
89  void tearDown() override {}
90  // This test verifies inheritance behaviour, this test will fail if the behaviour changes in the future
91  void TestInheritance()
92  {
94  mitk::Geometry3D::Pointer g3d = dynamic_cast<mitk::Geometry3D *>(plane.GetPointer());
95  CPPUNIT_ASSERT_MESSAGE("Planegeometry should not be castable to Geometry 3D", g3d.IsNull());
96 
97  mitk::BaseGeometry::Pointer base = dynamic_cast<mitk::BaseGeometry *>(plane.GetPointer());
98  CPPUNIT_ASSERT_MESSAGE("Planegeometry should be castable to BaseGeometry", base.IsNotNull());
99 
100  g3d = mitk::Geometry3D::New();
101  base = dynamic_cast<mitk::BaseGeometry *>(g3d.GetPointer());
102  CPPUNIT_ASSERT_MESSAGE("Geometry3D should be castable to BaseGeometry", base.IsNotNull());
103 
105  g3d = dynamic_cast<mitk::Geometry3D *>(sliced.GetPointer());
106  CPPUNIT_ASSERT_MESSAGE("SlicedGeometry3D should not be castable to Geometry3D", g3d.IsNull());
107 
109  plane = dynamic_cast<mitk::PlaneGeometry *>(thin.GetPointer());
110  CPPUNIT_ASSERT_MESSAGE("AbstractTransformGeometry should be castable to PlaneGeometry", plane.IsNotNull());
111 
112  plane = mitk::PlaneGeometry::New();
113  mitk::AbstractTransformGeometry::Pointer atg = dynamic_cast<mitk::AbstractTransformGeometry *>(plane.GetPointer());
114  CPPUNIT_ASSERT_MESSAGE("PlaneGeometry should not be castable to AbstractTransofrmGeometry", atg.IsNull());
115  }
116 
117  void TestDominantAxesError()
118  {
119  auto image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("NotQuiteARotationMatrix.nrrd"));
120  auto matrix = image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().transpose();
121  std::vector< int > axes = mitk::PlaneGeometry::CalculateDominantAxes(matrix);
122  CPPUNIT_ASSERT_MESSAGE("Domiant axes cannot be determined in this dataset. Output should be default ordering.", axes.at(0)==0 && axes.at(1)==1 && axes.at(2)==2);
123  }
124 
125  void TestCheckRotationMatrix()
126  {
127  auto image = mitk::IOUtil::Load<mitk::Image>(GetTestDataFilePath("NotQuiteARotationMatrix.nrrd"));
128  bool is_rotation = mitk::PlaneGeometry::CheckRotationMatrix(image->GetGeometry()->GetIndexToWorldTransform());
129  CPPUNIT_ASSERT_MESSAGE("Since the test data matrix is not quite a rotation matrix, this should be detected.", !is_rotation);
130  }
131 
132  void TestLefthandedCoordinateSystem()
133  {
141  planegeometry = mitk::PlaneGeometry::New();
142  width = 100;
143  widthInMM = 5;
144  height = 200;
145  heightInMM = 3;
146  thicknessInMM = 1.0;
147  mitk::FillVector3D(right, widthInMM, 0, 0);
148  mitk::FillVector3D(bottom, 0, heightInMM, 0);
149  // This one negative sign results in lefthanded coordinate orientation and det(matrix) < 0.
150  mitk::FillVector3D(normal, 0, 0, -thicknessInMM);
151 
152  mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
153 
154  mitk::AffineTransform3D::MatrixType matrix;
155  mitk::AffineTransform3D::MatrixType::InternalMatrixType &vnl_matrix = matrix.GetVnlMatrix();
156 
157  vnl_matrix.set_column(0, right);
158  vnl_matrix.set_column(1, bottom);
159  vnl_matrix.set_column(2, normal);
160 
161  // making sure that we didn't screw up this special test case or else fail deadly:
162  assert(vnl_determinant(vnl_matrix) < 0.0);
163 
164  transform->SetIdentity();
165  transform->SetMatrix(matrix);
166 
167  planegeometry->InitializeStandardPlane(width, height, transform); // Crux of the matter.
168  CPPUNIT_ASSERT_MESSAGE(
169  "Testing if IndexToWorldMatrix is correct after InitializeStandardPlane( width, height, transform ) ",
170  mitk::MatrixEqualElementWise(planegeometry->GetIndexToWorldTransform()->GetMatrix(), matrix));
171 
172  mitk::Point3D p_index;
173  p_index[0] = 10.;
174  p_index[1] = 10.;
175  p_index[2] = 0.;
176  mitk::Point3D p_world;
177  mitk::Point3D p_expectedResult;
178  p_expectedResult[0] = 50.;
179  p_expectedResult[1] = 30.;
180  p_expectedResult[2] = 0.;
181 
182  ((mitk::BaseGeometry::Pointer)planegeometry)->IndexToWorld(p_index, p_world); // Crux of the matter.
183  CPPUNIT_ASSERT_MESSAGE("Testing if IndexToWorld(a,b) function works correctly with lefthanded matrix ",
184  mitk::Equal(p_world, p_expectedResult, testEps));
185  }
186 
187  // See bug 1210
188  // Test does not use standard Parameters
189  void TestCase1210()
190  {
192 
193  mitk::Point3D origin;
194  mitk::Vector3D right, down, spacing;
195 
196  mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
197  mitk::FillVector3D(right, 1.015625, 1.015625, 1.1999969482421875);
198 
199  mitk::FillVector3D(down, 1.4012984643248170709237295832899161312802619418765e-45, 0, 0);
200  mitk::FillVector3D(spacing,
201  0,
202  1.4713633875410579244699160624544119378442750389703e-43,
203  9.2806360452222355258639080851310540729807238879469e-32);
204 
205  std::cout << "Testing InitializeStandardPlane(rightVector, downVector, spacing = nullptr): " << std::endl;
206  CPPUNIT_ASSERT_NO_THROW(planegeometry->InitializeStandardPlane(right, down, &spacing));
207  /*
208  std::cout << "Testing width, height and thickness (in units): ";
209  if((mitk::Equal(planegeometry->GetExtent(0),width)==false) ||
210  (mitk::Equal(planegeometry->GetExtent(1),height)==false) ||
211  (mitk::Equal(planegeometry->GetExtent(2),1)==false)
212  )
213  {
214  std::cout<<"[FAILED]"<<std::endl;
215  return EXIT_FAILURE;
216  }
217  std::cout<<"[PASSED]"<<std::endl;
218 
219  std::cout << "Testing width, height and thickness (in mm): ";
220  if((mitk::Equal(planegeometry->GetExtentInMM(0),widthInMM)==false) ||
221  (mitk::Equal(planegeometry->GetExtentInMM(1),heightInMM)==false) ||
222  (mitk::Equal(planegeometry->GetExtentInMM(2),thicknessInMM)==false)
223  )
224  {
225  std::cout<<"[FAILED]"<<std::endl;
226  return EXIT_FAILURE;
227  }
228  */
229  }
230 
247  // Test does not use standard Parameters
248  void TestIntersectionPoint()
249  {
250  // init plane with its parameter
252 
253  mitk::Point3D origin;
254  origin[0] = 0.0;
255  origin[1] = 2.0;
256  origin[2] = 0.0;
257 
258  mitk::Vector3D normal;
259  normal[0] = 0.0;
260  normal[1] = 1.0;
261  normal[2] = 0.0;
262 
263  myPlaneGeometry->InitializePlane(origin, normal);
264 
265  // generate points and line for intersection testing
266  // point distance of given line > 1
267  mitk::Point3D pointP1;
268  pointP1[0] = 2.0;
269  pointP1[1] = 1.0;
270  pointP1[2] = 0.0;
271 
272  mitk::Point3D pointP2;
273  pointP2[0] = 2.0;
274  pointP2[1] = 4.0;
275  pointP2[2] = 0.0;
276 
277  mitk::Vector3D lineDirection;
278  lineDirection[0] = pointP2[0] - pointP1[0];
279  lineDirection[1] = pointP2[1] - pointP1[1];
280  lineDirection[2] = pointP2[2] - pointP1[2];
281 
282  mitk::Line3D xingline(pointP1, lineDirection);
283  mitk::Point3D calcXingPoint;
284  myPlaneGeometry->IntersectionPoint(xingline, calcXingPoint);
285 
286  // point distance of given line < 1
287  mitk::Point3D pointP3;
288  pointP3[0] = 2.0;
289  pointP3[1] = 2.2;
290  pointP3[2] = 0.0;
291 
292  mitk::Point3D pointP4;
293  pointP4[0] = 2.0;
294  pointP4[1] = 1.7;
295  pointP4[2] = 0.0;
296 
297  mitk::Vector3D lineDirection2;
298  lineDirection2[0] = pointP4[0] - pointP3[0];
299  lineDirection2[1] = pointP4[1] - pointP3[1];
300  lineDirection2[2] = pointP4[2] - pointP3[2];
301 
302  mitk::Line3D xingline2(pointP3, lineDirection2);
303  mitk::Point3D calcXingPoint2;
304  myPlaneGeometry->IntersectionPoint(xingline2, calcXingPoint2);
305 
306  // intersection points must be the same
307  CPPUNIT_ASSERT_MESSAGE("Failed to calculate Intersection Point", calcXingPoint == calcXingPoint2);
308  }
309 
315  // Test does not use standard Parameters
316  void TestProjectPointOntoPlane()
317  {
319 
320  // create normal
321  mitk::Vector3D normal;
322  normal[0] = 0.0;
323  normal[1] = 0.0;
324  normal[2] = 1.0;
325 
326  // create origin
327  mitk::Point3D origin;
328  origin[0] = -27.582859;
329  origin[1] = 50;
330  origin[2] = 200.27742;
331 
332  // initialize plane geometry
333  myPlaneGeometry->InitializePlane(origin, normal);
334 
335  // output to descripe the test
336  std::cout << "Testing PlaneGeometry according to bug #3409" << std::endl;
337  std::cout << "Our normal is: " << normal << std::endl;
338  std::cout << "So ALL projected points should have exactly the same z-value!" << std::endl;
339 
340  // create a number of points
341  mitk::Point3D myPoints[5];
342  myPoints[0][0] = -27.582859;
343  myPoints[0][1] = 50.00;
344  myPoints[0][2] = 200.27742;
345 
346  myPoints[1][0] = -26.58662;
347  myPoints[1][1] = 50.00;
348  myPoints[1][2] = 200.19026;
349 
350  myPoints[2][0] = -26.58662;
351  myPoints[2][1] = 50.00;
352  myPoints[2][2] = 200.33124;
353 
354  myPoints[3][0] = 104.58662;
355  myPoints[3][1] = 452.12313;
356  myPoints[3][2] = 866.41236;
357 
358  myPoints[4][0] = -207.58662;
359  myPoints[4][1] = 312.00;
360  myPoints[4][2] = -300.12346;
361 
362  // project points onto plane
363  mitk::Point3D myProjectedPoints[5];
364  for (unsigned int i = 0; i < 5; ++i)
365  {
366  myProjectedPoints[i] = myPlaneGeometry->ProjectPointOntoPlane(myPoints[i]);
367  }
368 
369  // compare z-values with z-value of plane (should be equal)
370  bool allPointsOnPlane = true;
371  for (auto &myProjectedPoint : myProjectedPoints)
372  {
373  if (fabs(myProjectedPoint[2] - origin[2]) > mitk::sqrteps)
374  {
375  allPointsOnPlane = false;
376  }
377  }
378  CPPUNIT_ASSERT_MESSAGE("All points lie not on the same plane", allPointsOnPlane);
379  }
380 
381  void TestPlaneGeometryCloning()
382  {
384 
385  try
386  {
387  mitk::PlaneGeometry::Pointer clone = geometry2D->Clone();
388  itk::Matrix<mitk::ScalarType, 3, 3> matrix = clone->GetIndexToWorldTransform()->GetMatrix();
389  CPPUNIT_ASSERT_MESSAGE("Test if matrix element exists...", matrix[0][0] == 31);
390 
391  double origin = geometry2D->GetOrigin()[0];
392  CPPUNIT_ASSERT_MESSAGE("First Point of origin as expected...", mitk::Equal(origin, 8));
393 
394  double spacing = geometry2D->GetSpacing()[0];
395  CPPUNIT_ASSERT_MESSAGE("First Point of spacing as expected...", mitk::Equal(spacing, 31));
396  }
397  catch (...)
398  {
399  CPPUNIT_FAIL("Error during access on a member of cloned geometry");
400  }
401  // direction [row] [coloum]
402  MITK_TEST_OUTPUT(<< "Casting a rotated 2D ITK Image to a MITK Image and check if Geometry is still same");
403  }
404 
405  void TestPlaneGeometryInitializeOrder()
406  {
407  mitk::Vector3D mySpacing;
408  mySpacing[0] = 31;
409  mySpacing[1] = 0.1;
410  mySpacing[2] = 5.4;
411  mitk::Point3D myOrigin;
412  myOrigin[0] = 8;
413  myOrigin[1] = 9;
414  myOrigin[2] = 10;
415  mitk::AffineTransform3D::Pointer myTransform = mitk::AffineTransform3D::New();
416  itk::Matrix<mitk::ScalarType, 3, 3> transMatrix;
417  transMatrix.Fill(0);
418  transMatrix[0][0] = 1;
419  transMatrix[1][1] = 2;
420  transMatrix[2][2] = 4;
421 
422  myTransform->SetMatrix(transMatrix);
423 
425  geometry2D1->SetIndexToWorldTransform(myTransform);
426  geometry2D1->SetSpacing(mySpacing);
427  geometry2D1->SetOrigin(myOrigin);
428 
430  geometry2D2->SetSpacing(mySpacing);
431  geometry2D2->SetOrigin(myOrigin);
432  geometry2D2->SetIndexToWorldTransform(myTransform);
433 
435  geometry2D3->SetIndexToWorldTransform(myTransform);
436  geometry2D3->SetSpacing(mySpacing);
437  geometry2D3->SetOrigin(myOrigin);
438  geometry2D3->SetIndexToWorldTransform(myTransform);
439 
440  CPPUNIT_ASSERT_MESSAGE("Origin of Geometry 1 matches that of Geometry 2.",
441  mitk::Equal(geometry2D1->GetOrigin(), geometry2D2->GetOrigin()));
442  CPPUNIT_ASSERT_MESSAGE("Origin of Geometry 1 match those of Geometry 3.",
443  mitk::Equal(geometry2D1->GetOrigin(), geometry2D3->GetOrigin()));
444  CPPUNIT_ASSERT_MESSAGE("Origin of Geometry 2 match those of Geometry 3.",
445  mitk::Equal(geometry2D2->GetOrigin(), geometry2D3->GetOrigin()));
446 
447  CPPUNIT_ASSERT_MESSAGE("Spacing of Geometry 1 match those of Geometry 2.",
448  mitk::Equal(geometry2D1->GetSpacing(), geometry2D2->GetSpacing()));
449  CPPUNIT_ASSERT_MESSAGE("Spacing of Geometry 1 match those of Geometry 3.",
450  mitk::Equal(geometry2D1->GetSpacing(), geometry2D3->GetSpacing()));
451  CPPUNIT_ASSERT_MESSAGE("Spacing of Geometry 2 match those of Geometry 3.",
452  mitk::Equal(geometry2D2->GetSpacing(), geometry2D3->GetSpacing()));
453 
454  CPPUNIT_ASSERT_MESSAGE("Transformation of Geometry 1 match those of Geometry 2.",
455  compareMatrix(geometry2D1->GetIndexToWorldTransform()->GetMatrix(),
456  geometry2D2->GetIndexToWorldTransform()->GetMatrix()));
457  CPPUNIT_ASSERT_MESSAGE("Transformation of Geometry 1 match those of Geometry 3.",
458  compareMatrix(geometry2D1->GetIndexToWorldTransform()->GetMatrix(),
459  geometry2D3->GetIndexToWorldTransform()->GetMatrix()));
460  CPPUNIT_ASSERT_MESSAGE("Transformation of Geometry 2 match those of Geometry 3.",
461  compareMatrix(geometry2D2->GetIndexToWorldTransform()->GetMatrix(),
462  geometry2D3->GetIndexToWorldTransform()->GetMatrix()));
463  }
464 
465  void TestInitializeStandardPlane()
466  {
467  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: width",
468  mitk::Equal(planegeometry->GetExtent(0), width, testEps));
469  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: height",
470  mitk::Equal(planegeometry->GetExtent(1), height, testEps));
471  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: depth",
472  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
473 
474  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: width in mm",
475  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
476  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: heght in mm",
477  mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps));
478  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: depth in mm",
479  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
480 
481  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: AxisVectorRight",
482  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
483  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: AxisVectorBottom",
484  mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps));
485  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with default Spacing: AxisVectorNormal",
486  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
487 
488  mitk::Vector3D spacing;
489  thicknessInMM = 1.5;
490  normal.Normalize();
491  normal *= thicknessInMM;
492  mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
493  planegeometry->InitializeStandardPlane(right.GetVnlVector(), bottom.GetVnlVector(), &spacing);
494 
495  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: width",
496  mitk::Equal(planegeometry->GetExtent(0), width, testEps));
497  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: height",
498  mitk::Equal(planegeometry->GetExtent(1), height, testEps));
499  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: depth",
500  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
501 
502  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: width in mm",
503  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
504  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: height in mm",
505  mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps));
506  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: depth in mm",
507  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
508 
509  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: AxisVectorRight",
510  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
511  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: AxisVectorBottom",
512  mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps));
513  CPPUNIT_ASSERT_MESSAGE("Testing correct Standard Plane initialization with custom Spacing: AxisVectorNormal",
514  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
515 
516  ;
517  }
518 
519  void TestSetExtendInMM()
520  {
521  normal.Normalize();
522  normal *= thicknessInMM;
523  planegeometry->SetExtentInMM(2, thicknessInMM);
524  CPPUNIT_ASSERT_MESSAGE("Testing SetExtentInMM(2, ...), querying by GetExtentInMM(2): ",
525  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
526  CPPUNIT_ASSERT_MESSAGE("Testing SetExtentInMM(2, ...), querying by GetAxisVector(2) and comparing to normal: ",
527  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
528 
529  planegeometry->SetOrigin(origin);
530  CPPUNIT_ASSERT_MESSAGE("Testing SetOrigin", mitk::Equal(planegeometry->GetOrigin(), origin, testEps));
531 
532  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() after SetOrigin: Right",
533  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
534  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() after SetOrigin: Bottom",
535  mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps));
536  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() after SetOrigin: Normal",
537  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
538 
539  mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
540  }
541 
542  void TestRotate()
543  {
544  // Changing the IndexToWorldTransform to a rotated version by SetIndexToWorldTransform() (keep origin):
545  mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
546  mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
547  vnlmatrix = planegeometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
548  mitk::VnlVector axis(3);
549  mitk::FillVector3D(axis, 1.0, 1.0, 1.0);
550  axis.normalize();
551  vnl_quaternion<mitk::ScalarType> rotation(axis, 0.223);
552  vnlmatrix = rotation.rotation_matrix_transpose() * vnlmatrix;
553  mitk::Matrix3D matrix;
554  matrix = vnlmatrix;
555  transform->SetMatrix(matrix);
556  transform->SetOffset(planegeometry->GetIndexToWorldTransform()->GetOffset());
557 
558  right.SetVnlVector(rotation.rotation_matrix_transpose() * right.GetVnlVector());
559  bottom.SetVnlVector(rotation.rotation_matrix_transpose() * bottom.GetVnlVector());
560  normal.SetVnlVector(rotation.rotation_matrix_transpose() * normal.GetVnlVector());
561  planegeometry->SetIndexToWorldTransform(transform);
562 
563  // The origin changed,because m_Origin=m_IndexToWorldTransform->GetOffset()+GetAxisVector(2)*0.5
564  // and the AxisVector changes due to the rotation. In other words: the rotation was done around
565  // the corner of the box, not around the planes origin. Now change it to a rotation around
566  // the origin, simply by re-setting the origin to the original one:
567  planegeometry->SetOrigin(origin);
568 
569  CPPUNIT_ASSERT_MESSAGE("Testing whether SetIndexToWorldTransform kept origin: ",
570  mitk::Equal(planegeometry->GetOrigin(), origin, testEps));
571 
572  mitk::Point2D point;
573  point[0] = 4;
574  point[1] = 3;
575  mitk::Point2D dummy;
576  planegeometry->WorldToIndex(point, dummy);
577  planegeometry->IndexToWorld(dummy, dummy);
578  CPPUNIT_ASSERT_MESSAGE("Testing consistency of index and world coordinates.", dummy == point);
579 
580  CPPUNIT_ASSERT_MESSAGE("Testing width of rotated version: ",
581  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
582  CPPUNIT_ASSERT_MESSAGE("Testing height of rotated version: ",
583  mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps));
584  CPPUNIT_ASSERT_MESSAGE("Testing thickness of rotated version: ",
585  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
586 
587  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of rotated version: right ",
588  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
589  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of rotated version: bottom",
590  mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps));
591  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of rotated version: normal",
592  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
593 
594  CPPUNIT_ASSERT_MESSAGE(
595  "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ",
596  mitk::Equal(planegeometry->GetAxisVector(0).GetNorm(), planegeometry->GetExtentInMM(0), testEps));
597  CPPUNIT_ASSERT_MESSAGE(
598  "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ",
599  mitk::Equal(planegeometry->GetAxisVector(1).GetNorm(), planegeometry->GetExtentInMM(1), testEps));
600  CPPUNIT_ASSERT_MESSAGE(
601  "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ",
602  mitk::Equal(planegeometry->GetAxisVector(2).GetNorm(), planegeometry->GetExtentInMM(2), testEps));
603 
604  mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
605 
606  width *= 2;
607  height *= 3;
608  planegeometry->SetSizeInUnits(width, height);
609  CPPUNIT_ASSERT_MESSAGE("Testing SetSizeInUnits() of rotated version: ",
610  mitk::Equal(planegeometry->GetExtent(0), width, testEps));
611  CPPUNIT_ASSERT_MESSAGE("Testing SetSizeInUnits() of rotated version: ",
612  mitk::Equal(planegeometry->GetExtent(1), height, testEps));
613  CPPUNIT_ASSERT_MESSAGE("Testing SetSizeInUnits() of rotated version: ",
614  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
615 
616  CPPUNIT_ASSERT_MESSAGE("Testing width (in mm) of version with changed size in units: ",
617  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
618  CPPUNIT_ASSERT_MESSAGE("Testing height (in mm) of version with changed size in units: ",
619  mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps));
620  CPPUNIT_ASSERT_MESSAGE("Testing thickness (in mm) of version with changed size in units: ",
621  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
622 
623  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of version with changed size in units: right ",
624  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
625  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of version with changed size in units: bottom",
626  mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps));
627  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of version with changed size in units: normal",
628  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
629 
630  CPPUNIT_ASSERT_MESSAGE(
631  "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ",
632  mitk::Equal(planegeometry->GetAxisVector(0).GetNorm(), planegeometry->GetExtentInMM(0), testEps));
633  CPPUNIT_ASSERT_MESSAGE(
634  "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ",
635  mitk::Equal(planegeometry->GetAxisVector(1).GetNorm(), planegeometry->GetExtentInMM(1), testEps));
636  CPPUNIT_ASSERT_MESSAGE(
637  "Testing GetAxisVector(direction).GetNorm() != planegeometry->GetExtentInMM(direction) of rotated version: ",
638  mitk::Equal(planegeometry->GetAxisVector(2).GetNorm(), planegeometry->GetExtentInMM(2), testEps));
639 
640  mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
641  }
642 
643  void TestClone()
644  {
645  mitk::PlaneGeometry::Pointer clonedplanegeometry =
646  dynamic_cast<mitk::PlaneGeometry *>(planegeometry->Clone().GetPointer());
647  // Cave: Statement below is negated!
648  CPPUNIT_ASSERT_MESSAGE("Testing Clone(): ",
649  !((clonedplanegeometry.IsNull()) || (clonedplanegeometry->GetReferenceCount() != 1)));
650  CPPUNIT_ASSERT_MESSAGE("Testing origin of cloned version: ",
651  mitk::Equal(clonedplanegeometry->GetOrigin(), origin, testEps));
652 
653  CPPUNIT_ASSERT_MESSAGE("Testing width (in units) of cloned version: ",
654  mitk::Equal(clonedplanegeometry->GetExtent(0), width, testEps));
655  CPPUNIT_ASSERT_MESSAGE("Testing height (in units) of cloned version: ",
656  mitk::Equal(clonedplanegeometry->GetExtent(1), height, testEps));
657  CPPUNIT_ASSERT_MESSAGE("Testing extent (in units) of cloned version: ",
658  mitk::Equal(clonedplanegeometry->GetExtent(2), 1, testEps));
659 
660  CPPUNIT_ASSERT_MESSAGE("Testing width (in mm) of cloned version: ",
661  mitk::Equal(clonedplanegeometry->GetExtentInMM(0), widthInMM, testEps));
662  CPPUNIT_ASSERT_MESSAGE("Testing height (in mm) of cloned version: ",
663  mitk::Equal(clonedplanegeometry->GetExtentInMM(1), heightInMM, testEps));
664  CPPUNIT_ASSERT_MESSAGE("Testing thickness (in mm) of cloned version: ",
665  mitk::Equal(clonedplanegeometry->GetExtentInMM(2), thicknessInMM, testEps));
666 
667  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of cloned version: right",
668  mitk::Equal(clonedplanegeometry->GetAxisVector(0), right, testEps));
669  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of cloned version: bottom",
670  mitk::Equal(clonedplanegeometry->GetAxisVector(1), bottom, testEps));
671  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of cloned version: normal",
672  mitk::Equal(clonedplanegeometry->GetAxisVector(2), normal, testEps));
673 
674  mappingTests2D(clonedplanegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
675  }
676 
677  void TestSaggitalInitialization()
678  {
679  mitk::Point3D cornerpoint0 = planegeometry->GetCornerPoint(0);
680  mitk::PlaneGeometry::Pointer clonedplanegeometry = planegeometry->Clone();
681 
682  // Testing InitializeStandardPlane(clonedplanegeometry, planeorientation = Sagittal, zPosition = 0, frontside=true):
683  planegeometry->InitializeStandardPlane(clonedplanegeometry, mitk::PlaneGeometry::Sagittal);
684 
685  mitk::Vector3D newright, newbottom, newnormal;
686  mitk::ScalarType newthicknessInMM;
687 
688  newright = bottom;
689  newthicknessInMM = widthInMM / width * 1.0; // extent in normal direction is 1;
690  newnormal = right;
691  newnormal.Normalize();
692  newnormal *= newthicknessInMM;
693  newbottom = normal;
694  newbottom.Normalize();
695  newbottom *= thicknessInMM;
696 
697  CPPUNIT_ASSERT_MESSAGE("Testing GetCornerPoint(0) of sagitally initialized version:",
698  mitk::Equal(planegeometry->GetCornerPoint(0), cornerpoint0, testEps));
699 
700  // ok, corner was fine, so we can dare to believe the origin is ok.
701  origin = planegeometry->GetOrigin();
702 
703  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in units) of sagitally initialized version: ",
704  mitk::Equal(planegeometry->GetExtent(0), height, testEps));
705  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in units) of sagitally initialized version: ",
706  mitk::Equal(planegeometry->GetExtent(1), 1, testEps));
707  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in units) of sagitally initialized version: ",
708  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
709 
710  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in mm) of sagitally initialized version: ",
711  mitk::Equal(planegeometry->GetExtentInMM(0), heightInMM, testEps));
712  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in mm) of sagitally initialized version: ",
713  mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps));
714  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in mm) of sagitally initialized version: ",
715  mitk::Equal(planegeometry->GetExtentInMM(2), newthicknessInMM, testEps));
716 
717  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of sagitally initialized version: ",
718  mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps));
719  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of sagitally initialized version: ",
720  mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps));
721  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of sagitally initialized version: ",
722  mitk::Equal(planegeometry->GetAxisVector(2), newnormal, testEps));
723 
724  mappingTests2D(planegeometry, height, 1, heightInMM, thicknessInMM, origin, newright, newbottom);
725 
726  // set origin back to the one of the axial slice:
727  origin = clonedplanegeometry->GetOrigin();
728  // Testing backside initialization: InitializeStandardPlane(clonedplanegeometry, planeorientation = Axial, zPosition
729  // = 0, frontside=false, rotated=true):
730  planegeometry->InitializeStandardPlane(clonedplanegeometry, mitk::PlaneGeometry::Axial, 0, false, true);
731  mitk::Point3D backsideorigin;
732  backsideorigin = origin + clonedplanegeometry->GetAxisVector(1); //+clonedplanegeometry->GetAxisVector(2);
733 
734  CPPUNIT_ASSERT_MESSAGE("Testing origin of backsidedly, axially initialized version: ",
735  mitk::Equal(planegeometry->GetOrigin(), backsideorigin, testEps));
736 
737  mitk::Point3D backsidecornerpoint0;
738  backsidecornerpoint0 =
739  cornerpoint0 + clonedplanegeometry->GetAxisVector(1); //+clonedplanegeometry->GetAxisVector(2);
740  CPPUNIT_ASSERT_MESSAGE("Testing GetCornerPoint(0) of sagitally initialized version: ",
741  mitk::Equal(planegeometry->GetCornerPoint(0), backsidecornerpoint0, testEps));
742 
743  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in units) of backsidedly, axially initialized version "
744  "(should be same as in mm due to unit spacing, except for thickness, which is always 1): ",
745  mitk::Equal(planegeometry->GetExtent(0), width, testEps));
746  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in units) of backsidedly, axially initialized version "
747  "(should be same as in mm due to unit spacing, except for thickness, which is always 1): ",
748  mitk::Equal(planegeometry->GetExtent(1), height, testEps));
749  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in units) of backsidedly, axially initialized version "
750  "(should be same as in mm due to unit spacing, except for thickness, which is always 1): ",
751  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
752 
753  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in mm) of backsidedly, axially initialized version: ",
754  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
755  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in mm) of backsidedly, axially initialized version: ",
756  mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps));
757  CPPUNIT_ASSERT_MESSAGE("Testing width, height and thickness (in mm) of backsidedly, axially initialized version: ",
758  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
759 
760  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of backsidedly, axially initialized version: ",
761  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
762  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of backsidedly, axially initialized version: ",
763  mitk::Equal(planegeometry->GetAxisVector(1), -bottom, testEps));
764  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of backsidedly, axially initialized version: ",
765  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps)); // T22254: Flipped sign
766 
767  mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, backsideorigin, right, -bottom);
768  }
769 
770  void TestFrontalInitialization()
771  {
772  mitk::Point3D cornerpoint0 = planegeometry->GetCornerPoint(0);
773 
774  mitk::PlaneGeometry::Pointer clonedplanegeometry =
775  dynamic_cast<mitk::PlaneGeometry *>(planegeometry->Clone().GetPointer());
776  //--------
777 
778  mitk::Vector3D newright, newbottom, newnormal;
779  mitk::ScalarType newthicknessInMM;
780 
781  // Testing InitializeStandardPlane(clonedplanegeometry, planeorientation = Frontal, zPosition = 0, frontside=true)
782  planegeometry->InitializeStandardPlane(clonedplanegeometry, mitk::PlaneGeometry::Frontal);
783  newright = right;
784  newbottom = normal;
785  newbottom.Normalize();
786  newbottom *= thicknessInMM;
787  newthicknessInMM = heightInMM / height * 1.0 /*extent in normal direction is 1*/;
788  newnormal = -bottom;
789  newnormal.Normalize();
790  newnormal *= newthicknessInMM;
791 
792  CPPUNIT_ASSERT_MESSAGE("Testing GetCornerPoint(0) of frontally initialized version: ",
793  mitk::Equal(planegeometry->GetCornerPoint(0), cornerpoint0, testEps));
794 
795  // ok, corner was fine, so we can dare to believe the origin is ok.
796  origin = planegeometry->GetOrigin();
797 
798  CPPUNIT_ASSERT_MESSAGE("Testing width (in units) of frontally initialized version: ",
799  mitk::Equal(planegeometry->GetExtent(0), width, testEps));
800  CPPUNIT_ASSERT_MESSAGE("Testing height (in units) of frontally initialized version: ",
801  mitk::Equal(planegeometry->GetExtent(1), 1, testEps));
802  CPPUNIT_ASSERT_MESSAGE("Testing thickness (in units) of frontally initialized version: ",
803  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
804 
805  CPPUNIT_ASSERT_MESSAGE("Testing width (in mm) of frontally initialized version: ",
806  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
807  CPPUNIT_ASSERT_MESSAGE("Testing height (in mm) of frontally initialized version: ",
808  mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps));
809  CPPUNIT_ASSERT_MESSAGE("Testing thickness (in mm) of frontally initialized version: ",
810  mitk::Equal(planegeometry->GetExtentInMM(2), newthicknessInMM, testEps));
811 
812  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of frontally initialized version: ",
813  mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps));
814  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of frontally initialized version: ",
815  mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps));
816  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of frontally initialized version: ",
817  mitk::Equal(planegeometry->GetAxisVector(2), -newnormal, testEps)); // T22254: Flipped sign
818 
819  mappingTests2D(planegeometry, width, 1, widthInMM, thicknessInMM, origin, newright, newbottom);
820 
821  // Changing plane to in-plane unit spacing using SetSizeInUnits:
822  planegeometry->SetSizeInUnits(planegeometry->GetExtentInMM(0), planegeometry->GetExtentInMM(1));
823 
824  CPPUNIT_ASSERT_MESSAGE("Testing origin of unit spaced, frontally initialized version: ",
825  mitk::Equal(planegeometry->GetOrigin(), origin, testEps));
826 
827  CPPUNIT_ASSERT_MESSAGE(
828  "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ",
829  mitk::Equal(planegeometry->GetExtent(0), widthInMM, testEps));
830  CPPUNIT_ASSERT_MESSAGE(
831  "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ",
832  mitk::Equal(planegeometry->GetExtent(1), thicknessInMM, testEps));
833  CPPUNIT_ASSERT_MESSAGE(
834  "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ",
835  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
836 
837  CPPUNIT_ASSERT_MESSAGE(
838  "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ",
839  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
840  CPPUNIT_ASSERT_MESSAGE(
841  "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ",
842  mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps));
843  CPPUNIT_ASSERT_MESSAGE(
844  "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ",
845  mitk::Equal(planegeometry->GetExtentInMM(2), newthicknessInMM, testEps));
846 
847  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of unit spaced, frontally initialized version: ",
848  mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps));
849  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of unit spaced, frontally initialized version: ",
850  mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps));
851  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of unit spaced, frontally initialized version: ",
852  mitk::Equal(planegeometry->GetAxisVector(2), -newnormal, testEps)); // T22254: Flipped sign
853 
854  mappingTests2D(planegeometry, widthInMM, thicknessInMM, widthInMM, thicknessInMM, origin, newright, newbottom);
855 
856  // Changing plane to unit spacing also in normal direction using SetExtentInMM(2, 1.0):
857  planegeometry->SetExtentInMM(2, 1.0);
858  newnormal.Normalize();
859 
860  CPPUNIT_ASSERT_MESSAGE("Testing origin of unit spaced, frontally initialized version: ",
861  mitk::Equal(planegeometry->GetOrigin(), origin, testEps));
862 
863  CPPUNIT_ASSERT_MESSAGE(
864  "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ",
865  mitk::Equal(planegeometry->GetExtent(0), widthInMM, testEps));
866  CPPUNIT_ASSERT_MESSAGE(
867  "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ",
868  mitk::Equal(planegeometry->GetExtent(1), thicknessInMM, testEps));
869  CPPUNIT_ASSERT_MESSAGE(
870  "Testing width, height and thickness (in units) of unit spaced, frontally initialized version: ",
871  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
872 
873  CPPUNIT_ASSERT_MESSAGE(
874  "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ",
875  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
876  CPPUNIT_ASSERT_MESSAGE(
877  "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ",
878  mitk::Equal(planegeometry->GetExtentInMM(1), thicknessInMM, testEps));
879  CPPUNIT_ASSERT_MESSAGE(
880  "Testing width, height and thickness (in mm) of unit spaced, frontally initialized version: ",
881  mitk::Equal(planegeometry->GetExtentInMM(2), 1.0, testEps));
882 
883  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of unit spaced, frontally initialized version: ",
884  mitk::Equal(planegeometry->GetAxisVector(0), newright, testEps));
885  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of unit spaced, frontally initialized version: ",
886  mitk::Equal(planegeometry->GetAxisVector(1), newbottom, testEps));
887  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of unit spaced, frontally initialized version: ",
888  mitk::Equal(planegeometry->GetAxisVector(2), -newnormal, testEps)); // T22254: Flipped sign
889  mappingTests2D(planegeometry, widthInMM, thicknessInMM, widthInMM, thicknessInMM, origin, newright, newbottom);
890  }
891 
892  void TestAxialInitialization()
893  {
894  mitk::Point3D cornerpoint0 = planegeometry->GetCornerPoint(0);
895 
896  // Clone, move, rotate and test for 'IsParallel' and 'IsOnPlane'
897  mitk::PlaneGeometry::Pointer clonedplanegeometry =
898  dynamic_cast<mitk::PlaneGeometry *>(planegeometry->Clone().GetPointer());
899 
900  CPPUNIT_ASSERT_MESSAGE("Testing Clone(): ",
901  !((clonedplanegeometry.IsNull()) || (clonedplanegeometry->GetReferenceCount() != 1)));
902 
903  std::cout << "Testing InitializeStandardPlane(clonedplanegeometry, planeorientation = Axial, zPosition = 0, "
904  "frontside=true): "
905  << std::endl;
906  planegeometry->InitializeStandardPlane(clonedplanegeometry);
907 
908  CPPUNIT_ASSERT_MESSAGE("Testing origin of axially initialized version: ",
909  mitk::Equal(planegeometry->GetOrigin(), origin));
910 
911  CPPUNIT_ASSERT_MESSAGE("Testing GetCornerPoint(0) of axially initialized version: ",
912  mitk::Equal(planegeometry->GetCornerPoint(0), cornerpoint0));
913 
914  CPPUNIT_ASSERT_MESSAGE("Testing width (in units) of axially initialized version (should be same as in mm due to "
915  "unit spacing, except for thickness, which is always 1): ",
916  mitk::Equal(planegeometry->GetExtent(0), width, testEps));
917  CPPUNIT_ASSERT_MESSAGE("Testing height (in units) of axially initialized version (should be same as in mm due to "
918  "unit spacing, except for thickness, which is always 1): ",
919  mitk::Equal(planegeometry->GetExtent(1), height, testEps));
920  CPPUNIT_ASSERT_MESSAGE("Testing thickness (in units) of axially initialized version (should be same as in mm due "
921  "to unit spacing, except for thickness, which is always 1): ",
922  mitk::Equal(planegeometry->GetExtent(2), 1, testEps));
923 
924  CPPUNIT_ASSERT_MESSAGE("Testing width (in mm) of axially initialized version: ",
925  mitk::Equal(planegeometry->GetExtentInMM(0), widthInMM, testEps));
926  CPPUNIT_ASSERT_MESSAGE("Testing height (in mm) of axially initialized version: ",
927  mitk::Equal(planegeometry->GetExtentInMM(1), heightInMM, testEps));
928  CPPUNIT_ASSERT_MESSAGE("Testing thickness (in mm) of axially initialized version: ",
929  mitk::Equal(planegeometry->GetExtentInMM(2), thicknessInMM, testEps));
930 
931  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of axially initialized version: ",
932  mitk::Equal(planegeometry->GetAxisVector(0), right, testEps));
933  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of axially initialized version: ",
934  mitk::Equal(planegeometry->GetAxisVector(1), bottom, testEps));
935  CPPUNIT_ASSERT_MESSAGE("Testing GetAxisVector() of axially initialized version: ",
936  mitk::Equal(planegeometry->GetAxisVector(2), normal, testEps));
937 
938  mappingTests2D(planegeometry, width, height, widthInMM, heightInMM, origin, right, bottom);
939  }
940 
941  void TestPlaneComparison()
942  {
943  // Clone, move, rotate and test for 'IsParallel' and 'IsOnPlane'
944  mitk::PlaneGeometry::Pointer clonedplanegeometry2 =
945  dynamic_cast<mitk::PlaneGeometry *>(planegeometry->Clone().GetPointer());
946 
947  CPPUNIT_ASSERT_MESSAGE("Testing Clone(): ",
948  !((clonedplanegeometry2.IsNull()) || (clonedplanegeometry2->GetReferenceCount() != 1)));
949  CPPUNIT_ASSERT_MESSAGE("Testing wheter original and clone are at the same position",
950  clonedplanegeometry2->IsOnPlane(planegeometry.GetPointer()));
951  CPPUNIT_ASSERT_MESSAGE(" Asserting that origin is on the plane cloned plane:",
952  clonedplanegeometry2->IsOnPlane(origin));
953 
954  mitk::VnlVector newaxis(3);
955  mitk::FillVector3D(newaxis, 1.0, 1.0, 1.0);
956  newaxis.normalize();
957  vnl_quaternion<mitk::ScalarType> rotation2(newaxis, 0.0);
958 
959  mitk::Vector3D clonednormal = clonedplanegeometry2->GetNormal();
960  mitk::Point3D clonedorigin = clonedplanegeometry2->GetOrigin();
961 
962  auto planerot = new mitk::RotationOperation(mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector(0), 180.0);
963 
964  clonedplanegeometry2->ExecuteOperation(planerot);
965  CPPUNIT_ASSERT_MESSAGE(" Asserting that a flipped plane is still on the original plane: ",
966  clonedplanegeometry2->IsOnPlane(planegeometry.GetPointer()));
967 
968  clonedorigin += clonednormal;
969  clonedplanegeometry2->SetOrigin(clonedorigin);
970 
971  CPPUNIT_ASSERT_MESSAGE("Testing if the translated (cloned, flipped) plane is parallel to its origin plane: ",
972  clonedplanegeometry2->IsParallel(planegeometry));
973  delete planerot;
974 
975  planerot = new mitk::RotationOperation(mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector(0), 0.5);
976  clonedplanegeometry2->ExecuteOperation(planerot);
977 
978  CPPUNIT_ASSERT_MESSAGE("Testing if a non-paralell plane gets recognized as not paralell [rotation +0.5 degree] : ",
979  !clonedplanegeometry2->IsParallel(planegeometry));
980  delete planerot;
981 
982  planerot = new mitk::RotationOperation(mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector(0), -1.0);
983  clonedplanegeometry2->ExecuteOperation(planerot);
984 
985  CPPUNIT_ASSERT_MESSAGE("Testing if a non-paralell plane gets recognized as not paralell [rotation -0.5 degree] : ",
986  !clonedplanegeometry2->IsParallel(planegeometry));
987  delete planerot;
988 
989  planerot = new mitk::RotationOperation(mitk::OpROTATE, origin, clonedplanegeometry2->GetAxisVector(0), 360.5);
990  clonedplanegeometry2->ExecuteOperation(planerot);
991 
992  CPPUNIT_ASSERT_MESSAGE("Testing if a non-paralell plane gets recognized as paralell [rotation 360 degree] : ",
993  clonedplanegeometry2->IsParallel(planegeometry));
994  }
995 
996 private:
997  // helper Methods for the Tests
998 
1000  {
1001  mitk::Vector3D mySpacing;
1002  mySpacing[0] = 31;
1003  mySpacing[1] = 0.1;
1004  mySpacing[2] = 5.4;
1005  mitk::Point3D myOrigin;
1006  myOrigin[0] = 8;
1007  myOrigin[1] = 9;
1008  myOrigin[2] = 10;
1009  mitk::AffineTransform3D::Pointer myTransform = mitk::AffineTransform3D::New();
1010  itk::Matrix<mitk::ScalarType, 3, 3> transMatrix;
1011  transMatrix.Fill(0);
1012  transMatrix[0][0] = 1;
1013  transMatrix[1][1] = 2;
1014  transMatrix[2][2] = 4;
1015 
1016  myTransform->SetMatrix(transMatrix);
1017 
1019  geometry2D->SetIndexToWorldTransform(myTransform);
1020  geometry2D->SetSpacing(mySpacing);
1021  geometry2D->SetOrigin(myOrigin);
1022  return geometry2D;
1023  }
1024 
1025  bool compareMatrix(itk::Matrix<mitk::ScalarType, 3, 3> left, itk::Matrix<mitk::ScalarType, 3, 3> right)
1026  {
1027  bool equal = true;
1028  for (int i = 0; i < 3; ++i)
1029  for (int j = 0; j < 3; ++j)
1030  equal &= mitk::Equal(left[i][j], right[i][j]);
1031  return equal;
1032  }
1033 
1037  void mappingTests2D(const mitk::PlaneGeometry *planegeometry,
1038  const mitk::ScalarType &width,
1039  const mitk::ScalarType &height,
1040  const mitk::ScalarType &widthInMM,
1041  const mitk::ScalarType &heightInMM,
1042  const mitk::Point3D &origin,
1043  const mitk::Vector3D &right,
1044  const mitk::Vector3D &bottom)
1045  {
1046  std::cout << "Testing mapping Map(pt2d_mm(x=widthInMM/2.3,y=heightInMM/2.5), pt3d_mm) and compare with expected: ";
1047  mitk::Point2D pt2d_mm;
1048  mitk::Point3D pt3d_mm, expected_pt3d_mm;
1049  pt2d_mm[0] = widthInMM / 2.3;
1050  pt2d_mm[1] = heightInMM / 2.5;
1051  expected_pt3d_mm = origin + right * (pt2d_mm[0] / right.GetNorm()) + bottom * (pt2d_mm[1] / bottom.GetNorm());
1052  planegeometry->Map(pt2d_mm, pt3d_mm);
1053  CPPUNIT_ASSERT_MESSAGE(
1054  "Testing mapping Map(pt2d_mm(x=widthInMM/2.3,y=heightInMM/2.5), pt3d_mm) and compare with expected",
1055  mitk::Equal(pt3d_mm, expected_pt3d_mm, testEps));
1056 
1057  std::cout << "Testing mapping Map(pt3d_mm, pt2d_mm) and compare with expected: ";
1058  mitk::Point2D testpt2d_mm;
1059  planegeometry->Map(pt3d_mm, testpt2d_mm);
1060  std::cout << std::setprecision(12) << "Expected pt2d_mm " << pt2d_mm << std::endl;
1061  std::cout << std::setprecision(12) << "Result testpt2d_mm " << testpt2d_mm << std::endl;
1062  std::cout << std::setprecision(12) << "10*mitk::eps " << 10 * mitk::eps << std::endl;
1063  // This eps is temporarily set to 10*mitk::eps. See bug #15037 for details.
1064  CPPUNIT_ASSERT_MESSAGE("Testing mapping Map(pt3d_mm, pt2d_mm) and compare with expected",
1065  mitk::Equal(pt2d_mm, testpt2d_mm, 10 * mitk::eps));
1066 
1067  std::cout << "Testing IndexToWorld(pt2d_units, pt2d_mm) and compare with expected: ";
1068  mitk::Point2D pt2d_units;
1069  pt2d_units[0] = width / 2.0;
1070  pt2d_units[1] = height / 2.0;
1071  pt2d_mm[0] = widthInMM / 2.0;
1072  pt2d_mm[1] = heightInMM / 2.0;
1073  planegeometry->IndexToWorld(pt2d_units, testpt2d_mm);
1074  std::cout << std::setprecision(12) << "Expected pt2d_mm " << pt2d_mm << std::endl;
1075  std::cout << std::setprecision(12) << "Result testpt2d_mm " << testpt2d_mm << std::endl;
1076  std::cout << std::setprecision(12) << "10*mitk::eps " << 10 * mitk::eps << std::endl;
1077  // This eps is temporarily set to 10*mitk::eps. See bug #15037 for details.
1078  CPPUNIT_ASSERT_MESSAGE("Testing IndexToWorld(pt2d_units, pt2d_mm) and compare with expected: ",
1079  mitk::Equal(pt2d_mm, testpt2d_mm, 10 * mitk::eps));
1080 
1081  std::cout << "Testing WorldToIndex(pt2d_mm, pt2d_units) and compare with expected: ";
1082  mitk::Point2D testpt2d_units;
1083  planegeometry->WorldToIndex(pt2d_mm, testpt2d_units);
1084 
1085  std::cout << std::setprecision(12) << "Expected pt2d_units " << pt2d_units << std::endl;
1086  std::cout << std::setprecision(12) << "Result testpt2d_units " << testpt2d_units << std::endl;
1087  std::cout << std::setprecision(12) << "10*mitk::eps " << 10 * mitk::eps << std::endl;
1088  // This eps is temporarily set to 10*mitk::eps. See bug #15037 for details.
1089  CPPUNIT_ASSERT_MESSAGE("Testing WorldToIndex(pt2d_mm, pt2d_units) and compare with expected:",
1090  mitk::Equal(pt2d_units, testpt2d_units, 10 * mitk::eps));
1091  }
1092 };
1093 MITK_TEST_SUITE_REGISTRATION(mitkPlaneGeometry)
Descibes a line.
Definition: mitkLine.h:28
static std::vector< int > CalculateDominantAxes(mitk::AffineTransform3D::MatrixType::InternalMatrixType &rotation_matrix)
Standard implementation of BaseGeometry.
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
bool MatrixEqualElementWise(const vnl_matrix_fixed< TCoordRep, NRows, NCols > &matrix1, const vnl_matrix_fixed< TCoordRep, NRows, NCols > &matrix2, mitk::ScalarType epsilon=mitk::eps)
Check for element-wise matrix equality with a user defined accuracy.
Definition: mitkMatrix.h:140
static Pointer New()
vnl_vector< ScalarType > VnlVector
Definition: mitkVector.h:134
double ScalarType
static bool CheckRotationMatrix(AffineTransform3D *transform, double epsilon=mitk::eps)
Check if matrix is a rotation matrix:
#define MITK_TEST(TESTMETHOD)
Adds a test to the current test suite.
static std::string GetTestDataFilePath(const std::string &testData)
Get the absolute path for test data.
static Pointer New()
Constants for most interaction classes, due to the generic StateMachines.
static Matrix3D rotation
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const
itk::SmartPointer< Self > Pointer
#define MITK_TEST_OUTPUT(x)
Output some text.
static void clone(T *&dst, S *src, int n)
Definition: svm.cpp:59
virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const
Test fixture for parameterized tests.
Describes a geometry defined by an vtkAbstractTransform and a plane.
static mitk::PlaneGeometry::Pointer createPlaneGeometry()
mitk::Image::Pointer image
static const mitk::ScalarType testEps
MITKCORE_EXPORT const ScalarType sqrteps
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
static Pointer New()
MITKCORE_EXPORT const ScalarType eps
Describes a two-dimensional, rectangular plane.
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
BaseGeometry Describes the geometry of a data object.