Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
HyperRectDomain_Iterator.h
1
16
17#pragma once
18
31
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 typename std::conditional<std::is_same<typename TPoint::Component, BigInteger>::value, BigInteger, std::ptrdiff_t>::type
149 >
150 {
151 public:
152 using Point = TPoint;
154 using Dimension = typename Point::Dimension;
155 using DifferenceType = typename std::iterator_traits<Self>::difference_type;
156
157
168 : myPoint( p ), mylower( lower ), myupper( upper )
169 {
170 ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
171 lower.isLower(upper) || lower == upper + TPoint::diagonal(1),
172 "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
173 );
174
175 ASSERT_MSG(
176 ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
177 "The point must be inside the domain or be equal to one of his bound."
178 );
179
180 // Calculating iterator position in the sequence
181 pos = 0;
182 DifferenceType delta = 1;
183 for ( Dimension i = 0; i < Point::dimension; ++i )
184 {
185 pos += delta * (myPoint[i] - mylower[i]);
186 delta *= myupper[i] - mylower[i] + 1;
187 }
188 }
189
190 private:
191 friend class boost::iterator_core_access;
192
194 const Point& dereference() const
195 {
196 ASSERT_MSG( // we must be between [begin,end]
197 mylower.isLower(myPoint) && myPoint.isLower(myupper),
198 "The iterator points outside the domain."
199 );
200
201 return myPoint;
202
203 }
204
209 bool equal( const Self &other ) const
210 {
211 ASSERT_MSG( // we should only compare iterators on the same domain
212 mylower == other.mylower && myupper == other.myupper,
213 "The compared iterators iterate on different domains."
214 );
215
216 return pos == other.pos;
217 }
218
224 {
225 ++pos;
226 ++myPoint[0];
227 for ( Dimension i = 0; myPoint[i] > myupper[i] && i < Point::dimension - 1; ++i )
228 {
229 ++myPoint[i+1];
230 myPoint[i] = mylower[i];
231 }
232 }
233
239 {
240 --pos;
241 --myPoint[0];
242 for ( Dimension i = 0; myPoint[i] < mylower[i] && i < Point::dimension - 1; ++i )
243 {
244 --myPoint[i+1];
245 myPoint[i] = myupper[i];
246 }
247 }
248
253 void advance( DifferenceType const& n )
254 {
255 pos += n;
256 if (n > 0)
257 {
258 myPoint[0] += n;
259 for ( Dimension i = 0; myPoint[i] > myupper[i] && i < Point::dimension - 1; ++i )
260 {
261 typename Point::Component const shift = myPoint[i] - mylower[i];
262 typename Point::Component const length = myupper[i] - mylower[i] + 1;
263 myPoint[i+1] += shift / length;
264 myPoint[i] = mylower[i] + (shift % length);
265 }
266 }
267 else if (n < 0)
268 {
269 myPoint[0] += n;
270 for ( Dimension i = 0; myPoint[i] < mylower[i] && i < Point::dimension - 1; ++i )
271 {
272 typename Point::Component const shift = myupper[i] - myPoint[i];
273 typename Point::Component const length = myupper[i] - mylower[i] + 1;
274 myPoint[i+1] -= shift / length;
275 myPoint[i] = myupper[i] - (shift % length);
276 }
277 }
278 }
279
283 DifferenceType distance_to( const Self& other ) const
284 {
285 ASSERT_MSG( // we should only compare iterators on the same domain
286 mylower == other.mylower && myupper == other.myupper,
287 "The compared iterators iterate on different domains."
288 );
289
290 return other.pos - pos;
291 }
292
293 private:
295 TPoint myPoint;
296
299
302
303 }; // End of class HyperRectDomain_Iterator
304
306 // class HyperRectDomain_subIterator
311 template<typename TPoint>
313 : public boost::iterator_facade <
314 HyperRectDomain_subIterator<TPoint>,
315 const TPoint,
316 std::random_access_iterator_tag,
317 TPoint const&,
318 typename std::conditional<std::is_same<typename TPoint::Component, BigInteger>::value, BigInteger, std::ptrdiff_t>::type
319 >
320 {
321 public:
322 using Point = TPoint;
324 using Dimension = typename Point::Dimension;
325 using DifferenceType = typename std::iterator_traits<Self>::difference_type;
326
327 HyperRectDomain_subIterator(const TPoint & p, const TPoint& lower,
328 const TPoint &upper,
329 const std::vector<Dimension> &subDomain)
330 : myPoint( p ), mylower( lower ), myupper( upper )
331 {
332 ASSERT_MSG( // For an empty domain, lower = upper + diag(1) so that begin() == end().
333 lower.isLower(upper) || lower == upper + TPoint::diagonal(0).partialCopy( TPoint::diagonal(1), subDomain ),
334 "The lower bound must be lower than the upper bound or, for an empty domain, be equal to the upper bound + diagonal(1)."
335 );
336
337 ASSERT_MSG(
338 ( lower.isLower(p) && p.isLower(upper) ) || p == lower || p == upper,
339 "The point must be inside the domain or be equal to one of his bound."
340 );
341
342 ASSERT_MSG(
343 subDomain.size() <= TPoint::dimension,
344 "The sub-range cannot have more dimensions than the ambiant space."
345 );
346
347 mySubDomain.reserve( subDomain.size() );
348 for ( typename std::vector<Dimension>::const_iterator it = subDomain.begin();
349 it != subDomain.end(); ++it )
350 {
351 ASSERT_MSG(
352 *it <= TPoint::dimension,
353 "Invalid dimension in the sub-range."
354 );
355 mySubDomain.push_back( *it );
356 }
357
358 // Calculating iterator position in the sequence
359 pos = 0;
360 DifferenceType delta = 1;
361 for ( Dimension i = 0; i < mySubDomain.size(); ++i )
362 {
363 auto const ii = mySubDomain[i];
364 pos += delta * (myPoint[ii] - mylower[ii]);
365 delta *= myupper[ii] - mylower[ii] + 1;
366 }
367 }
368
369 private:
370 friend class boost::iterator_core_access;
371
373 const Point& dereference() const
374 {
375 ASSERT_MSG( // we must be between [begin,end]
376 mylower.isLower(myPoint) && myPoint.isLower(myupper),
377 "The iterator points outside the domain."
378 );
379
380 return myPoint;
381
382 }
383
388 bool equal( const Self &other ) const
389 {
390 ASSERT_MSG( // we should only compare iterators on the same domain and same dimensions
391 mylower == other.mylower && myupper == other.myupper && mySubDomain == other.mySubDomain,
392 "The compared iterators iterate on different domains or different dimensions."
393 );
394
395 return pos == other.pos;
396 }
397
398
404 {
405 ++pos;
406 ++myPoint[mySubDomain[0]];
407 for ( Dimension i = 0; myPoint[mySubDomain[i]] > myupper[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
408 {
409 ++myPoint[mySubDomain[i+1]];
411 }
412 }
413
419 {
420 --pos;
421 --myPoint[mySubDomain[0]];
422 for ( Dimension i = 0; myPoint[mySubDomain[i]] < mylower[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
423 {
424 --myPoint[mySubDomain[i+1]];
426 }
427 }
428
433 void advance( DifferenceType const& n )
434 {
435 pos += n;
436 if (n > 0)
437 {
438 myPoint[mySubDomain[0]] += n;
439 for ( Dimension i = 0; myPoint[mySubDomain[i]] > myupper[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
440 {
441 auto const ii = mySubDomain[i];
442 typename Point::Component const shift = myPoint[ii] - mylower[ii];
443 typename Point::Component const length = myupper[ii] - mylower[ii] + 1;
444 myPoint[mySubDomain[i+1]] += shift / length;
445 myPoint[ii] = mylower[ii] + (shift % length);
446 }
447 }
448 else if (n < 0)
449 {
450 myPoint[mySubDomain[0]] += n;
451 for ( Dimension i = 0; myPoint[mySubDomain[i]] < mylower[mySubDomain[i]] && i < mySubDomain.size() - 1; ++i )
452 {
453 auto const ii = mySubDomain[i];
454 typename Point::Component const shift = myupper[ii] - myPoint[ii];
455 typename Point::Component const length = myupper[ii] - mylower[ii] + 1;
456 myPoint[mySubDomain[i+1]] -= shift / length;
457 myPoint[ii] = myupper[ii] - (shift % length);
458 }
459 }
460 }
461
466 DifferenceType distance_to( const Self& other ) const
467 {
468 ASSERT_MSG( // we should only compare iterators on the same domain and same dimensions
469 mylower == other.mylower && myupper == other.myupper && mySubDomain == other.mySubDomain,
470 "The compared iterators iterate on different domains or different dimensions."
471 );
472
473 return other.pos - pos;
474 }
475
476 private:
478 TPoint myPoint;
479
482
486 std::vector<Dimension> mySubDomain;
487
490
491 }; // End of class HyperRectDomain_subIterator
492
493} //namespace
494// //
496
497#endif // !defined HyperRectDomain_Iterator_h
498
499#undef HyperRectDomain_Iterator_RECURSES
500#endif // else defined(HyperRectDomain_Iterator_RECURSES)
HyperRectDomain_Iterator(const Point &p, const Point &lower, const Point &upper)
HyperRectDomain iterator constructor.
bool equal(const Self &other) const
Compare iterators.
typename std::iterator_traits< Self >::difference_type DifferenceType
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).
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)...
typename std::iterator_traits< Self >::difference_type DifferenceType
DifferenceType distance_to(const Self &other) const
Distance between two iterators on the same domain.
const Point & dereference() const
Dereference.
HyperRectDomain_ReverseIterator< Iterator > Self
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.
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...
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
HyperRectDomain_subIterator(const TPoint &p, const TPoint &lower, const TPoint &upper, const std::vector< Dimension > &subDomain)
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)