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/topology/BreadthFirstVisitor.h"
41 #include "DGtal/topology/helpers/FrontierPredicate.h"
42 #include "DGtal/topology/helpers/BoundaryPredicate.h"
43 #include "DGtal/topology/CUndirectedSimpleLocalGraph.h"
44 #include "DGtal/topology/CUndirectedSimpleGraph.h"
46 #include "DGtal/shapes/Shapes.h"
50 using namespace DGtal;
59 bool testDigitalSetBoundary()
61 unsigned int nbok = 0;
67 typedef Boundary::SurfelConstIterator ConstIterator;
68 typedef Boundary::Tracker Tracker;
69 typedef Boundary::Surfel Surfel;
77 nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
79 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
80 <<
"K.init() is ok" << std::endl;
81 Boundary boundary( K, dig_set );
82 unsigned int nbsurfels = 0;
83 for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
88 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
89 nb++, nbok += nbsurfels == ( 12 + 44 ) ? 1 : 0;
90 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
91 <<
"nbsurfels == (12 + 44 )" << std::endl;
92 for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
95 Tracker* ptrTracker = boundary.newTracker( *it );
96 Surfel s = ptrTracker->current();
99 unsigned int m1 = ptrTracker->adjacent( s1, trackDir,
true );
100 unsigned int m2 = ptrTracker->adjacent( s2, trackDir,
false );
101 trace.
info() <<
"s = " << s << std::endl;
102 trace.
info() <<
"s1 = " << s1 <<
" m1 = " << m1 << std::endl;
103 trace.
info() <<
"s2 = " << s2 <<
" m2 = " << m2 << std::endl;
104 nb++, nbok += boundary.isInside( s1 ) ? 1 : 0;
105 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
106 <<
"boundary.isInside( s1 )" << std::endl;
107 nb++, nbok += boundary.isInside( s2 ) ? 1 : 0;
108 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
109 <<
"boundary.isInside( s2 )" << std::endl;
116 template <
typename TPo
int3>
121 : myA( a ), myB( b ), myC( c )
124 bool operator()(
const TPoint3 & p )
const
126 double x = ( (double) p[ 0 ] / myA );
127 double y = ( (double) p[ 1 ] / myB );
128 double z = ( (double) p[ 2 ] / myC );
129 return ( x*x + y*y + z*z ) <= 1.0;
134 bool testImplicitDigitalSurface()
136 unsigned int nbok = 0;
143 typedef Boundary::SurfelConstIterator ConstIterator;
144 typedef Boundary::Tracker Tracker;
145 typedef Boundary::Surfel Surfel;
146 Point p1( -10, -10, -10 );
147 Point p2( 10, 10, 10 );
149 nbok += K.init( p1, p2,
true ) ? 1 : 0;
151 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
152 <<
"K.init() is ok" << std::endl;
153 ImplicitDigitalEllipse ellipse( 6.0, 4.5, 3.4 );
155 Boundary boundary( K, ellipse,
157 unsigned int nbsurfels = 0;
158 for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
163 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
167 for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
170 Tracker* ptrTracker = boundary.newTracker( *it );
171 Surfel s = ptrTracker->current();
174 unsigned int m1 = ptrTracker->adjacent( s1, trackDir,
true );
175 unsigned int m2 = ptrTracker->adjacent( s2, trackDir,
false );
176 trace.
info() <<
"s = " << s << std::endl;
177 trace.
info() <<
"s1 = " << s1 <<
" m1 = " << m1 << std::endl;
178 trace.
info() <<
"s2 = " << s2 <<
" m2 = " << m2 << std::endl;
179 nb++, nbok += boundary.isInside( s1 ) ? 1 : 0;
180 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
181 <<
"boundary.isInside( s1 )" << std::endl;
182 nb++, nbok += boundary.isInside( s2 ) ? 1 : 0;
183 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
184 <<
"boundary.isInside( s2 )" << std::endl;
194 bool testLightImplicitDigitalSurface()
199 typedef Boundary::SurfelConstIterator ConstIterator;
200 typedef Boundary::Tracker Tracker;
201 typedef Boundary::Surfel Surfel;
203 unsigned int nbok = 0;
206 Point p1( -10, -10, -10 );
207 Point p2( 10, 10, 10 );
209 nbok += K.init( p1, p2,
true ) ? 1 : 0;
211 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
212 <<
"K.init() is ok" << std::endl;
213 ImplicitDigitalEllipse ellipse( 6.0, 4.5, 3.4 );
215 Boundary boundary( K, ellipse,
217 unsigned int nbsurfels = 0;
218 for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
223 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
224 trace.
beginBlock (
"Checks if adjacent surfels are part of the surface." );
226 for ( ConstIterator it = boundary.begin(), it_end = boundary.end();
229 Tracker* ptrTracker = boundary.newTracker( *it );
230 Surfel s = ptrTracker->current();
234 ptrTracker->adjacent( s1, trackDir,
true );
236 ptrTracker->adjacent( s2, trackDir,
false );
240 nb++, nbok += boundary.isInside( s1 ) ? 1 : 0;
243 nb++, nbok += boundary.isInside( s2 ) ? 1 : 0;
248 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") isInside tests." << std::endl;
254 template <
typename Image3D>
255 void fillImage3D( Image3D & img,
256 typename Image3D::Point low,
257 typename Image3D::Point up,
258 typename Image3D::Value value )
260 typedef typename Image3D::Point
Point;
261 typedef typename Image3D::Integer
Integer;
262 for ( Integer z = low[ 2 ]; z <= up[ 2 ]; ++z )
263 for ( Integer y = low[ 1 ]; y <= up[ 1 ]; ++y )
264 for ( Integer x = low[ 0 ]; x <= up[ 0 ]; ++x )
265 img.setValue( Point( x, y, z ), value );
271 bool testExplicitDigitalSurface()
277 typedef Frontier::SurfelConstIterator ConstIterator;
278 typedef Frontier::Tracker Tracker;
279 typedef Frontier::SCell
SCell;
280 typedef Frontier::Surfel Surfel;
282 unsigned int nbok = 0;
285 Point p1( -5, -5, -5 );
288 nbok += K.init( p1, p2,
true ) ? 1 : 0;
290 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
291 <<
"K.init() is ok" << std::endl;
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 );
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,
304 unsigned int nbsurfels = 0;
305 for ( ConstIterator it = frontier20.begin(), it_end = frontier20.end();
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;
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,
322 unsigned int nbsurfels = 0;
323 for ( ConstIterator it = frontier10.begin(), it_end = frontier10.end();
328 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
329 nb++, nbok += nbsurfels == 140 ? 1 : 0;
330 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
331 <<
"frontier10: nbsurfels == 140" << std::endl;
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,
340 unsigned int nbsurfels = 0;
341 for ( ConstIterator it = frontier12.begin(), it_end = frontier12.end();
346 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
347 nb++, nbok += nbsurfels == 36 ? 1 : 0;
348 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
349 <<
"frontier12: nbsurfels == 36" << std::endl;
354 typedef Boundary::SurfelConstIterator EConstIterator;
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,
364 unsigned int nbsurfels = 0;
365 for ( EConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
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;
382 bool testLightExplicitDigitalSurface()
388 typedef Frontier::SurfelConstIterator ConstIterator;
389 typedef Frontier::Tracker Tracker;
390 typedef Frontier::SCell
SCell;
391 typedef Frontier::Surfel Surfel;
393 unsigned int nbok = 0;
396 Point p1( -5, -5, -5 );
399 nbok += K.init( p1, p2,
true ) ? 1 : 0;
401 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
402 <<
"K.init() is ok" << std::endl;
404 fillImage3D( image, p1, p2, 0 );
405 fillImage3D( image, Point(-2,-2,-2 ), Point( 2, 2, 2 ), 1 );
406 fillImage3D( image, Point( 0, 0,-2 ), Point( 0, 0, 2 ), 2 );
407 fillImage3D( image, Point(-1,-1, 2 ), Point( 1, 1, 2 ), 2 );
409 SCell vox2 = K.sSpel( Point( 0, 0, 2 ), K.POS );
410 SCell bel20 = K.sIncident( vox2, 2,
true );
411 SurfelPredicate surfPredicate( K, image, 2, 0 );
412 Frontier frontier20( K, surfPredicate,
415 unsigned int nbsurfels = 0;
416 for ( ConstIterator it = frontier20.begin(), it_end = frontier20.end();
421 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
422 nb++, nbok += nbsurfels == 9 ? 1 : 0;
423 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
424 <<
"frontier20: nbsurfels == 9" << std::endl;
427 SCell vox1 = K.sSpel( Point( 2, 0, 0 ), K.POS );
428 SCell bel10 = K.sIncident( vox1, 0,
true );
429 SurfelPredicate surfPredicate( K, image, 1, 0 );
430 Frontier frontier10( K, surfPredicate,
433 unsigned int nbsurfels = 0;
434 for ( ConstIterator it = frontier10.begin(), it_end = frontier10.end();
439 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
440 nb++, nbok += nbsurfels == 140 ? 1 : 0;
441 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
442 <<
"frontier10: nbsurfels == 140" << std::endl;
445 SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
446 SCell bel12 = K.sIncident( vox1, 0,
false );
447 SurfelPredicate surfPredicate( K, image, 1, 2 );
448 Frontier frontier12( K, surfPredicate,
451 unsigned int nbsurfels = 0;
452 for ( ConstIterator it = frontier12.begin(), it_end = frontier12.end();
457 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
458 nb++, nbok += nbsurfels == 36 ? 1 : 0;
459 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
460 <<
"frontier12: nbsurfels == 36" << std::endl;
465 typedef Boundary::SurfelConstIterator LEConstIterator;
469 SCell vox1 = K.sSpel( Point( 1, 0, 0 ), K.POS );
470 SCell bel1x = K.sIncident( vox1, 0,
false );
471 SecondSurfelPredicate surfPredicate( K, image, 1 );
472 Boundary boundary1x( K, surfPredicate,
475 unsigned int nbsurfels = 0;
476 for ( LEConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
481 trace.
info() << nbsurfels <<
" surfels found." << std::endl;
482 nb++, nbok += nbsurfels == 176 ? 1 : 0;
483 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
484 <<
"boundary1x: nbsurfels == 176" << std::endl;
492 template <
typename KSpace>
493 bool testDigitalSurface()
495 unsigned int nbok = 0;
497 std::string msg(
"Testing block ... DigitalSurface in K" );
498 msg +=
'0' + KSpace::dimension;
501 typedef typename KSpace::Space
Space;
502 typedef typename KSpace::Size Size;
503 typedef typename Space::Point Point;
508 Point p0 = Point::diagonal( 0 );
509 Point p1 = Point::diagonal( -6 );
510 Point p2 = Point::diagonal( 6 );
511 Domain domain( p1, p2 );
512 DigitalSet dig_set( domain );
516 nbok += K.init( domain.lowerBound(), domain.upperBound(), true ) ? 1 : 0;
518 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
519 <<
"K.init() is ok" << std::endl;
532 typedef typename MyDS::Surfel Surfel;
533 DSContainer* ptrBdry =
new DSContainer( K, dig_set );
534 MyDS digsurf( ptrBdry );
536 ( K.dimension == 2 ) ? 12+28 :
537 ( K.dimension == 3 ) ? 30+174 :
538 ( K.dimension == 4 ) ? 56+984 :
539 ( K.dimension == 5 ) ? 4340 : 0;
540 nb++, nbok += digsurf.size() == nbsurfels ? 1 : 0;
541 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
542 <<
"digsurf.size() = " << digsurf.size()
543 <<
" == " << nbsurfels << std::endl;
544 for (
typename MyDS::ConstIterator it = digsurf.begin(),
545 it_end = digsurf.end();
550 nb++, nbok += digsurf.degree( s ) == 2*(K.dimension-1) ? 1 : 0;
552 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
553 <<
"digsurf.degree( s ) == "
554 << 2*(K.dimension-1) << std::endl;
560 unsigned int nb_dist_1 = 0;
562 while ( ! visitor.finished() )
565 if ( node.second == 1 ) ++nb_dist_1;
568 trace.
info() <<
"last node v=" << node.first <<
" d=" << node.second << std::endl;
569 nb++, nbok += nb_dist_1 == 2*(K.dimension-1) ? 1 : 0;
570 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
571 <<
"nb surfels at distance 1 == "
572 << 2*(K.dimension-1) << std::endl;
573 const BFVMarkSet & visitedVtx = visitor.markedVertices();
574 Size nbsurfelsComp1 =
575 ( K.dimension == 2 ) ? 28 :
576 ( K.dimension == 3 ) ? 174 :
577 ( K.dimension == 4 ) ? 984 : 0;
578 nb++, nbok += visitedVtx.size() == nbsurfelsComp1 ? 1 : 0;
579 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
580 <<
"nb visited = " << visitedVtx.size() <<
" == "
581 << nbsurfelsComp1 << std::endl;
593 int main(
int argc,
char** argv )
597 for (
int i = 0; i < argc; ++i )
601 bool res = testDigitalSetBoundary()
602 && testImplicitDigitalSurface()
603 && testLightImplicitDigitalSurface()
604 && testExplicitDigitalSurface()
605 && testLightExplicitDigitalSurface()
606 && testDigitalSurface<KhalimskySpaceND<2> >()
608 && testDigitalSurface<KhalimskySpaceND<4> >();
609 trace.
emphase() << ( res ?
"Passed." :
"Error." ) << endl;