DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
testCellularGridSpaceND.cpp
1 
30 
31 #include <iostream>
32 #include "DGtal/base/Common.h"
33 #include "DGtal/kernel/SpaceND.h"
34 #include "DGtal/kernel/domains/HyperRectDomain.h"
35 #include "DGtal/kernel/sets/DigitalSetSelector.h"
36 #include "DGtal/topology/CCellularGridSpaceND.h"
37 #include "DGtal/topology/KhalimskySpaceND.h"
38 #include "DGtal/topology/SurfelAdjacency.h"
39 #include "DGtal/topology/SurfelNeighborhood.h"
40 #include "DGtal/shapes/Shapes.h"
41 #include "DGtal/topology/helpers/Surfaces.h"
42 #include "DGtal/io/boards/Board2D.h"
43 #include "DGtal/io/Color.h"
45 
46 using namespace std;
47 using namespace DGtal;
48 
50 // Functions for testing class CellularGridSpaceND.
52 
56 template <typename KSpace>
57 bool testCellularGridSpaceND()
58 {
59  typedef typename KSpace::Cell Cell;
60  typedef typename KSpace::SCell SCell;
61  typedef typename KSpace::Point Point;
62  typedef typename KSpace::DirIterator DirIterator;
63  typedef typename KSpace::Cells Cells;
64  typedef typename KSpace::SCells SCells;
65  unsigned int nbok = 0;
66  unsigned int nb = 0;
67 
68  trace.beginBlock ( "Testing block KSpace instantiation and scan ..." );
69  KSpace K;
70  int xlow[ 4 ] = { -3, -2, -2, -1 };
71  int xhigh[ 4 ] = { 5, 3, 2, 3 };
72  Point low( xlow );
73  Point high( xhigh );
74  bool space_ok = K.init( low, high, true );
75  nbok += space_ok ? 1 : 0;
76  nb++;
77  trace.info() << "(" << nbok << "/" << nb << ") "
78  << "K.init( low, high )" << std::endl;
79  trace.info() << "K.dim()=" << K.dimension << endl;
80  int spel[ 4 ] = { 1, 1, 1, 1 }; // pixel
81  Point kp( spel );
82  Cell center = K.uCell( kp );
83  Cell c1 = K.uCell( kp );
84  Cell clow = K.uCell( low, kp );
85  Cell chigh = K.uCell( high, kp );
86  trace.info() << c1 << clow << chigh
87  << " topo(c1)=" << K.uTopology( c1 ) << " dirs=";
88  for ( DirIterator q = K.uDirs( clow ); q != 0; ++q )
89  trace.info() << " " << *q;
90  trace.info() << endl;
91  Cell f = K.uFirst( c1 );
92  Cell l = K.uLast( c1 );
93  trace.info() << "Loop in " << clow << chigh << endl;
94  c1 = f;
95  unsigned int nbelems = 0;
96  do {
97  ++nbelems;
98  // trace.info() << c1;
99  } while ( K.uNext( c1, f, l ) );
100  trace.info() << " -> " << nbelems << " elements." << endl;
101  unsigned int exp_nbelems = 1;
102  for ( Dimension i = 0; i < K.dimension; ++i )
103  exp_nbelems *= K.size( i );
104  nbok += nbelems == exp_nbelems ? 1 : 0;
105  nb++;
106  trace.info() << "(" << nbok << "/" << nb << ") "
107  << nbelems << " scanned elements == "
108  << exp_nbelems << " space size."
109  << std::endl;
110  trace.endBlock();
111  trace.beginBlock ( "Testing neighborhoods in KSpace..." );
112  Cells N = K.uNeighborhood( center );
113  nbok += N.size() == ( K.dimension*2 + 1 ) ? 1 : 0;
114  nb++;
115  trace.info() << "(" << nbok << "/" << nb << ") "
116  << N.size() << "(neighborhood size) == "
117  << ( K.dimension*2 + 1 ) << "(2*dim()+1)" << endl;
118  Cells Np = K.uProperNeighborhood( center );
119  nbok += Np.size() == ( K.dimension*2 ) ? 1 : 0;
120  nb++;
121  trace.info() << "(" << nbok << "/" << nb << ") "
122  << Np.size() << "(proper neighborhood size) == "
123  << ( K.dimension*2 ) << "(2*dim())" << endl;
124  trace.endBlock();
125 
126  trace.beginBlock ( "Testing faces in KSpace..." );
127  Cells Nf = K.uFaces( center );
128  nbok += Nf.size() == ceil( std::pow( 3.0 ,(int) K.dimension ) - 1 ) ? 1 : 0;
129  nb++;
130  trace.info() << "(" << nbok << "/" << nb << ") "
131  << Nf.size() << "(faces size) == "
132  << floor( std::pow( 3.0, (int)K.dimension ) - 1 ) << "(3^dim()-1)" << endl;
133  trace.endBlock();
134 
135  trace.beginBlock ( "Testing block Incidence in KSpace..." );
136  SCell sspel = K.sCell( kp, K.POS );
137  for ( DirIterator q1 = K.sDirs( sspel ); q1 != 0; ++q1 )
138  for ( DirIterator q2 = K.sDirs( sspel ); q2 != 0; ++q2 )
139  {
140  if ( *q1 != *q2 )
141  {
142  SCell s0 = K.sIncident( sspel, *q1, true );
143  SCell s1 = K.sIncident( sspel, *q2, true );
144  SCell l10 = K.sIncident( s0, *q2, true );
145  SCell l01 = K.sIncident( s1, *q1, true );
146  trace.info() << "D+_" << *q2 << "(D+_" << *q1 << "(V))=" << l10
147  << " D+_" << *q1 << "(D+_" << *q2 << "(V))=" << l01
148  << endl;
149  nbok += l10 == K.sOpp( l01 ) ? 1 : 0;
150  nb++;
151  }
152  }
153  trace.info() << "(" << nbok << "/" << nb << ") "
154  << "anti-commutativity of incidence operators." << std::endl;
155  trace.endBlock();
156 
157  trace.beginBlock ( "Testing direct Incidence in KSpace..." );
158  for ( DirIterator q1 = K.sDirs( sspel ); q1 != 0; ++q1 )
159  for ( DirIterator q2 = K.sDirs( sspel ); q2 != 0; ++q2 )
160  {
161  if ( *q1 != *q2 )
162  {
163  SCell s0 = K.sDirectIncident( sspel, *q1 );
164  SCell l10 = K.sDirectIncident( s0, *q2 );
165  SCell s1 = K.sDirectIncident( sspel, *q2 );
166  SCell l01 = K.sDirectIncident( s1, *q1 );
167  trace.info() << "Dd_" << *q2 << "(Dd_" << *q1 << "(V))=" << l10
168  << " Dd_" << *q1 << "(Dd_" << *q2 << "(V))=" << l01
169  << endl;
170  nbok += l10 != l01 ? 1 : 0;
171  nbok += K.sSign( s0 ) == K.POS ? 1 : 0;
172  nbok += K.sSign( s1 ) == K.POS ? 1 : 0;
173  nbok += K.sSign( l10 ) == K.POS ? 1 : 0;
174  nbok += K.sSign( l01 ) == K.POS ? 1 : 0;
175  nbok += s0 == K.sIncident( sspel, *q1, K.sDirect( sspel, *q1 ) )
176  ? 1 : 0;
177  nbok += s1 == K.sIncident( sspel, *q2, K.sDirect( sspel, *q2 ) )
178  ? 1 : 0;
179  nbok += l10 == K.sIncident( s0, *q2, K.sDirect( s0, *q2 ) )
180  ? 1 : 0;
181  nbok += l01 == K.sIncident( s1, *q1, K.sDirect( s1, *q1 ) )
182  ? 1 : 0;
183  nb += 9;
184  }
185  }
186  trace.info() << "(" << nbok << "/" << nb << ") "
187  << "correctness of direct and indirect orientations." << std::endl;
188 
189  trace.endBlock();
190 
191 
192  return nbok == nb;
193 }
194 
195 
196 template <typename KSpace>
197 bool testSurfelAdjacency()
198 {
199  typedef typename KSpace::Integer Integer;
200  typedef typename KSpace::Cell Cell;
201  typedef typename KSpace::SCell SCell;
202  typedef typename KSpace::Point Point;
203  typedef typename KSpace::DirIterator DirIterator;
204  typedef typename KSpace::Cells Cells;
205  typedef typename KSpace::SCells SCells;
206  unsigned int nbok = 0;
207  unsigned int nb = 0;
208 
209  trace.beginBlock ( "Testing block KSpace instantiation and scan ..." );
210  KSpace K;
211  int xlow[ 4 ] = { -3, -3, -3, -3 };
212  int xhigh[ 4 ] = { 5, 3, 3, 3 };
213  Point low( xlow );
214  Point high( xhigh );
215  bool space_ok = K.init( low, high, true );
216  nbok += space_ok ? 1 : 0;
217  nb++;
218  trace.info() << "(" << nbok << "/" << nb << ") "
219  << "K.init( low, high )" << std::endl;
220  trace.info() << "K.dim()=" << K.dimension << endl;
221  trace.endBlock();
222  trace.beginBlock ( "Testing surfel adjacency ..." );
224  for ( Dimension i = 0; i < K.dimension; ++i )
225  for ( Dimension j = 0; j < K.dimension; ++j )
226  if ( i != j )
227  trace.info() << "(" << i << "," << j << ")="
228  << ( SAdj.getAdjacency( i, j ) ? "i2e" : "e2i" );
229  trace.info() << endl;
230  trace.endBlock();
231 
232  int spel[ 4 ] = { 1, 1, 1, 1 }; // pixel
233  Point kp( spel );
234  SCell sspel = K.sCell( kp, K.POS );
235  trace.beginBlock ( "Testing surfel directness ..." );
236  for ( Dimension k = 0; k < K.dimension; ++k )
237  {
238  SCell surfel = K.sIncident( sspel, k, true );
239  SCell innerspel = K.sDirectIncident( surfel, K.sOrthDir( surfel ) );
240  trace.info() << "spel=" << sspel << " surfel=" << surfel
241  << " innerspel=" << innerspel << endl;
242  nbok += sspel == innerspel ? 1 : 0;
243  nb++;
244  trace.info() << "(" << nbok << "/" << nb << ") "
245  << "spel == innerspel" << std::endl;
246  surfel = K.sIncident( sspel, k, false );
247  innerspel = K.sDirectIncident( surfel, K.sOrthDir( surfel ) );
248  trace.info() << "spel=" << sspel << " surfel=" << surfel
249  << " innerspel=" << innerspel << endl;
250  nbok += sspel == innerspel ? 1 : 0;
251  nb++;
252  trace.info() << "(" << nbok << "/" << nb << ") "
253  << "spel == innerspel" << std::endl;
254  }
255  trace.endBlock();
256 
258  trace.beginBlock ( "Testing surfel neighborhood ..." );
259  SCell surfel = K.sIncident( sspel, 0, false );
260  SN.init( &K, &SAdj, surfel );
261  trace.info() << "surfel =" << surfel << endl;
262  trace.info() << "follower1(+)=" << SN.follower1( 1, true ) << endl;
263  trace.info() << "follower2(+)=" << SN.follower2( 1, true ) << endl;
264  trace.info() << "follower3(+)=" << SN.follower3( 1, true ) << endl;
265  trace.info() << "follower1(-)=" << SN.follower1( 1, false ) << endl;
266  trace.info() << "follower2(-)=" << SN.follower2( 1, false ) << endl;
267  trace.info() << "follower3(-)=" << SN.follower3( 1, false ) << endl;
268  trace.endBlock();
269 
270  trace.beginBlock ( "Testing surface tracking ..." );
274  Domain domain( low, high );
275  DigitalSet shape_set( domain );
276  SetPredicate<DigitalSet> shape_set_predicate( shape_set );
277  int center[ 4 ] = { 1, 0, 0, 0 }; // pixel
278  Point pcenter( center );
279  Shapes<Domain>::addNorm1Ball( shape_set, pcenter, 1 );
280  trace.info() << "surfel = " << surfel << endl;
281  SCell other1, other2;
282  SN.getAdjacentOnDigitalSet( other1, shape_set, 1, K.sDirect( surfel, 1 ) );
283  SN.getAdjacentOnDigitalSet( other2, shape_set, 1, !K.sDirect( surfel, 1 ) );
284  trace.info() << "directNext = " << other1 << endl;
285  trace.info() << "indirectNext= " << other2 << endl;
286  std::set<SCell> bdry;
287 
288  // surfel = Surfaces<KSpace>::findABel( K, shape_set );
289 
291  K, SAdj, shape_set_predicate, surfel );
292  trace.info() << "tracking finished, size=" << bdry.size()
293  << ", should be " << 2*K.dimension*(2*K.dimension-1) << endl;
294  nbok += bdry.size() == ( 2*K.dimension*(2*K.dimension-1) ) ? 1 : 0;
295  nb++;
296  trace.info() << "(" << nbok << "/" << nb << ") "
297  << "bdry.size() == ( 2*K.dimension*(2*K.dimension-1) )"
298  << std::endl;
299  std::set<SCell> bdry_direct;
301  K, SAdj, shape_set_predicate, surfel );
302  trace.info() << "fast direct tracking finished, size=" << bdry_direct.size()
303  << ", should be " << 2*K.dimension*(2*K.dimension-1) << endl;
304  nbok += bdry_direct.size() == ( 2*K.dimension*(2*K.dimension-1) ) ? 1 : 0;
305  nb++;
306  trace.info() << "(" << nbok << "/" << nb << ") "
307  << "bdry_direct.size() == ( 2*K.dimension*(2*K.dimension-1) )"
308  << std::endl;
309 
310  trace.endBlock();
311  if ( K.dimension == 2 )
312  {
313  Board2D board;
315  board << SetMode( domain.className(), "Paving" )
316  << domain;
317  for ( typename std::set<SCell>::const_iterator it = bdry_direct.begin(),
318  it_end = bdry_direct.end(); it != it_end; ++it )
319  board << *it;
320  board.saveEPS( "cells-2.eps" );
321  board.saveSVG( "cells-2.svg" );
322  }
323  return nbok == nb;
324 }
325 
326 template <typename KSpace>
327 bool testCellDrawOnBoard()
328 {
329  typedef typename KSpace::Integer Integer;
330  typedef typename KSpace::Cell Cell;
331  typedef typename KSpace::SCell SCell;
332  typedef typename KSpace::Point Point;
333  typedef typename KSpace::DirIterator DirIterator;
334  typedef typename KSpace::Cells Cells;
335  typedef typename KSpace::SCells SCells;
336  typedef SpaceND<2, Integer> Z2;
337  typedef HyperRectDomain<Z2> Domain;
338  unsigned int nbok = 0;
339  unsigned int nb = 0;
340  trace.beginBlock ( "Testing cell draw on digital board ..." );
341  KSpace K;
342  int xlow[ 4 ] = { -3, -3 };
343  int xhigh[ 4 ] = { 5, 3 };
344  Point low( xlow );
345  Point high( xhigh );
346  bool space_ok = K.init( low, high, true );
347  Domain domain( low, high );
348  Board2D board;
350  board << SetMode( domain.className(), "Paving" )
351  << domain;
352  int spel[ 2 ] = { 1, 1 }; // pixel 0,0
353  Point kp( spel );
354  Cell uspel = K.uCell( kp );
355  board << uspel
356  << low << high
357  << K.uIncident( uspel, 0, false )
358  << K.uIncident( uspel, 1, false );
359  int spel2[ 2 ] = { 5, 1 }; // pixel 2,0
360  Point kp2( spel2 );
361  SCell sspel2 = K.sCell( kp2, K.POS );
362  board << CustomStyle( sspel2.className(),
363  new CustomPen( Color( 200, 0, 0 ),
364  Color( 255, 100, 100 ),
365  2.0,
366  Board2D::Shape::SolidStyle ) )
367  << sspel2
368  << K.sIncident( sspel2, 0, K.sDirect( sspel2, 0 ) )
369  << K.sIncident( sspel2, 1, K.sDirect( sspel2, 0 ) );
370  board.saveEPS( "cells-1.eps" );
371  board.saveSVG( "cells-1.svg" );
372  trace.endBlock();
373  board.clear();
374  board << domain;
375  SCell slinel0 = K.sIncident( sspel2, 0, K.sDirect( sspel2, 0 ) );
376  SCell spointel01 = K.sIncident( slinel0, 1, K.sDirect( slinel0, 1 ) );
377  board << CustomStyle( sspel2.className(),
378  new CustomColors( Color( 200, 0, 0 ),
379  Color( 255, 100, 100 ) ) )
380  << sspel2
381  << CustomStyle( slinel0.className(),
382  new CustomColors( Color( 0, 200, 0 ),
383  Color( 100, 255, 100 ) ) )
384  << slinel0
385  << CustomStyle( spointel01.className(),
386  new CustomColors( Color( 0, 0, 200 ),
387  Color( 100, 100, 255 ) ) )
388  << spointel01;
389  board.saveEPS( "cells-3.eps" );
390  board.saveSVG( "cells-3.svg" );
391 
392  return ((space_ok) && (nbok == nb));
393 }
394 
395 template <typename KSpace>
396 bool testFindABel()
397 {
398  typedef typename KSpace::Point Point;
400  typedef HyperRectDomain<Space> Domain;
401  typedef typename DigitalSetSelector< Domain, BIG_DS+HIGH_BEL_DS >::Type DigitalSet;
402  typedef typename KSpace::SCell SCell;
403  typedef SetPredicate<DigitalSet> PointPredicate;
404 
405  trace.beginBlock("Test FindABel");
406  Point low(-3,-3,-3), high(3,3,3);
407  Domain domain( low, high );
408  DigitalSet shape_set( domain );
409  PointPredicate pp( shape_set );
410  KSpace K;
411  K.init( low, high, true );
412 
413  Point p000(0,0,0), p001(0,0,1), p010(0,1,0), p011(0,1,1),
414  p100(1,0,0), p101(1,0,1), p110(1,1,0), p111(1,1,1);
415 
416  shape_set.insert( p000 );
417  shape_set.insert( p100 );
418 
419  Surfaces<KSpace>::findABel( K, pp , p000 , p011 );
420  Surfaces<KSpace>::findABel( K, pp , p000 , p110 );
421  Surfaces<KSpace>::findABel( K, pp , p000 , p111 );
422  Surfaces<KSpace>::findABel( K, pp , p000 , p101 );
423  SCell s010 = Surfaces<KSpace>::findABel( K, pp , p000 , p010 );
424  SCell s001 = Surfaces<KSpace>::findABel( K, pp , p000 , p001 );
425 
426  trace.endBlock();
427  return ( (s010 == SCell( Point(1,2,1), true ) ) &&
428  (s001 == SCell( Point(1,1,2), false ) ) );
429 }
430 
432 // Standard services - public :
433 
434 int main( int argc, char** argv )
435 {
436  trace.beginBlock ( "Testing class CellularGridSpaceND" );
437  trace.info() << "Args:";
438  for ( int i = 0; i < argc; ++i )
439  trace.info() << " " << argv[ i ];
440  trace.info() << endl;
441 
442  typedef KhalimskySpaceND<2> K2;
443  typedef KhalimskySpaceND<3> K3;
444  typedef KhalimskySpaceND<4> K4;
445  BOOST_CONCEPT_ASSERT(( CCellularGridSpaceND< K2 > ));
446  BOOST_CONCEPT_ASSERT(( CCellularGridSpaceND< K3 > ));
447  BOOST_CONCEPT_ASSERT(( CCellularGridSpaceND< K4 > ));
448 
449  bool res = testCellularGridSpaceND<K2>()
450  && testCellularGridSpaceND<K3>()
451  && testCellularGridSpaceND<K4>()
452  && testSurfelAdjacency<K2>()
453  && testSurfelAdjacency<K3>()
454  && testSurfelAdjacency<K4>()
455  && testCellDrawOnBoard<K2>()
456  && testFindABel<K3>();
457  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
458  trace.endBlock();
459  return res ? 0 : 1;
460 }
461 // //