Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.