1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #ifndef itkLevelSetEquationContainer_h
20 #define itkLevelSetEquationContainer_h
21 
22 #include "itkObject.h"
23 #include "itkObjectFactory.h"
24 
25 namespace itk
26 {
27 /**
28  *  \class LevelSetEquationContainer
29  *  \brief Class for holding a set of level set equations (PDEs).
30  *
31  *  \tparam TTermContainer Container holding the terms in a level set equation
32  *
33  *  Evolving level-set functions \f$\left\{ \phi_j \right\}_{j=1}^{M}\f$
34  *  can be expressed as follows:
35  *  \f{eqnarray*}{
36  *  \frac{\partial \phi_1(p)}{\partial \tau} &=& \sum\limits_{i=1}^{N_1} \alpha_{i1}
37  *  \cdot \omega_{i1}(p) \\
38  *  \frac{\partial \phi_2(p)}{\partial \tau} &=& \sum\limits_{i=1}^{N_2} \alpha_{i2}
39  *  \cdot \omega_{i2}(p) \\
40  *  & \vdots & \\
41  *  \frac{\partial \phi_M(p)}{\partial \tau} &=& \sum\limits_{i=1}^{N_M} \alpha_{iM}
42  *  \cdot \omega_{iM}(p)
43  *  \f}
44  *  where \f$\omega_{iM}\f$ is a term which could depend on any of the level-set
45  *  functions \f$\left\{ \phi_j \right\}_{j=1}^{M}\f$ , the input image,
46  *  and \f$\alpha_{iM}\f$ is a weight to balance the contribution of each term
47  *  in the PDE.
48  *
49  *  Each equation of this system of equation (PDE) is referred as an equation in
50  *  the level-set framework. Each equation \f$ equation_{j} \f$ contributes to the
51  *  evolution of the level-set function \f$ \phi_j \f$.
52  *
53  *  \sa LevelSetEquationTerm
54  *
55  *  \ingroup ITKLevelSetsv4
56  */
57 template< typename TTermContainer >
58 class ITK_TEMPLATE_EXPORT LevelSetEquationContainer : public Object
59 {
60 public:
61   ITK_DISALLOW_COPY_AND_ASSIGN(LevelSetEquationContainer);
62 
63   using Self = LevelSetEquationContainer;
64   using Pointer = SmartPointer< Self >;
65   using ConstPointer = SmartPointer< const Self >;
66   using Superclass = Object;
67 
68   /** Method for creation through object factory */
69   itkNewMacro( Self );
70 
71   /** Run-time type information */
72   itkTypeMacro( LevelSetEquationContainer, Object );
73 
74   using TermContainerType = TTermContainer;
75   using TermContainerPointer = typename TermContainerType::Pointer;
76 
77   using InputImageType = typename TermContainerType::InputImageType;
78   using InputImagePointer = typename TermContainerType::InputImagePointer;
79 
80   using LevelSetOutputRealType = typename TermContainerType::LevelSetOutputRealType;
81   using LevelSetInputIndexType = typename TermContainerType::LevelSetInputIndexType;
82 
83   using LevelSetIdentifierType = typename TermContainerType::LevelSetIdentifierType;
84   using LevelSetContainerType = typename TermContainerType::LevelSetContainerType;
85   using LevelSetContainerPointer = typename TermContainerType::LevelSetContainerPointer;
86 
87   /** Add a equation to the system of equations in the EquationContainer map */
88   void AddEquation( const LevelSetIdentifierType& iId, TermContainerType * iEquation );
89 
90   /** Return a pointer to the equation of given id */
91   TermContainerType * GetEquation( const LevelSetIdentifierType& iId ) const;
92 
93   /** Update the equation container recursively by calling update on individual equations */
94   void UpdateInternalEquationTerms();
95 
96   /** Supply the update at a given pixel index to update the terms */
97   void UpdatePixel( const LevelSetInputIndexType & iP,
98                     const LevelSetOutputRealType & oldValue,
99                     const LevelSetOutputRealType & newValue );
100 
101   /** Initialize parameters in the terms of all the equations */
102   void InitializeParameters();
103 
104   /** Returns the Courant-Friedrichs-Lewy (CFL) contribution
105    * for all the equations */
106   LevelSetOutputRealType ComputeCFLContribution() const;
107 
108   /** Set/Get the input speed or feature image */
109   itkSetObjectMacro( Input, InputImageType );
110   itkGetModifiableObjectMacro(Input, InputImageType );
111 
112   itkSetObjectMacro( LevelSetContainer, LevelSetContainerType );
113   itkGetModifiableObjectMacro(LevelSetContainer, LevelSetContainerType );
114 
115 protected:
116   using MapContainerType = std::map< LevelSetIdentifierType, TermContainerPointer >;
117   using MapContainerIterator = typename MapContainerType::iterator;
118   using MapContainerConstIterator = typename MapContainerType::const_iterator;
119 
120 public:
121   class Iterator;
122   friend class Iterator;
123 
124   class ConstIterator
125   {
126   public:
127     ConstIterator() = default;
ConstIterator(const MapContainerConstIterator & it)128     ConstIterator( const MapContainerConstIterator& it ) : m_Iterator( it ) {}
129     ~ConstIterator() = default;
ConstIterator(const Iterator & it)130     ConstIterator( const Iterator& it ) : m_Iterator( it.m_Iterator ) {}
131     ConstIterator & operator * () { return *this; }
132     ConstIterator * operator->() { return this; }
133     ConstIterator & operator++()
134       {
135       ++m_Iterator;
136       return *this;
137       }
138     ConstIterator operator++(int)
139       {
140       ConstIterator tmp( *this );
141       ++(*this);
142       return tmp;
143       }
144     ConstIterator & operator--()
145       {
146       --m_Iterator;
147       return *this;
148       }
149     ConstIterator operator--(int)
150       {
151       ConstIterator tmp( *this );
152       --(*this);
153       return tmp;
154       }
155     bool operator == (const Iterator& it) const
156       {
157       return (m_Iterator == it.m_Iterator);
158       }
159     bool operator != (const Iterator& it) const
160       {
161       return (m_Iterator != it.m_Iterator);
162       }
163     bool operator == (const ConstIterator& it) const
164       {
165       return (m_Iterator == it.m_Iterator);
166       }
167     bool operator != (const ConstIterator& it) const
168       {
169       return (m_Iterator != it.m_Iterator);
170       }
GetIdentifier()171     LevelSetIdentifierType GetIdentifier() const
172       {
173       return m_Iterator->first;
174       }
175 
GetEquation()176     TermContainerType * GetEquation() const
177       {
178       return m_Iterator->second;
179       }
180   private:
181     MapContainerConstIterator m_Iterator;
182     friend class Iterator;
183   };
184 
185   class Iterator
186   {
187   public:
188     Iterator() = default;
Iterator(const MapContainerIterator & it)189     Iterator( const MapContainerIterator& it ) : m_Iterator( it ) {}
Iterator(const ConstIterator & it)190     Iterator( const ConstIterator& it ) : m_Iterator( it.m_Iterator ) {}
191     ~Iterator() = default;
192 
193     Iterator & operator * () { return *this; }
194     Iterator * operator ->() { return this; }
195 
196     Iterator & operator++()
197       {
198       ++m_Iterator;
199       return *this;
200       }
201     Iterator operator++(int)
202       {
203       Iterator tmp( *this );
204       ++(*this);
205       return tmp;
206       }
207     Iterator & operator--()
208       {
209       --m_Iterator;
210       return *this;
211       }
212     Iterator operator--(int)
213       {
214       Iterator tmp( *this );
215       --(*this);
216       return tmp;
217       }
218 
219     bool operator==(const Iterator& it) const
220       {
221       return (m_Iterator==it.m_Iterator);
222       }
223     bool operator!=(const Iterator& it) const
224       {
225       return (m_Iterator!=it.m_Iterator);
226       }
227     bool operator==(const ConstIterator& it)const
228       {
229       return (m_Iterator == it.m_Iterator);
230       }
231     bool operator!=(const ConstIterator& it)const
232       {
233       return (m_Iterator != it.m_Iterator);
234       }
GetIdentifier()235     LevelSetIdentifierType GetIdentifier() const
236       {
237       return m_Iterator->first;
238       }
239 
GetEquation()240     TermContainerType * GetEquation() const
241       {
242       return m_Iterator->second;
243       }
244   private:
245     MapContainerIterator m_Iterator;
246     friend class ConstIterator;
247   };
248 
249   Iterator Begin();
250   Iterator End();
251 
252   ConstIterator Begin() const;
253   ConstIterator End() const;
254 
255 protected:
256 
257   LevelSetEquationContainer() = default;
258   ~LevelSetEquationContainer() override = default;
259 
260   LevelSetContainerPointer  m_LevelSetContainer;
261   MapContainerType          m_Container;
262   InputImagePointer         m_Input;
263 };
264 }
265 
266 #ifndef ITK_MANUAL_INSTANTIATION
267 #include "itkLevelSetEquationContainer.hxx"
268 #endif
269 
270 #endif // itkLevelSetEquationContainer_h
271