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 itkSliceIterator_h
19 #define itkSliceIterator_h
20 
21 #include "itkMacro.h"
22 #include "itkIntTypes.h"
23 #include <valarray>
24 
25 namespace itk
26 {
27 /** \class SliceIterator
28  * \brief A flexible iterator for itk containers(i.e. itk::Neighborhood)
29  * that support pixel access through operator[].
30  *
31  * SliceIterator allows iteration along a std::slice through the container.
32  * A slice is a construct that defines a starting position, stride length
33  * (distance between adjacent elements), and a length.
34  *
35  * Any container with operator[] is supported.  Because it uses this interface
36  * the iterator is only as efficient as the implementation of a container's
37  * operator[] method.
38  *
39  * References:
40  * Modelled after a slice iterator proposed by Bjarne Stroustrup
41  * in C++ Programming Language, Third Edition. Bjarne Stroustrup.  Addison
42  * Wesley, Reading, MA. 1997.
43  *
44  * \ingroup Iterators
45  * \ingroup ITKCommon
46  */
47 template< typename TPixel, typename TContainer >
48 class SliceIterator
49 {
50 public:
51   /** Constructor. */
SliceIterator(TContainer * n,std::slice s)52   SliceIterator(TContainer *n, std::slice s):
53     m_ContainerPointer(n), m_Pos(0), m_Slice(s) {}
54 
55   /** Returns a SliceIterator that points to the beginning of the slice. */
Begin()56   SliceIterator Begin()
57   {
58     SliceIterator ans = *this;
59 
60     ans.m_Pos = 0;
61     return ans;
62   }
63 
64   /** Returns a SliceIterator that points to one past the end of the slice. */
End()65   SliceIterator End()
66   {
67     SliceIterator ans = *this;
68 
69     ans.m_Pos = static_cast< OffsetValueType >( m_Slice.size() );
70     return ans;
71   }
72 
73   /** Increments the iterator. */
74   SliceIterator operator++()
75   {
76     m_Pos++;
77     return *this;
78   }
79 
80   /** Increments the iterator. */
81   SliceIterator operator++(int)
82   {
83     SliceIterator ans  = *this;
84 
85     m_Pos++;
86     return ans;
87   }
88 
89   /** Returns the element at position n of the slice. Sets the
90    * iterator to point to position n. */
91   TPixel & operator[](OffsetValueType n)
92   { return this->Loc(m_Pos = n); }
93 
94   /** Dereferences the iterator, returning the value that it points
95    * to. */
96   TPixel & operator*()
97   { return Loc(m_Pos); }
98 
99   /** Returns the logical && of the boolean == of two slice iterator positions,
100    * stride, and start locations. */
101   bool operator==(const SliceIterator & orig)
102   {
103     return orig.m_Pos == this->m_Pos
104            &&   orig.m_Slice.stride() == this->m_Slice.stride()
105            &&   orig.m_Slice.start() == this->m_Slice.start();
106   }
107 
108   /** Returns the logical inverse of the boolean == of two slice iterators. */
109   bool operator!=(const SliceIterator & orig)
110   {
111     return !operator==(orig);
112   }
113 
114   /** Returns the boolean < of two slice iterator positions.  Result
115    * is only true if the slice iterators have the same stride and
116    * start location. */
117   bool operator<(const SliceIterator & orig)
118   {
119     return this->m_Pos < orig.m_Pos
120            &&   this->m_Slice.stride() == orig.m_Slice.stride()
121            &&   this->m_Slice.start() == orig.m_Slice.start();
122   }
123 
124 private:
125   /** Returns the value located at position n of the slice. */
Loc(OffsetValueType n)126   TPixel & Loc(OffsetValueType n) const
127   {
128     const auto start  = static_cast< OffsetValueType >( m_Slice.start() );
129     const auto stride = static_cast< OffsetValueType >( m_Slice.stride() );
130 
131     return ( *m_ContainerPointer )[start + n * stride];
132   }
133 
134   /** Pointer to the container referenced by the slice iterator. */
135   TContainer *m_ContainerPointer;
136 
137   /** Current position within the slice. */
138   OffsetValueType m_Pos;
139 
140   /** Slice structure information. */
141   std::slice m_Slice;
142 };
143 } // end namespace itk
144 
145 #endif
146