Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkGeometryDataIOTest.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkTestFixture.h"
18 #include "mitkTestingMacros.h"
19 
20 #include "mitkGeometry3D.h"
21 #include "mitkGeometryData.h"
23 
24 #include "mitkIOMimeTypes.h"
25 #include "mitkIOUtil.h"
34 class mitkGeometryDataIOTestSuite : public mitk::TestFixture
35 {
36  CPPUNIT_TEST_SUITE(mitkGeometryDataIOTestSuite);
37  MITK_TEST(StoreDefaultGeometry3D);
38  MITK_TEST(StoreImageGeometry);
39  MITK_TEST(StoreFrameOfReference);
40  MITK_TEST(StoreOrigin);
41  MITK_TEST(StoreSpacing);
42  MITK_TEST(StoreBounds);
43  MITK_TEST(StoreTransform);
44  MITK_TEST(StoreProportionalTimeGeometry);
45  CPPUNIT_TEST_SUITE_END();
46 
47  mitk::GeometryData::Pointer m_GeometryData;
50 
51  mitk::GeometryData::Pointer m_ReadGeometryData;
52  mitk::Geometry3D::Pointer m_ReadGeom3D;
53  mitk::ProportionalTimeGeometry::Pointer m_ReadProportionalTimeGeom;
54 
55 public:
56  void setUp() override
57  {
58  m_GeometryData = mitk::GeometryData::New();
59  m_Geom3D = mitk::Geometry3D::New();
60 
61  m_GeometryData->SetGeometry(m_Geom3D); // does copy!? doc says otherwise
62  // --> we reference and use the clone, not the original!
63  m_Geom3D = static_cast<mitk::Geometry3D *>(m_GeometryData->GetGeometry());
64 
65  m_TimeGeometry = dynamic_cast<mitk::ProportionalTimeGeometry *>(m_GeometryData->GetTimeGeometry());
66  CPPUNIT_ASSERT(m_TimeGeometry.IsNotNull());
67  }
68 
69  void tearDown() override
70  {
71  m_GeometryData = nullptr;
72  m_Geom3D = nullptr;
73  m_ReadGeometryData = nullptr;
74  m_ReadGeom3D = nullptr;
75  m_ReadProportionalTimeGeom = nullptr;
76  }
77 
78  void StoreDefaultGeometry3D()
79  {
80  // m_Geom3D already prepared in setUp()
81  ASSERT_Geometry3D_WriteReadLoop_Works();
82  }
83 
84  void StoreImageGeometry()
85  {
86  m_Geom3D->SetImageGeometry(true);
87  ASSERT_Geometry3D_WriteReadLoop_Works();
88 
89  m_Geom3D->SetImageGeometry(false);
90  ASSERT_Geometry3D_WriteReadLoop_Works();
91  }
92 
93  void StoreFrameOfReference()
94  {
95  m_Geom3D->SetFrameOfReferenceID(513);
96  ASSERT_Geometry3D_WriteReadLoop_Works();
97 
98  m_Geom3D->SetFrameOfReferenceID(std::numeric_limits<unsigned int>::max());
99  ASSERT_Geometry3D_WriteReadLoop_Works();
100  }
101 
102  void StoreOrigin()
103  {
104  mitk::Point3D origin;
106  m_Geom3D->SetOrigin(origin);
107  ASSERT_Geometry3D_WriteReadLoop_Works();
108 
110  m_Geom3D->SetOrigin(origin);
111  ASSERT_Geometry3D_WriteReadLoop_Works();
112  }
113 
114  void StoreSpacing()
115  {
116  mitk::Vector3D spacing;
117  // tempted to test with spacing of std::numeric_limits<mitk::ScalarType>::max()
118  // BUT that puts TinyXML into a pretty long loop counting the required numbers needed
119  // So we test a _big_ spacing
120  mitk::FillVector3D(spacing, 0.0000001, 0.0017, 918273645.18293746);
121  m_Geom3D->SetSpacing(spacing);
122  ASSERT_Geometry3D_WriteReadLoop_Works();
123 
124  // tempted to test negative spacings? they should be serialized, but
125  // there are assertions somewhere in the code that verify positive
126  // spacings, so we can skip this test.
127  }
128 
129  void StoreBounds()
130  {
133  bounds[1] = -52.723;
134  bounds[2] = -0.002;
135  bounds[3] = 918273645.18293746;
136  bounds[4] = -0.002;
137  bounds[5] = +52.723;
138  m_Geom3D->SetBounds(bounds);
139  ASSERT_Geometry3D_WriteReadLoop_Works();
140  }
141 
142  void StoreTransform()
143  {
144  mitk::ScalarType matrixCoeffs[9] = {0.0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8};
145 
146  mitk::AffineTransform3D::MatrixType matrix;
147  matrix.GetVnlMatrix().set(matrixCoeffs);
148 
149  mitk::AffineTransform3D::OffsetType offset;
150  offset[0] = -918273645.1829374; // don't want limits::min(), there is a minimal difference for this value.
151  // offset[1] = -0.0; // this causes problems with mitk::Equal
152  offset[1] = 0.0;
153  offset[2] = +918273645.1829374;
154 
156  transform->SetMatrix(matrix);
157  transform->SetOffset(offset);
158  m_Geom3D->SetIndexToWorldTransform(transform);
159 
160  ASSERT_Geometry3D_WriteReadLoop_Works();
161  }
162 
163  void WriteAndRead_m_GeometryData()
164  {
165  // temp path
166  std::string tmpPath = mitk::IOUtil::CreateTemporaryDirectory("GeomDataIOTest_XXXXXX");
167 
168  // let IOUtil find a good file extension
169  std::string filename("geometrydata_geometry3d");
170  std::string extension(mitk::IOMimeTypes::GEOMETRY_DATA_MIMETYPE().GetExtensions().front());
171 
172  // don't specify the extension, expect that there is no other writer
173  // TODO Other than documented, Save does not add the extension. Anything missing in my MIMETYPE??
174  CPPUNIT_ASSERT_NO_THROW(mitk::IOUtil::Save(m_GeometryData, tmpPath + "/" + filename + "." + extension));
175 
176  // read into member
177  std::vector<mitk::BaseData::Pointer> loadedData = mitk::IOUtil::Load(tmpPath + "/" + filename + "." + extension);
178  CPPUNIT_ASSERT_MESSAGE("IOUtil could read something (and just one)", loadedData.size() == 1);
179 
180  m_ReadGeometryData = dynamic_cast<mitk::GeometryData *>(loadedData.front().GetPointer());
181  CPPUNIT_ASSERT_MESSAGE("IOUtil could read _some_ GeometryData", m_ReadGeometryData.IsNotNull());
182 
183  m_ReadGeom3D = dynamic_cast<mitk::Geometry3D *>(m_ReadGeometryData->GetGeometry());
184  CPPUNIT_ASSERT_MESSAGE("IOUtil could read _some_ Geometry3D", m_ReadGeom3D.IsNotNull());
185 
186  m_ReadProportionalTimeGeom = dynamic_cast<mitk::ProportionalTimeGeometry *>(m_ReadGeometryData->GetTimeGeometry());
187  CPPUNIT_ASSERT_MESSAGE("IOUtil could read _some_ ProportionalTimeGeometry", m_ReadProportionalTimeGeom.IsNotNull());
188  }
189 
190  void ASSERT_Geometry3D_WriteReadLoop_Works()
191  {
192  WriteAndRead_m_GeometryData();
193  // Doc of mitk::Equal for BaseGeometry says
194  // "The function compares the spacing, origin, axis vectors, extents, the matrix of the
195  // IndexToWorldTransform(element wise), the bounding(element wise) and the ImageGeometry flag."
196  // This seems pretty much everything that we can have in a Geometry3D..
197  CPPUNIT_ASSERT_MESSAGE("Geometry3D > file > Geometry3D keeps geometry",
198  mitk::Equal(*m_Geom3D, *m_ReadGeom3D, 0.000001, true));
199  // Tolerance: Storing huge values 9.18274e+008 does not work at the precision of mitk::eps
200  // So the author of this test judged above tolerance sufficient. If more is
201  // required we need to inspect in more detail.
202  }
203 
204  void StoreProportionalTimeGeometry()
205  {
206  // Set Time Geometry
207  m_TimeGeometry->ClearAllGeometries(); // remove default filling from setUp();
208 
209  for (int t = 0; t < 4; ++t)
210  {
211  // add new time steps
213  vtkSmartPointer<vtkMatrix4x4> vtk_matrix = vtkSmartPointer<vtkMatrix4x4>::New();
214  for (int i = 0; i != 4; ++i)
215  {
216  for (int j = 0; j != 4; ++j)
217  {
218  vtk_matrix->SetElement(i, j, t + (i + j) / 8.0); // just insignificant values
219  }
220  }
221 
222  if (t % 2 == 0) // invert every second one
223  vtk_matrix->Invert();
224 
225  timestepGeometry->SetIndexToWorldTransformByVtkMatrix(vtk_matrix);
226  m_TimeGeometry->SetTimeStepGeometry(timestepGeometry, t);
227  }
228 
229  // time steps are handled as ScalarType, so use some negative values
230  m_TimeGeometry->SetFirstTimePoint(-5017.20);
231  m_TimeGeometry->SetStepDuration(2743.83);
232 
233  // fill m_GeometryData with something that has multiple time steps
234  ASSERT_ProportionalTimeGeometry_WriteReadLoop_Works();
235  }
236 
237  void ASSERT_ProportionalTimeGeometry_WriteReadLoop_Works()
238  {
239  WriteAndRead_m_GeometryData();
240 
241  CPPUNIT_ASSERT_MESSAGE("ProportionalTimeGeometry > file > ProportionalTimeGeometry keeps geometry",
242  mitk::Equal(*m_TimeGeometry, *m_ReadProportionalTimeGeom, 0.000001, true));
243  // Tolerance: Storing huge values 9.18274e+008 does not work at the precision of mitk::eps
244  // So the author of this test judged above tolerance sufficient. If more is
245  // required we need to inspect in more detail.
246  }
247 
248 }; // class
249 
250 MITK_TEST_SUITE_REGISTRATION(mitkGeometryDataIO)
static void Save(const mitk::BaseData *data, const std::string &path)
Save a mitk::BaseData instance.
Definition: mitkIOUtil.cpp:824
itk::SmartPointer< Self > Pointer
Standard implementation of BaseGeometry.
MITK_TEST_SUITE_REGISTRATION(mitkImageToItk)
BoundingBoxType::BoundsArrayType BoundsArrayType
double ScalarType
#define MITK_TEST(TESTMETHOD)
Adds a test to the current test suite.
static Pointer New()
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:110
static Vector3D offset
static const std::string filename
Test fixture for parameterized tests.
static Pointer New()
static T max(T x, T y)
Definition: svm.cpp:70
Data class only having a BaseGeometry but not containing any specific data.
static std::string CreateTemporaryDirectory(const std::string &templateName="XXXXXX", std::string path=std::string())
Definition: mitkIOUtil.cpp:452
static T min(T x, T y)
Definition: svm.cpp:67
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 DataStorage::SetOfObjects::Pointer Load(const std::string &path, DataStorage &storage)
Load a file into the given DataStorage.
Definition: mitkIOUtil.cpp:483
static CustomMimeType GEOMETRY_DATA_MIMETYPE()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.