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/topology/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"
55 using namespace DGtal;
56 using namespace LibBoard;
58 #define INBLOCK_TEST(x) \
59 nbok += ( x ) ? 1 : 0; \
61 trace.info() << "(" << nbok << "/" << nb << ") " \
64 #define INBLOCK_TEST2(x,y) \
65 nbok += ( x ) ? 1 : 0; \
67 trace.info() << "(" << nbok << "/" << nb << ") " \
79 unsigned int nbok = 0;
86 Point p1( -449, -449 );
88 DomainType domain( p1, p2 );
102 typedef ObjectType::SmallSet SmallSet;
104 typedef ObjectType::Size Size;
110 Adj4 adj4( domain, madj4 );
111 Adj8 adj8( domain, madj8 );
112 DT48 dt48( adj4, adj8, JORDAN_DT );
115 double radius = (double) (r+1);
118 MediumSet disk( domain );
120 sstr <<
"Creating disk( r < " << radius <<
" ) ...";
122 for ( DomainType::ConstIterator it = domain.begin();
126 if ( (*it - c ).norm() < radius )
128 disk.insertNew( *it );
132 trace.
beginBlock (
"Testing Object instanciation and smart copy ..." );
133 ObjectType disk_object( dt48, disk );
134 nbok += disk_object.size() == 7825 ? 1 : 0;
136 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
137 <<
"Disk (r=450.0) " << disk_object << std::endl;
138 trace.
info() <<
" size=" << disk_object.size() << std::endl;
139 ObjectType disk_object2( disk_object );
140 nbok += disk_object2.size() == 7825 ? 1 : 0;
142 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
143 <<
"Disk2 (r=450.0) " << disk_object2 << std::endl;
144 trace.
info() <<
" size=" << disk_object2.size() << std::endl;
148 trace.
info() <<
"Removing center point in Disk." << std::endl;
149 disk_object.pointSet().erase( c );
150 disk_object2.pointSet().insert( c );
151 nbok += disk_object.size() == 7824 ? 1 : 0;
153 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
154 <<
"Disk - c (r=450.0) " << disk_object << std::endl;
155 trace.
info() <<
" size=" << disk_object.size() << std::endl;
156 nbok += disk_object2.size() == 7825 ? 1 : 0;
158 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
159 <<
"Disk2 + c (r=450.0) " << disk_object2 << std::endl;
160 trace.
info() <<
" size=" << disk_object2.size() << std::endl;
165 nbok += neigh.
size() == 4 ? 1 : 0;
167 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
168 <<
"N_4(Disk, c).size() = " << neigh.
size()
169 <<
" == 4" << std::endl;
171 nbok += neigh.
size() == 3 ? 1 : 0;
173 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
174 <<
"N*_4(Disk, " << l <<
").size() = " << neigh.
size()
175 <<
" == 3" << std::endl;
176 Size size = disk_object.properNeighborhoodSize( l );
177 nbok += size == 3 ? 1 : 0;
179 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
180 <<
"#N*_4(Disk, " << l <<
") = " << size
181 <<
" == 3" << std::endl;
184 nbok += neigh.
size() == 5 ? 1 : 0;
186 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
187 <<
"N_4(Disk2, c).size() = " << neigh.
size()
188 <<
" == 5" << std::endl;
193 ( neigh.
pointSet(), disk_object.pointSet() );
194 nbok += neigh.
size() == 7824 ? 1 : 0;
196 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
197 <<
"neigh = disk_object, size() = " << neigh.
size()
198 <<
" == 636100" << std::endl;
199 SmallObjectType neigh2 = disk_object2.neighborhood( c );
201 ( neigh.
pointSet(), neigh2.pointSet() );
202 nbok += neigh.
size() == 5 ? 1 : 0;
204 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
205 <<
"neigh = N_4(Disk2, c), size() = " << neigh.
size()
206 <<
" == 5" << std::endl;
210 ObjectType bdisk = disk_object.border();
211 nbok += bdisk.size() == 400 ? 1 : 0;
213 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
214 <<
"Border(Disk, c), size() = " << bdisk.size()
215 <<
" == 3372" << std::endl;
216 ObjectType bdisk2 = disk_object2.border();
217 nbok += bdisk2.size() == 392 ? 1 : 0;
219 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
220 <<
"Border(Disk2, c), size() = " << bdisk2.size()
221 <<
" == 3364" << std::endl;
224 trace.
beginBlock (
"Testing expansion by layers on the boundary ..." );
226 ObjectExpander expander( bdisk, *(bdisk.pointSet().begin()) );
227 while ( ! expander.finished() )
229 nbok += expander.layer().size() <= 2 ? 1 : 0;
231 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
232 <<
"expander.layer.size() <= 2 "
233 << expander << std::endl;
234 expander.nextLayer();
238 trace.
beginBlock (
"Testing expansion by layers on the disk from center..." );
239 ObjectExpander expander2( disk_object2, c );
240 while ( ! expander2.finished() )
243 expander2.nextLayer();
245 nbok += expander2.distance() <= sqrt(2.0)*radius ? 1 : 0;
247 trace.
info() <<
"(" << nbok <<
"/" << nb <<
") "
248 <<
"expander.distance() = " << expander2.distance()
249 <<
" <= " << sqrt(2.0)*radius << std::endl;
261 unsigned int nbok = 0;
267 typedef Z3::Point Point;
274 DT6_18 dt6_18( adj6, adj18, JORDAN_DT );
276 Point p1( -50, -50, -50 );
277 Point p2( 50, 50, 50 );
278 Domain domain( p1, p2 );
282 trace.
beginBlock (
"Testing 3D Object instanciation and smart copy ..." );
283 trace.
info() <<
"Creating diamond (r=15)" << endl;
285 DigitalSet diamond_set( domain );
286 for ( DomainConstIterator it = domain.begin(); it != domain.end(); ++it )
288 if ( (*it - c ).norm1() <= 15 ) diamond_set.insertNew( *it );
290 ObjectType diamond( dt6_18, diamond_set );
291 trace.
info() <<
"Cloning diamond" << endl;
293 ObjectType diamond_clone( diamond );
295 trace.
info() <<
"Removing two points " << c <<
" and " << d << endl;
296 diamond_clone.pointSet().erase( c );
297 diamond_clone.pointSet().erase( d );
299 trace.
info() <<
"Inserting into vector<Object>" << endl;
300 vector<ObjectType> objects;
301 back_insert_iterator< vector< ObjectType > > inserter( objects );
302 *inserter++ = diamond;
303 *inserter++ = diamond_clone;
305 for ( vector<ObjectType>::const_iterator it = objects.begin();
308 trace.
info() <<
"- objects[" << (it - objects.begin() ) <<
"]"
309 <<
" = " << *it << endl;
311 INBLOCK_TEST( objects[ 0 ].size() == ( objects[ 1 ].size() + 2 ) );
312 INBLOCK_TEST( objects[ 0 ].size() == 4991 );
322 vector<ObjectType> objects2;
323 back_insert_iterator< vector< ObjectType > > inserter2( objects2 );
324 unsigned int nbc0 = objects[ 0 ].border().writeComponents( inserter2 );
325 INBLOCK_TEST( nbc0 == 1 );
326 INBLOCK_TEST( objects[ 0 ].computeConnectedness() == CONNECTED );
330 unsigned int nbc1 = objects[ 1 ].border().writeComponents( inserter2 );
331 INBLOCK_TEST( nbc1 == 3 );
333 for ( vector<ObjectType>::const_iterator it = objects2.begin();
334 it != objects2.end();
336 trace.
info() <<
"- objects2[" << (it - objects2.begin() ) <<
"]"
337 <<
" = " << *it << endl;
338 INBLOCK_TEST( objects2[ 0 ].size() == objects2[ 1 ].size() );
339 INBLOCK_TEST( objects2[ 2 ].size() == objects2[ 3 ].size() );
340 INBLOCK_TEST( objects2[ 0 ].size() == 1688 );
341 INBLOCK_TEST( objects2[ 2 ].size() == 18 );
353 bool testSimplePoints3D()
355 unsigned int nbok = 0;
361 typedef Z3::Point Point;
370 DT6_18 dt6_18( adj6, adj18, JORDAN_DT );
372 Point p1( -10, -10, -10 );
373 Point p2( 10, 10, 10 );
374 Domain domain( p1, p2 );
380 DigitalSet diamond_set( domain );
381 for ( DomainConstIterator it = domain.begin(); it != domain.end(); ++it )
383 if ( (*it - c ).norm1() <= 3 ) diamond_set.insertNew( *it );
385 diamond_set.erase( c );
386 ObjectType diamond( dt6_18, diamond_set );
390 SmallObjectType geoN6_3 = diamond.geodesicNeighborhood( adj6, r, 3 );
391 SmallObjectType geoN18_2 = diamond.geodesicNeighborhood( adj18, r, 2 );
392 trace.
info() <<
"geoN6_3 = " << geoN6_3 << endl;
393 trace.
info() <<
"geoN18_2 = " << geoN18_2 << endl;
394 SmallComplementObjectType cgeoN6_3 = diamond.geodesicNeighborhoodInComplement( adj6, r, 3 );
395 SmallComplementObjectType cgeoN18_2 = diamond.geodesicNeighborhoodInComplement( adj18, r, 2 );
396 trace.
info() <<
"cgeoN6_3 = " << cgeoN6_3 << endl;
397 trace.
info() <<
"cgeoN18_2 = " << cgeoN18_2 << endl;
402 it != diamond.pointSet().end();
405 <<
" " << ( diamond.isSimple( *it ) ?
"Simple" :
"Not simple" )
416 unsigned int nbok = 0;
425 Point p1( -10, -10 );
427 DomainType domain( p1, p2 );
444 typedef ObjectType::SmallSet SmallSet;
446 typedef ObjectType::Size Size;
452 Adj4 adj4( domain, madj4 );
453 Adj8 adj8( domain, madj8 );
454 DT48 dt48( adj4, adj8, JORDAN_DT );
455 DT84 dt84( adj8, adj4, JORDAN_DT );
458 double radius = (double) (r+1);
461 MediumSet disk( domain );
463 sstr <<
"Creating disk( r < " << radius <<
" ) ...";
465 for ( DomainType::ConstIterator it = domain.begin();
469 if ( (*it - c ).norm() < radius )
471 disk.insertNew( *it );
475 trace.
beginBlock (
"Testing Object instanciation and smart copy ..." );
476 ObjectType disk_object( dt48, disk );
477 ObjectType84 disk_object2( dt84, disk );
483 board.
setUnit(Board::UCentimeter);
485 board <<
SetMode( domain.className(),
"Grid" ) << domain;
486 board << disk_object;
488 board.
saveSVG(
"disk-object.svg");
491 board2.
setUnit(Board::UCentimeter);
493 board2 <<
SetMode( domain.className(),
"Grid" ) << domain;
494 board2 <<
SetMode( disk_object.className(),
"DrawAdjacencies" ) << disk_object;
496 board2.
saveSVG(
"disk-object-adj.svg");
499 board3.
setUnit(Board::UCentimeter);
501 board3 <<
SetMode( domain.className(),
"Grid" ) << domain;
502 board3 <<
SetMode( disk_object2.className(),
"DrawAdjacencies" ) << disk_object2;
504 board3.
saveSVG(
"disk-object-adj-bis.svg");
539 using namespace DGtal::Z2i;
545 bool testSimplePoints2D()
547 unsigned int nbok = 0;
552 Point p1( -17, -17 );
554 Domain domain( p1, p2 );
555 DigitalSet shape_set( domain );
565 shape_set.erase( Point( 5, 0 ) );
566 shape_set.erase( Point( -1, -2 ) );
571 cmap_grad.addColor(
Color( 128, 128, 255 ) );
572 cmap_grad.addColor(
Color( 255, 255, 128 ) );
575 board.
setUnit(Board::UCentimeter);
576 board <<
SetMode( domain.className(),
"Paving" )
579 board2.
setUnit(Board::UCentimeter);
580 board2 <<
SetMode( domain.className(),
"Grid" )
589 DigitalSet & S = shape.pointSet();
590 std::queue<DigitalSet::Iterator> Q;
592 if ( shape.isSimple( *it ) )
595 while ( ! Q.empty() )
599 if ( shape.isSimple( *it ) )
603 ( cmap_grad( layer ) ) )
611 while ( nb_simple != 0 );
619 DigitalSet & S = shape2.pointSet();
620 std::queue<DigitalSet::Iterator> Q;
622 if ( shape2.isSimple( *it ) )
625 while ( ! Q.empty() )
629 if ( shape2.isSimple( *it ) )
633 ( cmap_grad( layer ) ) )
641 while ( nb_simple != 0 );
646 board.
saveSVG(
"shape-thinning-4-8.svg");
651 board2.saveSVG(
"shape-thinning-8-4.svg");
663 int main(
int argc,
char** argv )
667 for (
int i = 0; i < argc; ++i )
671 bool res = testObject() &&
672 testObject3D() && testDraw()
673 && testSimplePoints3D()
674 && testSimplePoints2D();
676 trace.
emphase() << ( res ?
"Passed." :
"Error." ) << endl;