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 itkImageRandomConstIteratorWithOnlyIndex_h
19 #define itkImageRandomConstIteratorWithOnlyIndex_h
20 
21 #include "itkImageConstIteratorWithOnlyIndex.h"
22 #include "itkMersenneTwisterRandomVariateGenerator.h"
23 
24 namespace itk
25 {
26 /** \class ImageRandomConstIteratorWithOnlyIndex
27  * \brief A multi-dimensional image iterator that visits a random set of locations
28  * within an image region, providing index information.
29  *
30  * ImageRandomConstIteratorWithOnlyIndex is a multi-dimensional iterator class that
31  * is templated over image type.  ImageRandomConstIteratorWithOnlyIndex is
32  * constrained to walk  only within the specified region. It samples random
33  * region positions at each increment or decrement.
34  *
35  * No access to image data is possible, and thus the class can be used with
36  * images of type ImageBase.
37  *
38  * ImageRandomConstIteratorWithOnlyIndex assumes a particular layout of the image data. The
39  * is arranged in a 1D array as if it were [][][][slice][row][col] with
40  * Index[0] = col, Index[1] = row, Index[2] = slice, etc.
41  *
42  * The operator++ method provides a simple syntax for walking around a region
43  * of a multidimensional image. operator++ performs a jump to a random position
44  * within the specified image region.  This is designed to facilitate the
45  * extraction of random indecies from the image.
46  *
47  * This is the typical use of this iterator in a loop:
48  *
49    \code
50 
51    ImageRandomConstIteratorWithOnlyIndex<ImageType> it( image, image->GetRequestedRegion() );
52 
53    it.SetNumberOfSamples(200);
54    it.GoToBegin();
55    while( !it.IsAtEnd() )
56    {
57      std::cout << it.GetIndex() << std::endl;
58      ++it;  // here it jumps to another random position inside the region
59     }
60 
61     \endcode
62  *
63  * or
64  *
65    \code
66 
67    ImageRandomConstIteratorWithOnlyIndex<ImageType> it( image, image->GetRequestedRegion() );
68 
69    it.SetNumberOfSamples(200);
70    it.GoToEnd();
71    while( !it.IsAtBegin() )
72    {
73      std::cout << it.GetIndex() << std::endl;
74      --it;  // here it jumps to another random position inside the region
75     }
76 
77     \endcode
78  *
79  * \warning Incrementing the iterator (++it) followed by a decrement (--it)
80  * or vice versa does not in general return the iterator to the same position.
81  *
82  * \par MORE INFORMATION
83  * For a complete description of the ITK Image Iterators and their API, please
84  * see the Iterators chapter in the ITK Software Guide.  The ITK Software Guide
85  * is available in print and as a free .pdf download from https://www.itk.org.
86  *
87  * \ingroup ImageIterators
88  *
89  * Index-only iterators:
90  *
91  * \sa ImageConstIteratorWithOnlyIndex
92  * \sa ConstNeighborhoodIteratorWithOnlyIndex
93  *
94  * Pixel data-access iterators:
95  *
96  * \sa ImageConstIterator \sa ConditionalConstIterator
97  * \sa ConstNeighborhoodIterator \sa ConstShapedNeighborhoodIterator
98  * \sa ConstSliceIterator  \sa CorrespondenceDataStructureIterator
99  * \sa FloodFilledFunctionConditionalConstIterator
100  * \sa FloodFilledImageFunctionConditionalConstIterator
101  * \sa FloodFilledImageFunctionConditionalIterator
102  * \sa FloodFilledSpatialFunctionConditionalConstIterator
103  * \sa FloodFilledSpatialFunctionConditionalIterator
104  * \sa ImageConstIterator \sa ImageConstIteratorWithIndex
105  * \sa ImageIterator \sa ImageIteratorWithIndex
106  * \sa ImageLinearConstIteratorWithIndex  \sa ImageLinearIteratorWithIndex
107  * \sa ImageRandomConstIteratorWithIndex  \sa ImageRandomIteratorWithIndex
108  * \sa ImageRegionConstIterator \sa ImageRegionConstIteratorWithIndex
109  * \sa ImageRegionExclusionConstIteratorWithIndex
110  * \sa ImageRegionExclusionIteratorWithIndex
111  * \sa ImageRegionIterator  \sa ImageRegionIteratorWithIndex
112  * \sa ImageRegionReverseConstIterator  \sa ImageRegionReverseIterator
113  * \sa ImageReverseConstIterator  \sa ImageReverseIterator
114  * \sa ImageSliceConstIteratorWithIndex  \sa ImageSliceIteratorWithIndex
115  * \sa NeighborhoodIterator \sa PathConstIterator  \sa PathIterator
116  * \sa ShapedNeighborhoodIterator  \sa SliceIterator
117  * \sa ImageConstIteratorWithIndex
118  *
119  * \ingroup ITKCommon
120  *
121  */
122 template< typename TImage >
123 class ITK_TEMPLATE_EXPORT ImageRandomConstIteratorWithOnlyIndex:public ImageConstIteratorWithOnlyIndex< TImage >
124 {
125 public:
126   /** Standard class type aliases. */
127   using Self = ImageRandomConstIteratorWithOnlyIndex;
128   using Superclass = ImageConstIteratorWithOnlyIndex< TImage >;
129 
130   /** Inherit types from the superclass */
131   using IndexType = typename Superclass::IndexType;
132   using SizeType = typename Superclass::SizeType;
133   using OffsetType = typename Superclass::OffsetType;
134   using RegionType = typename Superclass::RegionType;
135   using ImageType = typename Superclass::ImageType;
136   using IndexValueType = typename Superclass::IndexValueType;
137   using OffsetValueType = typename Superclass::OffsetValueType;
138   using SizeValueType = typename Superclass::SizeValueType;
139 
140   /** Default constructor. Needed since we provide a cast constructor. */
141   ImageRandomConstIteratorWithOnlyIndex();
142   ~ImageRandomConstIteratorWithOnlyIndex() override = default;
143 
144   /** Constructor establishes an iterator to walk a particular image and a
145    * particular region of that image. */
146   ImageRandomConstIteratorWithOnlyIndex(const ImageType *ptr, const RegionType & region);
147 
148   /** Constructor that can be used to cast from an ImageIterator to an
149    * ImageRandomConstIteratorWithOnlyIndex. Many routines return an ImageIterator, but for a
150    * particular task, you may want an ImageRandomConstIteratorWithOnlyIndex.  Rather than
151    * provide overloaded APIs that return different types of Iterators, itk
152    * returns ImageIterators and uses constructors to cast from an
153    * ImageIterator to a ImageRandomConstIteratorWithOnlyIndex. */
ImageRandomConstIteratorWithOnlyIndex(const ImageConstIteratorWithOnlyIndex<TImage> & it)154   ImageRandomConstIteratorWithOnlyIndex(const ImageConstIteratorWithOnlyIndex< TImage > & it)
155   {
156     this->ImageConstIteratorWithOnlyIndex< TImage >::operator=(it);
157   }
158 
159   /** Move an iterator to the beginning of the region. */
GoToBegin()160   void GoToBegin()
161   {
162     this->RandomJump();
163     m_NumberOfSamplesDone = 0L;
164   }
165 
166   /** Move an iterator to one position past the End of the region. */
GoToEnd()167   void GoToEnd()
168   {
169     this->RandomJump();
170     m_NumberOfSamplesDone = m_NumberOfSamplesRequested;
171   }
172 
173   /** Is the iterator at the beginning of the region? */
IsAtBegin()174   bool IsAtBegin() const
175   {
176     return ( m_NumberOfSamplesDone == 0L );
177   }
178 
179   /** Is the iterator at the end of the region? */
IsAtEnd()180   bool IsAtEnd() const
181   {
182     return ( m_NumberOfSamplesDone >= m_NumberOfSamplesRequested );
183   }
184 
185   /** Increment (prefix) the selected dimension.
186    * No bounds checking is performed. \sa GetIndex \sa operator-- */
187   Self & operator++()
188   {
189     this->RandomJump();
190     m_NumberOfSamplesDone++;
191     return *this;
192   }
193 
194   /** Decrement (prefix) the selected dimension.
195    * No bounds checking is performed. \sa GetIndex \sa operator++ */
196   Self & operator--()
197   {
198     this->RandomJump();
199     m_NumberOfSamplesDone--;
200     return *this;
201   }
202 
203   /** Set/Get number of random samples to get from the image region */
204   void SetNumberOfSamples(SizeValueType number);
205 
206   SizeValueType GetNumberOfSamples() const;
207 
208   /** Reinitialize the seed of the random number generator  */
209   void ReinitializeSeed();
210 
211   void ReinitializeSeed(int);
212 
213 private:
214   void RandomJump();
215 
216   using GeneratorPointer = typename Statistics::MersenneTwisterRandomVariateGenerator::Pointer;
217   GeneratorPointer m_Generator;
218   SizeValueType    m_NumberOfSamplesRequested;
219   SizeValueType    m_NumberOfSamplesDone;
220   SizeValueType    m_NumberOfPixelsInRegion;
221 };
222 } // end namespace itk
223 
224 #ifndef ITK_MANUAL_INSTANTIATION
225 #include "itkImageRandomConstIteratorWithOnlyIndex.hxx"
226 #endif
227 
228 #endif
229