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