/*========================================================================= * * 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 itkLevelSetEquationContainer_h #define itkLevelSetEquationContainer_h #include "itkObject.h" #include "itkObjectFactory.h" namespace itk { /** * \class LevelSetEquationContainer * \brief Class for holding a set of level set equations (PDEs). * * \tparam TTermContainer Container holding the terms in a level set equation * * Evolving level-set functions \f$\left\{ \phi_j \right\}_{j=1}^{M}\f$ * can be expressed as follows: * \f{eqnarray*}{ * \frac{\partial \phi_1(p)}{\partial \tau} &=& \sum\limits_{i=1}^{N_1} \alpha_{i1} * \cdot \omega_{i1}(p) \\ * \frac{\partial \phi_2(p)}{\partial \tau} &=& \sum\limits_{i=1}^{N_2} \alpha_{i2} * \cdot \omega_{i2}(p) \\ * & \vdots & \\ * \frac{\partial \phi_M(p)}{\partial \tau} &=& \sum\limits_{i=1}^{N_M} \alpha_{iM} * \cdot \omega_{iM}(p) * \f} * where \f$\omega_{iM}\f$ is a term which could depend on any of the level-set * functions \f$\left\{ \phi_j \right\}_{j=1}^{M}\f$ , the input image, * and \f$\alpha_{iM}\f$ is a weight to balance the contribution of each term * in the PDE. * * Each equation of this system of equation (PDE) is referred as an equation in * the level-set framework. Each equation \f$ equation_{j} \f$ contributes to the * evolution of the level-set function \f$ \phi_j \f$. * * \sa LevelSetEquationTerm * * \ingroup ITKLevelSetsv4 */ template class ITK_TEMPLATE_EXPORT LevelSetEquationContainer : public Object { public: ITK_DISALLOW_COPY_AND_MOVE(LevelSetEquationContainer); using Self = LevelSetEquationContainer; using Pointer = SmartPointer; using ConstPointer = SmartPointer; using Superclass = Object; /** Method for creation through object factory */ itkNewMacro(Self); /** \see LightObject::GetNameOfClass() */ itkOverrideGetNameOfClassMacro(LevelSetEquationContainer); using TermContainerType = TTermContainer; using TermContainerPointer = typename TermContainerType::Pointer; using InputImageType = typename TermContainerType::InputImageType; using InputImagePointer = typename TermContainerType::InputImagePointer; using LevelSetOutputRealType = typename TermContainerType::LevelSetOutputRealType; using LevelSetInputIndexType = typename TermContainerType::LevelSetInputIndexType; using LevelSetIdentifierType = typename TermContainerType::LevelSetIdentifierType; using LevelSetContainerType = typename TermContainerType::LevelSetContainerType; using LevelSetContainerPointer = typename TermContainerType::LevelSetContainerPointer; /** Add a equation to the system of equations in the EquationContainer map */ void AddEquation(const LevelSetIdentifierType & iId, TermContainerType * iEquation); /** Return a pointer to the equation of given id */ TermContainerType * GetEquation(const LevelSetIdentifierType & iId) const; /** Update the equation container recursively by calling update on individual equations */ void UpdateInternalEquationTerms(); /** Supply the update at a given pixel index to update the terms */ void UpdatePixel(const LevelSetInputIndexType & iP, const LevelSetOutputRealType & oldValue, const LevelSetOutputRealType & newValue); /** Initialize parameters in the terms of all the equations */ void InitializeParameters(); /** Returns the Courant-Friedrichs-Lewy (CFL) contribution * for all the equations */ LevelSetOutputRealType ComputeCFLContribution() const; /** Set/Get the input speed or feature image */ itkSetObjectMacro(Input, InputImageType); itkGetModifiableObjectMacro(Input, InputImageType); itkSetObjectMacro(LevelSetContainer, LevelSetContainerType); itkGetModifiableObjectMacro(LevelSetContainer, LevelSetContainerType); protected: using MapContainerType = std::map; using MapContainerIterator = typename MapContainerType::iterator; using MapContainerConstIterator = typename MapContainerType::const_iterator; public: class Iterator; friend class Iterator; class ConstIterator { public: ConstIterator() = default; ConstIterator(const MapContainerConstIterator & 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); LevelSetIdentifierType GetIdentifier() const { return m_Iterator->first; } TermContainerType * GetEquation() const { return m_Iterator->second; } private: MapContainerConstIterator m_Iterator; friend class Iterator; }; class Iterator { public: Iterator() = default; Iterator(const MapContainerIterator & 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); LevelSetIdentifierType GetIdentifier() const { return m_Iterator->first; } TermContainerType * GetEquation() const { return m_Iterator->second; } private: MapContainerIterator m_Iterator; friend class ConstIterator; }; Iterator Begin(); Iterator End(); ConstIterator Begin() const; ConstIterator End() const; protected: LevelSetEquationContainer() = default; ~LevelSetEquationContainer() override = default; LevelSetContainerPointer m_LevelSetContainer{}; MapContainerType m_Container{}; InputImagePointer m_Input{}; }; } // namespace itk #ifndef ITK_MANUAL_INSTANTIATION # include "itkLevelSetEquationContainer.hxx" #endif #endif // itkLevelSetEquationContainer_h