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 itkConstNeighborhoodIteratorWithOnlyIndex_h
19 #define itkConstNeighborhoodIteratorWithOnlyIndex_h
20 
21 #include <vector>
22 #include <cstring>
23 #include <iostream>
24 #include "itkImage.h"
25 #include "itkNeighborhood.h"
26 #include "itkMacro.h"
27 
28 namespace itk
29 {
30 /** \class ConstNeighborhoodIteratorWithOnlyIndex
31  *
32  * \brief Index-only version of ConstNeighborhoodIterator, defining iteration of a local
33  * N-dimensional neighborhood of indecies across an itk::Image or itk::ImageBase.
34  *
35  * ConstNeighborhoodIteratorWithOnlyIndex implements the index-only methods of
36  * NeighborhoodIterator. No image data is accessed, so this iterator can be used
37  * with type itk::ImageBase.  It serves as a base class from which other iterators
38  * can be derived. See NeighborhoodIterator for more complete information.
39  *
40  * The parent class itk::Neighborhood is declared with 'char' as its first
41  * template parameter, because the pixel type is not used in this class.
42  *
43  * \ingroup ImageIterators
44  *
45  * Other index-only iterators:
46  *
47  * \sa ImageConstIteratorWithOnlyIndex
48  * \sa ConstNeighborhoodIteratorWithOnlyIndex
49  *
50  * Other iterators:
51  *
52  * \sa ImageIterator \sa NeighborhoodIterator
53  *
54  * \sa Neighborhood
55  *
56  * \ingroup ITKCommon
57  *
58  */
59 template< typename TImage >
60 class ITK_TEMPLATE_EXPORT ConstNeighborhoodIteratorWithOnlyIndex:
61   public Neighborhood< char, TImage::ImageDimension >
62 {
63 public:
64 
65   /** Type used to refer to space dimensions */
66   using DimensionValueType = unsigned int;
67 
68   /** Save the image dimension. */
69   static constexpr DimensionValueType Dimension = TImage::ImageDimension;
70 
71   using DummyNeighborhoodPixelType = char;
72 
73   /** Standard class type aliases. */
74   using Self = ConstNeighborhoodIteratorWithOnlyIndex;
75   using Superclass = Neighborhood< DummyNeighborhoodPixelType, Self::Dimension >;
76 
77   /** Inherit type alias from superclass */
78   using OffsetType = typename Superclass::OffsetType;
79   using RadiusType = typename Superclass::RadiusType;
80   using SizeType = typename Superclass::SizeType;
81   using Iterator = typename Superclass::Iterator;
82   using ConstIterator = typename Superclass::ConstIterator;
83 
84   /** Typedef support for common objects */
85   using ImageType = TImage;
86   using RegionType = typename TImage::RegionType;
87   using IndexType = Index< Self::Dimension >;
88   using NeighborhoodType = Neighborhood< DummyNeighborhoodPixelType, Self::Dimension >;
89 
90   /** Type used to refer to the elements in the list of neighbor pixels. */
91   using NeighborIndexType = typename NeighborhoodType::NeighborIndexType;
92 
93   /** Default constructor */
94   ConstNeighborhoodIteratorWithOnlyIndex();
95 
96   /** Virtual destructor */
97   ~ConstNeighborhoodIteratorWithOnlyIndex() override = default;
98 
99   /** Copy constructor */
100   ConstNeighborhoodIteratorWithOnlyIndex(const ConstNeighborhoodIteratorWithOnlyIndex &);
101 
102   /** Constructor which establishes the region size, neighborhood, and image
103    * over which to walk. */
104   ConstNeighborhoodIteratorWithOnlyIndex(const SizeType & radius, const ImageType *ptr, const RegionType & region);
105 
106   /** Assignment operator */
107   Self & operator=(const Self & orig);
108 
109   /** Standard itk print method */
110   void PrintSelf(std::ostream &, Indent) const override;
111 
112   /** Computes the internal, N-d offset of a pixel array position n from
113    * (0,0, ..., 0) in the "upper-left" corner of the neighborhood. */
114   OffsetType ComputeInternalIndex(NeighborIndexType n) const;
115 
116   /** Returns the array of upper loop bounds used during iteration. */
GetBound()117   IndexType GetBound() const
118   {
119     return m_Bound;
120   }
121 
122   /** Returns the loop bound used to define the edge of a single
123    * dimension in the itk::Image region. */
GetBound(NeighborIndexType n)124   IndexValueType GetBound(NeighborIndexType n) const
125   {
126     return m_Bound[n];
127   }
128 
129   /** Returns a smartpointer to the image on which this iterator operates. */
GetImagePointer()130   const ImageType * GetImagePointer() const
131   {
132     return m_ConstImage;
133   }
134 
135   /** Returns the N-dimensional index of the iterator's position in
136    * the image. */
GetIndex()137   ITK_ITERATOR_VIRTUAL IndexType GetIndex() const ITK_ITERATOR_FINAL
138   {
139     return m_Loop;
140   }
141 
142   /** Returns the image index for neighbor pixel at offset o from the center of
143       the neighborhood. */
GetIndex(const OffsetType & o)144   ITK_ITERATOR_VIRTUAL IndexType GetIndex(const OffsetType & o) const ITK_ITERATOR_FINAL
145   {
146     return ( this->GetIndex() + o );
147   }
148 
149   /** Returns the image index for neighbor pixel at index i in the
150       neighborhood. */
GetIndex(NeighborIndexType i)151   ITK_ITERATOR_VIRTUAL IndexType GetIndex(NeighborIndexType i) const ITK_ITERATOR_FINAL
152   {
153     return ( this->GetIndex() + this->GetOffset(i) );
154   }
155 
156   /**  Returns the region of iteration. */
GetRegion()157   RegionType GetRegion() const
158   {
159     return m_Region;
160   }
161 
162   /** Returns the N-dimensional starting index of the iterator's position on
163    * the image. */
GetBeginIndex()164   IndexType GetBeginIndex() const
165   {
166     return m_BeginIndex;
167   }
168 
169   /** Returns a bounding box for the region spanned by this neighborhood
170       represented by an itk::ImageRegion */
171   RegionType GetBoundingBoxAsImageRegion() const;
172 
173   /** Method for rewinding the iterator to its beginning image index. */
174   ITK_ITERATOR_VIRTUAL void GoToBegin() ITK_ITERATOR_FINAL;
175 
176   /** Method for sending the iterator to one past the last index in its
177    * region. */
178   ITK_ITERATOR_VIRTUAL void GoToEnd() ITK_ITERATOR_FINAL;
179 
180   /** Initializes the iterator to walk a particular image and a particular
181    * region of that image. */
182   ITK_ITERATOR_VIRTUAL void Initialize(const SizeType & radius, const ImageType *ptr, const RegionType & region) ITK_ITERATOR_FINAL;
183 
184   /** Virtual method for determining whether the iterator is at the
185    * beginning of its iteration region. */
IsAtBegin()186   ITK_ITERATOR_VIRTUAL bool IsAtBegin() const ITK_ITERATOR_FINAL
187   {
188     return ( this->GetIndex() == m_BeginIndex );
189   }
190 
191   /** Virtual method for determining whether the iterator has reached the
192    * end of its iteration region. */
193   ITK_ITERATOR_VIRTUAL bool IsAtEnd() const ITK_ITERATOR_FINAL;
194 
195   /** Increments the pointers in the ConstNeighborhoodIteratorWithOnlyIndex,
196    * wraps across boundaries automatically, accounting for
197    * the disparity in the buffer size and the region size of the
198    * image. */
199   Self & operator++();
200 
201   /** Decrements the pointers in the ConstNeighborhoodIteratorWithOnlyIndex,
202    * wraps across boundaries automatically, accounting for
203    * the disparity in the buffer size and the region size of the
204    * image. */
205   Self & operator--();
206 
207   /** Returns a boolean == comparison of the current location/index
208    * of two ConstNeighborhoodIteratorWithOnlyIndexs of like
209    * dimensionality.  The radii of the iterators are ignored. */
210   bool operator==(const Self & it) const
211   {
212     return it.GetIndex() == this->GetIndex();
213   }
214 
215   /** Returns a boolean != comparison of the current location/index
216    * of two ConstNeighborhoodIteratorWithOnlyIndexs of like
217    * dimensionality.  The radii of the iterators are ignored. */
218   bool operator!=(const Self & it) const
219   {
220     return it.GetIndex() != this->GetIndex();
221   }
222 
223   /** Returns a boolean < comparison of the  current location/index of
224    * two ConstNeighborhoodIteratorWithOnlyIndexs
225    * of like dimensionality.  The radii of the iterators are ignored.
226    * The comparison progresses by dimension starting from the
227    * greatest. */
228   bool operator<(const Self & it) const;
229 
230   /** Returns a boolean <= comparison of the  current location/index of
231    * two ConstNeighborhoodIteratorWithOnlyIndexs
232    * of like dimensionality.  The radii of the iterators are ignored.
233    * The comparison progresses by dimension starting from the
234    * greatest. */
235   bool operator<=(const Self & it) const;
236 
237   /** Returns a boolean > comparison of the  current location/index of
238    * two ConstNeighborhoodIteratorWithOnlyIndexs
239    * of like dimensionality.  The radii of the iterators are ignored.
240    * The comparison progresses by dimension starting from the
241    * greatest. */
242   bool operator>(const Self & it) const;
243 
244   /** Returns a boolean >= comparison of the  current location/index of
245    * two ConstNeighborhoodIteratorWithOnlyIndexs
246    * of like dimensionality.  The radii of the iterators are ignored.
247    * The comparison progresses by dimension starting from the
248    * greatest. */
249   bool operator>=(const Self & it) const;
250 
251   /** This method positions the iterator at an indexed location in the
252    * image. SetLocation should _NOT_ be used to update the position of the
253    * iterator during iteration, only for initializing it to a position
254    * prior to iteration.  This method is not optimized for speed. */
SetLocation(const IndexType & position)255   void SetLocation(const IndexType & position)
256   {
257     this->SetLoop(position);
258   }
259 
260   /** Addition of an itk::Offset.  Note that this method does not do any bounds
261    * checking.  Adding an offset that moves the iterator out of its assigned
262    * region will produce undefined results. */
263   Self & operator+=(const OffsetType &);
264 
265   /** Subtraction of an itk::Offset. Note that this method does not do any
266    *  bounds checking.  Subtracting an offset that moves the iterator out
267    * of its assigned region will produce undefined results. */
268   Self & operator-=(const OffsetType &);
269 
270   /** Distance between two iterators */
271   OffsetType operator-(const Self & b)
272   {
273     return m_Loop - b.m_Loop;
274   }
275 
276   /** Returns false if the iterator overlaps region boundaries, true
277    * otherwise.  Also updates an internal boolean array indicating
278    * which of the iterator's faces are out of bounds. */
279   bool InBounds() const;
280 
281   /** Returns true if the neighborhood index is within region boundaries,
282    * false otherwise.
283    * If false, then internalIndex and offset are calculated. Otherwise their
284    * values are left unchanged.
285    * Also updates an internal boolean array indicating
286    * which of the iterator's faces are out of bounds.
287    * \param n - linear neighborhood index.
288    * \param internalIndex - calculated for index \c n only when the neighborhood is not
289    * completely within region boundaries.
290    * \param offset - per-dimension offsets for index n to nearest boundary index,
291    * calculate only when the neighborhood is not completely within region boundaries. */
292   bool IndexInBounds(const NeighborIndexType n, OffsetType & internalIndex, OffsetType & offset ) const;
293 
294   /** */
NeedToUseBoundaryConditionOn()295   void NeedToUseBoundaryConditionOn()
296   {
297     this->SetNeedToUseBoundaryCondition(true);
298   }
299 
NeedToUseBoundaryConditionOff()300   void NeedToUseBoundaryConditionOff()
301   {
302     this->SetNeedToUseBoundaryCondition(false);
303   }
304 
SetNeedToUseBoundaryCondition(bool b)305   void SetNeedToUseBoundaryCondition(bool b)
306   {
307     m_NeedToUseBoundaryCondition = b;
308   }
309 
GetNeedToUseBoundaryCondition()310   bool GetNeedToUseBoundaryCondition() const
311   {
312     return m_NeedToUseBoundaryCondition;
313   }
314 
315 protected:
316 
317   /** Default method for setting the coordinate location of the iterator.
318    * Loop indices correspond to the actual Image region index. */
SetLoop(const IndexType & p)319   ITK_ITERATOR_VIRTUAL void SetLoop(const IndexType & p) ITK_ITERATOR_FINAL
320   {
321     m_Loop = p; m_IsInBoundsValid = false;
322   }
323 
324   /** Virtual method for setting internal loop boundaries.  This
325    * method must be defined in each subclass because
326    * each subclass may handle loop boundaries differently. */
327   ITK_ITERATOR_VIRTUAL void SetBound(const SizeType &) ITK_ITERATOR_FINAL;
328 
329   /** Default method for setting the first index of the
330    * iteration region. */
SetBeginIndex(const IndexType & start)331   ITK_ITERATOR_VIRTUAL void SetBeginIndex(const IndexType & start) ITK_ITERATOR_FINAL
332   {
333     m_BeginIndex = start;
334   }
335 
336   /** Default method for setting the last index of the
337    * iteration region. */
338   ITK_ITERATOR_VIRTUAL void SetEndIndex() ITK_ITERATOR_FINAL;
339 
340   /** The starting index for iteration within the itk::Image region
341    * on which this ConstNeighborhoodIteratorWithOnlyIndex is defined. */
342   IndexType m_BeginIndex;
343 
344   /** An array of upper looping boundaries used during iteration. */
345   IndexType m_Bound;
346 
347   /** The image on which iteration is defined. */
348   typename ImageType::ConstPointer m_ConstImage;
349 
350   /** The end index for iteration within the itk::Image region
351    * on which this ConstNeighborhoodIteratorWithOnlyIndex is defined. */
352   IndexType m_EndIndex;
353 
354   /** Array of loop counters used during iteration. */
355   IndexType m_Loop;
356 
357   /** The region over which iteration is defined. */
358   RegionType m_Region;
359 
360   /** Denotes which of the iterators dimensional sides spill outside
361    * region of interest boundaries. */
362   mutable bool m_InBounds[Dimension];
363 
364   /** Denotes if iterator is entirely within bounds */
365   mutable bool m_IsInBounds;
366 
367   /** Is the m_InBounds and m_IsInBounds variables up to date? Set to
368    * false whenever the iterator is repositioned.  Set to true within
369    * InBounds(). */
370   mutable bool m_IsInBoundsValid;
371 
372   /** Lower threshold of in-bounds loop counter values. */
373   IndexType m_InnerBoundsLow;
374 
375   /** Upper threshold of in-bounds loop counter values. */
376   IndexType m_InnerBoundsHigh;
377 
378   /** Does the specified region need to worry about boundary conditions? */
379   bool m_NeedToUseBoundaryCondition;
380 };
381 
382 template< typename TImage >
383 inline ConstNeighborhoodIteratorWithOnlyIndex< TImage >
384 operator+(const ConstNeighborhoodIteratorWithOnlyIndex< TImage > & it,
385           const typename ConstNeighborhoodIteratorWithOnlyIndex< TImage >
386           ::OffsetType & ind)
387 {
388   ConstNeighborhoodIteratorWithOnlyIndex< TImage > ret;
389   ret = it;
390   ret += ind;
391   return ret;
392 }
393 
394 template< typename TImage >
395 inline ConstNeighborhoodIteratorWithOnlyIndex< TImage >
396 operator+(const typename ConstNeighborhoodIteratorWithOnlyIndex< TImage >
397           ::OffsetType & ind,
398           const ConstNeighborhoodIteratorWithOnlyIndex< TImage > & it)
399 {  return ( it + ind ); }
400 
401 template< typename TImage >
402 inline ConstNeighborhoodIteratorWithOnlyIndex< TImage >
403 operator-(const ConstNeighborhoodIteratorWithOnlyIndex< TImage > & it,
404           const typename ConstNeighborhoodIteratorWithOnlyIndex< TImage >
405           ::OffsetType & ind)
406 {
407   ConstNeighborhoodIteratorWithOnlyIndex< TImage > ret;
408   ret = it;
409   ret -= ind;
410   return ret;
411 }
412 } // namespace itk
413 
414 #ifndef ITK_MANUAL_INSTANTIATION
415 #include "itkConstNeighborhoodIteratorWithOnlyIndex.hxx"
416 #endif
417 
418 #endif
419