diff --git a/CMake/PackageDepends/MITK_tinyxml2_Config.cmake b/CMake/PackageDepends/MITK_tinyxml2_Config.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/CMake/PackageDepends/MITK_tinyxml_Config.cmake b/CMake/PackageDepends/MITK_tinyxml_Config.cmake deleted file mode 100644 index ee84a8ae1a..0000000000 --- a/CMake/PackageDepends/MITK_tinyxml_Config.cmake +++ /dev/null @@ -1,4 +0,0 @@ -list(APPEND ALL_LIBRARIES ${tinyxml_LIBRARIES}) -if(tinyxml_INCLUDE_DIRS) - list(APPEND ALL_INCLUDE_DIRECTORIES ${tinyxml_INCLUDE_DIRS}) -endif() diff --git a/CMakeExternals/ExternalProjectList.cmake b/CMakeExternals/ExternalProjectList.cmake index ab452fc867..6305e62d20 100644 --- a/CMakeExternals/ExternalProjectList.cmake +++ b/CMakeExternals/ExternalProjectList.cmake @@ -1,26 +1,26 @@ mitkFunctionAddExternalProject(NAME Poco ON COMPONENTS Foundation Net Util XML Zip) mitkFunctionAddExternalProject(NAME DCMTK ON DOC "EXPERIMENTAL, superbuild only: Use DCMTK in MITK") mitkFunctionAddExternalProject(NAME OpenIGTLink OFF) -mitkFunctionAddExternalProject(NAME tinyxml ON ADVANCED) +mitkFunctionAddExternalProject(NAME tinyxml2 ON ADVANCED) mitkFunctionAddExternalProject(NAME GDCM ON ADVANCED) mitkFunctionAddExternalProject(NAME Eigen ON ADVANCED DOC "Use the Eigen library") mitkFunctionAddExternalProject(NAME ANN ON ADVANCED DOC "Use Approximate Nearest Neighbor Library") mitkFunctionAddExternalProject(NAME CppUnit ON ADVANCED DOC "Use CppUnit for unit tests") mitkFunctionAddExternalProject(NAME PCRE OFF ADVANCED NO_PACKAGE) mitkFunctionAddExternalProject(NAME HDF5 ON ADVANCED) mitkFunctionAddExternalProject(NAME SWIG OFF ADVANCED NO_PACKAGE DEPENDS PCRE) mitkFunctionAddExternalProject(NAME OpenCV OFF) mitkFunctionAddExternalProject(NAME Vigra OFF DEPENDS HDF5) mitkFunctionAddExternalProject(NAME ITK ON NO_CACHE DEPENDS HDF5) mitkFunctionAddExternalProject(NAME VTK ON NO_CACHE) mitkFunctionAddExternalProject(NAME Boost ON NO_CACHE) mitkFunctionAddExternalProject(NAME ZLIB OFF ADVANCED) mitkFunctionAddExternalProject(NAME cpprestsdk OFF DEPENDS Boost ZLIB ADVANCED) mitkFunctionAddExternalProject(NAME OpenMesh OFF) mitkFunctionAddExternalProject(NAME CTK ON DEPENDS Qt5 DCMTK DOC "Use CTK in MITK") mitkFunctionAddExternalProject(NAME DCMQI ON DEPENDS DCMTK ITK DOC "Use dcmqi in MITK") mitkFunctionAddExternalProject(NAME MatchPoint OFF ADVANCED DEPENDS ITK DOC "Use the MatchPoint translation image registration library") if(MITK_USE_Qt5) mitkFunctionAddExternalProject(NAME Qwt ON ADVANCED DEPENDS Qt5) endif() diff --git a/CMakeExternals/tinyxml-2.6.2.patch b/CMakeExternals/tinyxml-2.6.2.patch deleted file mode 100644 index 4a601bb1e5..0000000000 --- a/CMakeExternals/tinyxml-2.6.2.patch +++ /dev/null @@ -1,266 +0,0 @@ -diff -burN tinyxml/tinyxml.cpp tinyxml-src/tinyxml.cpp ---- tinyxml/tinyxml.cpp 2011-05-15 04:24:57.000000000 +0200 -+++ tinyxml-src/tinyxml.cpp 2015-01-14 15:19:38.685333149 +0100 -@@ -34,6 +34,9 @@ - FILE* TiXmlFOpen( const char* filename, const char* mode ); - - bool TiXmlBase::condenseWhiteSpace = true; -+static unsigned int required_decimal_places = 14+1; // Need 14 for mitk default accuracy plus 1 to make sure we're within tolerance. -+ -+ - - // Microsoft compiler security - FILE* TiXmlFOpen( const char* filename, const char* mode ) -@@ -757,21 +760,21 @@ - #endif - - --void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -+void TiXmlElement::SetDoubleAttribute( const char * name, double val, const unsigned int requiredDecimalPlaces ) - { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { -- attrib->SetDoubleValue( val ); -+ attrib->SetDoubleValue( val, requiredDecimalPlaces ); - } - } - - - #ifdef TIXML_USE_STL --void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -+void TiXmlElement::SetDoubleAttribute( const std::string& name, double val, const unsigned int requiredDecimalPlaces ) - { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { -- attrib->SetDoubleValue( val ); -+ attrib->SetDoubleValue( val, requiredDecimalPlaces ); - } - } - #endif -@@ -1242,33 +1245,73 @@ - - int TiXmlAttribute::QueryDoubleValue( double* dval ) const - { -+ //save old locale -+ char * oldLocale; -+ oldLocale = setlocale( LC_ALL, 0 ); -+ -+ //set new locale -+ setlocale( LC_ALL, "C" ); - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) -+ { -+ //restore locale -+ setlocale( LC_ALL, oldLocale ); - return TIXML_SUCCESS; -+ } -+ //restore locale -+ setlocale( LC_ALL, oldLocale ); - return TIXML_WRONG_TYPE; - } - - void TiXmlAttribute::SetIntValue( int _value ) - { - char buf [64]; -- #if defined(TIXML_SNPRINTF) -+#if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); -- #else -+#else - sprintf (buf, "%d", _value); -- #endif -+#endif - SetValue (buf); - } - --void TiXmlAttribute::SetDoubleValue( double _value ) -+ -+ -+ -+void TiXmlAttribute::SetDoubleValue( double _value, const unsigned int requiredDecimalPlaces ) - { -+#if defined(TIXML_USE_STL) -+ std::ostringstream ss; -+ //save old locale -+ char * oldLocale; -+ oldLocale = setlocale( LC_ALL, 0 ); -+ -+ //set new locale -+ setlocale( LC_ALL, "C" ); -+ ss.precision(TiXmlBase::Precision(_value, requiredDecimalPlaces)); -+ ss << _value; -+ SetValue( ss.str() ); -+ //restore locale -+ setlocale( LC_ALL, oldLocale ); -+#else - char buf [256]; -- #if defined(TIXML_SNPRINTF) -- TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); -- #else -- sprintf (buf, "%g", _value); -- #endif -+ -+ //save old locale -+ char * oldLocale; -+ oldLocale = setlocale( LC_ALL, 0 ); -+ -+ //set new locale -+ setlocale( LC_ALL, "C" ); -+#if defined(TIXML_SNPRINTF) -+ TIXML_SNPRINTF( buf, sizeof(buf), TiXmlBase::Format(_value, requiredDecimalPlaces).c_str(), _value); -+#else -+ sprintf (buf, TiXmlBase::Format(_value, requiredDecimalPlaces).c_str(), _value); -+#endif - SetValue (buf); -+ //restore locale -+ setlocale( LC_ALL, oldLocale ); -+#endif - } - -+ - int TiXmlAttribute::IntValue() const - { - return atoi (value.c_str ()); -@@ -1276,7 +1319,15 @@ - - double TiXmlAttribute::DoubleValue() const - { -+#if defined(TIXML_USE_STL) -+ std::istringstream ss(value); -+ ss.imbue(std::locale("C")); -+ double dval; -+ ss >> dval; -+ return dval; -+#else - return atof (value.c_str ()); -+#endif - } - - -@@ -1884,3 +1935,36 @@ - return true; - } - -+unsigned int TiXmlBase::Precision( const double value, const unsigned int requiredDecimalPlaces ) const -+{ -+ unsigned int lhs = 0; -+ unsigned int one_for_plus_minus_sign = 1; -+ -+ lhs = 0; -+ double temp(value); -+ while (temp >= 1.0) -+ { -+ lhs++; -+ temp /= 10.0; -+ } -+ -+ return( lhs + requiredDecimalPlaces + one_for_plus_minus_sign ); -+} -+ -+/** -+ Return the printf format string that will ensure that the double value -+ passed in will be stored with 'required_decimal_places' worth of decimal -+ points as well as enough digits for the left hand side of the decimal point. -+ */ -+TIXML_STRING TiXmlBase::Format( const double value, const unsigned int requiredDecimalPlaces ) const -+{ -+ char buf[ 32 ]; -+ -+#if defined(TIXML_SNPRINTF) -+ TIXML_SNPRINTF( buf, sizeof(buf), "%%%d.%dlf", Precision(value, requiredDecimalPlaces), requiredDecimalPlaces); -+#else -+ sprintf( buf, "%%%d.%dlf", Precision(value, requiredDecimalPlaces), requiredDecimalPlaces); -+#endif -+ -+ return(TIXML_STRING(buf)); -+} -diff -burN tinyxml/tinyxml.h tinyxml-src/tinyxml.h ---- tinyxml/tinyxml.h 2011-05-15 04:24:57.000000000 +0200 -+++ tinyxml-src/tinyxml.h 2015-01-14 15:19:38.686333149 +0100 -@@ -20,12 +20,24 @@ - - 3. This notice may not be removed or altered from any source - distribution. --*/ -+ */ - - - #ifndef TINYXML_INCLUDED - #define TINYXML_INCLUDED - -+#ifndef TIXML_USE_STL -+ #define TIXML_USE_STL -+#endif -+ -+#ifndef TIXML_USE_STL -+#define TIXML_USE_STL -+#endif -+ -+#ifndef TIXML_USE_STL -+#define TIXML_USE_STL -+#endif -+ - #ifdef _MSC_VER - #pragma warning( push ) - #pragma warning( disable : 4530 ) -@@ -93,9 +105,11 @@ - const int TIXML_MINOR_VERSION = 6; - const int TIXML_PATCH_VERSION = 2; - -+#define DEFAULT_REQUIRED_DECIMAL_PLACES 14 -+ - /* Internal structure for tracking location of items - in the XML file. --*/ -+ */ - struct TiXmlCursor - { - TiXmlCursor() { Clear(); } -@@ -283,6 +297,10 @@ - TIXML_ERROR_STRING_COUNT - }; - -+ unsigned int Precision( const double value, const unsigned int requiredDecimalPlaces ) const ; -+ -+ TIXML_STRING Format( const double value, const unsigned int requiredDecimalPlaces ) const; -+ - protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); -@@ -836,14 +854,14 @@ - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. -- void SetDoubleValue( double _value ); ///< Set the value from a double. -+ void SetDoubleValue( double _value, const unsigned int requiredDecimalPlaces = DEFAULT_REQUIRED_DECIMAL_PLACES ); ///< Set the value from a double. - -- #ifdef TIXML_USE_STL -+#ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } -- #endif -+#endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; -@@ -1061,8 +1079,8 @@ - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. -- void SetDoubleAttribute( const std::string& name, double value ); -- #endif -+ void SetDoubleAttribute( const std::string& name, double value, const unsigned int requiredDecimalPlaces = DEFAULT_REQUIRED_DECIMAL_PLACES ); -+#endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. -@@ -1072,7 +1090,7 @@ - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ -- void SetDoubleAttribute( const char * name, double value ); -+ void SetDoubleAttribute( const char * name, double value, const unsigned int requiredDecimalPlaces = DEFAULT_REQUIRED_DECIMAL_PLACES ); - - /** Deletes an attribute with the given name. - */ diff --git a/CMakeExternals/tinyxml.cmake b/CMakeExternals/tinyxml2.cmake similarity index 65% rename from CMakeExternals/tinyxml.cmake rename to CMakeExternals/tinyxml2.cmake index 74391bee27..8b24f8c184 100644 --- a/CMakeExternals/tinyxml.cmake +++ b/CMakeExternals/tinyxml2.cmake @@ -1,52 +1,52 @@ #----------------------------------------------------------------------------- -# tinyxml +# tinyxml2 #----------------------------------------------------------------------------- # Sanity checks -if(DEFINED tinyxml_DIR AND NOT EXISTS ${tinyxml_DIR}) - message(FATAL_ERROR "tinyxml_DIR variable is defined but corresponds to non-existing directory") +if(DEFINED tinyxml2_DIR AND NOT EXISTS ${tinyxml2_DIR}) + message(FATAL_ERROR "tinyxml2_DIR variable is defined but corresponds to non-existing directory") endif() -set(proj tinyxml) +set(proj tinyxml2) set(proj_DEPENDENCIES ) set(${proj}_DEPENDS ${proj}) -if(NOT DEFINED tinyxml_DIR) +if(NOT DEFINED tinyxml2_DIR) set(additional_cmake_args ) if(WIN32) set(additional_cmake_args -DBUILD_SHARED_LIBS:BOOL=OFF) endif() if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/tinyxml_2_6_2.tar.gz - URL_MD5 c1b864c96804a10526540c664ade67f0 - PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/tinyxml-2.6.2.patch - COMMAND ${CMAKE_COMMAND} -Dproj=${proj} -Dproj_target:STRING=tinyxml -P ${CMAKE_CURRENT_LIST_DIR}/GenerateDefaultCMakeBuildSystem.cmake + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/tinyxml2-8.0.0.tar.gz + URL_MD5 5dc535c8b34ee621fe2128f072d275b5 CMAKE_GENERATOR ${gen} CMAKE_GENERATOR_PLATFORM ${gen_platform} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} CMAKE_CACHE_ARGS ${ep_common_cache_args} + -DBUILD_TESTING:BOOL=OFF + -DBUILD_TESTS:BOOL=OFF CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(${proj}_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/tinyxmlCMakeLists.txt b/CMakeExternals/tinyxmlCMakeLists.txt deleted file mode 100644 index d19c0dfb25..0000000000 --- a/CMakeExternals/tinyxmlCMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -cmake_minimum_required(VERSION 2.8.4) - -project(tinyxml) - -set(${PROJECT_NAME}_MAJOR_VERSION 2) -set(${PROJECT_NAME}_MINOR_VERSION 6) -set(${PROJECT_NAME}_PATCH_VERSION 2) -set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}.${${PROJECT_NAME}_PATCH_VERSION}) - - -set(tinyxml_HEADERS - tinystr.h - tinyxml.h -) - -set(tinyxml_SOURCES - tinyxml.cpp - tinyxmlparser.cpp - tinyxmlerror.cpp - tinystr.cpp -) - -add_library(tinyxml ${tinyxml_HEADERS} ${tinyxml_SOURCES}) -set_target_properties(tinyxml PROPERTIES - SOVERSION ${${PROJECT_NAME}_VERSION}) - -set(${PROJECT_NAME}_LIBRARIES tinyxml) - -# Install support - -install(TARGETS ${${PROJECT_NAME}_LIBRARIES} EXPORT ${PROJECT_NAME}_TARGETS - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - RUNTIME DESTINATION bin - INCLUDES DESTINATION include/${PROJECT_NAME} -) -install(FILES ${tinyxml_HEADERS} - DESTINATION include/${PROJECT_NAME} -) - -# Config files -configure_file( - ${PROJECT_NAME}Config.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake - @ONLY -) -configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}ConfigVersion.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake - @ONLY -) - -export(EXPORT ${PROJECT_NAME}_TARGETS - FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake -) - -set(config_package_location lib/cmake/${PROJECT_NAME}) -install(EXPORT ${PROJECT_NAME}_TARGETS - FILE ${PROJECT_NAME}Targets.cmake - DESTINATION ${config_package_location} -) -install(FILES - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - DESTINATION ${config_package_location} -) diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox index 5babea66ab..2b93804d69 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox @@ -1,107 +1,107 @@ /** \page thirdpartylibs Third-party libraries The following third-party libraries can be used with MITK by default and can, in part, be automatically downloaded during superbuild. \par ANN https://www.cs.umd.edu/~mount/ANN/ \par Boost https://www.boost.org/ \par C++ REST SDK https://github.com/Microsoft/cpprestsdk/ \par CppUnit https://sourceforge.net/projects/cppunit/ \par CTK https://commontk.org/ \par DCMTK https://dicom.offis.de/dcmtk \par Eigen http://eigen.tuxfamily.org/index.php?title=Main_Page \par GDCM https://gdcm.sourceforge.net/ \par HDF5 https://support.hdfgroup.org/HDF5/ \par ITK https://itk.org/ \par MatchPoint https://www.dkfz.de/en/sidt/projects/MatchPoint/info.html \par OpenCL https://www.khronos.org/opencl/ \par OpenCV https://opencv.org/ \par OpenIGTLink http://openigtlink.org/ \par OpenMesh https://www.openmesh.org/ \par PCRE https://www.pcre.org/ \par POCO https://pocoproject.org/ \par Python https://www.python.org/ \par Qt https://www.qt.io/ \par Qwt http://qwt.sourceforge.net/ \par SWIG http://www.swig.org/ -\par tinyxml +\par TinyXML-2 -http://www.grinninglizard.com/tinyxml/ +http://www.grinninglizard.com/tinyxml2/ \par VIGRA https://ukoethe.github.io/vigra/ \par VTK https://vtk.org/ \par zlib https://zlib.net/ For copyright information on any of the above toolkits see the corresponding home page or the corresponding source folder. */ diff --git a/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt b/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt index 24b2612a99..06b8804507 100644 --- a/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt +++ b/Examples/FirstSteps/NewModule/autoload/IO/CMakeLists.txt @@ -1,8 +1,14 @@ MITK_CREATE_MODULE( NewModuleIO INCLUDE_DIRS PRIVATE src/IO DEPENDS PUBLIC MitkNewModule MitkSceneSerialization PACKAGE_DEPENDS - PRIVATE tinyxml + PRIVATE tinyxml2|tinyxml2 AUTOLOAD_WITH MitkCore ) + +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} + PRIVATE tinyxml2::tinyxml2 + ) +endif() diff --git a/Modules/CEST/autoload/IO/resource/cest_DKFZ.xml b/Modules/CEST/autoload/IO/resource/cest_DKFZ.xml index b87f554740..6a35902e76 100644 --- a/Modules/CEST/autoload/IO/resource/cest_DKFZ.xml +++ b/Modules/CEST/autoload/IO/resource/cest_DKFZ.xml @@ -1,11 +1,11 @@ - + - \ No newline at end of file + diff --git a/Modules/CameraCalibration/mitkCameraIntrinsics.cpp b/Modules/CameraCalibration/mitkCameraIntrinsics.cpp index cb81b0f60b..fbb1ce2894 100644 --- a/Modules/CameraCalibration/mitkCameraIntrinsics.cpp +++ b/Modules/CameraCalibration/mitkCameraIntrinsics.cpp @@ -1,507 +1,508 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkCameraIntrinsics.h" #include #include #include +#include mitk::CameraIntrinsics::CameraIntrinsics() : m_Valid(false), m_Mutex(itk::FastMutexLock::New()) { m_CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); m_CameraMatrix.at(2,2) = 1.0; m_DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); } mitk::CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics& other) : itk::Object() , mitk::XMLSerializable() , m_Valid(false) , m_Mutex(itk::FastMutexLock::New()) { this->Copy(&other); } mitk::CameraIntrinsics::~CameraIntrinsics() { } bool mitk::CameraIntrinsics::Equals( const CameraIntrinsics* other ) const { return other->GetDistorsionCoeffsAsPoint4D()== this->GetDistorsionCoeffsAsPoint4D() && other->GetFocalPoint()== this->GetFocalPoint() && other->GetPrincipalPoint() == this->GetPrincipalPoint(); } void mitk::CameraIntrinsics::Copy(const CameraIntrinsics* other) { this->SetIntrinsics( other->GetCameraMatrix().clone() , other->GetDistorsionCoeffs().clone() ); this->SetValid(other->m_Valid); } bool mitk::CameraIntrinsics::IsValid() const { itk::MutexLockHolder lock(*m_Mutex); return m_Valid; } vnl_matrix_fixed mitk::CameraIntrinsics::GetVnlCameraMatrix() const { vnl_matrix_fixed mat; mat.set_identity(); { itk::MutexLockHolder lock(*m_Mutex); mat(0,0) = m_CameraMatrix.at(0,0); mat(1,1) = m_CameraMatrix.at(1,1); mat(0,2) = m_CameraMatrix.at(0,2); mat(1,2) = m_CameraMatrix.at(1,2); } return mat; } void mitk::CameraIntrinsics::SetCameraMatrix( const vnl_matrix_fixed& _CameraMatrix ) { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,0) = _CameraMatrix(0,0); m_CameraMatrix.at(1,1) = _CameraMatrix(1,1); m_CameraMatrix.at(0,2) = _CameraMatrix(0,2); m_CameraMatrix.at(1,2) = _CameraMatrix(1,2); } vnl_matrix_fixed mitk::CameraIntrinsics::GetVnlCameraMatrix3x4() const { vnl_matrix_fixed mat; mat.fill(0); mat.update( this->GetVnlCameraMatrix().as_matrix() ); return mat; } void mitk::CameraIntrinsics::SetIntrinsics( const cv::Mat& _CameraMatrix , const cv::Mat& _DistorsionCoeffs) { { itk::MutexLockHolder lock(*m_Mutex); if( _CameraMatrix.cols != 3 || _CameraMatrix.rows != 3) throw std::invalid_argument("Wrong format of camera matrix. Should be 3x3" " double."); endoAssertMsg( (_DistorsionCoeffs.cols == 5) && _DistorsionCoeffs.rows == 1, "Wrong format of distorsion coefficients" " vector. Should be 5x1 double."); m_CameraMatrix = _CameraMatrix.clone(); m_DistorsionCoeffs = _DistorsionCoeffs.clone(); m_Valid = true; } this->Modified(); } void mitk::CameraIntrinsics::SetIntrinsics( const mitk::Point3D& focalPoint, const mitk::Point3D& principalPoint, const mitk::Point4D& distortionCoefficients) { { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,0) = focalPoint[0]; m_CameraMatrix.at(1,1) = focalPoint[1]; m_CameraMatrix.at(0,2) = principalPoint[0]; m_CameraMatrix.at(1,2) = principalPoint[1]; m_DistorsionCoeffs.at(0,0) = distortionCoefficients[0]; m_DistorsionCoeffs.at(0,1) = distortionCoefficients[1]; m_DistorsionCoeffs.at(0,2) = distortionCoefficients[2]; m_DistorsionCoeffs.at(0,3) = distortionCoefficients[3]; } this->Modified(); } void mitk::CameraIntrinsics::SetFocalLength( double x, double y ) { { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,0) = x; m_CameraMatrix.at(1,1) = y; } this->Modified(); } void mitk::CameraIntrinsics::SetPrincipalPoint( double x, double y ) { { itk::MutexLockHolder lock(*m_Mutex); m_CameraMatrix.at(0,2) = x; m_CameraMatrix.at(1,2) = y; } this->Modified(); } void mitk::CameraIntrinsics::SetDistorsionCoeffs( double k1, double k2, double p1, double p2 ) { { itk::MutexLockHolder lock(*m_Mutex); m_DistorsionCoeffs.at(0,0) = k1; m_DistorsionCoeffs.at(0,1) = k2; m_DistorsionCoeffs.at(0,2) = p1; m_DistorsionCoeffs.at(0,3) = p2; } this->Modified(); } cv::Mat mitk::CameraIntrinsics::GetCameraMatrix() const { itk::MutexLockHolder lock(*m_Mutex); return m_CameraMatrix.clone(); // return a copy of this small matrix } cv::Mat mitk::CameraIntrinsics::GetDistorsionCoeffs() const { itk::MutexLockHolder lock(*m_Mutex); return m_DistorsionCoeffs.clone(); // return a copy of this small matrix } cv::Mat mitk::CameraIntrinsics::GetDistorsionCoeffs() { const CameraIntrinsics* intrinsics = this; return intrinsics->GetDistorsionCoeffs(); } std::string mitk::CameraIntrinsics::ToString() const { itk::MutexLockHolder lock(*m_Mutex); std::ostringstream s; s.precision(12); const cv::Mat& CameraMatrix = m_CameraMatrix; const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs; s.str(""); s << this->GetNameOfClass() << ": "; s << "fx = " << CameraMatrix.at(0,0); s << ", fy = " << CameraMatrix.at(1,1); s << ", cx = " << CameraMatrix.at(0,2); s << ", cy = " << CameraMatrix.at(1,2); s << ", k1 = " << DistorsionCoeffs.at(0,0); s << ", k2 = " << DistorsionCoeffs.at(0,1); s << ", p1 = " << DistorsionCoeffs.at(0,2); s << ", p2 = " << DistorsionCoeffs.at(0,3); //s << ", k3 = " << DistorsionCoeffs.at(0,4); return s.str(); } -void mitk::CameraIntrinsics::ToXML(TiXmlElement* elem) const +void mitk::CameraIntrinsics::ToXML(tinyxml2::XMLElement* elem) const { itk::MutexLockHolder lock(*m_Mutex); elem->SetValue(this->GetNameOfClass()); std::ostringstream s; s.precision(12); const cv::Mat& CameraMatrix = m_CameraMatrix; s.str(""); s << CameraMatrix.at(0,0); - elem->SetAttribute( "fx", s.str() ); + elem->SetAttribute( "fx", s.str().c_str() ); s.str(""); s << CameraMatrix.at(1,1); - elem->SetAttribute( "fy", s.str() ); + elem->SetAttribute( "fy", s.str().c_str()); s.str(""); s << CameraMatrix.at(0,2); - elem->SetAttribute( "cx", s.str() ); + elem->SetAttribute( "cx", s.str().c_str()); s.str(""); s << CameraMatrix.at(1,2); - elem->SetAttribute( "cy", s.str() ); + elem->SetAttribute( "cy", s.str().c_str()); const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs; s.str(""); s << DistorsionCoeffs.at(0,0); - elem->SetAttribute( "k1", s.str() ); + elem->SetAttribute( "k1", s.str().c_str()); s.str(""); s << DistorsionCoeffs.at(0,1); - elem->SetAttribute( "k2", s.str() ); + elem->SetAttribute( "k2", s.str().c_str()); s.str(""); s << DistorsionCoeffs.at(0,2); - elem->SetAttribute( "p1", s.str() ); + elem->SetAttribute( "p1", s.str().c_str()); s.str(""); s << DistorsionCoeffs.at(0,3); - elem->SetAttribute( "p2", s.str() ); - elem->SetAttribute("Valid", m_Valid); + elem->SetAttribute( "p2", s.str().c_str()); + elem->SetAttribute("Valid", static_cast(m_Valid)); //s.str(""); s << DistorsionCoeffs.at(4,0); - //elem->SetAttribute( "k3", s.str() ); + //elem->SetAttribute( "k3", s.str().c_str() ); } -void mitk::CameraIntrinsics::FromGMLCalibrationXML(TiXmlElement* elem) +void mitk::CameraIntrinsics::FromGMLCalibrationXML(const tinyxml2::XMLElement* elem) { assert( elem ); - assert( elem->ValueStr() == "results" ); + assert( std::string(elem->Value()) == "results" ); cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); CameraMatrix.at(2,2) = 1.0; cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); - TiXmlElement* focus_lenXElem = elem->FirstChildElement("focus_lenX"); + const auto* focus_lenXElem = elem->FirstChildElement("focus_lenX"); endoAssert( focus_lenXElem != nullptr ); CameraMatrix.at(0,0) = atof( focus_lenXElem->GetText() ); - TiXmlElement* focus_lenYElem = elem->FirstChildElement("focus_lenY"); + const auto* focus_lenYElem = elem->FirstChildElement("focus_lenY"); endoAssert( focus_lenYElem != nullptr ); CameraMatrix.at(1,1) = atof( focus_lenYElem->GetText() ); - TiXmlElement* PrincipalXElem = elem->FirstChildElement("PrincipalX"); + const auto* PrincipalXElem = elem->FirstChildElement("PrincipalX"); endoAssert( PrincipalXElem != nullptr ); CameraMatrix.at(0,2) = atof( PrincipalXElem->GetText() ); - TiXmlElement* PrincipalYElem = elem->FirstChildElement("PrincipalY"); + const auto* PrincipalYElem = elem->FirstChildElement("PrincipalY"); endoAssert( PrincipalYElem != nullptr ); CameraMatrix.at(1,2) = atof( PrincipalYElem->GetText() ); // DISTORSION COEFFS - TiXmlElement* Dist1Elem = elem->FirstChildElement("Dist1"); + const auto* Dist1Elem = elem->FirstChildElement("Dist1"); endoAssert( Dist1Elem != nullptr ); DistorsionCoeffs.at(0,0) = atof( Dist1Elem->GetText() ); - TiXmlElement* Dist2Elem = elem->FirstChildElement("Dist2"); + const auto* Dist2Elem = elem->FirstChildElement("Dist2"); endoAssert( Dist2Elem != nullptr ); DistorsionCoeffs.at(0,1) = atof( Dist2Elem->GetText() ); - TiXmlElement* Dist3Elem = elem->FirstChildElement("Dist3"); + const auto* Dist3Elem = elem->FirstChildElement("Dist3"); endoAssert( Dist3Elem != nullptr ); DistorsionCoeffs.at(0,2) = atof( Dist3Elem->GetText() ); - TiXmlElement* Dist4Elem = elem->FirstChildElement("Dist4"); + const auto* Dist4Elem = elem->FirstChildElement("Dist4"); endoAssert( Dist4Elem != nullptr ); DistorsionCoeffs.at(0,3) = atof( Dist4Elem->GetText() ); int valid = 0; elem->QueryIntAttribute("Valid", &valid); { itk::MutexLockHolder lock(*m_Mutex); m_Valid = static_cast(valid); m_CameraMatrix = CameraMatrix; m_DistorsionCoeffs = DistorsionCoeffs; } this->Modified(); } -void mitk::CameraIntrinsics::FromXML(TiXmlElement* elem) +void mitk::CameraIntrinsics::FromXML(const tinyxml2::XMLElement* elem) { endoAssert ( elem ); MITK_DEBUG << elem->Value(); - std::string filename; - if(elem->QueryStringAttribute("file", &filename) == TIXML_SUCCESS) + const char* filename = elem->Attribute("file"); + if(nullptr != filename) { this->FromXMLFile(filename); return; } else if(strcmp(elem->Value(), "CalibrationProject") == 0) { this->FromGMLCalibrationXML(elem->FirstChildElement("results")); return; } assert ( elem ); if(strcmp(elem->Value(), this->GetNameOfClass()) != 0) elem = elem->FirstChildElement(this->GetNameOfClass()); std::ostringstream err; // CAMERA MATRIX cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); CameraMatrix.at(2,2) = 1.0; double val = 0.0; - if(elem->QueryDoubleAttribute("fx", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("fx", &val) == tinyxml2::XML_SUCCESS) CameraMatrix.at(0,0) = val; else err << "fx, "; - if(elem->QueryDoubleAttribute("fy", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("fy", &val) == tinyxml2::XML_SUCCESS) CameraMatrix.at(1,1) = val; else err << "fy, "; - if(elem->QueryDoubleAttribute("cx", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("cx", &val) == tinyxml2::XML_SUCCESS) CameraMatrix.at(0,2) = val; else err << "cx, "; - if(elem->QueryDoubleAttribute("cy", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("cy", &val) == tinyxml2::XML_SUCCESS) CameraMatrix.at(1,2) = val; else err << "cy, "; // DISTORSION COEFFS endodebug( "creating DistorsionCoeffs from XML file") cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); - if(elem->QueryDoubleAttribute("k1", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("k1", &val) == tinyxml2::XML_SUCCESS) DistorsionCoeffs.at(0,0) = val; else err << "k1, "; - if(elem->QueryDoubleAttribute("k2", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("k2", &val) == tinyxml2::XML_SUCCESS) DistorsionCoeffs.at(0,1) = val; else err << "k2, "; - if(elem->QueryDoubleAttribute("p1", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("p1", &val) == tinyxml2::XML_SUCCESS) DistorsionCoeffs.at(0,2) = val; else err << "p1, "; - if(elem->QueryDoubleAttribute("p2", &val) == TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("p2", &val) == tinyxml2::XML_SUCCESS) DistorsionCoeffs.at(0,3) = val; else err << "p2, "; DistorsionCoeffs.at(0,4) = 0.0; - /*if(elem->QueryDoubleAttribute("k3", &val) == TIXML_SUCCESS) + /*if(elem->QueryDoubleAttribute("k3", &val) == tinyxml2::XML_SUCCESS) DistorsionCoeffs.at(4,0) = val; else err << "k3, ";*/ std::string errorStr = err.str(); int errLength = errorStr.length(); if(errLength > 0) { errorStr = errorStr.substr(0, errLength-2); errorStr.append(" not found"); throw std::invalid_argument(err.str()); } int valid = 0; elem->QueryIntAttribute("Valid", &valid); { itk::MutexLockHolder lock(*m_Mutex); m_Valid = static_cast(valid); m_CameraMatrix = CameraMatrix; m_DistorsionCoeffs = DistorsionCoeffs; } this->Modified(); } double mitk::CameraIntrinsics::GetFocalLengthX() const { itk::MutexLockHolder lock(*m_Mutex); double FocalLengthX = m_CameraMatrix.at(0,0); return FocalLengthX; } double mitk::CameraIntrinsics::GetFocalLengthY() const { itk::MutexLockHolder lock(*m_Mutex); double FocalLengthY = m_CameraMatrix.at(1,1);; return FocalLengthY; } double mitk::CameraIntrinsics::GetPrincipalPointX() const { itk::MutexLockHolder lock(*m_Mutex); double PrincipalPointX = m_CameraMatrix.at(0,2); return PrincipalPointX; } double mitk::CameraIntrinsics::GetPrincipalPointY() const { itk::MutexLockHolder lock(*m_Mutex); double PrincipalPointY = m_CameraMatrix.at(1,2); return PrincipalPointY; } mitk::Point4D mitk::CameraIntrinsics::GetDistorsionCoeffsAsPoint4D() const { itk::MutexLockHolder lock(*m_Mutex); mitk::Point4D coeffs; coeffs[0] = m_DistorsionCoeffs.at(0,0); coeffs[1] = m_DistorsionCoeffs.at(0,1); coeffs[2] = m_DistorsionCoeffs.at(0,2); coeffs[3] = m_DistorsionCoeffs.at(0,3); return coeffs; } mitk::Point3D mitk::CameraIntrinsics::GetFocalPoint() const { mitk::Point3D p; p[0] = this->GetFocalLengthX(); p[1] = this->GetFocalLengthY(); p[2] = 0; return p; } mitk::Point3D mitk::CameraIntrinsics::GetPrincipalPoint() const { mitk::Point3D p; p[0] = this->GetPrincipalPointX(); p[1] = this->GetPrincipalPointY(); p[2] = 0; return p; } vnl_vector_fixed mitk::CameraIntrinsics::GetFocalPointAsVnlVector() const { vnl_vector_fixed vec; vec[0] = this->GetFocalLengthX(); vec[1] = this->GetFocalLengthY(); return vec; } vnl_vector_fixed mitk::CameraIntrinsics::GetPrincipalPointAsVnlVector() const { vnl_vector_fixed vec; vec[0] = this->GetPrincipalPointX(); vec[1] = this->GetPrincipalPointY(); return vec; } std::ostream& operator<< (std::ostream& os, mitk::CameraIntrinsics::Pointer p) { os << p->ToString(); return os; } std::string mitk::CameraIntrinsics::GetString() { return this->ToString(); } std::string mitk::CameraIntrinsics::ToOctaveString( const std::string& varName) { std::ostringstream s; s << varName << " = [" << this->GetFocalLengthX() << " 0 " << this->GetPrincipalPointX() << "; 0 " << this->GetFocalLengthY() << " " << this->GetPrincipalPointY() << ";" << " 0 0 1 ];"; return s.str(); } void mitk::CameraIntrinsics::SetValid( bool valid ) { itk::MutexLockHolder lock(*m_Mutex); m_Valid = valid; } itk::LightObject::Pointer mitk::CameraIntrinsics::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); result->UnRegister(); return result; } diff --git a/Modules/CameraCalibration/mitkCameraIntrinsics.h b/Modules/CameraCalibration/mitkCameraIntrinsics.h index a6004b8960..a36cbf0a7f 100644 --- a/Modules/CameraCalibration/mitkCameraIntrinsics.h +++ b/Modules/CameraCalibration/mitkCameraIntrinsics.h @@ -1,141 +1,141 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkCameraIntrinsics_h #define mitkCameraIntrinsics_h #include #include #include #include #include #include "mitkXMLSerializable.h" #include #include "opencv2/core.hpp" int mitkCameraIntrinsicsTest(int, char* []); namespace mitk { /// /// \brief class representing camera intrinsics and related functions /// class MITKCAMERACALIBRATION_EXPORT CameraIntrinsics: virtual public itk::Object, virtual public mitk::XMLSerializable { public: /// /// for testing purposes /// friend int mitkCameraIntrinsicsTest(int argc, char* argv[]); /// /// smartpointer typedefs /// mitkClassMacroItkParent(CameraIntrinsics, itk::Object); /// /// the static new function /// itkFactorylessNewMacro(Self); /// /// make a clone of this intrinsics /// itkCloneMacro(Self); /// /// copy information from other to this /// void Copy(const CameraIntrinsics* other); /// /// checks two intrinsics for equality /// bool Equals( const CameraIntrinsics* other ) const; /// /// \return the intrinsic parameter matrix as a 3x3 vnl matrix /// vnl_matrix_fixed GetVnlCameraMatrix() const; /// /// \return the intrinsic parameter matrix as a 3x4 vnl matrix /// (the last column only containing zeros) /// vnl_matrix_fixed GetVnlCameraMatrix3x4() const; /// /// \return true if the intrinsics are set (some plausibility checks /// may be done here) /// bool IsValid() const; void SetValid(bool valid); cv::Mat GetCameraMatrix() const; cv::Mat GetDistorsionCoeffs(); cv::Mat GetDistorsionCoeffs() const; - void ToXML(TiXmlElement* elem) const override; + void ToXML(tinyxml2::XMLElement* elem) const override; std::string ToString() const; std::string GetString(); double GetFocalLengthX() const; double GetFocalLengthY() const; double GetPrincipalPointX() const; double GetPrincipalPointY() const; mitk::Point4D GetDistorsionCoeffsAsPoint4D() const; mitk::Point3D GetFocalPoint() const; mitk::Point3D GetPrincipalPoint() const; vnl_vector_fixed GetFocalPointAsVnlVector() const; vnl_vector_fixed GetPrincipalPointAsVnlVector() const; /// /// set a new camera matrix utilizing a vnl matrix /// void SetCameraMatrix( const vnl_matrix_fixed& _CameraMatrix ); void SetIntrinsics( const cv::Mat& _CameraMatrix , const cv::Mat& _DistorsionCoeffs); void SetFocalLength( double x, double y ); void SetPrincipalPoint( double x, double y ); void SetDistorsionCoeffs( double k1, double k2, double p1, double p2 ); void SetIntrinsics( const mitk::Point3D& focalPoint, const mitk::Point3D& principalPoint, const mitk::Point4D& distortionCoefficients); - void FromXML(TiXmlElement* elem) override; - void FromGMLCalibrationXML(TiXmlElement* elem); + void FromXML(const tinyxml2::XMLElement* elem) override; + void FromGMLCalibrationXML(const tinyxml2::XMLElement* elem); std::string ToOctaveString(const std::string& varName="CameraIntrinsics"); ~CameraIntrinsics() override; protected: CameraIntrinsics(); CameraIntrinsics(const CameraIntrinsics& other); cv::Mat m_CameraMatrix; cv::Mat m_DistorsionCoeffs; bool m_Valid; itk::FastMutexLock::Pointer m_Mutex; private: itk::LightObject::Pointer InternalClone() const override; }; } // namespace mitk MITKCAMERACALIBRATION_EXPORT std::ostream& operator<< (std::ostream& os, mitk::CameraIntrinsics::Pointer p); #endif // mitkCameraIntrinsics_h diff --git a/Modules/CameraCalibration/mitkEndoDebugFromXmlFile.cpp b/Modules/CameraCalibration/mitkEndoDebugFromXmlFile.cpp index a88a588b80..e9b827e034 100644 --- a/Modules/CameraCalibration/mitkEndoDebugFromXmlFile.cpp +++ b/Modules/CameraCalibration/mitkEndoDebugFromXmlFile.cpp @@ -1,159 +1,169 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkEndoDebugFromXmlFile.h" #include -#include +#include #include using namespace std; namespace mitk { struct EndoDebugFromXmlFileData { const std::string* m_FileName; // private EndoDebug* m_EndoDebug; long int m_FileModifiedTime; }; EndoDebugFromXmlFile::EndoDebugFromXmlFile( const std::string* _FileName, EndoDebug* _EndoDebug ) : d( new EndoDebugFromXmlFileData ) { d->m_FileName = _FileName; d->m_EndoDebug = _EndoDebug; d->m_FileModifiedTime = 0; } EndoDebugFromXmlFile::~EndoDebugFromXmlFile() { delete d; } void StringExplode(string str, string separator, set* results){ std::size_t found; found = str.find_first_of(separator); while(found != string::npos){ if(found != 0){ results->insert(str.substr(0,found)); } str = str.substr(found+1); found = str.find_first_of(separator); } if(!str.empty()){ results->insert(str); } } #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable:4390) #endif void EndoDebugFromXmlFile::Update() { endodebug( __FUNCTION__ ) std::string _FileName = *d->m_FileName; if( !itksys::SystemTools::FileExists( _FileName.c_str() ) ) { endodebug(_FileName << " does not exist"); return; } long int _FileModifiedTime = itksys::SystemTools::ModifiedTime( _FileName.c_str() ); // file has changed: we know an older version... if( d->m_FileModifiedTime >= _FileModifiedTime ) { endodebug("File not changed. No Update necessary."); return; } // reread - endodebugvar( _FileName ) - TiXmlDocument doc( _FileName ); - doc.LoadFile(); - TiXmlHandle docHandle( &doc ); - TiXmlElement* elem = docHandle.FirstChildElement().FirstChildElement( "EndoDebug" ).ToElement(); + endodebugvar(_FileName) + tinyxml2::XMLDocument doc; + doc.LoadFile(_FileName.c_str()); + tinyxml2::XMLHandle docHandle(&doc); + auto* elem = docHandle.FirstChildElement().FirstChildElement( "EndoDebug" ).ToElement(); if(elem == nullptr) { endodebug("EndoDebug element not found"); return; } int _DebugEnabled = d->m_EndoDebug->GetDebugEnabled(); - if( elem->QueryIntAttribute("DebugEnabled",&_DebugEnabled) != TIXML_SUCCESS ) + if( elem->QueryIntAttribute("DebugEnabled",&_DebugEnabled) != tinyxml2::XML_SUCCESS ) { endodebug("DebugEnabled attribute not found"); } int _ShowImagesInDebug = d->m_EndoDebug->GetShowImagesInDebug(); - if( elem->QueryIntAttribute("ShowImagesInDebug",&_ShowImagesInDebug) != TIXML_SUCCESS ) + if( elem->QueryIntAttribute("ShowImagesInDebug",&_ShowImagesInDebug) != tinyxml2::XML_SUCCESS) { endodebug("ShowImagesInDebug attribute not found"); } int _ShowImagesTimeOut = static_cast(d->m_EndoDebug->GetShowImagesTimeOut()); - if( elem->QueryIntAttribute("ShowImagesTimeOut",&_ShowImagesTimeOut) != TIXML_SUCCESS ) + if( elem->QueryIntAttribute("ShowImagesTimeOut",&_ShowImagesTimeOut) != tinyxml2::XML_SUCCESS) { endodebug("ShowImagesTimeOut attribute not found"); } - std::string _DebugImagesOutputDirectory = d->m_EndoDebug->GetDebugImagesOutputDirectory(); - if( elem->QueryStringAttribute("DebugImagesOutputDirectory",&_DebugImagesOutputDirectory) != TIXML_SUCCESS ) + std::string _DebugImagesOutputDirectory; + const char* _DebugImagesOutputDirectoryC = elem->Attribute("DebugImagesOutputDirectory"); + if(nullptr == _DebugImagesOutputDirectoryC) { + _DebugImagesOutputDirectory = d->m_EndoDebug->GetDebugImagesOutputDirectory(); endodebug("DebugImagesOutputDirectory attribute not found"); } + else + { + _DebugImagesOutputDirectory = _DebugImagesOutputDirectoryC; + } std::set _FilesToDebug; std::string _FilesToDebugString; - if( elem->QueryStringAttribute("FilesToDebug",&_FilesToDebugString) != TIXML_SUCCESS ) + const char* _FilesToDebugStringC = elem->Attribute("FilesToDebug"); + if(nullptr == _FilesToDebugStringC) { endodebug("FilesToDebug attribute not found"); } else { - StringExplode( _FilesToDebugString, ";", &_FilesToDebug ); + _FilesToDebugString = _FilesToDebugStringC; + StringExplode( _FilesToDebugString, ";", &_FilesToDebug ); } std::set _SymbolsToDebug; std::string _SymbolsToDebugString; - if( elem->QueryStringAttribute("SymbolsToDebug",&_SymbolsToDebugString) != TIXML_SUCCESS ) + const char* _SymbolsToDebugStringC = elem->Attribute("SymbolsToDebug"); + if( nullptr == _SymbolsToDebugStringC ) { endodebug("SymbolsToDebug attribute not found"); } else { - StringExplode( _SymbolsToDebugString, ";", &_SymbolsToDebug ); + _SymbolsToDebugString = _SymbolsToDebugStringC; + StringExplode( _SymbolsToDebugString, ";", &_SymbolsToDebug ); } // save mitk::EndoDebug::GetInstance().SetDebugEnabled( _DebugEnabled == 1? true: false ); mitk::EndoDebug::GetInstance().SetShowImagesInDebug( _ShowImagesInDebug == 1? true: false ); mitk::EndoDebug::GetInstance().SetShowImagesTimeOut( _ShowImagesTimeOut ); mitk::EndoDebug::GetInstance().SetDebugImagesOutputDirectory( _DebugImagesOutputDirectory ); mitk::EndoDebug::GetInstance().SetFilesToDebug(_FilesToDebug); mitk::EndoDebug::GetInstance().SetSymbolsToDebug(_SymbolsToDebug); // save that modified time d->m_FileModifiedTime = _FileModifiedTime; } #ifdef _MSC_VER # pragma warning(pop) #endif } diff --git a/Modules/CameraCalibration/mitkEndoDebugToXmlFile.cpp b/Modules/CameraCalibration/mitkEndoDebugToXmlFile.cpp index 8e0a52463c..82a0e184c1 100644 --- a/Modules/CameraCalibration/mitkEndoDebugToXmlFile.cpp +++ b/Modules/CameraCalibration/mitkEndoDebugToXmlFile.cpp @@ -1,121 +1,122 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkEndoDebugToXmlFile.h" -#include +#include namespace mitk { struct EndoDebugToXmlFileData { EndoDebug* m_EndoDebug; const std::string* m_FileName; }; EndoDebugToXmlFile::EndoDebugToXmlFile(EndoDebug *_EndoDebug, const std::string* _FileName) : d( new EndoDebugToXmlFileData ) { d->m_EndoDebug = _EndoDebug; d->m_FileName = _FileName; } EndoDebugToXmlFile::~EndoDebugToXmlFile() { delete d; } void EndoDebugToXmlFile::Update() { std::string _FileName = *d->m_FileName; - TiXmlDocument doc( _FileName.c_str() ); - TiXmlElement* root = nullptr; - TiXmlElement* elem = nullptr; + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = nullptr; + tinyxml2::XMLElement* elem = nullptr; // check if element is already available - if(doc.LoadFile()) + if(tinyxml2::XML_SUCCESS == doc.LoadFile(_FileName.c_str())) { root = doc.FirstChildElement("data"); - if(root) + if(nullptr != root) { elem = root->FirstChildElement( "EndoDebug" ); - if(elem) - root->RemoveChild(elem); - elem = nullptr; + if (nullptr != elem) + { + root->DeleteChild(elem); + elem = nullptr; + } } } else { // document did not exist, create new one with declration - auto decl = new TiXmlDeclaration( "1.0", "", "" ); - doc.LinkEndChild( decl ); + doc.InsertEndChild( doc.NewDeclaration() ); // create root - root = new TiXmlElement( "data" ); - doc.LinkEndChild( root ); + root = doc.NewElement( "data" ); + doc.InsertEndChild( root ); } // create elem if not existent - elem = new TiXmlElement( "EndoDebug" ); + elem = doc.NewElement( "EndoDebug" ); elem->SetAttribute( "DebugEnabled", (d->m_EndoDebug->GetDebugEnabled()? 1:0) ); elem->SetAttribute( "ShowImagesInDebug", (d->m_EndoDebug->GetShowImagesInDebug()? 1:0) ); elem->SetAttribute( "ShowImagesTimeOut", (static_cast(d->m_EndoDebug->GetShowImagesTimeOut())) ); elem->SetAttribute( "DebugImagesOutputDirectory", - d->m_EndoDebug->GetDebugImagesOutputDirectory() ); + d->m_EndoDebug->GetDebugImagesOutputDirectory().c_str() ); std::set _FilesToDebug = d->m_EndoDebug->GetFilesToDebug(); std::string _FilesToDebugString; auto it = _FilesToDebug.begin(); while( it != _FilesToDebug.end() ) { if( it != _FilesToDebug.begin() ) _FilesToDebugString.append( ";" ); _FilesToDebugString.append( *it ); ++it; } - elem->SetAttribute( "FilesToDebug", _FilesToDebugString ); + elem->SetAttribute( "FilesToDebug", _FilesToDebugString.c_str() ); std::set _SymbolsToDebug = d->m_EndoDebug->GetSymbolsToDebug(); std::string _SymbolsToDebugString; it = _SymbolsToDebug.begin(); while( it != _SymbolsToDebug.end() ) { if( it != _SymbolsToDebug.begin() ) _SymbolsToDebugString.append( ";" ); _SymbolsToDebugString.append( *it ); ++it; } - elem->SetAttribute( "SymbolsToDebug", _SymbolsToDebugString ); + elem->SetAttribute( "SymbolsToDebug", _SymbolsToDebugString.c_str() ); endodebug("adding the EndoDebug as child element of the data node") - root->LinkEndChild(elem); + root->InsertEndChild(elem); endodebug("saving file " << _FileName) - if( !doc.SaveFile( _FileName ) ) + if( tinyxml2::XML_SUCCESS != doc.SaveFile( _FileName.c_str() ) ) { endodebug("File " << _FileName << " could not be written. Please check permissions."); } } void EndoDebugToXmlFile::SetEndoDebug(EndoDebug *_EndoDebug) { d->m_EndoDebug = _EndoDebug; } void EndoDebugToXmlFile::SetFileName(const std::string *_FileName) { d->m_FileName = _FileName; } } diff --git a/Modules/CameraCalibration/mitkTransform.cpp b/Modules/CameraCalibration/mitkTransform.cpp index d77d2d87fe..0a65753afb 100644 --- a/Modules/CameraCalibration/mitkTransform.cpp +++ b/Modules/CameraCalibration/mitkTransform.cpp @@ -1,745 +1,750 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkTransform.h" #include #include #include #include #include #include +#include + namespace mitk { // DO NOT CHANGE THE VALUES OF THESE CONSTANTS!! const std::string Transform::UNKNOWN_TYPE = "Unknown type"; const std::string Transform::ENDOSCOPE_SCOPE_TOOL = "Endoscope scope tool"; const std::string Transform::ENDOSCOPE_CAM_TOOL = "Endoscope camera tool"; const std::string Transform::CHESSBOARD_TOOL = "Chessboard tool"; const std::string Transform::POINTER_TOOL = "Pointer tool"; const std::string Transform::POINTER_TO_CHESSBOARD_ORIGIN = "Pointer to chessboard origin"; const std::string Transform::POINTER_TO_CHESSBOARD_X_SUPPORT_POINT = "Pointer to chessboard X support origin"; const std::string Transform::POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT = "Pointer to chessboard Y support origin"; const std::string Transform::BOARD_TO_BOARD_TOOL = "Board to board tool"; const std::string Transform::REFERENCE_CAMERA_TRANSFORM = "Reference camera transform"; const std::string Transform::REFERENCE_SCOPE_TRANSFORM = "Reference scope transform"; const std::string Transform::EYE_TO_HAND_TRANSFORM = "Eye to hand transform"; const std::string Transform::CAMERA_EXTRINSICS = "Camera extrinsics"; Transform::Transform() : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { vnl_matrix_fixed rot; rot.set_identity(); this->SetRotation( rot ); } Transform::Transform(const mitk::NavigationData* nd) : m_NavData(mitk::NavigationData::New()), m_Type( UNKNOWN_TYPE ) { m_NavData->Graft(nd); } Transform::Transform(const std::string& s) : m_NavData(mitk::NavigationData::New()), m_Type( s ) { vnl_matrix_fixed rot; rot.set_identity(); this->SetRotation( rot ); } void Transform::Copy(const mitk::NavigationData* nd) { (const_cast(m_NavData.GetPointer()))->Graft(nd); } void Transform::Concatenate( mitk::Transform* transform ) { vnl_matrix_fixed mat = transform->GetMatrix(); mat = mat * this->GetMatrix(); // this->SetMatrix( mat ); } void Transform::Concatenate( const vnl_matrix_fixed& transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::Concatenate( const vtkMatrix4x4* transform ) { Transform::Pointer t = Transform::New(); t->SetMatrix( transform ); this->Concatenate( t ); } void Transform::Reset() { mitk::NavigationData::Pointer nd = NavigationData::New(); this->Copy( nd ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { m_NavData->SetOrientation(orientation); this->Modified(); } void Transform::SetTranslation( const vnl_vector_fixed& transl) { mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); this->Modified(); } void Transform::SetTranslation( float* array ) { vnl_vector_fixed vec; for(unsigned int i=0; iSetTranslation( vec ); } void Transform::SetRotation( float* array ) { vnl_matrix_fixed mat; unsigned int row = 0; unsigned int col = 0; for(unsigned int i=0; i 0 && i % 3 == 0 ) { ++row; col = 0; } mat(row,col) = array[i]; ++col; } this->SetRotation( mat ); } void Transform::SetOrientation( const vnl_quaternion& orientation) { vnl_vector_fixed qvec; VnlVectorFixedCaster caster( &orientation, &qvec ); caster.Update(); mitk::Quaternion p( qvec ); this->SetOrientation( p ); } vnl_vector_fixed Transform::GetVnlDoubleTranslation() const { vnl_vector_fixed vecFloat = this->GetVnlTranslation(); vnl_vector_fixed vecDouble; VnlVectorFixedCaster caster( &vecFloat, &vecDouble ); caster.Update(); return vecDouble; } void Transform::SetTranslation( const vnl_vector& transl) { vnl_vector_fixed dTransl(transl); vnl_vector_fixed fTransl; VnlVectorFixedCaster caster( &dTransl, &fTransl ); caster.Update(); this->SetTranslation( fTransl ); } vnl_quaternion Transform::GetVnlDoubleQuaternion() const { mitk::Quaternion fOrientation = this->GetOrientation(); vnl_quaternion dOrientation; VnlVectorFixedCaster caster( &fOrientation, &dOrientation ); caster.Update(); return dOrientation; } void Transform::FromCSVFile(const std::string& file) { std::ifstream csvFile (file.c_str()); endoAssert ( csvFile.fail() == false ); mitk::Transform::Pointer transform = mitk::Transform::New(); vnl_matrix_fixed mat; std::string line; mitk::ScalarType d = 0.0f; int row=0,column = 0; while (std::getline (csvFile, line)) { std::istringstream linestream(line); std::string item; column = 0; while (std::getline (linestream, item, ',')) { std::istringstream number; number.str(item); number >> d; mat(row, column) = d; ++column; } ++row; } endoAssert( row == 4 && column == 4 ); transform->SetMatrix( mat ); this->SetNavigationData( transform->GetNavigationData() ); // modified is called in SetNavigationData } std::string Transform::ToCSVString() const { std::ostringstream s; s.precision(12); vnl_matrix_fixed mat = this->GetMatrix(); for( unsigned int j=0; j mat = this->GetMatrix(); s << varname << " = ["; for( unsigned int j=0; jGraft(transform->GetNavigationData()); m_Type = transform->GetType(); } mitk::Transform::Pointer Transform::Clone() const { Transform::Pointer copy = Transform::New(); copy->Copy( this ); return copy; } void Transform::SetMatrix( const vtkMatrix4x4* mat) { vnl_matrix_fixed vnlMat; for(unsigned int i=0; i<4; ++i) for(unsigned int j=0; j<4; ++j) vnlMat(i,j) = mat->GetElement(i, j); this->SetMatrix( vnlMat ); } void Transform::ToCSVFile(const std::string& file) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToCSVString(); csvFile.close(); } void Transform::ToMatlabFile(const std::string& file , const std::string& varname) const { std::ofstream csvFile; csvFile.open(file.c_str()); endoAssert ( csvFile.fail() == false ); csvFile << this->ToMatlabString(varname); csvFile.close(); } void Transform::SetNavigationData( const mitk::NavigationData* naviData ) { endoAssert( naviData != nullptr ); m_NavData->Graft( naviData ); this->Modified(); } void Transform::SetRotation( vnl_matrix_fixed& mat) { this->m_NavData->SetOrientation( mitk::Quaternion(mat) ); this->Modified(); } void Transform::SetRotation( vnl_matrix& mat) { vnl_matrix_fixed tmp(mat); this->SetRotation( tmp ); } void Transform::SetPosition( const mitk::Point3D& transl) { this->SetTranslation( transl.GetVnlVector() ); } void Transform::SetTranslation( double array[3] ) { mitk::Point3D p; for(unsigned int i = 0; i < 3; ++i) p.SetElement(i, array[i]); this->SetTranslation( p.GetVnlVector() ); } void Transform::SetRotation( double array[3][3] ) { vnl_matrix_fixed mat; for(unsigned int i = 0; i < 3; ++i) for(unsigned int j = 0; j < 3; ++j) mat(i, j) = array[i][j]; this->SetRotation( mat ); } void Transform::Invert() { vnl_matrix_fixed tmp(this->GetMatrix()); this->SetMatrix( vnl_inverse( tmp ) ); } void Transform::SetMatrix( const vnl_matrix_fixed& mat) { // set translation first vnl_vector transl = mat.get_column(3); mitk::Point3D p; for(unsigned int i=0; i<3; ++i) p[i] = transl[i]; m_NavData->SetPosition(p); // set rotation vnl_matrix_fixed rotMatFixed( mat.extract(3,3)); this->SetRotation(rotMatFixed); } bool Transform::IsValid() const { return m_NavData->IsDataValid(); } void Transform::SetTranslation( const cv::Mat& transl) { vnl_vector vec(3); VnlVectorFromCvMat _VnlVectorFromCvMat( &transl, &vec ); _VnlVectorFromCvMat.Update(); this->SetTranslation( vnl_vector_fixed( vec ) ); } void Transform::SetRotation( const cv::Mat& mat ) { vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &mat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation(vnlMatFixed); } void Transform::SetRotationVector( const cv::Mat& rotVec ) { cv::Mat rotMat; cv::Rodrigues( rotVec, rotMat ); vnl_matrix vnlMat(3, 3); VnlMatrixFromCvMat _VnlMatrixFromCvMat( &rotMat, &vnlMat ); _VnlMatrixFromCvMat.Update(); vnl_matrix_fixed vnlMatFixed(vnlMat); this->SetRotation( vnlMatFixed ); } //# getter mitk::NavigationData::Pointer Transform::GetNavigationData() const { return m_NavData; } mitk::Point3D Transform::GetTranslation() const { return m_NavData->GetPosition(); } mitk::Point3D Transform::GetPosition() const { return m_NavData->GetPosition(); } mitk::Quaternion Transform::GetOrientation() const { return m_NavData->GetOrientation(); } void Transform::GetMatrix(vtkMatrix4x4* matrix) const { vnl_matrix_fixed vnlMat = this->GetMatrix(); for(unsigned int i=0; iSetElement(i,j, vnlMat(i,j)); } void Transform::GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const { vnl_matrix vnlRotation = this->GetVnlRotationMatrix().as_matrix(); // normalize rows of rotation matrix vnlRotation.normalize_rows(); vnl_matrix vnlInverseRotation(3,3); // invert rotation vnlInverseRotation = vnl_matrix_inverse(vnlRotation); vnl_vector vnlTranslation = this->GetPosition().GetVnlVector(); // rotate translation vector by inverse rotation P = P' vnlTranslation = vnlInverseRotation * vnlTranslation; vnlTranslation *= -1; // save -P' // set position mitk::Transform::Pointer tmp = mitk::Transform::New(); tmp->SetTranslation( vnlTranslation ); tmp->SetRotation( vnlRotation ); tmp->GetMatrix(matrix); } mitk::Point3D Transform::TransformPoint(mitk::Point3D point) const { itk::Matrix R(GetVnlRotationMatrix()); itk::Point pointR = (R * point); mitk::Point3D retPoint = pointR; retPoint[0] = pointR[0] + GetPosition()[0]; retPoint[1] = pointR[1] + GetPosition()[1]; retPoint[2] = pointR[2] + GetPosition()[2]; return retPoint; } //# cv getter cv::Mat Transform::GetCvTranslation() const { cv::Mat mat; vnl_vector vec = this->GetVnlTranslation().as_vector(); endodebugvar( vec ) CvMatFromVnlVector _CvMatFromVnlVector(&vec, &mat); _CvMatFromVnlVector.Update(); return mat; } cv::Mat Transform::GetCvRotationMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetVnlRotationMatrix().as_matrix(); endodebugvar( vec ) CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvMatrix() const { cv::Mat mat; vnl_matrix vec = this->GetMatrix().as_matrix(); CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); _CvMatFromVnlMatrix.Update(); return mat; } cv::Mat Transform::GetCvRotationVector() const { cv::Mat rotVec(3,1,cv::DataType::type); cv::Rodrigues( this->GetCvRotationMatrix(), rotVec ); return rotVec; } //# vnl getter vnl_vector_fixed Transform::GetVnlTranslation() const { vnl_vector_fixed vec(m_NavData->GetPosition() .GetVnlVector()); return vec; } vnl_matrix_fixed Transform::GetVnlRotationMatrix() const { return m_NavData->GetOrientation().rotation_matrix_transpose(); } vnl_matrix_fixed Transform::GetVnlDoubleMatrix() const { vnl_matrix_fixed mat = this->GetMatrix(); vnl_matrix_fixed doubleMat; for(unsigned int i=0; i( mat(i,j) ); return doubleMat; } vnl_matrix_fixed Transform::GetMatrix() const { vnl_vector_fixed transl = this->GetVnlTranslation(); vnl_matrix_fixed rot = this->GetVnlRotationMatrix(); vnl_matrix_fixed homMat; homMat.set_identity(); //std::cout << homMat << std::endl; for(unsigned int i=0; i rotMat = this->GetVnlRotationMatrix().transpose(); this->SetRotation( rotMat ); } void Transform::SetValid( bool valid ) { if( m_NavData->IsDataValid() == valid ) return; m_NavData->SetDataValid( valid ); this->Modified(); } std::string mitk::Transform::ToString() const { std::ostringstream s; s.precision(12); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); s << "Translation: [" << position[0] << ", " << position[1] << ", " << position[2] << "]"; s << ", orientation: [" << orientation[0] << ", " << orientation[1] << ", " << orientation[2] << ", " << orientation[3] << "]"; s << ", valid: [" << (this->IsValid()? "true": "false") << "]"; return s.str(); } - void mitk::Transform::ToXML(TiXmlElement* elem) const + void mitk::Transform::ToXML(tinyxml2::XMLElement* elem) const { - std::string value = elem->ValueStr(); + std::string value = elem->Value() != nullptr ? elem->Value() : ""; if(value.empty()) elem->SetValue(this->GetNameOfClass()); mitk::NavigationData::PositionType position; position.Fill(0.0); position = m_NavData->GetPosition(); mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); orientation = m_NavData->GetOrientation(); mitk::NavigationData::CovarianceMatrixType matrix; matrix.SetIdentity(); matrix = m_NavData->GetCovErrorMatrix(); bool hasPosition = true; hasPosition = m_NavData->GetHasPosition(); bool hasOrientation = true; hasOrientation = m_NavData->GetHasOrientation(); bool dataValid = false; dataValid = m_NavData->IsDataValid(); mitk::NavigationData::TimeStampType timestamp=0.0; - elem->SetAttribute("Type", m_Type); - elem->SetDoubleAttribute("Time", timestamp); - elem->SetDoubleAttribute("X", position[0]); - elem->SetDoubleAttribute("Y", position[1]); - elem->SetDoubleAttribute("Z", position[2]); - - elem->SetDoubleAttribute("QX", orientation[0]); - elem->SetDoubleAttribute("QY", orientation[1]); - elem->SetDoubleAttribute("QZ", orientation[2]); - elem->SetDoubleAttribute("QR", orientation[3]); - - elem->SetDoubleAttribute("C00", matrix[0][0]); - elem->SetDoubleAttribute("C01", matrix[0][1]); - elem->SetDoubleAttribute("C02", matrix[0][2]); - elem->SetDoubleAttribute("C03", matrix[0][3]); - elem->SetDoubleAttribute("C04", matrix[0][4]); - elem->SetDoubleAttribute("C05", matrix[0][5]); - elem->SetDoubleAttribute("C10", matrix[1][0]); - elem->SetDoubleAttribute("C11", matrix[1][1]); - elem->SetDoubleAttribute("C12", matrix[1][2]); - elem->SetDoubleAttribute("C13", matrix[1][3]); - elem->SetDoubleAttribute("C14", matrix[1][4]); - elem->SetDoubleAttribute("C15", matrix[1][5]); + elem->SetAttribute("Type", m_Type.c_str()); + elem->SetAttribute("Time", timestamp); + elem->SetAttribute("X", position[0]); + elem->SetAttribute("Y", position[1]); + elem->SetAttribute("Z", position[2]); + + elem->SetAttribute("QX", orientation[0]); + elem->SetAttribute("QY", orientation[1]); + elem->SetAttribute("QZ", orientation[2]); + elem->SetAttribute("QR", orientation[3]); + + elem->SetAttribute("C00", matrix[0][0]); + elem->SetAttribute("C01", matrix[0][1]); + elem->SetAttribute("C02", matrix[0][2]); + elem->SetAttribute("C03", matrix[0][3]); + elem->SetAttribute("C04", matrix[0][4]); + elem->SetAttribute("C05", matrix[0][5]); + elem->SetAttribute("C10", matrix[1][0]); + elem->SetAttribute("C11", matrix[1][1]); + elem->SetAttribute("C12", matrix[1][2]); + elem->SetAttribute("C13", matrix[1][3]); + elem->SetAttribute("C14", matrix[1][4]); + elem->SetAttribute("C15", matrix[1][5]); if (dataValid) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (hasOrientation) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (hasPosition) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); } - void mitk::Transform::FromXML(TiXmlElement* elem) + void mitk::Transform::FromXML(const tinyxml2::XMLElement* elem) { assert(elem); mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); mitk::NavigationData::TimeStampType timestamp = -1; mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); - std::string type = Transform::UNKNOWN_TYPE; - elem->QueryStringAttribute("Type", &type); + const char* typeC = elem->Attribute("Type"); + std::string type = nullptr == typeC + ? Transform::UNKNOWN_TYPE + : typeC; + elem->QueryDoubleAttribute("Time",×tamp); // position and orientation is mandatory! - if(elem->QueryDoubleAttribute("X", &position[0]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("X", &position[0]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No X position found in xml"); - if(elem->QueryDoubleAttribute("Y", &position[1]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("Y", &position[1]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No Y position found in xml"); - if(elem->QueryDoubleAttribute("Z", &position[2]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("Z", &position[2]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No Z position found in xml"); - if(elem->QueryDoubleAttribute("QX", &orientation[0]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("QX", &orientation[0]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No QX orientation found in xml"); - if(elem->QueryDoubleAttribute("QY", &orientation[1]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("QY", &orientation[1]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No QY orientation found in xml"); - if(elem->QueryDoubleAttribute("QZ", &orientation[2]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("QZ", &orientation[2]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No QZ orientation found in xml"); - if(elem->QueryDoubleAttribute("QR", &orientation[3]) != TIXML_SUCCESS) + if(elem->QueryDoubleAttribute("QR", &orientation[3]) != tinyxml2::XML_SUCCESS) throw std::invalid_argument("No QR orientation found in xml"); elem->QueryDoubleAttribute("C00", &matrix[0][0]); elem->QueryDoubleAttribute("C01", &matrix[0][1]); elem->QueryDoubleAttribute("C02", &matrix[0][2]); elem->QueryDoubleAttribute("C03", &matrix[0][3]); elem->QueryDoubleAttribute("C04", &matrix[0][4]); elem->QueryDoubleAttribute("C05", &matrix[0][5]); elem->QueryDoubleAttribute("C10", &matrix[1][0]); elem->QueryDoubleAttribute("C11", &matrix[1][1]); elem->QueryDoubleAttribute("C12", &matrix[1][2]); elem->QueryDoubleAttribute("C13", &matrix[1][3]); elem->QueryDoubleAttribute("C14", &matrix[1][4]); elem->QueryDoubleAttribute("C15", &matrix[1][5]); int tmpval = 0; elem->QueryIntAttribute("Valid", &tmpval); if (tmpval == 0) dataValid = false; else dataValid = true; tmpval = 0; elem->QueryIntAttribute("hO", &tmpval); if (tmpval == 0) hasOrientation = false; else hasOrientation = true; tmpval = 0; elem->QueryIntAttribute("hP", &tmpval); if (tmpval == 0) hasPosition = false; else hasPosition = true; nd->SetIGTTimeStamp(timestamp); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetCovErrorMatrix(matrix); nd->SetDataValid(dataValid); nd->SetHasOrientation(hasOrientation); nd->SetHasPosition(hasPosition); m_NavData = nd; m_Type = type; this->Modified(); } } // namespace mitk std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p) { os << p->ToString(); return os; } diff --git a/Modules/CameraCalibration/mitkTransform.h b/Modules/CameraCalibration/mitkTransform.h index 233abbc5b2..7aeabdd4b5 100644 --- a/Modules/CameraCalibration/mitkTransform.h +++ b/Modules/CameraCalibration/mitkTransform.h @@ -1,301 +1,300 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKTRANSFORM_H #define MITKTRANSFORM_H #include #include #include #include #include -#include #include #include #include #include namespace mitk { /// /// \brief class representing a transfrom in 3D /// /// internally it stores a mitk navigation data. this is more /// or less a wrapper for navigation data for easy casting /// between opencv/vnl/mitk/xml representations of transform /// data /// class MITKCAMERACALIBRATION_EXPORT Transform: public itk::Object, public XMLSerializable { public: mitkClassMacroItkParent(Transform, itk::Object); itkFactorylessNewMacro(Transform); mitkNewMacro1Param(Transform, const mitk::NavigationData*); mitkNewMacro1Param(Transform, const std::string&); /// /// constants describing the type of transform /// represented here /// static const std::string UNKNOWN_TYPE; static const std::string ENDOSCOPE_SCOPE_TOOL; static const std::string ENDOSCOPE_CAM_TOOL; static const std::string CHESSBOARD_TOOL; static const std::string POINTER_TOOL; static const std::string POINTER_TO_CHESSBOARD_ORIGIN; static const std::string POINTER_TO_CHESSBOARD_X_SUPPORT_POINT; static const std::string POINTER_TO_CHESSBOARD_Y_SUPPORT_POINT; static const std::string BOARD_TO_BOARD_TOOL; static const std::string REFERENCE_CAMERA_TRANSFORM; static const std::string REFERENCE_SCOPE_TRANSFORM; static const std::string EYE_TO_HAND_TRANSFORM; static const std::string CAMERA_EXTRINSICS; itkGetConstMacro(Type, std::string); itkSetMacro(Type, std::string&); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::Transform* transform ); /// /// Copies the content of transform to this /// instance /// void Copy( const mitk::NavigationData* transform ); /// /// Inverts the rotation of this transform /// (Polaris navigation Data have inverted rotation /// so you may want to call this function when using /// polaris data) /// void TransposeRotation(); /// /// get a copy of this transform /// mitk::Transform::Pointer Clone() const; /// /// concatenate this transform with the given one, /// i.e. this transform is done first, then transform /// ( if x is this transform, y is transform, then this will be y*x) /// post multiply semantics! /// \see vtkTransform /// void Concatenate( mitk::Transform* transform ); /// /// same as above with vnl mat argument /// void Concatenate( const vnl_matrix_fixed& transform ); /// /// same as above with vtk mat argument /// void Concatenate( const vtkMatrix4x4* transform ); /// /// invert this transform /// void Invert(); /// /// resets the internal variables except type /// void Reset(); /// /// read from xml /// - void FromXML(TiXmlElement* elem) override; + void FromXML(const tinyxml2::XMLElement* elem) override; /// /// read csv file /// void FromCSVFile(const std::string& file); /// /// grafts the data from naviData to this transform /// void SetNavigationData( const mitk::NavigationData* naviData ); /// /// method to set orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set float valued orientation quat /// void SetOrientation( const vnl_quaternion& orientation); /// /// method to set translation /// void SetTranslation( const vnl_vector_fixed& transl); /// /// method to set a vector of doubles as translation /// void SetTranslation( const vnl_vector& transl); /// /// method to set a mitk::Point3D as position /// void SetPosition( const mitk::Point3D& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( vnl_matrix_fixed& mat); /// /// sets rotation with a non fixed rotation matrix /// void SetRotation( vnl_matrix& mat); /// /// sets rotation and translation with a transformation matrix /// void SetMatrix( const vnl_matrix_fixed& mat); /// /// sets rotation and translation with a vtk transformation matrix /// void SetMatrix( const vtkMatrix4x4* mat); /// /// sets translation from a POD vector /// void SetTranslation( float* array ); /// /// sets translation from a POD vector. this must be a /// 3x3=9 sized vector in row major format (first row = first /// three elements) /// void SetRotation( float* array ); /// /// sets translation from a POD vector /// void SetTranslation( double array[3] ); /// /// sets translation from a POD vector /// void SetRotation( double array[3][3] ); /// /// method to set translation by cv vector /// void SetTranslation( const cv::Mat& transl); /// /// sets rotation with a rotation matrix /// void SetRotation( const cv::Mat& mat ); /// /// sets rotation with a rodrigues rotation vector /// void SetRotationVector( const cv::Mat& rotVec); /// /// \return the navigation data that stores all information /// mitk::NavigationData::Pointer GetNavigationData() const; /// /// calls navigationdata::GetPosition() /// mitk::Point3D GetPosition() const; /// /// same as GetPosition /// mitk::Point3D GetTranslation() const; /// /// calls navigationdata::IsValid() /// bool IsValid() const; /// /// calls navigationdata::SetValid() /// void SetValid(bool valid); /// /// calls navigationdata::GetOrientation() /// mitk::Quaternion GetOrientation() const; /// /// \return the homogeneous matrix representing this transform /// vnl_matrix_fixed GetMatrix() const; /// /// \return the homogeneous vtk matrix representing this transform /// void GetMatrix(vtkMatrix4x4* matrix) const; /// /// \return the homogeneous vtk matrix representing this transform /// in !OpenGL! left handed coordinate system /// void GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const; mitk::Point3D TransformPoint(mitk::Point3D point) const; /// /// create xml representation /// - void ToXML(TiXmlElement* elem) const override; + void ToXML(tinyxml2::XMLElement* elem) const override; /// /// create string representation /// std::string ToString() const; /// /// create string csv representation (only the transformation values!!!!) /// std::string ToCSVString() const; /// /// create matlab representation /// std::string ToMatlabString(const std::string& varname="transform", bool printLastRow=true) const; /// /// write csv representation to file (only the transformation values!!!!) /// void ToCSVFile(const std::string& file) const; /// /// write matlab representation to file /// void ToMatlabFile(const std::string& file , const std::string& varname="transform") const; /// /// conversion to cv types /// cv::Mat GetCvTranslation() const; cv::Mat GetCvRotationVector() const; cv::Mat GetCvRotationMatrix() const; cv::Mat GetCvMatrix() const; /// /// conversion to vnl types /// vnl_vector_fixed GetVnlTranslation() const; vnl_vector_fixed GetVnlDoubleTranslation() const; vnl_quaternion GetVnlDoubleQuaternion() const; vnl_matrix_fixed GetVnlRotationMatrix() const; vnl_matrix_fixed GetVnlDoubleMatrix() const; protected: Transform(); Transform(const mitk::NavigationData* nd); Transform(const std::string& s); // everything is stored here mitk::NavigationData::Pointer m_NavData; /// /// saves the type of the transform (Default is UNKNOWN_TYPE) /// std::string m_Type; }; } // namespace mitk MITKCAMERACALIBRATION_EXPORT std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p); #endif // MITKTRANSFORM_H diff --git a/Modules/CameraCalibration/mitkXMLSerializable.cpp b/Modules/CameraCalibration/mitkXMLSerializable.cpp index 525f8456de..0479a46ab1 100644 --- a/Modules/CameraCalibration/mitkXMLSerializable.cpp +++ b/Modules/CameraCalibration/mitkXMLSerializable.cpp @@ -1,137 +1,137 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include "mitkEndoDebug.h" #include "mitkEndoMacros.h" #include +#include namespace mitk { const std::string XMLSerializable::FILE_REFERENCE_ATTRIBUTE_NAME = "fileRef"; const std::string XMLSerializable::ROOT_NAME = "data"; void mitk::XMLSerializable::ToXMLFile(const std::string& file , const std::string& elemName) { - TiXmlElement * rootElem=nullptr; - TiXmlElement * element=nullptr; + tinyxml2::XMLElement * rootElem=nullptr; + tinyxml2::XMLElement* element=nullptr; // determine element to write to std::string elementName = elemName; if(elementName.empty()) elementName = this->GetNameOfClass(); - TiXmlDocument doc( file.c_str() ); - bool loadOkay = doc.LoadFile(); + tinyxml2::XMLDocument doc; // if the document already exists ... - if(loadOkay) + if(tinyxml2::XML_SUCCESS == doc.LoadFile(file.c_str())) { // try to identify the XML element of this class as the root // or as the child of the root rootElem = doc.RootElement(); endoAssertMsg( rootElem, "No root element found in " << file ); // if root element represents this element remove the root - if( rootElem->ValueStr() == elementName ) + if( std::string(rootElem->Value() != nullptr ? rootElem->Value() : "") == elementName ) { - doc.RemoveChild(rootElem); + doc.DeleteChild(rootElem); rootElem = nullptr; } else { // if it is a child of the root remove it too - element = rootElem->FirstChildElement(elementName); + element = rootElem->FirstChildElement(elementName.c_str()); if(element) - rootElem->RemoveChild(element); + rootElem->DeleteChild(element); } } else { // document did not exist, create new one with declration - auto decl = new TiXmlDeclaration( "1.0", "", "" ); - doc.LinkEndChild( decl ); + doc.InsertEndChild( doc.NewDeclaration() ); } m_XMLFileName = file; // create element (if the document already exists this element was removed) - element = new TiXmlElement( elementName ); + element = doc.NewElement( elementName.c_str() ); this->ToXML( element ); // if we do not have a root element create a new one if(!rootElem) - rootElem = new TiXmlElement( ROOT_NAME ); + rootElem = doc.NewElement( ROOT_NAME.c_str() ); // add the element node as child - rootElem->LinkEndChild(element); + rootElem->InsertEndChild(element); // if no root element exists, add it now if(doc.RootElement() == nullptr) - doc.LinkEndChild( rootElem ); + doc.InsertEndChild( rootElem ); - if(!doc.SaveFile( file )) + if(tinyxml2::XML_SUCCESS != doc.SaveFile( file.c_str() )) { std::ostringstream s; s << "File " << file << " could not be written. Please check permissions."; throw std::logic_error(s.str()); } } std::string mitk::XMLSerializable::GetXMLFileName() const { return m_XMLFileName; } void mitk::XMLSerializable::FromXMLFile(const std::string& file , const std::string& elemName) { endodebug( "Trying to read from " << file ) - TiXmlDocument doc( file.c_str() ); - bool loadOkay = doc.LoadFile(); - if(!loadOkay) + tinyxml2::XMLDocument doc; + if(tinyxml2::XML_SUCCESS != doc.LoadFile(file.c_str())) { std::ostringstream s; s << "File " << file << " could not be loaded!"; throw std::logic_error(s.str().c_str()); } m_XMLFileName = file; - TiXmlElement* elem = doc.FirstChildElement(); + auto* elem = doc.FirstChildElement(); endoAssertMsg( elem, "No root element found" ); // determine element to read from std::string elementName = elemName; if(elementName.empty()) elementName = this->GetNameOfClass(); // try again with the first element if(strcmp(elem->Value(), elementName.c_str()) != 0) elem = elem->FirstChildElement(elementName.c_str()); endoAssertMsg( elem, "No child element \"" << elementName << "\" found in " << file ); // if theres an attribute as file reference try to load the class // from that file - std::string filename; - if(elem->QueryStringAttribute(FILE_REFERENCE_ATTRIBUTE_NAME.c_str(), &filename) - == TIXML_SUCCESS) + const char* filenameC = elem->Attribute(FILE_REFERENCE_ATTRIBUTE_NAME.c_str()); + std::string filename = nullptr != filenameC + ? filenameC + : ""; + if(!filename.empty()) { if( !itksys::SystemTools::FileIsFullPath(filename.c_str()) ) filename = itksys::SystemTools::GetFilenamePath(file) + "/" + filename; this->FromXMLFile(filename); return; // exit! } this->FromXML( elem ); } } diff --git a/Modules/CameraCalibration/mitkXMLSerializable.h b/Modules/CameraCalibration/mitkXMLSerializable.h index 31dc61d346..8c0d78ecb9 100644 --- a/Modules/CameraCalibration/mitkXMLSerializable.h +++ b/Modules/CameraCalibration/mitkXMLSerializable.h @@ -1,88 +1,92 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKXMLSerializable_H #define MITKXMLSerializable_H #include -#include #include #include #include +namespace tinyxml2 +{ + class XMLElement; +} + namespace mitk { /// /// \brief interface for all classes able to write themselves to XML files /// class MITKCAMERACALIBRATION_EXPORT XMLSerializable { public: /// /// value of the special tag for file references /// if this is attribute is found the class /// will be loaded from the file in the attributes value /// static const std::string FILE_REFERENCE_ATTRIBUTE_NAME; /// /// the name of the root node that is created when the element is saved /// static const std::string ROOT_NAME; /// /// the tag value will be equals to the class name (function /// implemented by the itkTypeMacro) /// virtual const char* GetNameOfClass() const = 0; /// /// write your values here to elem /// - virtual void ToXML(TiXmlElement* elem) const = 0; + virtual void ToXML(tinyxml2::XMLElement* elem) const = 0; /// /// read your values here from elem /// - virtual void FromXML(TiXmlElement* elem) = 0; + virtual void FromXML(const tinyxml2::XMLElement* elem) = 0; /// /// tries to write the xml data obtained in ToXML() to file /// virtual void ToXMLFile(const std::string& file , const std::string& elemName=""); /// /// loads the XML file and calls FromXML() /// takes the first child of the document /// if this root node value is not equal to GetNameOfClass() /// the method will try to find the first children of the root /// node with the value of GetNameOfClass() /// if elemName is not empty then this value will be used instead /// of GetNameOfClass() /// if this node is found it will check if an attribute named /// FILE_REFERENCE_ATTRIBUTE_NAME is found: in this case /// the method calls itself with this attributes value as parameter /// virtual void FromXMLFile(const std::string& file , const std::string& elemName=""); /// /// \see m_XMLFileName /// std::string GetXMLFileName() const; private: /// /// saves the xmlfile name set for this serializable ( in FromXMLFile() ) /// std::string m_XMLFileName; }; } #endif diff --git a/Modules/Classification/CLUtilities/CMakeLists.txt b/Modules/Classification/CLUtilities/CMakeLists.txt index 3c7f86a35d..0d441525b8 100644 --- a/Modules/Classification/CLUtilities/CMakeLists.txt +++ b/Modules/Classification/CLUtilities/CMakeLists.txt @@ -1,14 +1,14 @@ mitk_create_module( DEPENDS MitkCore MitkCLCore MitkCommandLine MitkDICOM - PACKAGE_DEPENDS PUBLIC Eigen PRIVATE tinyxml VTK|FiltersStatistics + PACKAGE_DEPENDS PUBLIC Eigen PRIVATE tinyxml2|tinyxml2 VTK|FiltersStatistics ) if(TARGET ${MODULE_TARGET}) if(MITK_USE_OpenMP) - target_link_libraries(${MODULE_TARGET} PUBLIC OpenMP::OpenMP_CXX) + target_link_libraries(${MODULE_TARGET} PUBLIC OpenMP::OpenMP_CXX PRIVATE tinyxml2::tinyxml2) endif() if(BUILD_TESTING) add_subdirectory(test) endif() endif() diff --git a/Modules/Classification/CLUtilities/src/mitkCLResultXMLWriter.cpp b/Modules/Classification/CLUtilities/src/mitkCLResultXMLWriter.cpp index 0d3bf0c5ef..c884a41381 100644 --- a/Modules/Classification/CLUtilities/src/mitkCLResultXMLWriter.cpp +++ b/Modules/Classification/CLUtilities/src/mitkCLResultXMLWriter.cpp @@ -1,318 +1,321 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include #include #include #include #include #include #include #include #include #include #include -#include +#include template class punct_facet : public std::numpunct { public: punct_facet(charT sep) : m_Sep(sep) { } protected: charT do_decimal_point() const override { return m_Sep; } private: charT m_Sep; }; -void AddPropertyAsNode(const mitk::Image* image, const std::string& key, const std::string& tag, TiXmlElement* rootNode) +void AddPropertyAsNode(const mitk::Image* image, const std::string& key, const std::string& tag, tinyxml2::XMLElement* rootNode) { auto prop = image->GetProperty(key.c_str()); if (prop.IsNotNull()) { - auto propNode = new TiXmlElement(tag); - TiXmlText* valueText = new TiXmlText(prop->GetValueAsString()); - propNode->LinkEndChild(valueText); + auto* doc = rootNode->GetDocument(); + auto propNode = doc->NewElement(tag.c_str()); + auto* valueText = doc->NewText(prop->GetValueAsString().c_str()); + propNode->InsertEndChild(valueText); - rootNode->LinkEndChild(propNode); + rootNode->InsertEndChild(propNode); } } -void AddSeriesInstanceUID(const mitk::Image* image, TiXmlElement* xmlNode) +void AddSeriesInstanceUID(const mitk::Image* image, tinyxml2::XMLElement* xmlNode) { AddPropertyAsNode(image, mitk::DICOMTagPathToPropertyName(mitk::DICOMTagPath(0x0020, 0x000e)), "mp:seriesInstanceUID", xmlNode); } -void AddFilePath(const mitk::Image* image, TiXmlElement* xmlNode) +void AddFilePath(const mitk::Image* image, tinyxml2::XMLElement* xmlNode) { AddPropertyAsNode(image, mitk::PropertyKeyPathToPropertyName(mitk::IOMetaInformationPropertyConstants::READER_INPUTLOCATION()), "mp:filePath", xmlNode); } -void AddSOPInstanceUIDs(const mitk::Image* image, TiXmlElement* xmlNode) +void AddSOPInstanceUIDs(const mitk::Image* image, tinyxml2::XMLElement* xmlNode) { auto prop = image->GetProperty(mitk::DICOMTagPathToPropertyName(mitk::DICOMTagPath(0x0008, 0x0018)).c_str()); auto dicomProp = dynamic_cast(prop.GetPointer()); + auto* doc = xmlNode->GetDocument(); if (dicomProp != nullptr) { - auto instanceUIDsNode = new TiXmlElement("mp:sopInstanceUIDs"); - xmlNode->LinkEndChild(instanceUIDsNode); + auto* instanceUIDsNode = doc->NewElement("mp:sopInstanceUIDs"); + xmlNode->InsertEndChild(instanceUIDsNode); if (dicomProp->IsUniform()) { - auto instanceUIDNode = new TiXmlElement("mp:sopInstanceUID"); - TiXmlText* valueText = new TiXmlText(dicomProp->GetValueAsString()); - instanceUIDNode->LinkEndChild(valueText); - instanceUIDsNode->LinkEndChild(instanceUIDNode); + auto* instanceUIDNode = doc->NewElement("mp:sopInstanceUID"); + auto* valueText = doc->NewText(dicomProp->GetValueAsString().c_str()); + instanceUIDNode->InsertEndChild(valueText); + instanceUIDsNode->InsertEndChild(instanceUIDNode); } else { const auto timeSteps = dicomProp->GetAvailableTimeSteps(); for (auto timeStep : timeSteps) { const auto slices = dicomProp->GetAvailableSlices(timeStep); for (auto slice : slices) { - auto instanceUIDNode = new TiXmlElement("mp:sopInstanceUID"); - instanceUIDNode->SetAttribute("z", slice); - instanceUIDNode->SetAttribute("t", timeStep); - TiXmlText* valueText = new TiXmlText(dicomProp->GetValue(timeStep, slice)); - instanceUIDNode->LinkEndChild(valueText); - instanceUIDsNode->LinkEndChild(instanceUIDNode); + auto instanceUIDNode = doc->NewElement("mp:sopInstanceUID"); + instanceUIDNode->SetAttribute("z", static_cast(slice)); + instanceUIDNode->SetAttribute("t", static_cast(timeStep)); + auto* valueText = doc->NewText(dicomProp->GetValue(timeStep, slice).c_str()); + instanceUIDNode->InsertEndChild(valueText); + instanceUIDsNode->InsertEndChild(instanceUIDNode); } } } } } -void AddDateAndTime(TiXmlElement* rootNode) +void AddDateAndTime(tinyxml2::XMLElement* rootNode) { - auto dateNode = new TiXmlElement("mp:generationDate"); + auto* doc = rootNode->GetDocument(); + auto* dateNode = doc->NewElement("mp:generationDate"); auto time = std::time(nullptr); std::ostringstream sstream; sstream << std::put_time(std::localtime(&time), "%Y%m%d"); - TiXmlText* valueText = new TiXmlText(sstream.str()); - dateNode->LinkEndChild(valueText); + auto* valueText = doc->NewText(sstream.str().c_str()); + dateNode->InsertEndChild(valueText); - rootNode->LinkEndChild(dateNode); + rootNode->InsertEndChild(dateNode); - auto timeNode = new TiXmlElement("mp:generationTime"); + auto* timeNode = doc->NewElement("mp:generationTime"); std::ostringstream timestream; timestream << std::put_time(std::localtime(&time), "%H%M%S"); - valueText = new TiXmlText(timestream.str()); - timeNode->LinkEndChild(valueText); + valueText = doc->NewText(timestream.str().c_str()); + timeNode->InsertEndChild(valueText); - rootNode->LinkEndChild(timeNode); + rootNode->InsertEndChild(timeNode); } -void AddParameters(const std::map& parameters, TiXmlElement* paramsNode) +void AddParameters(const std::map& parameters, tinyxml2::XMLElement* paramsNode) { + auto* doc = paramsNode->GetDocument(); for (const auto& param : parameters) { mitk::LocaleSwitch lswitch("C"); - auto paramNode = new TiXmlElement("mp:parameter"); - paramNode->SetAttribute("name", param.first); - TiXmlText* valueText = new TiXmlText(param.second.ToString()); - paramNode->LinkEndChild(valueText); - paramsNode->LinkEndChild(paramNode); + auto paramNode = doc->NewElement("mp:parameter"); + paramNode->SetAttribute("name", param.first.c_str()); + auto* valueText = doc->NewText(param.second.ToString().c_str()); + paramNode->InsertEndChild(valueText); + paramsNode->InsertEndChild(paramNode); } } -void AddFeatures(const mitk::AbstractGlobalImageFeature::FeatureListType& features, TiXmlElement* featsNode) +void AddFeatures(const mitk::AbstractGlobalImageFeature::FeatureListType& features, tinyxml2::XMLElement* featsNode) { + auto* doc = featsNode->GetDocument(); for (const auto& feat : features) { - auto featNode = new TiXmlElement("mp:feature"); - featNode->SetAttribute("name", feat.first.name); - featNode->SetAttribute("version", feat.first.version); - featNode->SetAttribute("class", feat.first.featureClass); - featNode->SetAttribute("setting", feat.first.settingID); + auto featNode = doc->NewElement("mp:feature"); + featNode->SetAttribute("name", feat.first.name.c_str()); + featNode->SetAttribute("version", feat.first.version.c_str()); + featNode->SetAttribute("class", feat.first.featureClass.c_str()); + featNode->SetAttribute("setting", feat.first.settingID.c_str()); std::ostringstream sstream; sstream.imbue(std::locale("C")); sstream << feat.second; - TiXmlText* valueText = new TiXmlText(sstream.str()); - featNode->LinkEndChild(valueText); - featsNode->LinkEndChild(featNode); + auto* valueText = doc->NewText(sstream.str().c_str()); + featNode->InsertEndChild(valueText); + featsNode->InsertEndChild(featNode); } } -void AddFeatureSettings(const mitk::AbstractGlobalImageFeature::FeatureListType& features, TiXmlElement* featSettingsNode) +void AddFeatureSettings(const mitk::AbstractGlobalImageFeature::FeatureListType& features, tinyxml2::XMLElement* featSettingsNode) { + auto* doc = featSettingsNode->GetDocument(); std::list coveredSettings; for (const auto& feat : features) { auto finding = std::find(coveredSettings.begin(), coveredSettings.end(), feat.first.settingID); if (finding == coveredSettings.end()) { - auto featSettingNode = new TiXmlElement("mp:featureSetting"); - featSettingsNode->LinkEndChild(featSettingNode); - featSettingNode->SetAttribute("name", feat.first.settingID); + auto featSettingNode = doc->NewElement("mp:featureSetting"); + featSettingsNode->InsertEndChild(featSettingNode); + featSettingNode->SetAttribute("name", feat.first.settingID.c_str()); AddParameters(feat.first.parameters, featSettingNode); coveredSettings.push_back(feat.first.settingID); } } } -void AddReaderInfo(const mitk::Image* image, TiXmlElement* imageNode) +void AddReaderInfo(const mitk::Image* image, tinyxml2::XMLElement* imageNode) { - auto ioNode = new TiXmlElement("mp:IOReader"); - imageNode->LinkEndChild(ioNode); + auto* doc = imageNode->GetDocument(); + auto ioNode = doc->NewElement("mp:IOReader"); + imageNode->InsertEndChild(ioNode); AddPropertyAsNode(image, mitk::PropertyKeyPathToPropertyName(mitk::IOMetaInformationPropertyConstants::READER_DESCRIPTION()), "mp:description", ioNode); AddPropertyAsNode(image, mitk::PropertyKeyPathToPropertyName(mitk::IOMetaInformationPropertyConstants::READER_VERSION()), "mp:version", ioNode); AddPropertyAsNode(image, mitk::PropertyKeyPathToPropertyName(mitk::DICOMIOMetaInformationPropertyConstants::READER_CONFIGURATION()), "mp:configuration", ioNode); AddPropertyAsNode(image, mitk::PropertyKeyPathToPropertyName(mitk::DICOMIOMetaInformationPropertyConstants::READER_GDCM()), "mp:gdcmVersion", ioNode); AddPropertyAsNode(image, mitk::PropertyKeyPathToPropertyName(mitk::DICOMIOMetaInformationPropertyConstants::READER_DCMTK()), "mp:dcmtkVersion", ioNode); } void WriteDocument(std::ostream& stream, const mitk::Image* image, const mitk::Image* mask, const mitk::AbstractGlobalImageFeature::FeatureListType& features, const std::string& methodName, const std::string& organisation, const std::string& version, const std::string& pipelineUID, const std::map& cliArgs) { - TiXmlDocument doc; - doc.SetCondenseWhiteSpace(false); + tinyxml2::XMLDocument doc; + doc.InsertEndChild(doc.NewDeclaration()); - auto decl = new TiXmlDeclaration( - "1.0", "UTF-8", ""); - doc.LinkEndChild(decl); - - auto rootNode = new TiXmlElement("mp:measurement"); + auto* rootNode = doc.NewElement("mp:measurement"); rootNode->SetAttribute("xmlns:mp", "http://www.mitk.org/Phenotyping"); - doc.LinkEndChild(rootNode); + doc.InsertEndChild(rootNode); - auto methodNode = new TiXmlElement("mp:measurementMethod"); - rootNode->LinkEndChild(methodNode); + auto* methodNode = doc.NewElement("mp:measurementMethod"); + rootNode->InsertEndChild(methodNode); - auto methodNameNode = new TiXmlElement("mp:name"); - TiXmlText* valueText = new TiXmlText(methodName); - methodNameNode->LinkEndChild(valueText); - methodNode->LinkEndChild(methodNameNode); + auto* methodNameNode = doc.NewElement("mp:name"); + auto* valueText = doc.NewText(methodName.c_str()); + methodNameNode->InsertEndChild(valueText); + methodNode->InsertEndChild(methodNameNode); - auto organisationNode = new TiXmlElement("mp:organisation"); - valueText = new TiXmlText(organisation); - organisationNode->LinkEndChild(valueText); - methodNode->LinkEndChild(organisationNode); + auto* organisationNode = doc.NewElement("mp:organisation"); + valueText = doc.NewText(organisation.c_str()); + organisationNode->InsertEndChild(valueText); + methodNode->InsertEndChild(organisationNode); - auto versionNode = new TiXmlElement("mp:version"); - valueText = new TiXmlText(version); - versionNode->LinkEndChild(valueText); - methodNode->LinkEndChild(versionNode); + auto* versionNode = doc.NewElement("mp:version"); + valueText = doc.NewText(version.c_str()); + versionNode->InsertEndChild(valueText); + methodNode->InsertEndChild(versionNode); - auto imageNode = new TiXmlElement("mp:image"); - rootNode->LinkEndChild(imageNode); + auto* imageNode = doc.NewElement("mp:image"); + rootNode->InsertEndChild(imageNode); AddSeriesInstanceUID(image, imageNode); AddFilePath(image, imageNode); AddSOPInstanceUIDs(image, imageNode); AddReaderInfo(image,imageNode); - auto maskNode = new TiXmlElement("mp:mask"); - rootNode->LinkEndChild(maskNode); + auto* maskNode = doc.NewElement("mp:mask"); + rootNode->InsertEndChild(maskNode); AddSeriesInstanceUID(mask, maskNode); AddFilePath(mask, maskNode); AddSOPInstanceUIDs(mask, maskNode); AddReaderInfo(mask, maskNode); //todo mask reader meta info AddDateAndTime(rootNode); - auto pipelineNode = new TiXmlElement("mp:pipelineUID"); - valueText = new TiXmlText(pipelineUID); - pipelineNode->LinkEndChild(valueText); - rootNode->LinkEndChild(pipelineNode); + auto* pipelineNode = doc.NewElement("mp:pipelineUID"); + valueText = doc.NewText(pipelineUID.c_str()); + pipelineNode->InsertEndChild(valueText); + rootNode->InsertEndChild(pipelineNode); - auto paramsNode = new TiXmlElement("mp:parameters"); - rootNode->LinkEndChild(paramsNode); + auto* paramsNode = doc.NewElement("mp:parameters"); + rootNode->InsertEndChild(paramsNode); AddParameters(cliArgs, paramsNode); - auto featsNode = new TiXmlElement("mp:features"); - rootNode->LinkEndChild(featsNode); + auto* featsNode = doc.NewElement("mp:features"); + rootNode->InsertEndChild(featsNode); AddFeatures(features, featsNode); - auto featSettingsNode = new TiXmlElement("mp:featureSettings"); - rootNode->LinkEndChild(featSettingsNode); + auto* featSettingsNode = doc.NewElement("mp:featureSettings"); + rootNode->InsertEndChild(featSettingsNode); AddFeatureSettings(features, featSettingsNode); - TiXmlPrinter printer; + tinyxml2::XMLPrinter printer; + doc.Print(&printer); - doc.Accept(&printer); - stream << printer.Str(); + stream << printer.CStr(); } void mitk::cl::CLResultXMLWriter::SetImage(const Image* image) { m_Image = image; } void mitk::cl::CLResultXMLWriter::SetMask(const Image* mask) { m_Mask = mask; } void mitk::cl::CLResultXMLWriter::SetFeatures(const mitk::AbstractGlobalImageFeature::FeatureListType& features) { m_Features = features; } void mitk::cl::CLResultXMLWriter::SetMethodName(const std::string& name) { m_MethodName = name; } void mitk::cl::CLResultXMLWriter::SetMethodVersion(const std::string& version) { m_MethodVersion = version; } void mitk::cl::CLResultXMLWriter::SetOrganisation(const std::string& orga) { m_Organisation = orga; } void mitk::cl::CLResultXMLWriter::SetPipelineUID(const std::string& pipelineUID) { m_PipelineUID = pipelineUID; } void mitk::cl::CLResultXMLWriter::SetCLIArgs(const std::map& args) { m_CLIArgs = args; } void mitk::cl::CLResultXMLWriter::write(const std::string& filePath) const { std::ofstream resultFile; resultFile.open(filePath.c_str()); if (resultFile.is_open()) { this->write(resultFile); resultFile.close(); } else { MITK_ERROR << "Cannot write xml results. Unable to open file: \""< #include +#include #include #include +#include + +namespace +{ + // Previous versions of the ContourModelSetWriter produced flawed + // XML files with multiple XML declarations. + std::string RemoveErroneousXMLDeclarations(const std::string& filename) + { + std::ifstream file(filename); + file.seekg(0, std::ios_base::end); + auto size = file.tellg(); + std::string string(size, '\0'); + file.seekg(0); + file.read(&string[0], size); + file.close(); + std::regex regex("><\\?xml.+\\?>"); + return std::regex_replace(string, regex, ">"); + } +} mitk::ContourModelReader::ContourModelReader(const mitk::ContourModelReader &other) : mitk::AbstractFileReader(other) { } mitk::ContourModelReader::ContourModelReader() : AbstractFileReader() { std::string category = "Contour File"; mitk::CustomMimeType customMimeType; customMimeType.SetCategory(category); customMimeType.AddExtension("cnt"); this->SetDescription(category); this->SetMimeType(customMimeType); m_ServiceReg = this->RegisterService(); } mitk::ContourModelReader::~ContourModelReader() { } std::vector> mitk::ContourModelReader::DoRead() { std::vector> result; std::string location = GetInputLocation(); // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); try { - TiXmlDocument doc(location.c_str()); - bool loadOkay = doc.LoadFile(); - if (loadOkay) + auto string = RemoveErroneousXMLDeclarations(location); + + tinyxml2::XMLDocument doc; + if (tinyxml2::XML_SUCCESS == doc.Parse(string.c_str())) { - TiXmlHandle docHandle(&doc); + tinyxml2::XMLHandle docHandle(&doc); /*++++ handle n contourModels within data tags ++++*/ - for (TiXmlElement *currentContourElement = docHandle.FirstChildElement("contourModel").ToElement(); + for (auto *currentContourElement = docHandle.FirstChildElement("contourModel").ToElement(); currentContourElement != nullptr; currentContourElement = currentContourElement->NextSiblingElement()) { mitk::ContourModel::Pointer newContourModel = mitk::ContourModel::New(); if (currentContourElement->FirstChildElement("data")->FirstChildElement("timestep") != nullptr) { - // handle geometry information - // TiXmlElement* currentGeometryInfo = - // currentContourElement->FirstChildElement("head")->FirstChildElement("geometryInformation")->ToElement(); - ///////////// NOT SUPPORTED YET //////////////// - /*++++ handle n timesteps within timestep tags ++++*/ - for (TiXmlElement *currentTimeSeries = + for (auto *currentTimeSeries = currentContourElement->FirstChildElement("data")->FirstChildElement("timestep")->ToElement(); currentTimeSeries != nullptr; currentTimeSeries = currentTimeSeries->NextSiblingElement()) { unsigned int currentTimeStep(0); currentTimeStep = atoi(currentTimeSeries->Attribute("n")); this->ReadPoints(newContourModel, currentTimeSeries, currentTimeStep); int isClosed; currentTimeSeries->QueryIntAttribute("isClosed", &isClosed); if (isClosed) { newContourModel->Close(currentTimeStep); } } /*++++ END handle n timesteps within timestep tags ++++*/ } else { // this should not happen MITK_WARN << "wrong file format!"; // newContourModel = this->ReadPoint(newContourModel, currentContourElement, 0); } newContourModel->UpdateOutputInformation(); result.push_back(dynamic_cast(newContourModel.GetPointer())); } /*++++ END handle n contourModels within data tags ++++*/ } else { MITK_WARN << "XML parser error!"; } } catch (...) { MITK_ERROR << "Cannot read contourModel."; } return result; } mitk::ContourModelReader *mitk::ContourModelReader::Clone() const { return new ContourModelReader(*this); } void mitk::ContourModelReader::ReadPoints(mitk::ContourModel::Pointer newContourModel, - TiXmlElement *currentTimeSeries, + const tinyxml2::XMLElement *currentTimeSeries, unsigned int currentTimeStep) { // check if the timesteps in contourModel have to be expanded if (currentTimeStep != newContourModel->GetTimeSteps()) { newContourModel->Expand(currentTimeStep + 1); } // read all points within controlPoints tag if (currentTimeSeries->FirstChildElement("controlPoints")->FirstChildElement("point") != nullptr) { - for (TiXmlElement *currentPoint = + for (auto *currentPoint = currentTimeSeries->FirstChildElement("controlPoints")->FirstChildElement("point")->ToElement(); currentPoint != nullptr; currentPoint = currentPoint->NextSiblingElement()) { double x(0.0); double y(0.0); double z(0.0); x = atof(currentPoint->FirstChildElement("x")->GetText()); y = atof(currentPoint->FirstChildElement("y")->GetText()); z = atof(currentPoint->FirstChildElement("z")->GetText()); int isActivePoint; currentPoint->QueryIntAttribute("isActive", &isActivePoint); mitk::Point3D point; mitk::FillVector3D(point, x, y, z); newContourModel->AddVertex(point, isActivePoint, currentTimeStep); } } else { // nothing to read } } diff --git a/Modules/ContourModel/IO/mitkContourModelReader.h b/Modules/ContourModel/IO/mitkContourModelReader.h index bbeae0a7ec..f91298ae2c 100644 --- a/Modules/ContourModel/IO/mitkContourModelReader.h +++ b/Modules/ContourModel/IO/mitkContourModelReader.h @@ -1,56 +1,60 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_CONTOURMODEL_READER__H_ #define _MITK_CONTOURMODEL_READER__H_ // MITK #include #include #include #include #include #include -#include #include +namespace tinyxml2 +{ + class XMLElement; +} + namespace mitk { /** * @brief * @ingroup MitkContourModelModule */ class ContourModelReader : public mitk::AbstractFileReader { public: ContourModelReader(const ContourModelReader &other); ContourModelReader(); ~ContourModelReader() override; using AbstractFileReader::Read; protected: virtual void ReadPoints(mitk::ContourModel::Pointer newContourModel, - TiXmlElement *currentTimeSeries, + const tinyxml2::XMLElement *currentTimeSeries, unsigned int currentTimeStep); std::vector> DoRead() override; private: ContourModelReader *Clone() const override; us::ServiceRegistration m_ServiceReg; }; } #endif diff --git a/Modules/ContourModel/IO/mitkContourModelSetReader.h b/Modules/ContourModel/IO/mitkContourModelSetReader.h index 91e24180a1..3472efff46 100644 --- a/Modules/ContourModel/IO/mitkContourModelSetReader.h +++ b/Modules/ContourModel/IO/mitkContourModelSetReader.h @@ -1,54 +1,53 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_ContourModelSetReader__H_ #define _MITK_ContourModelSetReader__H_ // MITK #include #include #include #include #include #include #include -#include #include namespace mitk { /** * @brief * @ingroup MitkContourModelModule */ class ContourModelSetReader : public mitk::AbstractFileReader { public: ContourModelSetReader(const ContourModelSetReader &other); ContourModelSetReader(); ~ContourModelSetReader() override; using AbstractFileReader::Read; protected: std::vector> DoRead() override; private: ContourModelSetReader *Clone() const override; us::ServiceRegistration m_ServiceReg; }; } #endif diff --git a/Modules/ContourModel/IO/mitkContourModelSetWriter.cpp b/Modules/ContourModel/IO/mitkContourModelSetWriter.cpp index c437dd022b..deb595a399 100644 --- a/Modules/ContourModel/IO/mitkContourModelSetWriter.cpp +++ b/Modules/ContourModel/IO/mitkContourModelSetWriter.cpp @@ -1,82 +1,85 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkContourModelSetWriter.h" #include "mitkContourModelWriter.h" #include #include #include mitk::ContourModelSetWriter::ContourModelSetWriter() : AbstractFileWriter(ContourModelSet::GetStaticNameOfClass()) { std::string category = "ContourModelSet File"; mitk::CustomMimeType customMimeType; customMimeType.SetCategory(category); customMimeType.AddExtension("cnt_set"); this->SetDescription(category); this->SetMimeType(customMimeType); RegisterService(); } mitk::ContourModelSetWriter::ContourModelSetWriter(const mitk::ContourModelSetWriter &other) : AbstractFileWriter(other) { } mitk::ContourModelSetWriter::~ContourModelSetWriter() { } void mitk::ContourModelSetWriter::Write() { std::ostream *out; std::ofstream outStream; if (this->GetOutputStream()) { out = this->GetOutputStream(); } else { outStream.open(this->GetOutputLocation().c_str()); out = &outStream; } if (!out->good()) { mitkThrow() << "Stream not good."; } + *out << "\n"; + // Use regular ContourModel writer to write each contour of the set to a single file. // Just use a different file extension .cnt_set - mitk::ContourModelWriter writer; + bool writeXMLHeader = false; + mitk::ContourModelWriter writer(writeXMLHeader); mitk::ContourModelSet::ConstPointer contourModelSet = dynamic_cast(this->GetInput()); // // for each contour object set input of writer // for (int i = 0; i < contourModelSet->GetSize(); ++i) { const mitk::ContourModel *contour = contourModelSet->GetContourModelAt(i); writer.SetInput(contour); writer.SetOutputStream(this->GetOutputLocation(), out); writer.Write(); } } mitk::ContourModelSetWriter *mitk::ContourModelSetWriter::Clone() const { return new ContourModelSetWriter(*this); } diff --git a/Modules/ContourModel/IO/mitkContourModelWriter.cpp b/Modules/ContourModel/IO/mitkContourModelWriter.cpp index f41a1d83f4..8e7710a626 100644 --- a/Modules/ContourModel/IO/mitkContourModelWriter.cpp +++ b/Modules/ContourModel/IO/mitkContourModelWriter.cpp @@ -1,335 +1,335 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkContourModelWriter.h" #include "mitkIOMimeTypes.h" #include "mitkTimeGeometry.h" #include #include #include /* * The xml file will look like: * * * * * * * * * * * * * * * * * * * */ // // Initialization of the xml tags. // const char *mitk::ContourModelWriter::XML_CONTOURMODEL = "contourModel"; const char *mitk::ContourModelWriter::XML_HEAD = "head"; const char *mitk::ContourModelWriter::XML_GEOMETRY_INFO = "geometryInfo"; const char *mitk::ContourModelWriter::XML_DATA = "data"; const char *mitk::ContourModelWriter::XML_TIME_STEP = "timestep"; const char *mitk::ContourModelWriter::XML_CONTROL_POINTS = "controlPoints"; const char *mitk::ContourModelWriter::XML_POINT = "point"; const char *mitk::ContourModelWriter::XML_X = "x"; const char *mitk::ContourModelWriter::XML_Y = "y"; const char *mitk::ContourModelWriter::XML_Z = "z"; -mitk::ContourModelWriter::ContourModelWriter() - : AbstractFileWriter(ContourModel::GetStaticNameOfClass()), m_IndentDepth(0), m_Indent(2) +mitk::ContourModelWriter::ContourModelWriter(bool writeXMLHeader) + : AbstractFileWriter(ContourModel::GetStaticNameOfClass()), m_WriteXMLHeader(writeXMLHeader), m_IndentDepth(0), m_Indent(2) { std::string category = "Contour File"; mitk::CustomMimeType customMimeType; customMimeType.SetCategory(category); customMimeType.AddExtension("cnt"); this->SetDescription(category); this->SetMimeType(customMimeType); RegisterService(); } mitk::ContourModelWriter::ContourModelWriter(const mitk::ContourModelWriter &other) : AbstractFileWriter(other), m_IndentDepth(other.m_IndentDepth), m_Indent(other.m_Indent) { } mitk::ContourModelWriter::~ContourModelWriter() { } void mitk::ContourModelWriter::Write() { std::ostream *out; std::ofstream outStream; if (this->GetOutputStream()) { out = this->GetOutputStream(); } else { outStream.open(this->GetOutputLocation().c_str()); out = &outStream; } if (!out->good()) { mitkThrow() << "Stream not good."; } std::locale previousLocale(out->getloc()); - std::locale I("C"); - out->imbue(I); + out->imbue(std::locale::classic()); /*+++++++++++ Here the actual xml writing begins +++++++++*/ /*++++ ++++*/ - WriteXMLHeader(*out); + if (m_WriteXMLHeader) + WriteXMLHeader(*out); // // for each input object write its xml representation to // the stream // mitk::ContourModel::ConstPointer contourModel = dynamic_cast(this->GetInput()); assert(contourModel.IsNotNull()); WriteXML(contourModel.GetPointer(), *out); out->imbue(previousLocale); if (!out->good()) // some error during output { throw std::ios_base::failure("Some error during contour writing."); } } mitk::ContourModelWriter *mitk::ContourModelWriter::Clone() const { return new ContourModelWriter(*this); } void mitk::ContourModelWriter::WriteXML(const mitk::ContourModel *contourModel, std::ostream &out) { /*++++ ++++*/ WriteStartElement(XML_CONTOURMODEL, out); /*++++ ++++*/ WriteStartElement(XML_HEAD, out); /*++++ ++++*/ WriteStartElement(XML_GEOMETRY_INFO, out); WriteGeometryInformation(contourModel->GetTimeGeometry(), out); /*++++ ++++*/ WriteEndElement(XML_GEOMETRY_INFO, out); /*++++ ++++*/ WriteEndElement(XML_HEAD, out); /*++++ ++++*/ WriteStartElement(XML_DATA, out); unsigned int timecount = contourModel->GetTimeSteps(); for (unsigned int i = 0; i < timecount; i++) { /*++++ ++++*/ std::vector at; at.push_back("n"); std::vector val; val.push_back(ConvertToString(i)); at.push_back("isClosed"); val.push_back(ConvertToString(contourModel->IsClosed())); WriteStartElementWithAttribut(XML_TIME_STEP, at, val, out); /*++++ ++++*/ WriteStartElement(XML_CONTROL_POINTS, out); auto it = contourModel->IteratorBegin(); auto end = contourModel->IteratorEnd(); while (it != end) { mitk::ContourModel::VertexType *v = *it; /*++++ ++++*/ std::vector attr; attr.push_back("IsControlPoint"); std::vector value; value.push_back(ConvertToString(v->IsControlPoint)); WriteStartElementWithAttribut(XML_POINT, attr, value, out); /*++++ ++++*/ WriteStartElement(XML_X, out); WriteCharacterData(ConvertToString(v->Coordinates[0]).c_str(), out); /*++++ ++++*/ WriteEndElement(XML_X, out, false); /*++++ ++++*/ WriteStartElement(XML_Y, out); WriteCharacterData(ConvertToString(v->Coordinates[1]).c_str(), out); /*++++ ++++*/ WriteEndElement(XML_Y, out, false); /*++++ ++++*/ WriteStartElement(XML_Z, out); WriteCharacterData(ConvertToString(v->Coordinates[2]).c_str(), out); /*++++ ++++*/ WriteEndElement(XML_Z, out, false); /*++++ ++++*/ WriteEndElement(XML_POINT, out); it++; } /*++++ ++++*/ WriteEndElement(XML_CONTROL_POINTS, out); /*++++ ++++*/ WriteEndElement(XML_TIME_STEP, out); } /*++++ ++++*/ WriteEndElement(XML_DATA, out); /*++++ ++++*/ WriteEndElement(XML_CONTOURMODEL, out); } void mitk::ContourModelWriter::WriteGeometryInformation(const mitk::TimeGeometry * /*geometry*/, std::ostream &out) { WriteCharacterData("", out); } template std::string mitk::ContourModelWriter::ConvertToString(T value) { std::ostringstream o; std::locale I("C"); o.imbue(I); if (o << value) { return o.str(); } else return "conversion error"; } void mitk::ContourModelWriter::WriteXMLHeader(std::ostream &file) { file << ""; } void mitk::ContourModelWriter::WriteStartElement(const char *const tag, std::ostream &file) { file << std::endl; WriteIndent(file); file << '<' << tag << '>'; m_IndentDepth++; } void mitk::ContourModelWriter::WriteStartElementWithAttribut(const char *const tag, std::vector attributes, std::vector values, std::ostream &file) { file << std::endl; WriteIndent(file); file << '<' << tag; unsigned int attributesSize = attributes.size(); unsigned int valuesSize = values.size(); if (attributesSize == valuesSize) { auto attributesIt = attributes.begin(); auto end = attributes.end(); auto valuesIt = values.begin(); while (attributesIt != end) { file << ' '; WriteCharacterData(*attributesIt, file); file << '=' << '"'; WriteCharacterData(*valuesIt, file); file << '"'; attributesIt++; valuesIt++; } } file << '>'; m_IndentDepth++; } void mitk::ContourModelWriter::WriteEndElement(const char *const tag, std::ostream &file, const bool &indent) { m_IndentDepth--; if (indent) { file << std::endl; WriteIndent(file); } file << '<' << '/' << tag << '>'; } void mitk::ContourModelWriter::WriteCharacterData(const char *const data, std::ostream &file) { file << data; } void mitk::ContourModelWriter::WriteStartElement(std::string &tag, std::ostream &file) { WriteStartElement(tag.c_str(), file); } void mitk::ContourModelWriter::WriteEndElement(std::string &tag, std::ostream &file, const bool &indent) { WriteEndElement(tag.c_str(), file, indent); } void mitk::ContourModelWriter::WriteCharacterData(std::string &data, std::ostream &file) { WriteCharacterData(data.c_str(), file); } void mitk::ContourModelWriter::WriteIndent(std::ostream &file) { std::string spaces(m_IndentDepth * m_Indent, ' '); file << spaces.c_str(); } diff --git a/Modules/ContourModel/IO/mitkContourModelWriter.h b/Modules/ContourModel/IO/mitkContourModelWriter.h index e338c4eee8..3a1b587533 100644 --- a/Modules/ContourModel/IO/mitkContourModelWriter.h +++ b/Modules/ContourModel/IO/mitkContourModelWriter.h @@ -1,169 +1,171 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_CONTOURMODEL_WRITER__H_ #define _MITK_CONTOURMODEL_WRITER__H_ #include #include // DEPRECATED #include namespace mitk { /** * @brief XML-based writer for mitk::ContourModels * * XML-based writer for mitk::ContourModels. Multiple ContourModels can be written in * a single XML file by simply setting multiple inputs to the filter. * * The xml file will look like: * * * * * * * * * * * * * * * * * * * * * @ingroup MitkContourModelModule */ class TimeSlicedGeometry; class ContourModelWriter : public mitk::AbstractFileWriter { public: - ContourModelWriter(); + explicit ContourModelWriter(bool writeXMLHeader = true); ~ContourModelWriter() override; using AbstractFileWriter::Write; void Write() override; protected: ContourModelWriter(const ContourModelWriter &other); mitk::ContourModelWriter *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 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 contourModel the point set to be converted to xml * @param out the stream to write to. */ void WriteXML(const mitk::ContourModel *contourModel, std::ostream &out); /** * Writes the geometry information of the TimeGeometry to an outstream. * The root tag is not included. * @param geometry the TimeGeometry of the contour. * @param out the stream to write to. */ void WriteGeometryInformation(const mitk::TimeGeometry *geometry, std::ostream &out); /** * Writes the geometry information of the TimeGeometry to an outstream. * The root tag is not included. * @param geometry the TimeGeometry of the contour. * @param out the stream to write to. * * \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see * http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201 */ DEPRECATED(void WriteGeometryInformation(const mitk::TimeSlicedGeometry *geometry, 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 a start element tag */ void WriteStartElement(const char *const tag, std::ostream &file); void WriteStartElementWithAttribut(const char *const tag, std::vector attributes, std::vector values, std::ostream &file); /** * Write an end element tag * End-Elements following character data should pass indent = false. */ void WriteEndElement(const char *const tag, std::ostream &file, const bool &indent = true); /** Write character data inside a tag. */ void WriteCharacterData(const char *const data, std::ostream &file); /** Write a start element tag */ void WriteStartElement(std::string &tag, std::ostream &file); /** Write an end element tag */ void WriteEndElement(std::string &tag, std::ostream &file, const bool &indent = true); /** Write character data inside a tag. */ void WriteCharacterData(std::string &data, std::ostream &file); /** Writes empty spaces to the stream according to m_IndentDepth and m_Indent */ void WriteIndent(std::ostream &file); + bool m_WriteXMLHeader; + unsigned int m_IndentDepth; unsigned int m_Indent; public: static const char *XML_CONTOURMODEL; static const char *XML_HEAD; static const char *XML_GEOMETRY_INFO; static const char *XML_DATA; static const char *XML_TIME_STEP; static const char *XML_CONTROL_POINTS; static const char *XML_POINT; static const char *XML_X; static const char *XML_Y; static const char *XML_Z; }; } #endif diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt index 40e19fd8b4..8a143eee99 100644 --- a/Modules/Core/CMakeLists.txt +++ b/Modules/Core/CMakeLists.txt @@ -1,65 +1,70 @@ set(TOOL_CPPS "") # temporary suppress warnings in the following files until image accessors are fully integrated. set_source_files_properties( src/DataManagement/mitkImage.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS ) set_source_files_properties( src/Controllers/mitkSliceNavigationController.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS ) MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC ${MITK_BINARY_DIR} PRIVATE src/Algorithms src/Controllers src/DataManagement src/Interactions src/IO src/Rendering ${OPENGL_INCLUDE_DIR} DEPENDS PUBLIC mbilog CppMicroServices PACKAGE_DEPENDS - PRIVATE tinyxml OpenGL + PRIVATE tinyxml2|tinyxml2 OpenGL PUBLIC ITK|ITKTransform+ITKImageGrid+ITKImageFeature+ITKIOImageBase+ITKIOHDF5+ITKIOLSM+ITKIOMRC+ITKIOBioRad+ITKIOGE+ITKIOStimulate+ITKIOBruker+ITKIOMINC # We privately use/link all ITK modules in order to support all IO, Transform, etc. # factories from ITK which are registered "automatically" via a factory manager. PRIVATE ITK PUBLIC VTK|FiltersTexture+FiltersParallel+ImagingStencil+ImagingMath+InteractionStyle+RenderingOpenGL2+RenderingVolumeOpenGL2+RenderingFreeType+RenderingLabel+InteractionWidgets+IOGeometry+IOXML PUBLIC Boost|boost # Do not automatically create CppMicroServices initialization code. # Because the VTK 6 "auto-init" functionality injects file-local static # initialization code in every cpp file which includes a VTK header, # static initialization order becomes an issue again. For the Mitk # core library, we need to ensure that the VTK static initialization stuff # happens before the CppMicroServices initialization, since the latter # might already use VTK code which needs to access VTK object factories. # Hence, CppMicroServices initialization code is placed manually within # the mitkCoreActivator.cpp file. NO_INIT ) if(NOT TARGET ${MODULE_TARGET}) message(SEND_ERROR "Core target ${MODULE_TARGET} does not exist") endif() + +target_link_libraries(${MODULE_TARGET} + PRIVATE tinyxml2::tinyxml2 +) + function(_itk_create_factory_register_manager) # In MITK_ITK_Config.cmake, we do *not* include ITK_USE_FILE, which # prevents multiple registrations/unregistrations of ITK IO factories # during library loading/unloading (of MITK libraries). However, we need # "one" place where the IO factories are registered at # least once. This could be the application executable, but every executable would # need to take care of that itself. Instead, we allow the auto registration in the # Mitk Core library. set(NO_DIRECTORY_SCOPED_ITK_COMPILE_DEFINITION 1) find_package(ITK) include(${ITK_USE_FILE}) if(NOT ITK_NO_IO_FACTORY_REGISTER_MANAGER) # We manually add the define which will be of target scope. MITK # patches ITK_USE_FILE to remove the directory scoped compile # definition since it would be propagated to other targets in the # same directory scope but these targets might want to *not* # use the ITK factory manager stuff. target_compile_definitions(${MODULE_TARGET} PRIVATE ITK_IO_FACTORY_REGISTER_MANAGER) endif() endfunction() _itk_create_factory_register_manager() if(MSVC_IDE OR MSVC_VERSION) target_link_libraries(${MODULE_TARGET} PRIVATE psapi.lib) endif() if(BUILD_TESTING) add_subdirectory(TestingHelper) add_subdirectory(test) endif() diff --git a/Modules/Core/TestingHelper/CMakeLists.txt b/Modules/Core/TestingHelper/CMakeLists.txt index c1d32c6cfd..a317355092 100644 --- a/Modules/Core/TestingHelper/CMakeLists.txt +++ b/Modules/Core/TestingHelper/CMakeLists.txt @@ -1,7 +1,12 @@ mitk_create_module( DEPENDS PUBLIC MitkCore PACKAGE_DEPENDS - PUBLIC CppUnit - PRIVATE VTK|IOImage+TestingRendering tinyxml OpenGL + PUBLIC CppUnit tinyxml2|tinyxml2 + PRIVATE VTK|IOImage+TestingRendering OpenGL ) +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} + PUBLIC tinyxml2::tinyxml2 + ) +endif() diff --git a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp index dea87c3ef7..92578ca3cf 100644 --- a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp +++ b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp @@ -1,432 +1,429 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include #include #include #include #include // VTK #include #include // us #include -#include +#include mitk::InteractionTestHelper::InteractionTestHelper(const std::string &interactionXmlFilePath) : m_InteractionFilePath(interactionXmlFilePath) { this->Initialize(interactionXmlFilePath); } void mitk::InteractionTestHelper::Initialize(const std::string &interactionXmlFilePath) { - // TiXmlDocument document(interactionXmlPath.c_str()); - TiXmlDocument document(interactionXmlFilePath); - bool loadOkay = document.LoadFile(); - if (loadOkay) + tinyxml2::XMLDocument document; + if (tinyxml2::XML_SUCCESS == document.LoadFile(interactionXmlFilePath.c_str())) { // get RenderingManager instance auto rm = mitk::RenderingManager::GetInstance(); // create data storage m_DataStorage = mitk::StandaloneDataStorage::New(); // for each renderer found create a render window and configure - for (TiXmlElement *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions()) - ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot()) - ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer()); + for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str()) + ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str()) + ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()); element != nullptr; - element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer())) + element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str())) { // get name of renderer const char *rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); // get view direction mitk::SliceNavigationController::ViewDirection viewDirection = mitk::SliceNavigationController::Axial; - if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str()) != nullptr) { int viewDirectionNum = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str())); viewDirection = static_cast(viewDirectionNum); } // get mapper slot id mitk::BaseRenderer::MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; - if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr) { int mapperIDNum = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str())); mapperID = static_cast(mapperIDNum); } // Get Size of Render Windows int size[3]; size[0] = size[1] = size[2] = 0; - if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str()) != nullptr) { - size[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX())->c_str()); + size[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str())); } - if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str()) != nullptr) { - size[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY())->c_str()); + size[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str())); } - if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str()) != nullptr) { - size[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ())->c_str()); + size[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str())); } // create renderWindow, renderer and dispatcher auto rw = RenderWindow::New(nullptr, rendererName); // VtkRenderWindow is created within constructor if nullptr if (size[0] != 0 && size[1] != 0) { rw->SetSize(size[0], size[1]); rw->GetRenderer()->Resize(size[0], size[1]); } // set storage of renderer rw->GetRenderer()->SetDataStorage(m_DataStorage); // set view direction to axial rw->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); // set renderer to render 2D rw->GetRenderer()->SetMapperID(mapperID); rw->GetRenderer()->PrepareRender(); // Some more magic for the 3D render window case: // Camera view direction, position and focal point if (mapperID == mitk::BaseRenderer::Standard3D) { - if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr) { double cameraFocalPoint[3]; cameraFocalPoint[0] = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str())); cameraFocalPoint[1] = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str())); cameraFocalPoint[2] = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint); } - if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr) { double cameraPosition[3]; - cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX())->c_str()); - cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY())->c_str()); - cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ())->c_str()); + cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str())); + cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str())); + cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition); } - if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr) { double viewUp[3]; - viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX())->c_str()); - viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY())->c_str()); - viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ())->c_str()); + viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str())); + viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str())); + viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp); } } rw->GetVtkRenderWindow()->Render(); rw->GetVtkRenderWindow()->WaitForCompletion(); // connect SliceNavigationControllers to timestep changed event of TimeNavigationController rw->GetSliceNavigationController()->ConnectGeometryTimeEvent(rm->GetTimeNavigationController(), false); rm->GetTimeNavigationController()->ConnectGeometryTimeEvent(rw->GetSliceNavigationController(), false); // add to list of kown render windows m_RenderWindowList.push_back(rw); } // TODO: check the following lines taken from QmitkStdMultiWidget and adapt them to be executed in our code here. // mitkWidget1->GetSliceNavigationController() // ->ConnectGeometrySendEvent(mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())); //########### register display interactor to handle scroll events ################## // use MouseModeSwitcher to ensure that the statemachine of DisplayInteractor is loaded correctly m_MouseModeSwitcher = mitk::MouseModeSwitcher::New(); } else { mitkThrow() << "Can not load interaction xml file <" << m_InteractionFilePath << ">"; } // WARNING assumes a 3D window exists !!!! this->AddDisplayPlaneSubTree(); } mitk::InteractionTestHelper::~InteractionTestHelper() { mitk::RenderingManager *rm = mitk::RenderingManager::GetInstance(); // unregister renderers auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { rm->GetTimeNavigationController()->Disconnect((*it)->GetSliceNavigationController()); (*it)->GetSliceNavigationController()->Disconnect(rm->GetTimeNavigationController()); mitk::BaseRenderer::RemoveInstance((*it)->GetVtkRenderWindow()); } rm->RemoveAllObservers(); } mitk::DataStorage::Pointer mitk::InteractionTestHelper::GetDataStorage() { return m_DataStorage; } void mitk::InteractionTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); this->Set3dCameraSettings(); } void mitk::InteractionTestHelper::PlaybackInteraction() { mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); // load events if not loaded yet if (m_Events.empty()) this->LoadInteraction(); auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { (*it)->GetRenderer()->PrepareRender(); (*it)->GetVtkRenderWindow()->Render(); (*it)->GetVtkRenderWindow()->WaitForCompletion(); } mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); it = m_RenderWindowList.begin(); for (; it != end; ++it) { (*it)->GetVtkRenderWindow()->Render(); (*it)->GetVtkRenderWindow()->WaitForCompletion(); } // mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); // playback all events in queue for (unsigned long i = 0; i < m_Events.size(); ++i) { // let dispatcher of sending renderer process the event m_Events.at(i)->GetSender()->GetDispatcher()->ProcessEvent(m_Events.at(i)); } if (false) { it--; (*it)->GetVtkRenderWindow()->GetInteractor()->Start(); } } void mitk::InteractionTestHelper::LoadInteraction() { // load interaction pattern from xml file std::ifstream xmlStream(m_InteractionFilePath.c_str()); mitk::XML2EventParser parser(xmlStream); m_Events = parser.GetInteractions(); xmlStream.close(); // Avoid VTK warning: Trying to delete object with non-zero reference count. parser.SetReferenceCount(0); } void mitk::InteractionTestHelper::SetTimeStep(int newTimeStep) { mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); bool timeStepIsvalid = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetCreatedWorldGeometry()->IsValidTimeStep( newTimeStep); if (timeStepIsvalid) { mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->SetPos(newTimeStep); } } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByName(const std::string &name) { auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { if (name.compare((*it)->GetRenderer()->GetName()) == 0) return (*it).GetPointer(); } return nullptr; } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByDefaultViewDirection( mitk::SliceNavigationController::ViewDirection viewDirection) { auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { if (viewDirection == (*it)->GetSliceNavigationController()->GetDefaultViewDirection()) return (*it).GetPointer(); } return nullptr; } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindow(unsigned int index) { if (index < m_RenderWindowList.size()) { return m_RenderWindowList.at(index).GetPointer(); } else { return nullptr; } } void mitk::InteractionTestHelper::AddDisplayPlaneSubTree() { // add the displayed planes of the multiwidget to a node to which the subtree // @a planesSubTree points ... mitk::PlaneGeometryDataMapper2D::Pointer mapper; mitk::IntProperty::Pointer layer = mitk::IntProperty::New(1000); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetProperty("name", mitk::StringProperty::New("Widgets")); node->SetProperty("helper object", mitk::BoolProperty::New(true)); m_DataStorage->Add(node); for (auto it : m_RenderWindowList) { if (it->GetRenderer()->GetMapperID() == BaseRenderer::Standard3D) continue; // ... of widget 1 mitk::DataNode::Pointer planeNode1 = (mitk::BaseRenderer::GetInstance(it->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode(); planeNode1->SetProperty("visible", mitk::BoolProperty::New(true)); planeNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane")); planeNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); planeNode1->SetProperty("helper object", mitk::BoolProperty::New(true)); planeNode1->SetProperty("layer", layer); planeNode1->SetColor(1.0, 0.0, 0.0); mapper = mitk::PlaneGeometryDataMapper2D::New(); planeNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper); m_DataStorage->Add(planeNode1, node); } } void mitk::InteractionTestHelper::Set3dCameraSettings() { - TiXmlDocument document(m_InteractionFilePath); - bool loadOkay = document.LoadFile(); - if (loadOkay) + tinyxml2::XMLDocument document; + if (tinyxml2::XML_SUCCESS == document.LoadFile(m_InteractionFilePath.c_str())) { // for each renderer found create a render window and configure - for (TiXmlElement *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions()) - ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot()) - ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer()); + for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str()) + ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str()) + ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()); element != nullptr; - element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer())) + element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str())) { // get name of renderer const char *rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); // get mapper slot id mitk::BaseRenderer::MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; - if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr) { int mapperIDNum = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str())); mapperID = static_cast(mapperIDNum); } if (mapperID == mitk::BaseRenderer::Standard3D) { RenderWindow *namedRenderer = nullptr; for (auto it : m_RenderWindowList) { if (strcmp(it->GetRenderer()->GetName(), rendererName) == 0) { namedRenderer = it.GetPointer(); break; } } if (namedRenderer == nullptr) { MITK_ERROR << "No match for render window was found."; return; } namedRenderer->GetRenderer()->PrepareRender(); - if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr) { double cameraFocalPoint[3]; cameraFocalPoint[0] = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str())); cameraFocalPoint[1] = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str())); cameraFocalPoint[2] = - std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ())->c_str()); + std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint); } - if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr) { double cameraPosition[3]; - cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX())->c_str()); - cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY())->c_str()); - cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ())->c_str()); + cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str())); + cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str())); + cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition); } - if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX()) != nullptr) + if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr) { double viewUp[3]; - viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX())->c_str()); - viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY())->c_str()); - viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ())->c_str()); + viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str())); + viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str())); + viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp); } namedRenderer->GetVtkRenderWindow()->Render(); } } } } diff --git a/Modules/Core/include/mitkGeometryDataReaderService.h b/Modules/Core/include/mitkGeometryDataReaderService.h index 1c7f8e23cb..aa95947ed4 100644 --- a/Modules/Core/include/mitkGeometryDataReaderService.h +++ b/Modules/Core/include/mitkGeometryDataReaderService.h @@ -1,61 +1,59 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkGeometryDataReaderService_h #define mitkGeometryDataReaderService_h // MITK #include #include -class TiXmlElement; - namespace mitk { /** * @internal * * @brief reads XML representations of mitk::GeometryData from a file/stream. * * To be used via IOUtil. * * Reader for XML files containing one or multiple XML represenations of * mitk::GeometryData. If multiple mitk::GeometryData objects are stored in one file, * these are assigned to multiple BaseData objects. * * @sa Geometry3DToXML * * @ingroup IO */ class GeometryDataReaderService : public AbstractFileReader { public: GeometryDataReaderService(); ~GeometryDataReaderService() override; using AbstractFileReader::Read; /** * @brief Provides the MIME type for reader and writer. */ static CustomMimeType GEOMETRY_DATA_MIMETYPE(); protected: std::vector> DoRead() override; private: GeometryDataReaderService(const GeometryDataReaderService &other); GeometryDataReaderService *Clone() const override; }; } #endif diff --git a/Modules/Core/include/mitkGeometryDataWriterService.h b/Modules/Core/include/mitkGeometryDataWriterService.h index 6544cd8f4e..6de0ddabd4 100644 --- a/Modules/Core/include/mitkGeometryDataWriterService.h +++ b/Modules/Core/include/mitkGeometryDataWriterService.h @@ -1,55 +1,52 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkGeometryDataWriterService_h #define mitkGeometryDataWriterService_h #include #include -// forward -class TiXmlNode; - namespace mitk { // forward class Geometry3D; /** * @internal * * @brief XML-based writer for mitk::GeometryData * * XML-based writer for mitk::GeometryData. Multiple GeometryData instances * can be written in a single XML file by simply setting multiple inputs to the filter. * * @sa Geometry3DToXML * * @ingroup IO */ class GeometryDataWriterService : public AbstractFileWriter { public: GeometryDataWriterService(); ~GeometryDataWriterService() override; using AbstractFileWriter::Write; void Write() override; private: GeometryDataWriterService(const GeometryDataWriterService &other); mitk::GeometryDataWriterService *Clone() const override; }; } #endif diff --git a/Modules/Core/include/mitkPlaneOrientationProperty.h b/Modules/Core/include/mitkPlaneOrientationProperty.h index 54798b7f00..3d97490348 100644 --- a/Modules/Core/include/mitkPlaneOrientationProperty.h +++ b/Modules/Core/include/mitkPlaneOrientationProperty.h @@ -1,122 +1,122 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITK_PLANE_DECORATION_PROPERTY__H #define MITK_PLANE_DECORATION_PROPERTY__H #include "mitkEnumerationProperty.h" namespace mitk { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4522) #endif /** * Property which controls whether 2D line representation of a PlaneGeometry * should have small arrows at both ends to indicate the orientation of * the plane, and whether the arrows should be oriented in the direction of * the plane's normal or against it. * * Valid values of the enumeration property are * - PLANE_DECORATION_NONE (no arrows) * - PLANE_DECORATION_POSITIVE_ORIENTATION (arrows pointing upwards) * - PLANE_DECORATION_NEGATIVE_ORIENTATION (arrows pointing downwards) * * See also mitk::PlaneGeometryDataMapper2D::DrawOrientationArrow() */ class MITKCORE_EXPORT PlaneOrientationProperty : public EnumerationProperty { public: mitkClassMacro(PlaneOrientationProperty, EnumerationProperty); itkFactorylessNewMacro(Self); itkCloneMacro(Self); - mitkNewMacro1Param(PlaneOrientationProperty, const IdType &); + mitkNewMacro1Param(PlaneOrientationProperty, const IdType &); mitkNewMacro1Param(PlaneOrientationProperty, const std::string &); enum { PLANE_DECORATION_NONE, PLANE_DECORATION_POSITIVE_ORIENTATION, PLANE_DECORATION_NEGATIVE_ORIENTATION }; /** * Returns the state of plane decoration. */ virtual int GetPlaneDecoration(); /** * Sets the decoration type to no decoration. */ virtual void SetPlaneDecorationToNone(); /** * Sets the decoration type to arrows in positive plane direction. */ virtual void SetPlaneDecorationToPositiveOrientation(); /** * Sets the decoration type to arrows in negative plane direction. */ virtual void SetPlaneDecorationToNegativeOrientation(); using BaseProperty::operator=; protected: /** * Constructor. Sets the decoration type to none. */ PlaneOrientationProperty(); /** * Constructor. Sets the decoration type to the given value. If it is not * valid, the interpolation is set to none */ PlaneOrientationProperty(const IdType &value); /** * Constructor. Sets the decoration type to the given value. If it is not * valid, the representation is set to none */ PlaneOrientationProperty(const std::string &value); /** * this function is overridden as protected, so that the user may not add * additional invalid types. */ bool AddEnum(const std::string &name, const IdType &id) override; /** * Adds the standard enumeration types with corresponding strings. */ virtual void AddDecorationTypes(); private: // purposely not implemented PlaneOrientationProperty &operator=(const PlaneOrientationProperty &); itk::LightObject::Pointer InternalClone() const override; }; #ifdef _MSC_VER #pragma warning(pop) #endif } // end of namespace mitk #endif diff --git a/Modules/Core/src/IO/mitkGeometry3DToXML.cpp b/Modules/Core/src/IO/mitkGeometry3DToXML.cpp index c611eac6c7..e9ee434cf7 100644 --- a/Modules/Core/src/IO/mitkGeometry3DToXML.cpp +++ b/Modules/Core/src/IO/mitkGeometry3DToXML.cpp @@ -1,236 +1,242 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkGeometry3DToXML.h" #include -#include +#include -TiXmlElement *mitk::Geometry3DToXML::ToXML(const Geometry3D *geom3D) +#include + +tinyxml2::XMLElement *mitk::Geometry3DToXML::ToXML(tinyxml2::XMLDocument& doc, const Geometry3D *geom3D) { assert(geom3D); // really serialize const AffineTransform3D *transform = geom3D->GetIndexToWorldTransform(); // get transform parameters that would need to be serialized AffineTransform3D::MatrixType matrix = transform->GetMatrix(); AffineTransform3D::OffsetType offset = transform->GetOffset(); bool isImageGeometry = geom3D->GetImageGeometry(); BaseGeometry::BoundsArrayType bounds = geom3D->GetBounds(); // create XML file // construct XML tree describing the geometry - auto *geomElem = new TiXmlElement("Geometry3D"); - geomElem->SetAttribute("ImageGeometry", isImageGeometry ? "true" : "false"); + auto *geomElem = doc.NewElement("Geometry3D"); + geomElem->SetAttribute("ImageGeometry", isImageGeometry); geomElem->SetAttribute("FrameOfReferenceID", geom3D->GetFrameOfReferenceID()); // coefficients are matrix[row][column]! - auto *matrixElem = new TiXmlElement("IndexToWorld"); + auto *matrixElem = doc.NewElement("IndexToWorld"); matrixElem->SetAttribute("type", "Matrix3x3"); - matrixElem->SetAttribute("m_0_0", boost::lexical_cast(matrix[0][0])); - matrixElem->SetAttribute("m_0_1", boost::lexical_cast(matrix[0][1])); - matrixElem->SetAttribute("m_0_2", boost::lexical_cast(matrix[0][2])); - matrixElem->SetAttribute("m_1_0", boost::lexical_cast(matrix[1][0])); - matrixElem->SetAttribute("m_1_1", boost::lexical_cast(matrix[1][1])); - matrixElem->SetAttribute("m_1_2", boost::lexical_cast(matrix[1][2])); - matrixElem->SetAttribute("m_2_0", boost::lexical_cast(matrix[2][0])); - matrixElem->SetAttribute("m_2_1", boost::lexical_cast(matrix[2][1])); - matrixElem->SetAttribute("m_2_2", boost::lexical_cast(matrix[2][2])); - geomElem->LinkEndChild(matrixElem); - - auto *offsetElem = new TiXmlElement("Offset"); + matrixElem->SetAttribute("m_0_0", boost::lexical_cast(matrix[0][0]).c_str()); + matrixElem->SetAttribute("m_0_1", boost::lexical_cast(matrix[0][1]).c_str()); + matrixElem->SetAttribute("m_0_2", boost::lexical_cast(matrix[0][2]).c_str()); + matrixElem->SetAttribute("m_1_0", boost::lexical_cast(matrix[1][0]).c_str()); + matrixElem->SetAttribute("m_1_1", boost::lexical_cast(matrix[1][1]).c_str()); + matrixElem->SetAttribute("m_1_2", boost::lexical_cast(matrix[1][2]).c_str()); + matrixElem->SetAttribute("m_2_0", boost::lexical_cast(matrix[2][0]).c_str()); + matrixElem->SetAttribute("m_2_1", boost::lexical_cast(matrix[2][1]).c_str()); + matrixElem->SetAttribute("m_2_2", boost::lexical_cast(matrix[2][2]).c_str()); + geomElem->InsertEndChild(matrixElem); + + auto *offsetElem = doc.NewElement("Offset"); offsetElem->SetAttribute("type", "Vector3D"); - offsetElem->SetAttribute("x", boost::lexical_cast(offset[0])); - offsetElem->SetAttribute("y", boost::lexical_cast(offset[1])); - offsetElem->SetAttribute("z", boost::lexical_cast(offset[2])); - geomElem->LinkEndChild(offsetElem); + offsetElem->SetAttribute("x", boost::lexical_cast(offset[0]).c_str()); + offsetElem->SetAttribute("y", boost::lexical_cast(offset[1]).c_str()); + offsetElem->SetAttribute("z", boost::lexical_cast(offset[2]).c_str()); + geomElem->InsertEndChild(offsetElem); - auto *boundsElem = new TiXmlElement("Bounds"); - auto *boundsMinElem = new TiXmlElement("Min"); + auto *boundsElem = doc.NewElement("Bounds"); + auto *boundsMinElem = doc.NewElement("Min"); boundsMinElem->SetAttribute("type", "Vector3D"); - boundsMinElem->SetAttribute("x", boost::lexical_cast(bounds[0])); - boundsMinElem->SetAttribute("y", boost::lexical_cast(bounds[2])); - boundsMinElem->SetAttribute("z", boost::lexical_cast(bounds[4])); - boundsElem->LinkEndChild(boundsMinElem); - auto *boundsMaxElem = new TiXmlElement("Max"); + boundsMinElem->SetAttribute("x", boost::lexical_cast(bounds[0]).c_str()); + boundsMinElem->SetAttribute("y", boost::lexical_cast(bounds[2]).c_str()); + boundsMinElem->SetAttribute("z", boost::lexical_cast(bounds[4]).c_str()); + boundsElem->InsertEndChild(boundsMinElem); + auto *boundsMaxElem = doc.NewElement("Max"); boundsMaxElem->SetAttribute("type", "Vector3D"); - boundsMaxElem->SetAttribute("x", boost::lexical_cast(bounds[1])); - boundsMaxElem->SetAttribute("y", boost::lexical_cast(bounds[3])); - boundsMaxElem->SetAttribute("z", boost::lexical_cast(bounds[5])); - boundsElem->LinkEndChild(boundsMaxElem); - geomElem->LinkEndChild(boundsElem); + boundsMaxElem->SetAttribute("x", boost::lexical_cast(bounds[1]).c_str()); + boundsMaxElem->SetAttribute("y", boost::lexical_cast(bounds[3]).c_str()); + boundsMaxElem->SetAttribute("z", boost::lexical_cast(bounds[5]).c_str()); + boundsElem->InsertEndChild(boundsMaxElem); + geomElem->InsertEndChild(boundsElem); return geomElem; } -mitk::Geometry3D::Pointer mitk::Geometry3DToXML::FromXML(TiXmlElement *geometryElement) +mitk::Geometry3D::Pointer mitk::Geometry3DToXML::FromXML(const tinyxml2::XMLElement *geometryElement) { if (!geometryElement) { MITK_ERROR << "Cannot deserialize Geometry3D from nullptr."; return nullptr; } AffineTransform3D::MatrixType matrix; AffineTransform3D::OffsetType offset; bool isImageGeometry(false); unsigned int frameOfReferenceID(0); BaseGeometry::BoundsArrayType bounds; - if (TIXML_SUCCESS != geometryElement->QueryUnsignedAttribute("FrameOfReferenceID", &frameOfReferenceID)) + if (tinyxml2::XML_SUCCESS != geometryElement->QueryUnsignedAttribute("FrameOfReferenceID", &frameOfReferenceID)) { MITK_WARN << "Missing FrameOfReference for Geometry3D."; } - if (TIXML_SUCCESS != geometryElement->QueryBoolAttribute("ImageGeometry", &isImageGeometry)) + if (tinyxml2::XML_SUCCESS != geometryElement->QueryBoolAttribute("ImageGeometry", &isImageGeometry)) { MITK_WARN << "Missing bool ImageGeometry for Geometry3D."; } // matrix - if (TiXmlElement *matrixElem = geometryElement->FirstChildElement("IndexToWorld")->ToElement()) + if (auto *matrixElem = geometryElement->FirstChildElement("IndexToWorld")) { bool matrixComplete = true; for (unsigned int r = 0; r < 3; ++r) { for (unsigned int c = 0; c < 3; ++c) { std::stringstream element_namer; element_namer << "m_" << r << "_" << c; - std::string string_value; - if (TIXML_SUCCESS == matrixElem->QueryStringAttribute(element_namer.str().c_str(), &string_value)) + const char* string_value = matrixElem->Attribute(element_namer.str().c_str()); + if (nullptr != string_value) { try { matrix[r][c] = boost::lexical_cast(string_value); } catch ( const boost::bad_lexical_cast &e ) { MITK_ERROR << "Could not parse '" << string_value << "' as number: " << e.what(); return nullptr; } } else { matrixComplete = false; } } } if (!matrixComplete) { MITK_ERROR << "Could not parse all Geometry3D matrix coefficients!"; return nullptr; } } else { MITK_ERROR << "Parse error: expected Matrix3x3 child below Geometry3D node"; return nullptr; } // offset - if (TiXmlElement *offsetElem = geometryElement->FirstChildElement("Offset")->ToElement()) + if (auto *offsetElem = geometryElement->FirstChildElement("Offset")) { - bool vectorComplete = true; - std::string offset_string[3]; - vectorComplete &= TIXML_SUCCESS == offsetElem->QueryStringAttribute("x", &offset_string[0]); - vectorComplete &= TIXML_SUCCESS == offsetElem->QueryStringAttribute("y", &offset_string[1]); - vectorComplete &= TIXML_SUCCESS == offsetElem->QueryStringAttribute("z", &offset_string[2]); + std::array offset_string = { + offsetElem->Attribute("x"), + offsetElem->Attribute("y"), + offsetElem->Attribute("z") + }; - if (!vectorComplete) + if (nullptr == offset_string[0] || nullptr == offset_string[1] || nullptr == offset_string[2]) { MITK_ERROR << "Could not parse complete Geometry3D offset!"; return nullptr; } for (unsigned int d = 0; d < 3; ++d) try { offset[d] = boost::lexical_cast(offset_string[d]); } catch ( const boost::bad_lexical_cast &e ) { MITK_ERROR << "Could not parse '" << offset_string[d] << "' as number: " << e.what(); return nullptr; } } else { MITK_ERROR << "Parse error: expected Offset3D child below Geometry3D node"; return nullptr; } // bounds - if (TiXmlElement *boundsElem = geometryElement->FirstChildElement("Bounds")->ToElement()) + if (auto *boundsElem = geometryElement->FirstChildElement("Bounds")) { - bool vectorsComplete(true); - std::string bounds_string[6]; - if (TiXmlElement *minElem = boundsElem->FirstChildElement("Min")->ToElement()) + bool vectorsComplete; + std::array bounds_string; + if (auto* minElem = boundsElem->FirstChildElement("Min")) { - vectorsComplete &= TIXML_SUCCESS == minElem->QueryStringAttribute("x", &bounds_string[0]); - vectorsComplete &= TIXML_SUCCESS == minElem->QueryStringAttribute("y", &bounds_string[2]); - vectorsComplete &= TIXML_SUCCESS == minElem->QueryStringAttribute("z", &bounds_string[4]); + bounds_string[0] = minElem->Attribute("x"); + bounds_string[2] = minElem->Attribute("y"); + bounds_string[4] = minElem->Attribute("z"); + + vectorsComplete = !(nullptr == bounds_string[0] || nullptr == bounds_string[2] || nullptr == bounds_string[4]); } else { vectorsComplete = false; } - if (TiXmlElement *maxElem = boundsElem->FirstChildElement("Max")->ToElement()) + if (auto *maxElem = boundsElem->FirstChildElement("Max")) { - vectorsComplete &= TIXML_SUCCESS == maxElem->QueryStringAttribute("x", &bounds_string[1]); - vectorsComplete &= TIXML_SUCCESS == maxElem->QueryStringAttribute("y", &bounds_string[3]); - vectorsComplete &= TIXML_SUCCESS == maxElem->QueryStringAttribute("z", &bounds_string[5]); + bounds_string[1] = maxElem->Attribute("x"); + bounds_string[3] = maxElem->Attribute("y"); + bounds_string[5] = maxElem->Attribute("z"); + + vectorsComplete = !(nullptr == bounds_string[1] || nullptr == bounds_string[3] || nullptr == bounds_string[5]); } else { vectorsComplete = false; } if (!vectorsComplete) { MITK_ERROR << "Could not parse complete Geometry3D bounds!"; return nullptr; } for (unsigned int d = 0; d < 6; ++d) try { bounds[d] = boost::lexical_cast(bounds_string[d]); } catch ( const boost::bad_lexical_cast &e ) { MITK_ERROR << "Could not parse '" << bounds_string[d] << "' as number: " << e.what(); return nullptr; } } // build GeometryData from matrix/offset AffineTransform3D::Pointer newTransform = AffineTransform3D::New(); newTransform->SetMatrix(matrix); newTransform->SetOffset(offset); Geometry3D::Pointer newGeometry = Geometry3D::New(); newGeometry->SetFrameOfReferenceID(frameOfReferenceID); newGeometry->SetImageGeometry(isImageGeometry); newGeometry->SetIndexToWorldTransform(newTransform); newGeometry->SetBounds(bounds); return newGeometry; } diff --git a/Modules/Core/src/IO/mitkGeometry3DToXML.h b/Modules/Core/src/IO/mitkGeometry3DToXML.h index d0cd9d0f6d..ef3a2454eb 100644 --- a/Modules/Core/src/IO/mitkGeometry3DToXML.h +++ b/Modules/Core/src/IO/mitkGeometry3DToXML.h @@ -1,51 +1,55 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkGeometry3DToXML_h #define mitkGeometry3DToXML_h // MITK #include "mitkGeometry3D.h" -class TiXmlElement; +namespace tinyxml2 +{ + class XMLDocument; + class XMLElement; +} namespace mitk { /** * @internal * * @brief Helper for Geometry3D related I/O classes. * * Creates TinyXML elements (blocks) that describe a Geometry3D. * Also offers a method to read such blocks and create a corresponding Geometry3D. * * @sa GeometryDataReaderService, GeometryDataWriterService, PointSetWriterService, PointSetReaderService * * @ingroup IO */ class Geometry3DToXML { public: /** * @brief Serialize given geometry to XML. */ - static TiXmlElement *ToXML(const Geometry3D *geometry); + static tinyxml2::XMLElement *ToXML(tinyxml2::XMLDocument& doc, const Geometry3D *geometry); /** * @brief Create a Geometry3D from XML. * Interprets only the format created by ToXML(). */ - static Geometry3D::Pointer FromXML(TiXmlElement *node); + static Geometry3D::Pointer FromXML(const tinyxml2::XMLElement *node); }; } #endif diff --git a/Modules/Core/src/IO/mitkGeometryDataReaderService.cpp b/Modules/Core/src/IO/mitkGeometryDataReaderService.cpp index 0b13ffe89c..8731ae70e8 100644 --- a/Modules/Core/src/IO/mitkGeometryDataReaderService.cpp +++ b/Modules/Core/src/IO/mitkGeometryDataReaderService.cpp @@ -1,112 +1,113 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include "mitkGeometryDataReaderService.h" #include "mitkGeometry3DToXML.h" #include "mitkIOMimeTypes.h" #include "mitkProportionalTimeGeometryToXML.h" // STL #include -#include +#include mitk::GeometryDataReaderService::GeometryDataReaderService() : AbstractFileReader(IOMimeTypes::GEOMETRY_DATA_MIMETYPE(), "MITK Geometry Data Reader") { RegisterService(); } mitk::GeometryDataReaderService::~GeometryDataReaderService() { } std::vector> mitk::GeometryDataReaderService::DoRead() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); std::vector> result; InputStream stream(this); - TiXmlDocument doc; - stream >> doc; + std::string s(std::istreambuf_iterator{stream.rdbuf()}, std::istreambuf_iterator()); + tinyxml2::XMLDocument doc; + doc.Parse(s.c_str(), s.size()); if (!doc.Error()) { - TiXmlHandle docHandle(&doc); + tinyxml2::XMLHandle docHandle(&doc); - for (TiXmlElement *geomDataElement = docHandle.FirstChildElement("GeometryData").ToElement(); + for (auto *geomDataElement = docHandle.FirstChildElement("GeometryData").ToElement(); geomDataElement != nullptr; geomDataElement = geomDataElement->NextSiblingElement()) { - for (TiXmlElement *currentElement = geomDataElement->FirstChildElement(); currentElement != nullptr; + for (auto *currentElement = geomDataElement->FirstChildElement(); currentElement != nullptr; currentElement = currentElement->NextSiblingElement()) { // different geometries could have been serialized from a GeometryData // object: std::string tagName = currentElement->Value(); if (tagName == "Geometry3D") { Geometry3D::Pointer restoredGeometry = Geometry3DToXML::FromXML(currentElement); if (restoredGeometry.IsNotNull()) { GeometryData::Pointer newGeometryData = GeometryData::New(); newGeometryData->SetGeometry(restoredGeometry); result.push_back(newGeometryData.GetPointer()); } else { MITK_ERROR << "Invalid tag encountered. Skipping."; } } else if (tagName == "ProportionalTimeGeometry") { ProportionalTimeGeometry::Pointer restoredTimeGeometry = ProportionalTimeGeometryToXML::FromXML(currentElement); if (restoredTimeGeometry.IsNotNull()) { GeometryData::Pointer newGeometryData = GeometryData::New(); newGeometryData->SetTimeGeometry(restoredTimeGeometry); result.push_back(newGeometryData.GetPointer()); } else { MITK_ERROR << "Invalid tag encountered. Skipping."; } } } // for child of } // for } else { - mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc(); + mitkThrow() << doc.ErrorStr(); } if (result.empty()) { mitkThrow() << "Did not read a single GeometryData object from input."; } return result; } mitk::GeometryDataReaderService::GeometryDataReaderService(const mitk::GeometryDataReaderService &other) : mitk::AbstractFileReader(other) { } mitk::GeometryDataReaderService *mitk::GeometryDataReaderService::Clone() const { return new GeometryDataReaderService(*this); } diff --git a/Modules/Core/src/IO/mitkGeometryDataWriterService.cpp b/Modules/Core/src/IO/mitkGeometryDataWriterService.cpp index 1ca99cb8d0..57f02597a9 100644 --- a/Modules/Core/src/IO/mitkGeometryDataWriterService.cpp +++ b/Modules/Core/src/IO/mitkGeometryDataWriterService.cpp @@ -1,91 +1,90 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkGeometryDataWriterService.h" #include "mitkIOMimeTypes.h" #include "mitkProportionalTimeGeometryToXML.h" -#include +#include #include mitk::GeometryDataWriterService::GeometryDataWriterService() : AbstractFileWriter( GeometryData::GetStaticNameOfClass(), IOMimeTypes::GEOMETRY_DATA_MIMETYPE(), "MITK Geometry Data Writer") { RegisterService(); } mitk::GeometryDataWriterService::GeometryDataWriterService(const mitk::GeometryDataWriterService &other) : AbstractFileWriter(other) { } mitk::GeometryDataWriterService::~GeometryDataWriterService() { } void mitk::GeometryDataWriterService::Write() { /* using the stream interface produces files without line breaks or indentation.. But before changing to file interface, need to understand the new I/O classes */ OutputStream out(this); if (!out.good()) { mitkThrow() << "Stream not good."; } // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); // Open XML file using TinyXML, // loop over all inputs, // call appropriate serializing functions - TiXmlDocument doc; + tinyxml2::XMLDocument doc; + doc.InsertEndChild(doc.NewDeclaration()); - auto *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); - - auto *rootNode = new TiXmlElement("GeometryData"); - doc.LinkEndChild(rootNode); + auto* rootNode = doc.NewElement("GeometryData"); + doc.InsertEndChild(rootNode); // note version info - auto *version = new TiXmlElement("Version"); + auto *version = doc.NewElement("Version"); version->SetAttribute("Writer", __FILE__); version->SetAttribute("FileVersion", 1); - rootNode->LinkEndChild(version); + rootNode->InsertEndChild(version); const auto *data = static_cast(this->GetInput()); const ProportionalTimeGeometry *timeGeometry(nullptr); if ((timeGeometry = dynamic_cast(data->GetTimeGeometry()))) { - TiXmlElement *timeGeometryElement = ProportionalTimeGeometryToXML::ToXML(timeGeometry); - rootNode->LinkEndChild(timeGeometryElement); + auto *timeGeometryElement = ProportionalTimeGeometryToXML::ToXML(doc, timeGeometry); + rootNode->InsertEndChild(timeGeometryElement); } else { MITK_WARN << "Serializing GeometryData that does not have a valid ProportionalTimeGeometry! Not implemented!"; } // Write out document - out << doc; + tinyxml2::XMLPrinter printer; + doc.Print(&printer); + out << printer.CStr(); } mitk::GeometryDataWriterService *mitk::GeometryDataWriterService::Clone() const { return new GeometryDataWriterService(*this); } diff --git a/Modules/Core/src/IO/mitkPointSetReaderService.cpp b/Modules/Core/src/IO/mitkPointSetReaderService.cpp index 68cc84f562..63d3018782 100644 --- a/Modules/Core/src/IO/mitkPointSetReaderService.cpp +++ b/Modules/Core/src/IO/mitkPointSetReaderService.cpp @@ -1,275 +1,276 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include "mitkPointSetReaderService.h" #include "mitkGeometry3DToXML.h" #include "mitkIOMimeTypes.h" #include "mitkProportionalTimeGeometry.h" +#include // STL #include #include -#include -#include +#include mitk::PointSetReaderService::PointSetReaderService() : AbstractFileReader(CustomMimeType(IOMimeTypes::POINTSET_MIMETYPE()), "MITK Point Set Reader") { RegisterService(); } mitk::PointSetReaderService::~PointSetReaderService() { } std::vector> mitk::PointSetReaderService::DoRead() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); std::vector> result; InputStream stream(this); - TiXmlDocument doc; - stream >> doc; + std::string s(std::istreambuf_iterator{stream.rdbuf()}, std::istreambuf_iterator()); + tinyxml2::XMLDocument doc; + doc.Parse(s.c_str(), s.size()); if (!doc.Error()) { - TiXmlHandle docHandle(&doc); + tinyxml2::XMLHandle docHandle(&doc); // unsigned int pointSetCounter(0); - for (TiXmlElement *currentPointSetElement = + for (auto *currentPointSetElement = docHandle.FirstChildElement("point_set_file").FirstChildElement("point_set").ToElement(); currentPointSetElement != nullptr; currentPointSetElement = currentPointSetElement->NextSiblingElement()) { mitk::PointSet::Pointer newPointSet = mitk::PointSet::New(); // time geometry assembled for addition after all points // else the SetPoint method would already transform the points that we provide it mitk::ProportionalTimeGeometry::Pointer timeGeometry = mitk::ProportionalTimeGeometry::New(); if (currentPointSetElement->FirstChildElement("time_series") != nullptr) { - for (TiXmlElement *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement(); + for (auto *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement(); currentTimeSeries != nullptr; currentTimeSeries = currentTimeSeries->NextSiblingElement()) { unsigned int currentTimeStep(0); - TiXmlElement *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id"); + auto *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id"); currentTimeStep = atoi(currentTimeSeriesID->GetText()); timeGeometry->Expand(currentTimeStep + 1); // expand (default to identity) in any case - TiXmlElement *geometryElem = currentTimeSeries->FirstChildElement("Geometry3D"); + auto *geometryElem = currentTimeSeries->FirstChildElement("Geometry3D"); if (geometryElem) { Geometry3D::Pointer geometry = Geometry3DToXML::FromXML(geometryElem); if (geometry.IsNotNull()) { timeGeometry->SetTimeStepGeometry(geometry, currentTimeStep); } else { MITK_ERROR << "Could not deserialize Geometry3D element."; } } else { MITK_WARN << "Fallback to legacy behavior: defining PointSet geometry as identity"; } newPointSet = this->ReadPoints(newPointSet, currentTimeSeries, currentTimeStep); } } else { newPointSet = this->ReadPoints(newPointSet, currentPointSetElement, 0); } newPointSet->SetTimeGeometry(timeGeometry); result.push_back(newPointSet.GetPointer()); } } else { - mitkThrow() << "Parsing error at line " << doc.ErrorRow() << ", col " << doc.ErrorCol() << ": " << doc.ErrorDesc(); + mitkThrow() << doc.ErrorStr(); } return result; } -mitk::BaseGeometry::Pointer mitk::PointSetReaderService::ReadGeometry(TiXmlElement *parentElement) +mitk::BaseGeometry::Pointer mitk::PointSetReaderService::ReadGeometry(tinyxml2::XMLElement *parentElement) { - TiXmlElement *geometryElem = parentElement->FirstChildElement("geometry3d"); + auto *geometryElem = parentElement->FirstChildElement("geometry3d"); if (!geometryElem) return nullptr; // data to generate AffineTransform3D::MatrixType matrix; AffineTransform3D::OffsetType offset; bool isImageGeometry(false); unsigned int frameOfReferenceID(0); BaseGeometry::BoundsArrayType bounds; bool somethingMissing(false); // find data in xml structure - TiXmlElement *imageGeometryElem = geometryElem->FirstChildElement("image_geometry"); + auto *imageGeometryElem = geometryElem->FirstChildElement("image_geometry"); if (imageGeometryElem) { std::string igs = imageGeometryElem->GetText(); isImageGeometry = igs == "true" || igs == "TRUE" || igs == "1"; } else somethingMissing = true; - TiXmlElement *frameOfReferenceElem = geometryElem->FirstChildElement("frame_of_reference_id"); + auto *frameOfReferenceElem = geometryElem->FirstChildElement("frame_of_reference_id"); if (frameOfReferenceElem) { frameOfReferenceID = atoi(frameOfReferenceElem->GetText()); } else somethingMissing = true; - TiXmlElement *indexToWorldElem = geometryElem->FirstChildElement("index_to_world"); + auto *indexToWorldElem = geometryElem->FirstChildElement("index_to_world"); if (indexToWorldElem) { - TiXmlElement *matrixElem = indexToWorldElem->FirstChildElement("matrix3x3"); - TiXmlElement *offsetElem = indexToWorldElem->FirstChildElement("offset"); + auto *matrixElem = indexToWorldElem->FirstChildElement("matrix3x3"); + auto *offsetElem = indexToWorldElem->FirstChildElement("offset"); if (indexToWorldElem && offsetElem) { - TiXmlElement *col0 = matrixElem->FirstChildElement("column_0"); - TiXmlElement *col1 = matrixElem->FirstChildElement("column_1"); - TiXmlElement *col2 = matrixElem->FirstChildElement("column_2"); + auto*col0 = matrixElem->FirstChildElement("column_0"); + auto*col1 = matrixElem->FirstChildElement("column_1"); + auto*col2 = matrixElem->FirstChildElement("column_2"); if (col0 && col1 && col2) { - somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("x", &matrix[0][0]); - somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("y", &matrix[1][0]); - somethingMissing |= TIXML_SUCCESS != col0->QueryDoubleAttribute("z", &matrix[2][0]); + somethingMissing |= tinyxml2::XML_SUCCESS != col0->QueryDoubleAttribute("x", &matrix[0][0]); + somethingMissing |= tinyxml2::XML_SUCCESS != col0->QueryDoubleAttribute("y", &matrix[1][0]); + somethingMissing |= tinyxml2::XML_SUCCESS != col0->QueryDoubleAttribute("z", &matrix[2][0]); - somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("x", &matrix[0][1]); - somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("y", &matrix[1][1]); - somethingMissing |= TIXML_SUCCESS != col1->QueryDoubleAttribute("z", &matrix[2][1]); + somethingMissing |= tinyxml2::XML_SUCCESS != col1->QueryDoubleAttribute("x", &matrix[0][1]); + somethingMissing |= tinyxml2::XML_SUCCESS != col1->QueryDoubleAttribute("y", &matrix[1][1]); + somethingMissing |= tinyxml2::XML_SUCCESS != col1->QueryDoubleAttribute("z", &matrix[2][1]); - somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("x", &matrix[0][2]); - somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("y", &matrix[1][2]); - somethingMissing |= TIXML_SUCCESS != col2->QueryDoubleAttribute("z", &matrix[2][2]); + somethingMissing |= tinyxml2::XML_SUCCESS != col2->QueryDoubleAttribute("x", &matrix[0][2]); + somethingMissing |= tinyxml2::XML_SUCCESS != col2->QueryDoubleAttribute("y", &matrix[1][2]); + somethingMissing |= tinyxml2::XML_SUCCESS != col2->QueryDoubleAttribute("z", &matrix[2][2]); } else somethingMissing = true; - somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("x", &offset[0]); - somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("y", &offset[1]); - somethingMissing |= TIXML_SUCCESS != offsetElem->QueryDoubleAttribute("z", &offset[2]); + somethingMissing |= tinyxml2::XML_SUCCESS != offsetElem->QueryDoubleAttribute("x", &offset[0]); + somethingMissing |= tinyxml2::XML_SUCCESS != offsetElem->QueryDoubleAttribute("y", &offset[1]); + somethingMissing |= tinyxml2::XML_SUCCESS != offsetElem->QueryDoubleAttribute("z", &offset[2]); } else somethingMissing = true; - TiXmlElement *boundsElem = geometryElem->FirstChildElement("bounds"); + auto *boundsElem = geometryElem->FirstChildElement("bounds"); if (boundsElem) { - TiXmlElement *minBoundsElem = boundsElem->FirstChildElement("min"); - TiXmlElement *maxBoundsElem = boundsElem->FirstChildElement("max"); + auto *minBoundsElem = boundsElem->FirstChildElement("min"); + auto *maxBoundsElem = boundsElem->FirstChildElement("max"); if (minBoundsElem && maxBoundsElem) { - somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("x", &bounds[0]); - somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("y", &bounds[2]); - somethingMissing |= TIXML_SUCCESS != minBoundsElem->QueryDoubleAttribute("z", &bounds[4]); + somethingMissing |= tinyxml2::XML_SUCCESS != minBoundsElem->QueryDoubleAttribute("x", &bounds[0]); + somethingMissing |= tinyxml2::XML_SUCCESS != minBoundsElem->QueryDoubleAttribute("y", &bounds[2]); + somethingMissing |= tinyxml2::XML_SUCCESS != minBoundsElem->QueryDoubleAttribute("z", &bounds[4]); - somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("x", &bounds[1]); - somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("y", &bounds[3]); - somethingMissing |= TIXML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("z", &bounds[5]); + somethingMissing |= tinyxml2::XML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("x", &bounds[1]); + somethingMissing |= tinyxml2::XML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("y", &bounds[3]); + somethingMissing |= tinyxml2::XML_SUCCESS != maxBoundsElem->QueryDoubleAttribute("z", &bounds[5]); } else somethingMissing = true; } else somethingMissing = true; } else somethingMissing = true; if (somethingMissing) { MITK_ERROR << "XML structure of geometry inside a PointSet file broken. Refusing to build Geometry3D"; return nullptr; } else { Geometry3D::Pointer g = Geometry3D::New(); g->SetImageGeometry(isImageGeometry); g->SetFrameOfReferenceID(frameOfReferenceID); g->SetBounds(bounds); AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetMatrix(matrix); transform->SetOffset(offset); g->SetIndexToWorldTransform(transform); return g.GetPointer(); } } mitk::PointSet::Pointer mitk::PointSetReaderService::ReadPoints(mitk::PointSet::Pointer newPointSet, - TiXmlElement *currentTimeSeries, + tinyxml2::XMLElement *currentTimeSeries, unsigned int currentTimeStep) { if (currentTimeSeries->FirstChildElement("point") != nullptr) { - for (TiXmlElement *currentPoint = currentTimeSeries->FirstChildElement("point")->ToElement(); currentPoint != nullptr; + for (auto *currentPoint = currentTimeSeries->FirstChildElement("point"); currentPoint != nullptr; currentPoint = currentPoint->NextSiblingElement()) { unsigned int id(0); auto spec((mitk::PointSpecificationType)0); double x(0.0); double y(0.0); double z(0.0); id = atoi(currentPoint->FirstChildElement("id")->GetText()); if (currentPoint->FirstChildElement("specification") != nullptr) { spec = (mitk::PointSpecificationType)atoi(currentPoint->FirstChildElement("specification")->GetText()); } x = atof(currentPoint->FirstChildElement("x")->GetText()); y = atof(currentPoint->FirstChildElement("y")->GetText()); z = atof(currentPoint->FirstChildElement("z")->GetText()); mitk::Point3D point; mitk::FillVector3D(point, x, y, z); newPointSet->SetPoint(id, point, spec, currentTimeStep); } } else { if (currentTimeStep != newPointSet->GetTimeSteps() + 1) { newPointSet->Expand(currentTimeStep + 1); // expand time step series with empty time step } } return newPointSet; } mitk::PointSetReaderService::PointSetReaderService(const mitk::PointSetReaderService &other) : mitk::AbstractFileReader(other) { } mitk::PointSetReaderService *mitk::PointSetReaderService::Clone() const { return new mitk::PointSetReaderService(*this); } diff --git a/Modules/Core/src/IO/mitkPointSetReaderService.h b/Modules/Core/src/IO/mitkPointSetReaderService.h index 5aba51b592..f72bc23fdb 100644 --- a/Modules/Core/src/IO/mitkPointSetReaderService.h +++ b/Modules/Core/src/IO/mitkPointSetReaderService.h @@ -1,62 +1,65 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_POINT_SET_READER_SERVICE__H_ #define _MITK_POINT_SET_READER_SERVICE__H_ // MITK #include #include -class TiXmlElement; +namespace tinyxml2 +{ + class XMLElement; +} namespace mitk { /** * @internal * * @brief reads xml representations of mitk::PointSets from a file * * Reader for xml files containing one or multiple xml represenations of * mitk::PointSet. If multiple mitk::PointSet objects are stored in one file, * these are assigned to multiple BaseData objects. * * The reader is able to read the old 3D Pointsets without the "specification" and "timeseries" tags and the new 4D * Pointsets. * * @ingroup IO */ class PointSetReaderService : public AbstractFileReader { public: PointSetReaderService(); ~PointSetReaderService() override; using AbstractFileReader::Read; protected: std::vector> DoRead() override; private: PointSetReaderService(const PointSetReaderService &other); - mitk::BaseGeometry::Pointer ReadGeometry(TiXmlElement *parentElement); + mitk::BaseGeometry::Pointer ReadGeometry(tinyxml2::XMLElement *parentElement); mitk::PointSet::Pointer ReadPoints(mitk::PointSet::Pointer newPointSet, - TiXmlElement *currentTimeSeries, + tinyxml2::XMLElement *currentTimeSeries, unsigned int currentTimeStep); PointSetReaderService *Clone() const override; }; } #endif diff --git a/Modules/Core/src/IO/mitkPointSetWriterService.cpp b/Modules/Core/src/IO/mitkPointSetWriterService.cpp index 30a5d25dcc..63e99ad061 100644 --- a/Modules/Core/src/IO/mitkPointSetWriterService.cpp +++ b/Modules/Core/src/IO/mitkPointSetWriterService.cpp @@ -1,182 +1,179 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkPointSetWriterService.h" #include "mitkGeometry3DToXML.h" #include "mitkIOMimeTypes.h" #include "mitkLocaleSwitch.h" #include "mitkGeometry3D.h" -#include - #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") { RegisterService(); } mitk::PointSetWriterService::PointSetWriterService(const mitk::PointSetWriterService &other) : AbstractFileWriter(other) { } mitk::PointSetWriterService::~PointSetWriterService() { } void mitk::PointSetWriterService::Write() { mitk::LocaleSwitch localeC("C"); - TiXmlDocument doc; - - auto *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); + tinyxml2::XMLDocument doc; + doc.InsertEndChild(doc.NewDeclaration()); - auto *rootNode = new TiXmlElement(XML_POINT_SET_FILE); - doc.LinkEndChild(rootNode); + auto *rootNode = doc.NewElement(XML_POINT_SET_FILE.c_str()); + doc.InsertEndChild(rootNode); - auto *versionNode = new TiXmlElement(XML_FILE_VERSION); - auto *versionText = new TiXmlText(VERSION_STRING); - versionNode->LinkEndChild(versionText); - rootNode->LinkEndChild(versionNode); + auto *versionNode = doc.NewElement(XML_FILE_VERSION.c_str()); + auto *versionText = doc.NewText(VERSION_STRING.c_str()); + versionNode->InsertEndChild(versionText); + rootNode->InsertEndChild(versionNode); - TiXmlElement *pointSetNode = ToXML(static_cast(this->GetInput())); + auto *pointSetNode = ToXML(doc, static_cast(this->GetInput())); if (!pointSetNode) { mitkThrow() << "Serialization error during PointSet writing."; } - rootNode->LinkEndChild(pointSetNode); + rootNode->InsertEndChild(pointSetNode); // out << doc; // streaming of TinyXML write no new-lines, // rendering XML files unreadable (for humans) LocalFile f(this); - if (!doc.SaveFile(f.GetFileName())) + if (tinyxml2::XML_SUCCESS != doc.SaveFile(f.GetFileName().c_str())) { mitkThrow() << "Some error during point set writing."; } } mitk::PointSetWriterService *mitk::PointSetWriterService::Clone() const { return new PointSetWriterService(*this); } -TiXmlElement *mitk::PointSetWriterService::ToXML(const mitk::PointSet *pointSet) +tinyxml2::XMLElement *mitk::PointSetWriterService::ToXML(tinyxml2::XMLDocument& doc, const mitk::PointSet *pointSet) { // 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. - auto *pointSetElement = new TiXmlElement(XML_POINT_SET); + auto *pointSetElement = doc.NewElement(XML_POINT_SET.c_str()); unsigned int timecount = pointSet->GetTimeSteps(); for (unsigned int i = 0; i < timecount; i++) { - auto *timeSeriesElement = new TiXmlElement(XML_TIME_SERIES); - pointSetElement->LinkEndChild(timeSeriesElement); + auto *timeSeriesElement = doc.NewElement(XML_TIME_SERIES.c_str()); + pointSetElement->InsertEndChild(timeSeriesElement); - auto *timeSeriesIDElement = new TiXmlElement(XML_TIME_SERIES_ID); - timeSeriesElement->LinkEndChild(timeSeriesIDElement); - TiXmlText *timeSeriesIDText = new TiXmlText(ConvertToString(i)); - timeSeriesIDElement->LinkEndChild(timeSeriesIDText); + auto *timeSeriesIDElement = doc.NewElement(XML_TIME_SERIES_ID.c_str()); + timeSeriesElement->InsertEndChild(timeSeriesIDElement); + auto *timeSeriesIDText = doc.NewText(ConvertToString(i).c_str()); + timeSeriesIDElement->InsertEndChild(timeSeriesIDText); PointSet::PointsContainer *pointsContainer = pointSet->GetPointSet(i)->GetPoints(); PointSet::PointsContainer::Iterator it; auto *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); + auto *geometryElement = Geometry3DToXML::ToXML(doc, geometry); + timeSeriesElement->InsertEndChild(geometryElement); } for (it = pointsContainer->Begin(); it != pointsContainer->End(); ++it) { - auto *pointElement = new TiXmlElement(XML_POINT); - timeSeriesElement->LinkEndChild(pointElement); + auto *pointElement = doc.NewElement(XML_POINT.c_str()); + timeSeriesElement->InsertEndChild(pointElement); - auto *pointIDElement = new TiXmlElement(XML_ID); - TiXmlText *pointIDText = new TiXmlText(ConvertToString(it->Index())); - pointIDElement->LinkEndChild(pointIDText); - pointElement->LinkEndChild(pointIDElement); + auto *pointIDElement = doc.NewElement(XML_ID.c_str()); + auto *pointIDText = doc.NewText(ConvertToString(it->Index()).c_str()); + pointIDElement->InsertEndChild(pointIDText); + pointElement->InsertEndChild(pointIDElement); mitk::PointSet::PointType point = it->Value(); - auto *pointSpecElement = new TiXmlElement(XML_SPEC); - TiXmlText *pointSpecText = new TiXmlText(ConvertToString(pointSet->GetSpecificationTypeInfo(it->Index(), i))); - pointSpecElement->LinkEndChild(pointSpecText); - pointElement->LinkEndChild(pointSpecElement); - - auto *pointXElement = new TiXmlElement(XML_X); - TiXmlText *pointXText = new TiXmlText(ConvertToString(point[0])); - pointXElement->LinkEndChild(pointXText); - pointElement->LinkEndChild(pointXElement); - - auto *pointYElement = new TiXmlElement(XML_Y); - TiXmlText *pointYText = new TiXmlText(ConvertToString(point[1])); - pointYElement->LinkEndChild(pointYText); - pointElement->LinkEndChild(pointYElement); - - auto *pointZElement = new TiXmlElement(XML_Z); - TiXmlText *pointZText = new TiXmlText(ConvertToString(point[2])); - pointZElement->LinkEndChild(pointZText); - pointElement->LinkEndChild(pointZElement); + auto *pointSpecElement = doc.NewElement(XML_SPEC.c_str()); + auto *pointSpecText = doc.NewText(ConvertToString(pointSet->GetSpecificationTypeInfo(it->Index(), i)).c_str()); + pointSpecElement->InsertEndChild(pointSpecText); + pointElement->InsertEndChild(pointSpecElement); + + auto *pointXElement = doc.NewElement(XML_X.c_str()); + auto *pointXText = doc.NewText(ConvertToString(point[0]).c_str()); + pointXElement->InsertEndChild(pointXText); + pointElement->InsertEndChild(pointXElement); + + auto *pointYElement = doc.NewElement(XML_Y.c_str()); + auto *pointYText = doc.NewText(ConvertToString(point[1]).c_str()); + pointYElement->InsertEndChild(pointYText); + pointElement->InsertEndChild(pointYElement); + + auto *pointZElement = doc.NewElement(XML_Z.c_str()); + auto *pointZText = doc.NewText(ConvertToString(point[2]).c_str()); + pointZElement->InsertEndChild(pointZText); + pointElement->InsertEndChild(pointZElement); } } return pointSetElement; } template std::string mitk::PointSetWriterService::ConvertToString(T value) { std::ostringstream o; std::locale I("C"); o.imbue(I); if (o << std::setprecision(12) << value) { return o.str(); } else { return "conversion error"; } } diff --git a/Modules/Core/src/IO/mitkPointSetWriterService.h b/Modules/Core/src/IO/mitkPointSetWriterService.h index b9b55d4aef..68aa0e99e7 100644 --- a/Modules/Core/src/IO/mitkPointSetWriterService.h +++ b/Modules/Core/src/IO/mitkPointSetWriterService.h @@ -1,71 +1,75 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_POINT_SET_WRITER_SERVICE__H_ #define _MITK_POINT_SET_WRITER_SERVICE__H_ #include #include -class TiXmlElement; +namespace tinyxml2 +{ + class XMLDocument; + class XMLElement; +} 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(); ~PointSetWriterService() override; using AbstractFileWriter::Write; void Write() override; private: PointSetWriterService(const PointSetWriterService &other); mitk::PointSetWriterService *Clone() const override; template std::string ConvertToString(T value); - TiXmlElement *ToXML(const mitk::PointSet *pointSet); + tinyxml2::XMLElement *ToXML(tinyxml2::XMLDocument &doc, 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 diff --git a/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.cpp b/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.cpp index 6df438ad99..3b42888705 100644 --- a/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.cpp +++ b/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.cpp @@ -1,162 +1,164 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkProportionalTimeGeometryToXML.h" #include "mitkGeometry3DToXML.h" -#include - #include -TiXmlElement *mitk::ProportionalTimeGeometryToXML::ToXML(const ProportionalTimeGeometry *timeGeom) +#include + +tinyxml2::XMLElement *mitk::ProportionalTimeGeometryToXML::ToXML(tinyxml2::XMLDocument& doc, const ProportionalTimeGeometry *timeGeom) { assert(timeGeom); - auto *timeGeomElem = new TiXmlElement("ProportionalTimeGeometry"); - timeGeomElem->SetAttribute("NumberOfTimeSteps", timeGeom->CountTimeSteps()); + auto *timeGeomElem = doc.NewElement("ProportionalTimeGeometry"); + timeGeomElem->SetAttribute("NumberOfTimeSteps", static_cast(timeGeom->CountTimeSteps())); // TinyXML cannot serialize infinity (default value for time step) // So we guard this value and the first time point against serialization problems // by not writing them. The reader can then tell that absence of those values // means "keep the default values" if (timeGeom->GetFirstTimePoint() != -std::numeric_limits::max()) - timeGeomElem->SetAttribute("FirstTimePoint", boost::lexical_cast(timeGeom->GetFirstTimePoint())); + timeGeomElem->SetAttribute("FirstTimePoint", boost::lexical_cast(timeGeom->GetFirstTimePoint()).c_str()); if (timeGeom->GetStepDuration() != std::numeric_limits::infinity()) - timeGeomElem->SetAttribute("StepDuration", boost::lexical_cast(timeGeom->GetStepDuration())); + timeGeomElem->SetAttribute("StepDuration", boost::lexical_cast(timeGeom->GetStepDuration()).c_str()); for (TimeStepType t = 0; t < timeGeom->CountTimeSteps(); ++t) { // add a node for the geometry of each time step const Geometry3D *geom3D(nullptr); if ((geom3D = dynamic_cast(timeGeom->GetGeometryForTimeStep(t).GetPointer()))) { - TiXmlElement *geom3DElement = Geometry3DToXML::ToXML(geom3D); - geom3DElement->SetAttribute("TimeStep", t); // mark order for us - timeGeomElem->LinkEndChild(geom3DElement); + auto *geom3DElement = Geometry3DToXML::ToXML(doc, geom3D); + geom3DElement->SetAttribute("TimeStep", static_cast(t)); // mark order for us + timeGeomElem->InsertEndChild(geom3DElement); } else { MITK_WARN << "Serializing a ProportionalTimeGeometry that contains something other than Geometry3D!" << " (in time step " << t << ")" << " File will miss information!"; } } return timeGeomElem; } -mitk::ProportionalTimeGeometry::Pointer mitk::ProportionalTimeGeometryToXML::FromXML(TiXmlElement *timeGeometryElement) +mitk::ProportionalTimeGeometry::Pointer mitk::ProportionalTimeGeometryToXML::FromXML(const tinyxml2::XMLElement *timeGeometryElement) { if (!timeGeometryElement) { MITK_ERROR << "Cannot deserialize ProportionalTimeGeometry from nullptr."; return nullptr; } int numberOfTimeSteps = 0; - if (TIXML_SUCCESS != timeGeometryElement->QueryIntAttribute("NumberOfTimeSteps", &numberOfTimeSteps)) + if (tinyxml2::XML_SUCCESS != timeGeometryElement->QueryIntAttribute("NumberOfTimeSteps", &numberOfTimeSteps)) { MITK_WARN << " found without NumberOfTimeSteps attribute. Counting..."; } // might be missing! TimePointType firstTimePoint; - std::string firstTimePoint_s; + const char* firstTimePoint_s = nullptr; TimePointType stepDuration; - std::string stepDuration_s; + const char* stepDuration_s = nullptr; try { - if (TIXML_SUCCESS == timeGeometryElement->QueryStringAttribute("FirstTimePoint", &firstTimePoint_s)) + firstTimePoint_s = timeGeometryElement->Attribute("FirstTimePoint"); + if (nullptr != firstTimePoint_s) { firstTimePoint = boost::lexical_cast(firstTimePoint_s); } else { firstTimePoint = -std::numeric_limits::max(); } - if (TIXML_SUCCESS == timeGeometryElement->QueryStringAttribute("StepDuration", &stepDuration_s)) + stepDuration_s = timeGeometryElement->Attribute("StepDuration"); + if (nullptr != stepDuration_s) { stepDuration = boost::lexical_cast(stepDuration_s); } else { stepDuration = std::numeric_limits::infinity(); } } catch ( const boost::bad_lexical_cast &e ) { MITK_ERROR << "Could not parse string as number: " << e.what(); return nullptr; } // list of all geometries with their time steps std::multimap allReadGeometries; int indexForUnlabeledTimeStep(-1); - for (TiXmlElement *currentElement = timeGeometryElement->FirstChildElement(); currentElement != nullptr; + for (auto *currentElement = timeGeometryElement->FirstChildElement(); currentElement != nullptr; currentElement = currentElement->NextSiblingElement()) { // different geometries could have been inside a ProportionalTimeGeometry. // By now, we only support Geometry3D std::string tagName = currentElement->Value(); if (tagName == "Geometry3D") { Geometry3D::Pointer restoredGeometry = Geometry3DToXML::FromXML(currentElement); if (restoredGeometry.IsNotNull()) { int timeStep(-1); - if (TIXML_SUCCESS != currentElement->QueryIntAttribute("TimeStep", &timeStep)) + if (tinyxml2::XML_SUCCESS != currentElement->QueryIntAttribute("TimeStep", &timeStep)) { timeStep = indexForUnlabeledTimeStep--; // decrement index for next one MITK_WARN << "Found without 'TimeStep' attribute in . No guarantees " "on order anymore."; } if (allReadGeometries.count(static_cast(timeStep)) > 0) { MITK_WARN << "Found tags with identical 'TimeStep' attribute in . No " "guarantees on order anymore."; } allReadGeometries.insert(std::make_pair(static_cast(timeStep), restoredGeometry.GetPointer())); } } else { MITK_WARN << "Found unsupported tag <" << tagName << "> inside . Ignoring."; } } // now add all BaseGeometries that were read to a new instance // of ProportionalTimeGeometry ProportionalTimeGeometry::Pointer newTimeGeometry = ProportionalTimeGeometry::New(); newTimeGeometry->SetFirstTimePoint(firstTimePoint); newTimeGeometry->SetStepDuration(stepDuration); newTimeGeometry->ReserveSpaceForGeometries(allReadGeometries.size()); TimeStepType t(0); for (auto entry : allReadGeometries) { // We add items with newly assigned time steps. // This avoids great confusion when a file contains // bogus numbers. newTimeGeometry->SetTimeStepGeometry(entry.second, t++); } // Need to re-calculate global bounding box. // This is neither stored in a file, nor done by SetTimeStepGeometry newTimeGeometry->UpdateBoundingBox(); return newTimeGeometry; } diff --git a/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.h b/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.h index 5091a9a482..5ccd053619 100644 --- a/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.h +++ b/Modules/Core/src/IO/mitkProportionalTimeGeometryToXML.h @@ -1,51 +1,54 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkProportionalTimeGeometryToXML_h #define mitkProportionalTimeGeometryToXML_h -// MITK #include "mitkProportionalTimeGeometry.h" -class TiXmlElement; +namespace tinyxml2 +{ + class XMLDocument; + class XMLElement; +} namespace mitk { /** * @internal * * @brief Helper for ProportionalTimeGeometry related I/O classes. * * Creates TinyXML elements (blocks) that describe a ProportionalTimeGeometry. * Also offers a method to read such blocks and create a corresponding ProportionalTimeGeometry. * * @sa GeometryDataWriterService, GeometryDataReaderService, Geometry3DToXML * * @ingroup IO */ class ProportionalTimeGeometryToXML { public: /** * @brief Serialize given geometry to XML. */ - static TiXmlElement *ToXML(const ProportionalTimeGeometry *geometry); + static tinyxml2::XMLElement *ToXML(tinyxml2::XMLDocument& doc, const ProportionalTimeGeometry *geometry); /** * @brief Create a ProportionalTimeGeometry from XML. * Interprets only the format created by ToXML(). */ - static ProportionalTimeGeometry::Pointer FromXML(TiXmlElement *node); + static ProportionalTimeGeometry::Pointer FromXML(const tinyxml2::XMLElement *node); }; } #endif diff --git a/Modules/Core/test/CMakeLists.txt b/Modules/Core/test/CMakeLists.txt index d3d3321aed..c1758a4f44 100644 --- a/Modules/Core/test/CMakeLists.txt +++ b/Modules/Core/test/CMakeLists.txt @@ -1,181 +1,181 @@ # The core tests need relaxed compiler flags... # TODO fix core tests to compile without these additional no-error flags if(MSVC_VERSION) # disable deprecated warnings (they would lead to errors) mitkFunctionCheckCAndCXXCompilerFlags("/wd4996" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=deprecated-declarations" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() MITK_CREATE_MODULE_TESTS() if(TARGET ${TESTDRIVER}) - mitk_use_modules(TARGET ${TESTDRIVER} PACKAGES ITK|ITKThresholding+ITKTestKernel VTK|TestingRendering tinyxml) + mitk_use_modules(TARGET ${TESTDRIVER} PACKAGES ITK|ITKThresholding+ITKTestKernel VTK|TestingRendering tinyxml2|tinyxml2) mitkAddCustomModuleTest(mitkVolumeCalculatorTest_Png2D-bw mitkVolumeCalculatorTest ${MITK_DATA_DIR}/Png2D-bw.png ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkEventConfigTest_CreateObjectInDifferentWays mitkEventConfigTest ${MITK_SOURCE_DIR}/Modules/Core/test/resource/Interactions/StatemachineConfigTest.xml ) mitkAddCustomModuleTest(mitkDataStorageTest_US4DCyl mitkDataStorageTest ${MITK_DATA_DIR}/US4DCyl.nrrd ) mitkAddCustomModuleTest(mitkPointSetReaderTest mitkPointSetReaderTest ${MITK_DATA_DIR}/PointSetReaderTestData.mps ) mitkAddCustomModuleTest(mitkImageTest_4DImageData mitkImageTest ${MITK_DATA_DIR}/US4DCyl.nrrd ) mitkAddCustomModuleTest(mitkImageTest_2D+tImageData mitkImageTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkImageTest_3DImageData mitkImageTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkImageEqualTest mitkImageEqualTest) mitkAddCustomModuleTest(mitkImageTest_brainImage mitkImageTest ${MITK_DATA_DIR}/brain.mhd ) mitkAddCustomModuleTest(mitkLevelWindowManagerTest mitkLevelWindowManagerTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkMultiComponentImageDataComparisonFilterTest mitkMultiComponentImageDataComparisonFilterTest ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg ) mitkAddCustomModuleTest(mitkImageToItkTest mitkImageToItkTest ${MITK_DATA_DIR}/Pic3D.nrrd ) mitkAddCustomModuleTest(mitkImageSliceSelectorTest mitkImageSliceSelectorTest ${MITK_DATA_DIR}/Pic2DplusT.nrrd ) mitkAddCustomModuleTest(mitkRotatedSlice4DTest mitkRotatedSlice4DTest ${MITK_DATA_DIR}/UltrasoundImages/4D_TEE_Data_MV.dcm ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_rgbaImage640x480 mitkImageVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/rgbaImage.png #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/rgbaImage640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_pic3d640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3d640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_pic3dColorBlue640x480 mitkImageVtkMapper2DColorTest #test for color property (=blue) Pic3D sagittal slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dColorBlue640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_pic3dLevelWindow640x480 mitkImageVtkMapper2DLevelWindowTest #test for levelwindow property (=blood) #Pic3D sagittal slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dLevelWindowBlood640x480REF.png #corresponding reference #screenshot ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_pic3dSwivel640x480 mitkImageVtkMapper2DSwivelTest #test for a randomly chosen Pic3D swivelled slice ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dSwivel640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkPointSetVtkMapper2D_openMeAlone640x480 mitkPointSetVtkMapper2DTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAlone640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkPointSetVtkMapper2D_Pic3DPointSetForPic3D640x480 mitkPointSetVtkMapper2DImageTest ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/RenderingTestData/PointSetForPic3D.mps #input point set and image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Pic3DPointSetForPic3D640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkPointSetVtkMapper2D_openMeAloneGlyphType640x480 mitkPointSetVtkMapper2DGlyphTypeTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAloneGlyphType640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkPointSetVtkMapper2D_openMeAloneTransformed640x480 mitkPointSetVtkMapper2DTransformedPointsTest ${MITK_DATA_DIR}/RenderingTestData/openMeAlone.mps #input point set to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/openMeAloneTransformedPoints640x480REF.png #corresponding reference screenshot ) # Currently not working on windows because of a rendering timing issue # see bug 18083 for details if(NOT WIN32) mitkAddCustomModuleRenderingTest(mitkSurfaceDepthSortingTransparency_StanfordBunnySTL640x480 mitkSurfaceDepthSortingTest ${MITK_DATA_DIR}/RenderingTestData/Stanford_bunny.stl -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Stanford_bunnySTLDepthSorting640x480REF.png) endif() # BUG 18695 - tests deactivated, because win 32 bit continuous renders images slightly different. TODO! #Test reslice interpolation #note: nearest mode is already tested by swivel test #mitkAddCustomModuleRenderingTest(ResliceInterpolationIsLinear mitkImageVtkMapper2DResliceInterpolationPropertyTest # 1 #linear # ${MITK_DATA_DIR}/Pic3D.nrrd # -V # ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dRefLinear.png #corresponding reference screenshot LINEAR #) #mitkAddCustomModuleRenderingTest(ResliceInterpolationIsCubic mitkImageVtkMapper2DResliceInterpolationPropertyTest # 3 #cubic # ${MITK_DATA_DIR}/Pic3D.nrrd # -V # ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/pic3dRefCubic.png #corresponding reference screenshot CUBIC #) #End test reslice interpolation # Testing of the rendering of binary images #mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_binaryTestImage640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice # ${MITK_DATA_DIR}/RenderingTestData/binaryImage.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryImage640x480REF.png #corresponding reference screenshot #) #mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2D_binaryTestImageWithRef640x480 mitkImageVtkMapper2DTest #test for standard Pic3D axial slice # ${MITK_DATA_DIR}/Pic3D.nrrd ${MITK_DATA_DIR}/RenderingTestData/binaryImage.nrrd #input image to load in data storage # -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/binaryImageWithRef640x480REF.png #corresponding reference screenshot #) # End of binary image tests mitkAddCustomModuleRenderingTest(mitkSurfaceVtkMapper3DTest_TextureProperty mitkSurfaceVtkMapper3DTest ${MITK_DATA_DIR}/RenderingTestData/earth.jpg -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/texturedSphere640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2DTransferFunctionTest_Png2D-bw mitkImageVtkMapper2DTransferFunctionTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-TransferFunctionRGBImage640x480REF.png #corresponding reference screenshot ) mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2DOpacityTransferFunctionTest_Png2D-bw mitkImageVtkMapper2DOpacityTransferFunctionTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-OpacityTransferFunctionRGBImage640x480REF.png #corresponding reference screenshot ) ############################## DISABLED TESTS mitkAddCustomModuleRenderingTest(mitkImageVtkMapper2DLookupTableTest_Png2D-bw mitkImageVtkMapper2DLookupTableTest ${MITK_DATA_DIR}/Png2D-bw.png -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/Png2D-bw-LookupTableRGBImage640x480REF.png #corresponding reference screenshot ) #mitkAddCustomModuleRenderingTest(mitkImageTest_color2DImage mitkImageTest # ${MITK_DATA_DIR}/NrrdWritingTestImage.jpg #) #mitkAddCustomModuleRenderingTest(mitkNodeDependentPointSetInteractorTest mitkNodeDependentPointSetInteractorTest # ${MITK_DATA_DIR}/Pic3D.pic.gz ${MITK_DATA_DIR}/BallBinary30x30x30.pic.gz #) mitkAddCustomModuleRenderingTest(mitkPlaneGeometryDataMapper2DTest mitkPlaneGeometryDataMapper2DTest ${MITK_DATA_DIR}/Pic3D.nrrd #input image to load in data storage -V ${MITK_DATA_DIR}/RenderingTestData/ReferenceScreenshots/PlaneGeometryMapper640x480REF.png #corresponding reference screenshot ) endif() # TARGET ${TESTDRIVER} diff --git a/Modules/Core/test/mitkTinyXMLTest.cpp b/Modules/Core/test/mitkTinyXMLTest.cpp index ddd251e473..392ab4384d 100644 --- a/Modules/Core/test/mitkTinyXMLTest.cpp +++ b/Modules/Core/test/mitkTinyXMLTest.cpp @@ -1,159 +1,162 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Testing #include "mitkTestFixture.h" #include // std includes #include #include -#include +#include // MITK includes #include "mitkStringProperty.h" #include // itksys #include // VTK includes #include // vnl includes #include class mitkTinyXMLTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkTinyXMLTestSuite); MITK_TEST(TestingFunctionSetupWorks_Success); MITK_TEST(TestingReadValueFromSetupDocument_Success); MITK_TEST(TestingReadOutValueWorks_Success); MITK_TEST(TestDoubleValueWriteOut_Success); MITK_TEST(TestDoubleValueWriteOutManyDecimalPlaces_Success); CPPUNIT_TEST_SUITE_END(); private: const std::string m_Filename = itksys::SystemTools::GetCurrentWorkingDirectory() + "/TinyXMLTest.txt"; const std::string m_ElementToStoreAttributeName = "DoubleTest"; const std::string m_AttributeToStoreName = "CommaValue"; - TiXmlDocument m_Document; - TiXmlElement *m_DoubleTest; + tinyxml2::XMLDocument m_Document; + tinyxml2::XMLElement *m_DoubleTest; double calcPrecision(const unsigned int requiredDecimalPlaces) { return pow(10.0, -1.0 * ((double)requiredDecimalPlaces)); } bool Setup(double valueToWrite) { + m_Document.Clear(); + m_DoubleTest = nullptr; + // 1. create simple document - auto decl = new TiXmlDeclaration("1.0", "", ""); // TODO what to write here? encoding? etc.... - m_Document.LinkEndChild(decl); + m_Document.InsertEndChild(m_Document.NewDeclaration()); - auto version = new TiXmlElement("Version"); + auto *version = m_Document.NewElement("Version"); version->SetAttribute("Writer", __FILE__); version->SetAttribute("CVSRevision", "$Revision: 17055 $"); version->SetAttribute("FileVersion", 1); - m_Document.LinkEndChild(version); + m_Document.InsertEndChild(version); // 2. store one element containing a double value with potentially many after comma digits. - auto vElement = new TiXmlElement(m_ElementToStoreAttributeName); - vElement->SetDoubleAttribute(m_AttributeToStoreName, valueToWrite); - m_Document.LinkEndChild(vElement); + auto *vElement = m_Document.NewElement(m_ElementToStoreAttributeName.c_str()); + vElement->SetAttribute(m_AttributeToStoreName.c_str(), valueToWrite); + m_Document.InsertEndChild(vElement); // 3. store in file. - return m_Document.SaveFile(m_Filename); + auto err = m_Document.SaveFile(m_Filename.c_str()); + return tinyxml2::XML_SUCCESS == err; } public: void setUp() override {} void tearDown() override {} void TestingFunctionSetupWorks_Success() { CPPUNIT_ASSERT_MESSAGE("Test if Setup correctly writes data to file", Setup(1.0)); } int readValueFromSetupDocument(double &readOutValue) { - if (!m_Document.LoadFile(m_Filename)) + if (tinyxml2::XML_SUCCESS != m_Document.LoadFile(m_Filename.c_str())) { CPPUNIT_ASSERT_MESSAGE("Test Setup failed, could not open file", false); - return TIXML_NO_ATTRIBUTE; + return tinyxml2::XML_NO_ATTRIBUTE; } else { - m_DoubleTest = m_Document.FirstChildElement(m_ElementToStoreAttributeName); - return m_DoubleTest->QueryDoubleAttribute(m_AttributeToStoreName, &readOutValue); + m_DoubleTest = m_Document.FirstChildElement(m_ElementToStoreAttributeName.c_str()); + return m_DoubleTest->QueryDoubleAttribute(m_AttributeToStoreName.c_str(), &readOutValue); } } void TestingReadValueFromSetupDocument_Success() { - if (!m_Document.LoadFile(m_Filename)) + if (tinyxml2::XML_SUCCESS != m_Document.LoadFile(m_Filename.c_str())) { - CPPUNIT_ASSERT_MESSAGE("Test Setup failed, could not open file", !m_Document.LoadFile(m_Filename)); + CPPUNIT_ASSERT_MESSAGE("Test Setup failed, could not open file", tinyxml2::XML_SUCCESS != m_Document.LoadFile(m_Filename.c_str())); } else { - m_DoubleTest = m_Document.FirstChildElement(m_ElementToStoreAttributeName); + m_DoubleTest = m_Document.FirstChildElement(m_ElementToStoreAttributeName.c_str()); CPPUNIT_ASSERT_MESSAGE("Test Setup could open file", m_DoubleTest != nullptr); } } /** * this first test ensures we can correctly readout values from the * TinyXMLDocument. */ void TestingReadOutValueWorks_Success() { double readValue; CPPUNIT_ASSERT_MESSAGE("checking if readout mechanism works.", - TIXML_SUCCESS == readValueFromSetupDocument(readValue)); + tinyxml2::XML_SUCCESS == readValueFromSetupDocument(readValue)); } void TestDoubleValueWriteOut_Success() { const double valueToWrite = -1.123456; const int validDigitsAfterComma = 6; // indicates the number of valid digits after comma of valueToWrite const double neededPrecision = calcPrecision(validDigitsAfterComma + 1); double readValue; Setup(valueToWrite); readValueFromSetupDocument(readValue); CPPUNIT_ASSERT_MESSAGE("Testing if value valueToWrite equals readValue which was retrieved from TinyXML document", mitk::Equal(valueToWrite, readValue, neededPrecision)); } void TestDoubleValueWriteOutManyDecimalPlaces_Success() { const double valueToWrite = -1.12345678910111; const int validDigitsAfterComma = 14; // indicates the number of valid digits after comma of valueToWrite const double neededPrecision = calcPrecision(validDigitsAfterComma + 1); double readValue; Setup(valueToWrite); readValueFromSetupDocument(readValue); CPPUNIT_ASSERT_MESSAGE("Testing if value valueToWrite equals readValue which was retrieved from TinyXML document", mitk::Equal(valueToWrite, readValue, neededPrecision)); } }; MITK_TEST_SUITE_REGISTRATION(mitkTinyXML) diff --git a/Modules/DICOM/CMakeLists.txt b/Modules/DICOM/CMakeLists.txt index 98d7de357c..2bedc88018 100644 --- a/Modules/DICOM/CMakeLists.txt +++ b/Modules/DICOM/CMakeLists.txt @@ -1,9 +1,15 @@ MITK_CREATE_MODULE( DEPENDS MitkCore PACKAGE_DEPENDS - PUBLIC tinyxml GDCM + PUBLIC tinyxml2|tinyxml2 GDCM PRIVATE ITK|ITKIOImageBase+ITKIOGDCM DCMTK ) +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} + PUBLIC tinyxml2::tinyxml2 + ) +endif() + add_subdirectory(test) add_subdirectory(autoload/DICOMImageIO) diff --git a/Modules/DICOM/include/mitkDICOMReaderConfigurator.h b/Modules/DICOM/include/mitkDICOMReaderConfigurator.h index e098ee4b85..00da6131c2 100644 --- a/Modules/DICOM/include/mitkDICOMReaderConfigurator.h +++ b/Modules/DICOM/include/mitkDICOMReaderConfigurator.h @@ -1,142 +1,145 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkDICOMReaderConfigurator_h #define mitkDICOMReaderConfigurator_h #include "mitkClassicDICOMSeriesReader.h" #include "mitkDICOMTagBasedSorter.h" -// to put into private implementation -#include "tinyxml.h" +namespace tinyxml2 +{ + class XMLDocument; + class XMLElement; +} namespace mitk { /** \ingroup DICOMModule \brief Too-simple factory to create DICOMFileReader%s. This class is able to instantiate and configure (where possible) DICOMFileReader%s from XML descriptions. \note This is a bad factory example, because the factory is not extensible and needs to know all the specific readers. A flexible implementation should be provided in a future version. In its current version, the XML input is meant to be structured like \verbatim \endverbatim The root-tag \c \ names the class to be instantiated, currently this can be one of - DICOMITKSeriesGDCMReader - ThreeDnTDICOMSeriesReader Both classes bring simple configuration flags with them and a description of how images are sorted prior to loading. Flag for DICOMITKSeriesGDCMReader:
fixTiltByShearing="true|false"
Determines whether a potential gantry tilt should be "fixed" by shearing the output image. Flag for ThreeDnTDICOMSeriesReader:
group3DnT="true|false"
Determines whether images at the same spatial position should be interpreted as 3D+t images. The tags \c \ and \c \ describe the basic loading strategy of both reader mentioned above: first images are divided into incompatible groups (\c \), and afterwards the images within each group are sorted by means of DICOMSortCriterion, which most commonly mentions a tag. Tag element and group are interpreted as the exadecimal numbers found all around the DICOM standard. The numbers can be prepended by a "0x" if this is preferred by the programmer (but they are taken as hexadecimal in all cases). \section DICOMReaderConfigurator_AboutTheFuture About the future evolution of this class This first version is hard coded for the current state of the implementation. If things should evolve in a way that needs us to splitt off readers for "old" versions, time should be taken to refactor this class. Basically, a serializer class should accompany each of the configurable classes. Such serializer classes should be registered and discovered via micro-services (to support extensions). A serializer should offer both methods to serialize a class and to desirialize it again. A "version" attribute at the top-level tag should be used to distinguish versions. Usually it should be enough to keep DE-serializers for all versions. Writers for the most recent version should be enough. */ class MITKDICOM_EXPORT DICOMReaderConfigurator : public itk::LightObject { public: mitkClassMacroItkParent( DICOMReaderConfigurator, itk::LightObject ); itkNewMacro( DICOMReaderConfigurator ); DICOMFileReader::Pointer CreateFromConfigFile(const std::string& filename) const; DICOMFileReader::Pointer CreateFromUTF8ConfigString(const std::string& xmlContents) const; std::string CreateConfigStringFromReader(DICOMFileReader::ConstPointer reader) const; protected: DICOMReaderConfigurator(); ~DICOMReaderConfigurator() override; private: - DICOMFileReader::Pointer CreateFromTiXmlDocument(TiXmlDocument& doc) const; - DICOMTag tagFromXMLElement(TiXmlElement*) const; - std::string requiredStringAttribute(TiXmlElement* xmlElement, const std::string& key) const; + DICOMFileReader::Pointer CreateFromXMLDocument(tinyxml2::XMLDocument& doc) const; + DICOMTag tagFromXMLElement(const tinyxml2::XMLElement*) const; + std::string requiredStringAttribute(const tinyxml2::XMLElement* xmlElement, const std::string& key) const; unsigned int hexStringToUInt(const std::string& s) const; - ThreeDnTDICOMSeriesReader::Pointer ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement*) const; - DICOMITKSeriesGDCMReader::Pointer ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement*) const; - void ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const; - void ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const; + ThreeDnTDICOMSeriesReader::Pointer ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, const tinyxml2::XMLElement*) const; + DICOMITKSeriesGDCMReader::Pointer ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, const tinyxml2::XMLElement*) const; + void ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, const tinyxml2::XMLElement* element) const; + void ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, const tinyxml2::XMLElement* element) const; + + DICOMSortCriterion::Pointer CreateDICOMSortByTag(const tinyxml2::XMLElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const; + DICOMSortCriterion::Pointer CreateSortByImagePositionPatient(const tinyxml2::XMLElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const; - DICOMSortCriterion::Pointer CreateDICOMSortByTag(TiXmlElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const; - DICOMSortCriterion::Pointer CreateSortByImagePositionPatient(TiXmlElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const; + mitk::DICOMTagBasedSorter::Pointer CreateDICOMTagBasedSorter(const tinyxml2::XMLElement* element) const; - mitk::DICOMTagBasedSorter::Pointer CreateDICOMTagBasedSorter(TiXmlElement* element) const; + tinyxml2::XMLElement* CreateConfigStringFromReader(tinyxml2::XMLDocument& doc, const DICOMITKSeriesGDCMReader* reader) const; + tinyxml2::XMLElement* CreateConfigStringFromReader(tinyxml2::XMLDocument& doc, const ThreeDnTDICOMSeriesReader* reader) const; + tinyxml2::XMLElement* CreateConfigStringFromReader(tinyxml2::XMLDocument& doc, const ClassicDICOMSeriesReader* reader) const; - TiXmlElement* CreateConfigStringFromReader(const DICOMITKSeriesGDCMReader* reader) const; - TiXmlElement* CreateConfigStringFromReader(const ThreeDnTDICOMSeriesReader* reader) const; - TiXmlElement* CreateConfigStringFromReader(const ClassicDICOMSeriesReader* reader) const; + tinyxml2::XMLElement* CreateConfigStringFromDICOMDatasetSorter(tinyxml2::XMLDocument& doc, const DICOMTagBasedSorter* sorter) const; - TiXmlElement* CreateConfigStringFromDICOMDatasetSorter(const DICOMTagBasedSorter* sorter) const; + tinyxml2::XMLElement* CreateConfigStringFromDICOMTag(tinyxml2::XMLDocument& doc, const DICOMTag& tag) const; - TiXmlElement* CreateConfigStringFromDICOMTag(const DICOMTag& tag) const; + tinyxml2::XMLElement* CreateDICOMFileReaderTag(tinyxml2::XMLDocument& doc, const DICOMFileReader* reader) const; - TiXmlElement* CreateDICOMFileReaderTag(const DICOMFileReader* reader) const; - const char* toString(bool) const; std::string toHexString(unsigned int i) const; /** Helper that queries an boolean xml attribute. If the attribute does not exist, the passed default value is used.*/ - bool QueryBooleanAttribute(const TiXmlElement* element, const char* attributeName, bool defaultValue) const; + bool QueryBooleanAttribute(const tinyxml2::XMLElement* element, const char* attributeName, bool defaultValue) const; }; } // namespace #endif // mitkDICOMReaderConfigurator_h diff --git a/Modules/DICOM/resource/configurations/3D/classicreader.xml b/Modules/DICOM/resource/configurations/3D/classicreader.xml index 7ed3332f6a..e5e063d39c 100644 --- a/Modules/DICOM/resource/configurations/3D/classicreader.xml +++ b/Modules/DICOM/resource/configurations/3D/classicreader.xml @@ -1,10 +1,10 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/imageposition.xml b/Modules/DICOM/resource/configurations/3D/imageposition.xml index c00d4cd8e2..09b55d3ecf 100644 --- a/Modules/DICOM/resource/configurations/3D/imageposition.xml +++ b/Modules/DICOM/resource/configurations/3D/imageposition.xml @@ -1,25 +1,25 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/imageposition_byacquisition.xml b/Modules/DICOM/resource/configurations/3D/imageposition_byacquisition.xml index 54b9f6377a..d145528099 100644 --- a/Modules/DICOM/resource/configurations/3D/imageposition_byacquisition.xml +++ b/Modules/DICOM/resource/configurations/3D/imageposition_byacquisition.xml @@ -1,26 +1,26 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/imagetime.xml b/Modules/DICOM/resource/configurations/3D/imagetime.xml index 83cdb1c1b0..62e97e455f 100644 --- a/Modules/DICOM/resource/configurations/3D/imagetime.xml +++ b/Modules/DICOM/resource/configurations/3D/imagetime.xml @@ -1,24 +1,24 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/instancenumber.xml b/Modules/DICOM/resource/configurations/3D/instancenumber.xml index f83b56e3c8..1fd86e4db6 100644 --- a/Modules/DICOM/resource/configurations/3D/instancenumber.xml +++ b/Modules/DICOM/resource/configurations/3D/instancenumber.xml @@ -1,24 +1,24 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/instancenumber_soft.xml b/Modules/DICOM/resource/configurations/3D/instancenumber_soft.xml index 1c2c660700..9cf61cbfcf 100644 --- a/Modules/DICOM/resource/configurations/3D/instancenumber_soft.xml +++ b/Modules/DICOM/resource/configurations/3D/instancenumber_soft.xml @@ -1,24 +1,24 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/simpleinstancenumber_soft.xml b/Modules/DICOM/resource/configurations/3D/simpleinstancenumber_soft.xml index 79c636e78b..eba6bbef60 100644 --- a/Modules/DICOM/resource/configurations/3D/simpleinstancenumber_soft.xml +++ b/Modules/DICOM/resource/configurations/3D/simpleinstancenumber_soft.xml @@ -1,25 +1,25 @@ - + diff --git a/Modules/DICOM/resource/configurations/3D/slicelocation.xml b/Modules/DICOM/resource/configurations/3D/slicelocation.xml index 967bb5af57..7ddb18d2f1 100644 --- a/Modules/DICOM/resource/configurations/3D/slicelocation.xml +++ b/Modules/DICOM/resource/configurations/3D/slicelocation.xml @@ -1,24 +1,24 @@ - + diff --git a/Modules/DICOM/resource/configurations/3DnT/classicreader.xml b/Modules/DICOM/resource/configurations/3DnT/classicreader.xml index 1a0ca7f09a..6d40321c7f 100644 --- a/Modules/DICOM/resource/configurations/3DnT/classicreader.xml +++ b/Modules/DICOM/resource/configurations/3DnT/classicreader.xml @@ -1,11 +1,11 @@ - + - \ No newline at end of file + diff --git a/Modules/DICOM/resource/configurations/3DnT/imageposition.xml b/Modules/DICOM/resource/configurations/3DnT/imageposition.xml index f8e1601952..a44d46cfc9 100644 --- a/Modules/DICOM/resource/configurations/3DnT/imageposition.xml +++ b/Modules/DICOM/resource/configurations/3DnT/imageposition.xml @@ -1,21 +1,21 @@ - + diff --git a/Modules/DICOM/resource/configurations/3DnT/imageposition_byacquisition.xml b/Modules/DICOM/resource/configurations/3DnT/imageposition_byacquisition.xml index 1a356abfb1..d6815044b6 100644 --- a/Modules/DICOM/resource/configurations/3DnT/imageposition_byacquisition.xml +++ b/Modules/DICOM/resource/configurations/3DnT/imageposition_byacquisition.xml @@ -1,19 +1,19 @@ - + - \ No newline at end of file + diff --git a/Modules/DICOM/resource/configurations/3DnT/imageposition_bytriggertime.xml b/Modules/DICOM/resource/configurations/3DnT/imageposition_bytriggertime.xml index f8f636255c..1a3f39fae4 100644 --- a/Modules/DICOM/resource/configurations/3DnT/imageposition_bytriggertime.xml +++ b/Modules/DICOM/resource/configurations/3DnT/imageposition_bytriggertime.xml @@ -1,19 +1,19 @@ - + - \ No newline at end of file + diff --git a/Modules/DICOM/src/mitkDICOMReaderConfigurator.cpp b/Modules/DICOM/src/mitkDICOMReaderConfigurator.cpp index 87e64e6c1c..68f7a4dccb 100644 --- a/Modules/DICOM/src/mitkDICOMReaderConfigurator.cpp +++ b/Modules/DICOM/src/mitkDICOMReaderConfigurator.cpp @@ -1,678 +1,673 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkDICOMReaderConfigurator.h" #include "mitkDICOMSortByTag.h" #include "mitkSortByImagePositionPatient.h" +#include mitk::DICOMReaderConfigurator ::DICOMReaderConfigurator() { } mitk::DICOMReaderConfigurator ::~DICOMReaderConfigurator() { } mitk::DICOMFileReader::Pointer mitk::DICOMReaderConfigurator ::CreateFromConfigFile(const std::string& filename) const { - TiXmlDocument doc (filename); - if (doc.LoadFile()) + tinyxml2::XMLDocument doc; + if (tinyxml2::XML_SUCCESS == doc.LoadFile(filename.c_str())) { - return this->CreateFromTiXmlDocument( doc ); + return this->CreateFromXMLDocument( doc ); } else { MITK_ERROR << "Unable to load file at '" << filename <<"'"; return DICOMFileReader::Pointer(); } } mitk::DICOMFileReader::Pointer mitk::DICOMReaderConfigurator ::CreateFromUTF8ConfigString(const std::string& xmlContents) const { - TiXmlDocument doc; - doc.Parse(xmlContents.c_str(), nullptr, TIXML_ENCODING_UTF8); + tinyxml2::XMLDocument doc; + doc.Parse(xmlContents.c_str()); - return this->CreateFromTiXmlDocument( doc ); + return this->CreateFromXMLDocument( doc ); } mitk::DICOMFileReader::Pointer mitk::DICOMReaderConfigurator -::CreateFromTiXmlDocument(TiXmlDocument& doc) const +::CreateFromXMLDocument(tinyxml2::XMLDocument& doc) const { - TiXmlHandle root(doc.RootElement()); + tinyxml2::XMLHandle root(doc.RootElement()); - if (TiXmlElement* rootElement = root.ToElement()) + if (auto* rootElement = root.ToElement()) { if (strcmp(rootElement->Value(), "DICOMFileReader")) // :-( no std::string methods { MITK_ERROR << "File should contain a tag at top-level! Found '" << (rootElement->Value() ? std::string(rootElement->Value()) : std::string("!nothing!")) << "' instead"; return nullptr; } const char* classnameC = rootElement->Attribute("class"); if (!classnameC) { MITK_ERROR << "File should name a reader class in the class attribute: . Found nothing instead"; return nullptr; } int version(1); - if ( rootElement->QueryIntAttribute("version", &version) == TIXML_SUCCESS) + if ( rootElement->QueryIntAttribute("version", &version) == tinyxml2::XML_SUCCESS) { if (version == 1) { MITK_WARN << "Warning the given configuration is for DICOMFileReaders of version 1. " << "This old version may be interpreted differently. Reason: " << "The default values for the following xml settings have been changed: " << "FixTiltByShearing (false -> true); StrictSorting (true -> false); ExpectDistanceOne (true -> false)."; } else if (version >2) { MITK_WARN << "This reader is only capable of creating DICOMFileReaders of version 1 and 2. " << "Will not continue, because given configuration is meant for version " << version << "."; return nullptr; } } else { MITK_ERROR << "File should name the version of the reader class in the version attribute: ." << " Found nothing instead, assuming version 1!"; version = 1; } std::string classname(classnameC); double decimalPlacesForOrientation(mitk::DICOMITKSeriesGDCMReader::GetDefaultDecimalPlacesForOrientation()); bool useDecimalPlacesForOrientation(false); useDecimalPlacesForOrientation = - rootElement->QueryDoubleAttribute("decimalPlacesForOrientation", &decimalPlacesForOrientation) == TIXML_SUCCESS; // attribute present and a double value + rootElement->QueryDoubleAttribute("decimalPlacesForOrientation", &decimalPlacesForOrientation) == tinyxml2::XML_SUCCESS; // attribute present and a double value if (classname == "ClassicDICOMSeriesReader") { mitk::ClassicDICOMSeriesReader::Pointer reader = mitk::ClassicDICOMSeriesReader::New(); this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader.GetPointer(), rootElement); this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader.GetPointer(), rootElement); return reader.GetPointer(); } if (classname == "ThreeDnTDICOMSeriesReader") { mitk::ThreeDnTDICOMSeriesReader::Pointer reader; if (useDecimalPlacesForOrientation) reader = mitk::ThreeDnTDICOMSeriesReader::New(decimalPlacesForOrientation); else reader = mitk::ThreeDnTDICOMSeriesReader::New(); return ConfigureThreeDnTDICOMSeriesReader(reader, rootElement).GetPointer(); } else if (classname == "DICOMITKSeriesGDCMReader") { bool simpleVolumeImport = QueryBooleanAttribute(rootElement, "simpleVolumeImport", mitk::DICOMITKSeriesGDCMReader::GetDefaultSimpleVolumeImport()); mitk::DICOMITKSeriesGDCMReader::Pointer reader; if (useDecimalPlacesForOrientation) reader = mitk::DICOMITKSeriesGDCMReader::New( decimalPlacesForOrientation, simpleVolumeImport ); else reader = mitk::DICOMITKSeriesGDCMReader::New( mitk::DICOMITKSeriesGDCMReader::GetDefaultDecimalPlacesForOrientation(), simpleVolumeImport ); // simple volume import that ignores number of frames and inter slice distance return ConfigureDICOMITKSeriesGDCMReader(reader, rootElement).GetPointer(); } else { MITK_ERROR << "DICOMFileReader tag names unknown class '" << classname << "'"; return nullptr; } } else { MITK_ERROR << "Great confusion: no root element in XML document. Expecting a DICOMFileReader tag at top-level."; return nullptr; } } #define boolStringTrue(s) \ ( s == "true" || s == "on" || s == "1" \ || s == "TRUE" || s == "ON") bool mitk::DICOMReaderConfigurator -::QueryBooleanAttribute(const TiXmlElement* element, const char* attributeName, bool defaultValue) const +::QueryBooleanAttribute(const tinyxml2::XMLElement* element, const char* attributeName, bool defaultValue) const { bool value(defaultValue); - const char* valueC = element->Attribute(attributeName); - if (valueC) + const auto* valueC = element->Attribute(attributeName); + + if (nullptr != valueC) { - std::string valueS(valueC); + std::string valueS = valueC; value = boolStringTrue(valueS); } + return value; } void mitk::DICOMReaderConfigurator -::ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const +::ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, const tinyxml2::XMLElement* element) const { // add the "group3DnT" flag bool group3DnT = QueryBooleanAttribute(element, "group3DnT", ThreeDnTDICOMSeriesReader::GetDefaultGroup3DandT()); reader->SetGroup3DandT( group3DnT ); // add the "onlyCondenseSameSeries" flag bool onlyCondenseSameSeries = QueryBooleanAttribute(element, "onlyCondenseSameSeries", ThreeDnTDICOMSeriesReader::GetDefaultOnlyCondenseSameSeries()); reader->SetOnlyCondenseSameSeries(onlyCondenseSameSeries); } mitk::ThreeDnTDICOMSeriesReader::Pointer mitk::DICOMReaderConfigurator -::ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, TiXmlElement* element) const +::ConfigureThreeDnTDICOMSeriesReader(ThreeDnTDICOMSeriesReader::Pointer reader, const tinyxml2::XMLElement* element) const { assert(element); // use all the base class configuration if (this->ConfigureDICOMITKSeriesGDCMReader( reader.GetPointer(), element ).IsNull()) { return nullptr; } this->ConfigureCommonPropertiesOfThreeDnTDICOMSeriesReader(reader,element); return reader; } void mitk::DICOMReaderConfigurator -::ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const +::ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, const tinyxml2::XMLElement* element) const { assert(element); const char* configLabelC = element->Attribute("label"); if (configLabelC) { std::string configLabel(configLabelC); reader->SetConfigurationLabel(configLabel); } const char* configDescriptionC = element->Attribute("description"); if (configDescriptionC) { reader->SetConfigurationDescription(configDescriptionC); } // "fixTiltByShearing" flag bool fixTiltByShearing = QueryBooleanAttribute(element, "fixTiltByShearing", DICOMITKSeriesGDCMReader::GetDefaultFixTiltByShearing()); reader->SetFixTiltByShearing( fixTiltByShearing ); } mitk::DICOMITKSeriesGDCMReader::Pointer mitk::DICOMReaderConfigurator -::ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, TiXmlElement* element) const +::ConfigureDICOMITKSeriesGDCMReader(DICOMITKSeriesGDCMReader::Pointer reader, const tinyxml2::XMLElement* element) const { assert(element); this->ConfigureCommonPropertiesOfDICOMITKSeriesGDCMReader(reader, element); // "acceptTwoSlicesGroups" flag bool acceptTwoSlicesGroups = QueryBooleanAttribute(element, "acceptTwoSlicesGroups", true); reader->SetAcceptTwoSlicesGroups( acceptTwoSlicesGroups ); // "toleratedOriginError" attribute (double) bool toleratedOriginErrorIsAbsolute = QueryBooleanAttribute(element, "toleratedOriginErrorIsAbsolute", false); double toleratedOriginError(0.3); - if (element->QueryDoubleAttribute("toleratedOriginError", &toleratedOriginError) == TIXML_SUCCESS) // attribute present and a double value + if (element->QueryDoubleAttribute("toleratedOriginError", &toleratedOriginError) == tinyxml2::XML_SUCCESS) // attribute present and a double value { if (toleratedOriginErrorIsAbsolute) { reader->SetToleratedOriginOffset( toleratedOriginError ); } else { reader->SetToleratedOriginOffsetToAdaptive( toleratedOriginError ); } } // DICOMTagBasedSorters are the only thing we create at this point // TODO for-loop over all child elements of type DICOMTagBasedSorter, BUT actually a single sorter of this type is enough. - TiXmlElement* dElement = element->FirstChildElement("DICOMDatasetSorter"); + auto* dElement = element->FirstChildElement("DICOMDatasetSorter"); if (dElement) { const char* classnameC = dElement->Attribute("class"); if (!classnameC) { MITK_ERROR << "File should name a DICOMDatasetSorter class in the class attribute of . Found nothing instead"; return nullptr; } std::string classname(classnameC); if (classname == "DICOMTagBasedSorter") { DICOMTagBasedSorter::Pointer tagSorter = CreateDICOMTagBasedSorter(dElement); if (tagSorter.IsNotNull()) { reader->AddSortingElement( tagSorter ); } } else { MITK_ERROR << "DICOMDatasetSorter tag names unknown class '" << classname << "'"; return nullptr; } } return reader; } mitk::DICOMTagBasedSorter::Pointer mitk::DICOMReaderConfigurator -::CreateDICOMTagBasedSorter(TiXmlElement* element) const +::CreateDICOMTagBasedSorter(const tinyxml2::XMLElement* element) const { mitk::DICOMTagBasedSorter::Pointer tagSorter = mitk::DICOMTagBasedSorter::New(); // "strictSorting" parameter! bool strictSorting = QueryBooleanAttribute(element, "strictSorting", mitk::DICOMTagBasedSorter::GetDefaultStrictSorting()); tagSorter->SetStrictSorting(strictSorting); // "strictSorting" parameter! bool expectDistanceOne = QueryBooleanAttribute(element, "expectDistanceOne", mitk::DICOMTagBasedSorter::GetDefaultExpectDistanceOne()); tagSorter->SetExpectDistanceOne(expectDistanceOne); - TiXmlElement* dElement = element->FirstChildElement("Distinguishing"); + auto* dElement = element->FirstChildElement("Distinguishing"); if (dElement) { - for ( TiXmlElement* tChild = dElement->FirstChildElement(); + for ( auto* tChild = dElement->FirstChildElement(); tChild != nullptr; tChild = tChild->NextSiblingElement() ) { try { mitk::DICOMTag tag = tagFromXMLElement(tChild); int i(5); - if (tChild->QueryIntAttribute("cutDecimalPlaces", &i) == TIXML_SUCCESS) + if (tChild->QueryIntAttribute("cutDecimalPlaces", &i) == tinyxml2::XML_SUCCESS) { tagSorter->AddDistinguishingTag( tag, new mitk::DICOMTagBasedSorter::CutDecimalPlaces(i) ); } else { tagSorter->AddDistinguishingTag( tag ); } } catch(...) { return nullptr; } } } // "sorting tags" - TiXmlElement* sElement = element->FirstChildElement("Sorting"); + auto* sElement = element->FirstChildElement("Sorting"); if (sElement) { DICOMSortCriterion::Pointer previousCriterion; DICOMSortCriterion::Pointer currentCriterion; - for ( TiXmlNode* tChildNode = sElement->LastChild(); + for ( auto* tChildNode = sElement->LastChild(); tChildNode != nullptr; tChildNode = tChildNode->PreviousSibling() ) { - TiXmlElement* tChild = tChildNode->ToElement(); + auto* tChild = tChildNode->ToElement(); if (!tChild) continue; if (!strcmp(tChild->Value(), "Tag")) { try { currentCriterion = this->CreateDICOMSortByTag(tChild, previousCriterion); } catch(...) { std::stringstream ss; - ss << "Could not parse element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!"; + ss << "Could not parse element at input line " << tChild->GetLineNum() << "!"; MITK_ERROR << ss.str(); return nullptr; } } else if (!strcmp(tChild->Value(), "ImagePositionPatient")) { try { currentCriterion = this->CreateSortByImagePositionPatient(tChild, previousCriterion); } catch(...) { std::stringstream ss; - ss << "Could not parse element at (input line " << tChild->Row() << ", col. " << tChild->Column() << ")!"; + ss << "Could not parse element at input line " << tChild->GetLineNum() << "!"; MITK_ERROR << ss.str(); return nullptr; } } else { MITK_ERROR << "File contain unknown tag <" << tChild->Value() << "> tag as child to ! Cannot interpret..."; } previousCriterion = currentCriterion; } tagSorter->SetSortCriterion( currentCriterion.GetPointer() ); } return tagSorter; } std::string mitk::DICOMReaderConfigurator -::requiredStringAttribute(TiXmlElement* xmlElement, const std::string& key) const +::requiredStringAttribute(const tinyxml2::XMLElement* xmlElement, const std::string& key) const { assert(xmlElement); const char* gC = xmlElement->Attribute(key.c_str()); if (gC) { std::string gS(gC); return gS; } else { std::stringstream ss; - ss << "Expected an attribute '" << key << "' at this position " - "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!"; + ss << "Expected an attribute '" << key << "' at " + "input line " << xmlElement->GetLineNum() << "!"; MITK_ERROR << ss.str(); throw std::invalid_argument( ss.str() ); } } unsigned int mitk::DICOMReaderConfigurator ::hexStringToUInt(const std::string& s) const { std::stringstream converter(s); unsigned int ui; converter >> std::hex >> ui; MITK_DEBUG << "Converted string '" << s << "' to unsigned int " << ui; return ui; } mitk::DICOMTag mitk::DICOMReaderConfigurator -::tagFromXMLElement(TiXmlElement* xmlElement) const +::tagFromXMLElement(const tinyxml2::XMLElement* xmlElement) const { assert(xmlElement); if (strcmp(xmlElement->Value(), "Tag")) // :-( no std::string methods { std::stringstream ss; - ss << "Expected a tag at this position " - "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!"; + ss << "Expected a tag at " + "input line " << xmlElement->GetLineNum() << "!"; MITK_ERROR << ss.str(); throw std::invalid_argument( ss.str() ); } std::string groupS = requiredStringAttribute(xmlElement, "group"); std::string elementS = requiredStringAttribute(xmlElement, "element"); try { // convert string to int (assuming string is in hex format with leading "0x" like "0x0020") unsigned int group = hexStringToUInt(groupS); unsigned int element = hexStringToUInt(elementS); return DICOMTag(group, element); } catch(...) { std::stringstream ss; ss << "Expected group and element values in to be hexadecimal with leading 0x, e.g. '0x0020'" - "(input line " << xmlElement->Row() << ", col. " << xmlElement->Column() << ")!"; + "(input line " << xmlElement->GetLineNum() << ")!"; MITK_ERROR << ss.str(); throw std::invalid_argument( ss.str() ); } } mitk::DICOMSortCriterion::Pointer mitk::DICOMReaderConfigurator -::CreateDICOMSortByTag(TiXmlElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const +::CreateDICOMSortByTag(const tinyxml2::XMLElement* xmlElement, DICOMSortCriterion::Pointer secondaryCriterion) const { mitk::DICOMTag tag = tagFromXMLElement(xmlElement); return DICOMSortByTag::New(tag, secondaryCriterion).GetPointer(); } mitk::DICOMSortCriterion::Pointer mitk::DICOMReaderConfigurator -::CreateSortByImagePositionPatient(TiXmlElement*, DICOMSortCriterion::Pointer secondaryCriterion) const +::CreateSortByImagePositionPatient(const tinyxml2::XMLElement*, DICOMSortCriterion::Pointer secondaryCriterion) const { return SortByImagePositionPatient::New(secondaryCriterion).GetPointer(); } std::string mitk::DICOMReaderConfigurator ::CreateConfigStringFromReader(DICOMFileReader::ConstPointer reader) const { // check possible sub-classes from the most-specific one up to the most generic one const DICOMFileReader* cPointer = reader; - TiXmlElement* root; + tinyxml2::XMLDocument document; + tinyxml2::XMLElement* root = nullptr; if (const auto* specificReader = dynamic_cast(cPointer)) { - root = this->CreateConfigStringFromReader(specificReader); + root = this->CreateConfigStringFromReader(document, specificReader); } else if (const auto* specificReader = dynamic_cast(cPointer)) { - root = this->CreateConfigStringFromReader(specificReader); + root = this->CreateConfigStringFromReader(document, specificReader); } else if (const auto* specificReader = dynamic_cast(cPointer)) { - root = this->CreateConfigStringFromReader(specificReader); + root = this->CreateConfigStringFromReader(document, specificReader); } else { MITK_WARN << "Unknown reader class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize."; return ""; // no serialization, what a pity } - if (root) + if (nullptr != root) { - TiXmlDocument document; - document.LinkEndChild( root ); + document.InsertEndChild( root ); - TiXmlPrinter printer; - printer.SetIndent( " " ); + tinyxml2::XMLPrinter printer; + document.Print(&printer); - document.Accept( &printer ); std::string xmltext = printer.CStr(); return xmltext; } else { MITK_WARN << "DICOMReaderConfigurator::CreateConfigStringFromReader() created empty serialization. Problem?"; return ""; } } -TiXmlElement* +tinyxml2::XMLElement* mitk::DICOMReaderConfigurator -::CreateConfigStringFromReader(const DICOMITKSeriesGDCMReader* reader) const +::CreateConfigStringFromReader(tinyxml2::XMLDocument &doc, const DICOMITKSeriesGDCMReader* reader) const { - TiXmlElement* root = this->CreateDICOMFileReaderTag(reader); + auto* root = this->CreateDICOMFileReaderTag(doc, reader); assert(root); - root->SetAttribute("fixTiltByShearing", toString(reader->GetFixTiltByShearing())); - root->SetAttribute("acceptTwoSlicesGroups", toString(reader->GetAcceptTwoSlicesGroups())); - root->SetDoubleAttribute("toleratedOriginError", reader->GetToleratedOriginError()); - root->SetAttribute("toleratedOriginErrorIsAbsolute", toString(reader->IsToleratedOriginOffsetAbsolute())); - root->SetDoubleAttribute("decimalPlacesForOrientation", reader->GetDecimalPlacesForOrientation()); + root->SetAttribute("fixTiltByShearing", reader->GetFixTiltByShearing()); + root->SetAttribute("acceptTwoSlicesGroups", reader->GetAcceptTwoSlicesGroups()); + root->SetAttribute("toleratedOriginError", reader->GetToleratedOriginError()); + root->SetAttribute("toleratedOriginErrorIsAbsolute", reader->IsToleratedOriginOffsetAbsolute()); + root->SetAttribute("decimalPlacesForOrientation", reader->GetDecimalPlacesForOrientation()); // iterate DICOMDatasetSorter objects DICOMITKSeriesGDCMReader::ConstSorterList sorterList = reader->GetFreelyConfiguredSortingElements(); for(auto sorterIter = sorterList.begin(); sorterIter != sorterList.end(); ++sorterIter) { const DICOMDatasetSorter* sorter = *sorterIter; if (const auto* specificSorter = dynamic_cast(sorter)) { - TiXmlElement* sorterTag = this->CreateConfigStringFromDICOMDatasetSorter(specificSorter); - root->LinkEndChild(sorterTag); + auto* sorterTag = this->CreateConfigStringFromDICOMDatasetSorter(doc, specificSorter); + root->InsertEndChild(sorterTag); } else { MITK_WARN << "Unknown DICOMDatasetSorter class passed to DICOMReaderConfigurator::CreateConfigStringFromReader(). Cannot serialize."; return nullptr; } } return root; } -TiXmlElement* +tinyxml2::XMLElement* mitk::DICOMReaderConfigurator -::CreateConfigStringFromDICOMDatasetSorter(const DICOMTagBasedSorter* sorter) const +::CreateConfigStringFromDICOMDatasetSorter(tinyxml2::XMLDocument &doc, const DICOMTagBasedSorter* sorter) const { assert(sorter); - auto sorterTag = new TiXmlElement("DICOMDatasetSorter"); + auto *sorterTag = doc.NewElement("DICOMDatasetSorter"); sorterTag->SetAttribute("class", sorter->GetNameOfClass()); - sorterTag->SetAttribute("strictSorting", toString(sorter->GetStrictSorting())); - sorterTag->SetAttribute("expectDistanceOne", toString(sorter->GetExpectDistanceOne())); + sorterTag->SetAttribute("strictSorting", sorter->GetStrictSorting()); + sorterTag->SetAttribute("expectDistanceOne", sorter->GetExpectDistanceOne()); - auto distinguishingTagsElement = new TiXmlElement("Distinguishing"); - sorterTag->LinkEndChild(distinguishingTagsElement); + auto *distinguishingTagsElement = doc.NewElement("Distinguishing"); + sorterTag->InsertEndChild(distinguishingTagsElement); mitk::DICOMTagList distinguishingTags = sorter->GetDistinguishingTags(); for (auto tagIter = distinguishingTags.begin(); tagIter != distinguishingTags.end(); ++tagIter) { - TiXmlElement* tag = this->CreateConfigStringFromDICOMTag(*tagIter); - distinguishingTagsElement->LinkEndChild(tag); + auto* tag = this->CreateConfigStringFromDICOMTag(doc, *tagIter); + distinguishingTagsElement->InsertEndChild(tag); const DICOMTagBasedSorter::TagValueProcessor* processor = sorter->GetTagValueProcessorForDistinguishingTag(*tagIter); if (const auto* specificProcessor = dynamic_cast(processor)) { - tag->SetDoubleAttribute("cutDecimalPlaces", specificProcessor->GetPrecision()); + tag->SetAttribute("cutDecimalPlaces", specificProcessor->GetPrecision()); } } - auto sortingElement = new TiXmlElement("Sorting"); - sorterTag->LinkEndChild(sortingElement); + auto *sortingElement = doc.NewElement("Sorting"); + sorterTag->InsertEndChild(sortingElement); mitk::DICOMSortCriterion::ConstPointer sortCriterion = sorter->GetSortCriterion(); while (sortCriterion.IsNotNull()) { std::string classname = sortCriterion->GetNameOfClass(); if (classname == "SortByImagePositionPatient") { - sortingElement->LinkEndChild( new TiXmlElement("ImagePositionPatient") ); // no parameters + sortingElement->InsertEndChild( doc.NewElement("ImagePositionPatient") ); // no parameters } else if (classname == "DICOMSortByTag") { DICOMTagList pseudoTagList = sortCriterion->GetTagsOfInterest(); if (pseudoTagList.size() == 1) { DICOMTag firstTag = pseudoTagList.front(); - TiXmlElement* tagElement = this->CreateConfigStringFromDICOMTag(firstTag); + auto* tagElement = this->CreateConfigStringFromDICOMTag(doc, firstTag); - sortingElement->LinkEndChild( tagElement ); + sortingElement->InsertEndChild( tagElement ); } else { MITK_ERROR << "Encountered SortByTag class with MULTIPLE tag in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize."; return nullptr; } } else { MITK_ERROR << "Encountered unknown class '" << classname << "' in CreateConfigStringFromDICOMDatasetSorter. Cannot serialize."; return nullptr; } sortCriterion = sortCriterion->GetSecondaryCriterion(); } return sorterTag; } -TiXmlElement* +tinyxml2::XMLElement* mitk::DICOMReaderConfigurator -::CreateConfigStringFromDICOMTag(const DICOMTag& tag) const +::CreateConfigStringFromDICOMTag(tinyxml2::XMLDocument& doc, const DICOMTag& tag) const { - auto tagElement = new TiXmlElement("Tag"); // name group element + auto tagElement = doc.NewElement("Tag"); // name group element tagElement->SetAttribute("name", tag.GetName().c_str()); - tagElement->SetAttribute("group", toHexString(tag.GetGroup())); - tagElement->SetAttribute("element", toHexString(tag.GetElement())); + tagElement->SetAttribute("group", toHexString(tag.GetGroup()).c_str()); + tagElement->SetAttribute("element", toHexString(tag.GetElement()).c_str()); return tagElement; } std::string mitk::DICOMReaderConfigurator ::toHexString(unsigned int i) const { std::stringstream ss; ss << "0x" << std::setfill ('0') << std::setw(4) << std::hex << i; return ss.str(); } -TiXmlElement* +tinyxml2::XMLElement* mitk::DICOMReaderConfigurator -::CreateConfigStringFromReader(const ThreeDnTDICOMSeriesReader* reader) const +::CreateConfigStringFromReader(tinyxml2::XMLDocument& doc, const ThreeDnTDICOMSeriesReader* reader) const { - TiXmlElement* root = this->CreateConfigStringFromReader(static_cast(reader)); + auto* root = this->CreateConfigStringFromReader(doc, static_cast(reader)); assert(root); - root->SetAttribute("group3DnT", toString(reader->GetGroup3DandT())); + root->SetAttribute("group3DnT", reader->GetGroup3DandT()); return root; } -const char* -mitk::DICOMReaderConfigurator -::toString(bool b) const -{ - return b ? "true" : "false"; -} - -TiXmlElement* +tinyxml2::XMLElement* mitk::DICOMReaderConfigurator -::CreateConfigStringFromReader(const ClassicDICOMSeriesReader* reader) const +::CreateConfigStringFromReader(tinyxml2::XMLDocument& doc, const ClassicDICOMSeriesReader* reader) const { - return this->CreateDICOMFileReaderTag(reader); + return this->CreateDICOMFileReaderTag(doc, reader); } -TiXmlElement* +tinyxml2::XMLElement* mitk::DICOMReaderConfigurator -::CreateDICOMFileReaderTag(const DICOMFileReader* reader) const +::CreateDICOMFileReaderTag(tinyxml2::XMLDocument& doc, const DICOMFileReader* reader) const { - auto readerTag = new TiXmlElement("DICOMFileReader"); + auto readerTag = doc.NewElement("DICOMFileReader"); readerTag->SetAttribute("class", reader->GetNameOfClass()); readerTag->SetAttribute("label", reader->GetConfigurationLabel().c_str()); readerTag->SetAttribute("description", reader->GetConfigurationDescription().c_str()); readerTag->SetAttribute("version", "1"); return readerTag; } diff --git a/Modules/IGT/CMakeLists.txt b/Modules/IGT/CMakeLists.txt index 760efba59f..a9eca5afcc 100644 --- a/Modules/IGT/CMakeLists.txt +++ b/Modules/IGT/CMakeLists.txt @@ -1,63 +1,69 @@ include(MITKIGTHardware.cmake) if(MITK_USE_MICRON_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_MICRON_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_MICRON_TRACKER_LIB}) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_OPTITRACK_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_OPTITRACK_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_OPTITRACK_TRACKER_LIB}) add_definitions( -DMITK_USE_OPTITRACK_TRACKER ) endif(MITK_USE_OPTITRACK_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_USE_MICROBIRD_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_USE_MICROBIRD_TRACKER_LIB}) endif(MITK_USE_MICROBIRD_TRACKER) if(MITK_USE_POLHEMUS_TRACKER) set(ADDITIONAL_INCLUDE_DIRS ${ADDITIONAL_INCLUDE_DIRS} ${MITK_POLHEMUS_TRACKER_INCLUDE_DIR}) set(ADDITIONAL_LIBS ${ADDITIONAL_LIBS} ${MITK_POLHEMUS_TRACKER_LIB}) endif(MITK_USE_POLHEMUS_TRACKER) MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC Algorithms Common DataManagement ExceptionHandling IO Rendering TrackingDevices TestingHelper PRIVATE ${ADDITIONAL_INCLUDE_DIRS} DEPENDS PUBLIC MitkImageStatistics MitkSceneSerialization MitkIGTBase MitkOpenIGTLink - PACKAGE_DEPENDS ITK|ITKRegistrationCommon tinyxml OpenIGTLink + PACKAGE_DEPENDS ITK|ITKRegistrationCommon tinyxml2|tinyxml2 OpenIGTLink ADDITIONAL_LIBS "${ADDITIONAL_LIBS}" ) +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} + PRIVATE tinyxml2::tinyxml2 + ) +endif() + if(MitkIGT_IS_ENABLED) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/ClaronMicron.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/IntuitiveDaVinci.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAurora_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraCompactFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraPlanarFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIAuroraTabletopFG_Prototype_Dome.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisOldModel.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectra.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisSpectraExtendedPyramid.stl ) MITK_INSTALL(FILES ${MITK_SOURCE_DIR}/Modules/IGT/Resources/NDIPolarisVicra.stl ) endif() if(NOT MODULE_IS_ENABLED) message(STATUS "IGTTutorialStep1 won't be built. Missing: ${_RESULT}") else() ## create IGT config configure_file(mitkIGTConfig.h.in ${PROJECT_BINARY_DIR}/mitkIGTConfig.h @ONLY) # add test programm for serial communication classADD_EXECUTABLE(SerialCommunicationTest IGTTrackingDevices/mitkSerialCommunicationTest.cpp)target_link_libraries(SerialCommunicationTest mitkIGT Mitk tinyxml PocoXML) add_subdirectory(autoload/DeviceRegistry) add_subdirectory(Tutorial) add_subdirectory(Testing) endif() diff --git a/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.cpp b/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.cpp index c10728cf92..0f9609216a 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.cpp +++ b/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.cpp @@ -1,362 +1,364 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkNavigationDataRecorderDeprecated.h" #include #include -#include +#include #include //headers for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" mitk::NavigationDataRecorderDeprecated::NavigationDataRecorderDeprecated() { //set default values m_NumberOfInputs = 0; m_RecordingMode = NormalFile; m_Recording = false; m_NumberOfRecordedFiles = 0; m_Stream = nullptr; m_FileName = ""; m_SystemTimeClock = RealTimeClock::New(); m_OutputFormat = mitk::NavigationDataRecorderDeprecated::xml; m_RecordCounter = 0; m_RecordCountLimit = -1; m_DoNotOverwriteFiles = false; m_StreamMustBeDeleted = false; //To get a start time mitk::IGTTimeStamp::GetInstance()->Start(this); } mitk::NavigationDataRecorderDeprecated::~NavigationDataRecorderDeprecated() { } void mitk::NavigationDataRecorderDeprecated::GenerateData() { } void mitk::NavigationDataRecorderDeprecated::AddNavigationData( const NavigationData* nd ) { // Process object is not const-correct so the const_cast is required here this->SetNthInput(m_NumberOfInputs, const_cast< mitk::NavigationData * >( nd ) ); m_NumberOfInputs++; this->Modified(); } void mitk::NavigationDataRecorderDeprecated::SetRecordingMode( RecordingMode mode ) { m_RecordingMode = mode; this->Modified(); } void mitk::NavigationDataRecorderDeprecated::Update() { if (m_Recording) { DataObjectPointerArray inputs = this->GetInputs(); //get all inputs mitk::NavigationData::TimeStampType timestamp=0.0; // timestamp for mitk time timestamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); mitk::NavigationData::TimeStampType sysTimestamp = 0.0; // timestamp for system time sysTimestamp = m_SystemTimeClock->GetCurrentStamp(); // cast system time double value to stringstream to avoid low precision rounding std::ostringstream strs; strs.precision(15); // rounding precision for system time double value strs << sysTimestamp; std::string sysTimeStr = strs.str(); //if csv-mode: write csv header and timestamp at beginning if (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv) { //write header only when it's the first line if (m_firstLine) { m_firstLine = false; *m_Stream << "TimeStamp"; for (unsigned int index = 0; index < inputs.size(); index++){ *m_Stream << ";Valid_Tool" << index << ";X_Tool" << index << ";Y_Tool" << index << ";Z_Tool" << index << ";QX_Tool" << index << ";QY_Tool" << index << ";QZ_Tool" << index << ";QR_Tool" << index;} *m_Stream << "\n"; } //write timestamp (always) *m_Stream << timestamp; } //write tool data for every tool for (unsigned int index = 0; index < inputs.size(); index++) { mitk::NavigationData* nd = dynamic_cast(inputs[index].GetPointer()); nd->Update(); // call update to propagate update to previous filters mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); position = nd->GetPosition(); orientation = nd->GetOrientation(); matrix = nd->GetCovErrorMatrix(); hasPosition = nd->GetHasPosition(); hasOrientation = nd->GetHasOrientation(); dataValid = nd->IsDataValid(); //use this one if you want the timestamps of the source //timestamp = nd->GetIGTTimeStamp(); //a timestamp is never < 0! this case happens only if you are using the timestamp of the nd object instead of getting a new one if (timestamp >= 0) { if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml) - { - auto elem = new TiXmlElement("NavigationData"); - - elem->SetDoubleAttribute("Time", timestamp); - elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time - elem->SetDoubleAttribute("Tool", index); - elem->SetDoubleAttribute("X", position[0]); - elem->SetDoubleAttribute("Y", position[1]); - elem->SetDoubleAttribute("Z", position[2]); - - elem->SetDoubleAttribute("QX", orientation[0]); - elem->SetDoubleAttribute("QY", orientation[1]); - elem->SetDoubleAttribute("QZ", orientation[2]); - elem->SetDoubleAttribute("QR", orientation[3]); - - elem->SetDoubleAttribute("C00", matrix[0][0]); - elem->SetDoubleAttribute("C01", matrix[0][1]); - elem->SetDoubleAttribute("C02", matrix[0][2]); - elem->SetDoubleAttribute("C03", matrix[0][3]); - elem->SetDoubleAttribute("C04", matrix[0][4]); - elem->SetDoubleAttribute("C05", matrix[0][5]); - elem->SetDoubleAttribute("C10", matrix[1][0]); - elem->SetDoubleAttribute("C11", matrix[1][1]); - elem->SetDoubleAttribute("C12", matrix[1][2]); - elem->SetDoubleAttribute("C13", matrix[1][3]); - elem->SetDoubleAttribute("C14", matrix[1][4]); - elem->SetDoubleAttribute("C15", matrix[1][5]); + { + tinyxml2::XMLDocument doc; + auto *elem = doc.NewElement("NavigationData"); + + elem->SetAttribute("Time", timestamp); + elem->SetAttribute("SystemTime", sysTimeStr.c_str()); // tag for system time + elem->SetAttribute("Tool", index); + elem->SetAttribute("X", position[0]); + elem->SetAttribute("Y", position[1]); + elem->SetAttribute("Z", position[2]); + + elem->SetAttribute("QX", orientation[0]); + elem->SetAttribute("QY", orientation[1]); + elem->SetAttribute("QZ", orientation[2]); + elem->SetAttribute("QR", orientation[3]); + + elem->SetAttribute("C00", matrix[0][0]); + elem->SetAttribute("C01", matrix[0][1]); + elem->SetAttribute("C02", matrix[0][2]); + elem->SetAttribute("C03", matrix[0][3]); + elem->SetAttribute("C04", matrix[0][4]); + elem->SetAttribute("C05", matrix[0][5]); + elem->SetAttribute("C10", matrix[1][0]); + elem->SetAttribute("C11", matrix[1][1]); + elem->SetAttribute("C12", matrix[1][2]); + elem->SetAttribute("C13", matrix[1][3]); + elem->SetAttribute("C14", matrix[1][4]); + elem->SetAttribute("C15", matrix[1][5]); if (dataValid) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (hasOrientation) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (hasPosition) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); // set additional attribute? auto it = m_AdditionalAttributes.find( nd ); if( it != m_AdditionalAttributes.end() ) { - elem->SetAttribute(it->second.first, it->second.second); + elem->SetAttribute(it->second.first.c_str(), it->second.second.c_str()); } - *m_Stream << " " << *elem << std::endl; + tinyxml2::XMLPrinter printer; + doc.Print(&printer); - delete elem; + *m_Stream << " " << printer.CStr() << std::endl; } else if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv) { *m_Stream << ";" << dataValid << ";" << position[0] << ";" << position[1] << ";" << position[2] << ";" << orientation[0] << ";" << orientation[1] << ";" << orientation[2] << ";" << orientation[3]; } } } if (this->m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv) { *m_Stream << "\n"; } } m_RecordCounter++; if ((m_RecordCountLimit<=m_RecordCounter)&&(m_RecordCountLimit != -1)) {StopRecording();} } void mitk::NavigationDataRecorderDeprecated::SetAdditionalAttribute(const NavigationData* nd, const std::string& attributeName , const std::string& attributeValue ) { auto it = m_AdditionalAttributes.find( nd ); if( it == m_AdditionalAttributes.end() ) m_AdditionalAttributes[nd] = std::pair(attributeName, attributeValue); else { it->second.first = attributeName; it->second.second = attributeValue; } } void mitk::NavigationDataRecorderDeprecated::RemoveAdditionalAttribute( const NavigationData* nd ) { auto it = m_AdditionalAttributes.find( nd ); if( it != m_AdditionalAttributes.end() ) m_AdditionalAttributes.erase(it); } void mitk::NavigationDataRecorderDeprecated::StartRecording() { if(!m_Recording) { if (m_Stream == nullptr) { std::stringstream ss; std::ostream* stream; //An existing extension will be cut and replaced with .xml std::string tmpPath = itksys::SystemTools::GetFilenamePath(m_FileName); m_FileName = itksys::SystemTools::GetFilenameWithoutExtension(m_FileName); std::string extension = ".xml"; if (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::csv) extension = ".csv"; ss << tmpPath << "/" << m_FileName << "-" << m_NumberOfRecordedFiles << extension; if( m_DoNotOverwriteFiles ) { unsigned int index = m_NumberOfRecordedFiles+1; while( itksys::SystemTools::FileExists( ss.str().c_str() ) ) { ss.str(""); ss << tmpPath << "/" << m_FileName << "-" << index << extension; index++; } } switch(m_RecordingMode) { case Console: stream = &std::cout; break; case NormalFile: if (m_FileName == "") //Check if there is a file name and path { std::string message = "No file name or file path set."; MITK_ERROR << message; mitkThrowException(mitk::IGTException) << message; } else { stream = new std::ofstream(ss.str().c_str()); } break; case ZipFile: stream = &std::cout; MITK_WARN << "Sorry no ZipFile support yet"; break; default: stream = &std::cout; break; } m_Stream = stream; m_StreamMustBeDeleted = true; m_firstLine = true; m_RecordCounter = 0; StartRecording(stream); } } else if (m_Recording) { MITK_WARN << "Already recording please stop before start new recording session"; return; } } void mitk::NavigationDataRecorderDeprecated::StartRecording(std::ostream* stream) { if (m_Recording) { MITK_WARN << "Already recording please stop before start new recording session"; return; } m_Stream = stream; m_Stream->precision(10); //TODO store date and GMT time //cheking if the stream is good if (m_Stream->good()) { if (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml) { *m_Stream << "" << std::endl; /**m_Stream << "" << std::endl;*/ // should be a generic version, meaning a member variable, which has the actual version *m_Stream << " " << "" << std::endl; } m_Recording = true; } else { m_Recording = false; mitkThrowException(mitk::IGTException)<<"The stream is not good"; } } void mitk::NavigationDataRecorderDeprecated::StopRecording() { if (!m_Recording) { std::cout << "You have to start a recording first" << std::endl; return; } if ((m_Stream) && (m_OutputFormat == mitk::NavigationDataRecorderDeprecated::xml)) { *m_Stream << "" << std::endl; } m_NumberOfRecordedFiles++; m_Recording = false; m_Stream->flush(); if (m_StreamMustBeDeleted) //stream must only be deleted if it was created inside this class { m_StreamMustBeDeleted = false; delete m_Stream; } m_Stream = nullptr; } diff --git a/Modules/IGTBase/autoload/IO/CMakeLists.txt b/Modules/IGTBase/autoload/IO/CMakeLists.txt index e6e391249c..cd58ef13ea 100644 --- a/Modules/IGTBase/autoload/IO/CMakeLists.txt +++ b/Modules/IGTBase/autoload/IO/CMakeLists.txt @@ -1,5 +1,11 @@ MITK_CREATE_MODULE(IGTIO DEPENDS MitkIGTBase - PACKAGE_DEPENDS tinyxml + PACKAGE_DEPENDS tinyxml2|tinyxml2 AUTOLOAD_WITH MitkCore ) + +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} + PRIVATE tinyxml2::tinyxml2 + ) +endif() diff --git a/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp index 24551b7f0a..7195fd995e 100644 --- a/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp @@ -1,364 +1,214 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include "mitkNavigationDataReaderXML.h" #include #include // Third Party #include #include -#include +#include - -mitk::NavigationDataReaderXML::NavigationDataReaderXML() : AbstractFileReader( - mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE(), - "MITK NavigationData Reader (XML)"), m_parentElement(nullptr), m_currentNode(nullptr) +namespace { - RegisterService(); -} + mitk::NavigationData::Pointer ReadNavigationData(const tinyxml2::XMLElement* ndElem) + { + if (nullptr == ndElem) + return nullptr; -mitk::NavigationDataReaderXML::~NavigationDataReaderXML() -{ -} + mitk::NavigationData::TimeStampType timeStamp = -1; -mitk::NavigationDataReaderXML::NavigationDataReaderXML(const mitk::NavigationDataReaderXML& other) : AbstractFileReader(other), m_parentElement(nullptr), m_currentNode(nullptr) -{ -} + ndElem->QueryDoubleAttribute("Time", &timeStamp); -mitk::NavigationDataReaderXML* mitk::NavigationDataReaderXML::Clone() const -{ - return new NavigationDataReaderXML(*this); -} + if (-1 == timeStamp) + return nullptr; + mitk::NavigationData::PositionType position; + position.Fill(0.0); -std::vector> mitk::NavigationDataReaderXML::DoRead() -{ - mitk::NavigationDataSet::Pointer dataset; - std::istream* in = GetInputStream(); - if (in == nullptr) - { - dataset = Read(GetInputLocation()); - } else { - dataset = Read(in); - } - std::vector result; - mitk::BaseData::Pointer base = dataset.GetPointer(); - result.push_back(base); - return result; -} + ndElem->QueryDoubleAttribute("X", &position[0]); + ndElem->QueryDoubleAttribute("Y", &position[1]); + ndElem->QueryDoubleAttribute("Z", &position[2]); + mitk::NavigationData::OrientationType orientation; + ndElem->QueryDoubleAttribute("QX", &orientation[0]); + ndElem->QueryDoubleAttribute("QY", &orientation[1]); + ndElem->QueryDoubleAttribute("QZ", &orientation[2]); + ndElem->QueryDoubleAttribute("QR", &orientation[3]); -mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::string fileName) -{ - //define own locale - mitk::LocaleSwitch localeSwitch("C"); + mitk::NavigationData::CovarianceMatrixType matrix; + matrix.SetIdentity(); - m_FileName = fileName; + ndElem->QueryDoubleAttribute("C00", &matrix[0][0]); + ndElem->QueryDoubleAttribute("C01", &matrix[0][1]); + ndElem->QueryDoubleAttribute("C02", &matrix[0][2]); + ndElem->QueryDoubleAttribute("C03", &matrix[0][3]); + ndElem->QueryDoubleAttribute("C04", &matrix[0][4]); + ndElem->QueryDoubleAttribute("C05", &matrix[0][5]); + ndElem->QueryDoubleAttribute("C10", &matrix[1][0]); + ndElem->QueryDoubleAttribute("C11", &matrix[1][1]); + ndElem->QueryDoubleAttribute("C12", &matrix[1][2]); + ndElem->QueryDoubleAttribute("C13", &matrix[1][3]); + ndElem->QueryDoubleAttribute("C14", &matrix[1][4]); + ndElem->QueryDoubleAttribute("C15", &matrix[1][5]); - TiXmlDocument document; - if (!document.LoadFile(fileName)) - { - mitkThrowException(mitk::IGTIOException) << "File '" << fileName << "' could not be loaded."; - } + int attrib = 0; + ndElem->QueryIntAttribute("Valid", &attrib); + bool isValid = 0 != attrib; - TiXmlElement* m_DataElem = document.FirstChildElement("Version"); - if (!m_DataElem) - { - // for backwards compatibility of version tag - m_DataElem = document.FirstChildElement("Data"); - if (!m_DataElem) - { - mitkThrowException(mitk::IGTIOException) << "Data element not found."; - } + attrib = 0; + ndElem->QueryIntAttribute("hP", &attrib); + bool hasPosition = 0 != attrib; - } + attrib = 0; + ndElem->QueryIntAttribute("hO", &attrib); + bool hasOrientation = 0 != attrib; - if (m_DataElem->QueryIntAttribute("Ver", &m_FileVersion) != TIXML_SUCCESS) - { - if (m_DataElem->QueryIntAttribute("version", &m_FileVersion) != TIXML_SUCCESS) - { - mitkThrowException(mitk::IGTIOException) << "Version not specified in XML file."; - } - } + auto navData = mitk::NavigationData::New(); - if (m_FileVersion != 1) - { - mitkThrowException(mitk::IGTIOException) << "File format version " << m_FileVersion << " is not supported."; - } + navData->SetIGTTimeStamp(timeStamp); + navData->SetPosition(position); + navData->SetOrientation(orientation); + navData->SetCovErrorMatrix(matrix); + navData->SetDataValid(isValid); + navData->SetHasPosition(hasPosition); + navData->SetHasOrientation(hasOrientation); - m_parentElement = document.FirstChildElement("Data"); - if (!m_parentElement) - { - mitkThrowException(mitk::IGTIOException) << "Data element not found."; + return navData; } - - m_parentElement->QueryIntAttribute("ToolCount", &m_NumberOfOutputs); - - mitk::NavigationDataSet::Pointer navigationDataSet = this->ReadNavigationDataSet(); - - return navigationDataSet; } -mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::istream* stream) +mitk::NavigationDataReaderXML::NavigationDataReaderXML() + : AbstractFileReader(IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE(), "MITK NavigationData Reader (XML)") { - //define own locale - mitk::LocaleSwitch localeSwitch("C"); - - // first get the file version - m_FileVersion = this->GetFileVersion(stream); - - // check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing - if (m_FileVersion < 1) - { - StreamInvalid("Playing not possible. Invalid file version!"); - return nullptr; - } + this->RegisterService(); +} - m_NumberOfOutputs = this->GetNumberOfNavigationDatas(stream); - if (m_NumberOfOutputs == 0) { return nullptr; } +mitk::NavigationDataReaderXML::~NavigationDataReaderXML() +{ +} - mitk::NavigationDataSet::Pointer dataSet = this->ReadNavigationDataSet(); +mitk::NavigationDataReaderXML::NavigationDataReaderXML(const mitk::NavigationDataReaderXML& other) + : AbstractFileReader(other) +{ +} - return dataSet; +mitk::NavigationDataReaderXML* mitk::NavigationDataReaderXML::Clone() const +{ + return new NavigationDataReaderXML(*this); } -mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::ReadNavigationDataSet() +std::vector> mitk::NavigationDataReaderXML::DoRead() { - mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(m_NumberOfOutputs); - mitk::NavigationData::Pointer curNavigationData; + mitk::NavigationDataSet::Pointer dataset = nullptr == this->GetInputStream() + ? this->Read(this->GetInputLocation()) + : this->Read(*this->GetInputStream()); - do - { - std::vector navDatas(m_NumberOfOutputs); - for (int n = 0; n < m_NumberOfOutputs; ++n) - { - curNavigationData = this->ReadVersion1(); + std::vector result; + result.emplace_back(dataset.GetPointer()); - if (curNavigationData.IsNull()) - { - if (n != 0) - { - MITK_WARN("mitkNavigationDataReaderXML") - << "Different number of NavigationData objects for different tools. Ignoring last ones."; - } - break; - } - navDatas.at(n) = curNavigationData; - } + return result; +} - if (curNavigationData.IsNotNull()) - { - navigationDataSet->AddNavigationDatas(navDatas); - } - } - while (curNavigationData.IsNotNull()); +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(const std::string& fileName) +{ + std::ifstream stream(fileName); + stream.imbue(std::locale::classic()); - return navigationDataSet; + return this->Read(stream); } -mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadVersion1() +mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::istream& stream) { - if ( !m_parentElement ) - { - mitkThrowException(mitk::IGTIOException) << "Reading XML is not possible. Parent element is not set."; - } + std::string string(std::istreambuf_iterator(stream), {}); + tinyxml2::XMLDocument doc; + + if (tinyxml2::XML_SUCCESS != doc.Parse(string.c_str())) + mitkThrowException(IGTIOException) << "Could not parse stream."; + + const auto* rootElem = doc.RootElement(); + decltype(rootElem) dataElem = nullptr; - TiXmlElement* elem; - m_currentNode = m_parentElement->IterateChildren(m_currentNode); + if (nullptr == rootElem) + return nullptr; - bool delElem; + int version = 0; + auto err = tinyxml2::XML_SUCCESS; + + std::string rootElemVal = rootElem->Value(); - if(m_currentNode) + if ("Version" == rootElemVal) { - elem = m_currentNode->ToElement(); - if(elem==nullptr) - { - mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?"; - } - delElem = false; + err = rootElem->QueryIntAttribute("Ver", &version); + dataElem = rootElem->NextSiblingElement("Data"); } - - else + else if ("Data" == rootElemVal) { - elem = new TiXmlElement(""); - delElem = true; + err = rootElem->QueryIntAttribute("version", &version); + dataElem = rootElem; } + if (err != tinyxml2::XML_SUCCESS) + mitkThrowException(IGTIOException) << "Could not parse file format version."; - mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); + if (version != 1) + mitkThrowException(IGTIOException) << "File format version " << version << " is not supported."; - if(delElem) { delete elem; } + if (nullptr == dataElem) + mitkThrowException(IGTIOException) << "Data element not found."; - return nd; -} + int toolCount = 0; -mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadNavigationData(TiXmlElement* elem) -{ - if (elem == nullptr) {mitkThrow() << "Error: Element is nullptr!";} - - mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + if (tinyxml2::XML_SUCCESS != dataElem->QueryIntAttribute("ToolCount", &toolCount)) + mitkThrowException(IGTIOException) << "ToolCount attribute missing from Data element."; - mitk::NavigationData::PositionType position; - mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); - mitk::NavigationData::TimeStampType timestamp = -1; - mitk::NavigationData::CovarianceMatrixType matrix; + if (0 >= toolCount) + mitkThrowException(IGTIOException) << "Invalid ToolCount: " << toolCount << "."; - bool hasPosition = true; - bool hasOrientation = true; - bool dataValid = false; + auto navDataSet = NavigationDataSet::New(static_cast(toolCount)); + NavigationData::Pointer navData; - position.Fill(0.0); - matrix.SetIdentity(); + const auto* ndElem = dataElem->FirstChildElement(); - elem->QueryDoubleAttribute("Time",×tamp); - if (timestamp == -1) + if (nullptr != ndElem) { - return nullptr; //the calling method should check the return value if it is valid/not nullptr - } - - elem->QueryDoubleAttribute("X", &position[0]); - elem->QueryDoubleAttribute("Y", &position[1]); - elem->QueryDoubleAttribute("Z", &position[2]); - - elem->QueryDoubleAttribute("QX", &orientation[0]); - elem->QueryDoubleAttribute("QY", &orientation[1]); - elem->QueryDoubleAttribute("QZ", &orientation[2]); - elem->QueryDoubleAttribute("QR", &orientation[3]); - - elem->QueryDoubleAttribute("C00", &matrix[0][0]); - elem->QueryDoubleAttribute("C01", &matrix[0][1]); - elem->QueryDoubleAttribute("C02", &matrix[0][2]); - elem->QueryDoubleAttribute("C03", &matrix[0][3]); - elem->QueryDoubleAttribute("C04", &matrix[0][4]); - elem->QueryDoubleAttribute("C05", &matrix[0][5]); - elem->QueryDoubleAttribute("C10", &matrix[1][0]); - elem->QueryDoubleAttribute("C11", &matrix[1][1]); - elem->QueryDoubleAttribute("C12", &matrix[1][2]); - elem->QueryDoubleAttribute("C13", &matrix[1][3]); - elem->QueryDoubleAttribute("C14", &matrix[1][4]); - elem->QueryDoubleAttribute("C15", &matrix[1][5]); - - int tmpval = 0; - elem->QueryIntAttribute("Valid", &tmpval); - if (tmpval == 0) - dataValid = false; - else - dataValid = true; - - tmpval = 0; - elem->QueryIntAttribute("hO", &tmpval); - if (tmpval == 0) - hasOrientation = false; - else - hasOrientation = true; - - tmpval = 0; - elem->QueryIntAttribute("hP", &tmpval); - if (tmpval == 0) - hasPosition = false; - else - hasPosition = true; - - nd->SetIGTTimeStamp(timestamp); - nd->SetPosition(position); - nd->SetOrientation(orientation); - nd->SetCovErrorMatrix(matrix); - nd->SetDataValid(dataValid); - nd->SetHasOrientation(hasOrientation); - nd->SetHasPosition(hasPosition); - - - return nd; -} + do + { + std::vector navDatas(toolCount); -// -- deprecated | begin -unsigned int mitk::NavigationDataReaderXML::GetFileVersion(std::istream* stream) -{ - if (stream==nullptr) - { - MITK_ERROR << "No input stream set!"; - mitkThrowException(mitk::IGTIOException)<<"No input stream set!"; - } - if (!stream->good()) - { - MITK_ERROR << "Stream is not good!"; - mitkThrowException(mitk::IGTIOException)<<"Stream is not good!"; - } - int version = 1; + for (decltype(toolCount) i = 0; i < toolCount; ++i) + { + navData = ReadNavigationData(ndElem); - auto dec = new TiXmlDeclaration(); - *stream >> *dec; - if(strcmp(dec->Version(),"") == 0) - { - MITK_ERROR << "The input stream seems to have XML incompatible format"; - mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format"; - } + if (navData.IsNull()) + { + if (0 != i) + MITK_WARN("mitkNavigationDataReaderXML") << "Different number of NavigationData objects for different tools. Ignoring last ones."; - m_parentElement = new TiXmlElement(""); - *stream >> *m_parentElement; //2nd line this is the file version + break; + } - std::string tempValue = m_parentElement->Value(); - if(tempValue != "Version") - { - if(tempValue == "Data"){ - m_parentElement->QueryIntAttribute("version",&version); + navDatas[i] = navData; + ndElem = ndElem->NextSiblingElement(); } - } - else - { - m_parentElement->QueryIntAttribute("Ver",&version); - } - if (version > 0) { return version; } - else { return 0; } -} + if (navData.IsNotNull()) + navDataSet->AddNavigationDatas(navDatas); -unsigned int mitk::NavigationDataReaderXML::GetNumberOfNavigationDatas(std::istream* stream) -{ - if (stream == nullptr) - { - MITK_ERROR << "No input stream set!"; - mitkThrowException(mitk::IGTException)<<"No input stream set!"; - } - if (!stream->good()) - { - MITK_ERROR << "Stream not good!"; - mitkThrowException(mitk::IGTException)<<"Stream not good!"; - } - - //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters - //catch this here with a select case block (see GenerateData() method) - - int numberOfTools = 0; - - std::string tempValue = m_parentElement->Value(); - if(tempValue == "Version"){ - *stream >> *m_parentElement; + } while (nullptr != ndElem && navData.IsNotNull()); } - m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools); - - if (numberOfTools > 0) { return numberOfTools; } - return 0; -} - -void mitk::NavigationDataReaderXML::StreamInvalid(std::string message) -{ - m_StreamEnd = true; - m_ErrorMessage = message; - m_StreamValid = false; - mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; + return navDataSet; } -// -- deprecated | end diff --git a/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h index 8c6dc89b47..2209f661e6 100644 --- a/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h @@ -1,106 +1,50 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ #define MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ #include #include #include // includes for exceptions #include #include -class TiXmlElement; -class TiXmlNode; - namespace mitk { class MITKIGTIO_EXPORT NavigationDataReaderXML : public AbstractFileReader { public: NavigationDataReaderXML(); ~NavigationDataReaderXML() override; using AbstractFileReader::Read; protected: std::vector> DoRead() override; NavigationDataReaderXML(const NavigationDataReaderXML& other); mitk::NavigationDataReaderXML* Clone() const override; - NavigationDataSet::Pointer ReadNavigationDataSet(); - - /** - * \brief This method reads one line of the XML document and returns the data as a NavigationData object - * If there is a new file version another method must be added which reads this data. - * @throw mitk::IGTException Throws an exceptions if file is damaged. - */ - mitk::NavigationData::Pointer ReadVersion1(); - mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); - std::string m_FileName; - TiXmlElement* m_parentElement; - TiXmlNode* m_currentNode; - - int m_FileVersion; ///< indicates which XML encoding is used - int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document - - // -- deprecated | begin - //std::istream* m_Stream; ///< stores a pointer to the input stream - bool m_StreamEnd; ///< stores if the input stream arrived at end - bool m_StreamValid; ///< stores if the input stream is valid or not - std::string m_ErrorMessage; ///< stores the error message if the stream is invalid - - /** - * \brief Creates a stream out of the filename given by the variable m_FileName. - * The stream is then set to m_Stream. - * - * @throw mitk::IGTIOException Throws an exception if file does not exist - * @throw mitk::IGTException Throws an exception if the stream is nullptr - */ - //void CreateStreamFromFilename(); - - /** - * \brief Returns the file version out of the XML document. - * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is nullptr or not good. - * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. - */ - unsigned int GetFileVersion(std::istream* stream); - - /** - * \brief Returns the number of tracked tools out of the XML document. - * @throw Throws an exception if stream is nullptr. - * @throw Throws an exception if the input stream has an XML incompatible format. - */ - unsigned int GetNumberOfNavigationDatas(std::istream* stream); - - /** - * @brief This is a helping method which gives an error message and throws an exception with the given message. - * It can be used if a stream is found to be invalid. - * - * @throw mitk::IGTIOException Always throws an exception. - */ - void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error - // -- deprecated | end private: - NavigationDataSet::Pointer Read(std::istream* stream); - NavigationDataSet::Pointer Read(std::string fileName); + NavigationDataSet::Pointer Read(std::istream& stream); + NavigationDataSet::Pointer Read(const std::string& fileName); }; } // namespace mitk #endif // MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp index 8816d1ab38..1256f4f8f0 100644 --- a/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp @@ -1,139 +1,141 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include "mitkNavigationDataSetWriterXML.h" #include #include // Third Party -#include +#include #include #include #include mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML() : AbstractFileWriter(NavigationDataSet::GetStaticNameOfClass(), mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE(), "MITK NavigationDataSet Writer (XML)") { RegisterService(); } mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML(const mitk::NavigationDataSetWriterXML& other) : AbstractFileWriter(other) { } mitk::NavigationDataSetWriterXML::~NavigationDataSetWriterXML() { } mitk::NavigationDataSetWriterXML* mitk::NavigationDataSetWriterXML::Clone() const { return new NavigationDataSetWriterXML(*this); } void mitk::NavigationDataSetWriterXML::Write() { std::ostream* out = GetOutputStream(); if (out == nullptr) { out = new std::ofstream( GetOutputLocation().c_str() ); } mitk::NavigationDataSet::ConstPointer data = dynamic_cast (this->GetInput()); mitk::LocaleSwitch localeSwitch("C"); StreamHeader(out, data); StreamData(out, data); StreamFooter(out); // Cleanup out->flush(); delete out; } void mitk::NavigationDataSetWriterXML::StreamHeader (std::ostream* stream, mitk::NavigationDataSet::ConstPointer data) { stream->precision(10); //TODO store date and GMT time //checking if the stream is good if (stream->good()) { *stream << "" << std::endl; /**m_Stream << "" << std::endl;*/ // should be a generic version, meaning a member variable, which has the actual version *stream << " " << "GetNumberOfTools() << "\" version=\"1.0\">" << std::endl; } } void mitk::NavigationDataSetWriterXML::StreamData (std::ostream* stream, mitk::NavigationDataSet::ConstPointer data) { // For each time step in the Dataset for (auto it = data->Begin(); it != data->End(); it++) { for (std::size_t toolIndex = 0; toolIndex < it->size(); toolIndex++) { mitk::NavigationData::Pointer nd = it->at(toolIndex); - auto elem = new TiXmlElement("ND"); + tinyxml2::XMLDocument doc; + auto *elem = doc.NewElement("ND"); - elem->SetDoubleAttribute("Time", nd->GetIGTTimeStamp()); + elem->SetAttribute("Time", nd->GetIGTTimeStamp()); // elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time - elem->SetDoubleAttribute("Tool", toolIndex); - elem->SetDoubleAttribute("X", nd->GetPosition()[0]); - elem->SetDoubleAttribute("Y", nd->GetPosition()[1]); - elem->SetDoubleAttribute("Z", nd->GetPosition()[2]); - - elem->SetDoubleAttribute("QX", nd->GetOrientation()[0]); - elem->SetDoubleAttribute("QY", nd->GetOrientation()[1]); - elem->SetDoubleAttribute("QZ", nd->GetOrientation()[2]); - elem->SetDoubleAttribute("QR", nd->GetOrientation()[3]); - - elem->SetDoubleAttribute("C00", nd->GetCovErrorMatrix()[0][0]); - elem->SetDoubleAttribute("C01", nd->GetCovErrorMatrix()[0][1]); - elem->SetDoubleAttribute("C02", nd->GetCovErrorMatrix()[0][2]); - elem->SetDoubleAttribute("C03", nd->GetCovErrorMatrix()[0][3]); - elem->SetDoubleAttribute("C04", nd->GetCovErrorMatrix()[0][4]); - elem->SetDoubleAttribute("C05", nd->GetCovErrorMatrix()[0][5]); - elem->SetDoubleAttribute("C10", nd->GetCovErrorMatrix()[1][0]); - elem->SetDoubleAttribute("C11", nd->GetCovErrorMatrix()[1][1]); - elem->SetDoubleAttribute("C12", nd->GetCovErrorMatrix()[1][2]); - elem->SetDoubleAttribute("C13", nd->GetCovErrorMatrix()[1][3]); - elem->SetDoubleAttribute("C14", nd->GetCovErrorMatrix()[1][4]); - elem->SetDoubleAttribute("C15", nd->GetCovErrorMatrix()[1][5]); + elem->SetAttribute("Tool", static_cast(toolIndex)); + elem->SetAttribute("X", nd->GetPosition()[0]); + elem->SetAttribute("Y", nd->GetPosition()[1]); + elem->SetAttribute("Z", nd->GetPosition()[2]); + + elem->SetAttribute("QX", nd->GetOrientation()[0]); + elem->SetAttribute("QY", nd->GetOrientation()[1]); + elem->SetAttribute("QZ", nd->GetOrientation()[2]); + elem->SetAttribute("QR", nd->GetOrientation()[3]); + + elem->SetAttribute("C00", nd->GetCovErrorMatrix()[0][0]); + elem->SetAttribute("C01", nd->GetCovErrorMatrix()[0][1]); + elem->SetAttribute("C02", nd->GetCovErrorMatrix()[0][2]); + elem->SetAttribute("C03", nd->GetCovErrorMatrix()[0][3]); + elem->SetAttribute("C04", nd->GetCovErrorMatrix()[0][4]); + elem->SetAttribute("C05", nd->GetCovErrorMatrix()[0][5]); + elem->SetAttribute("C10", nd->GetCovErrorMatrix()[1][0]); + elem->SetAttribute("C11", nd->GetCovErrorMatrix()[1][1]); + elem->SetAttribute("C12", nd->GetCovErrorMatrix()[1][2]); + elem->SetAttribute("C13", nd->GetCovErrorMatrix()[1][3]); + elem->SetAttribute("C14", nd->GetCovErrorMatrix()[1][4]); + elem->SetAttribute("C15", nd->GetCovErrorMatrix()[1][5]); if (nd->IsDataValid()) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (nd->GetHasOrientation()) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (nd->GetHasPosition()) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); - *stream << " " << *elem << std::endl; + tinyxml2::XMLPrinter printer; + doc.Print(&printer); - delete elem; + *stream << " " << printer.CStr() << std::endl; } } } void mitk::NavigationDataSetWriterXML::StreamFooter (std::ostream* stream) { *stream << "" << std::endl; } diff --git a/Modules/LegacyIO/CMakeLists.txt b/Modules/LegacyIO/CMakeLists.txt index d9debfbd64..dfa9b7c754 100644 --- a/Modules/LegacyIO/CMakeLists.txt +++ b/Modules/LegacyIO/CMakeLists.txt @@ -1,8 +1,14 @@ mitkFunctionCheckCompilerFlags("/wd4996" CMAKE_CXX_FLAGS) mitkFunctionCheckCompilerFlags("-Wno-deprecated-declarations" CMAKE_CXX_FLAGS) MITK_CREATE_MODULE( DEPENDS MitkCore - PACKAGE_DEPENDS PRIVATE ITK|ITKIOGDCM+ITKIORAW tinyxml + PACKAGE_DEPENDS PRIVATE ITK|ITKIOGDCM+ITKIORAW tinyxml2|tinyxml2 DEPRECATED_SINCE 2014.10 ) + +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} + PRIVATE tinyxml2::tinyxml2 + ) +endif() diff --git a/Modules/LegacyIO/mitkPointSetReader.cpp b/Modules/LegacyIO/mitkPointSetReader.cpp index 7222c061e5..f33d2cc3f8 100644 --- a/Modules/LegacyIO/mitkPointSetReader.cpp +++ b/Modules/LegacyIO/mitkPointSetReader.cpp @@ -1,195 +1,195 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkPointSetReader.h" #include #include #include +#include mitk::PointSetReader::PointSetReader() { m_Success = false; } mitk::PointSetReader::~PointSetReader() { } void mitk::PointSetReader::GenerateData() { // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); m_Success = false; if (m_FileName == "") { itkWarningMacro(<< "Sorry, filename has not been set!"); return; } if (!this->CanReadFile(m_FileName.c_str())) { itkWarningMacro(<< "Sorry, can't read file " << m_FileName << "!"); return; } try { - TiXmlDocument doc(m_FileName.c_str()); - bool loadOkay = doc.LoadFile(); - if (loadOkay) + tinyxml2::XMLDocument doc; + if (tinyxml2::XML_SUCCESS == doc.LoadFile(m_FileName.c_str())) { - TiXmlHandle docHandle(&doc); + tinyxml2::XMLHandle docHandle(&doc); unsigned int pointSetCounter(0); - for (TiXmlElement *currentPointSetElement = + for (auto *currentPointSetElement = docHandle.FirstChildElement("point_set_file").FirstChildElement("point_set").ToElement(); currentPointSetElement != nullptr; currentPointSetElement = currentPointSetElement->NextSiblingElement()) { mitk::PointSet::Pointer newPointSet = mitk::PointSet::New(); if (currentPointSetElement->FirstChildElement("time_series") != nullptr) { - for (TiXmlElement *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series")->ToElement(); + for (auto *currentTimeSeries = currentPointSetElement->FirstChildElement("time_series"); currentTimeSeries != nullptr; currentTimeSeries = currentTimeSeries->NextSiblingElement()) { unsigned int currentTimeStep(0); - TiXmlElement *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id"); + auto *currentTimeSeriesID = currentTimeSeries->FirstChildElement("time_series_id"); currentTimeStep = atoi(currentTimeSeriesID->GetText()); newPointSet = this->ReadPoint(newPointSet, currentTimeSeries, currentTimeStep); } } else { newPointSet = this->ReadPoint(newPointSet, currentPointSetElement, 0); } this->SetNthOutput(pointSetCounter, newPointSet); pointSetCounter++; } } else { MITK_WARN << "XML parser error!"; } } catch (...) { MITK_ERROR << "Cannot read point set."; m_Success = false; } m_Success = true; } mitk::PointSet::Pointer mitk::PointSetReader::ReadPoint(mitk::PointSet::Pointer newPointSet, - TiXmlElement *currentTimeSeries, + const tinyxml2::XMLElement *currentTimeSeries, unsigned int currentTimeStep) { if (currentTimeSeries->FirstChildElement("point") != nullptr) { - for (TiXmlElement *currentPoint = currentTimeSeries->FirstChildElement("point")->ToElement(); + for (auto *currentPoint = currentTimeSeries->FirstChildElement("point"); currentPoint != nullptr; currentPoint = currentPoint->NextSiblingElement()) { unsigned int id(0); mitk::PointSpecificationType spec((mitk::PointSpecificationType)0); double x(0.0); double y(0.0); double z(0.0); id = atoi(currentPoint->FirstChildElement("id")->GetText()); if (currentPoint->FirstChildElement("specification") != nullptr) { spec = (mitk::PointSpecificationType)atoi(currentPoint->FirstChildElement("specification")->GetText()); } x = atof(currentPoint->FirstChildElement("x")->GetText()); y = atof(currentPoint->FirstChildElement("y")->GetText()); z = atof(currentPoint->FirstChildElement("z")->GetText()); mitk::Point3D point; mitk::FillVector3D(point, x, y, z); newPointSet->SetPoint(id, point, spec, currentTimeStep); } } else { if (currentTimeStep != newPointSet->GetTimeSteps() + 1) { newPointSet->Expand(currentTimeStep + 1); // expand time step series with empty time step } } return newPointSet; } void mitk::PointSetReader::GenerateOutputInformation() { } int mitk::PointSetReader::CanReadFile(const char *name) { std::ifstream in(name); bool isGood = in.good(); in.close(); return isGood; } bool mitk::PointSetReader::CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern) { // First check the extension if (filename == "") { // MITK_INFO<<"No filename specified."<GetNumberOfOutputs(); this->SetNumberOfIndexedOutputs(num); for (unsigned int i = prevNum; i < num; ++i) { this->SetNthOutput(i, this->MakeOutput(i).GetPointer()); } } bool mitk::PointSetReader::GetSuccess() const { return m_Success; } diff --git a/Modules/LegacyIO/mitkPointSetReader.h b/Modules/LegacyIO/mitkPointSetReader.h index eb4cc27c51..9ea21cd980 100644 --- a/Modules/LegacyIO/mitkPointSetReader.h +++ b/Modules/LegacyIO/mitkPointSetReader.h @@ -1,141 +1,145 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_POINT_SET_READER__H_ #define _MITK_POINT_SET_READER__H_ #include #include #include #include #include -#include #include +namespace tinyxml2 +{ + class XMLElement; +} + namespace mitk { /** * @brief reads xml representations of mitk::PointSets from a file * * Reader for xml files containing one or multiple xml represenations of * mitk::PointSets. If multiple mitk::PointSets are stored in one file, * these are assigned to multiple outputs of the filter. The number of point * sets which have be read can be retrieven by a call to GetNumberOfOutputs() * after the pipeline update(). * The reader is able to read the old 3D Pointsets without the "specification" and "timeseries" tags and the new 4D * Pointsets. * @note loading point sets from multiple files according to a given file pattern * is not yet supported! * * @ingroup MitkLegacyIOModule * * @deprecatedSince{2014_10} Use mitk::IOUtils or mitk::FileReaderRegistry instead. */ class MITKLEGACYIO_EXPORT PointSetReader : public PointSetSource, public FileReader { public: mitkClassMacro(PointSetReader, FileReader); itkFactorylessNewMacro(Self); itkCloneMacro(Self); /** * @brief Sets the filename of the file to be read * @param _arg the filename of the point set xml-file */ itkSetStringMacro(FileName); /** * @brief Returns the filename of the point set xml-file. * @returns the filename of the point set xml-file. */ itkGetStringMacro(FileName); /** * @warning multiple load not (yet) supported */ itkSetStringMacro(FilePrefix); /** * @warning multiple load not (yet) supported */ itkGetStringMacro(FilePrefix); /** * @warning multiple load not (yet) supported */ itkSetStringMacro(FilePattern); /** * @warning multiple load not (yet) supported */ itkGetStringMacro(FilePattern); static bool CanReadFile(const std::string filename, const std::string filePrefix, const std::string filePattern); /** * @returns whether the last read attempt was successful or not. */ bool GetSuccess() const; protected: /** * Constructor */ PointSetReader(); /** * Virtual destructor */ ~PointSetReader() override; /** * Actually reads the point sets from the given file */ void GenerateData() override; virtual mitk::PointSet::Pointer ReadPoint(mitk::PointSet::Pointer newPointSet, - TiXmlElement *currentTimeSeries, + const tinyxml2::XMLElement *currentTimeSeries, unsigned int currentTimeStep); /** * Does nothing in the current implementation */ void GenerateOutputInformation() override; /** * Resizes the output-objects according to the given number. * @param num the new number of output objects. */ virtual void ResizeOutputs(const unsigned int &num); /** * Checks if the given file has appropriate * read access. * @returns true if the file exists and may be read * or false otherwise. */ virtual int CanReadFile(const char *name); std::string m_FileName; std::string m_FilePrefix; std::string m_FilePattern; bool m_Success; }; } #endif diff --git a/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h b/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h index b3db0deccc..d26f60e0d1 100644 --- a/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h +++ b/Modules/ModelFit/include/mitkScalarListLookupTablePropertySerializer.h @@ -1,55 +1,55 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkScalarListLookupTablePropertySerializer_h #define mitkScalarListLookupTablePropertySerializer_h #include "mitkBasePropertySerializer.h" #include "mitkBaseProperty.h" #include "MitkModelFitExports.h" namespace mitk { /** * @brief Serializer for the ScalarListLookupTableProperty so it can be written and read from * file. */ class ScalarListLookupTablePropertySerializer : public BasePropertySerializer { public: mitkClassMacro(ScalarListLookupTablePropertySerializer, BasePropertySerializer); itkNewMacro(Self); - TiXmlElement* Serialize() override; - BaseProperty::Pointer Deserialize(TiXmlElement* element) override; + tinyxml2::XMLElement* Serialize(tinyxml2::XMLDocument& doc) override; + BaseProperty::Pointer Deserialize(const tinyxml2::XMLElement* element) override; protected: ScalarListLookupTablePropertySerializer() {} ~ScalarListLookupTablePropertySerializer() override {} }; namespace PropertyPersistenceSerialization { /** Serialization of a ScalarListLookupTableProperty into a XML string.*/ MITKMODELFIT_EXPORT ::std::string serializeScalarListLookupTablePropertyToXML(const mitk::BaseProperty *prop); } namespace PropertyPersistenceDeserialization { /**Deserialize a passed XML string into a ScalarListLookupTableProperty.*/ MITKMODELFIT_EXPORT mitk::BaseProperty::Pointer deserializeXMLToScalarListLookupTableProperty(const std::string &value); } } #endif // mitkScalarListLookupTablePropertySerializer_h diff --git a/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp b/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp index 751a407cce..e54b48d683 100644 --- a/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp +++ b/Modules/ModelFit/src/Common/mitkScalarListLookupTablePropertySerializer.cpp @@ -1,127 +1,129 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkScalarListLookupTableProperty.h" #include "mitkScalarListLookupTablePropertySerializer.h" +#include - -TiXmlElement* mitk::ScalarListLookupTablePropertySerializer::Serialize() +tinyxml2::XMLElement* mitk::ScalarListLookupTablePropertySerializer::Serialize(tinyxml2::XMLDocument& doc) { - const ScalarListLookupTableProperty* prop = - dynamic_cast(m_Property.GetPointer()); - - if (prop == nullptr) - { - MITK_ERROR << "Serialization: Property is NULL"; - return nullptr; - } - - ScalarListLookupTable lut = prop->GetValue(); - const ScalarListLookupTable::LookupTableType& map = lut.GetLookupTable(); - - TiXmlElement* mapElement = new TiXmlElement("ScalarListLookupTable"); - - for (ScalarListLookupTable::LookupTableType::const_iterator mapIter = map.begin(); - mapIter != map.end(); ++mapIter) - { - const ScalarListLookupTable::ValueType& list = mapIter->second; - TiXmlElement* listElement = new TiXmlElement("List"); - listElement->SetAttribute("name", mapIter->first); - - for (ScalarListLookupTable::ValueType::const_iterator listIter = list.begin(); - listIter != list.end(); ++listIter) - { - TiXmlElement* valueElement = new TiXmlElement("Element"); - valueElement->SetDoubleAttribute("value", *listIter); - listElement->LinkEndChild(valueElement); - } - - mapElement->LinkEndChild(listElement); - } - - return mapElement; + const ScalarListLookupTableProperty* prop = + dynamic_cast(m_Property.GetPointer()); + + if (prop == nullptr) + { + MITK_ERROR << "Serialization: Property is NULL"; + return nullptr; + } + + ScalarListLookupTable lut = prop->GetValue(); + const ScalarListLookupTable::LookupTableType& map = lut.GetLookupTable(); + + auto* mapElement = doc.NewElement("ScalarListLookupTable"); + + for (ScalarListLookupTable::LookupTableType::const_iterator mapIter = map.begin(); + mapIter != map.end(); ++mapIter) + { + const ScalarListLookupTable::ValueType& list = mapIter->second; + auto* listElement = doc.NewElement("List"); + listElement->SetAttribute("name", mapIter->first.c_str()); + + for (ScalarListLookupTable::ValueType::const_iterator listIter = list.begin(); + listIter != list.end(); ++listIter) + { + auto* valueElement = doc.NewElement("Element"); + valueElement->SetAttribute("value", *listIter); + listElement->InsertEndChild(valueElement); + } + + mapElement->InsertEndChild(listElement); + } + + return mapElement; } mitk::BaseProperty::Pointer -mitk::ScalarListLookupTablePropertySerializer::Deserialize(TiXmlElement* element) +mitk::ScalarListLookupTablePropertySerializer::Deserialize(const tinyxml2::XMLElement* element) { - if (!element) - { - MITK_ERROR << "Deserialization: Element is NULL"; - return nullptr; - } - - ScalarListLookupTable lut; - - for (TiXmlElement* listElement = element->FirstChildElement("List"); - listElement != nullptr; listElement = listElement->NextSiblingElement("List")) - { - std::string name; - - if (listElement->Attribute("name") != nullptr) - { - name = listElement->Attribute("name"); - } - else - { - MITK_ERROR << "Deserialization: No element with attribute 'name' found"; - return nullptr; - } - - ScalarListLookupTable::ValueType list; - - for (TiXmlElement* valueElement = listElement->FirstChildElement("Element"); - valueElement != nullptr; - valueElement = valueElement->NextSiblingElement("Element")) - { - double value; - - if (valueElement->QueryDoubleAttribute("value", &value) == TIXML_WRONG_TYPE) - { - MITK_ERROR << "Deserialization: No element with attribute 'value' found"; - return nullptr; - } - - list.push_back(value); - } - - lut.SetTableValue(name, list); - } - - return ScalarListLookupTableProperty::New(lut).GetPointer(); + if (!element) + { + MITK_ERROR << "Deserialization: Element is NULL"; + return nullptr; + } + + ScalarListLookupTable lut; + + for (auto* listElement = element->FirstChildElement("List"); + listElement != nullptr; listElement = listElement->NextSiblingElement("List")) + { + std::string name; + + if (listElement->Attribute("name") != nullptr) + { + name = listElement->Attribute("name"); + } + else + { + MITK_ERROR << "Deserialization: No element with attribute 'name' found"; + return nullptr; + } + + ScalarListLookupTable::ValueType list; + + for (auto* valueElement = listElement->FirstChildElement("Element"); + valueElement != nullptr; + valueElement = valueElement->NextSiblingElement("Element")) + { + double value; + + if (valueElement->QueryDoubleAttribute("value", &value) != tinyxml2::XML_SUCCESS) + { + MITK_ERROR << "Deserialization: No element with attribute 'value' found"; + return nullptr; + } + + list.push_back(value); + } + + lut.SetTableValue(name, list); + } + + return ScalarListLookupTableProperty::New(lut).GetPointer(); } MITK_REGISTER_SERIALIZER(ScalarListLookupTablePropertySerializer); ::std::string mitk::PropertyPersistenceSerialization::serializeScalarListLookupTablePropertyToXML( const mitk::BaseProperty *prop) { mitk::ScalarListLookupTablePropertySerializer::Pointer lutSerializer = mitk::ScalarListLookupTablePropertySerializer::New(); lutSerializer->SetProperty(prop); - auto xmlLut = lutSerializer->Serialize(); - TiXmlPrinter printer; - xmlLut->Accept(&printer); - printer.SetStreamPrinting(); - return printer.Str(); + tinyxml2::XMLDocument doc; + lutSerializer->Serialize(doc); + + tinyxml2::XMLPrinter printer; + doc.Print(&printer); + + return printer.CStr(); } mitk::BaseProperty::Pointer mitk::PropertyPersistenceDeserialization::deserializeXMLToScalarListLookupTableProperty( const std::string &value) { mitk::ScalarListLookupTablePropertySerializer::Pointer lutSerializer = mitk::ScalarListLookupTablePropertySerializer::New(); - TiXmlDocument doc; + tinyxml2::XMLDocument doc; doc.Parse(value.c_str()); return lutSerializer->Deserialize(doc.RootElement()); } diff --git a/Modules/Multilabel/autoload/IO/mitkLabelSetImageIO.cpp b/Modules/Multilabel/autoload/IO/mitkLabelSetImageIO.cpp index 0e041818c9..981ea9cf30 100644 --- a/Modules/Multilabel/autoload/IO/mitkLabelSetImageIO.cpp +++ b/Modules/Multilabel/autoload/IO/mitkLabelSetImageIO.cpp @@ -1,652 +1,648 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef __mitkLabelSetImageWriter__cpp #define __mitkLabelSetImageWriter__cpp #include "mitkLabelSetImageIO.h" #include "mitkBasePropertySerializer.h" #include "mitkIOMimeTypes.h" #include "mitkImageAccessByItk.h" #include "mitkLabelSetIOHelper.h" #include "mitkLabelSetImageConverter.h" #include #include #include #include #include #include // itk #include "itkImageFileReader.h" #include "itkImageFileWriter.h" #include "itkMetaDataDictionary.h" #include "itkMetaDataObject.h" #include "itkNrrdImageIO.h" +#include + namespace mitk { const char* const PROPERTY_NAME_TIMEGEOMETRY_TYPE = "org.mitk.timegeometry.type"; const char* const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS = "org.mitk.timegeometry.timepoints"; const char* const PROPERTY_KEY_TIMEGEOMETRY_TYPE = "org_mitk_timegeometry_type"; const char* const PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS = "org_mitk_timegeometry_timepoints"; const char* const PROPERTY_KEY_UID = "org_mitk_uid"; LabelSetImageIO::LabelSetImageIO() : AbstractFileIO(LabelSetImage::GetStaticNameOfClass(), IOMimeTypes::NRRD_MIMETYPE(), "MITK Multilabel Image") { AbstractFileWriter::SetRanking(10); AbstractFileReader::SetRanking(10); this->RegisterService(); } IFileIO::ConfidenceLevel LabelSetImageIO::GetWriterConfidenceLevel() const { if (AbstractFileIO::GetWriterConfidenceLevel() == Unsupported) return Unsupported; const auto *input = static_cast(this->GetInput()); if (input) return Supported; else return Unsupported; } void LabelSetImageIO::Write() { ValidateOutputLocation(); auto input = dynamic_cast(this->GetInput()); mitk::LocaleSwitch localeSwitch("C"); mitk::Image::Pointer inputVector = mitk::ConvertLabelSetImageToImage(input); // image write if (inputVector.IsNull()) { mitkThrow() << "Cannot write non-image data"; } itk::NrrdImageIO::Pointer nrrdImageIo = itk::NrrdImageIO::New(); // Clone the image geometry, because we might have to change it // for writing purposes BaseGeometry::Pointer geometry = inputVector->GetGeometry()->Clone(); // Check if geometry information will be lost if (inputVector->GetDimension() == 2 && !geometry->Is2DConvertable()) { MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might " "consider using Convert2Dto3DImageFilter before saving."; // set matrix to identity mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); affTrans->SetIdentity(); mitk::Vector3D spacing = geometry->GetSpacing(); mitk::Point3D origin = geometry->GetOrigin(); geometry->SetIndexToWorldTransform(affTrans); geometry->SetSpacing(spacing); geometry->SetOrigin(origin); } LocalFile localFile(this); const std::string path = localFile.GetFileName(); MITK_INFO << "Writing image: " << path << std::endl; try { // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. const unsigned int dimension = inputVector->GetDimension(); const unsigned int *const dimensions = inputVector->GetDimensions(); const mitk::PixelType pixelType = inputVector->GetPixelType(); const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); const mitk::Point3D mitkOrigin = geometry->GetOrigin(); // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, // though they are not supported in MITK itk::Vector spacing4D; spacing4D[0] = mitkSpacing[0]; spacing4D[1] = mitkSpacing[1]; spacing4D[2] = mitkSpacing[2]; spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here itk::Vector origin4D; origin4D[0] = mitkOrigin[0]; origin4D[1] = mitkOrigin[1]; origin4D[2] = mitkOrigin[2]; origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here // Set the necessary information for imageIO nrrdImageIo->SetNumberOfDimensions(dimension); nrrdImageIo->SetPixelType(pixelType.GetPixelType()); nrrdImageIo->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? static_cast(pixelType.GetComponentType()) : itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); nrrdImageIo->SetNumberOfComponents(pixelType.GetNumberOfComponents()); itk::ImageIORegion ioRegion(dimension); for (unsigned int i = 0; i < dimension; i++) { nrrdImageIo->SetDimensions(i, dimensions[i]); nrrdImageIo->SetSpacing(i, spacing4D[i]); nrrdImageIo->SetOrigin(i, origin4D[i]); mitk::Vector3D mitkDirection; mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); itk::Vector direction4D; direction4D[0] = mitkDirection[0]; direction4D[1] = mitkDirection[1]; direction4D[2] = mitkDirection[2]; // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. if (i == 3) { direction4D[3] = 1; // homogenous component } else { direction4D[3] = 0; } vnl_vector axisDirection(dimension); for (unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction4D[j] / spacing4D[i]; } nrrdImageIo->SetDirection(i, axisDirection); ioRegion.SetSize(i, inputVector->GetLargestPossibleRegion().GetSize(i)); ioRegion.SetIndex(i, inputVector->GetLargestPossibleRegion().GetIndex(i)); } // use compression if available nrrdImageIo->UseCompressionOn(); nrrdImageIo->SetIORegion(ioRegion); nrrdImageIo->SetFileName(path); // label set specific meta data char keybuffer[512]; char valbuffer[512]; sprintf(keybuffer, "modality"); sprintf(valbuffer, "org.mitk.image.multilabel"); itk::EncapsulateMetaData( nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); sprintf(keybuffer, "layers"); sprintf(valbuffer, "%1d", input->GetNumberOfLayers()); itk::EncapsulateMetaData( nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); for (unsigned int layerIdx = 0; layerIdx < input->GetNumberOfLayers(); layerIdx++) { sprintf(keybuffer, "layer_%03u", layerIdx); // layer idx sprintf(valbuffer, "%1u", input->GetNumberOfLabels(layerIdx)); // number of labels for the layer itk::EncapsulateMetaData( nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), std::string(valbuffer)); auto iter = input->GetLabelSet(layerIdx)->IteratorConstBegin(); unsigned int count(0); while (iter != input->GetLabelSet(layerIdx)->IteratorConstEnd()) { - std::unique_ptr document; - document.reset(new TiXmlDocument()); - - auto *decl = new TiXmlDeclaration("1.0", "", ""); // TODO what to write here? encoding? etc.... - document->LinkEndChild(decl); - TiXmlElement *labelElem = mitk::LabelSetIOHelper::GetLabelAsTiXmlElement(iter->second); - document->LinkEndChild(labelElem); - TiXmlPrinter printer; - printer.SetIndent(""); - printer.SetLineBreak(""); - - document->Accept(&printer); + tinyxml2::XMLDocument document; + document.InsertEndChild(document.NewDeclaration()); + auto *labelElem = mitk::LabelSetIOHelper::GetLabelAsXMLElement(document, iter->second); + document.InsertEndChild(labelElem); + tinyxml2::XMLPrinter printer; + document.Print(&printer); sprintf(keybuffer, "org.mitk.label_%03u_%05u", layerIdx, count); itk::EncapsulateMetaData( - nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), printer.Str()); + nrrdImageIo->GetMetaDataDictionary(), std::string(keybuffer), printer.CStr()); ++iter; ++count; } } // end label set specific meta data // Handle time geometry const auto* arbitraryTG = dynamic_cast(input->GetTimeGeometry()); if (arbitraryTG) { itk::EncapsulateMetaData(nrrdImageIo->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TYPE, ArbitraryTimeGeometry::GetStaticNameOfClass()); auto metaTimePoints = ConvertTimePointListToMetaDataObject(arbitraryTG); nrrdImageIo->GetMetaDataDictionary().Set(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS, metaTimePoints); } // Handle properties mitk::PropertyList::Pointer imagePropertyList = input->GetPropertyList(); for (const auto& property : *imagePropertyList->GetMap()) { mitk::CoreServicePointer propPersistenceService(mitk::CoreServices::GetPropertyPersistence()); IPropertyPersistence::InfoResultType infoList = propPersistenceService->GetInfo(property.first, GetMimeType()->GetName(), true); if (infoList.empty()) { continue; } std::string value = infoList.front()->GetSerializationFunction()(property.second); if (value == mitk::BaseProperty::VALUE_CANNOT_BE_CONVERTED_TO_STRING) { continue; } std::string key = infoList.front()->GetKey(); itk::EncapsulateMetaData(nrrdImageIo->GetMetaDataDictionary(), key, value); } // Handle UID itk::EncapsulateMetaData(nrrdImageIo->GetMetaDataDictionary(), PROPERTY_KEY_UID, input->GetUID()); ImageReadAccessor imageAccess(inputVector); nrrdImageIo->Write(imageAccess.GetData()); } catch (const std::exception &e) { mitkThrow() << e.what(); } // end image write } IFileIO::ConfidenceLevel LabelSetImageIO::GetReaderConfidenceLevel() const { if (AbstractFileIO::GetReaderConfidenceLevel() == Unsupported) return Unsupported; const std::string fileName = this->GetLocalFileName(); itk::NrrdImageIO::Pointer io = itk::NrrdImageIO::New(); io->SetFileName(fileName); io->ReadImageInformation(); itk::MetaDataDictionary imgMetaDataDictionary = io->GetMetaDataDictionary(); std::string value(""); itk::ExposeMetaData(imgMetaDataDictionary, "modality", value); if (value.compare("org.mitk.image.multilabel") == 0) { return Supported; } else return Unsupported; } std::vector LabelSetImageIO::DoRead() { mitk::LocaleSwitch localeSwitch("C"); // begin regular image loading, adapted from mitkItkImageIO itk::NrrdImageIO::Pointer nrrdImageIO = itk::NrrdImageIO::New(); Image::Pointer image = Image::New(); const unsigned int MINDIM = 2; const unsigned int MAXDIM = 4; const std::string path = this->GetLocalFileName(); MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl; // Check to see if we can read the file given the name or prefix if (path.empty()) { mitkThrow() << "Empty filename in mitk::ItkImageIO "; } // Got to allocate space for the image. Determine the characteristics of // the image. nrrdImageIO->SetFileName(path); nrrdImageIO->ReadImageInformation(); unsigned int ndim = nrrdImageIO->GetNumberOfDimensions(); if (ndim < MINDIM || ndim > MAXDIM) { MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D."; ndim = MAXDIM; } itk::ImageIORegion ioRegion(ndim); itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize(); itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex(); unsigned int dimensions[MAXDIM]; dimensions[0] = 0; dimensions[1] = 0; dimensions[2] = 0; dimensions[3] = 0; ScalarType spacing[MAXDIM]; spacing[0] = 1.0f; spacing[1] = 1.0f; spacing[2] = 1.0f; spacing[3] = 1.0f; Point3D origin; origin.Fill(0); unsigned int i; for (i = 0; i < ndim; ++i) { ioStart[i] = 0; ioSize[i] = nrrdImageIO->GetDimensions(i); if (i < MAXDIM) { dimensions[i] = nrrdImageIO->GetDimensions(i); spacing[i] = nrrdImageIO->GetSpacing(i); if (spacing[i] <= 0) spacing[i] = 1.0f; } if (i < 3) { origin[i] = nrrdImageIO->GetOrigin(i); } } ioRegion.SetSize(ioSize); ioRegion.SetIndex(ioStart); MITK_INFO << "ioRegion: " << ioRegion << std::endl; nrrdImageIO->SetIORegion(ioRegion); void *buffer = new unsigned char[nrrdImageIO->GetImageSizeInBytes()]; nrrdImageIO->Read(buffer); image->Initialize(MakePixelType(nrrdImageIO), ndim, dimensions); image->SetImportChannel(buffer, 0, Image::ManageMemory); // access direction of itk::Image and include spacing mitk::Matrix3D matrix; matrix.SetIdentity(); unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim); for (i = 0; i < itkDimMax3; ++i) for (j = 0; j < itkDimMax3; ++j) matrix[i][j] = nrrdImageIO->GetDirection(j)[i]; // re-initialize PlaneGeometry with origin and direction PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0); planeGeometry->SetOrigin(origin); planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix); // re-initialize SlicedGeometry3D SlicedGeometry3D *slicedGeometry = image->GetSlicedGeometry(0); slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2)); slicedGeometry->SetSpacing(spacing); MITK_INFO << slicedGeometry->GetCornerPoint(false, false, false); MITK_INFO << slicedGeometry->GetCornerPoint(true, true, true); // re-initialize TimeGeometry const itk::MetaDataDictionary& dictionary = nrrdImageIO->GetMetaDataDictionary(); TimeGeometry::Pointer timeGeometry; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE)) { // also check for the name because of backwards compatibility. Past code version stored with the name and not with // the key itk::MetaDataObject::ConstPointer timeGeometryTypeData; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE)) { timeGeometryTypeData = dynamic_cast*>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE)); } else { timeGeometryTypeData = dynamic_cast*>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE)); } if (timeGeometryTypeData->GetMetaDataObjectValue() == ArbitraryTimeGeometry::GetStaticNameOfClass()) { MITK_INFO << "used time geometry: " << ArbitraryTimeGeometry::GetStaticNameOfClass(); typedef std::vector TimePointVector; TimePointVector timePoints; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)); } else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)); } if (timePoints.empty()) { MITK_ERROR << "Stored timepoints are empty. Meta information seems to bee invalid. Switch to ProportionalTimeGeometry fallback"; } else if (timePoints.size() - 1 != image->GetDimension(3)) { MITK_ERROR << "Stored timepoints (" << timePoints.size() - 1 << ") and size of image time dimension (" << image->GetDimension(3) << ") do not match. Switch to ProportionalTimeGeometry fallback"; } else { ArbitraryTimeGeometry::Pointer arbitraryTimeGeometry = ArbitraryTimeGeometry::New(); TimePointVector::const_iterator pos = timePoints.begin(); auto prePos = pos++; for (; pos != timePoints.end(); ++prePos, ++pos) { arbitraryTimeGeometry->AppendNewTimeStepClone(slicedGeometry, *prePos, *pos); } timeGeometry = arbitraryTimeGeometry; } } } if (timeGeometry.IsNull()) { // Fallback. If no other valid time geometry has been created, create a ProportionalTimeGeometry MITK_INFO << "used time geometry: " << ProportionalTimeGeometry::GetStaticNameOfClass(); ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New(); propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3)); timeGeometry = propTimeGeometry; } image->SetTimeGeometry(timeGeometry); buffer = nullptr; MITK_INFO << "number of image components: " << image->GetPixelType().GetNumberOfComponents(); // end regular image loading LabelSetImage::Pointer output = ConvertImageToLabelSetImage(image); // get labels and add them as properties to the image char keybuffer[256]; unsigned int numberOfLayers = GetIntByKey(dictionary, "layers"); std::string _xmlStr; mitk::Label::Pointer label; for (unsigned int layerIdx = 0; layerIdx < numberOfLayers; layerIdx++) { sprintf(keybuffer, "layer_%03u", layerIdx); int numberOfLabels = GetIntByKey(dictionary, keybuffer); mitk::LabelSet::Pointer labelSet = mitk::LabelSet::New(); for (int labelIdx = 0; labelIdx < numberOfLabels; labelIdx++) { - TiXmlDocument doc; + tinyxml2::XMLDocument doc; sprintf(keybuffer, "label_%03u_%05d", layerIdx, labelIdx); _xmlStr = GetStringByKey(dictionary, keybuffer); - doc.Parse(_xmlStr.c_str()); + doc.Parse(_xmlStr.c_str(), _xmlStr.size()); - TiXmlElement *labelElem = doc.FirstChildElement("Label"); + auto *labelElem = doc.FirstChildElement("Label"); if (labelElem == nullptr) mitkThrow() << "Error parsing NRRD header for mitk::LabelSetImage IO"; - label = mitk::LabelSetIOHelper::LoadLabelFromTiXmlDocument(labelElem); + label = mitk::LabelSetIOHelper::LoadLabelFromXMLDocument(labelElem); if (label->GetValue() == 0) // set exterior label is needed to hold exterior information output->SetExteriorLabel(label); labelSet->AddLabel(label); labelSet->SetLayer(layerIdx); } output->AddLabelSetToLayer(layerIdx, labelSet); } for (auto iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd; ++iter) { if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string)) { const std::string& key = iter->first; std::string assumedPropertyName = key; std::replace(assumedPropertyName.begin(), assumedPropertyName.end(), '_', '.'); std::string mimeTypeName = GetMimeType()->GetName(); // Check if there is already a info for the key and our mime type. mitk::CoreServicePointer propPersistenceService(mitk::CoreServices::GetPropertyPersistence()); IPropertyPersistence::InfoResultType infoList = propPersistenceService->GetInfoByKey(key); auto predicate = [&mimeTypeName](const PropertyPersistenceInfo::ConstPointer& x) { return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName; }; auto finding = std::find_if(infoList.begin(), infoList.end(), predicate); if (finding == infoList.end()) { auto predicateWild = [](const PropertyPersistenceInfo::ConstPointer& x) { return x.IsNotNull() && x->GetMimeTypeName() == PropertyPersistenceInfo::ANY_MIMETYPE_NAME(); }; finding = std::find_if(infoList.begin(), infoList.end(), predicateWild); } PropertyPersistenceInfo::ConstPointer info; if (finding != infoList.end()) { assumedPropertyName = (*finding)->GetName(); info = *finding; } else { // we have not found anything suitable so we generate our own info auto newInfo = PropertyPersistenceInfo::New(); newInfo->SetNameAndKey(assumedPropertyName, key); newInfo->SetMimeTypeName(PropertyPersistenceInfo::ANY_MIMETYPE_NAME()); info = newInfo; } std::string value = dynamic_cast*>(iter->second.GetPointer())->GetMetaDataObjectValue(); mitk::BaseProperty::Pointer loadedProp = info->GetDeserializationFunction()(value); output->SetProperty(assumedPropertyName.c_str(), loadedProp); // Read properties should be persisted unless they are default properties // which are written anyway bool isDefaultKey = false; for (const auto& defaultKey : m_DefaultMetaDataKeys) { if (defaultKey.length() <= assumedPropertyName.length()) { // does the start match the default key if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos) { isDefaultKey = true; break; } } } if (!isDefaultKey) { propPersistenceService->AddInfo(info); } } } // Handle UID if (dictionary.HasKey(PROPERTY_KEY_UID)) { itk::MetaDataObject::ConstPointer uidData = dynamic_cast*>(dictionary.Get(PROPERTY_KEY_UID)); if (uidData.IsNotNull()) { mitk::UIDManipulator uidManipulator(output); uidManipulator.SetUID(uidData->GetMetaDataObjectValue()); } } MITK_INFO << "...finished!"; std::vector result; result.push_back(output.GetPointer()); return result; } int LabelSetImageIO::GetIntByKey(const itk::MetaDataDictionary &dic, const std::string &str) { std::vector imgMetaKeys = dic.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString(""); for (; itKey != imgMetaKeys.end(); itKey++) { itk::ExposeMetaData(dic, *itKey, metaString); if (itKey->find(str.c_str()) != std::string::npos) { return atoi(metaString.c_str()); } } return 0; } std::string LabelSetImageIO::GetStringByKey(const itk::MetaDataDictionary &dic, const std::string &str) { std::vector imgMetaKeys = dic.GetKeys(); std::vector::const_iterator itKey = imgMetaKeys.begin(); std::string metaString(""); for (; itKey != imgMetaKeys.end(); itKey++) { itk::ExposeMetaData(dic, *itKey, metaString); if (itKey->find(str.c_str()) != std::string::npos) { return metaString; } } return metaString; } LabelSetImageIO *LabelSetImageIO::IOClone() const { return new LabelSetImageIO(*this); } void LabelSetImageIO::InitializeDefaultMetaDataKeys() { this->m_DefaultMetaDataKeys.push_back("NRRD.space"); this->m_DefaultMetaDataKeys.push_back("NRRD.kinds"); this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TYPE); this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS); this->m_DefaultMetaDataKeys.push_back("ITK.InputFilterName"); this->m_DefaultMetaDataKeys.push_back("label_"); this->m_DefaultMetaDataKeys.push_back("layer_"); } } // namespace #endif //__mitkLabelSetImageWriter__cpp diff --git a/Modules/Multilabel/mitkLabel.cpp b/Modules/Multilabel/mitkLabel.cpp index b7952a6ef9..f2b6df44c5 100644 --- a/Modules/Multilabel/mitkLabel.cpp +++ b/Modules/Multilabel/mitkLabel.cpp @@ -1,299 +1,298 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkLabel.h" #include "itkProcessObject.h" -#include "tinyxml.h" #include #include #include #include const mitk::Label::PixelType mitk::Label::MAX_LABEL_VALUE = std::numeric_limits::max(); mitk::Label::Label() : PropertyList() { if (GetProperty("locked") == nullptr) SetLocked(true); if (GetProperty("visible") == nullptr) SetVisible(true); if (GetProperty("opacity") == nullptr) SetOpacity(0.6); if (GetProperty("center.coordinates") == nullptr) { mitk::Point3D pnt; pnt.SetElement(0, 0); pnt.SetElement(1, 0); pnt.SetElement(2, 0); SetCenterOfMassCoordinates(pnt); } if (GetProperty("center.index") == nullptr) { mitk::Point3D pnt; pnt.SetElement(0, 0); pnt.SetElement(1, 0); pnt.SetElement(2, 0); SetCenterOfMassIndex(pnt); } if (GetProperty("color") == nullptr) { mitk::Color col; col.Set(0, 0, 0); SetColor(col); } if (GetProperty("name") == nullptr) SetName("noName!"); if (GetProperty("value") == nullptr) SetValue(0); if (GetProperty("layer") == nullptr) SetLayer(0); DICOMSegmentationPropertyHelper::SetDICOMSegmentProperties(this); } mitk::Label::Label(const Label &other) : PropertyList(other) // copyconstructer of property List handles the coping action { auto *map = this->GetMap(); auto it = map->begin(); auto end = map->end(); for (; it != end; ++it) { itk::SimpleMemberCommand