Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkPointSetReaderService.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 // MITK
19 #include "mitkGeometry3DToXML.h"
20 #include "mitkIOMimeTypes.h"
22 
23 // STL
24 #include <fstream>
25 #include <iostream>
26 #include <mitkLocaleSwitch.h>
27 
28 #include <tinyxml.h>
29 
31  : AbstractFileReader(CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE()), "MITK Point Set Reader")
32 {
34 }
35 
37 {
38 }
39 
40 std::vector<itk::SmartPointer<mitk::BaseData>> mitk::PointSetReaderService::Read()
41 {
42  // Switch the current locale to "C"
43  LocaleSwitch localeSwitch("C");
44 
45  std::vector<itk::SmartPointer<mitk::BaseData>> result;
46 
47  InputStream stream(this);
48 
49  TiXmlDocument doc;
50  stream >> doc;
51  if (!doc.Error())
52  {
53  TiXmlHandle docHandle(&doc);
54  // unsigned int pointSetCounter(0);
55  for (TiXmlElement *currentPointSetElement =
56  docHandle.FirstChildElement("point_set_file").FirstChildElement("point_set").ToElement();
57  currentPointSetElement != NULL;
58  currentPointSetElement = currentPointSetElement->NextSiblingElement())
59  {
61 
62  // time geometry assembled for addition after all points
63  // else the SetPoint method would already transform the points that we provide it
65 
66  if (currentPointSetElement->FirstChildElement("time_series") != NULL)
67  {
68  for (TiXmlElement *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement();
69  currentTimeSeries != NULL;
70  currentTimeSeries = currentTimeSeries->NextSiblingElement())
71  {
72  unsigned int currentTimeStep(0);
73  TiXmlElement *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id");
74 
75  currentTimeStep = atoi(currentTimeSeriesID->GetText());
76 
77  timeGeometry->Expand(currentTimeStep + 1); // expand (default to identity) in any case
78  TiXmlElement *geometryElem = currentTimeSeries->FirstChildElement("Geometry3D");
79  if (geometryElem)
80  {
81  Geometry3D::Pointer geometry = Geometry3DToXML::FromXML(geometryElem);
82  if (geometry.IsNotNull())
83  {
84  timeGeometry->SetTimeStepGeometry(geometry, currentTimeStep);
85  }
86  else
87  {
88  MITK_ERROR << "Could not deserialize Geometry3D element.";
89  }
90  }
91  else
92  {
93  MITK_WARN << "Fallback to legacy behavior: defining PointSet geometry as identity";
94  }
95 
96  newPointSet = this->ReadPoints(newPointSet, currentTimeSeries, currentTimeStep);
97  }
98  }
99  else
100  {
101  newPointSet = this->ReadPoints(newPointSet, currentPointSetElement, 0);
102  }
103 
104  newPointSet->SetTimeGeometry(timeGeometry);
105 
106  result.push_back(newPointSet.GetPointer());
107  }
108  }
109  else
110  {
111  mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc();
112  }
113 
114  return result;
115 }
116 
117 mitk::BaseGeometry::Pointer mitk::PointSetReaderService::ReadGeometry(TiXmlElement *parentElement)
118 {
119  TiXmlElement *geometryElem = parentElement->FirstChildElement("geometry3d");
120  if (!geometryElem)
121  return nullptr;
122 
123  // data to generate
124  AffineTransform3D::MatrixType matrix;
125  AffineTransform3D::OffsetType offset;
126  bool isImageGeometry(false);
127  unsigned int frameOfReferenceID(0);
129 
130  bool somethingMissing(false);
131 
132  // find data in xml structure
133  TiXmlElement *imageGeometryElem = geometryElem->FirstChildElement("image_geometry");
134  if (imageGeometryElem)
135  {
136  std::string igs = imageGeometryElem->GetText();
137  isImageGeometry = igs == "true" || igs == "TRUE" || igs == "1";
138  }
139  else
140  somethingMissing = true;
141 
142  TiXmlElement *frameOfReferenceElem = geometryElem->FirstChildElement("frame_of_reference_id");
143  if (frameOfReferenceElem)
144  {
145  frameOfReferenceID = atoi(frameOfReferenceElem->GetText());
146  }
147  else
148  somethingMissing = true;
149 
150  TiXmlElement *indexToWorldElem = geometryElem->FirstChildElement("index_to_world");
151  if (indexToWorldElem)
152  {
153  TiXmlElement *matrixElem = indexToWorldElem->FirstChildElement("matrix3x3");
154  TiXmlElement *offsetElem = indexToWorldElem->FirstChildElement("offset");
155  if (indexToWorldElem && offsetElem)
156  {
157  TiXmlElement *col0 = matrixElem->FirstChildElement("column_0");
158  TiXmlElement *col1 = matrixElem->FirstChildElement("column_1");
159  TiXmlElement *col2 = matrixElem->FirstChildElement("column_2");
160 
161  if (col0 && col1 && col2)
162  {
163  somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("x", &matrix[0][0]);
164  somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("y", &matrix[1][0]);
165  somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("z", &matrix[2][0]);
166 
167  somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("x", &matrix[0][1]);
168  somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("y", &matrix[1][1]);
169  somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("z", &matrix[2][1]);
170 
171  somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("x", &matrix[0][2]);
172  somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("y", &matrix[1][2]);
173  somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("z", &matrix[2][2]);
174  }
175  else
176  somethingMissing = true;
177 
178  somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("x", &offset[0]);
179  somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("y", &offset[1]);
180  somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("z", &offset[2]);
181  }
182  else
183  somethingMissing = true;
184 
185  TiXmlElement *boundsElem = geometryElem->FirstChildElement("bounds");
186  if (boundsElem)
187  {
188  TiXmlElement *minBoundsElem = boundsElem->FirstChildElement("min");
189  TiXmlElement *maxBoundsElem = boundsElem->FirstChildElement("max");
190 
191  if (minBoundsElem && maxBoundsElem)
192  {
193  somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("x", &bounds[0]);
194  somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("y", &bounds[2]);
195  somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("z", &bounds[4]);
196 
197  somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("x", &bounds[1]);
198  somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("y", &bounds[3]);
199  somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("z", &bounds[5]);
200  }
201  else
202  somethingMissing = true;
203  }
204  else
205  somethingMissing = true;
206  }
207  else
208  somethingMissing = true;
209 
210  if (somethingMissing)
211  {
212  MITK_ERROR << "XML structure of geometry inside a PointSet file broken. Refusing to build Geometry3D";
213  return nullptr;
214  }
215  else
216  {
218  g->SetImageGeometry(isImageGeometry);
219  g->SetFrameOfReferenceID(frameOfReferenceID);
220  g->SetBounds(bounds);
221 
223  transform->SetMatrix(matrix);
224  transform->SetOffset(offset);
225 
226  g->SetIndexToWorldTransform(transform);
227 
228  return g.GetPointer();
229  }
230 }
231 
232 mitk::PointSet::Pointer mitk::PointSetReaderService::ReadPoints(mitk::PointSet::Pointer newPointSet,
233  TiXmlElement *currentTimeSeries,
234  unsigned int currentTimeStep)
235 {
236  if (currentTimeSeries->FirstChildElement("point") != NULL)
237  {
238  for (TiXmlElement *currentPoint = currentTimeSeries->FirstChildElement("point")->ToElement(); currentPoint != NULL;
239  currentPoint = currentPoint->NextSiblingElement())
240  {
241  unsigned int id(0);
243  double x(0.0);
244  double y(0.0);
245  double z(0.0);
246 
247  id = atoi(currentPoint->FirstChildElement("id")->GetText());
248  if (currentPoint->FirstChildElement("specification") != NULL)
249  {
250  spec = (mitk::PointSpecificationType)atoi(currentPoint->FirstChildElement("specification")->GetText());
251  }
252  x = atof(currentPoint->FirstChildElement("x")->GetText());
253  y = atof(currentPoint->FirstChildElement("y")->GetText());
254  z = atof(currentPoint->FirstChildElement("z")->GetText());
255 
256  mitk::Point3D point;
257  mitk::FillVector3D(point, x, y, z);
258  newPointSet->SetPoint(id, point, spec, currentTimeStep);
259  }
260  }
261  else
262  {
263  if (currentTimeStep != newPointSet->GetTimeSteps() + 1)
264  {
265  newPointSet->Expand(currentTimeStep + 1); // expand time step series with empty time step
266  }
267  }
268  return newPointSet;
269 }
270 
272  : mitk::AbstractFileReader(other)
273 {
274 }
275 
276 mitk::PointSetReaderService *mitk::PointSetReaderService::Clone() const
277 {
278  return new mitk::PointSetReaderService(*this);
279 }
itk::SmartPointer< Self > Pointer
The IOMimeTypes class.
BoundingBoxType::BoundsArrayType BoundsArrayType
#define MITK_ERROR
Definition: mitkLogMacros.h:24
static Pointer New()
static Geometry3D::Pointer FromXML(TiXmlElement *node)
Create a Geometry3D from XML. Interprets only the format created by ToXML().
DataCollection - Class to facilitate loading/accessing structured data.
static Pointer New()
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:110
The CustomMimeType class represents a custom mime-type which may be registered as a service object...
static Vector3D offset
itk::SmartPointer< Self > Pointer
us::ServiceRegistration< IFileReader > RegisterService(us::ModuleContext *context=us::GetModuleContext())
#define MITK_WARN
Definition: mitkLogMacros.h:23
Convenience class to temporarily change the current locale.
#define mitkThrow()
virtual std::vector< itk::SmartPointer< BaseData > > Read() override
Reads a path or stream and creates a list of BaseData objects.
Base class for creating mitk::BaseData objects from files or streams.
PointSpecificationType
enumeration of the type a point can be
Definition: mitkPoint.h:30
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.