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"
63 unsigned int nbok = 0;
66 trace.beginBlock (
"Testing block ... DigitalSetBoundary" );
70 typedef Boundary::Tracker Tracker;
71 typedef Boundary::Surfel
Surfel;
79 nbok +=
K.init(
domain.lowerBound(),
domain.upperBound(),
true ) ? 1 : 0;
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();
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();
97 Tracker* ptrTracker = boundary.newTracker( *it );
98 Surfel s = ptrTracker->current();
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;
118template <
typename TPo
int3>
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;
138 unsigned int nbok = 0;
141 trace.beginBlock (
"Testing block ... ImplicitDigitalSurface" );
146 typedef Boundary::Tracker Tracker;
147 typedef Boundary::Surfel
Surfel;
148 Point p1( -10, -10, -10 );
149 Point p2( 10, 10, 10 );
151 nbok +=
K.init( p1, p2,
true ) ? 1 : 0;
153 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
154 <<
"K.init() is ok" << std::endl;
155 ImplicitDigitalEllipse ellipse( 6.0, 4.5, 3.4 );
157 Boundary boundary(
K, ellipse,
159 unsigned int nbsurfels = 0;
160 for (
ConstIterator it = boundary.begin(), it_end = boundary.end();
165 trace.info() << nbsurfels <<
" surfels found." << std::endl;
169 for (
ConstIterator it = boundary.begin(), it_end = boundary.end();
172 Tracker* ptrTracker = boundary.newTracker( *it );
173 Surfel s = ptrTracker->current();
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;
202 typedef Boundary::Tracker Tracker;
203 typedef Boundary::Surfel
Surfel;
205 unsigned int nbok = 0;
207 trace.beginBlock (
"Testing block ... LightImplicitDigitalSurface" );
208 Point p1( -10, -10, -10 );
209 Point p2( 10, 10, 10 );
211 nbok +=
K.init( p1, p2,
true ) ? 1 : 0;
213 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
214 <<
"K.init() is ok" << std::endl;
215 ImplicitDigitalEllipse ellipse( 6.0, 4.5, 3.4 );
217 Boundary boundary(
K, ellipse,
219 unsigned int nbsurfels = 0;
220 for (
ConstIterator it = boundary.begin(), it_end = boundary.end();
225 trace.info() << nbsurfels <<
" surfels found." << std::endl;
226 trace.beginBlock (
"Checks if adjacent surfels are part of the surface." );
228 for (
ConstIterator it = boundary.begin(), it_end = boundary.end();
231 Tracker* ptrTracker = boundary.newTracker( *it );
232 Surfel s = ptrTracker->current();
236 ptrTracker->adjacent( s1, trackDir,
true );
238 ptrTracker->adjacent( s2, trackDir,
false );
242 ++nb; nbok += boundary.isInside( s1 ) ? 1 : 0;
245 ++nb; nbok += boundary.isInside( s2 ) ? 1 : 0;
250 trace.info() <<
"(" << nbok <<
"/" << nb <<
") isInside tests." << std::endl;
256template <
typename Image3D>
258 typename Image3D::Point low,
259 typename Image3D::Point up,
260 typename Image3D::Value value )
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 );
281 unsigned int nbok = 0;
283 trace.beginBlock (
"Testing block ... ExplicitDigitalSurface" );
284 Point p1( -5, -5, -5 );
287 nbok +=
K.init( p1, p2,
true ) ? 1 : 0;
289 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
290 <<
"K.init() is ok" << std::endl;
298 SCell bel20 =
K.sIncident( vox2, 2,
true );
299 SurfelPredicate surfPredicate(
K,
image, 2, 0 );
300 Frontier frontier20(
K, surfPredicate,
303 unsigned int nbsurfels = 0;
304 for (
ConstIterator it = frontier20.begin(), it_end = frontier20.end();
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;
316 SCell bel10 =
K.sIncident( vox1, 0,
true );
317 SurfelPredicate surfPredicate(
K,
image, 1, 0 );
318 Frontier frontier10(
K, surfPredicate,
321 unsigned int nbsurfels = 0;
322 for (
ConstIterator it = frontier10.begin(), it_end = frontier10.end();
327 trace.info() << nbsurfels <<
" surfels found." << std::endl;
328 ++nb; nbok += nbsurfels == 140 ? 1 : 0;
329 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
330 <<
"frontier10: nbsurfels == 140" << std::endl;
334 SCell bel12 =
K.sIncident( vox1, 0,
false );
335 SurfelPredicate surfPredicate(
K,
image, 1, 2 );
336 Frontier frontier12(
K, surfPredicate,
339 unsigned int nbsurfels = 0;
340 for (
ConstIterator it = frontier12.begin(), it_end = frontier12.end();
345 trace.info() << nbsurfels <<
" surfels found." << std::endl;
346 ++nb; nbok += nbsurfels == 36 ? 1 : 0;
347 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
348 <<
"frontier12: nbsurfels == 36" << std::endl;
353 typedef Boundary::SurfelConstIterator EConstIterator;
358 SCell bel1x =
K.sIncident( vox1, 0,
false );
359 SecondSurfelPredicate surfPredicate(
K,
image, 1 );
360 Boundary boundary1x(
K, surfPredicate,
363 unsigned int nbsurfels = 0;
364 for ( EConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
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;
389 unsigned int nbok = 0;
391 trace.beginBlock (
"Testing block ... LightExplicitDigitalSurface" );
392 Point p1( -5, -5, -5 );
395 nbok +=
K.init( p1, p2,
true ) ? 1 : 0;
397 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
398 <<
"K.init() is ok" << std::endl;
406 SCell bel20 =
K.sIncident( vox2, 2,
true );
407 SurfelPredicate surfPredicate(
K,
image, 2, 0 );
408 Frontier frontier20(
K, surfPredicate,
411 unsigned int nbsurfels = 0;
412 for (
ConstIterator it = frontier20.begin(), it_end = frontier20.end();
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;
424 SCell bel10 =
K.sIncident( vox1, 0,
true );
425 SurfelPredicate surfPredicate(
K,
image, 1, 0 );
426 Frontier frontier10(
K, surfPredicate,
429 unsigned int nbsurfels = 0;
430 for (
ConstIterator it = frontier10.begin(), it_end = frontier10.end();
435 trace.info() << nbsurfels <<
" surfels found." << std::endl;
436 ++nb; nbok += nbsurfels == 140 ? 1 : 0;
437 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
438 <<
"frontier10: nbsurfels == 140" << std::endl;
442 SCell bel12 =
K.sIncident( vox1, 0,
false );
443 SurfelPredicate surfPredicate(
K,
image, 1, 2 );
444 Frontier frontier12(
K, surfPredicate,
447 unsigned int nbsurfels = 0;
448 for (
ConstIterator it = frontier12.begin(), it_end = frontier12.end();
453 trace.info() << nbsurfels <<
" surfels found." << std::endl;
454 ++nb; nbok += nbsurfels == 36 ? 1 : 0;
455 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
456 <<
"frontier12: nbsurfels == 36" << std::endl;
461 typedef Boundary::SurfelConstIterator LEConstIterator;
466 SCell bel1x =
K.sIncident( vox1, 0,
false );
467 SecondSurfelPredicate surfPredicate(
K,
image, 1 );
468 Boundary boundary1x(
K, surfPredicate,
471 unsigned int nbsurfels = 0;
472 for ( LEConstIterator it = boundary1x.begin(), it_end = boundary1x.end();
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;
488template <
typename KSpace>
491 unsigned int nbok = 0;
493 std::string msg(
"Testing block ... DigitalSurface in K" );
495 trace.beginBlock ( msg );
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 );
512 nbok +=
K.init(
domain.lowerBound(),
domain.upperBound(),
true ) ? 1 : 0;
514 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
515 <<
"K.init() is ok" << std::endl;
518 trace.beginBlock (
"Testing DigitalSurface" );
523 BOOST_CONCEPT_ASSERT(( CConstSinglePassRange < MyDS> ));
524 BOOST_CONCEPT_ASSERT(( CUndirectedSimpleLocalGraph < MyDS> ));
525 BOOST_CONCEPT_ASSERT(( CUndirectedSimpleGraph < MyDS> ));
528 typedef typename MyDS::Surfel
Surfel;
529 DSContainer* ptrBdry =
new DSContainer(
K, dig_set );
530 MyDS digsurf( ptrBdry );
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();
546 ++nb; nbok += digsurf.degree( s ) == 2*(
K.dimension-1) ? 1 : 0;
548 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
549 <<
"digsurf.degree( s ) == "
550 << 2*(
K.dimension-1) << std::endl;
552 trace.beginBlock (
"Testing BreadthFirstVisitor on DigitalSurface" );
556 unsigned int nb_dist_1 = 0;
561 if ( node.second == 1 ) ++nb_dist_1;
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;
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;
596 typedef typename MyDS::Vertex
Vertex;
597 typedef typename MyDS::SCell
SCell;
599 unsigned int nbok = 0;
601 trace.beginBlock (
"Creating surface around one voxel" );
603 Point pt1 = Point::diagonal( -1 );
604 Point pt2 = Point::diagonal( 1 );
609 nbok +=
K.init(
domain.lowerBound(),
domain.upperBound(),
true ) ? 1 : 0;
611 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
612 <<
"K.init() is ok" << std::endl;
613 DSContainer* ptrBdry =
new DSContainer(
K, dig_set );
614 MyDS digsurf( ptrBdry );
615 ++nb; nbok += digsurf.size() == 6 ? 1 : 0;
616 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
617 <<
"digsurf.size() = " << digsurf.size()
618 <<
" == " << 6 << std::endl;
620 trace.beginBlock (
"Check ordering" );
621 std::map< std::pair< SCell, SCell >,
unsigned int > nb_arcs;
622 for (
Vertex v : digsurf )
624 auto faces = digsurf.facesAroundVertex( v,
true );
625 for (
unsigned int i = 0; i < faces.size(); ++i )
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() )
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 )
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;
646 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
647 <<
"arcs have all norm 1." << std::endl;
648 for (
auto arc : nb_arcs )
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;
656 trace.info() <<
"(" << nbok <<
"/" << nb <<
") "
657 <<
"arcs are unique and their inverse are unique." << std::endl;
665int main(
int argc,
char** argv )
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;
682 trace.emphase() << ( res ?
"Passed." :
"Error." ) << endl;
665int main(
int argc,
char** argv ) {
…}
Aim: This class is useful to perform a breadth-first exploration of a graph given a starting point or...
const Node & current() const
const MarkSet & markedVertices() const
std::pair< Vertex, Data > Node
FIXME.
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as the boundary of a given...
void insert(const Point &p)
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....
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
Aim: implements association bewteen points lying in a digital domain and values.
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,...
NumberTraits< Integer >::UnsignedVersion Size
SpaceND< dim, Integer > Space
static const constexpr Dimension dimension
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...
static void addNorm2Ball(TDigitalSet &aSet, const Point &aCenter, UnsignedInteger aRadius)
static void removeNorm2Ball(TDigitalSet &aSet, const Point &aCenter, UnsignedInteger aRadius)
PointVector< dim, Integer > Point
static SCell findABel(const KSpace &K, const PointPredicate &pp, unsigned int nbtries=1000)
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
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....
Point::Coordinate Integer
Z2i this namespace gathers the standard of types for 2D imagery.
Z3i this namespace gathers the standard of types for 3D imagery.
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
DigitalSetByAssociativeContainer< Domain, std::unordered_set< typename Domain::Point > > Type
bool operator()(const TPoint3 &p) const
ImplicitDigitalEllipse3(double a, double b, double c)
bool testDigitalSurface()
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
HyperRectDomain< Space > Domain
Z2i::DigitalSet DigitalSet