DGtal  1.5.beta
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 #include "DGtal/images/ImageContainerBySTLVector.h"
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 
281  unsigned int nbok = 0;
282  unsigned int nb = 0;
283  trace.beginBlock ( "Testing block ... ExplicitDigitalSurface" );
284  Point p1( -5, -5, -5 );
285  Point p2( 5, 5, 5 );
286  KSpace K;
287  nbok += K.init( p1, p2, true ) ? 1 : 0;
288  nb++;
289  trace.info() << "(" << nbok << "/" << nb << ") "
290  << "K.init() is ok" << std::endl;
291  Image image( Domain(p1, p2) );
292  fillImage3D( image, p1, p2, 0 );
293  fillImage3D( image, Point(-2,-2,-2 ), Point( 2, 2, 2 ), 1 );
294  fillImage3D( image, Point( 0, 0,-2 ), Point( 0, 0, 2 ), 2 );
295  fillImage3D( image, Point(-1,-1, 2 ), Point( 1, 1, 2 ), 2 );
296  {
297  SCell vox2 = K.sSpel( Point( 0, 0, 2 ), K.POS );
298  SCell bel20 = K.sIncident( vox2, 2, true );
299  SurfelPredicate surfPredicate( K, image, 2, 0 );
300  Frontier frontier20( K, surfPredicate,
302  bel20 );
303  unsigned int nbsurfels = 0;
304  for ( ConstIterator it = frontier20.begin(), it_end = frontier20.end();
305  it != it_end; ++it )
306  {
307  ++nbsurfels;
308  }
309  trace.info() << nbsurfels << " surfels found." << std::endl;
310  ++nb; nbok += nbsurfels == 9 ? 1 : 0;
311  trace.info() << "(" << nbok << "/" << nb << ") "
312  << "frontier20: nbsurfels == 9" << std::endl;
313  }
314  {
315  SCell vox1 = K.sSpel( Point( 2, 0, 0 ), K.POS );
316  SCell bel10 = K.sIncident( vox1, 0, true );
317  SurfelPredicate surfPredicate( K, image, 1, 0 );
318  Frontier frontier10( K, surfPredicate,
320  bel10 );
321  unsigned int nbsurfels = 0;
322  for ( ConstIterator it = frontier10.begin(), it_end = frontier10.end();
323  it != it_end; ++it )
324  {
325  ++nbsurfels;
326  }
327  trace.info() << nbsurfels << " surfels found." << std::endl;
328  ++nb; nbok += nbsurfels == 140 ? 1 : 0; // 4*25(sides) + 16(top) + 24(bot)
329  trace.info() << "(" << nbok << "/" << nb << ") "
330  << "frontier10: nbsurfels == 140" << std::endl;
331  }
332  {
333  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
334  SCell bel12 = K.sIncident( vox1, 0, false );
335  SurfelPredicate surfPredicate( K, image, 1, 2 );
336  Frontier frontier12( K, surfPredicate,
338  bel12 );
339  unsigned int nbsurfels = 0;
340  for ( ConstIterator it = frontier12.begin(), it_end = frontier12.end();
341  it != it_end; ++it )
342  {
343  ++nbsurfels;
344  }
345  trace.info() << nbsurfels << " surfels found." << std::endl;
346  ++nb; nbok += nbsurfels == 36 ? 1 : 0; // 8+12(top) + 16(axis)
347  trace.info() << "(" << nbok << "/" << nb << ") "
348  << "frontier12: nbsurfels == 36" << std::endl;
349  }
350  {
351  typedef BoundaryPredicate<KSpace, Image> SecondSurfelPredicate;
353  typedef Boundary::SurfelConstIterator EConstIterator;
354  // typedef Boundary::Tracker Tracker;
355  // typedef Boundary::SCell SCell;
356  // typedef Boundary::Surfel Surfel;
357  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
358  SCell bel1x = K.sIncident( vox1, 0, false );
359  SecondSurfelPredicate surfPredicate( K, image, 1 );
360  Boundary boundary1x( K, surfPredicate,
362  bel1x );
363  unsigned int nbsurfels = 0;
364  for ( EConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
365  it != it_end; ++it )
366  {
367  ++nbsurfels;
368  }
369  trace.info() << nbsurfels << " surfels found." << std::endl;
370  ++nb; nbok += nbsurfels == 176 ? 1 : 0;
371  trace.info() << "(" << nbok << "/" << nb << ") "
372  << "boundary1x: nbsurfels == 176" << std::endl;
373  }
374  trace.endBlock();
375  return nbok == nb;
376 }
377 
378 //-----------------------------------------------------------------------------
379 // Testing LightExplicitDigitalSurface
380 //-----------------------------------------------------------------------------
382 {
383  using namespace Z3i;
385  typedef FrontierPredicate<KSpace, Image> SurfelPredicate;
387  typedef Frontier::SurfelConstIterator ConstIterator;
388 
389  unsigned int nbok = 0;
390  unsigned int nb = 0;
391  trace.beginBlock ( "Testing block ... LightExplicitDigitalSurface" );
392  Point p1( -5, -5, -5 );
393  Point p2( 5, 5, 5 );
394  KSpace K;
395  nbok += K.init( p1, p2, true ) ? 1 : 0;
396  nb++;
397  trace.info() << "(" << nbok << "/" << nb << ") "
398  << "K.init() is ok" << std::endl;
399  Image image( Domain(p1, p2) );
400  fillImage3D( image, p1, p2, 0 );
401  fillImage3D( image, Point(-2,-2,-2 ), Point( 2, 2, 2 ), 1 );
402  fillImage3D( image, Point( 0, 0,-2 ), Point( 0, 0, 2 ), 2 );
403  fillImage3D( image, Point(-1,-1, 2 ), Point( 1, 1, 2 ), 2 );
404  {
405  SCell vox2 = K.sSpel( Point( 0, 0, 2 ), K.POS );
406  SCell bel20 = K.sIncident( vox2, 2, true );
407  SurfelPredicate surfPredicate( K, image, 2, 0 );
408  Frontier frontier20( K, surfPredicate,
410  bel20 );
411  unsigned int nbsurfels = 0;
412  for ( ConstIterator it = frontier20.begin(), it_end = frontier20.end();
413  it != it_end; ++it )
414  {
415  ++nbsurfels;
416  }
417  trace.info() << nbsurfels << " surfels found." << std::endl;
418  ++nb; nbok += nbsurfels == 9 ? 1 : 0;
419  trace.info() << "(" << nbok << "/" << nb << ") "
420  << "frontier20: nbsurfels == 9" << std::endl;
421  }
422  {
423  SCell vox1 = K.sSpel( Point( 2, 0, 0 ), K.POS );
424  SCell bel10 = K.sIncident( vox1, 0, true );
425  SurfelPredicate surfPredicate( K, image, 1, 0 );
426  Frontier frontier10( K, surfPredicate,
428  bel10 );
429  unsigned int nbsurfels = 0;
430  for ( ConstIterator it = frontier10.begin(), it_end = frontier10.end();
431  it != it_end; ++it )
432  {
433  ++nbsurfels;
434  }
435  trace.info() << nbsurfels << " surfels found." << std::endl;
436  ++nb; nbok += nbsurfels == 140 ? 1 : 0; // 4*25(sides) + 16(top) + 24(bot)
437  trace.info() << "(" << nbok << "/" << nb << ") "
438  << "frontier10: nbsurfels == 140" << std::endl;
439  }
440  {
441  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
442  SCell bel12 = K.sIncident( vox1, 0, false );
443  SurfelPredicate surfPredicate( K, image, 1, 2 );
444  Frontier frontier12( K, surfPredicate,
446  bel12 );
447  unsigned int nbsurfels = 0;
448  for ( ConstIterator it = frontier12.begin(), it_end = frontier12.end();
449  it != it_end; ++it )
450  {
451  ++nbsurfels;
452  }
453  trace.info() << nbsurfels << " surfels found." << std::endl;
454  ++nb; nbok += nbsurfels == 36 ? 1 : 0; // 8+12(top) + 16(axis)
455  trace.info() << "(" << nbok << "/" << nb << ") "
456  << "frontier12: nbsurfels == 36" << std::endl;
457  }
458  {
459  typedef BoundaryPredicate<KSpace, Image> SecondSurfelPredicate;
461  typedef Boundary::SurfelConstIterator LEConstIterator;
462  //typedef Boundary::Tracker Tracker;
463  //typedef Boundary::SCell SCell;
464  //typedef Boundary::Surfel Surfel;
465  SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
466  SCell bel1x = K.sIncident( vox1, 0, false );
467  SecondSurfelPredicate surfPredicate( K, image, 1 );
468  Boundary boundary1x( K, surfPredicate,
470  bel1x );
471  unsigned int nbsurfels = 0;
472  for ( LEConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
473  it != it_end; ++it )
474  {
475  ++nbsurfels;
476  }
477  trace.info() << nbsurfels << " surfels found." << std::endl;
478  ++nb; nbok += nbsurfels == 176 ? 1 : 0;
479  trace.info() << "(" << nbok << "/" << nb << ") "
480  << "boundary1x: nbsurfels == 176" << std::endl;
481  }
482  trace.endBlock();
483  return nbok == nb;
484 }
485 
486 
487 
488 template <typename KSpace>
490 {
491  unsigned int nbok = 0;
492  unsigned int nb = 0;
493  std::string msg( "Testing block ... DigitalSurface in K" );
494  msg += '0' + KSpace::dimension;
495  trace.beginBlock ( msg );
496  //"Testing block ... DigitalSurface " + std::string( KSpace.dimension ) );
497  typedef typename KSpace::Space Space;
498  typedef typename KSpace::Size Size;
499  typedef typename Space::Point Point;
502 
503  trace.beginBlock ( "Creating object and DigitalSurfaceContainer" );
504  Point p0 = Point::diagonal( 0 );
505  Point p1 = Point::diagonal( -6 );
506  Point p2 = Point::diagonal( 6 );
507  Domain domain( p1, p2 );
508  DigitalSet dig_set( domain );
509  Shapes<Domain>::addNorm2Ball( dig_set, p0, 3 );
510  Shapes<Domain>::removeNorm2Ball( dig_set, p0, 1 );
511  KSpace K;
512  nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
513  nb++;
514  trace.info() << "(" << nbok << "/" << nb << ") "
515  << "K.init() is ok" << std::endl;
516  trace.endBlock();
517 
518  trace.beginBlock ( "Testing DigitalSurface" );
519  typedef DigitalSetBoundary<KSpace,DigitalSet> DSContainer;
520  typedef DigitalSurface<DSContainer> MyDS;
521 
522  //Checking the type as a model of CSinglePassConstRange
523  BOOST_CONCEPT_ASSERT(( CConstSinglePassRange < MyDS> ));
524  BOOST_CONCEPT_ASSERT(( CUndirectedSimpleLocalGraph < MyDS> ));
525  BOOST_CONCEPT_ASSERT(( CUndirectedSimpleGraph < MyDS> ));
526 
527 
528  typedef typename MyDS::Surfel Surfel;
529  DSContainer* ptrBdry = new DSContainer( K, dig_set );
530  MyDS digsurf( ptrBdry ); // acquired
531  Size nbsurfels =
532  ( K.dimension == 2 ) ? 12+28 :
533  ( K.dimension == 3 ) ? 30+174 :
534  ( K.dimension == 4 ) ? 56+984 :
535  ( K.dimension == 5 ) ? 4340 : 0;
536  ++nb; nbok += digsurf.size() == nbsurfels ? 1 : 0;
537  trace.info() << "(" << nbok << "/" << nb << ") "
538  << "digsurf.size() = " << digsurf.size()
539  << " == " << nbsurfels << std::endl;
540  for ( typename MyDS::ConstIterator it = digsurf.begin(),
541  it_end = digsurf.end();
542  it != it_end;
543  ++it )
544  {
545  Surfel s = *it;
546  ++nb; nbok += digsurf.degree( s ) == 2*(K.dimension-1) ? 1 : 0;
547  }
548  trace.info() << "(" << nbok << "/" << nb << ") "
549  << "digsurf.degree( s ) == "
550  << 2*(K.dimension-1) << std::endl;
551  trace.endBlock();
552  trace.beginBlock ( "Testing BreadthFirstVisitor on DigitalSurface" );
553  BreadthFirstVisitor< MyDS > visitor( digsurf, *digsurf.begin() );
554  typedef typename BreadthFirstVisitor< MyDS >::Node BFVNode;
555  typedef typename BreadthFirstVisitor< MyDS >::MarkSet BFVMarkSet;
556  unsigned int nb_dist_1 = 0;
557  BFVNode node;
558  while ( ! visitor.finished() )
559  {
560  node = visitor.current();
561  if ( node.second == 1 ) ++nb_dist_1;
562  visitor.expand();
563  }
564  trace.info() << "last node v=" << node.first << " d=" << node.second << std::endl;
565  ++nb; nbok += nb_dist_1 == 2*(K.dimension-1) ? 1 : 0;
566  trace.info() << "(" << nbok << "/" << nb << ") "
567  << "nb surfels at distance 1 == "
568  << 2*(K.dimension-1) << std::endl;
569  const BFVMarkSet & visitedVtx = visitor.markedVertices();
570  Size nbsurfelsComp1 =
571  ( K.dimension == 2 ) ? 28 :
572  ( K.dimension == 3 ) ? 174 :
573  ( K.dimension == 4 ) ? 984 : 0;
574  ++nb; nbok += visitedVtx.size() == nbsurfelsComp1 ? 1 : 0;
575  trace.info() << "(" << nbok << "/" << nb << ") "
576  << "nb visited = " << visitedVtx.size() << " == "
577  << nbsurfelsComp1 << std::endl;
578 
579  trace.endBlock();
580 
581 
582  trace.endBlock();
583  return nbok == nb;
584 }
585 
587 {
588  typedef KhalimskySpaceND<3> KSpace;
589  typedef typename KSpace::Space Space;
590  typedef typename Space::Point Point;
593  DigitalSet;
594  typedef DigitalSetBoundary<KSpace,DigitalSet> DSContainer;
595  typedef DigitalSurface<DSContainer> MyDS;
596  typedef typename MyDS::Vertex Vertex;
597  typedef typename MyDS::SCell SCell;
598 
599  unsigned int nbok = 0;
600  unsigned int nb = 0;
601  trace.beginBlock ( "Creating surface around one voxel" );
602  Point pt0;
603  Point pt1 = Point::diagonal( -1 );
604  Point pt2 = Point::diagonal( 1 );
605  Domain domain( pt1, pt2 );
606  DigitalSet dig_set( domain );
607  dig_set.insert( pt0 );
608  KSpace K;
609  nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
610  nb++;
611  trace.info() << "(" << nbok << "/" << nb << ") "
612  << "K.init() is ok" << std::endl;
613  DSContainer* ptrBdry = new DSContainer( K, dig_set );
614  MyDS digsurf( ptrBdry ); // acquired
615  ++nb; nbok += digsurf.size() == 6 ? 1 : 0;
616  trace.info() << "(" << nbok << "/" << nb << ") "
617  << "digsurf.size() = " << digsurf.size()
618  << " == " << 6 << std::endl;
619  trace.endBlock();
620  trace.beginBlock ( "Check ordering" );
621  std::map< std::pair< SCell, SCell >, unsigned int > nb_arcs;
622  for ( Vertex v : digsurf )
623  {
624  auto faces = digsurf.facesAroundVertex( v, true );
625  for ( unsigned int i = 0; i < faces.size(); ++i )
626  {
627  auto p = std::make_pair( digsurf.pivot( faces[ i ] ),
628  digsurf.pivot( faces[ (i+1)%4 ] ) );
629  trace.info() << "Arc " << p.first << " --- " << p.second << std::endl;
630  if ( nb_arcs.find( p ) == nb_arcs.end() )
631  nb_arcs[ p ] = 1;
632  else
633  nb_arcs[ p ] += 1;
634  }
635  }
636  ++nb; nbok += nb_arcs.size() == 24 ? 1 : 0;
637  trace.info() << "(" << nbok << "/" << nb << ") "
638  << "nb_arcs.size() = " << nb_arcs.size()
639  << " == " << 24 << " (cube has 24 arcs)" << std::endl;
640  for ( auto arc : nb_arcs )
641  {
642  SCell p1 = arc.first.first;
643  SCell p2 = arc.first.second;
644  ++nb; nbok += (K.sCoords( p1 ) - K.sCoords( p2 )).norm1() == 1 ? 1 : 0;
645  }
646  trace.info() << "(" << nbok << "/" << nb << ") "
647  << "arcs have all norm 1." << std::endl;
648  for ( auto arc : nb_arcs )
649  {
650  SCell p1 = arc.first.first;
651  SCell p2 = arc.first.second;
652  auto it = nb_arcs.find( std::make_pair( p2, p1 ) );
653  ++nb; nbok += arc.second == 1 ? 1 : 0;
654  ++nb; nbok += ( it != nb_arcs.end() ) && it->second == 1 ? 1 : 0;
655  }
656  trace.info() << "(" << nbok << "/" << nb << ") "
657  << "arcs are unique and their inverse are unique." << std::endl;
658  trace.endBlock();
659  return nb == nbok;
660 }
661 
663 // Standard services - public :
664 
665 int main( int argc, char** argv )
666 {
667  trace.beginBlock ( "Testing class DigitalSurface" );
668  trace.info() << "Args:";
669  for ( int i = 0; i < argc; ++i )
670  trace.info() << " " << argv[ i ];
671  trace.info() << endl;
672 
673  bool res = testDigitalSetBoundary()
678  && testDigitalSurface<KhalimskySpaceND<2> >()
680  && testDigitalSurface<KhalimskySpaceND<4> >()
682  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
683  trace.endBlock();
684  return res ? 0 : 1;
685 }
686 // //
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....
Z3i::SCell SCell
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:136
Trace trace
Definition: Common.h:153
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
Z2i::DigitalSet DigitalSet