diff --git a/Modules/Core/include/mitkNodePredicateGeometry.h b/Modules/Core/include/mitkNodePredicateGeometry.h index 626da5b3ac..a0f6777ca6 100644 --- a/Modules/Core/include/mitkNodePredicateGeometry.h +++ b/Modules/Core/include/mitkNodePredicateGeometry.h @@ -1,69 +1,80 @@ /*============================================================================ 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 MITKNODEPREDICATEGEOMETRY_H_HEADER_INCLUDED_ #define MITKNODEPREDICATEGEOMETRY_H_HEADER_INCLUDED_ #include "mitkNodePredicateBase.h" #include "mitkBaseGeometry.h" #include "mitkTimeGeometry.h" namespace mitk { class BaseData; /**Documentation @brief Predicate that evaluates if the given DataNode's data object has the same geometry (in terms of spacing, origin, orientation) like - the reference geometry. One can either check the whole time geometry of + the reference geometry. + + One can either check the whole time geometry of the date node by defining a referenc time geometry or check against one given reference base geometry. If the predicate should check against a base geometry, you can specify the timepoint of the data's time geometry that should be checked. If no timepoint is defined the predicate will evaluate the data geometry in the first timestep. Evaluates to "false" for unsupported or undefined data objects/geometries. + + On can specify the tolerance/precesion of the check via SetCheckPrecision(). + @remark The default tolerance is 1e-6 and therefore not as strict as mitk::eps. The reason is, + that, for the typicale usage of the node predicate, mitk::eps would be to pedantic. We + often encounter floating point differences and practically it makes no difference e.g. + if two images differ something like 0.000001 mm in size or spacing @ingroup DataStorage */ class MITKCORE_EXPORT NodePredicateGeometry : public NodePredicateBase { public: mitkClassMacro(NodePredicateGeometry, NodePredicateBase); mitkNewMacro1Param(NodePredicateGeometry, const TimeGeometry*); mitkNewMacro1Param(NodePredicateGeometry, const BaseGeometry*); mitkNewMacro2Param(NodePredicateGeometry, const BaseGeometry*, TimePointType); itkSetMacro(CheckPrecision, mitk::ScalarType); itkGetMacro(CheckPrecision, mitk::ScalarType); ~NodePredicateGeometry() override; bool CheckNode(const mitk::DataNode *node) const override; protected: /**Constructor that is used configures the predicate to check the reference geometry against the first data timepoint.*/ NodePredicateGeometry(const BaseGeometry* refGeometry); /**Constructor allows to define the timepoint that should be evaluated against the reference.*/ NodePredicateGeometry(const BaseGeometry* refGeometry, TimePointType relevantTimePoint); /**Constructor that is used configures the predicate to check against the whole time geometry.*/ NodePredicateGeometry(const TimeGeometry* refGeometry); BaseGeometry::ConstPointer m_RefGeometry; TimeGeometry::ConstPointer m_RefTimeGeometry; TimePointType m_TimePoint; /**Indicates if m_TimePoint should be regarded or always the first timestep should be used.*/ bool m_UseTimePoint; /**Precision that should be used for the equal checks.*/ mitk::ScalarType m_CheckPrecision; }; + + constexpr double NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION = 1e-6; + } // namespace mitk #endif /* MITKNodePredicateGeometry_H_HEADER_INCLUDED_ */ diff --git a/Modules/Core/include/mitkNodePredicateSubGeometry.h b/Modules/Core/include/mitkNodePredicateSubGeometry.h index dbb6dcc602..fb8f19fd63 100644 --- a/Modules/Core/include/mitkNodePredicateSubGeometry.h +++ b/Modules/Core/include/mitkNodePredicateSubGeometry.h @@ -1,68 +1,74 @@ /*============================================================================ 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 MITKNODEPREDICATESUBGEOMETRY_H_HEADER_INCLUDED_ #define MITKNODEPREDICATESUBGEOMETRY_H_HEADER_INCLUDED_ #include "mitkNodePredicateBase.h" #include "mitkBaseGeometry.h" #include "mitkTimeGeometry.h" namespace mitk { class BaseData; /**Documentation @brief Predicate that evaluates if the given DataNode's data object has a geometry that is a sub geomety of the reference geometry. Sub geometry means that both geometries have the same voxel grid (same spacing, same axes, orgin is on voxel grid), but the bounding box of the checked geometry is contained or equal to the bounding box of the reference geometry.\n One can either check the whole time geometry of the data node by defining a referenc time geometry or check against one given2 reference base geometry. If the predicate should check against a base geometry, you can specify the timepoint of the data's time geometry that should be checked. If no timepoint is defined the predicate will evaluate the data geometry in the first timestep. Evaluates to "false" for unsupported or undefined data objects/geometries. + + On can specify the tolerance/precesion of the check via SetCheckPrecision(). + @remark The default tolerance is the same like for NodePredicateGeometry and therefore not as strict as mitk::eps. The reason is, + that, for the typicale usage of the node predicate, mitk::eps would be to pedantic. We + often encounter floating point differences and practically it makes no difference e.g. + if two images differ something like 0.000001 mm in size or spacing @ingroup DataStorage */ class MITKCORE_EXPORT NodePredicateSubGeometry : public NodePredicateBase { public: mitkClassMacro(NodePredicateSubGeometry, NodePredicateBase); mitkNewMacro1Param(NodePredicateSubGeometry, const BaseGeometry*); mitkNewMacro2Param(NodePredicateSubGeometry, const BaseGeometry*, TimePointType); itkSetMacro(CheckPrecision, mitk::ScalarType); itkGetMacro(CheckPrecision, mitk::ScalarType); ~NodePredicateSubGeometry() override; bool CheckNode(const mitk::DataNode *node) const override; protected: /**Constructor that is used configures the predicate to check the reference geometry against the first data timepoint.*/ NodePredicateSubGeometry(const BaseGeometry* refGeometry); /**Constructor allows to define the timepoint that should be evaluated against the reference.*/ NodePredicateSubGeometry(const BaseGeometry* refGeometry, TimePointType relevantTimePoint); BaseGeometry::ConstPointer m_RefGeometry; TimePointType m_TimePoint; /**Indicates if m_TimePoint should be regarded or always the first timestep should be used.*/ bool m_UseTimePoint; /**Precision that should be used for the equal checks.*/ mitk::ScalarType m_CheckPrecision; }; } // namespace mitk #endif diff --git a/Modules/Core/src/DataManagement/mitkNodePredicateGeometry.cpp b/Modules/Core/src/DataManagement/mitkNodePredicateGeometry.cpp index 7aae96581c..13bdc740c8 100644 --- a/Modules/Core/src/DataManagement/mitkNodePredicateGeometry.cpp +++ b/Modules/Core/src/DataManagement/mitkNodePredicateGeometry.cpp @@ -1,67 +1,67 @@ /*============================================================================ 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 "mitkNodePredicateGeometry.h" #include "mitkDataNode.h" #include "mitkImage.h" mitk::NodePredicateGeometry::NodePredicateGeometry(const BaseGeometry* refGeometry, TimePointType relevantTimePoint) - : m_RefGeometry(refGeometry), m_RefTimeGeometry(nullptr), m_TimePoint(relevantTimePoint), m_UseTimePoint(true), m_CheckPrecision(mitk::eps) + : m_RefGeometry(refGeometry), m_RefTimeGeometry(nullptr), m_TimePoint(relevantTimePoint), m_UseTimePoint(true), m_CheckPrecision(NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION) { if (m_RefGeometry.IsNull()) mitkThrow() << "Invalid constructor initialization. Reference base geometry instance is nullptr pointer."; } mitk::NodePredicateGeometry::NodePredicateGeometry(const BaseGeometry* refGeometry) - : m_RefGeometry(refGeometry), m_RefTimeGeometry(nullptr), m_TimePoint(0), m_UseTimePoint(false), m_CheckPrecision(mitk::eps) + : m_RefGeometry(refGeometry), m_RefTimeGeometry(nullptr), m_TimePoint(0), m_UseTimePoint(false), m_CheckPrecision(NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION) { if (m_RefGeometry.IsNull()) mitkThrow() << "Invalid constructor initialization. Reference base geometry instance is nullptr pointer."; } mitk::NodePredicateGeometry::NodePredicateGeometry(const TimeGeometry* refGeometry) - : m_RefGeometry(nullptr), m_RefTimeGeometry(refGeometry), m_TimePoint(0), m_UseTimePoint(false), m_CheckPrecision(mitk::eps) + : m_RefGeometry(nullptr), m_RefTimeGeometry(refGeometry), m_TimePoint(0), m_UseTimePoint(false), m_CheckPrecision(NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION) { if (m_RefTimeGeometry.IsNull()) mitkThrow() << "Invalid constructor initialization. Reference base geometry instance is nullptr pointer."; } mitk::NodePredicateGeometry::~NodePredicateGeometry() { } bool mitk::NodePredicateGeometry::CheckNode(const mitk::DataNode *node) const { if (node == nullptr) mitkThrow() << "NodePredicateGeometry: invalid node"; mitk::BaseData *data = node->GetData(); if (data) { if (m_RefGeometry.IsNotNull()) { //check only one time point. mitk::BaseGeometry::Pointer testGeometry = data->GetGeometry(); if (this->m_UseTimePoint) { testGeometry = data->GetTimeGeometry()->GetGeometryForTimePoint(m_TimePoint); } if (testGeometry) { return Equal(*testGeometry, *m_RefGeometry, this->m_CheckPrecision, false); } } else { //check whole time geometry return Equal(*data->GetTimeGeometry(), *m_RefTimeGeometry, this->m_CheckPrecision, false); } } return false; } diff --git a/Modules/Core/src/DataManagement/mitkNodePredicateSubGeometry.cpp b/Modules/Core/src/DataManagement/mitkNodePredicateSubGeometry.cpp index fe55cc35a9..0826e927ac 100644 --- a/Modules/Core/src/DataManagement/mitkNodePredicateSubGeometry.cpp +++ b/Modules/Core/src/DataManagement/mitkNodePredicateSubGeometry.cpp @@ -1,57 +1,58 @@ /*============================================================================ 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 "mitkNodePredicateSubGeometry.h" #include "mitkDataNode.h" #include "mitkImage.h" +#include "mitkNodePredicateGeometry.h" mitk::NodePredicateSubGeometry::NodePredicateSubGeometry(const BaseGeometry* refGeometry, TimePointType relevantTimePoint) - : m_RefGeometry(refGeometry), m_TimePoint(relevantTimePoint), m_UseTimePoint(true), m_CheckPrecision(mitk::eps) + : m_RefGeometry(refGeometry), m_TimePoint(relevantTimePoint), m_UseTimePoint(true), m_CheckPrecision(mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION) { if (m_RefGeometry.IsNull()) mitkThrow() << "Invalid constructor initialization. Reference base geometry instance is nullptr pointer."; } mitk::NodePredicateSubGeometry::NodePredicateSubGeometry(const BaseGeometry* refGeometry) - : m_RefGeometry(refGeometry), m_TimePoint(0), m_UseTimePoint(false), m_CheckPrecision(mitk::eps) + : m_RefGeometry(refGeometry), m_TimePoint(0), m_UseTimePoint(false), m_CheckPrecision(mitk::NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_PRECISION) { if (m_RefGeometry.IsNull()) mitkThrow() << "Invalid constructor initialization. Reference base geometry instance is nullptr pointer."; } mitk::NodePredicateSubGeometry::~NodePredicateSubGeometry() { } bool mitk::NodePredicateSubGeometry::CheckNode(const mitk::DataNode *node) const { if (node == nullptr) mitkThrow() << "NodePredicateSubGeometry: invalid node"; const auto *data = node->GetData(); if (data) { if (nullptr != data && m_RefGeometry.IsNotNull()) { //check only one time point. mitk::BaseGeometry::Pointer testGeometry = data->GetGeometry(); if (this->m_UseTimePoint) { testGeometry = data->GetTimeGeometry()->GetGeometryForTimePoint(m_TimePoint); } if (testGeometry.IsNotNull()) { return IsSubGeometry(*testGeometry, *m_RefGeometry, this->m_CheckPrecision, false); } } } return false; }