DGtal  1.5.beta
ArrayImageIterator.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /*
18  * @file ArrayImageIterator.ih
19  * @author Roland Denis (\c roland.denis@univ-smb.fr )
20  * LAboratory of MAthematics - LAMA (CNRS, UMR 5127), University of Savoie, France
21  *
22  * @date 2015/06/19
23  *
24  * This file is part of the DGtal library.
25  */
26 
27 
28 //////////////////////////////////////////////////////////////////////////////
29 #include <DGtal/base/Assert.h>
30 //////////////////////////////////////////////////////////////////////////////
31 
32 ///////////////////////////////////////////////////////////////////////////////
33 // IMPLEMENTATION of inline methods.
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 ///////////////////////////////////////////////////////////////////////////////
37 // ----------------------- Standard services ------------------------------
38 
39 
40 //------------------------------------------------------------------------------
41 /// Default constructor.
42 template <typename TIterableClass>
43 DGtal::ArrayImageIterator<TIterableClass>::
44 ArrayImageIterator()
45  : myIterableClassPtr(nullptr)
46 {}
47 
48 //------------------------------------------------------------------------------
49 /// Iterator from a point.
50 template <typename TIterableClass>
51 DGtal::ArrayImageIterator<TIterableClass>::
52 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, Domain const& aViewDomain, Point const& aPoint )
53  : myIterableClassPtr( anIterableClassPtr )
54  , myFullDomain{ aFullDomain }
55  , myViewDomain{ aViewDomain }
56  , myFullExtent( myFullDomain.upperBound() - myFullDomain.lowerBound() + Point::diagonal(1) )
57  , myViewExtent( myViewDomain.upperBound() - myViewDomain.lowerBound() + Point::diagonal(1) )
58  , myPoint{ aPoint }
59  , myFullIndex( Self::Linearizer::getIndex( myPoint - myFullDomain.lowerBound(), myFullExtent ) )
60 {
61  ASSERT_MSG(
62  myFullDomain.lowerBound().isLower( myViewDomain.lowerBound() )
63  && myFullDomain.upperBound().isUpper( myViewDomain.upperBound() ),
64  "The viewable domain must be included into the full domain."
65  );
66  ASSERT_MSG(
67  myViewDomain.isInside(aPoint),
68  "The point is outside the viewable domain !"
69  );
70 }
71 
72 //------------------------------------------------------------------------------
73 /// Iterator pointing to the first value.
74 template <typename TIterableClass>
75 DGtal::ArrayImageIterator<TIterableClass>::
76 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, Domain const& aViewDomain )
77  : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aViewDomain, aViewDomain.lowerBound() }
78 {}
79 
80 //------------------------------------------------------------------------------
81 /// Iterator pointing to the first value and spanning the whole domain.
82 template <typename TIterableClass>
83 DGtal::ArrayImageIterator<TIterableClass>::
84 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain )
85  : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aFullDomain }
86 {}
87 
88 //------------------------------------------------------------------------------
89 /// Iterator pointing after the last value of the viewable domain.
90 template <typename TIterableClass>
91 DGtal::ArrayImageIterator<TIterableClass>::
92 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, Domain const& aViewDomain, bool /* last */ )
93  : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aViewDomain, aViewDomain.upperBound() }
94 {
95  increment();
96 }
97 
98 //------------------------------------------------------------------------------
99 /// Iterator pointing after the last value of the whole domain.
100 template <typename TIterableClass>
101 DGtal::ArrayImageIterator<TIterableClass>::
102 ArrayImageIterator( IterableClass* anIterableClassPtr, Domain const& aFullDomain, bool /* last */ )
103  : ArrayImageIterator{ anIterableClassPtr, aFullDomain, aFullDomain, true }
104 {}
105 
106 //------------------------------------------------------------------------------
107 /// Copy constructor with type interoperability.
108 template <typename TIterableClass>
109 template <typename TOtherIterableClass>
110 DGtal::ArrayImageIterator<TIterableClass>::
111 ArrayImageIterator(
112  ArrayImageIterator<TOtherIterableClass> const& other,
113  typename std::enable_if< std::is_convertible<TOtherIterableClass*, IterableClass*>::value >::type*
114 )
115  : myIterableClassPtr( other.myIterableClassPtr )
116  , myFullDomain{ other.myFullDomain }
117  , myViewDomain{ other.myViewDomain }
118  , myFullExtent{ other.myFullExtent }
119  , myViewExtent{ other.myViewExtent }
120  , myPoint{ other.myPoint }
121  , myFullIndex{ other.myFullIndex }
122 {}
123 
124 //------------------------------------------------------------------------------
125 /// Move constructor with type interoperability.
126 template <typename TIterableClass>
127 template <typename TOtherIterableClass>
128 DGtal::ArrayImageIterator<TIterableClass>::
129 ArrayImageIterator(
130  ArrayImageIterator<TOtherIterableClass> && other,
131  typename std::enable_if< std::is_convertible<TOtherIterableClass*, IterableClass*>::value >::type*
132 ) noexcept
133  : myIterableClassPtr( std::move(other.myIterableClassPtr) )
134  , myFullDomain{ std::move(other.myFullDomain) }
135  , myViewDomain{ std::move(other.myViewDomain) }
136  , myFullExtent{ std::move(other.myFullExtent) }
137  , myViewExtent{ std::move(other.myViewExtent) }
138  , myPoint{ std::move(other.myPoint) }
139  , myFullIndex{ std::move(other.myFullIndex) }
140 {}
141 
142 //------------------------------------------------------------------------------
143 /// Destructor.
144 template <typename TIterableClass>
145 DGtal::ArrayImageIterator<TIterableClass>::
146 ~ArrayImageIterator()
147 {}
148 
149 //------------------------------------------------------------------------------
150 /// Copy assignment with type interoperability.
151 template <typename TIterableClass>
152 template <typename TOtherIterableClass>
153 typename std::enable_if<
154  std::is_convertible<TOtherIterableClass*, TIterableClass*>::value,
155  typename DGtal::ArrayImageIterator<TIterableClass>::Self&>::type
156 DGtal::ArrayImageIterator<TIterableClass>::
157 operator= ( ArrayImageIterator<TOtherIterableClass> const& other )
158 {
159  myIterableClassPtr = other.myIterableClassPtr;
160  myFullDomain = other.myFullDomain;
161  myViewDomain = other.myViewDomain;
162  myFullExtent = other.myFullExtent;
163  myViewExtent = other.myViewExtent;
164  myPoint = other.myPoint;
165  myFullIndex = other.myFullIndex;
166  return *this;
167 }
168 
169 //------------------------------------------------------------------------------
170 /// Move assignment constructor with type interoperability.
171 template <typename TIterableClass>
172 template <typename TOtherIterableClass>
173 typename std::enable_if<
174  std::is_convertible<TOtherIterableClass*, TIterableClass*>::value,
175  typename DGtal::ArrayImageIterator<TIterableClass>::Self&>::type
176 DGtal::ArrayImageIterator<TIterableClass>::
177 operator= ( ArrayImageIterator<TOtherIterableClass> && other )
178 {
179  myIterableClassPtr = std::move(other.myIterableClassPtr);
180  myFullDomain = std::move(other.myFullDomain);
181  myViewDomain = std::move(other.myViewDomain);
182  myFullExtent = std::move(other.myFullExtent);
183  myViewExtent = std::move(other.myViewExtent);
184  myPoint = std::move(other.myPoint);
185  myFullIndex = std::move(other.myFullIndex);
186  return *this;
187 }
188 
189 ///////////////////////////////////////////////////////////////////////////////
190 // Interface - public :
191 
192 //------------------------------------------------------------------------------
193 /// Return the point behind this iterator.
194 template <typename TIterableClass>
195 inline
196 typename DGtal::ArrayImageIterator<TIterableClass>::Point const&
197 DGtal::ArrayImageIterator<TIterableClass>::
198  getPoint() const noexcept
199 {
200  return myPoint;
201 }
202 
203 //------------------------------------------------------------------------------
204 /// Return the distance from this iterator to a given point.
205 template <typename TIterableClass>
206 inline
207 std::ptrdiff_t
208 DGtal::ArrayImageIterator<TIterableClass>::
209 distance_to( Point const& aPoint ) const noexcept
210 {
211  ASSERT_MSG(
212  myViewDomain.isInside(aPoint),
213  "The point is outside the viewable domain !"
214  );
215  return
216  static_cast<std::ptrdiff_t>( Linearizer::getIndex(aPoint, myViewDomain.lowerBound(), myViewExtent) )
217  - static_cast<std::ptrdiff_t>( Linearizer::getIndex(myPoint, myViewDomain.lowerBound(), myViewExtent) );
218 }
219 
220 //------------------------------------------------------------------------------
221 /// Writes/Displays the object on an output stream.
222 template <typename TIterableClass>
223 inline
224 void
225 DGtal::ArrayImageIterator<TIterableClass>::
226  selfDisplay ( std::ostream & out ) const
227 {
228  out << "[ArrayImageIterator] pointing to " << getPoint();
229 }
230 
231 //------------------------------------------------------------------------------
232 ///Checks the validity/consistency of the object.
233 template <typename TIterableClass>
234 inline
235 bool
236 DGtal::ArrayImageIterator<TIterableClass>::isValid() const
237 {
238  return myIterableClassPtr != nullptr;
239 }
240 
241 
242 ///////////////////////////////////////////////////////////////////////////////
243 // Hidden services :
244 
245 //------------------------------------------------------------------------------
246 /// Increment of one step.
247 template <typename TIterableClass>
248 void
249 DGtal::ArrayImageIterator<TIterableClass>::
250 increment()
251 {
252  ++myFullIndex;
253  ++myPoint[0];
254  for ( auto i = 1; i < (int)Domain::dimension && myPoint[i-1] > myViewDomain.upperBound()[i-1]; ++i )
255  {
256  myPoint[i-1] = myViewDomain.lowerBound()[i-1];
257  ++myPoint[i];
258  std::size_t cum = myFullExtent[i-1] - myViewExtent[i-1];
259  for ( auto j = 0; j < i-1; ++j )
260  cum *= myFullExtent[j];
261 
262  myFullIndex += cum;
263  }
264 }
265 
266 //------------------------------------------------------------------------------
267 /// Decrement of one step.
268 template <typename TIterableClass>
269 void
270 DGtal::ArrayImageIterator<TIterableClass>::
271 decrement()
272 {
273  --myFullIndex;
274  --myPoint[0];
275  for ( Dimension i = 1; i < Domain::dimension && myPoint[i-1] < myViewDomain.lowerBound()[i-1]; ++i )
276  {
277  myPoint[i-1] = myViewDomain.upperBound()[i-1];
278  --myPoint[i];
279  std::size_t accum = myFullExtent[i-1] - myViewExtent[i-1];
280  for ( int j = 0; j < (int)i-1; ++j )
281  accum *= myFullExtent[j];
282 
283  myFullIndex -= accum;
284  }
285 }
286 
287 //------------------------------------------------------------------------------
288 /// Equality.
289 template <typename TIterableClass>
290 inline
291 bool
292 DGtal::ArrayImageIterator<TIterableClass>::
293 equal( Self const& other ) const
294 {
295  return myFullIndex == other.myFullIndex;
296 }
297 
298 //------------------------------------------------------------------------------
299 /// Dereference.
300 template <typename TIterableClass>
301 inline
302 typename DGtal::ArrayImageIterator<TIterableClass>::Reference
303 DGtal::ArrayImageIterator<TIterableClass>::
304 dereference() const
305 {
306  return myIterableClassPtr->dereference( myPoint, myFullIndex );
307 }
308 
309 //------------------------------------------------------------------------------
310 /// Distance to other iterator.
311 template <typename TIterableClass>
312 inline
313 std::ptrdiff_t
314 DGtal::ArrayImageIterator<TIterableClass>::
315 distance_to( Self const& other ) const
316 {
317  return distance_to( other.myPoint );
318 }
319 
320 //------------------------------------------------------------------------------
321 /// Advance by n steps.
322 template <typename TIterableClass>
323 void
324 DGtal::ArrayImageIterator<TIterableClass>::
325 advance( std::ptrdiff_t n )
326 {
327  const auto pos = Self::Linearizer::getIndex( myPoint, myViewDomain.lowerBound(), myViewExtent );
328  myPoint = Self::Linearizer::getPoint( pos + n, myViewDomain.lowerBound(), myViewExtent );
329  myFullIndex = Self::Linearizer::getIndex( myPoint, myFullDomain.lowerBound(), myFullExtent );
330 }
331 
332 
333 ///////////////////////////////////////////////////////////////////////////////
334 // Implementation of inline functions //
335 
336 template <typename T>
337 inline
338 std::ostream&
339 DGtal::operator<< ( std::ostream & out,
340  const ArrayImageIterator<T> & object )
341 {
342  object.selfDisplay( out );
343  return out;
344 }
345 
346 // //
347 ///////////////////////////////////////////////////////////////////////////////
348