DGtal  0.9.2
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)
35 
36 #define HyperRectDomain_Iterator_RECURSES
37 
38 #if !defined HyperRectDomain_Iterator_h
39 
40 #define HyperRectDomain_Iterator_h
41 
43 // Inclusions
44 #include <iostream>
45 #include <vector>
46 #include "DGtal/base/Common.h"
49 //#include <iterator> // Bug for operator * => dangling reference !!!
50 // Class allowing to build a reverse iterator of a given iterator.
51 template<typename _Iterator>
53  : public std::iterator<typename std::iterator_traits<_Iterator>::iterator_category,
54  typename std::iterator_traits<_Iterator>::value_type,
55  typename std::iterator_traits<_Iterator>::difference_type,
56  typename std::iterator_traits<_Iterator>::pointer,
57  typename std::iterator_traits<_Iterator>::reference>
58 {
59 protected:
60  _Iterator current;
61  _Iterator prev;
62 
63 public:
64  typedef _Iterator iterator_type;
65  typedef typename std::iterator_traits<_Iterator>::difference_type
67  typedef typename std::iterator_traits<_Iterator>::reference reference;
68  typedef typename std::iterator_traits<_Iterator>::pointer pointer;
69 
70 public:
71  explicit
72  myreverse_iterator(iterator_type __x) : current(__x),
73  prev(current)
74  { --prev; }
75 
77  : current(__x.current), prev(__x.prev) { }
78 
79  iterator_type base() const
80  { return current; }
81 
82  /*const*/ reference operator*() const
83  { return *prev; }
84 
85  reference operator*()
86  { return *prev; }
87 
88  pointer operator->() const
89  { return &(operator*()); }
90 
92  { --current; --prev;
93  return *this;
94  }
95 
97  {
98  myreverse_iterator __tmp = *this;
99  operator++();
100  return __tmp;
101  }
102 
104  {
105  ++current; ++prev;
106  return *this;
107  }
108 
110  {
111  myreverse_iterator __tmp = *this;
112  operator--();
113  return __tmp;
114  }
115 
117  { return myreverse_iterator(current - __n); }
118 
120  {
121  current -= __n; prev = current; --prev;
122  return *this;
123  }
124 
126  { return myreverse_iterator(current + __n); }
127 
129  {
130  current += __n; prev = current; --prev;
131  return *this;
132  }
133 
134  reference operator[](difference_type __n) const
135  { return *(*this + __n); }
136 };
137 template<typename _Iterator>
138 inline bool
141 { return __x.base() == __y.base(); }
142 template<typename _Iterator>
143 inline bool
146 { return !(__x == __y); }
147 
148 //******************************************************************************
149 namespace DGtal
150 {
152  // class HyperRectDomain_Iterator
157  template<typename TPoint>
159  {
160  public:
161  typedef std::bidirectional_iterator_tag iterator_category;
162  typedef TPoint value_type;
163  typedef ptrdiff_t difference_type;
164  typedef TPoint* pointer;
165  typedef TPoint& reference;
166  typedef typename TPoint::Dimension Dimension;
167 
168 
169  HyperRectDomain_Iterator( const TPoint & p, const TPoint& lower, const TPoint &upper )
170  : myPoint( p ), mylower( lower ), myupper( upper )
171  {
172  ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
173  lower.isLower(upper) || lower == upper + TPoint::diagonal(1),
174  "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
175  );
176 
177  ASSERT_MSG(
178  ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
179  "The point must be inside the domain or be equal to one of his bound."
180  );
181  }
182 
183  const TPoint & operator*() const
184  {
185  ASSERT_MSG( // we must be between [begin,end]
186  mylower.isLower(myPoint) && myPoint.isLower(myupper),
187  "The iterator points outside the domain."
188  );
189 
190  return myPoint;
191  }
192 
193  TPoint & operator*()
194  {
195  ASSERT_MSG( // we must be between [begin,end]
196  mylower.isLower(myPoint) && myPoint.isLower(myupper),
197  "The iterator points outside the domain."
198  );
199 
200  return myPoint;
201  }
202 
208  {
209  return ( myPoint==it.myPoint );
210  }
211 
217  {
218  return ( myPoint!=aIt.myPoint );
219  }
220 
226  {
227  ++myPoint[0];
228  if (( TPoint::dimension > 1 ) &&
229  ( myPoint[0] > myupper[0] ) )
230  {
231  Dimension current_pos = 0;
232  do
233  {
234  myPoint[current_pos] = mylower[current_pos];
235  current_pos++;
236  if ( current_pos < TPoint::dimension )
237  ++myPoint[current_pos];
238  }
239  while (( current_pos + 1 < TPoint::dimension ) &&
240  ( myPoint[ current_pos ] > myupper[ current_pos ] ) );
241  }
242  }
243 
248  {
250  return *this;
251  }
252 
258  {
261  return tmp;
262  }
263 
269  {
270  --myPoint[0];
271  if (( TPoint::dimension > 1 ) &&
272  ( myPoint[0] < mylower[0] ) )
273  {
274  Dimension current_pos = 0;
275  do
276  {
277  myPoint[ current_pos ] = myupper[ current_pos ];
278  ++current_pos;
279  if ( current_pos < TPoint::dimension )
280  --myPoint[ current_pos ];
281  }
282  while (( current_pos + 1 < TPoint::dimension ) &&
283  ( myPoint[ current_pos ] < mylower[ current_pos ] ) );
284  }
285  }
286 
292  {
294  return *this;
295  }
296 
301  {
304  return tmp;
305  }
306 
307  private:
309  TPoint myPoint;
311  TPoint mylower, myupper;
312  }; // End of class HyperRectDomain_Iterator
313 
315  // class HyperRectDomain_Iterator
320  template<typename TPoint>
322  {
323  public:
324  typedef std::bidirectional_iterator_tag iterator_category;
325  typedef TPoint value_type;
326  typedef ptrdiff_t difference_type;
327  typedef TPoint* pointer;
328  typedef TPoint& reference;
329  typedef typename TPoint::Dimension Dimension;
330 
331  HyperRectDomain_subIterator(const TPoint & p, const TPoint& lower,
332  const TPoint &upper,
333  std::initializer_list<Dimension> subDomain)
334  : myPoint( p ), mylower( lower ), myupper( upper )
335  {
336  ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
337  lower.isLower(upper) || lower == upper + TPoint::diagonal(0).partialCopy( TPoint::diagonal(1), subDomain),
338  "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
339  );
340 
341  ASSERT_MSG(
342  ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
343  "The point must be inside the domain or be equal to one of his bound."
344  );
345 
346  ASSERT_MSG(
347  subDomain.size() <= TPoint::dimension,
348  "The sub-range cannot have more dimensions than the ambiant space."
349  );
350 
351  mySubDomain.reserve( subDomain.size() );
352  for ( const unsigned int *c = subDomain.begin();
353  c != subDomain.end(); ++c )
354  {
355  ASSERT_MSG(
356  *c <= TPoint::dimension,
357  "Invalid dimension in the sub-range."
358  );
359 
360  mySubDomain.push_back( *c );
361  }
362 
363  // TODO: check the validity of the subDomain ?
364  }
365 
366  HyperRectDomain_subIterator(const TPoint & p, const TPoint& lower,
367  const TPoint &upper,
368  const std::vector<Dimension> &subDomain)
369  : myPoint( p ), mylower( lower ), myupper( upper )
370  {
371  ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
372  lower.isLower(upper) || lower == upper + TPoint::diagonal(0).partialCopy( TPoint::diagonal(1), subDomain ),
373  "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
374  );
375 
376  ASSERT_MSG(
377  ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
378  "The point must be inside the domain or be equal to one of his bound."
379  );
380 
381  ASSERT_MSG(
382  subDomain.size() <= TPoint::dimension,
383  "The sub-range cannot have more dimensions than the ambiant space."
384  );
385 
386  mySubDomain.reserve( subDomain.size() );
387  for ( typename std::vector<Dimension>::const_iterator it = subDomain.begin();
388  it != subDomain.end(); ++it )
389  {
390  ASSERT_MSG(
391  *it <= TPoint::dimension,
392  "Invalid dimension in the sub-range."
393  );
394  mySubDomain.push_back( *it );
395  }
396 
397  // TODO: check the validity of the subDomain ?
398  }
399 
400 
401  const TPoint & operator*() const
402  {
403  ASSERT_MSG( // we must be between [begin,end]
404  mylower.isLower(myPoint) && myPoint.isLower(myupper),
405  "The iterator points outside the domain."
406  );
407 
408  return myPoint;
409  }
410 
411  TPoint & operator*()
412  {
413  ASSERT_MSG( // we must be between [begin,end]
414  mylower.isLower(myPoint) && myPoint.isLower(myupper),
415  "The iterator points outside the domain."
416  );
417 
418  return myPoint;
419  }
420 
426  {
427  for (unsigned int i=0; i<mySubDomain.size(); ++i)
428  if ( myPoint[mySubDomain[i]]!=it.myPoint[mySubDomain[i]])
429  return false;
430 
431  return true;
432  }
433 
439  {
440  return !operator==(aIt);
441  }
442 
448  {
449  ASSERT( mySubDomain.size() > 0 );
450  ++myPoint[ mySubDomain[0] ];
451 
452  if ( mySubDomain.size() > 1 &&
453  myPoint[ mySubDomain[0] ] >
454  myupper[ mySubDomain[0] ] )
455  {
456  Dimension current_pos = 0;
457  do
458  {
459  myPoint[ mySubDomain[current_pos] ] =
460  mylower[ mySubDomain[current_pos] ];
461  ++current_pos;
462  if ( current_pos < mySubDomain.size() )
463  ++myPoint[ mySubDomain[current_pos] ];
464  }
465  while (( current_pos + 1 < mySubDomain.size() ) &&
466  ( myPoint[ mySubDomain[current_pos] ] >
467  myupper[ mySubDomain[current_pos] ] ) );
468  }
469  }
470 
475  {
477  return *this;
478  }
479 
485  {
488  return tmp;
489  }
490 
496  {
497  ASSERT( mySubDomain.size() > 0 );
498  --myPoint[ mySubDomain[0] ];
499 
500  if ( mySubDomain.size() > 1 &&
501  myPoint[ mySubDomain[0] ] <
502  mylower[ mySubDomain[0] ] )
503  {
504  Dimension current_pos = 0;
505  do
506  {
507  myPoint[ mySubDomain[current_pos] ] =
508  myupper[ mySubDomain[current_pos] ];
509  ++current_pos;
510  if ( current_pos < mySubDomain.size() )
511  --myPoint[ mySubDomain[current_pos] ];
512  }
513  while (( current_pos + 1 < mySubDomain.size() ) &&
514  ( myPoint[ mySubDomain[current_pos] ] <
515  mylower[ mySubDomain[current_pos] ] ) );
516  }
517  }
518 
524  {
526  return *this;
527  }
528 
533  {
536  return tmp;
537  }
538 
539  private:
541  TPoint myPoint;
543  TPoint mylower, myupper;
546  std::vector<Dimension> mySubDomain;
547  }; // End of class HyperRectDomain_subIterator
548 
549 } //namespace
550 // //
552 
553 #endif // !defined HyperRectDomain_Iterator_h
554 
555 #undef HyperRectDomain_Iterator_RECURSES
556 #endif // else defined(HyperRectDomain_Iterator_RECURSES)
myreverse_iterator & operator++()
myreverse_iterator & operator-=(difference_type __n)
myreverse_iterator & operator+=(difference_type __n)
reference operator*() const
myreverse_iterator operator--(int)
myreverse_iterator & operator--()
myreverse_iterator operator+(difference_type __n) const
bool operator!=(const HyperRectDomain_Iterator< TPoint > &aIt) const
bool operator!=(const HyperRectDomain_subIterator< TPoint > &aIt) const
HyperRectDomain_Iterator< TPoint > & operator--()
HyperRectDomain_Iterator(const TPoint &p, const TPoint &lower, const TPoint &upper)
iterator_type base() const
myreverse_iterator operator++(int)
HyperRectDomain_subIterator< TPoint > & operator++()
std::iterator_traits< _Iterator >::difference_type difference_type
myreverse_iterator operator-(difference_type __n) const
HyperRectDomain_Iterator< TPoint > & operator++()
TPoint mylower
Copies of the Domain limits.
bool operator==(const HyperRectDomain_Iterator< TPoint > &it) const
bool operator==(const HyperRectDomain_subIterator< TPoint > &it) const
HyperRectDomain_subIterator(const TPoint &p, const TPoint &lower, const TPoint &upper, std::initializer_list< Dimension > subDomain)
myreverse_iterator(iterator_type __x)
DGtal is the top-level namespace which contains all DGtal functions and types.
TPoint mylower
Copies of the Domain limits.
bool operator!=(const Point &a, const Point &b)
Definition: Point.h:177
HyperRectDomain_subIterator< TPoint > & operator--()
bool operator==(const Point &a, const Point &b)
Definition: Point.h:171
HyperRectDomain_subIterator(const TPoint &p, const TPoint &lower, const TPoint &upper, const std::vector< Dimension > &subDomain)
TPoint myPoint
Current Point in the domain.
std::bidirectional_iterator_tag iterator_category
myreverse_iterator(const myreverse_iterator &__x)
TPoint myPoint
Current Point in the domain.
std::iterator_traits< _Iterator >::pointer pointer
std::bidirectional_iterator_tag iterator_category
reference operator[](difference_type __n) const
std::iterator_traits< _Iterator >::reference reference