Loading [MathJax]/extensions/TeX/AMSsymbols.js
DGtal 2.0.0
testObject-benchmark.cpp
1
16
29
31#include <cmath>
32#include <iostream>
33#include <sstream>
34#include "DGtal/base/Common.h"
35#include "DGtal/kernel/SpaceND.h"
36#include "DGtal/kernel/domains/DomainPredicate.h"
37#include "DGtal/kernel/domains/HyperRectDomain.h"
38#include "DGtal/kernel/sets/DigitalSetSelector.h"
39#include "DGtal/kernel/sets/DigitalSetConverter.h"
40#include "DGtal/topology/MetricAdjacency.h"
41#include "DGtal/topology/DomainAdjacency.h"
42#include "DGtal/topology/DigitalTopology.h"
43#include "DGtal/topology/Object.h"
44#include "DGtal/graph/Expander.h"
45#include "DGtal/io/boards/Board2D.h"
47
48using namespace std;
49using namespace DGtal;
50using namespace LibBoard;
51
52#define INBLOCK_TEST(x) \
53 nbok += ( x ) ? 1 : 0; \
54 nb++; \
55 trace.info() << "(" << nbok << "/" << nb << ") " \
56 << #x << std::endl;
57
58#define INBLOCK_TEST2(x,y) \
59 nbok += ( x ) ? 1 : 0; \
60 nb++; \
61 trace.info() << "(" << nbok << "/" << nb << ") " \
62 << y << std::endl;
63
65// Functions for testing class Object.
67
71bool testObject()
72{
73 unsigned int nbok = 0;
74 unsigned int nb = 0;
75
76 typedef SpaceND< 2 > Z2;
77 typedef Z2::Point Point;
78 typedef Point::Coordinate Coordinate;
79 typedef HyperRectDomain< Z2 > DomainType;
80 Point p1( -449, -449 );
81 Point p2( 449, 449 );
82 DomainType domain( p1, p2 );
83
84 // typedef DomainMetricAdjacency< DomainType, 1 > Adj4;
85 // typedef DomainMetricAdjacency< DomainType, 2 > Adj8;
86 typedef MetricAdjacency< Z2, 1 > MetricAdj4;
87 typedef MetricAdjacency< Z2, 2 > MetricAdj8;
92 MediumSet;
93// typedef DigitalSetSelector< DomainType, SMALL_DS >::Type
94// MediumSet;
95 typedef Object<DT48, MediumSet> ObjectType;
96 typedef ObjectType::SmallSet SmallSet;
97 typedef Object<DT48, SmallSet> SmallObjectType;
98 typedef ObjectType::Size Size;
99
100 // Adj4 adj4( domain );
101 // Adj8 adj8( domain );
102 MetricAdj4 madj4;
103 MetricAdj8 madj8;
104 Adj4 adj4( domain, madj4 );
105 Adj8 adj8( domain, madj8 );
106 DT48 dt48( adj4, adj8, JORDAN_DT );
107
108 Coordinate r = 449;
109 double radius = (double) (r + 1);
110 Point c( 0, 0 );
111 Point l( r, 0 );
112 MediumSet disk( domain );
113 ostringstream sstr;
114 sstr << "Creating disk( r < " << radius << " ) ...";
115 trace.beginBlock ( sstr.str() );
116 for ( DomainType::ConstIterator it = domain.begin();
117 it != domain.end();
118 ++it )
119 {
120 if ( (*it - c ).norm() < radius ) // 450.0
121 // insertNew is very important for vector container.
122 disk.insertNew( *it );
123 }
124 trace.endBlock();
125
126 trace.beginBlock ( "Testing Object instanciation and smart copy ..." );
127 ObjectType disk_object( dt48, disk );
128 nbok += disk_object.size() == 636101 ? 1 : 0;
129 nb++;
130 trace.info() << "(" << nbok << "/" << nb << ") "
131 << "Disk (r=450.0) " << disk_object << std::endl;
132 trace.info() << " size=" << disk_object.size() << std::endl;
133 ObjectType disk_object2( disk_object );
134 nbok += disk_object2.size() == 636101 ? 1 : 0;
135 nb++;
136 trace.info() << "(" << nbok << "/" << nb << ") "
137 << "Disk2 (r=450.0) " << disk_object2 << std::endl;
138 trace.info() << " size=" << disk_object2.size() << std::endl;
139 trace.endBlock();
140
141 trace.beginBlock ( "Testing copy on write system ..." );
142 trace.info() << "Removing center point in Disk." << std::endl;
143 disk_object.pointSet().erase( c );
144 disk_object2.pointSet().insert( c );
145 nbok += disk_object.size() == 636100 ? 1 : 0;
146 nb++;
147 trace.info() << "(" << nbok << "/" << nb << ") "
148 << "Disk - c (r=450.0) " << disk_object << std::endl;
149 trace.info() << " size=" << disk_object.size() << std::endl;
150 nbok += disk_object2.size() == 636101 ? 1 : 0;
151 nb++;
152 trace.info() << "(" << nbok << "/" << nb << ") "
153 << "Disk2 + c (r=450.0) " << disk_object2 << std::endl;
154 trace.info() << " size=" << disk_object2.size() << std::endl;
155 trace.endBlock();
156
157 trace.beginBlock ( "Testing neighborhoods ..." );
158 Object<DT48, SmallSet> neigh = disk_object.neighborhood( c );
159 nbok += neigh.size() == 4 ? 1 : 0;
160 nb++;
161 trace.info() << "(" << nbok << "/" << nb << ") "
162 << "N_4(Disk, c).size() = " << neigh.size()
163 << " == 4" << std::endl;
164 neigh = disk_object.properNeighborhood( l );
165 nbok += neigh.size() == 3 ? 1 : 0;
166 nb++;
167 trace.info() << "(" << nbok << "/" << nb << ") "
168 << "N*_4(Disk, " << l << ").size() = " << neigh.size()
169 << " == 3" << std::endl;
170 Size size = disk_object.properNeighborhoodSize( l );
171 nbok += size == 3 ? 1 : 0;
172 nb++;
173 trace.info() << "(" << nbok << "/" << nb << ") "
174 << "#N*_4(Disk, " << l << ") = " << size
175 << " == 3" << std::endl;
176
177 neigh = disk_object2.neighborhood( c );
178 nbok += neigh.size() == 5 ? 1 : 0;
179 nb++;
180 trace.info() << "(" << nbok << "/" << nb << ") "
181 << "N_4(Disk2, c).size() = " << neigh.size()
182 << " == 5" << std::endl;
183 trace.endBlock();
184
185 trace.beginBlock ( "Testing set converters ..." );
187 ( neigh.pointSet(), disk_object.pointSet() );
188 nbok += neigh.size() == 636100 ? 1 : 0;
189 nb++;
190 trace.info() << "(" << nbok << "/" << nb << ") "
191 << "neigh = disk_object, size() = " << neigh.size()
192 << " == 636100" << std::endl;
193 SmallObjectType neigh2 = disk_object2.neighborhood( c );
195 ( neigh.pointSet(), neigh2.pointSet() );
196 nbok += neigh.size() == 5 ? 1 : 0;
197 nb++;
198 trace.info() << "(" << nbok << "/" << nb << ") "
199 << "neigh = N_4(Disk2, c), size() = " << neigh.size()
200 << " == 5" << std::endl;
201 trace.endBlock();
202
203 trace.beginBlock ( "Testing border extraction ..." );
204 ObjectType bdisk = disk_object.border();
205 nbok += bdisk.size() == 3372 ? 1 : 0;
206 nb++;
207 trace.info() << "(" << nbok << "/" << nb << ") "
208 << "Border(Disk, c), size() = " << bdisk.size()
209 << " == 3372" << std::endl;
210 ObjectType bdisk2 = disk_object2.border();
211 nbok += bdisk2.size() == 3364 ? 1 : 0;
212 nb++;
213 trace.info() << "(" << nbok << "/" << nb << ") "
214 << "Border(Disk2, c), size() = " << bdisk2.size()
215 << " == 3364" << std::endl;
216 trace.endBlock();
217
218 trace.beginBlock ( "Testing expansion by layers on the boundary ..." );
219 typedef Expander< ObjectType > ObjectExpander;
220 ObjectExpander expander( bdisk, *(bdisk.pointSet().begin()) );
221 while ( ! expander.finished() )
222 {
223 nbok += expander.layer().size() <= 2 ? 1 : 0;
224 nb++;
225 trace.info() << "(" << nbok << "/" << nb << ") "
226 << "expander.layer.size() <= 2 "
227 << expander << std::endl;
228 expander.nextLayer();
229 }
230 trace.endBlock();
231
232 trace.beginBlock ( "Testing expansion by layers on the disk from center..." );
233 ObjectExpander expander2( disk_object2, c );
234 while ( ! expander2.finished() )
235 {
236 trace.info() << expander2 << std::endl;
237 expander2.nextLayer();
238 }
239 nbok += expander2.distance() <= sqrt(2.0) * radius ? 1 : 0;
240 nb++;
241 trace.info() << "(" << nbok << "/" << nb << ") "
242 << "expander.distance() = " << expander2.distance()
243 << " <= " << sqrt(2.0)*radius << std::endl;
244 trace.endBlock();
245
246 return nbok == nb;
247}
248
253bool testObject3D()
254{
255 unsigned int nbok = 0;
256 unsigned int nb = 0;
257 typedef SpaceND< 3 > Z3;
261 typedef Z3::Point Point;
263 typedef Domain::ConstIterator DomainConstIterator;
265 typedef Object<DT6_18, DigitalSet> ObjectType;
266 Adj6 adj6;
267 Adj18 adj18;
268 DT6_18 dt6_18( adj6, adj18, JORDAN_DT );
269
270 Point p1( -50, -50, -50 );
271 Point p2( 50, 50, 50 );
272 Domain domain( p1, p2 );
273 Point c( 0, 0, 0 );
274 Point d( 10, 2, 0 );
275
276 trace.beginBlock ( "Testing 3D Object instanciation and smart copy ..." );
277 trace.info() << "Creating diamond (r=45)" << endl;
278 // diamond of radius 30
279 DigitalSet diamond_set( domain );
280 for ( DomainConstIterator it = domain.begin(); it != domain.end(); ++it )
281 {
282 if ( (*it - c ).norm1() <= 45 )
283 diamond_set.insertNew( *it );
284 }
285 ObjectType diamond( dt6_18, diamond_set );
286 trace.info() << "Cloning diamond" << endl;
287 // The following line takes almost no time.
288 ObjectType diamond_clone( diamond );
289 // Since one of the objects is modified, the set is duplicated at the following line
290 trace.info() << "Removing two points " << c << " and " << d << endl;
291 diamond_clone.pointSet().erase( c );
292 diamond_clone.pointSet().erase( d );
293
294 trace.info() << "Inserting into vector<Object>" << endl;
295 vector<ObjectType> objects;
296 back_insert_iterator< vector< ObjectType > > inserter( objects );
297 *inserter++ = diamond;
298 *inserter++ = diamond_clone;
299
300 for ( vector<ObjectType>::const_iterator it = objects.begin();
301 it != objects.end();
302 ++it )
303 trace.info() << "- objects[" << (it - objects.begin() ) << "]"
304 << " = " << *it << endl;
305
306 INBLOCK_TEST( objects[ 0 ].size() == ( objects[ 1 ].size() + 2 ) );
307 INBLOCK_TEST( objects[ 0 ].size() == 125671 );
308 trace.endBlock();
309
310 trace.beginBlock ( "Testing connected component extraction ..." );
311 // JOL: do like this for output iterators pointing on the same
312 // container as 'this'. Works fine and nearly as fast.
313 //
314 // ObjectType( objects[ 0 ] ).writeComponents( inserter );
315
316 trace.beginBlock ( "Components of diamond.border() ..." );
317 vector<ObjectType> objects2;
318 back_insert_iterator< vector< ObjectType > > inserter2( objects2 );
319 const auto nbc0 = objects[ 0 ].border().writeComponents( inserter2 );
320 INBLOCK_TEST( nbc0 == 1 );
321 INBLOCK_TEST( objects[ 0 ].computeConnectedness() == CONNECTED );
322 trace.endBlock();
323
324 trace.beginBlock ( "Components of diamond_clone.border() ..." );
325 const auto nbc1 = objects[ 1 ].border().writeComponents( inserter2 );
326 INBLOCK_TEST( nbc1 == 3 );
327 trace.endBlock();
328 for ( vector<ObjectType>::const_iterator it = objects2.begin();
329 it != objects2.end();
330 ++it )
331 trace.info() << "- objects2[" << (it - objects2.begin() ) << "]"
332 << " = " << *it << endl;
333 INBLOCK_TEST( objects2[ 0 ].size() == objects2[ 1 ].size() );
334 INBLOCK_TEST( objects2[ 2 ].size() == objects2[ 3 ].size() );
335 INBLOCK_TEST( objects2[ 0 ].size() == 15848 );
336 INBLOCK_TEST( objects2[ 2 ].size() == 18 );
337
338 trace.endBlock();
339
340 return nbok == nb;
341
342}
343
349{
350 unsigned int nbok = 0;
351 unsigned int nb = 0;
352 typedef SpaceND< 3 > Z3;
356 typedef Z3::Point Point;
358 typedef Domain::ConstIterator DomainConstIterator;
360 typedef Object<DT6_18, DigitalSet> ObjectType;
361 typedef Object<DT6_18, DigitalSet>::SmallObject SmallObjectType;
362 typedef Object<DT6_18, DigitalSet>::SmallComplementObject SmallComplementObjectType;
363 Adj6 adj6;
364 Adj18 adj18;
365 DT6_18 dt6_18( adj6, adj18, JORDAN_DT );
366
367 Point p1( -10, -10, -10 );
368 Point p2( 10, 10, 10 );
369 Domain domain( p1, p2 );
370 Point c( 0, 0, 0 );
371 Point r( 3, 0, 0 );
372
373 trace.beginBlock ( "Creating Diamond (r=4)" );
374 // diamond of radius 4
375 DigitalSet diamond_set( domain );
376 for ( DomainConstIterator it = domain.begin(); it != domain.end(); ++it )
377 {
378 if ( (*it - c ).norm1() <= 3 )
379 diamond_set.insertNew( *it );
380 }
381 diamond_set.erase( c );
382 ObjectType diamond( dt6_18, diamond_set );
383 trace.endBlock();
384
385 trace.beginBlock ( "Geodesic neighborhoods ..." );
386 SmallObjectType geoN6_3 = diamond.geodesicNeighborhood( adj6, r, 3 );
387 SmallObjectType geoN18_2 = diamond.geodesicNeighborhood( adj18, r, 2 );
388 trace.info() << "geoN6_3 = " << geoN6_3 << endl;
389 trace.info() << "geoN18_2 = " << geoN18_2 << endl;
390 SmallComplementObjectType cgeoN6_3 = diamond.geodesicNeighborhoodInComplement( adj6, r, 3 );
391 SmallComplementObjectType cgeoN18_2 = diamond.geodesicNeighborhoodInComplement( adj18, r, 2 );
392 trace.info() << "cgeoN6_3 = " << cgeoN6_3 << endl;
393 trace.info() << "cgeoN18_2 = " << cgeoN18_2 << endl;
394 trace.endBlock();
395
396 trace.beginBlock ( "Simple points ..." );
397 for ( DigitalSet::ConstIterator it = diamond.pointSet().begin();
398 it != diamond.pointSet().end();
399 ++it )
400 trace.info() << "- " << *it
401 << " " << ( diamond.isSimple( *it ) ? "Simple" : "Not simple" )
402 << endl;
403 trace.endBlock();
404
405
406 return nbok == nb;
407}
408
409
410bool testDraw()
411{
412 unsigned int nbok = 0;
413 unsigned int nb = 0;
414
415 trace.beginBlock ( "testDraw(): testing drawing commands." );
416
417 typedef SpaceND< 2 > Z2;
418 typedef Z2::Point Point;
419 typedef Point::Coordinate Coordinate;
420 typedef HyperRectDomain< Z2 > DomainType;
421 Point p1( -10, -10 );
422 Point p2( 10, 10 );
423 DomainType domain( p1, p2 );
424
425 // typedef DomainMetricAdjacency< DomainType, 1 > Adj4;
426 // typedef DomainMetricAdjacency< DomainType, 2 > Adj8;
427 typedef MetricAdjacency< Z2, 1 > MetricAdj4;
428 typedef MetricAdjacency< Z2, 2 > MetricAdj8;
434 MediumSet;
435// typedef DigitalSetSelector< DomainType, SMALL_DS >::Type
436// MediumSet;
437 typedef Object<DT48, MediumSet> ObjectType;
438 typedef Object<DT84, MediumSet> ObjectType84;
439
440 //typedef ObjectType::SmallSet SmallSet;
441 //typedef Object<DT48, SmallSet> SmallObjectType;
442 //typedef ObjectType::Size Size;
443
444 // Adj4 adj4( domain );
445 // Adj8 adj8( domain );
446 MetricAdj4 madj4;
447 MetricAdj8 madj8;
448 Adj4 adj4( domain, madj4 );
449 Adj8 adj8( domain, madj8 );
450 DT48 dt48( adj4, adj8, JORDAN_DT );
451 DT84 dt84( adj8, adj4, JORDAN_DT );
452
453 Coordinate r = 5;
454 double radius = (double) (r + 1);
455 Point c( 0, 0 );
456 Point l( r, 0 );
457 MediumSet disk( domain );
458 ostringstream sstr;
459 sstr << "Creating disk( r < " << radius << " ) ...";
460 trace.beginBlock ( sstr.str() );
461 for ( DomainType::ConstIterator it = domain.begin();
462 it != domain.end();
463 ++it )
464 {
465 if ( (*it - c ).norm() < radius ) // 450.0
466 // insertNew is very important for vector container.
467 disk.insertNew( *it );
468 }
469 trace.endBlock();
470
471 trace.beginBlock ( "Testing Object instanciation and smart copy ..." );
472 ObjectType disk_object( dt48, disk );
473 ObjectType84 disk_object2( dt84, disk );
474 trace.endBlock();
475
476 trace.beginBlock ( "Testing export as SVG with libboard." );
477
478 Board2D board;
480
481 board << SetMode( domain.className(), "Grid" ) << domain;
482 board << disk_object;
483
484 board.saveSVG("disk-object.svg");
485
486 Board2D board2;
488
489 board2 << SetMode( domain.className(), "Grid" ) << domain;
490 board2 << SetMode( disk_object.className(), "DrawAdjacencies" ) << disk_object;
491
492 board2.saveSVG("disk-object-adj.svg");
493
494 Board2D board3;
495 board3.setUnit( Board::UCentimeter );
496
497 board3 << SetMode( domain.className(), "Grid" ) << domain;
498 board3 << SetMode( disk_object2.className(), "DrawAdjacencies" ) << disk_object2;
499
500 board3.saveSVG("disk-object-adj-bis.svg");
501 trace.endBlock();
502
503 trace.endBlock();
504
505 return nbok == nb;
506
507}
508
510// Standard services - public :
511
512int main( int argc, char** argv )
513{
514 trace.beginBlock ( "Testing class Object" );
515 trace.info() << "Args:";
516 for ( int i = 0; i < argc; ++i )
517 trace.info() << " " << argv[ i ];
518 trace.info() << endl;
519
520 bool res = testObject() &&
523
524 trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
525 trace.endBlock();
526 return res ? 0 : 1;
527}
528// //
Aim: This class specializes a 'Board' class so as to display DGtal objects more naturally (with <<)....
Definition Board2D.h:71
Aim: Given a domain and an adjacency, limits the given adjacency to the specified domain for all adja...
Aim: This class is useful to visit an object by adjacencies, layer by layer.
Definition Expander.h:98
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
Aim: Describes digital adjacencies in digital spaces that are defined with the 1-norm and the infinit...
Aim: An object (or digital object) represents a set in some digital space associated with a digital t...
Definition Object.h:120
Size size() const
Object< ReverseTopology, SmallSet > SmallComplementObject
Definition Object.h:154
const DigitalSet & pointSet() const
SmallObject properNeighborhood(const Point &p) const
SmallObject neighborhood(const Point &p) const
Object< DigitalTopology, SmallSet > SmallObject
Definition Object.h:153
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition Board.cpp:1011
void setUnit(Unit unit)
Definition Board.cpp:239
MetricAdjacency< Space, 1 > Adj4
Definition StdDefs.h:90
MetricAdjacency< Space, 2 > Adj8
Definition StdDefs.h:92
Space Z2
Definition StdDefs.h:76
MetricAdjacency< Space, 2 > Adj18
Definition StdDefs.h:161
Space Z3
Definition StdDefs.h:145
MetricAdjacency< Space, 1 > Adj6
Definition StdDefs.h:159
DigitalTopology< Adj6, Adj18 > DT6_18
Definition StdDefs.h:164
DGtal is the top-level namespace which contains all DGtal functions and types.
@ CONNECTED
Definition Topology.h:52
Trace trace
STL namespace.
static void assign(OutputDigitalSet &output, const InputDigitalSet &input)
DigitalSetByAssociativeContainer< Domain, std::unordered_set< typename Domain::Point > > Type
Modifier class in a Board2D stream. Useful to choose your own mode for a given class....
Definition Board2D.h:247
Struct representing a 2D point.
Definition Point.h:27
#define INBLOCK_TEST(x)
int main()
Definition testBits.cpp:56
HalfEdgeDataStructure::Size Size
bool testObject3D()
bool testSimplePoints3D()
bool testObject()
bool testDraw()
Domain domain
Z2i::DigitalSet DigitalSet