Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkProportionalTimeGeometryToXML.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 
18 
19 #include "mitkGeometry3DToXML.h"
20 
21 #include <tinyxml.h>
22 
23 #include <boost/lexical_cast.hpp>
24 
26 {
27  assert(timeGeom);
28 
29  TiXmlElement *timeGeomElem = new TiXmlElement("ProportionalTimeGeometry");
30  timeGeomElem->SetAttribute("NumberOfTimeSteps", timeGeom->CountTimeSteps());
31  // TinyXML cannot serialize infinity (default value for time step)
32  // So we guard this value and the first time point against serialization problems
33  // by not writing them. The reader can then tell that absence of those values
34  // means "keep the default values"
36  timeGeomElem->SetAttribute("FirstTimePoint", boost::lexical_cast<std::string>(timeGeom->GetFirstTimePoint()));
37  if (timeGeom->GetStepDuration() != std::numeric_limits<TimePointType>::infinity())
38  timeGeomElem->SetAttribute("StepDuration", boost::lexical_cast<std::string>(timeGeom->GetStepDuration()));
39 
40  for (TimeStepType t = 0; t < timeGeom->CountTimeSteps(); ++t)
41  {
42  // add a node for the geometry of each time step
43  const Geometry3D *geom3D(nullptr);
44  if ((geom3D = dynamic_cast<const Geometry3D *>(timeGeom->GetGeometryForTimeStep(t).GetPointer())))
45  {
46  TiXmlElement *geom3DElement = Geometry3DToXML::ToXML(geom3D);
47  geom3DElement->SetAttribute("TimeStep", t); // mark order for us
48  timeGeomElem->LinkEndChild(geom3DElement);
49  }
50  else
51  {
52  MITK_WARN << "Serializing a ProportionalTimeGeometry that contains something other than Geometry3D!"
53  << " (in time step " << t << ")"
54  << " File will miss information!";
55  }
56  }
57 
58  return timeGeomElem;
59 }
60 
62 {
63  if (!timeGeometryElement)
64  {
65  MITK_ERROR << "Cannot deserialize ProportionalTimeGeometry from nullptr.";
66  return nullptr;
67  }
68 
69  int numberOfTimeSteps = 0;
70 
71  if (TIXML_SUCCESS != timeGeometryElement->QueryIntAttribute("NumberOfTimeSteps", &numberOfTimeSteps))
72  {
73  MITK_WARN << "<ProportionalTimeGeometry> found without NumberOfTimeSteps attribute. Counting...";
74  }
75 
76  // might be missing!
77  TimePointType firstTimePoint;
78  std::string firstTimePoint_s;
79  TimePointType stepDuration;
80  std::string stepDuration_s;
81  try
82  {
83  if (TIXML_SUCCESS == timeGeometryElement->QueryStringAttribute("FirstTimePoint", &firstTimePoint_s))
84  {
85  firstTimePoint = boost::lexical_cast<double>(firstTimePoint_s);
86  }
87  else
88  {
89  firstTimePoint = -std::numeric_limits<TimePointType>::max();
90  }
91 
92  if (TIXML_SUCCESS == timeGeometryElement->QueryStringAttribute("StepDuration", &stepDuration_s))
93  {
94  stepDuration = boost::lexical_cast<double>(stepDuration_s);
95  }
96  else
97  {
98  stepDuration = std::numeric_limits<TimePointType>::infinity();
99  }
100  }
101  catch (boost::bad_lexical_cast &e)
102  {
103  MITK_ERROR << "Could not parse string as number: " << e.what();
104  return nullptr;
105  }
106 
107  // list of all geometries with their time steps
108  std::multimap<TimeStepType, BaseGeometry::Pointer> allReadGeometries;
109 
110  int indexForUnlabeledTimeStep(-1);
111  for (TiXmlElement *currentElement = timeGeometryElement->FirstChildElement(); currentElement != nullptr;
112  currentElement = currentElement->NextSiblingElement())
113  {
114  // different geometries could have been inside a ProportionalTimeGeometry.
115  // By now, we only support Geometry3D
116  std::string tagName = currentElement->Value();
117  if (tagName == "Geometry3D")
118  {
119  Geometry3D::Pointer restoredGeometry = Geometry3DToXML::FromXML(currentElement);
120  if (restoredGeometry.IsNotNull())
121  {
122  int timeStep(-1);
123  if (TIXML_SUCCESS != currentElement->QueryIntAttribute("TimeStep", &timeStep))
124  {
125  timeStep = indexForUnlabeledTimeStep--; // decrement index for next one
126  MITK_WARN << "Found <Geometry3D> without 'TimeStep' attribute in <ProportionalTimeGeometry>. No guarantees "
127  "on order anymore.";
128  }
129 
130  if (allReadGeometries.count(static_cast<TimeStepType>(timeStep)) > 0)
131  {
132  MITK_WARN << "Found <Geometry3D> tags with identical 'TimeStep' attribute in <ProportionalTimeGeometry>. No "
133  "guarantees on order anymore.";
134  }
135 
136  allReadGeometries.insert(std::make_pair(static_cast<TimeStepType>(timeStep), restoredGeometry.GetPointer()));
137  }
138  }
139  else
140  {
141  MITK_WARN << "Found unsupported tag <" << tagName << "> inside <ProportionalTimeGeometry>. Ignoring.";
142  }
143  }
144 
145  // now add all BaseGeometries that were read to a new instance
146  // of ProportionalTimeGeometry
148  newTimeGeometry->SetFirstTimePoint(firstTimePoint);
149  newTimeGeometry->SetStepDuration(stepDuration);
150  newTimeGeometry->ReserveSpaceForGeometries(allReadGeometries.size());
151 
152  TimeStepType t(0);
153  for (auto entry : allReadGeometries)
154  {
155  // We add items with newly assigned time steps.
156  // This avoids great confusion when a file contains
157  // bogus numbers.
158  newTimeGeometry->SetTimeStepGeometry(entry.second, t++);
159  }
160 
161  // Need to re-calculate global bounding box.
162  // This is neither stored in a file, nor done by SetTimeStepGeometry
163  newTimeGeometry->UpdateBoundingBox();
164 
165  return newTimeGeometry;
166 }
virtual TimeStepType CountTimeSteps() const override
Returns the number of time steps.
Standard implementation of BaseGeometry.
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const override
Returns the geometry which corresponds to the given time step.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
static TiXmlElement * ToXML(const ProportionalTimeGeometry *geometry)
Serialize given geometry to XML.
static Geometry3D::Pointer FromXML(TiXmlElement *node)
Create a Geometry3D from XML. Interprets only the format created by ToXML().
virtual TimePointType GetFirstTimePoint() const
static TiXmlElement * ToXML(const Geometry3D *geometry)
Serialize given geometry to XML.
virtual TimePointType GetStepDuration() const
#define MITK_WARN
Definition: mitkLogMacros.h:23
mitk::ScalarType TimePointType
std::vcl_size_t TimeStepType
static T max(T x, T y)
Definition: svm.cpp:70
static ProportionalTimeGeometry::Pointer FromXML(TiXmlElement *node)
Create a ProportionalTimeGeometry from XML. Interprets only the format created by ToXML()...