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 #ifndef itkShapedNeighborhoodIterator_h
19 #define itkShapedNeighborhoodIterator_h
20 
21 #include <vector>
22 #include <list>
23 #include "itkConstShapedNeighborhoodIterator.h"
24 
25 namespace itk
26 {
27 /** \class ShapedNeighborhoodIterator
28  *
29  * \brief  A neighborhood iterator which can take on an arbitrary shape.
30  *
31  * \par General Information
32  * The ShapedNeighborhoodIterator is a refinement of NeighborhoodIterator which
33  * allows the user to specify which of the neighborhood elements are active and
34  * which will be ignored.  This is useful for applications which only need to
35  * work with a subset of the neighborhood around a pixel such as morphological
36  * operations or cellular automata.  This iterator can also be used, for
37  * example, to specify "cross-shaped" neighborhood where only elements along a
38  * spatial axes are significant.
39  *
40  * \par Constructing a shaped neighborhood iterator
41  * A shaped neighborhood iterator is constructed by constructing a list of
42  * active neighbor locations.  The list is called the ActiveIndexList.  The
43  * methods ActivateOffset, DeactivateOffset, and ClearActiveList are used to
44  * construct the ActiveIndexList.  The argument to Activate/DeactivateOffset is
45  * an itk::Offset which represents the ND spatial offset from the center of the
46  * neighborhood.  For example, to activate the center pixel in the neighborhood,
47  * you would do the following:
48  *
49    \code
50    using ImageType = Image<float, 3>;
51    ShapedNeighborhoodIterator<ImageType> it(radius, image, region);
52    ShapedNeighborhoodIterator<ImageType>::OffsetType offset = {{0,0,0}};
53    it.ActivateOffset(offset);
54    \endcode
55  *
56  * where radius, image, and region are as described in NeighborhoodIterator.
57  *
58  * Once a neighborhood location has been activated, iteration (operator++,
59  * operator--, operator+=, operator-=) will update the value at the active
60  * location.  Note that values at inactive locations will NOT be valid if
61  * queried.
62  *
63  * \par Accessing elements in a shaped neighborhood.
64  * To access the value at an active neighborhood location, you can use the
65  * standard GetPixel, SetPixel methods.  SetPixel is not defined for
66  * ConstShapedNeighborhoodIterator.   The class will not complain if you
67  * attempt to access a value at a non-active location, but be aware that the
68  * result will be undefined.  Error checking is not done in this case for the
69  * sake of efficiency.
70  *
71  * A second way to access active shaped neighborhood values is through a
72  * ShapedNeighborhoodIterator::Iterator or
73  * ConstShapedNeighborhoodIterator::ConstIterator.  The following example
74  * demonstrates the use of these iterators.
75  *
76    \code
77    using ImageType = Image<float, 3>;
78    ShapedNeighborhoodIterator<ImageType> it(radius, image, region);
79    .
80    .
81    .
82    it.ActivateOffset(offset1);
83    it.ActivateOffset(offset2);
84    it.ActivateOffset(offset3);
85    etc..
86    .
87    .
88    .
89    ShapedNeighborhoodIterator<ImageType>::Iterator i;
90    for (i = it.Begin(); ! i.IsAtEnd(); i++)
91    { i.Set(i.Get() + 1.0); }
92    \\ you may also use i != i.End(), but IsAtEnd() may be slightly faster.
93    \endcode
94  *
95  * You can also iterate backward through the neighbohood active list.
96  *
97    \code
98    i = it.End();
99    i--;
100    while (i != it.Begin())
101    {
102      i.Set(i.Get() + 1.0);
103      i--;
104    }
105     i.Set(i.Get() + 1.0);
106    \endcode
107  *
108  * The Get() Set() syntax was chosen versus defining operator* for these
109  * iterators because lvalue vs. rvalue context information is needed to
110  * determine whether bounds checking must take place.
111  *
112  * \sa Neighborhood
113  *
114  * \par MORE INFORMATION
115  * For a complete description of the ITK Image Iterators and their API, please
116  * see the Iterators chapter in the ITK Software Guide.  The ITK Software Guide
117  * is available in print and as a free .pdf download from https://www.itk.org.
118  *
119  * \ingroup ImageIterators
120  *
121  * \sa ImageConstIterator \sa ConditionalConstIterator
122  * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator
123  * \sa ConstSliceIterator  \sa CorrespondenceDataStructureIterator
124  * \sa FloodFilledFunctionConditionalConstIterator
125  * \sa FloodFilledImageFunctionConditionalConstIterator
126  * \sa FloodFilledImageFunctionConditionalIterator
127  * \sa FloodFilledSpatialFunctionConditionalConstIterator
128  * \sa FloodFilledSpatialFunctionConditionalIterator
129  * \sa ImageConstIterator \sa ImageConstIteratorWithIndex
130  * \sa ImageIterator \sa ImageIteratorWithIndex
131  * \sa ImageLinearConstIteratorWithIndex  \sa ImageLinearIteratorWithIndex
132  * \sa ImageRandomConstIteratorWithIndex  \sa ImageRandomIteratorWithIndex
133  * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex
134  * \sa ImageRegionExclusionConstIteratorWithIndex
135  * \sa ImageRegionExclusionIteratorWithIndex
136  * \sa ImageRegionIterator  \sa ImageRegionIteratorWithIndex
137  * \sa ImageRegionReverseConstIterator  \sa ImageRegionReverseIterator
138  * \sa ImageReverseConstIterator  \sa ImageReverseIterator
139  * \sa ImageSliceConstIteratorWithIndex  \sa ImageSliceIteratorWithIndex
140  * \sa NeighborhoodIterator \sa PathConstIterator  \sa PathIterator
141  * \sa ShapedNeighborhoodIterator  \sa SliceIterator
142  * \sa ImageConstIteratorWithIndex
143  * \ingroup ITKCommon
144  *
145  * \wiki
146  * \wikiexample{Iterators/ShapedNeighborhoodIterator_Manual,Iterate over a region of an image with a shaped neighborhood}
147  * \wikiexample{Iterators/ShapedNeighborhoodIterator,Iterate over a region of an image with a shaped neighborhood}
148  * \endwiki
149  */
150 template< typename TImage,
151           typename TBoundaryCondition = ZeroFluxNeumannBoundaryCondition< TImage >
152           >
153 class ITK_TEMPLATE_EXPORT ShapedNeighborhoodIterator:
154     public ConstShapedNeighborhoodIterator< TImage,
155                                             TBoundaryCondition >
156 {
157 public:
158   /** Extract image type information. */
159   using InternalPixelType = typename TImage::InternalPixelType;
160   using PixelType = typename TImage::PixelType;
161 
162   /** Save the image dimension. */
163   static constexpr unsigned int Dimension = TImage::ImageDimension;
164 
165   /** Standard class type aliases. */
166   using Self = ShapedNeighborhoodIterator;
167   using Superclass = ConstShapedNeighborhoodIterator< TImage,
168                                                       TBoundaryCondition>;
169 
170   /** Inherit type alias from superclass */
171   using OffsetType = typename Superclass::OffsetType;
172   using OffsetValueType = typename OffsetType::OffsetValueType;
173   using RadiusType = typename Superclass::RadiusType;
174   using SizeType = typename Superclass::SizeType;
175   using SizeValueType = typename Superclass::SizeValueType;
176   using ConstIterator = typename Superclass::ConstIterator;
177   using IndexListType = typename Superclass::IndexListType;
178   using BoundaryConditionType = typename Superclass::BoundaryConditionType;
179   using ImageBoundaryConditionPointerType = typename Superclass::ImageBoundaryConditionPointerType;
180   using NeighborhoodType = typename Superclass::NeighborhoodType;
181   using IndexType = typename Superclass::IndexType;
182   using ImageType = typename Superclass::ImageType;
183   using RegionType = typename Superclass::RegionType;
184   using IndexValueType = typename Superclass::IndexValueType;
185 
186   /** An  iterator for the ShapedNeighborhood classes. */
187   struct Iterator:public ConstIterator {
188     Iterator() = default;
IteratorIterator189     Iterator(Self *s) :
190       ConstIterator(s) {}
191 
192     ~Iterator() ITK_ITERATOR_OVERRIDE = default;
193     Iterator & operator=(const Iterator & o)
194     {
195       ConstIterator::operator=(o);
196       return *this;
197     }
198 
199     // Promote to public
SetIterator200     void Set(const PixelType & v) const
201     { ConstIterator::ProtectedSet(v); }
202   protected:
203 
204     friend Self;
205 
IteratorIterator206     Iterator( const Self *s, const typename IndexListType::const_iterator &li )
207       : ConstIterator(s,li) { }
208 
209   };
210 
211   /** Default constructor */
212   ShapedNeighborhoodIterator() = default;
213 
214   /** Virtual destructor */
215   ~ShapedNeighborhoodIterator() override = default;
216 
217   /** Constructor which establishes the region size, neighborhood, and image
218    * over which to walk. */
ShapedNeighborhoodIterator(const SizeType & radius,const ImageType * ptr,const RegionType & region)219   ShapedNeighborhoodIterator(const SizeType & radius,
220                              const ImageType *ptr,
221                              const RegionType & region
222                              ):Superclass(radius, const_cast< ImageType * >( ptr ),
223                                           region)
224   {
225   }
226 
227   // Expose the following methods from the superclass.  This is a restricted
228   // subset of the methods available for NeighborhoodIterator.
229   using Superclass::SetPixel;
230   using Superclass::SetCenterPixel;
231 
232 
233   /** Assignment operator */
234   Self & operator=(const Self & orig)
235   {
236     Superclass::operator=(orig);
237     return *this;
238   }
239 
240   /** Standard itk print method */
241   void PrintSelf(std::ostream &, Indent) const override;
242 
243   /** Returns a const iterator for the neighborhood which points to the first
244    * pixel in the neighborhood. */
Begin()245   Iterator Begin() { return Iterator(this, this->m_ActiveIndexList.begin()); }
End()246   Iterator End() { return Iterator(this, this->m_ActiveIndexList.end()); }
247 
248   using Superclass::Begin;
249   using Superclass::End;
250 
251 protected:
252 
253   friend Superclass;
254 
255   /** Copy constructor */
256   ShapedNeighborhoodIterator(const ShapedNeighborhoodIterator & o) = delete;
257 
258   using NeighborIndexType = typename Superclass::NeighborIndexType;
259 
260 };
261 } // namespace itk
262 
263 #ifndef ITK_MANUAL_INSTANTIATION
264 #include "itkShapedNeighborhoodIterator.hxx"
265 #endif
266 
267 #endif
268