DGtal  1.3.beta
testHyperRectDomain.cpp
Go to the documentation of this file.
1 
33 #include <cstdio>
34 #include <cmath>
35 #include <iostream>
36 #include <fstream>
37 #include <algorithm>
38 #include <numeric>
39 #include <iterator>
40 
41 #include "DGtal/base/Common.h"
42 #include "DGtal/kernel/SpaceND.h"
43 #include "DGtal/kernel/PointVector.h"
44 #include "DGtal/kernel/domains/HyperRectDomain.h"
45 #include "DGtal/base/CConstBidirectionalRange.h"
46 
47 #include "DGtalCatch.h"
48 
49 using namespace DGtal;
50 using namespace std;
51 
52 
54 // Simple test of HyperRectDomain construction.
55 
56 TEST_CASE( "Simple HyperRectDomain", "[domain][4D]" )
57 {
58  typedef SpaceND<4> Space4Type;
59  typedef Space4Type::Point Point;
61 
62  Space4Type::Integer t [] = { 1, 2, 3 , 4};
63  Point a ( t );
64  Space4Type::Integer t2[] = { 5, 5, 3 , 4};
65  Point b ( t2 );
66  double td [] = { 1.1, 2.5, 3 , 4};
67  RealPoint c ( td );
68  double td2[] = { 4.9, 4.5, 3 , 4};
69  RealPoint d ( td2 );
70 
71  trace.beginBlock ( "HyperRectDomain init" );
72 
73  // Checking that HyperRectDomain is a model of CDomain.
74  typedef HyperRectDomain<Space4Type> HRDomain4;
75  BOOST_CONCEPT_ASSERT(( concepts::CDomain< HRDomain4 > ));
76  BOOST_CONCEPT_ASSERT(( concepts::CConstBidirectionalRange<HRDomain4> ));
77 
78  // Empty domain using the default constructor
79  trace.info() << "Empty domain using the default constructor" << std::endl;
80  HyperRectDomain<Space4Type> myEmptyDomain;
81 
82  trace.info() << "Empty domain = " << myEmptyDomain << std::endl;
83  REQUIRE( myEmptyDomain.isValid() );
84  REQUIRE( myEmptyDomain.isEmpty() );
85  REQUIRE( myEmptyDomain.size() == 0 );
86  REQUIRE( (myEmptyDomain.end() - myEmptyDomain.begin()) == 0 );
87  REQUIRE( (myEmptyDomain.begin() - myEmptyDomain.end()) == 0 );
88  REQUIRE( (myEmptyDomain.rend() - myEmptyDomain.rbegin()) == 0 );
89  REQUIRE( (myEmptyDomain.rbegin() - myEmptyDomain.rend()) == 0 );
90 
91  // Domain characterized by points a and b
92  trace.info() << "Domain characterized by points a and b" << std::endl;
93  HyperRectDomain<Space4Type> myHyperRectDomain ( a, b );
94 
95  trace.info() << "Domain = " << myHyperRectDomain << std::endl;
96  REQUIRE( myHyperRectDomain.isValid() );
97  REQUIRE( myHyperRectDomain.lowerBound() == a );
98  REQUIRE( myHyperRectDomain.upperBound() == b );
99 
100  trace.info() << "Domain size = " << myHyperRectDomain.size() << std::endl;
101  REQUIRE( myHyperRectDomain.size() == 20 );
102  REQUIRE( (myHyperRectDomain.end() - myHyperRectDomain.begin()) == 20 );
103  REQUIRE( (myHyperRectDomain.begin() - myHyperRectDomain.end()) == -20 );
104  REQUIRE( (myHyperRectDomain.rend() - myHyperRectDomain.rbegin()) == 20 );
105  REQUIRE( (myHyperRectDomain.rbegin() - myHyperRectDomain.rend()) == -20 );
106 
107  // Domain initialized with RealPoint
108  trace.info() << "Domain initialized with RealPoint" << std::endl;
109  HyperRectDomain<Space4Type> myHyperRectDomain_rr ( c, d );
110  trace.info() << "Domain = " << myHyperRectDomain_rr << std::endl;
111  REQUIRE( myHyperRectDomain_rr.isValid() );
112  REQUIRE( myHyperRectDomain_rr.lowerBound() == myHyperRectDomain.lowerBound() );
113  REQUIRE( myHyperRectDomain_rr.upperBound() == myHyperRectDomain.upperBound() );
114 
115  HyperRectDomain<Space4Type> myHyperRectDomain_ir ( a, d );
116  trace.info() << "Domain = " << myHyperRectDomain_ir << std::endl;
117  REQUIRE( myHyperRectDomain_ir.isValid() );
118  REQUIRE( myHyperRectDomain_ir.lowerBound() == myHyperRectDomain.lowerBound() );
119  REQUIRE( myHyperRectDomain_ir.upperBound() == myHyperRectDomain.upperBound() );
120 
121  HyperRectDomain<Space4Type> myHyperRectDomain_ri ( c, b );
122  trace.info() << "Domain = " << myHyperRectDomain_ri << std::endl;
123  REQUIRE( myHyperRectDomain_ri.isValid() );
124  REQUIRE( myHyperRectDomain_ri.lowerBound() == myHyperRectDomain.lowerBound() );
125  REQUIRE( myHyperRectDomain_ri.upperBound() == myHyperRectDomain.upperBound() );
126 
127  trace.endBlock();
128 
129  // Test Copy Constructor
130  trace.beginBlock("Test Copy Constructor");
131  HyperRectDomain<Space4Type> myHyperRectDomainBis( myHyperRectDomain );
132  trace.info() << "Domain = " << myHyperRectDomainBis << std::endl;
133  trace.info() << "Domain size = " << myHyperRectDomainBis.size() << std::endl;
134  REQUIRE( myHyperRectDomainBis.isValid() );
135  REQUIRE( myHyperRectDomainBis.lowerBound() == myHyperRectDomain.lowerBound() );
136  REQUIRE( myHyperRectDomainBis.upperBound() == myHyperRectDomain.upperBound() );
137  REQUIRE( myHyperRectDomainBis.size() == 20 );
138  trace.endBlock();
139 
140  // Test Assignement
141  trace.beginBlock("Test Assignement");
142  HyperRectDomain<Space4Type> myHyperRectDomainTer;
143  myHyperRectDomainTer = myHyperRectDomain;
144  trace.info() << "Domain = " << myHyperRectDomainTer << std::endl;
145  trace.info() << "Domain size = " << myHyperRectDomainTer.size() << std::endl;
146  REQUIRE( myHyperRectDomainTer.isValid() );
147  REQUIRE( myHyperRectDomainTer.lowerBound() == myHyperRectDomain.lowerBound() );
148  REQUIRE( myHyperRectDomainTer.upperBound() == myHyperRectDomain.upperBound() );
149  REQUIRE( myHyperRectDomainTer.size() == 20 );
150  trace.endBlock();
151 }
152 
154 // Checking iterators
155 
157 template <
158  typename Iterator,
159  typename Point,
160  typename Domain,
161  typename Dimension
162 >
164  Iterator & it, Iterator const& it_begin, Iterator const& it_end,
165  typename std::iterator_traits<Iterator>::difference_type & cnt_begin,
166  Point & pt, Domain const& domain, std::vector<Dimension> const& dimensions, std::size_t id,
167  bool forward)
168 {
169  if (id == 0)
170  {
171  trace.warning() << *it << std::endl;
172  REQUIRE( it != it_end );
173  REQUIRE( pt == *it );
174  REQUIRE( std::distance(it_begin, it) == cnt_begin );
175  REQUIRE( std::distance(it, it_begin) == -cnt_begin );
176  INFO( *(it_begin + cnt_begin) << " == " << *it );
177  REQUIRE( it_begin + cnt_begin == it );
178  INFO( *(it - cnt_begin) << " == " << *it_begin);
179  REQUIRE( it - cnt_begin == it_begin );
180  ++it;
181  ++cnt_begin;
182  return;
183  }
184 
185  --id;
186 
187  const auto d = dimensions[id];
188 
189  if (forward)
190  {
191  while ( pt[d] <= domain.upperBound()[d] )
192  {
193  testIteratorHelperImpl(it, it_begin, it_end, cnt_begin, pt, domain, dimensions, id, forward);
194  ++pt[d];
195  }
196 
197  pt[d] = domain.lowerBound()[d];
198  }
199  else
200  {
201  while ( pt[d] >= domain.lowerBound()[d] )
202  {
203  testIteratorHelperImpl(it, it_begin, it_end, cnt_begin, pt, domain, dimensions, id, forward);
204  --pt[d];
205  }
206 
207  pt[d] = domain.upperBound()[d];
208  }
209 }
210 
211 template <
212  typename Iterator,
213  typename Point,
214  typename Domain,
215  typename Dimension
216 >
218  Iterator const& it_begin, Iterator const& it_end,
219  Point pt, Domain const& domain, std::vector<Dimension> const& dimensions,
220  bool forward = true)
221 {
222  Iterator it = it_begin;
223  typename std::iterator_traits<Iterator>::difference_type cnt_begin = 0;
224 
226  it, it_begin, it_end, cnt_begin,
227  pt, domain, dimensions, dimensions.size(),
228  forward);
229  REQUIRE( it == it_end );
230 }
231 
232 template <
233  typename Iterator,
234  typename Point,
235  typename Domain
236 >
238  Iterator const& it_begin, Iterator const& it_end,
239  Point pt, Domain const& domain, bool forward = true)
240 {
241  using Dimension = typename Domain::Dimension;
242  std::vector<Dimension> dimensions(Domain::dimension);
243  std::iota(dimensions.begin(), dimensions.end(), Dimension(0));
244 
245  testIteratorHelper(it_begin, it_end, pt, domain, dimensions, forward);
246 }
247 
248 template <
249  typename Point
250 >
251 void testIterator(Point const& a, Point const& b, Point const& c)
252 {
253  using Dimension = typename Point::Dimension;
256 
257  Domain domain(a, b);
258  trace.info() << "Domain = " << domain << std::endl;
259 
260  trace.emphase() << "Iterator" << std::endl;
262 
263  trace.emphase() << "Reverse iterator" << std::endl;
265 
266  trace.emphase() << "Iterator from starting point" << std::endl;
268 
269  trace.emphase() << "Reverse iterator from starting point" << std::endl;
270  testIteratorHelper(domain.rbegin(c), domain.rend(), c, domain, false);
271 
272  trace.emphase() << "Iterator on reversed dimension order: " << std::endl;
273  std::vector<Dimension> dimensions(Point::dimension);
274  std::iota(dimensions.rbegin(), dimensions.rend(), Dimension(0));
275  const auto range = domain.subRange(dimensions);
276  testIteratorHelper(range.begin(), range.end(), domain.lowerBound(), domain, dimensions);
277 
278  trace.emphase() << "Reverse iterator on reversed dimension order: " << std::endl;
279  testIteratorHelper(range.rbegin(), range.rend(), domain.upperBound(), domain, dimensions, false);
280 
281  trace.emphase() << "Iterator on reversed dimension order and from a starting point: " << std::endl;
282  const auto range2 = domain.subRange(dimensions);
283  testIteratorHelper(range2.begin(c), range2.end(), c, domain, dimensions);
284 
285  trace.emphase() << "Reverse iterator on reversed dimension order and from a starting point: " << std::endl;
286  testIteratorHelper(range2.rbegin(c), range2.rend(), c, domain, dimensions, false);
287 
288  trace.emphase() << "Iterator along one dimension: " << std::endl;
289  const auto range3 = domain.subRange({1});
290  const std::vector<Dimension> one_dimension({1});
291  testIteratorHelper(range3.begin(), range3.end(), domain.lowerBound(), domain, one_dimension);
292 
293  trace.emphase() << "Reverse iterator along one dimension: " << std::endl;
294  auto upper_one_dim = domain.lowerBound();
295  upper_one_dim.partialCopy(domain.upperBound(), one_dimension);
296  testIteratorHelper(range3.rbegin(), range3.rend(), upper_one_dim, domain, one_dimension, false);
297 
298  trace.emphase() << "Iterator along one dimension and from a starting point: " << std::endl;
299  const auto range4 = domain.subRange({1}, c);
300  testIteratorHelper(range4.begin(c), range4.end(), c, domain, one_dimension);
301 
302  trace.emphase() << "Reverse iterator along one dimension and from a starting point: " << std::endl;
303  testIteratorHelper(range4.rbegin(c), range4.rend(), c, domain, one_dimension, false);
304 }
305 
306 TEST_CASE( "Iterator 2D", "[iterator][2D]" )
307 {
308  using Space = SpaceND<2>;
309  using Point = Space::Point;
310 
311  Point a (1, 1);
312  Point b (4, 5);
313  Point c (2, 2);
314 
315  trace.beginBlock( "Iterator 2D" );
316  testIterator(a, b, c);
317  trace.endBlock();
318 }
319 
320 TEST_CASE( "Iterator 4D", "[iterator][4D]" )
321 {
322  using Space = SpaceND<4>;
323  using Point = Space::Point;
324 
325  Point a({1, 1, 1, 1});
326  Point b({2, 3, 4, 5});
327  Point c({1, 2, 3, 2});
328 
329  trace.beginBlock( "Iterator 4D" );
330  testIterator(a, b, c);
331  trace.endBlock();
332 }
333 
334 #ifdef WITH_BIGINTEGER
335 TEST_CASE( "Iterator 4D GMP", "[iterator][4D][GMP]" )
336 {
338  using Point = Space::Point;
339 
340  Point a({1, 1, 1, 1});
341  Point b({2, 3, 4, 5});
342  Point c({1, 2, 3, 2});
343 
344  trace.beginBlock( "Iterator 4D using GMP" );
345  testIterator(a, b, c);
346  trace.endBlock();
347 }
348 #endif
349 
350 TEST_CASE( "STL compatiblity", "[iterator][4D][STL]" )
351 {
352  typedef SpaceND<4> TSpace4D;
353  typedef TSpace4D::Point Point4D;
354  TSpace4D::Integer t[] = {1, 1, 1, 1};
355  Point4D a4D (t);
356  TSpace4D::Integer t2[] = {3, 3, 3, 3};
357  Point4D b4D (t2);
358 
359  trace.beginBlock ( "TestSTL Compatibility" );
360 
361  HyperRectDomain<TSpace4D> myHyperRectDomain4D ( a4D, b4D );
362  trace.emphase() << myHyperRectDomain4D << std::endl;
363 
364  std::copy ( myHyperRectDomain4D.begin(),
365  myHyperRectDomain4D.end(),
366  ostream_iterator<Point4D> ( trace.info(), " " ) );
367 
368  trace.info() << std::endl;
369  trace.endBlock();
370 }
371 
372 TEST_CASE( "Empty domain", "[domain][3D][empty]" )
373 {
374  typedef SpaceND<3> TSpace;
375  typedef TSpace::Point TPoint;
376  typedef HyperRectDomain<TSpace> TDomain;
377 
378  const TDomain nonempty_domain( TPoint::diagonal(0), TPoint::diagonal(0) );
379  REQUIRE( !nonempty_domain.isEmpty() );
380 
381  const TDomain default_domain;
382  REQUIRE( default_domain.isEmpty() );
383 
384  const TDomain domain( TPoint::diagonal(1), TPoint::diagonal(0) );
385  REQUIRE( domain.isEmpty() );
386  REQUIRE( domain.size() == 0 );
387  REQUIRE( domain.begin() == domain.end() );
388  REQUIRE( domain.rbegin() == domain.rend() );
389 
390  TDomain::ConstSubRange range = domain.subRange( 0, 1, 2, domain.lowerBound() );
391  REQUIRE( range.begin() == range.end() );
392  REQUIRE( range.rbegin() == range.rend() );
393 
394  range = domain.subRange( 2, 1, 0, domain.lowerBound() );
395  REQUIRE( range.begin() == range.end() );
396  REQUIRE( range.rbegin() == range.rend() );
397 
398  range = domain.subRange( 0, 2, domain.lowerBound() );
399  REQUIRE( range.begin() == range.end() );
400  REQUIRE( range.rbegin() == range.rend() );
401 
402  range = domain.subRange( 2, 0, domain.lowerBound() );
403  REQUIRE( range.begin() == range.end() );
404  REQUIRE( range.rbegin() == range.rend() );
405 
406  range = domain.subRange( 1, domain.lowerBound() );
407  REQUIRE( range.begin() == range.end() );
408  REQUIRE( range.rbegin() == range.rend() );
409 }
410 
DGtal::HyperRectDomain::rend
ConstReverseIterator rend() const
Definition: HyperRectDomain.h:236
DGtal::HyperRectDomain::isEmpty
bool isEmpty() const
DGtal::HyperRectDomain< Space >::Dimension
Space::Dimension Dimension
Definition: HyperRectDomain.h:116
DGtal::HyperRectDomain
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
Definition: HyperRectDomain.h:99
DGtal::Trace::endBlock
double endBlock()
DGtal::HyperRectDomain::size
Size size() const
Definition: HyperRectDomain.h:565
DGtal::SpaceND::Point
PointVector< dim, Integer > Point
Points in DGtal::SpaceND.
Definition: SpaceND.h:110
DGtal::HyperRectDomain::upperBound
const Point & upperBound() const
DGtal::Trace::emphase
std::ostream & emphase()
DGtal::trace
Trace trace
Definition: Common.h:154
DGtal::Dimension
DGtal::uint32_t Dimension
Definition: Common.h:137
DGtal::Trace::beginBlock
void beginBlock(const std::string &keyword="")
REQUIRE
REQUIRE(domain.isInside(aPoint))
testIteratorHelper
void testIteratorHelper(Iterator const &it_begin, Iterator const &it_end, Point pt, Domain const &domain, std::vector< Dimension > const &dimensions, bool forward=true)
Definition: testHyperRectDomain.cpp:217
DGtal::PointVector::partialCopy
Self & partialCopy(const PointVector< dim, OtherComponent, OtherContainer > &pv, const std::vector< Dimension > &dimensions)
Partial copy of a given PointVector.
testIterator
void testIterator(Point const &a, Point const &b, Point const &c)
Definition: testHyperRectDomain.cpp:251
DGtal::SpaceND
Definition: SpaceND.h:95
testIteratorHelperImpl
void testIteratorHelperImpl(Iterator &it, Iterator const &it_begin, Iterator const &it_end, typename std::iterator_traits< Iterator >::difference_type &cnt_begin, Point &pt, Domain const &domain, std::vector< Dimension > const &dimensions, std::size_t id, bool forward)
Checking iterator given then span domain and dimensions order.
Definition: testHyperRectDomain.cpp:163
DGtal::Trace::info
std::ostream & info()
DGtal::concepts::CDomain
Aim: This concept represents a digital domain, i.e. a non mutable subset of points of the given digit...
Definition: CDomain.h:129
DGtal
DGtal is the top-level namespace which contains all DGtal functions and types.
Domain
HyperRectDomain< Space > Domain
Definition: testSimpleRandomAccessRangeFromPoint.cpp:44
DGtal::HyperRectDomain::end
const ConstIterator & end() const
Definition: HyperRectDomain.h:201
DGtal::concepts::CConstBidirectionalRange
Aim: Defines the concept describing a bidirectional const range.
Definition: CConstBidirectionalRange.h:89
TEST_CASE
TEST_CASE("Simple HyperRectDomain", "[domain][4D]")
Definition: testHyperRectDomain.cpp:56
Integer
Point::Coordinate Integer
Definition: examplePlaneProbingParallelepipedEstimator.cpp:44
domain
Domain domain
Definition: testProjection.cpp:88
DGtal::PointVector
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:165
DGtal::HyperRectDomain::isValid
bool isValid() const
DGtal::HyperRectDomain::subRange
ConstSubRange subRange(const std::vector< Dimension > &permutation) const
Definition: HyperRectDomain.h:472
DGtal::Trace::warning
std::ostream & warning()
DGtal::HyperRectDomain::begin
const ConstIterator & begin() const
Definition: HyperRectDomain.h:176
DGtal::HyperRectDomain::rbegin
ConstReverseIterator rbegin() const
Definition: HyperRectDomain.h:210
Point
MyPointD Point
Definition: testClone2.cpp:383
RealPoint
Z2i::RealPoint RealPoint
Definition: testAstroid2D.cpp:46
DGtal::HyperRectDomain::lowerBound
const Point & lowerBound() const