/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkLevelSetEquationTermContainer_h #define itkLevelSetEquationTermContainer_h #include "itkLevelSetEquationTermBase.h" #include "itkObject.h" #include #include #include #include namespace itk { /** * \class LevelSetEquationTermContainer * \brief Class for container holding the terms of a given level set update equation * * \tparam TInputImage Input image or speed image or feature image for segmentation * \tparam TLevelSetContainer Container holding all the level set functions * * \ingroup ITKLevelSetsv4 */ template class ITK_TEMPLATE_EXPORT LevelSetEquationTermContainer : public Object { public: ITK_DISALLOW_COPY_AND_MOVE(LevelSetEquationTermContainer); using Self = LevelSetEquationTermContainer; using Pointer = SmartPointer; using ConstPointer = SmartPointer; using Superclass = Object; /** Method for creation through object factory */ itkNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(LevelSetEquationTermContainer); using TermIdType = unsigned int; using InputImageType = TInputImage; using InputImagePointer = typename InputImageType::Pointer; using LevelSetContainerType = TLevelSetContainer; using LevelSetContainerPointer = typename LevelSetContainerType::Pointer; using LevelSetType = typename LevelSetContainerType::LevelSetType; using LevelSetPointer = typename LevelSetContainerType::LevelSetPointer; using LevelSetIdentifierType = typename LevelSetContainerType::LevelSetIdentifierType; using LevelSetOutputPixelType = typename LevelSetContainerType::OutputType; using LevelSetOutputRealType = typename LevelSetContainerType::OutputRealType; using LevelSetDataType = typename LevelSetContainerType::LevelSetDataType; using LevelSetInputIndexType = typename LevelSetContainerType::InputIndexType; using LevelSetGradientType = typename LevelSetContainerType::GradientType; using LevelSetHessianType = typename LevelSetContainerType::HessianType; using TermType = LevelSetEquationTermBase; using TermPointer = typename TermType::Pointer; /** Set/Get the input image to be segmented. */ itkSetObjectMacro(Input, InputImageType); itkGetModifiableObjectMacro(Input, InputImageType); itkSetMacro(CurrentLevelSetId, LevelSetIdentifierType); itkGetMacro(CurrentLevelSetId, LevelSetIdentifierType); itkSetObjectMacro(LevelSetContainer, LevelSetContainerType); itkGetModifiableObjectMacro(LevelSetContainer, LevelSetContainerType); /** Add a term to the end of the container */ void PushTerm(TermType * iTerm); /** Replace the pointer to the term with the given id */ void AddTerm(const TermIdType & iId, TermType * iTerm); /** Get the term with the given id */ TermType * GetTerm(const TermIdType & iId); /** Get the term with the given name */ TermType * GetTerm(const std::string & iName); /** \todo */ void Initialize(const LevelSetInputIndexType & iP); /** Supply the update at a given pixel location to update the term parameters */ void UpdatePixel(const LevelSetInputIndexType & iP, const LevelSetOutputRealType & oldValue, const LevelSetOutputRealType & newValue); /** Initialize the term parameters prior to the start of an iteration */ void InitializeParameters(); /** Evaluate the term at a given pixel location */ LevelSetOutputRealType Evaluate(const LevelSetInputIndexType & iP); LevelSetOutputRealType Evaluate(const LevelSetInputIndexType & iP, const LevelSetDataType & iData); /** Update the term parameters at end of iteration */ void Update(); /** Return the CFL contribution of the current term */ LevelSetOutputRealType ComputeCFLContribution() const; void ComputeRequiredData(const LevelSetInputIndexType & iP, LevelSetDataType & ioData); protected: using MapTermContainerType = std::map; using MapTermContainerIteratorType = typename MapTermContainerType::iterator; using MapTermContainerConstIteratorType = typename MapTermContainerType::const_iterator; public: class Iterator; friend class Iterator; class ConstIterator { public: ConstIterator() = default; ConstIterator(const MapTermContainerConstIteratorType & it) : m_Iterator(it) {} ~ConstIterator() = default; ConstIterator(const Iterator & it) : m_Iterator(it.m_Iterator) {} ConstIterator & operator*() { return *this; } ConstIterator * operator->() { return this; } ConstIterator & operator++() { ++m_Iterator; return *this; } ConstIterator operator++(int) { ConstIterator tmp(*this); ++(*this); return tmp; } ConstIterator & operator--() { --m_Iterator; return *this; } ConstIterator operator--(int) { ConstIterator tmp(*this); --(*this); return tmp; } bool operator==(const Iterator & it) const { return (m_Iterator == it.m_Iterator); } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Iterator); bool operator==(const ConstIterator & it) const { return (m_Iterator == it.m_Iterator); } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(ConstIterator); TermIdType GetIdentifier() const { return m_Iterator->first; } TermType * GetTerm() const { return m_Iterator->second; } private: MapTermContainerConstIteratorType m_Iterator; friend class Iterator; }; class Iterator { public: Iterator() = default; Iterator(const MapTermContainerIteratorType & it) : m_Iterator(it) {} Iterator(const ConstIterator & it) : m_Iterator(it.m_Iterator) {} ~Iterator() = default; Iterator & operator*() { return *this; } Iterator * operator->() { return this; } Iterator & operator++() { ++m_Iterator; return *this; } Iterator operator++(int) { Iterator tmp(*this); ++(*this); return tmp; } Iterator & operator--() { --m_Iterator; return *this; } Iterator operator--(int) { Iterator tmp(*this); --(*this); return tmp; } bool operator==(const Iterator & it) const { return (m_Iterator == it.m_Iterator); } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(Iterator); bool operator==(const ConstIterator & it) const { return (m_Iterator == it.m_Iterator); } ITK_UNEQUAL_OPERATOR_MEMBER_FUNCTION(ConstIterator); TermIdType GetIdentifier() const { return m_Iterator->first; } TermType * GetTerm() const { return m_Iterator->second; } private: MapTermContainerIteratorType m_Iterator; friend class ConstIterator; }; Iterator Begin(); Iterator End(); ConstIterator Begin() const; ConstIterator End() const; protected: LevelSetEquationTermContainer(); ~LevelSetEquationTermContainer() override = default; LevelSetIdentifierType m_CurrentLevelSetId{}; LevelSetContainerPointer m_LevelSetContainer{}; InputImagePointer m_Input{}; using HashMapStringTermContainerType = std::unordered_map; HashMapStringTermContainerType m_NameContainer{}; using RequiredDataType = typename TermType::RequiredDataType; RequiredDataType m_RequiredData{}; MapTermContainerType m_Container{}; using MapCFLContainerType = std::map>; using MapCFLContainerIterator = typename MapCFLContainerType::iterator; using MapCFLContainerConstIterator = typename MapCFLContainerType::const_iterator; MapCFLContainerType m_TermContribution{}; }; } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkLevelSetEquationTermContainer.hxx" #endif #endif // itkLevelSetEquationTermContainer_h