diff --git a/Modules/Core/include/mitkPoint.h b/Modules/Core/include/mitkPoint.h index 0436d5ae23..f8844cbae8 100644 --- a/Modules/Core/include/mitkPoint.h +++ b/Modules/Core/include/mitkPoint.h @@ -1,135 +1,153 @@ /*============================================================================ 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 mitkPoint_h #define mitkPoint_h #include <itkPoint.h> -#include "mitkArray.h" -#include "mitkEqual.h" -#include "mitkNumericConstants.h" +#include <mitkArray.h> +#include <mitkEqual.h> +#include <mitkNumericConstants.h> + +#include <nlohmann/json.hpp> namespace mitk { //##Documentation //##@brief enumeration of the type a point can be enum PointSpecificationType { PTUNDEFINED = 0, PTSTART, PTCORNER, PTEDGE, PTEND }; template <class TCoordRep, unsigned int NPointDimension = 3> class Point : public itk::Point<TCoordRep, NPointDimension> { public: /** Default constructor has nothing to do. */ explicit Point<TCoordRep, NPointDimension>() : itk::Point<TCoordRep, NPointDimension>() {} /** Pass-through constructors for the Array base class. */ template <typename TPointValueType> explicit Point(const Point<TPointValueType, NPointDimension> &r) : itk::Point<TCoordRep, NPointDimension>(r) { } template <typename TPointValueType> explicit Point(const TPointValueType r[NPointDimension]) : itk::Point<TCoordRep, NPointDimension>(r) { } template <typename TPointValueType> explicit Point(const TPointValueType &v) : itk::Point<TCoordRep, NPointDimension>(v) { } Point<TCoordRep, NPointDimension>(const mitk::Point<TCoordRep, NPointDimension> &r) : itk::Point<TCoordRep, NPointDimension>(r) { } Point<TCoordRep, NPointDimension>(const TCoordRep r[NPointDimension]) : itk::Point<TCoordRep, NPointDimension>(r) {} Point<TCoordRep, NPointDimension>(const TCoordRep &v) : itk::Point<TCoordRep, NPointDimension>(v) {} Point<TCoordRep, NPointDimension>(const itk::Point<TCoordRep, NPointDimension> &p) : itk::Point<TCoordRep, NPointDimension>(p) { } /** * Copies the elements from array array to this. * Note that this method will assign doubles to floats without complaining! * * @param array the array whose values shall be copied. Must overload [] operator. */ template <typename ArrayType> void FillPoint(const ArrayType &array) { itk::FixedArray<TCoordRep, NPointDimension> *thisP = dynamic_cast<itk::FixedArray<TCoordRep, NPointDimension> *>(this); mitk::FillArray<ArrayType, TCoordRep, NPointDimension>(*thisP, array); } /** * Copies the values stored in this point into the array array. * * @param array the array which should store the values of this. */ template <typename ArrayType> void ToArray(ArrayType array) const { mitk::ToArray<ArrayType, TCoordRep, NPointDimension>(array, *this); } }; + template <class TCoordRep, unsigned int NPointDimension> + void to_json(nlohmann::json& j, const Point<TCoordRep, NPointDimension>& p) + { + j = nlohmann::json::array(); + + for (size_t i = 0; i < NPointDimension; ++i) + j.push_back(p[i]); + } + + template <class TCoordRep, unsigned int NPointDimension> + void from_json(const nlohmann::json& j, Point<TCoordRep, NPointDimension>& p) + { + for (size_t i = 0; i < NPointDimension; ++i) + p[i] = j.at(i).get<TCoordRep>(); + } + typedef Point<ScalarType, 2> Point2D; typedef Point<ScalarType, 3> Point3D; typedef Point<ScalarType, 4> Point4D; typedef Point<int, 2> Point2I; typedef Point<int, 3> Point3I; typedef Point<int, 4> Point4I; /** * @ingroup MITKTestingAPI * * @param point1 Point to compare. * @param point2 Point to compare. * @param eps Tolerance for floating point comparison. * @param verbose Flag indicating detailed console output. * @return True if points are equal. */ template <typename TCoordRep, unsigned int NPointDimension> inline bool Equal(const itk::Point<TCoordRep, NPointDimension> &point1, const itk::Point<TCoordRep, NPointDimension> &point2, TCoordRep eps = mitk::eps, bool verbose = false) { bool isEqual = true; typename itk::Point<TCoordRep, NPointDimension>::VectorType diff = point1 - point2; for (unsigned int i = 0; i < NPointDimension; i++) { if (DifferenceBiggerOrEqualEps(diff[i], eps)) { isEqual = false; break; } } ConditionalOutputOfDifference(point1, point2, eps, verbose, isEqual); return isEqual; } } // namespace mitk #endif diff --git a/Modules/Core/include/mitkVector.h b/Modules/Core/include/mitkVector.h index fca4c9047d..ac111e18ee 100644 --- a/Modules/Core/include/mitkVector.h +++ b/Modules/Core/include/mitkVector.h @@ -1,239 +1,257 @@ /*============================================================================ 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 mitkVector_h #define mitkVector_h #include <itkVector.h> #include <vnl/vnl_vector.h> #include <vnl/vnl_vector_fixed.h> -#include "mitkArray.h" -#include "mitkEqual.h" -#include "mitkExceptionMacro.h" -#include "mitkNumericConstants.h" +#include <mitkArray.h> +#include <mitkEqual.h> +#include <mitkExceptionMacro.h> +#include <mitkNumericConstants.h> + +#include <nlohmann/json.hpp> namespace mitk { template <class TCoordRep, unsigned int NVectorDimension = 3> class Vector : public itk::Vector<TCoordRep, NVectorDimension> { public: /** * @brief Default constructor has nothing to do. */ explicit Vector<TCoordRep, NVectorDimension>() : itk::Vector<TCoordRep, NVectorDimension>() {} /** * @brief Copy constructor. */ explicit Vector<TCoordRep, NVectorDimension>(const mitk::Vector<TCoordRep, NVectorDimension> &r) : itk::Vector<TCoordRep, NVectorDimension>(r) { } /** Pass-through assignment operator for the Vector base class. */ Vector<TCoordRep, NVectorDimension> & operator=(const Vector<TCoordRep, NVectorDimension> & r) { itk::Vector<TCoordRep, NVectorDimension>::operator=(r); return *this; } /** * @brief Constructor to convert from itk::Vector to mitk::Vector. */ Vector<TCoordRep, NVectorDimension>(const itk::Vector<TCoordRep, NVectorDimension> &r) : itk::Vector<TCoordRep, NVectorDimension>(r) { } /** * @brief Constructor to convert an array to mitk::Vector * @param r the array. * @attention must have NVectorDimension valid arguments! */ Vector<TCoordRep, NVectorDimension>(const TCoordRep r[NVectorDimension]) : itk::Vector<TCoordRep, NVectorDimension>(r) { } /** * Constructor to initialize entire vector to one value. */ Vector<TCoordRep, NVectorDimension>(const TCoordRep &v) : itk::Vector<TCoordRep, NVectorDimension>(v) {} /** * @brief Constructor for vnl_vectors. * @throws mitk::Exception if vnl_vector.size() != NVectorDimension. */ Vector<TCoordRep, NVectorDimension>(const vnl_vector<TCoordRep> &vnlVector) : itk::Vector<TCoordRep, NVectorDimension>() { if (vnlVector.size() != NVectorDimension) mitkThrow() << "when constructing mitk::Vector from vnl_vector: sizes didn't match: mitk::Vector " << NVectorDimension << "; vnl_vector " << vnlVector.size(); for (unsigned int var = 0; (var < NVectorDimension) && (var < vnlVector.size()); ++var) { this->SetElement(var, vnlVector.get(var)); } } /** * @brief Constructor for vnl_vector_fixed. */ Vector<TCoordRep, NVectorDimension>(const vnl_vector_fixed<TCoordRep, NVectorDimension> &vnlVectorFixed) : itk::Vector<TCoordRep, NVectorDimension>() { for (unsigned int var = 0; var < NVectorDimension; ++var) { this->SetElement(var, vnlVectorFixed[var]); } }; /** * Copies the elements from array array to this. * Note that this method will assign doubles to floats without complaining! * * @param array the array whose values shall be copied. Must overload [] operator. */ template <typename ArrayType> void FillVector(const ArrayType &array) { itk::FixedArray<TCoordRep, NVectorDimension> *thisP = dynamic_cast<itk::FixedArray<TCoordRep, NVectorDimension> *>(this); mitk::FillArray<ArrayType, TCoordRep, NVectorDimension>(*thisP, array); } /** * Copies the values stored in this vector into the array array.d * * @param array the array which should store the values of this. */ template <typename ArrayType> void ToArray(ArrayType array) const { mitk::ToArray<ArrayType, TCoordRep, NVectorDimension>(array, *this); } /** * @brief User defined conversion of mitk::Vector to vnl_vector. * Note: the conversion to mitk::Vector to vnl_vector_fixed has not been implemented since this * would collide with the conversion vnl_vector to vnl_vector_fixed provided by vnl. */ operator vnl_vector<TCoordRep>() const { return this->GetVnlVector(); } }; // end mitk::Vector + template <class TCoordRep, unsigned int NVectorDimension> + void to_json(nlohmann::json &j, const Vector<TCoordRep, NVectorDimension> &v) + { + j = nlohmann::json::array(); + + for (size_t i = 0; i < NVectorDimension; ++i) + j.push_back(v[i]); + } + + template <class TCoordRep, unsigned int NVectorDimension> + void from_json(const nlohmann::json &j, Vector<TCoordRep, NVectorDimension> &v) + { + for (size_t i = 0; i < NVectorDimension; ++i) + v[i] = j.at(i).get<TCoordRep>(); + } + // convenience typedefs for often used mitk::Vector representations. typedef Vector<ScalarType, 2> Vector2D; typedef Vector<ScalarType, 3> Vector3D; typedef Vector<ScalarType, 4> Vector4D; // other vector types used in MITK typedef vnl_vector<ScalarType> VnlVector; // The equal methods to compare vectors for equality are below: /** * @ingroup MITKTestingAPI * * @param vector1 Vector to compare. * @param vector2 Vector to compare. * @param eps Tolerance for floating point comparison. * @param verbose Flag indicating detailed console output. * @return True if vectors are equal. */ template <typename TCoordRep, unsigned int NPointDimension> inline bool Equal(const itk::Vector<TCoordRep, NPointDimension> &vector1, const itk::Vector<TCoordRep, NPointDimension> &vector2, TCoordRep eps = mitk::eps, bool verbose = false) { bool isEqual = true; typename itk::Vector<TCoordRep, NPointDimension>::VectorType diff = vector1 - vector2; for (unsigned int i = 0; i < NPointDimension; i++) { if (DifferenceBiggerOrEqualEps(diff[i], eps)) { isEqual = false; break; } } ConditionalOutputOfDifference(vector1, vector2, eps, verbose, isEqual); return isEqual; } /** * @ingroup MITKTestingAPI * * @param vector1 Vector to compare. * @param vector2 Vector to compare. * @param eps Tolerance for floating point comparison. * @param verbose Flag indicating detailed console output. * @return True if vectors are equal. */ inline bool Equal(const mitk::VnlVector &vector1, const mitk::VnlVector &vector2, ScalarType eps = mitk::eps, bool verbose = false) { bool isEqual = true; mitk::VnlVector diff = vector1 - vector2; for (unsigned int i = 0; i < diff.size(); i++) { if (DifferenceBiggerOrEqualEps(diff[i], eps)) { isEqual = false; break; } } ConditionalOutputOfDifference(vector1, vector2, eps, verbose, isEqual); return isEqual; } /** * @ingroup MITKTestingAPI * * @param vector1 Vector to compare. * @param vector2 Vector to compare. * @param eps Tolerance for floating point comparison. * @param verbose Flag indicating detailed console output. * @return True if vectors are equal. */ template <typename TCoordRep, unsigned int NPointDimension> inline bool Equal(const vnl_vector_fixed<TCoordRep, NPointDimension> &vector1, const vnl_vector_fixed<TCoordRep, NPointDimension> &vector2, TCoordRep eps = mitk::eps, bool verbose = false) { vnl_vector_fixed<TCoordRep, NPointDimension> diff = vector1 - vector2; bool isEqual = true; for (unsigned int i = 0; i < diff.size(); i++) { if (DifferenceBiggerOrEqualEps(diff[i], eps)) { isEqual = false; break; } } ConditionalOutputOfDifference(vector1, vector2, eps, verbose, isEqual); return isEqual; } } // end namespace mitk #endif diff --git a/Modules/ROI/autoload/IO/src/mitkROIIO.cpp b/Modules/ROI/autoload/IO/src/mitkROIIO.cpp index 0354b844dc..6bdce335bb 100644 --- a/Modules/ROI/autoload/IO/src/mitkROIIO.cpp +++ b/Modules/ROI/autoload/IO/src/mitkROIIO.cpp @@ -1,36 +1,118 @@ /*============================================================================ 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 "mitkROIIO.h" #include <mitkROI.h> #include <mitkROIIOMimeTypes.h> +#include <nlohmann/json.hpp> + +#include <filesystem> +#include <fstream> + mitk::ROIIO::ROIIO() : AbstractFileIO(ROI::GetStaticNameOfClass(), MitkROIIOMimeTypes::ROI_MIMETYPE(), "MITK ROI") { this->RegisterService(); } std::vector<mitk::BaseData::Pointer> mitk::ROIIO::DoRead() { - std::vector<BaseData::Pointer> result; - return result; + auto *stream = this->GetInputStream(); + std::ifstream fileStream; + + if (nullptr == stream) + { + auto filename = this->GetInputLocation(); + + if (filename.empty() || !std::filesystem::exists(filename)) + mitkThrow() << "Invalid or nonexistent filename: \"" << filename << "\"!"; + + fileStream.open(filename); + + if (!fileStream.is_open()) + mitkThrow() << "Could not open file \"" << filename << "\" for reading!"; + + stream = &fileStream; + } + + nlohmann::json json; + + try + { + json = nlohmann::json::parse(*stream); + } + catch (const nlohmann::json::exception &e) + { + mitkThrow() << e.what(); + } + + if (!json.is_object()) + mitkThrow() << "Unknown file format (expected JSON object as root)!"; + + if ("MITK ROI" != json.value("FileFormat", "")) + mitkThrow() << "Unknown file format (expected \"MITK ROI\")!"; + + if (1 != json.value<int>("Version", 0)) + mitkThrow() << "Unknown file format version (expected \"1\")!"; + + auto geometry = Geometry3D::New(); + + if (json.contains("Geometry")) + { + auto jsonGeometry = json["Geometry"]; + + if (!jsonGeometry.is_object()) + mitkThrow() << "Geometry is expected to be a JSON object."; + + auto geometryType = jsonGeometry.value<std::string>("Type", "Embedded"); + + if (geometryType != "Embedded") + mitkThrow() << "Unknown geometry type \"" << geometryType << "\"!"; + + if (jsonGeometry.contains("Origin")) + geometry->SetOrigin(jsonGeometry["Origin"].get<Point3D>()); + + if (jsonGeometry.contains("Spacing")) + geometry->SetSpacing(jsonGeometry["Spacing"].get<Vector3D>()); + } + + if (!json.contains("ROIs") || !json["ROIs"].is_array()) + mitkThrow() << "ROIs array not found!"; + + std::vector<BaseData::Pointer> results; + + try + { + for (const auto& roi : json["ROIs"]) + { + auto result = ROI::New(); + result->SetGeometry(geometry); + results.push_back(result.GetPointer()); + } + } + catch (const nlohmann::json::type_error &e) + { + mitkThrow() << e.what(); + } + + return results; } void mitk::ROIIO::Write() { } mitk::ROIIO* mitk::ROIIO::IOClone() const { return new ROIIO(*this); }