DGtal  1.5.beta
HyperRectDomain_Iterator.h
1 
17 #pragma once
18 
32 #if defined(HyperRectDomain_Iterator_RECURSES)
33 #error Recursive header files inclusion detected in HyperRectDomain_Iterator.h
34 #else // defined(HyperRectDomain_Iterator_RECURSES)
36 #define HyperRectDomain_Iterator_RECURSES
37 
38 #if !defined HyperRectDomain_Iterator_h
40 #define HyperRectDomain_Iterator_h
41 
43 // Inclusions
44 #include <iostream>
45 #include <vector>
46 #include <iterator>
47 #include <type_traits>
48 
49 #include <boost/iterator/iterator_facade.hpp>
50 
51 #include "DGtal/base/Common.h"
53 
54 namespace DGtal
55 {
65  template <typename TIterator>
67  : public boost::iterator_facade <
68  HyperRectDomain_ReverseIterator<TIterator>,
69  typename TIterator::Point const,
70  std::random_access_iterator_tag,
71  typename TIterator::Point const&,
72  typename std::iterator_traits<TIterator>::difference_type
73  >
74  {
75  public:
76  using Iterator = TIterator;
78  using Point = typename Iterator::Point;
79  using Dimension = typename Point::Dimension;
80  using DifferenceType = typename std::iterator_traits<Self>::difference_type;
81 
82  public:
85  : current(it)
86  , prev(it)
87  {
88  --prev;
89  }
90 
92  const Point& dereference() const
93  {
94  return *prev;
95  }
96 
98  bool equal( const Self &other ) const
99  {
100  return current == other.current;
101  }
102 
104  void increment()
105  {
106  --current;
107  --prev;
108  }
109 
111  void decrement()
112  {
113  ++current;
114  ++prev;
115  }
116 
118  void advance( DifferenceType const& n )
119  {
120  current -= n;
121  prev -= n;
122  }
123 
125  DifferenceType distance_to( const Self& other ) const
126  {
127  return std::distance(other.current, current);
128  }
129 
130  private:
132 
133  };
134 
136  // class HyperRectDomain_Iterator
141  template <typename TPoint>
143  : public boost::iterator_facade <
144  HyperRectDomain_Iterator<TPoint>,
145  TPoint const,
146  std::random_access_iterator_tag,
147  TPoint const&,
148 #ifdef WITH_BIGINTEGER
149  typename std::conditional<std::is_same<typename TPoint::Component, BigInteger>::value, BigInteger, std::ptrdiff_t>::type
150 #else
151  std::ptrdiff_t
152 #endif
153  >
154  {
155  public:
156  using Point = TPoint;
158  using Dimension = typename Point::Dimension;
159  using DifferenceType = typename std::iterator_traits<Self>::difference_type;
160 
161 
171  HyperRectDomain_Iterator( const Point & p, const Point& lower, const Point &upper )
172  : myPoint( p ), mylower( lower ), myupper( upper )
173  {
174  ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
175  lower.isLower(upper) || lower == upper + TPoint::diagonal(1),
176  "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
177  );
178 
179  ASSERT_MSG(
180  ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
181  "The point must be inside the domain or be equal to one of his bound."
182  );
183 
184  // Calculating iterator position in the sequence
185  pos = 0;
186  DifferenceType delta = 1;
187  for ( Dimension i = 0; i < Point::dimension; ++i )
188  {
189  pos += delta * (myPoint[i] - mylower[i]);
190  delta *= myupper[i] - mylower[i] + 1;
191  }
192  }
193 
194  private:
196 
198  const Point& dereference() const
199  {
200  ASSERT_MSG( // we must be between [begin,end]
201  mylower.isLower(myPoint) && myPoint.isLower(myupper),
202  "The iterator points outside the domain."
203  );
204 
205  return myPoint;
206 
207  }
208 
213  bool equal( const Self &other ) const
214  {
215  ASSERT_MSG( // we should only compare iterators on the same domain
216  mylower == other.mylower && myupper == other.myupper,
217  "The compared iterators iterate on different domains."
218  );
219 
220  return pos == other.pos;
221  }
222 
227  void increment()
228  {
229  ++pos;
230  ++myPoint[0];
231  for ( Dimension i = 0; myPoint[i] > myupper[i] && i < Point::dimension - 1; ++i )
232  {
233  ++myPoint[i+1];
234  myPoint[i] = mylower[i];
235  }
236  }
237 
242  void decrement()
243  {
244  --pos;
245  --myPoint[0];
246  for ( Dimension i = 0; myPoint[i] < mylower[i] && i < Point::dimension - 1; ++i )
247  {
248  --myPoint[i+1];
249  myPoint[i] = myupper[i];
250  }
251  }
252 
257  void advance( DifferenceType const& n )
258  {
259  pos += n;
260  if (n > 0)
261  {
262  myPoint[0] += n;
263  for ( Dimension i = 0; myPoint[i] > myupper[i] && i < Point::dimension - 1; ++i )
264  {
265  typename Point::Component const shift = myPoint[i] - mylower[i];
266  typename Point::Component const length = myupper[i] - mylower[i] + 1;
267  myPoint[i+1] += shift / length;
268  myPoint[i] = mylower[i] + (shift % length);
269  }
270  }
271  else if (n < 0)
272  {
273  myPoint[0] += n;
274  for ( Dimension i = 0; myPoint[i] < mylower[i] && i < Point::dimension - 1; ++i )
275  {
276  typename Point::Component const shift = myupper[i] - myPoint[i];
277  typename Point::Component const length = myupper[i] - mylower[i] + 1;
278  myPoint[i+1] -= shift / length;
279  myPoint[i] = myupper[i] - (shift % length);
280  }
281  }
282  }
283 
287  DifferenceType distance_to( const Self& other ) const
288  {
289  ASSERT_MSG( // we should only compare iterators on the same domain
290  mylower == other.mylower && myupper == other.myupper,
291  "The compared iterators iterate on different domains."
292  );
293 
294  return other.pos - pos;
295  }
296 
297  private:
299  TPoint myPoint;
300 
302  TPoint mylower, myupper;
303 
306 
307  }; // End of class HyperRectDomain_Iterator
308 
310  // class HyperRectDomain_subIterator
315  template<typename TPoint>
317  : public boost::iterator_facade <
318  HyperRectDomain_subIterator<TPoint>,
319  const TPoint,
320  std::random_access_iterator_tag,
321  TPoint const&,
322 #ifdef WITH_BIGINTEGER
323  typename std::conditional<std::is_same<typename TPoint::Component, BigInteger>::value, BigInteger, std::ptrdiff_t>::type
324 #else
325  std::ptrdiff_t
326 #endif
327  >
328  {
329  public:
330  using Point = TPoint;
332  using Dimension = typename Point::Dimension;
333  using DifferenceType = typename std::iterator_traits<Self>::difference_type;
334 
335  HyperRectDomain_subIterator(const TPoint & p, const TPoint& lower,
336  const TPoint &upper,
337  const std::vector<Dimension> &subDomain)
338  : myPoint( p ), mylower( lower ), myupper( upper )
339  {
340  ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
341  lower.isLower(upper) || lower == upper + TPoint::diagonal(0).partialCopy( TPoint::diagonal(1), subDomain ),
342  "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
343  );
344 
345  ASSERT_MSG(
346  ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
347  "The point must be inside the domain or be equal to one of his bound."
348  );
349 
350  ASSERT_MSG(
351  subDomain.size() <= TPoint::dimension,
352  "The sub-range cannot have more dimensions than the ambiant space."
353  );
354 
355  mySubDomain.reserve( subDomain.size() );
356  for ( typename std::vector<Dimension>::const_iterator it = subDomain.begin();
357  it != subDomain.end(); ++it )
358  {
359  ASSERT_MSG(
360  *it <= TPoint::dimension,
361  "Invalid dimension in the sub-range."
362  );
363  mySubDomain.push_back( *it );
364  }
365 
366  // Calculating iterator position in the sequence
367  pos = 0;
368  DifferenceType delta = 1;
369  for ( Dimension i = 0; i < mySubDomain.size(); ++i )
370  {
371  auto const ii = mySubDomain[i];
372  pos += delta * (myPoint[ii] - mylower[ii]);
373  delta *= myupper[ii] - mylower[ii] + 1;
374  }
375  }
376 
377  private:
379 
381  const Point& dereference() const
382  {
383  ASSERT_MSG( // we must be between [begin,end]
384  mylower.isLower(myPoint) && myPoint.isLower(myupper),
385  "The iterator points outside the domain."
386  );
387 
388  return myPoint;
389 
390  }
391 
396  bool equal( const Self &other ) const
397  {
398  ASSERT_MSG( // we should only compare iterators on the same domain and same dimensions
399  mylower == other.mylower && myupper == other.myupper && mySubDomain == other.mySubDomain,
400  "The compared iterators iterate on different domains or different dimensions."
401  );
402 
403  return pos == other.pos;
404  }
405 
406 
411  void increment()
412  {
413  ++pos;
414  ++myPoint[mySubDomain[0]];
415  for ( Dimension i = 0; myPoint[mySubDomain[i]] > myupper[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
416  {
417  ++myPoint[mySubDomain[i+1]];
419  }
420  }
421 
426  void decrement()
427  {
428  --pos;
429  --myPoint[mySubDomain[0]];
430  for ( Dimension i = 0; myPoint[mySubDomain[i]] < mylower[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
431  {
432  --myPoint[mySubDomain[i+1]];
434  }
435  }
436 
441  void advance( DifferenceType const& n )
442  {
443  pos += n;
444  if (n > 0)
445  {
446  myPoint[mySubDomain[0]] += n;
447  for ( Dimension i = 0; myPoint[mySubDomain[i]] > myupper[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
448  {
449  auto const ii = mySubDomain[i];
450  typename Point::Component const shift = myPoint[ii] - mylower[ii];
451  typename Point::Component const length = myupper[ii] - mylower[ii] + 1;
452  myPoint[mySubDomain[i+1]] += shift / length;
453  myPoint[ii] = mylower[ii] + (shift % length);
454  }
455  }
456  else if (n < 0)
457  {
458  myPoint[mySubDomain[0]] += n;
459  for ( Dimension i = 0; myPoint[mySubDomain[i]] < mylower[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
460  {
461  auto const ii = mySubDomain[i];
462  typename Point::Component const shift = myupper[ii] - myPoint[ii];
463  typename Point::Component const length = myupper[ii] - mylower[ii] + 1;
464  myPoint[mySubDomain[i+1]] -= shift / length;
465  myPoint[ii] = myupper[ii] - (shift % length);
466  }
467  }
468  }
469 
474  DifferenceType distance_to( const Self& other ) const
475  {
476  ASSERT_MSG( // we should only compare iterators on the same domain and same dimensions
477  mylower == other.mylower && myupper == other.myupper && mySubDomain == other.mySubDomain,
478  "The compared iterators iterate on different domains or different dimensions."
479  );
480 
481  return other.pos - pos;
482  }
483 
484  private:
486  TPoint myPoint;
487 
489  TPoint mylower, myupper;
490 
494  std::vector<Dimension> mySubDomain;
495 
498 
499  }; // End of class HyperRectDomain_subIterator
500 
501 } //namespace
502 // //
504 
505 #endif // !defined HyperRectDomain_Iterator_h
506 
507 #undef HyperRectDomain_Iterator_RECURSES
508 #endif // else defined(HyperRectDomain_Iterator_RECURSES)
Iterator for HyperRectDomain.
HyperRectDomain_Iterator(const Point &p, const Point &lower, const Point &upper)
HyperRectDomain iterator constructor.
DifferenceType pos
Iterator position in the current sequence.
TPoint mylower
Copies of the Domain limits.
bool equal(const Self &other) const
Compare iterators.
typename std::iterator_traits< Self >::difference_type DifferenceType
Type of the difference between two iterators (usually std::ptrdiff_t except for BigInteger).
void decrement()
Decrements the iterator in order to scan the domain points dimension by dimension (lexicographic orde...
const Point & dereference() const
Dereference.
DifferenceType distance_to(const Self &other) const
Distance between two iterators on the same domain (lexicographic order).
TPoint myPoint
Current Point in the domain.
void increment()
Increments the iterator in order to scan the domain points dimension by dimension (lexicographic orde...
void advance(DifferenceType const &n)
Advances the iterator in order to scan the domain points dimension by dimension (lexicographic order)...
Reverse iterator for HyperRectDomain.
typename std::iterator_traits< Self >::difference_type DifferenceType
Type of the difference between two iterators (usually std::ptrdiff_t except for BigInteger).
DifferenceType distance_to(const Self &other) const
Distance between two iterators on the same domain.
const Point & dereference() const
Dereference.
HyperRectDomain_ReverseIterator(Iterator it)
Constructor from a HyperRectDomain iterator.
void advance(DifferenceType const &n)
Advance iterator by given steps.
bool equal(const Self &other) const
Compare iterators.
TPoint mylower
Copies of the Domain limits.
bool equal(const Self &other) const
Compare iterators.
DifferenceType distance_to(const Self &other) const
Distance between two iterators on the same domain (by using the subDomain order given by the user).
void decrement()
Decrements the iterator in order to scan the domain points dimension by dimension (by using the subDo...
void advance(DifferenceType const &n)
Advances the iterator in order to scan the domain points dimension by dimension (by using the subDoma...
DifferenceType pos
Iterator position in the current sequence.
void increment()
Increments the iterator in order to scan the domain points dimension by dimension (by using the subDo...
const Point & dereference() const
Dereference.
typename std::iterator_traits< Self >::difference_type DifferenceType
Type of the difference between two iterators (usually std::ptrdiff_t except for BigInteger).
HyperRectDomain_subIterator(const TPoint &p, const TPoint &lower, const TPoint &upper, const std::vector< Dimension > &subDomain)
TPoint myPoint
Current Point in the domain.
DGtal is the top-level namespace which contains all DGtal functions and types.
MyPointD Point
Definition: testClone2.cpp:383
Vector lower(const Vector &z, unsigned int k)
Vector upper(const Vector &z, unsigned int k)