DGtal 1.3.0
Loading...
Searching...
No Matches
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
49using namespace DGtal;
50using namespace std;
51
52
54// Simple test of HyperRectDomain construction.
55
56TEST_CASE( "Simple HyperRectDomain", "[domain][4D]" )
57{
58 typedef SpaceND<4> Space4Type;
59 typedef Space4Type::Point Point;
60 typedef Space4Type::RealPoint RealPoint;
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
157template <
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
211template <
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
232template <
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
248template <
249 typename Point
250>
251void 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;
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
306TEST_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
320TEST_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
335TEST_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
350TEST_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
372TEST_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) );
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
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
const ConstIterator & begin() const
const Point & lowerBound() const
ConstReverseIterator rbegin() const
const Point & upperBound() const
ConstSubRange subRange(const std::vector< Dimension > &permutation) const
ConstReverseIterator rend() const
const ConstIterator & end() const
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:593
Self & partialCopy(const PointVector< dim, OtherComponent, OtherContainer > &pv, const std::vector< Dimension > &dimensions)
Partial copy of a given PointVector.
PointVector< dim, Integer > Point
Points in DGtal::SpaceND.
Definition: SpaceND.h:110
void beginBlock(const std::string &keyword="")
std::ostream & warning()
std::ostream & emphase()
std::ostream & info()
double endBlock()
DGtal is the top-level namespace which contains all DGtal functions and types.
DGtal::uint32_t Dimension
Definition: Common.h:137
Trace trace
Definition: Common.h:154
STL namespace.
Aim: Defines the concept describing a bidirectional const range.
Aim: This concept represents a digital domain, i.e. a non mutable subset of points of the given digit...
Definition: CDomain.h:130
Z2i::RealPoint RealPoint
MyPointD Point
Definition: testClone2.cpp:383
void testIterator(Point const &a, Point const &b, Point const &c)
void testIteratorHelper(Iterator const &it_begin, Iterator const &it_end, Point pt, Domain const &domain, std::vector< Dimension > const &dimensions, bool forward=true)
TEST_CASE("Simple HyperRectDomain", "[domain][4D]")
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.
Domain domain
HyperRectDomain< Space > Domain
REQUIRE(domain.isInside(aPoint))