Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkPlanarFigureWriter.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 "mitkPlanarFigureWriter.h"
19 #include "mitkPlaneGeometry.h"
20 #include <tinyxml.h>
21 
23  : m_FileName(""),
24  m_FilePrefix(""),
25  m_FilePattern(""),
26  m_Extension(".pf"),
27  m_MimeType("application/MITK.PlanarFigure"),
28  m_Success(false)
29 {
30  this->SetNumberOfRequiredInputs(1);
31  this->SetNumberOfIndexedOutputs(0);
32  // this->SetNthOutput( 0, mitk::PlanarFigure::New().GetPointer() );
33 
34  m_CanWriteToMemory = true;
35 }
36 
38 {
39 }
40 
42 {
43  m_Success = false;
44 
45  if (!m_WriteToMemory && m_FileName.empty())
46  {
47  MITK_ERROR << "Could not write planar figures. File name is invalid";
48  throw std::invalid_argument("file name is empty");
49  }
50 
51  TiXmlDocument document;
52  auto decl = new TiXmlDeclaration("1.0", "", ""); // TODO what to write here? encoding? etc....
53  document.LinkEndChild(decl);
54 
55  auto version = new TiXmlElement("Version");
56  version->SetAttribute("Writer", __FILE__);
57  version->SetAttribute("CVSRevision", "$Revision: 17055 $");
58  version->SetAttribute("FileVersion", 1);
59  document.LinkEndChild(version);
60 
61  /* create xml element for each input */
62  for (unsigned int i = 0; i < this->GetNumberOfInputs(); ++i)
63  {
64  // Create root element for this PlanarFigure
65  InputType::Pointer pf = this->GetInput(i);
66  if (pf.IsNull())
67  continue;
68  auto pfElement = new TiXmlElement("PlanarFigure");
69  pfElement->SetAttribute("type", pf->GetNameOfClass());
70  document.LinkEndChild(pfElement);
71 
72  if (pf->GetNumberOfControlPoints() == 0)
73  continue;
74 
75  // PlanarFigure::VertexContainerType* vertices = pf->GetControlPoints();
76  // if (vertices == NULL)
77  // continue;
78 
79  // Serialize property list of PlanarFigure
80  mitk::PropertyList::Pointer propertyList = pf->GetPropertyList();
81  mitk::PropertyList::PropertyMap::const_iterator it;
82  for (it = propertyList->GetMap()->begin(); it != propertyList->GetMap()->end(); ++it)
83  {
84  // Create seralizer for this property
85  const mitk::BaseProperty *prop = it->second;
86  std::string serializerName = std::string(prop->GetNameOfClass()) + "Serializer";
87  std::list<itk::LightObject::Pointer> allSerializers =
88  itk::ObjectFactoryBase::CreateAllInstance(serializerName.c_str());
89 
90  if (allSerializers.size() != 1)
91  {
92  // No or too many serializer(s) found, skip this property
93  continue;
94  }
95 
96  mitk::BasePropertySerializer *serializer =
97  dynamic_cast<mitk::BasePropertySerializer *>(allSerializers.begin()->GetPointer());
98  if (serializer == nullptr)
99  {
100  // Serializer not valid; skip this property
101  }
102 
103  auto keyElement = new TiXmlElement("property");
104  keyElement->SetAttribute("key", it->first);
105  keyElement->SetAttribute("type", prop->GetNameOfClass());
106 
107  serializer->SetProperty(prop);
108  TiXmlElement *valueElement = nullptr;
109  try
110  {
111  valueElement = serializer->Serialize();
112  }
113  catch (...)
114  {
115  }
116 
117  if (valueElement == nullptr)
118  {
119  // Serialization failed; skip this property
120  continue;
121  }
122 
123  // Add value to property element
124  keyElement->LinkEndChild(valueElement);
125 
126  // Append serialized property to property list
127  pfElement->LinkEndChild(keyElement);
128  }
129 
130  // Serialize control points of PlanarFigure
131  auto controlPointsElement = new TiXmlElement("ControlPoints");
132  pfElement->LinkEndChild(controlPointsElement);
133  for (unsigned int i = 0; i < pf->GetNumberOfControlPoints(); i++)
134  {
135  auto vElement = new TiXmlElement("Vertex");
136  vElement->SetAttribute("id", i);
137  vElement->SetDoubleAttribute("x", pf->GetControlPoint(i)[0]);
138  vElement->SetDoubleAttribute("y", pf->GetControlPoint(i)[1]);
139  controlPointsElement->LinkEndChild(vElement);
140  }
141  auto geoElement = new TiXmlElement("Geometry");
142  const PlaneGeometry *planeGeo = dynamic_cast<const PlaneGeometry *>(pf->GetPlaneGeometry());
143  if (planeGeo != nullptr)
144  {
145  // Write parameters of IndexToWorldTransform of the PlaneGeometry
146  typedef mitk::Geometry3D::TransformType TransformType;
147  const TransformType *affineGeometry = planeGeo->GetIndexToWorldTransform();
148  const TransformType::ParametersType &parameters = affineGeometry->GetParameters();
149  auto vElement = new TiXmlElement("transformParam");
150  for (unsigned int i = 0; i < affineGeometry->GetNumberOfParameters(); ++i)
151  {
152  std::stringstream paramName;
153  paramName << "param" << i;
154  vElement->SetDoubleAttribute(paramName.str().c_str(), parameters.GetElement(i));
155  }
156  geoElement->LinkEndChild(vElement);
157 
158  // Write bounds of the PlaneGeometry
160  const BoundsArrayType &bounds = planeGeo->GetBounds();
161  vElement = new TiXmlElement("boundsParam");
162  for (unsigned int i = 0; i < 6; ++i)
163  {
164  std::stringstream boundName;
165  boundName << "bound" << i;
166  vElement->SetDoubleAttribute(boundName.str().c_str(), bounds.GetElement(i));
167  }
168  geoElement->LinkEndChild(vElement);
169 
170  // Write spacing and origin of the PlaneGeometry
171  Vector3D spacing = planeGeo->GetSpacing();
172  Point3D origin = planeGeo->GetOrigin();
173  geoElement->LinkEndChild(this->CreateXMLVectorElement("Spacing", spacing));
174  geoElement->LinkEndChild(this->CreateXMLVectorElement("Origin", origin));
175 
176  pfElement->LinkEndChild(geoElement);
177  }
178  }
179 
180  if (m_WriteToMemory)
181  {
182  // Declare a printer
183  TiXmlPrinter printer;
184  // attach it to the document you want to convert in to a std::string
185  document.Accept(&printer);
186 
187  // Create memory buffer and print tinyxmldocument there...
188  m_MemoryBufferSize = printer.Size() + 1;
189  m_MemoryBuffer = new char[m_MemoryBufferSize];
190  strcpy(m_MemoryBuffer, printer.CStr());
191  }
192  else
193  {
194  if (document.SaveFile(m_FileName) == false)
195  {
196  MITK_ERROR << "Could not write planar figures to " << m_FileName << "\nTinyXML reports '" << document.ErrorDesc()
197  << "'";
198  throw std::ios_base::failure("Error during writing of planar figure xml file.");
199  }
200  }
201  m_Success = true;
202 }
203 
205 {
206  if (m_MemoryBuffer != nullptr)
207  {
208  delete[] m_MemoryBuffer;
209  }
210 }
211 
212 TiXmlElement *mitk::PlanarFigureWriter::CreateXMLVectorElement(const char *name, itk::FixedArray<mitk::ScalarType, 3> v)
213 {
214  auto vElement = new TiXmlElement(name);
215  vElement->SetDoubleAttribute("x", v.GetElement(0));
216  vElement->SetDoubleAttribute("y", v.GetElement(1));
217  vElement->SetDoubleAttribute("z", v.GetElement(2));
218  return vElement;
219 }
220 
221 void mitk::PlanarFigureWriter::ResizeInputs(const unsigned int &num)
222 {
223  // unsigned int prevNum = this->GetNumberOfInputs();
224  this->SetNumberOfIndexedInputs(num);
225  // for ( unsigned int i = prevNum; i < num; ++i )
226  //{
227  // this->SetNthInput( i, mitk::PlanarFigure::New().GetPointer() );
228  //}
229 }
230 
232 {
233  this->ProcessObject::SetNthInput(0, PlanarFigure);
234 }
235 
237 {
238  if (id >= this->GetNumberOfInputs())
239  this->ResizeInputs(id + 1);
240  this->ProcessObject::SetNthInput(id, PlanarFigure);
241 }
242 
244 {
245  if (this->GetNumberOfInputs() < 1)
246  return nullptr;
247  else
248  return dynamic_cast<InputType *>(this->GetInput(0));
249 }
250 
252 {
253  return dynamic_cast<InputType *>(this->ProcessObject::GetInput(num));
254 }
255 
257 {
258  if (input == nullptr)
259  return false;
260 
261  mitk::BaseData *data = input->GetData();
262  if (data == nullptr)
263  return false;
264 
266  if (PlanarFigure.IsNull())
267  return false;
268  // add code for special subclasses here
269  return true;
270 }
271 
273 {
274  if (this->CanWriteDataType(input))
275  this->ProcessObject::SetNthInput(0, dynamic_cast<mitk::PlanarFigure *>(input->GetData()));
276 }
277 
279 {
281 }
282 
284 {
285  return m_MimeType;
286 }
287 
289 {
290  std::vector<std::string> possibleFileExtensions;
291  possibleFileExtensions.push_back(m_Extension);
292  return possibleFileExtensions;
293 }
294 
296 {
297  return m_Extension;
298 }
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
BoundingBoxType::BoundsArrayType BoundsArrayType
virtual void ReleaseMemory() override
CAUTION: It's up to the user to call this function to release the memory buffer after use in case the...
Base of all data objects.
Definition: mitkBaseData.h:39
virtual void ResizeInputs(const unsigned int &num)
#define MITK_ERROR
Definition: mitkLogMacros.h:24
virtual std::string GetFileExtension() override
Return the extension to be added to the filename.
virtual std::string GetWritenMIMEType() override
Return the MimeType of the saved File.
virtual void SetProperty(const BaseProperty *_arg)
GeometryTransformHolder::TransformType TransformType
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual std::vector< std::string > GetPossibleFileExtensions() override
Return the possible file extensions for the data type associated with the writer. ...
static const char * GetStaticNameOfClass()
Definition: mitkBaseData.h:42
const BoundsArrayType GetBounds() const
virtual bool CanWriteDataType(DataNode *) override
Check if the Writer can write the Content of the.
Abstract base class for properties.
virtual TiXmlElement * Serialize()
Serializes given BaseProperty object.
virtual void GenerateData() override
TiXmlElement * CreateXMLVectorElement(const char *name, itk::FixedArray< mitk::ScalarType, 3 > v)
creates a TinyXML element that contains x, y, and z values
Base class for objects that serialize BaseProperty types.
Base-class for geometric planar (2D) figures, such as lines, circles, rectangles, polygons...
void SetInput(InputType *input)
Describes a two-dimensional, rectangular plane.
virtual std::string GetSupportedBaseData() const override
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
BoundingBoxType::BoundsArrayType BoundsArrayType