DGtal  1.2.0
testDigitalSurface.cpp
Go to the documentation of this file.
1 
31 #include <iostream>
32 #include "DGtal/base/Common.h"
33 #include "DGtal/base/CConstSinglePassRange.h"
34 #include "DGtal/topology/DigitalSurface.h"
35 #include "DGtal/topology/DigitalSetBoundary.h"
36 #include "DGtal/topology/ImplicitDigitalSurface.h"
37 #include "DGtal/topology/LightImplicitDigitalSurface.h"
38 #include "DGtal/topology/ExplicitDigitalSurface.h"
39 #include "DGtal/topology/LightExplicitDigitalSurface.h"
40 #include "DGtal/graph/BreadthFirstVisitor.h"
41 #include "DGtal/topology/helpers/FrontierPredicate.h"
42 #include "DGtal/topology/helpers/BoundaryPredicate.h"
43 #include "DGtal/graph/CUndirectedSimpleLocalGraph.h"
44 #include "DGtal/graph/CUndirectedSimpleGraph.h"
45 
46 #include "DGtal/shapes/Shapes.h"
48 
49 using namespace std;
50 using namespace DGtal;
51 using namespace DGtal::concepts;
52 using namespace DGtal::functors;
53 
55 // Functions for testing class DigitalSurface.
57 
62 {
63  unsigned int nbok = 0;
64  unsigned int nb = 0;
65 
66  trace.beginBlock ( "Testing block ... DigitalSetBoundary" );
67  using namespace Z2i;
69  typedef Boundary::SurfelConstIterator ConstIterator;
70  typedef Boundary::Tracker Tracker;
71  typedef Boundary::Surfel Surfel;
72  Point p1( -10, -10 );
73  Point p2( 10, 10 );
74  Domain domain( p1, p2 );
75  DigitalSet dig_set( domain );
76  Shapes<Domain>::addNorm2Ball( dig_set, Point( 0, 0 ), 5 );
77  Shapes<Domain>::removeNorm2Ball( dig_set, Point( 0, 0 ), 1 );
78  KSpace K;
79  nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
80  nb++;
81  trace.info() << "(" << nbok << "/" << nb << ") "
82  << "K.init() is ok" << std::endl;
83  Boundary boundary( K, dig_set );
84  unsigned int nbsurfels = 0;
85  for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
86  it != it_end; ++it )
87  {
88  ++nbsurfels;
89  }
90  trace.info() << nbsurfels << " surfels found." << std::endl;
91  ++nb; nbok += nbsurfels == ( 12 + 44 ) ? 1 : 0;
92  trace.info() << "(" << nbok << "/" << nb << ") "
93  << "nbsurfels == (12 + 44 )" << std::endl;
94  for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
95  it != it_end; ++it )
96  {
97  Tracker* ptrTracker = boundary.newTracker( *it );
98  Surfel s = ptrTracker->current();
99  Dimension trackDir = * K.sDirs( s );
100  Surfel s1, s2;
101  unsigned int m1 = ptrTracker->adjacent( s1, trackDir, true );
102  unsigned int m2 = ptrTracker->adjacent( s2, trackDir, false );
103  trace.info() << "s = " << s << std::endl;
104  trace.info() << "s1 = " << s1 << " m1 = " << m1 << std::endl;
105  trace.info() << "s2 = " << s2 << " m2 = " << m2 << std::endl;
106  ++nb; nbok += boundary.isInside( s1 ) ? 1 : 0;
107  trace.info() << "(" << nbok << "/" << nb << ") "
108  << "boundary.isInside( s1 )" << std::endl;
109  ++nb; nbok += boundary.isInside( s2 ) ? 1 : 0;
110  trace.info() << "(" << nbok << "/" << nb << ") "
111  << "boundary.isInside( s2 )" << std::endl;
112  delete ptrTracker;
113  }
114  trace.endBlock();
115  return nbok == nb;
116 }
117 
118 template <typename TPoint3>
119 struct ImplicitDigitalEllipse3 {
120  typedef TPoint3 Point;
121  inline
122  ImplicitDigitalEllipse3( double a, double b, double c )
123  : myA( a ), myB( b ), myC( c )
124  {}
125  inline
126  bool operator()( const TPoint3 & p ) const
127  {
128  double x = ( (double) p[ 0 ] / myA );
129  double y = ( (double) p[ 1 ] / myB );
130  double z = ( (double) p[ 2 ] / myC );
131  return ( x*x + y*y + z*z ) <= 1.0;
132  }
133  double myA, myB, myC;
134 };
135 
137 {
138  unsigned int nbok = 0;
139  unsigned int nb = 0;
140 
141  trace.beginBlock ( "Testing block ... ImplicitDigitalSurface" );
142  using namespace Z3i;
143  typedef ImplicitDigitalEllipse3<Point> ImplicitDigitalEllipse;
145  typedef Boundary::SurfelConstIterator ConstIterator;
146  typedef Boundary::Tracker Tracker;
147  typedef Boundary::Surfel Surfel;
148  Point p1( -10, -10, -10 );
149  Point p2( 10, 10, 10 );
150  KSpace K;
151  nbok += K.init( p1, p2, true ) ? 1 : 0;
152  nb++;
153  trace.info() << "(" << nbok << "/" << nb << ") "
154  << "K.init() is ok" << std::endl;
155  ImplicitDigitalEllipse ellipse( 6.0, 4.5, 3.4 );
156  Surfel bel = Surfaces<KSpace>::findABel( K, ellipse, 10000 );
157  Boundary boundary( K, ellipse,
158  SurfelAdjacency<KSpace::dimension>( true ), bel );
159  unsigned int nbsurfels = 0;
160  for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
161  it != it_end; ++it )
162  {
163  ++nbsurfels;
164  }
165  trace.info() << nbsurfels << " surfels found." << std::endl;
166  // ++nb; nbok += nbsurfels == ( 12 + 44 ) ? 1 : 0;
167  // trace.info() << "(" << nbok << "/" << nb << ") "
168  // << "nbsurfels == (12 + 44 )" << std::endl;
169  for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
170  it != it_end; ++it )
171  {
172  Tracker* ptrTracker = boundary.newTracker( *it );
173  Surfel s = ptrTracker->current();
174  Dimension trackDir = * K.sDirs( s );
175  Surfel s1, s2;
176  unsigned int m1 = ptrTracker->adjacent( s1, trackDir, true );
177  unsigned int m2 = ptrTracker->adjacent( s2, trackDir, false );
178  trace.info() << "s = " << s << std::endl;
179  trace.info() << "s1 = " << s1 << " m1 = " << m1 << std::endl;
180  trace.info() << "s2 = " << s2 << " m2 = " << m2 << std::endl;
181  ++nb; nbok += boundary.isInside( s1 ) ? 1 : 0;
182  trace.info() << "(" << nbok << "/" << nb << ") "
183  << "boundary.isInside( s1 )" << std::endl;
184  ++nb; nbok += boundary.isInside( s2 ) ? 1 : 0;
185  trace.info() << "(" << nbok << "/" << nb << ") "
186  << "boundary.isInside( s2 )" << std::endl;
187  delete ptrTracker;
188  }
189  trace.endBlock();
190  return nbok == nb;
191 }
192 
193 //-----------------------------------------------------------------------------
194 // Testing LightImplicitDigitalSurface
195 //-----------------------------------------------------------------------------
197 {
198  using namespace Z3i;
199  typedef ImplicitDigitalEllipse3<Point> ImplicitDigitalEllipse;
201  typedef Boundary::SurfelConstIterator ConstIterator;
202  typedef Boundary::Tracker Tracker;
203  typedef Boundary::Surfel Surfel;
204 
205  unsigned int nbok = 0;
206  unsigned int nb = 0;
207  trace.beginBlock ( "Testing block ... LightImplicitDigitalSurface" );
208  Point p1( -10, -10, -10 );
209  Point p2( 10, 10, 10 );
210  KSpace K;
211  nbok += K.init( p1, p2, true ) ? 1 : 0;
212  nb++;
213  trace.info() << "(" << nbok << "/" << nb << ") "
214  << "K.init() is ok" << std::endl;
215  ImplicitDigitalEllipse ellipse( 6.0, 4.5, 3.4 );
216  Surfel bel = Surfaces<KSpace>::findABel( K, ellipse, 10000 );
217  Boundary boundary( K, ellipse,
218  SurfelAdjacency<KSpace::dimension>( true ), bel );
219  unsigned int nbsurfels = 0;
220  for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
221  it != it_end; ++it )
222  {
223  ++nbsurfels;
224  }
225  trace.info() << nbsurfels << " surfels found." << std::endl;
226  trace.beginBlock ( "Checks if adjacent surfels are part of the surface." );
227 
228  for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
229  it != it_end; ++it )
230  {
231  Tracker* ptrTracker = boundary.newTracker( *it );
232  Surfel s = ptrTracker->current();
233  Dimension trackDir = * K.sDirs( s );
234  Surfel s1, s2;
235  // unsigned int m1 =
236  ptrTracker->adjacent( s1, trackDir, true );
237  // unsigned int m2 =
238  ptrTracker->adjacent( s2, trackDir, false );
239  // trace.info() << "s = " << s << std::endl;
240  // trace.info() << "s1 = " << s1 << " m1 = " << m1 << std::endl;
241  // trace.info() << "s2 = " << s2 << " m2 = " << m2 << std::endl;
242  ++nb; nbok += boundary.isInside( s1 ) ? 1 : 0;
243  // trace.info() << "(" << nbok << "/" << nb << ") "
244  // << "boundary.isInside( s1 )" << std::endl;
245  ++nb; nbok += boundary.isInside( s2 ) ? 1 : 0;
246  // trace.info() << "(" << nbok << "/" << nb << ") "
247  // << "boundary.isInside( s2 )" << std::endl;
248  delete ptrTracker;
249  }
250  trace.info() << "(" << nbok << "/" << nb << ") isInside tests." << std::endl;
251  trace.endBlock();
252  trace.endBlock();
253  return nbok == nb;
254 }
255 
256 template <typename Image3D>
257 void fillImage3D( Image3D & img,
258  typename Image3D::Point low,
259  typename Image3D::Point up,
260  typename Image3D::Value value )
261 {
262  typedef typename Image3D::Point Point;
263  typedef typename Image3D::Integer Integer;
264  for ( Integer z = low[ 2 ]; z <= up[ 2 ]; ++z )
265  for ( Integer y = low[ 1 ]; y <= up[ 1 ]; ++y )
266  for ( Integer x = low[ 0 ]; x <= up[ 0 ]; ++x )
267  img.setValue( Point( x, y, z ), value );
268 }
269 
270 //-----------------------------------------------------------------------------
271 // Testing ExplicitDigitalSurface
272 //-----------------------------------------------------------------------------
274 {
275  using namespace Z3i;
277  typedef FrontierPredicate<KSpace, Image> SurfelPredicate;
279  typedef Frontier::SurfelConstIterator ConstIterator;
280  typedef Frontier::SCell SCell;
281 
282  unsigned int nbok = 0;
283  unsigned int nb = 0;
284  trace.beginBlock ( "Testing block ... ExplicitDigitalSurface" );
285  Point p1( -5, -5, -5 );
286  Point p2( 5, 5, 5 );
287  KSpace K;
288  nbok += K.init( p1, p2, true ) ? 1 : 0;
289  nb++;
290  trace.info() << "(" << nbok << "/" << nb << ") "
291  << "K.init() is ok" << std::endl;
292  Image image( Domain(p1, p2) );
293  fillImage3D( image, p1, p2, 0 );
294  fillImage3D( image, Point(-2,-2,-2 ), Point( 2, 2, 2 ), 1 );
295  fillImage3D( image, Point( 0, 0,-2 ), Point( 0, 0, 2 ), 2 );
296  fillImage3D( image, Point(-1,-1, 2 ), Point( 1, 1, 2 ), 2 );
297  {
298  SCell vox2 = K.sSpel( Point( 0, 0, 2 ), K.POS );
299  SCell bel20 = K.sIncident( vox2, 2, true );
300  SurfelPredicate surfPredicate( K, image, 2, 0 );
301  Frontier frontier20( K, surfPredicate,
303  bel20 );
304  unsigned int nbsurfels = 0;
305  for ( ConstIterator it = frontier20.begin(), it_end = frontier20.end();
306  it != it_end; ++it )
307  {
308  ++nbsurfels;
309  }
310  trace.info() << nbsurfels << " surfels found." << std::endl;
311  ++nb; nbok += nbsurfels == 9 ? 1 : 0;
312  trace.info() << "(" << nbok << "/" << nb << ") "
313  << "frontier20: nbsurfels == 9" << std::endl;
314  }
315  {
316  SCell vox1 = K.sSpel( Point( 2, 0, 0 ), K.POS );
317  SCell bel10 = K.sIncident( vox1, 0, true );
318  SurfelPredicate surfPredicate( K, image, 1, 0 );
319  Frontier frontier10( K, surfPredicate,
321  bel10 );
322  unsigned int nbsurfels = 0;
323  for ( ConstIterator it = frontier10.begin(), it_end = frontier10.end();
324  it != it_end; ++it )
325  {
326  ++nbsurfels;
327  }
328  trace.info() << nbsurfels << " surfels found." << std::endl;
329  ++nb; nbok += nbsurfels == 140 ? 1 : 0; // 4*25(sides) + 16(top) + 24(bot)
330  trace.info() << "(" << nbok << "/" << nb << ") "
331  << "frontier10: nbsurfels == 140" << std::endl;
332  }
333  {
334  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
335  SCell bel12 = K.sIncident( vox1, 0, false );
336  SurfelPredicate surfPredicate( K, image, 1, 2 );
337  Frontier frontier12( K, surfPredicate,
339  bel12 );
340  unsigned int nbsurfels = 0;
341  for ( ConstIterator it = frontier12.begin(), it_end = frontier12.end();
342  it != it_end; ++it )
343  {
344  ++nbsurfels;
345  }
346  trace.info() << nbsurfels << " surfels found." << std::endl;
347  ++nb; nbok += nbsurfels == 36 ? 1 : 0; // 8+12(top) + 16(axis)
348  trace.info() << "(" << nbok << "/" << nb << ") "
349  << "frontier12: nbsurfels == 36" << std::endl;
350  }
351  {
352  typedef BoundaryPredicate<KSpace, Image> SecondSurfelPredicate;
354  typedef Boundary::SurfelConstIterator EConstIterator;
355  // typedef Boundary::Tracker Tracker;
356  // typedef Boundary::SCell SCell;
357  // typedef Boundary::Surfel Surfel;
358  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
359  SCell bel1x = K.sIncident( vox1, 0, false );
360  SecondSurfelPredicate surfPredicate( K, image, 1 );
361  Boundary boundary1x( K, surfPredicate,
363  bel1x );
364  unsigned int nbsurfels = 0;
365  for ( EConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
366  it != it_end; ++it )
367  {
368  ++nbsurfels;
369  }
370  trace.info() << nbsurfels << " surfels found." << std::endl;
371  ++nb; nbok += nbsurfels == 176 ? 1 : 0;
372  trace.info() << "(" << nbok << "/" << nb << ") "
373  << "boundary1x: nbsurfels == 176" << std::endl;
374  }
375  trace.endBlock();
376  return nbok == nb;
377 }
378 
379 //-----------------------------------------------------------------------------
380 // Testing LightExplicitDigitalSurface
381 //-----------------------------------------------------------------------------
383 {
384  using namespace Z3i;
386  typedef FrontierPredicate<KSpace, Image> SurfelPredicate;
388  typedef Frontier::SurfelConstIterator ConstIterator;
389  typedef Frontier::SCell SCell;
390 
391  unsigned int nbok = 0;
392  unsigned int nb = 0;
393  trace.beginBlock ( "Testing block ... LightExplicitDigitalSurface" );
394  Point p1( -5, -5, -5 );
395  Point p2( 5, 5, 5 );
396  KSpace K;
397  nbok += K.init( p1, p2, true ) ? 1 : 0;
398  nb++;
399  trace.info() << "(" << nbok << "/" << nb << ") "
400  << "K.init() is ok" << std::endl;
401  Image image( Domain(p1, p2) );
402  fillImage3D( image, p1, p2, 0 );
403  fillImage3D( image, Point(-2,-2,-2 ), Point( 2, 2, 2 ), 1 );
404  fillImage3D( image, Point( 0, 0,-2 ), Point( 0, 0, 2 ), 2 );
405  fillImage3D( image, Point(-1,-1, 2 ), Point( 1, 1, 2 ), 2 );
406  {
407  SCell vox2 = K.sSpel( Point( 0, 0, 2 ), K.POS );
408  SCell bel20 = K.sIncident( vox2, 2, true );
409  SurfelPredicate surfPredicate( K, image, 2, 0 );
410  Frontier frontier20( K, surfPredicate,
412  bel20 );
413  unsigned int nbsurfels = 0;
414  for ( ConstIterator it = frontier20.begin(), it_end = frontier20.end();
415  it != it_end; ++it )
416  {
417  ++nbsurfels;
418  }
419  trace.info() << nbsurfels << " surfels found." << std::endl;
420  ++nb; nbok += nbsurfels == 9 ? 1 : 0;
421  trace.info() << "(" << nbok << "/" << nb << ") "
422  << "frontier20: nbsurfels == 9" << std::endl;
423  }
424  {
425  SCell vox1 = K.sSpel( Point( 2, 0, 0 ), K.POS );
426  SCell bel10 = K.sIncident( vox1, 0, true );
427  SurfelPredicate surfPredicate( K, image, 1, 0 );
428  Frontier frontier10( K, surfPredicate,
430  bel10 );
431  unsigned int nbsurfels = 0;
432  for ( ConstIterator it = frontier10.begin(), it_end = frontier10.end();
433  it != it_end; ++it )
434  {
435  ++nbsurfels;
436  }
437  trace.info() << nbsurfels << " surfels found." << std::endl;
438  ++nb; nbok += nbsurfels == 140 ? 1 : 0; // 4*25(sides) + 16(top) + 24(bot)
439  trace.info() << "(" << nbok << "/" << nb << ") "
440  << "frontier10: nbsurfels == 140" << std::endl;
441  }
442  {
443  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
444  SCell bel12 = K.sIncident( vox1, 0, false );
445  SurfelPredicate surfPredicate( K, image, 1, 2 );
446  Frontier frontier12( K, surfPredicate,
448  bel12 );
449  unsigned int nbsurfels = 0;
450  for ( ConstIterator it = frontier12.begin(), it_end = frontier12.end();
451  it != it_end; ++it )
452  {
453  ++nbsurfels;
454  }
455  trace.info() << nbsurfels << " surfels found." << std::endl;
456  ++nb; nbok += nbsurfels == 36 ? 1 : 0; // 8+12(top) + 16(axis)
457  trace.info() << "(" << nbok << "/" << nb << ") "
458  << "frontier12: nbsurfels == 36" << std::endl;
459  }
460  {
461  typedef BoundaryPredicate<KSpace, Image> SecondSurfelPredicate;
463  typedef Boundary::SurfelConstIterator LEConstIterator;
464  //typedef Boundary::Tracker Tracker;
465  //typedef Boundary::SCell SCell;
466  //typedef Boundary::Surfel Surfel;
467  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
468  SCell bel1x = K.sIncident( vox1, 0, false );
469  SecondSurfelPredicate surfPredicate( K, image, 1 );
470  Boundary boundary1x( K, surfPredicate,
472  bel1x );
473  unsigned int nbsurfels = 0;
474  for ( LEConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
475  it != it_end; ++it )
476  {
477  ++nbsurfels;
478  }
479  trace.info() << nbsurfels << " surfels found." << std::endl;
480  ++nb; nbok += nbsurfels == 176 ? 1 : 0;
481  trace.info() << "(" << nbok << "/" << nb << ") "
482  << "boundary1x: nbsurfels == 176" << std::endl;
483  }
484  trace.endBlock();
485  return nbok == nb;
486 }
487 
488 
489 
490 template <typename KSpace>
492 {
493  unsigned int nbok = 0;
494  unsigned int nb = 0;
495  std::string msg( "Testing block ... DigitalSurface in K" );
496  msg += '0' + KSpace::dimension;
497  trace.beginBlock ( msg );
498  //"Testing block ... DigitalSurface " + std::string( KSpace.dimension ) );
499  typedef typename KSpace::Space Space;
500  typedef typename KSpace::Size Size;
501  typedef typename Space::Point Point;
504 
505  trace.beginBlock ( "Creating object and DigitalSurfaceContainer" );
506  Point p0 = Point::diagonal( 0 );
507  Point p1 = Point::diagonal( -6 );
508  Point p2 = Point::diagonal( 6 );
509  Domain domain( p1, p2 );
510  DigitalSet dig_set( domain );
511  Shapes<Domain>::addNorm2Ball( dig_set, p0, 3 );
512  Shapes<Domain>::removeNorm2Ball( dig_set, p0, 1 );
513  KSpace K;
514  nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
515  nb++;
516  trace.info() << "(" << nbok << "/" << nb << ") "
517  << "K.init() is ok" << std::endl;
518  trace.endBlock();
519 
520  trace.beginBlock ( "Testing DigitalSurface" );
521  typedef DigitalSetBoundary<KSpace,DigitalSet> DSContainer;
522  typedef DigitalSurface<DSContainer> MyDS;
523 
524  //Checking the type as a model of CSinglePassConstRange
525  BOOST_CONCEPT_ASSERT(( CConstSinglePassRange < MyDS> ));
526  BOOST_CONCEPT_ASSERT(( CUndirectedSimpleLocalGraph < MyDS> ));
527  BOOST_CONCEPT_ASSERT(( CUndirectedSimpleGraph < MyDS> ));
528 
529 
530  typedef typename MyDS::Surfel Surfel;
531  DSContainer* ptrBdry = new DSContainer( K, dig_set );
532  MyDS digsurf( ptrBdry ); // acquired
533  Size nbsurfels =
534  ( K.dimension == 2 ) ? 12+28 :
535  ( K.dimension == 3 ) ? 30+174 :
536  ( K.dimension == 4 ) ? 56+984 :
537  ( K.dimension == 5 ) ? 4340 : 0;
538  ++nb; nbok += digsurf.size() == nbsurfels ? 1 : 0;
539  trace.info() << "(" << nbok << "/" << nb << ") "
540  << "digsurf.size() = " << digsurf.size()
541  << " == " << nbsurfels << std::endl;
542  for ( typename MyDS::ConstIterator it = digsurf.begin(),
543  it_end = digsurf.end();
544  it != it_end;
545  ++it )
546  {
547  Surfel s = *it;
548  ++nb; nbok += digsurf.degree( s ) == 2*(K.dimension-1) ? 1 : 0;
549  }
550  trace.info() << "(" << nbok << "/" << nb << ") "
551  << "digsurf.degree( s ) == "
552  << 2*(K.dimension-1) << std::endl;
553  trace.endBlock();
554  trace.beginBlock ( "Testing BreadthFirstVisitor on DigitalSurface" );
555  BreadthFirstVisitor< MyDS > visitor( digsurf, *digsurf.begin() );
556  typedef typename BreadthFirstVisitor< MyDS >::Node BFVNode;
557  typedef typename BreadthFirstVisitor< MyDS >::MarkSet BFVMarkSet;
558  unsigned int nb_dist_1 = 0;
559  BFVNode node;
560  while ( ! visitor.finished() )
561  {
562  node = visitor.current();
563  if ( node.second == 1 ) ++nb_dist_1;
564  visitor.expand();
565  }
566  trace.info() << "last node v=" << node.first << " d=" << node.second << std::endl;
567  ++nb; nbok += nb_dist_1 == 2*(K.dimension-1) ? 1 : 0;
568  trace.info() << "(" << nbok << "/" << nb << ") "
569  << "nb surfels at distance 1 == "
570  << 2*(K.dimension-1) << std::endl;
571  const BFVMarkSet & visitedVtx = visitor.markedVertices();
572  Size nbsurfelsComp1 =
573  ( K.dimension == 2 ) ? 28 :
574  ( K.dimension == 3 ) ? 174 :
575  ( K.dimension == 4 ) ? 984 : 0;
576  ++nb; nbok += visitedVtx.size() == nbsurfelsComp1 ? 1 : 0;
577  trace.info() << "(" << nbok << "/" << nb << ") "
578  << "nb visited = " << visitedVtx.size() << " == "
579  << nbsurfelsComp1 << std::endl;
580 
581  trace.endBlock();
582 
583 
584  trace.endBlock();
585  return nbok == nb;
586 }
587 
589 {
590  typedef KhalimskySpaceND<3> KSpace;
591  typedef typename KSpace::Space Space;
592  typedef typename Space::Point Point;
595  DigitalSet;
596  typedef DigitalSetBoundary<KSpace,DigitalSet> DSContainer;
597  typedef DigitalSurface<DSContainer> MyDS;
598  typedef typename MyDS::Vertex Vertex;
599  typedef typename MyDS::SCell SCell;
600 
601  unsigned int nbok = 0;
602  unsigned int nb = 0;
603  trace.beginBlock ( "Creating surface around one voxel" );
604  Point pt0;
605  Point pt1 = Point::diagonal( -1 );
606  Point pt2 = Point::diagonal( 1 );
607  Domain domain( pt1, pt2 );
608  DigitalSet dig_set( domain );
609  dig_set.insert( pt0 );
610  KSpace K;
611  nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
612  nb++;
613  trace.info() << "(" << nbok << "/" << nb << ") "
614  << "K.init() is ok" << std::endl;
615  DSContainer* ptrBdry = new DSContainer( K, dig_set );
616  MyDS digsurf( ptrBdry ); // acquired
617  ++nb; nbok += digsurf.size() == 6 ? 1 : 0;
618  trace.info() << "(" << nbok << "/" << nb << ") "
619  << "digsurf.size() = " << digsurf.size()
620  << " == " << 6 << std::endl;
621  trace.endBlock();
622  trace.beginBlock ( "Check ordering" );
623  std::map< std::pair< SCell, SCell >, unsigned int > nb_arcs;
624  for ( Vertex v : digsurf )
625  {
626  auto faces = digsurf.facesAroundVertex( v, true );
627  for ( unsigned int i = 0; i < faces.size(); ++i )
628  {
629  auto p = std::make_pair( digsurf.pivot( faces[ i ] ),
630  digsurf.pivot( faces[ (i+1)%4 ] ) );
631  trace.info() << "Arc " << p.first << " --- " << p.second << std::endl;
632  if ( nb_arcs.find( p ) == nb_arcs.end() )
633  nb_arcs[ p ] = 1;
634  else
635  nb_arcs[ p ] += 1;
636  }
637  }
638  ++nb; nbok += nb_arcs.size() == 24 ? 1 : 0;
639  trace.info() << "(" << nbok << "/" << nb << ") "
640  << "nb_arcs.size() = " << nb_arcs.size()
641  << " == " << 24 << " (cube has 24 arcs)" << std::endl;
642  for ( auto arc : nb_arcs )
643  {
644  SCell p1 = arc.first.first;
645  SCell p2 = arc.first.second;
646  ++nb; nbok += (K.sCoords( p1 ) - K.sCoords( p2 )).norm1() == 1 ? 1 : 0;
647  }
648  trace.info() << "(" << nbok << "/" << nb << ") "
649  << "arcs have all norm 1." << std::endl;
650  for ( auto arc : nb_arcs )
651  {
652  SCell p1 = arc.first.first;
653  SCell p2 = arc.first.second;
654  auto it = nb_arcs.find( std::make_pair( p2, p1 ) );
655  ++nb; nbok += arc.second == 1 ? 1 : 0;
656  ++nb; nbok += ( it != nb_arcs.end() ) && it->second == 1 ? 1 : 0;
657  }
658  trace.info() << "(" << nbok << "/" << nb << ") "
659  << "arcs are unique and their inverse are unique." << std::endl;
660  trace.endBlock();
661  return nb == nbok;
662 }
663 
665 // Standard services - public :
666 
667 int main( int argc, char** argv )
668 {
669  trace.beginBlock ( "Testing class DigitalSurface" );
670  trace.info() << "Args:";
671  for ( int i = 0; i < argc; ++i )
672  trace.info() << " " << argv[ i ];
673  trace.info() << endl;
674 
675  bool res = testDigitalSetBoundary()
680  && testDigitalSurface<KhalimskySpaceND<2> >()
682  && testDigitalSurface<KhalimskySpaceND<4> >()
684  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
685  trace.endBlock();
686  return res ? 0 : 1;
687 }
688 // //
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const MarkSet & markedVertices() const
const Node & current() const
std::pair< Vertex, Data > Node
FIXME.
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
Aim: A wrapper class around a STL associative container for storing sets of digital points within som...
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as connected surfels....
const Point & lowerBound() const
const Point & upperBound() const
Aim: implements association bewteen points lying in a digital domain and values.
Definition: Image.h:70
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of an impl...
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.
static constexpr const Sign POS
DirIterator sDirs(const SCell &p) const
Given a signed cell [p], returns an iterator to iterate over each coordinate the cell spans.
Point sCoords(const SCell &c) const
Return its digital coordinates.
static constexpr const Dimension dimension
SCell sSpel(Point p, Sign sign=POS) const
From the digital coordinates of a point in Zn, builds the corresponding spel (cell of maximal dimensi...
NumberTraits< Integer >::UnsignedVersion Size
Type used to represent sizes in the digital space.
SCell sIncident(const SCell &c, Dimension k, bool up) const
Return the forward or backward signed cell incident to [c] along axis [k], depending on [up].
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as connected surfels....
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of an impl...
Aim: A utility class for constructing different shapes (balls, diamonds, and others).
Aim: A utility class for constructing surfaces (i.e. set of (n-1)-cells).
Definition: Surfaces.h:79
void beginBlock(const std::string &keyword="")
std::ostream & emphase()
std::ostream & info()
double endBlock()
Aim: The predicate on surfels that represents the frontier between a region and its complementary in ...
Aim: The predicate on surfels that represents the frontier between two regions in an image....
MyDigitalSurface::ConstIterator ConstIterator
Aim: Gathers several functions useful for concept checks.
functors namespace gathers all DGtal functors.
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
Represents a signed cell in a cellular grid space by its Khalimsky coordinates and a boolean value.
Aim: Defines the concept describing a const single pass range.
Aim: Represents the concept of local graph: each vertex has neighboring vertices, but we do not neces...
Aim: Represents the concept of local graph: each vertex has neighboring vertices, but we do not neces...
MyPointD Point
Definition: testClone2.cpp:383
KSpace K
bool testDigitalSurface()
int main(int argc, char **argv)
bool testLightImplicitDigitalSurface()
void fillImage3D(Image3D &img, typename Image3D::Point low, typename Image3D::Point up, typename Image3D::Value value)
bool testDigitalSetBoundary()
bool testExplicitDigitalSurface()
bool testLightExplicitDigitalSurface()
bool testOrderingDigitalSurfaceFacesAroundVertex()
bool testImplicitDigitalSurface()
HalfEdgeDataStructure::Size Size
Domain domain
Image image(domain)
ImageContainerBySTLVector< Domain, Value > Image
HyperRectDomain< Space > Domain
TriMesh::Vertex Vertex