DGtal 1.4.0
Loading...
Searching...
No Matches
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
54namespace 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
105 {
106 --current;
107 --prev;
108 }
109
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
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
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
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
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
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
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
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)
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.
Vector lower(const Vector &z, unsigned int k)
Vector upper(const Vector &z, unsigned int k)