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