diff --git a/Modules/Core/src/IO/mitkPointSetWriterService.cpp b/Modules/Core/src/IO/mitkPointSetWriterService.cpp index f70c461c16..e9766d7ed3 100644 --- a/Modules/Core/src/IO/mitkPointSetWriterService.cpp +++ b/Modules/Core/src/IO/mitkPointSetWriterService.cpp @@ -1,194 +1,197 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetWriterService.h" +#include "mitkGeometry3DToXML.h" #include "mitkIOMimeTypes.h" +#include "mitkGeometry3D.h" + +#include + #include #include #include // // Initialization of the xml tags. // const std::string mitk::PointSetWriterService::XML_POINT_SET_FILE = "point_set_file" ; const std::string mitk::PointSetWriterService::XML_FILE_VERSION = "file_version" ; const std::string mitk::PointSetWriterService::XML_POINT_SET = "point_set" ; const std::string mitk::PointSetWriterService::XML_TIME_SERIES = "time_series"; const std::string mitk::PointSetWriterService::XML_TIME_SERIES_ID = "time_series_id"; const std::string mitk::PointSetWriterService::XML_POINT = "point" ; const std::string mitk::PointSetWriterService::XML_ID = "id" ; const std::string mitk::PointSetWriterService::XML_SPEC = "specification" ; const std::string mitk::PointSetWriterService::XML_X = "x" ; const std::string mitk::PointSetWriterService::XML_Y = "y" ; const std::string mitk::PointSetWriterService::XML_Z = "z" ; const std::string mitk::PointSetWriterService::VERSION_STRING = "0.1" ; mitk::PointSetWriterService::PointSetWriterService() : AbstractFileWriter(PointSet::GetStaticNameOfClass(), CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE()), "MITK Point Set Writer") - , m_IndentDepth(0) - , m_Indent(2) { RegisterService(); } mitk::PointSetWriterService::PointSetWriterService(const mitk::PointSetWriterService& other) : AbstractFileWriter(other) - , m_IndentDepth(other.m_IndentDepth) - , m_Indent(other.m_Indent) { } mitk::PointSetWriterService::~PointSetWriterService() -{} +{ + +} void mitk::PointSetWriterService::Write() { OutputStream out(this); if ( !out.good() ) { mitkThrow() << "Stream not good."; } std::locale previousLocale(out.getloc()); std::locale I("C"); out.imbue(I); - // - // Here the actual xml writing begins - // - WriteXMLHeader( out ); - WriteStartElement( XML_POINT_SET_FILE, out ); - WriteStartElement( XML_FILE_VERSION, out ); - out << VERSION_STRING; - WriteEndElement( XML_FILE_VERSION, out, false ); + TiXmlDocument doc; - WriteXML( static_cast(this->GetInput()), out ); + TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", ""); // TODO what to write here? encoding? standalone would mean that we provide a DTD somewhere... + doc.LinkEndChild(decl); - WriteEndElement( XML_POINT_SET_FILE, out ); + TiXmlElement* rootNode = new TiXmlElement(XML_POINT_SET_FILE); + doc.LinkEndChild(rootNode); + + TiXmlElement* versionNode = new TiXmlElement(XML_FILE_VERSION); + TiXmlText* versionText = new TiXmlText(VERSION_STRING ); + versionNode->LinkEndChild(versionText); + rootNode->LinkEndChild( versionNode ); + + TiXmlElement* pointSetNode = ToXML( static_cast(this->GetInput()) ); + if (!pointSetNode) + { + mitkThrow() << "Serialization error during PointSet writing."; + } + rootNode->LinkEndChild(pointSetNode); + + // write document to stream (/file) + out << doc; out.imbue(previousLocale); if ( !out.good() ) // some error during output { mitkThrow() << "Some error during point set writing."; } } mitk::PointSetWriterService*mitk::PointSetWriterService::Clone() const { return new PointSetWriterService(*this); } -void mitk::PointSetWriterService::WriteXML( const mitk::PointSet* pointSet, std::ostream& out ) +TiXmlElement* mitk::PointSetWriterService::ToXML( const mitk::PointSet* pointSet ) { - WriteStartElement( XML_POINT_SET, out ); + // the following is rather bloated and could be expressed in more compact XML + // (e.g. using attributes instead of tags for x/y/z). The current format is + // kept to be compatible with the previous writer. + TiXmlElement* pointSetElement = new TiXmlElement( XML_POINT_SET ); unsigned int timecount = pointSet->GetTimeSteps(); for(unsigned int i=0; i< timecount; i++) { - WriteStartElement( XML_TIME_SERIES, out ); + TiXmlElement* timeSeriesElement = new TiXmlElement( XML_TIME_SERIES ); + pointSetElement->LinkEndChild(timeSeriesElement); + + TiXmlElement* timeSeriesIDElement = new TiXmlElement( XML_TIME_SERIES_ID ); + timeSeriesElement->LinkEndChild(timeSeriesIDElement); + TiXmlText* timeSeriesIDText = new TiXmlText(ConvertToString(i)); + timeSeriesIDElement->LinkEndChild(timeSeriesIDText); - WriteStartElement( XML_TIME_SERIES_ID, out ); - out << ConvertToString( i ); - WriteEndElement( XML_TIME_SERIES_ID, out, false ); + PointSet::PointsContainer* pointsContainer = pointSet->GetPointSet(i)->GetPoints(); + PointSet::PointsContainer::Iterator it; - mitk::PointSet::PointsContainer* pointsContainer = pointSet->GetPointSet(i)->GetPoints(); - mitk::PointSet::PointsContainer::Iterator it; + Geometry3D* geometry = dynamic_cast( pointSet->GetGeometry(i) ); + if (geometry == nullptr) + { + MITK_WARN << "Writing a PointSet with something other that a Geometry3D. This is not foreseen and not handled."; + // we'll continue anyway, this imitates previous behavior + } + else + { + TiXmlElement* geometryElement = Geometry3DToXML::ToXML( geometry ); + timeSeriesElement->LinkEndChild(geometryElement); + } for ( it = pointsContainer->Begin(); it != pointsContainer->End(); ++it ) { - WriteStartElement( XML_POINT, out ); + TiXmlElement* pointElement = new TiXmlElement(XML_POINT); + timeSeriesElement->LinkEndChild(pointElement); - WriteStartElement( XML_ID, out ); - out << ConvertToString( it->Index() ); - WriteEndElement( XML_ID, out, false ); + TiXmlElement* pointIDElement = new TiXmlElement(XML_ID); + TiXmlText* pointIDText = new TiXmlText( ConvertToString( it->Index() ) ); + pointIDElement->LinkEndChild(pointIDText); + pointElement->LinkEndChild(pointIDElement); mitk::PointSet::PointType point = it->Value(); - WriteStartElement( XML_SPEC, out ); - out << ConvertToString( pointSet->GetSpecificationTypeInfo(it->Index(), i) ); - WriteEndElement( XML_SPEC, out, false ); - - WriteStartElement( XML_X, out ); - out << ConvertToString( point[ 0 ] ); - WriteEndElement( XML_X, out, false ); - - WriteStartElement( XML_Y, out ); - out << ConvertToString( point[ 1 ] ); - WriteEndElement( XML_Y, out, false ); - - WriteStartElement( XML_Z, out ); - out << ConvertToString( point[ 2 ] ); - WriteEndElement( XML_Z, out, false ); - - WriteEndElement( XML_POINT, out ); + TiXmlElement* pointSpecElement = new TiXmlElement(XML_SPEC); + TiXmlText* pointSpecText = new TiXmlText( ConvertToString( pointSet->GetSpecificationTypeInfo(it->Index(), i) ) ); + pointSpecElement->LinkEndChild(pointSpecText); + pointElement->LinkEndChild(pointSpecElement); + + TiXmlElement* pointXElement = new TiXmlElement(XML_X); + TiXmlText* pointXText = new TiXmlText( ConvertToString( point[0] ) ); + pointXElement->LinkEndChild(pointXText); + pointElement->LinkEndChild(pointXElement); + + TiXmlElement* pointYElement = new TiXmlElement(XML_Y); + TiXmlText* pointYText = new TiXmlText( ConvertToString( point[1] ) ); + pointYElement->LinkEndChild(pointYText); + pointElement->LinkEndChild(pointYElement); + + TiXmlElement* pointZElement = new TiXmlElement(XML_Z); + TiXmlText* pointZText = new TiXmlText( ConvertToString( point[2] ) ); + pointZElement->LinkEndChild(pointZText); + pointElement->LinkEndChild(pointZElement); } - WriteEndElement( XML_TIME_SERIES, out ); } - WriteEndElement( XML_POINT_SET, out ); + return pointSetElement; } template < typename T> std::string mitk::PointSetWriterService::ConvertToString( T value ) { std::ostringstream o; std::locale I("C"); o.imbue(I); - if ( o << value ) + if ( o << std::setprecision(12) << value ) { return o.str(); } else { return "conversion error"; } -} - -void mitk::PointSetWriterService::WriteXMLHeader( std::ostream &file ) -{ - file << ""; -} - -void mitk::PointSetWriterService::WriteStartElement( const std::string& tag, std::ostream &file ) -{ - file << std::endl; - WriteIndent( file ); - file << '<' << tag << '>'; - m_IndentDepth++; -} - -void mitk::PointSetWriterService::WriteEndElement( const std::string& tag, std::ostream &file, const bool& indent ) -{ - m_IndentDepth--; - if ( indent ) - { - file << std::endl; - WriteIndent( file ); - } - file << '<' << '/' << tag << '>'; -} - -void mitk::PointSetWriterService::WriteIndent( std::ostream& file ) -{ - std::string spaces( m_IndentDepth * m_Indent, ' ' ); - file << spaces; -} +} \ No newline at end of file diff --git a/Modules/Core/src/IO/mitkPointSetWriterService.h b/Modules/Core/src/IO/mitkPointSetWriterService.h index 9ad8a5a58b..98cd5aa8a6 100644 --- a/Modules/Core/src/IO/mitkPointSetWriterService.h +++ b/Modules/Core/src/IO/mitkPointSetWriterService.h @@ -1,112 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_POINT_SET_WRITER_SERVICE__H_ #define _MITK_POINT_SET_WRITER_SERVICE__H_ #include #include +class TiXmlElement; + namespace mitk { +class Geometry3D; + /** * @internal * * @brief XML-based writer for mitk::PointSets * * XML-based writer for mitk::PointSet. Multiple PointSets can be written in * a single XML file by simply setting multiple inputs to the filter. * + * @todo This class would merit a XML library for maintainability or a denser format for performance. + * * @ingroup IO */ class PointSetWriterService : public AbstractFileWriter { public: PointSetWriterService(); virtual ~PointSetWriterService(); using AbstractFileWriter::Write; virtual void Write() override; private: PointSetWriterService(const PointSetWriterService& other); virtual mitk::PointSetWriterService* Clone() const override; - /** - * Converts an arbitrary type to a string. The type has to - * support the << operator. This works fine at least for integral - * data types as float, int, long etc. - * @param value the value to convert - * @returns the string representation of value - */ template < typename T> std::string ConvertToString( T value ); - /** - * Writes an XML representation of the given point set to - * an outstream. The XML-Header an root node is not included! - * @param pointSet the point set to be converted to xml - * @param out the stream to write to. - */ - void WriteXML( const mitk::PointSet* pointSet, std::ostream& out ); - - /** - * Writes an standard xml header to the given stream. - * @param file the stream in which the header is written. - */ - void WriteXMLHeader( std::ostream &file ); - - /** - * Write an end element tag - * End-Elements following character data should pass indent = false. - */ - void WriteEndElement( const std::string& tag, std::ostream &file, const bool& indent = true ); - - /** Write a start element tag */ - void WriteStartElement( const std::string &tag, std::ostream &file ); - - /** Write character data inside a tag. */ - void WriteCharacterData( const std::string &data, std::ostream &file ); - - /** Writes empty spaces to the stream according to m_IndentDepth and m_Indent */ - void WriteIndent( std::ostream& file ); - - unsigned int m_IndentDepth; - const unsigned int m_Indent; + TiXmlElement* ToXML( const mitk::PointSet* pointSet ); static const std::string XML_POINT_SET; static const std::string XML_TIME_SERIES; static const std::string XML_TIME_SERIES_ID; static const std::string XML_POINT_SET_FILE; static const std::string XML_FILE_VERSION; static const std::string XML_POINT; static const std::string XML_SPEC; static const std::string XML_ID; static const std::string XML_X; static const std::string XML_Y; static const std::string XML_Z; static const std::string VERSION_STRING; }; } #endif