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
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.