DGtal  1.4.beta
testObject.cpp
Go to the documentation of this file.
1 
31 #include <cmath>
32 #include <iostream>
33 #include <sstream>
34 #include <queue>
35 #include "DGtal/base/Common.h"
36 #include "DGtal/kernel/SpaceND.h"
37 #include "DGtal/kernel/domains/DomainPredicate.h"
38 #include "DGtal/kernel/domains/HyperRectDomain.h"
39 #include "DGtal/kernel/sets/DigitalSetSelector.h"
40 #include "DGtal/kernel/sets/DigitalSetConverter.h"
41 #include "DGtal/topology/MetricAdjacency.h"
42 #include "DGtal/topology/DomainMetricAdjacency.h"
43 #include "DGtal/topology/DomainAdjacency.h"
44 #include "DGtal/topology/DigitalTopology.h"
45 #include "DGtal/topology/Object.h"
46 #include "DGtal/graph/Expander.h"
47 #include "DGtal/io/boards/Board2D.h"
48 #include "DGtal/io/Color.h"
49 #include "DGtal/io/colormaps/GradientColorMap.h"
50 #include "DGtal/shapes/Shapes.h"
51 #include "DGtal/helpers/StdDefs.h"
52 #include "DGtal/topology/NeighborhoodConfigurations.h"
53 #include "DGtal/topology/tables/NeighborhoodTables.h"
55 
56 using namespace std;
57 using namespace DGtal;
58 using namespace LibBoard;
59 
60 #define INBLOCK_TEST(x) \
61  nbok += ( x ) ? 1 : 0; \
62  nb++; \
63  trace.info() << "(" << nbok << "/" << nb << ") " \
64  << #x << std::endl;
65 
66 #define INBLOCK_TEST2(x,y) \
67  nbok += ( x ) ? 1 : 0; \
68  nb++; \
69  trace.info() << "(" << nbok << "/" << nb << ") " \
70  << y << std::endl;
71 
73 // Functions for testing class Object.
75 
79 bool testObject()
80 {
81  unsigned int nbok = 0;
82  unsigned int nb = 0;
83 
84  typedef SpaceND< 2 > Z2;
85  typedef Z2::Point Point;
86  typedef Point::Coordinate Coordinate;
87  typedef HyperRectDomain< Z2 > DomainType;
88  Point p1( -449, -449 );
89  Point p2( 449, 449 );
90  DomainType domain( p1, p2 );
91 
92  // typedef DomainMetricAdjacency< DomainType, 1 > Adj4;
93  // typedef DomainMetricAdjacency< DomainType, 2 > Adj8;
94  typedef MetricAdjacency< Z2, 1 > MetricAdj4;
95  typedef MetricAdjacency< Z2, 2 > MetricAdj8;
98  typedef DigitalTopology< Adj4, Adj8 > DT48;
100  MediumSet;
101 // typedef DigitalSetSelector< DomainType, SMALL_DS >::Type
102 // MediumSet;
103  typedef Object<DT48, MediumSet> ObjectType;
104  typedef ObjectType::SmallSet SmallSet;
105  typedef Object<DT48, SmallSet> SmallObjectType;
106  typedef ObjectType::Size Size;
107 
108  // Adj4 adj4( domain );
109  // Adj8 adj8( domain );
110  MetricAdj4 madj4;
111  MetricAdj8 madj8;
112  Adj4 adj4( domain, madj4 );
113  Adj8 adj8( domain, madj8 );
114  DT48 dt48( adj4, adj8, JORDAN_DT );
115 
116  Coordinate r = 49;
117  double radius = (double) (r+1);
118  Point c( 0, 0 );
119  Point l( r, 0 );
120  MediumSet disk( domain );
121  ostringstream sstr;
122  sstr << "Creating disk( r < " << radius << " ) ...";
123  trace.beginBlock ( sstr.str() );
125  it != domain.end();
126  ++it )
127  {
128  if ( (*it - c ).norm() < radius ) // 450.0
129  // insertNew is very important for vector container.
130  disk.insertNew( *it );
131  }
132  trace.endBlock();
133 
134  trace.beginBlock ( "Testing Object instanciation and smart copy ..." );
135  ObjectType disk_object( dt48, disk );
136  nbok += disk_object.size() == 7825 ? 1 : 0;
137  nb++;
138  trace.info() << "(" << nbok << "/" << nb << ") "
139  << "Disk (r=450.0) " << disk_object << std::endl;
140  trace.info() << " size=" << disk_object.size() << std::endl;
141  ObjectType disk_object2( disk_object );
142  nbok += disk_object2.size() == 7825 ? 1 : 0;
143  nb++;
144  trace.info() << "(" << nbok << "/" << nb << ") "
145  << "Disk2 (r=450.0) " << disk_object2 << std::endl;
146  trace.info() << " size=" << disk_object2.size() << std::endl;
147  trace.endBlock();
148 
149  trace.beginBlock ( "Testing copy on write system ..." );
150  trace.info() << "Removing center point in Disk." << std::endl;
151  disk_object.pointSet().erase( c );
152  disk_object2.pointSet().insert( c );
153  nbok += disk_object.size() == 7824 ? 1 : 0;
154  nb++;
155  trace.info() << "(" << nbok << "/" << nb << ") "
156  << "Disk - c (r=450.0) " << disk_object << std::endl;
157  trace.info() << " size=" << disk_object.size() << std::endl;
158  nbok += disk_object2.size() == 7825 ? 1 : 0;
159  nb++;
160  trace.info() << "(" << nbok << "/" << nb << ") "
161  << "Disk2 + c (r=450.0) " << disk_object2 << std::endl;
162  trace.info() << " size=" << disk_object2.size() << std::endl;
163  trace.endBlock();
164 
165  trace.beginBlock ( "Testing neighborhoods ..." );
166  Object<DT48, SmallSet> neigh = disk_object.neighborhood( c );
167  nbok += neigh.size() == 4 ? 1 : 0;
168  nb++;
169  trace.info() << "(" << nbok << "/" << nb << ") "
170  << "N_4(Disk, c).size() = " << neigh.size()
171  << " == 4" << std::endl;
172  neigh = disk_object.properNeighborhood( l );
173  nbok += neigh.size() == 3 ? 1 : 0;
174  nb++;
175  trace.info() << "(" << nbok << "/" << nb << ") "
176  << "N*_4(Disk, " << l << ").size() = " << neigh.size()
177  << " == 3" << std::endl;
178  Size size = disk_object.properNeighborhoodSize( l );
179  nbok += size == 3 ? 1 : 0;
180  nb++;
181  trace.info() << "(" << nbok << "/" << nb << ") "
182  << "#N*_4(Disk, " << l << ") = " << size
183  << " == 3" << std::endl;
184 
185  neigh = disk_object2.neighborhood( c );
186  nbok += neigh.size() == 5 ? 1 : 0;
187  nb++;
188  trace.info() << "(" << nbok << "/" << nb << ") "
189  << "N_4(Disk2, c).size() = " << neigh.size()
190  << " == 5" << std::endl;
191  trace.endBlock();
192 
193  trace.beginBlock ( "Testing set converters ..." );
195  ( neigh.pointSet(), disk_object.pointSet() );
196  nbok += neigh.size() == 7824 ? 1 : 0;
197  nb++;
198  trace.info() << "(" << nbok << "/" << nb << ") "
199  << "neigh = disk_object, size() = " << neigh.size()
200  << " == 636100" << std::endl;
201  SmallObjectType neigh2 = disk_object2.neighborhood( c );
203  ( neigh.pointSet(), neigh2.pointSet() );
204  nbok += neigh.size() == 5 ? 1 : 0;
205  nb++;
206  trace.info() << "(" << nbok << "/" << nb << ") "
207  << "neigh = N_4(Disk2, c), size() = " << neigh.size()
208  << " == 5" << std::endl;
209  trace.endBlock();
210 
211  trace.beginBlock ( "Testing border extraction ..." );
212  ObjectType bdisk = disk_object.border();
213  nbok += bdisk.size() == 400 ? 1 : 0;
214  nb++;
215  trace.info() << "(" << nbok << "/" << nb << ") "
216  << "Border(Disk, c), size() = " << bdisk.size()
217  << " == 3372" << std::endl;
218  ObjectType bdisk2 = disk_object2.border();
219  nbok += bdisk2.size() == 392 ? 1 : 0;
220  nb++;
221  trace.info() << "(" << nbok << "/" << nb << ") "
222  << "Border(Disk2, c), size() = " << bdisk2.size()
223  << " == 3364" << std::endl;
224  trace.endBlock();
225 
226  trace.beginBlock ( "Testing expansion by layers on the boundary ..." );
227  typedef Expander< ObjectType > ObjectExpander;
228  ObjectExpander expander( bdisk, *(bdisk.pointSet().begin()) );
229  while ( ! expander.finished() )
230  {
231  nbok += expander.layer().size() <= 2 ? 1 : 0;
232  nb++;
233  trace.info() << "(" << nbok << "/" << nb << ") "
234  << "expander.layer.size() <= 2 "
235  << expander << std::endl;
236  expander.nextLayer();
237  }
238  trace.endBlock();
239 
240  trace.beginBlock ( "Testing expansion by layers on the disk from center..." );
241  ObjectExpander expander2( disk_object2, c );
242  while ( ! expander2.finished() )
243  {
244  trace.info() << expander2 << std::endl;
245  expander2.nextLayer();
246  }
247  nbok += expander2.distance() <= sqrt(2.0)*radius ? 1 : 0;
248  nb++;
249  trace.info() << "(" << nbok << "/" << nb << ") "
250  << "expander.distance() = " << expander2.distance()
251  << " <= " << sqrt(2.0)*radius << std::endl;
252  trace.endBlock();
253 
254  return nbok == nb;
255 }
256 
262 {
263  unsigned int nbok = 0;
264  unsigned int nb = 0;
265  typedef SpaceND< 3 > Z3;
266  typedef MetricAdjacency< Z3, 1 > Adj6;
267  typedef MetricAdjacency< Z3, 2 > Adj18;
268  typedef DigitalTopology< Adj6, Adj18 > DT6_18;
269  typedef Z3::Point Point;
271  typedef Domain::ConstIterator DomainConstIterator;
273  typedef Object<DT6_18, DigitalSet> ObjectType;
274  Adj6 adj6;
275  Adj18 adj18;
276  DT6_18 dt6_18( adj6, adj18, JORDAN_DT );
277 
278  Point p1( -50, -50, -50 );
279  Point p2( 50, 50, 50 );
280  Domain domain( p1, p2 );
281  Point c( 0, 0, 0 );
282  Point d( 5, 2, 0 );
283 
284  trace.beginBlock ( "Testing 3D Object instanciation and smart copy ..." );
285  trace.info() << "Creating diamond (r=15)" << endl;
286  // diamond of radius 30
287  DigitalSet diamond_set( domain );
288  for ( DomainConstIterator it = domain.begin(); it != domain.end(); ++it )
289  {
290  if ( (*it - c ).norm1() <= 15 ) diamond_set.insertNew( *it );
291  }
292  ObjectType diamond( dt6_18, diamond_set );
293  trace.info() << "Cloning diamond" << endl;
294  // The following line takes almost no time.
295  ObjectType diamond_clone( diamond );
296  // Since one of the objects is modified, the set is duplicated at the following line
297  trace.info() << "Removing two points " << c << " and " << d << endl;
298  diamond_clone.pointSet().erase( c );
299  diamond_clone.pointSet().erase( d );
300 
301  trace.info() << "Inserting into vector<Object>" << endl;
302  vector<ObjectType> objects;
303  back_insert_iterator< vector< ObjectType > > inserter( objects );
304  *inserter++ = diamond;
305  *inserter++ = diamond_clone;
306 
307  for ( vector<ObjectType>::const_iterator it = objects.begin();
308  it != objects.end();
309  ++it )
310  trace.info() << "- objects[" << (it - objects.begin() ) << "]"
311  << " = " << *it << endl;
312 
313  INBLOCK_TEST( objects[ 0 ].size() == ( objects[ 1 ].size() + 2 ) );
314  INBLOCK_TEST( objects[ 0 ].size() == 4991 );
315  trace.endBlock();
316 
317  trace.beginBlock ( "Testing connected component extraction ..." );
318  // JOL: do like this for output iterators pointing on the same
319  // container as 'this'. Works fine and nearly as fast.
320  //
321  // ObjectType( objects[ 0 ] ).writeComponents( inserter );
322 
323  trace.beginBlock ( "Components of diamond.border() ..." );
324  vector<ObjectType> objects2;
325  back_insert_iterator< vector< ObjectType > > inserter2( objects2 );
326  auto nbc0 = objects[ 0 ].border().writeComponents( inserter2 );
327  INBLOCK_TEST( nbc0 == 1 );
328  INBLOCK_TEST( objects[ 0 ].computeConnectedness() == CONNECTED );
329  trace.endBlock();
330 
331  trace.beginBlock ( "Components of diamond_clone.border() ..." );
332  auto nbc1 = objects[ 1 ].border().writeComponents( inserter2 );
333  INBLOCK_TEST( nbc1 == 3 );
334  trace.endBlock();
335  for ( vector<ObjectType>::const_iterator it = objects2.begin();
336  it != objects2.end();
337  ++it )
338  trace.info() << "- objects2[" << (it - objects2.begin() ) << "]"
339  << " = " << *it << endl;
340  INBLOCK_TEST( objects2[ 0 ].size() == objects2[ 1 ].size() );
341  INBLOCK_TEST( objects2[ 2 ].size() == objects2[ 3 ].size() );
342  INBLOCK_TEST( objects2[ 0 ].size() == 1688 );
343  INBLOCK_TEST( objects2[ 2 ].size() == 18 );
344 
345  trace.endBlock();
346 
347  return nbok == nb;
348 
349 }
350 
356 {
357  unsigned int nbok = 0;
358  unsigned int nb = 0;
359  typedef SpaceND< 3 > Z3;
360  typedef MetricAdjacency< Z3, 1 > Adj6;
361  typedef MetricAdjacency< Z3, 2 > Adj18;
362  typedef DigitalTopology< Adj6, Adj18 > DT6_18;
363  typedef Z3::Point Point;
365  typedef Domain::ConstIterator DomainConstIterator;
367  typedef Object<DT6_18, DigitalSet> ObjectType;
368  typedef Object<DT6_18, DigitalSet>::SmallObject SmallObjectType;
369  typedef Object<DT6_18, DigitalSet>::SmallComplementObject SmallComplementObjectType;
370  Adj6 adj6;
371  Adj18 adj18;
372  DT6_18 dt6_18( adj6, adj18, JORDAN_DT );
373 
374  Point p1( -10, -10, -10 );
375  Point p2( 10, 10, 10 );
376  Domain domain( p1, p2 );
377  Point c( 0, 0, 0 );
378  Point r( 3, 0, 0 );
379 
380  trace.beginBlock ( "Creating Diamond (r=4)" );
381  // diamond of radius 4
382  DigitalSet diamond_set( domain );
383  for ( DomainConstIterator it = domain.begin(); it != domain.end(); ++it )
384  {
385  if ( (*it - c ).norm1() <= 3 ) diamond_set.insertNew( *it );
386  }
387  diamond_set.erase( c );
388  ObjectType diamond( dt6_18, diamond_set );
389  trace.endBlock();
390 
391  trace.beginBlock ( "Geodesic neighborhoods ..." );
392  SmallObjectType geoN6_3 = diamond.geodesicNeighborhood( adj6, r, 3 );
393  SmallObjectType geoN18_2 = diamond.geodesicNeighborhood( adj18, r, 2 );
394  trace.info() << "geoN6_3 = " << geoN6_3 << endl;
395  trace.info() << "geoN18_2 = " << geoN18_2 << endl;
396  SmallComplementObjectType cgeoN6_3 = diamond.geodesicNeighborhoodInComplement( adj6, r, 3 );
397  SmallComplementObjectType cgeoN18_2 = diamond.geodesicNeighborhoodInComplement( adj18, r, 2 );
398  trace.info() << "cgeoN6_3 = " << cgeoN6_3 << endl;
399  trace.info() << "cgeoN18_2 = " << cgeoN18_2 << endl;
400  trace.endBlock();
401 
402  trace.beginBlock ( "Simple points ..." );
403  for ( DigitalSet::ConstIterator it = diamond.pointSet().begin();
404  it != diamond.pointSet().end();
405  ++it )
406  trace.info() << "- " << *it
407  << " " << ( diamond.isSimple( *it ) ? "Simple" : "Not simple" )
408  << endl;
409  trace.endBlock();
410 
411 
412  return nbok == nb;
413 }
414 
415 
416 bool testDraw()
417 {
418  unsigned int nbok = 0;
419  unsigned int nb = 0;
420 
421  trace.beginBlock ( "testDraw(): testing drawing commands." );
422 
423  typedef SpaceND< 2 > Z2;
424  typedef Z2::Point Point;
425  typedef Point::Coordinate Coordinate;
426  typedef HyperRectDomain< Z2 > DomainType;
427  Point p1( -10, -10 );
428  Point p2( 10, 10 );
429  DomainType domain( p1, p2 );
430 
431  // typedef DomainMetricAdjacency< DomainType, 1 > Adj4;
432  // typedef DomainMetricAdjacency< DomainType, 2 > Adj8;
433  typedef MetricAdjacency< Z2, 1 > MetricAdj4;
434  typedef MetricAdjacency< Z2, 2 > MetricAdj8;
437  typedef DigitalTopology< Adj4, Adj8 > DT48;
438  typedef DigitalTopology< Adj8, Adj4 > DT84;
440  MediumSet;
441 // typedef DigitalSetSelector< DomainType, SMALL_DS >::Type
442 // MediumSet;
443  typedef Object<DT48, MediumSet> ObjectType;
444  typedef Object<DT84, MediumSet> ObjectType84;
445 
446  //typedef ObjectType::SmallSet SmallSet;
447  //typedef Object<DT48, SmallSet> SmallObjectType;
448  //typedef ObjectType::Size Size;
449 
450  // Adj4 adj4( domain );
451  // Adj8 adj8( domain );
452  MetricAdj4 madj4;
453  MetricAdj8 madj8;
454  Adj4 adj4( domain, madj4 );
455  Adj8 adj8( domain, madj8 );
456  DT48 dt48( adj4, adj8, JORDAN_DT );
457  DT84 dt84( adj8, adj4, JORDAN_DT );
458 
459  Coordinate r = 5;
460  double radius = (double) (r+1);
461  Point c( 0, 0 );
462  Point l( r, 0 );
463  MediumSet disk( domain );
464  ostringstream sstr;
465  sstr << "Creating disk( r < " << radius << " ) ...";
466  trace.beginBlock ( sstr.str() );
468  it != domain.end();
469  ++it )
470  {
471  if ( (*it - c ).norm() < radius ) // 450.0
472  // insertNew is very important for vector container.
473  disk.insertNew( *it );
474  }
475  trace.endBlock();
476 
477  trace.beginBlock ( "Testing Object instanciation and smart copy ..." );
478  ObjectType disk_object( dt48, disk );
479  ObjectType84 disk_object2( dt84, disk );
480  trace.endBlock();
481 
482  trace.beginBlock ( "Testing export as SVG with libboard." );
483 
484  Board2D board;
485  board.setUnit(Board::UCentimeter);
486 
487  board << SetMode( domain.className(), "Grid" ) << domain;
488  board << disk_object;
489 
490  board.saveSVG("disk-object.svg");
491 
492  Board2D board2;
493  board2.setUnit(Board::UCentimeter);
494 
495  board2 << SetMode( domain.className(), "Grid" ) << domain;
496  board2 << SetMode( disk_object.className(), "DrawAdjacencies" ) << disk_object;
497 
498  board2.saveSVG("disk-object-adj.svg");
499 
500  Board2D board3;
501  board3.setUnit(Board::UCentimeter);
502 
503  board3 << SetMode( domain.className(), "Grid" ) << domain;
504  board3 << SetMode( disk_object2.className(), "DrawAdjacencies" ) << disk_object2;
505 
506  board3.saveSVG("disk-object-adj-bis.svg");
507  trace.endBlock();
508 
509  trace.endBlock();
510 
511  return nbok == nb;
512 
513 }
514 
515 struct MyDrawStyleCustomRed : public DrawableWithBoard2D
516 {
517  virtual void setStyle(Board2D & aboard) const
518  {
519  aboard.setFillColor( Color::Red);
520  aboard.setPenColorRGBi(200,0,0);
522  aboard.setLineWidth( 2 );
523  }
524 };
525 
526 struct MyDrawStyleCustomFillColor : public DrawableWithBoard2D
527 {
528  Color myColor;
529  MyDrawStyleCustomFillColor( const Color & c )
530  : myColor( c )
531  {}
532  virtual void setStyle(Board2D & aboard) const
533  {
534  aboard.setFillColor( myColor );
535  aboard.setPenColorRGBi( 0, 0, 0 );
537  aboard.setLineWidth( 1.0 );
538  }
539 };
540 
541 using namespace DGtal::Z2i;
542 
548 {
549  unsigned int nbok = 0;
550  unsigned int nb = 0;
551  typedef DGtal::Z2i::Point Point;
552  //typedef Domain::ConstIterator DomainConstIterator;
553 
554  Point p1( -17, -17 );
555  Point p2( 17, 17 );
556  Domain domain( p1, p2 );
557  DigitalSet shape_set( domain );
558  Shapes<Domain>::addNorm1Ball( shape_set, Point( -10, -8 ), 7 );
559  Shapes<Domain>::addNorm1Ball( shape_set, Point( 10, 8 ), 7 );
560  Shapes<Domain>::addNorm1Ball( shape_set, Point( 3, 0 ), 6 );
561  Shapes<Domain>::addNorm1Ball( shape_set, Point( 0, -3 ), 7 );
562  Shapes<Domain>::addNorm1Ball( shape_set, Point( -10, 0 ), 6 );
563  Shapes<Domain>::addNorm1Ball( shape_set, Point( -8, 8 ), 6 );
564  Shapes<Domain>::addNorm1Ball( shape_set, Point( 0, 9 ), 6 );
565  Shapes<Domain>::addNorm1Ball( shape_set, Point( 15, -2 ), 6 );
566  Shapes<Domain>::addNorm1Ball( shape_set, Point( 12, -10 ), 4 );
567  shape_set.erase( Point( 5, 0 ) );
568  shape_set.erase( Point( -1, -2 ) );
569  Object4_8 shape( dt4_8, shape_set );
570  Object8_4 shape2( dt8_4, shape_set );
571 
572  GradientColorMap<int> cmap_grad( 0, 6 );
573  cmap_grad.addColor( Color( 128, 128, 255 ) );
574  cmap_grad.addColor( Color( 255, 255, 128 ) );
575  //cmap_grad.addColor( Color( 220, 130, 25 ) );
576  Board2D board;
577  board.setUnit(Board::UCentimeter);
578  board << SetMode( domain.className(), "Paving" )
579  << domain;
580  Board2D board2;
581  board2.setUnit(Board::UCentimeter);
582  board2 << SetMode( domain.className(), "Grid" )
583  << domain;
584 
585  // Greedy thinning.
586  DGtal::uint64_t nb_simple;
587  trace.beginBlock ( "Greedy homotopic thinning ..." );
588  int layer = 0;
589  do
590  {
591  DigitalSet & S = shape.pointSet();
592  std::queue<DigitalSet::Iterator> Q;
593  for ( DigitalSet::Iterator it = S.begin(); it != S.end(); ++it )
594  if ( shape.isSimple( *it ) )
595  Q.push( it );
596  nb_simple = 0;
597  while ( ! Q.empty() )
598  {
599  DigitalSet::Iterator it = Q.front();
600  Q.pop();
601  if ( shape.isSimple( *it ) )
602  {
603  board << CustomStyle( it->className(),
604  new MyDrawStyleCustomFillColor
605  ( cmap_grad( layer ) ) )
606  << *it;
607  S.erase( *it );
608  ++nb_simple;
609  }
610  }
611  ++layer;
612  } while ( nb_simple != 0 );
613  trace.endBlock();
614 
615  // Greedy thinning.
616  trace.beginBlock ( "Greedy homotopic thinning ..." );
617  layer = 0;
618  do
619  {
620  DigitalSet & S = shape2.pointSet();
621  std::queue<DigitalSet::Iterator> Q;
622  for ( DigitalSet::Iterator it = S.begin(); it != S.end(); ++it )
623  if ( shape2.isSimple( *it ) )
624  Q.push( it );
625  nb_simple = 0;
626  while ( ! Q.empty() )
627  {
628  DigitalSet::Iterator it = Q.front();
629  Q.pop();
630  if ( shape2.isSimple( *it ) )
631  {
632  board2 << CustomStyle( it->className(),
633  new MyDrawStyleCustomFillColor
634  ( cmap_grad( layer ) ) )
635  << *it;
636  S.erase( *it );
637  ++nb_simple;
638  }
639  }
640  ++layer;
641  } while ( nb_simple != 0 );
642  trace.endBlock();
643 
644  board << CustomStyle( shape.className(), new MyDrawStyleCustomRed )
645  << shape;
646  board.saveSVG( "shape-thinning-4-8.svg");
647  board.clear();
648 
649  board2 << CustomStyle( shape2.className(), new MyDrawStyleCustomRed )
650  << shape2;
651  board2.saveSVG( "shape-thinning-8-4.svg");
652  board2.clear();
653 
654  return nbok == nb;
655 }
656 
658 {
659 
660  unsigned int nbok = 0;
661  unsigned int nb = 0;
662 
663  using namespace DGtal;
664  using namespace Z3i;
665  using Point = Z3i::Point ;
666  using Domain = Z3i::Domain ;
667  using DigitalSet = Z3i::DigitalSet ;
668  using KSpace = Z3i::KSpace ;
669  trace.beginBlock ( "Create Diamond Object" );
670  Point p1( -10, -10, -10 );
671  Point p2( 10, 10, 10 );
672  Domain domain( p1, p2 );
673  Point c( 0, 0, 0 );
674  Point r( 3, 0, 0 );
675 
676  // diamond of radius 4
677  DigitalSet diamond_set( domain );
678  for ( auto it = domain.begin(); it != domain.end(); ++it )
679  {
680  if ( (*it - c ).norm1() <= 3 ) diamond_set.insertNew( *it );
681  }
682  // diamond_set.erase( c );
683 
684  KSpace K;
685  bool space_ok = K.init( domain.lowerBound(),
686  domain.upperBound(), true // necessary
687  );
688  INBLOCK_TEST( space_ok == true ) ;
689 
690  using MyDigitalTopology = Z3i::DT26_6;
691  // using MyDigitalSet = Z3i::DigitalSet ;
694  MyDigitalTopology::ForegroundAdjacency adjF;
695  MyDigitalTopology::BackgroundAdjacency adjB;
696  MyDigitalTopology topo(adjF, adjB, DGtal::DigitalTopologyProperties::JORDAN_DT);
697  MyObject obj(topo,diamond_set);
698 
699  INBLOCK_TEST( obj.size() == diamond_set.size() );
700  trace.endBlock();
701  trace.beginBlock( "Check edges" );
702 
703  std::set<Point> corner_points;
704  Point north( 0 , 0 , 3 );
705  corner_points.insert(north);
706  Point south( 0 , 0 , -3 );
707  corner_points.insert(south);
708  Point east( 3 , 0 , 0 );
709  corner_points.insert(east);
710  Point west( -3 , 0 , 0 );
711  corner_points.insert(west);
712 
713  for(auto && p : corner_points){
714  auto pit = obj.pointSet().find(p);
715  if(pit == obj.pointSet().end()){
716  trace.info() << "point not found" << std::endl;
717  return false;
718  }
719  auto edges = obj.outEdges(*pit);
720  INBLOCK_TEST2( edges.size() == 5, edges.size() );
721  }
722  Point center( 0 , 0 , 0 );
723  auto cpit = obj.pointSet().find(center);
724  auto cedges = obj.outEdges(*cpit);
725  INBLOCK_TEST2( cedges.size() == 26, cedges.size() );
726 
727  // opposites edge
728  for(auto && e : cedges){
729  auto rev_e = obj.opposite(e);
730  INBLOCK_TEST(
731  (e.vertices[0] == rev_e.vertices[1]) &&
732  (e.vertices[1] == rev_e.vertices[0])
733  )
734  }
735  trace.endBlock();
736 
737  return nbok == nb;
738 
739 }
740 
742 {
743  unsigned int nbok = 0;
744  unsigned int nb = 0;
745  typedef DGtal::Z2i::Point Point;
746  //typedef Domain::ConstIterator DomainConstIterator;
747 
748  Point p1( -17, -17 );
749  Point p2( 17, 17 );
750  Domain domain( p1, p2 );
751  DigitalSet shape_set( domain );
752  Shapes<Domain>::addNorm1Ball( shape_set, Point( -10, -8 ), 7 );
753  Shapes<Domain>::addNorm1Ball( shape_set, Point( 10, 8 ), 7 );
754  Shapes<Domain>::addNorm1Ball( shape_set, Point( 3, 0 ), 6 );
755  Shapes<Domain>::addNorm1Ball( shape_set, Point( 0, -3 ), 7 );
756  Shapes<Domain>::addNorm1Ball( shape_set, Point( -10, 0 ), 6 );
757  Shapes<Domain>::addNorm1Ball( shape_set, Point( -8, 8 ), 6 );
758  Shapes<Domain>::addNorm1Ball( shape_set, Point( 0, 9 ), 6 );
759  Shapes<Domain>::addNorm1Ball( shape_set, Point( 15, -2 ), 6 );
760  Shapes<Domain>::addNorm1Ball( shape_set, Point( 12, -10 ), 4 );
761  shape_set.erase( Point( 5, 0 ) );
762  shape_set.erase( Point( -1, -2 ) );
763  Object4_8 shape( dt4_8, shape_set );
764  // shape.setTable(functions::loadTable<2>(simplicity::tableSimple4_8));
765  {
766  auto table_smart_ptr = functions::loadTable<2>(simplicity::tableSimple4_8);
767  shape.setTable(table_smart_ptr); // table must survive (smart_ptr)
768  }
769 
770  GradientColorMap<int> cmap_grad( 0, 6 );
771  cmap_grad.addColor( Color( 128, 128, 255 ) );
772  cmap_grad.addColor( Color( 255, 255, 128 ) );
773  //cmap_grad.addColor( Color( 220, 130, 25 ) );
774  Board2D board;
775  board.setUnit(Board::UCentimeter);
776  board << SetMode( domain.className(), "Paving" )
777  << domain;
778  Board2D board2;
779  board2.setUnit(Board::UCentimeter);
780  board2 << SetMode( domain.className(), "Grid" )
781  << domain;
782 
783  // Greedy thinning.
784  DGtal::uint64_t nb_simple;
785  trace.beginBlock ( "Greedy homotopic thinning with table..." );
786  int layer = 0;
787  do {
788  DigitalSet & S = shape.pointSet();
789  std::queue<DigitalSet::Iterator> Q;
790  for ( DigitalSet::Iterator it = S.begin(); it != S.end(); ++it )
791  if ( shape.isSimple( *it ) )
792  Q.push( it );
793  nb_simple = 0;
794  while ( ! Q.empty() )
795  {
796  DigitalSet::Iterator it = Q.front();
797  Q.pop();
798  if ( shape.isSimple( *it ) )
799  {
800  board << CustomStyle( it->className(),
801  new MyDrawStyleCustomFillColor
802  ( cmap_grad( layer ) ) )
803  << *it;
804  S.erase( *it );
805  ++nb_simple;
806  }
807  }
808  ++layer;
809  } while ( nb_simple != 0 );
810  trace.endBlock();
811 
812  return nbok == nb;
813 
814 }
816 // Standard services - public :
817 
818 int main( int argc, char** argv )
819 {
820  trace.beginBlock ( "Testing class Object" );
821  trace.info() << "Args:";
822  for ( int i = 0; i < argc; ++i )
823  trace.info() << " " << argv[ i ];
824  trace.info() << endl;
825 
826  bool res = testObject() &&
827  testObject3D() && testDraw()
828  && testSimplePoints3D()
829  && testSimplePoints2D()
830  && testObjectGraph()
831  && testSetTable();
832 
833  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
834  trace.endBlock();
835  return res ? 0 : 1;
836 }
837 // //
Aim: This class specializes a 'Board' class so as to display DGtal objects more naturally (with <<)....
Definition: Board2D.h:71
Structure representing an RGB triple with alpha component.
Definition: Color.h:68
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Container::iterator Iterator
Iterator type of the container.
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: This class template may be used to (linearly) convert scalar values in a given range into a colo...
void addColor(const Color &color)
Iterator for HyperRectDomain.
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
const ConstIterator & end() const
const ConstIterator & begin() const
const Point & lowerBound() const
const Point & upperBound() const
std::string className() const
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
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
std::string className() const
SmallObject properNeighborhood(const Point &p) const
SmallObject neighborhood(const Point &p) const
void setTable(Alias< boost::dynamic_bitset<> >inputTable)
bool isSimple(const Point &v) const
Component Coordinate
Type for Point elements.
Definition: PointVector.h:617
Aim: A utility class for constructing different shapes (balls, diamonds, and others).
void beginBlock(const std::string &keyword="")
std::ostream & emphase()
std::ostream & info()
double endBlock()
Board & setLineStyle(Shape::LineStyle style)
Board & setPenColorRGBi(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=255)
Definition: Board.cpp:277
void clear(const DGtal::Color &color=DGtal::Color::None)
Definition: Board.cpp:151
Board & setFillColor(const DGtal::Color &color)
Definition: Board.cpp:321
Board & setLineWidth(double width)
Definition: Board.cpp:328
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
MyDigitalSurface::ConstIterator ConstIterator
Z2i this namespace gathers the standard of types for 2D imagery.
DGtal is the top-level namespace which contains all DGtal functions and types.
@ CONNECTED
Definition: Topology.h:52
Trace trace
Definition: Common.h:153
boost::uint64_t uint64_t
unsigned 64-bit integer.
Definition: BasicTypes.h:65
Aim: Utility class to convert between types of sets.
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
MyPointD Point
Definition: testClone2.cpp:383
KSpace K
HalfEdgeDataStructure::Size Size
bool testObject3D()
Definition: testObject.cpp:261
bool testSetTable()
Definition: testObject.cpp:741
int main(int argc, char **argv)
Definition: testObject.cpp:818
bool testSimplePoints3D()
Definition: testObject.cpp:355
bool testObject()
Definition: testObject.cpp:79
bool testObjectGraph()
Definition: testObject.cpp:657
bool testDraw()
Definition: testObject.cpp:416
#define INBLOCK_TEST2(x, y)
Definition: testObject.cpp:66
bool testSimplePoints2D()
Definition: testObject.cpp:547
#define INBLOCK_TEST(x)
Definition: testObject.cpp:60
Domain domain
HyperRectDomain< Space > Domain
Z2i::DigitalSet DigitalSet