DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Surfaces.ih
1 
30 
31 #include <cstdlib>
32 #include <vector>
33 #include <queue>
34 #include <algorithm>
35 #include "DGtal/kernel/CPointPredicate.h"
36 #include "DGtal/images/imagesSetsUtils/ImageFromSet.h"
37 #include "DGtal/images/ImageSelector.h"
38 #include "DGtal/topology/CSurfelPredicate.h"
39 #include "DGtal/helpers/StdDefs.h"
40 
41 
43 
45 // IMPLEMENTATION of inline methods.
47 
49 // ----------------------- Standard services ------------------------------
50 
54 template <typename TKSpace>
55 inline
57 {
58 }
59 //-----------------------------------------------------------------------------
60 template <typename TKSpace>
61 template <typename PointPredicate>
65 ( const KSpace & K,
66  const PointPredicate & pp,
67  unsigned int nbtries) throw (DGtal::InputException)
68 {
69  BOOST_CONCEPT_ASSERT(( CPointPredicate<PointPredicate> ));
70 
71  DGtal::InputException dgtalerror;
72  Point sizes = K.upperBound() - K.lowerBound();
73  Point x1 = K.lowerBound();
74  Point x2;
75  // (1) Find two candidates in the space.
76  bool val_v1 = pp( x1 ); // dset.find( x1 ) != dset.end();
77  bool found = false;
78  Integer r;
79  for ( unsigned int j = 0; j < nbtries; ++j )
80  {
81  for ( Dimension i = 0; i < K.dimension; ++i )
82  {
83  r = rand();
84  x2[ i ] = ( r % sizes[ i ] ) + K.min( i );
85  }
86  bool val_v2 = pp( x2 ); // dset.find( x2 ) != dset.end();
87  if ( val_v2 != val_v1 )
88  {
89  found = true;
90  break;
91  }
92  }
93  if ( ! found ) throw dgtalerror;
94  return findABel( K, pp, x1, x2 );
95 }
96 //-----------------------------------------------------------------------------
97 template <typename TKSpace>
98 template <typename PointPredicate>
101 findABel
102 ( const KSpace & K,
103  const PointPredicate & pp,
104  Point x1, Point x2 )
105 {
106  BOOST_CONCEPT_ASSERT(( CPointPredicate<PointPredicate> ));
107  // (1) Checks the two candidates in the space.
108  bool val_v1 = pp( x1 ); // dset.find( x1 ) != dset.end();
109  ASSERT( val_v1 != pp( x2 ) );
110  // (2) Find two candidates on the same axis.
111  Dimension d = 0;
112  bool alreadyOnSameAxis = true;
113  for ( Dimension i = 0; i < K.dimension; ++i )
114  {
115  if ( x1[ i ] != x2[ i ] )
116  {
117  for ( Dimension j = i + 1; j < K.dimension; ++j )
118  {
119  if ( x1[ j ] != x2[ j ] )
120  {
121  alreadyOnSameAxis = false;
122  Integer c = x2[ j ];
123  x2[ j ] = x1[ j ];
124  bool val_v2 = pp( x2 ); // dset.find( x2 ) != dset.end();
125  if ( val_v2 != val_v1 )
126  { // v2 is updated.
127  d = i;
128  }
129  else
130  { // v1 is updated.
131  x1 = x2;
132  x2[ j ] = c;
133  d = j;
134  }
135  } // if ( x1[ j ] != x2[ j ] )
136  } // for ( Dimension j = i + 1; j < K.dimension; ++j )
137  if ( alreadyOnSameAxis )
138  d = i;
139  } // if ( x1[ i ] != x2[ i ] )
140  } // for ( Dimension i = 0; i < K.dimension; ++i )
141 
142  // (3) Check result.
143  for ( Dimension i = 0; i < K.dimension; ++i )
144  {
145  if ( ( i == d ) && ( x1[ i ] == x2[ i ] ) )
146  std::cerr << "[DGtal::Surfaces::findABel] Error 1a along "
147  << i << std::endl;
148  if ( ( i != d ) && ( x1[ i ] != x2[ i ] ) )
149  std::cerr << "[DGtal::Surfaces::findABel] Error 1b along "
150  << i << std::endl;
151  }
152 
153  // (4) Dichotomy
154  Point xmid = x1;
155  while ( true )
156  {
157  xmid[ d ] = ( x1[ d ] + x2[ d ] ) / 2;
158  if ( ( xmid[ d ] == x1[ d ] ) || ( xmid[ d ] == x2[ d ] ) )
159  break;
160  bool val_mid = pp( xmid ); // dset.find( xmid ) != dset.end();
161  if ( val_mid != val_v1 )
162  x2[ d ] = xmid[ d ];
163  else
164  x1[ d ] = xmid[ d ];
165  }
166 
167  // (5) Check result.
168  for ( Dimension i = 0; i < K.dimension; ++i )
169  {
170  // std::cerr << "i=" << i << " x1=" << x1[ i ] << " x2=" << x2[ i ]
171  // << std::endl;
172  if ( ( i == d ) && ( x1[ i ] != x2[ i ] - 1 ) )
173  std::cerr << "[DGtal::Surfaces::findABel] Error 2a along "
174  << i << std::endl;
175  if ( ( i != d ) && ( x1[ i ] != x2[ i ] ) )
176  std::cerr << "[DGtal::Surfaces::findABel] Error 2a along "
177  << i << std::endl;
178  }
179 
180  // (6) Computes bel.
181  if ( val_v1 )
182  return K.sIncident( K.sSpel( x1, K.POS ), d, true );
183  else
184  return K.sIncident( K.sSpel( x1, K.NEG ), d, true );
185 }
186 //-----------------------------------------------------------------------------
187 template <typename TKSpace>
188 template <typename SCellSet, typename PointPredicate >
189 void
191 trackBoundary( SCellSet & surface,
192  const KSpace & K,
193  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
194  const PointPredicate & pp,
195  const SCell & start_surfel )
196 {
197  BOOST_CONCEPT_ASSERT(( CPointPredicate<PointPredicate> ));
198 
199  SCell b; // current surfel
200  SCell bn; // neighboring surfel
201  ASSERT( K.sIsSurfel( start_surfel ) );
202  surface.clear(); // boundary being extracted.
203 
205  SN.init( &K, &surfel_adj, start_surfel );
206  std::queue<SCell> qbels;
207  qbels.push( start_surfel );
208  surface.insert( start_surfel );
209  // For all pending bels
210  while ( ! qbels.empty() )
211  {
212  b = qbels.front();
213  qbels.pop();
214  SN.setSurfel( b );
215  for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
216  {
217  Dimension track_dir = *q;
218  // ----- 1st pass with positive orientation ------
219  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir, true ) )
220  {
221  if ( surface.find( bn ) == surface.end() )
222  {
223  surface.insert( bn );
224  qbels.push( bn );
225  }
226  }
227  // ----- 2nd pass with negative orientation ------
228  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir, false ) )
229  {
230  if ( surface.find( bn ) == surface.end() )
231  {
232  surface.insert( bn );
233  qbels.push( bn );
234  }
235  }
236  } // for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
237  } // while ( ! qbels.empty() )
238 }
239 //-----------------------------------------------------------------------------
240 template <typename TKSpace>
241 template <typename SCellSet, typename SurfelPredicate >
242 void
244 trackSurface( SCellSet & surface,
245  const KSpace & K,
246  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
247  const SurfelPredicate & sp,
248  const SCell & start_surfel )
249 {
250  BOOST_CONCEPT_ASSERT(( CSurfelPredicate<SurfelPredicate> ));
251 
252  SCell b; // current surfel
253  SCell bn; // neighboring surfel
254  ASSERT( K.sIsSurfel( start_surfel ) );
255  surface.clear(); // boundary being extracted.
256 
258  SN.init( &K, &surfel_adj, start_surfel );
259  std::queue<SCell> qbels;
260  qbels.push( start_surfel );
261  surface.insert( start_surfel );
262  // For all pending bels
263  while ( ! qbels.empty() )
264  {
265  b = qbels.front();
266  qbels.pop();
267  SN.setSurfel( b );
268  for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
269  {
270  Dimension track_dir = *q;
271  // ----- 1st pass with positive orientation ------
272  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir, true ) )
273  {
274  if ( surface.find( bn ) == surface.end() )
275  {
276  surface.insert( bn );
277  qbels.push( bn );
278  }
279  }
280  // ----- 2nd pass with negative orientation ------
281  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir, false ) )
282  {
283  if ( surface.find( bn ) == surface.end() )
284  {
285  surface.insert( bn );
286  qbels.push( bn );
287  }
288  }
289  } // for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
290  } // while ( ! qbels.empty() )
291 }
292 
293 //-----------------------------------------------------------------------------
294 template <typename TKSpace>
295 template <typename SCellSet, typename SurfelPredicate >
296 void
298 trackClosedSurface( SCellSet & surface,
299  const KSpace & K,
300  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
301  const SurfelPredicate & sp,
302  const SCell & start_surfel )
303 {
304  BOOST_CONCEPT_ASSERT(( CSurfelPredicate<SurfelPredicate> ));
305 
306  SCell b; // current surfel
307  SCell bn; // neighboring surfel
308  ASSERT( K.sIsSurfel( start_surfel ) );
309  surface.clear(); // boundary being extracted.
310 
312  SN.init( &K, &surfel_adj, start_surfel );
313  std::queue<SCell> qbels;
314  qbels.push( start_surfel );
315  surface.insert( start_surfel );
316  // For all pending bels
317  while ( ! qbels.empty() )
318  {
319  b = qbels.front();
320  qbels.pop();
321  SN.setSurfel( b );
322  for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
323  {
324  Dimension track_dir = *q;
325  // ----- direct orientation ------
326  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir,
327  K.sDirect( b, track_dir ) ) )
328  {
329  if ( surface.find( bn ) == surface.end() )
330  {
331  surface.insert( bn );
332  qbels.push( bn );
333  }
334  }
335  } // for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
336  } // while ( ! qbels.empty() )
337 }
338 
339 
340 //-----------------------------------------------------------------------------
341 template <typename TKSpace>
342 template <typename PointPredicate>
343 void
345 ( std::vector<SCell> & aSCellContour2D,
346  const KSpace & K,
347  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
348  const PointPredicate & pp,
349  const SCell & start_surfel )
350 {
351  BOOST_CONCEPT_ASSERT(( CPointPredicate<PointPredicate> ));
352  ASSERT( K.dimension == 2 );
353 
354  SCell b= start_surfel; // current surfel
355  SCell bn; // neighboring surfel
356  ASSERT( K.sIsSurfel( start_surfel ) );
357  // std::set<SCell> setSurface;
358  // setSurface.insert(start_surfel);
359  aSCellContour2D.clear(); // boundary being extracted.
360  aSCellContour2D.push_back(start_surfel);
362  SN.init( &K, &surfel_adj, start_surfel );
363  SN.setSurfel( b );
364  // search along indirect orientation.
365  bool hasPrevNeighbor = true;
366  while ( hasPrevNeighbor )
367  {
368  hasPrevNeighbor=false;
369  Dimension track_dir = *(K.sDirs( b ));
370  SN.setSurfel( b );
371  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir,
372  ! K.sDirect( b, track_dir ) ) )
373  {
374  if ( bn != start_surfel )
375  // if ( setSurface.find( bn ) == setSurface.end() )
376  {
377  hasPrevNeighbor=true;
378  aSCellContour2D.push_back( bn );
379  // setSurface.insert(bn);
380  }
381  }
382  b = bn;
383  }
384  // since the contour is not necessary closed we search in the other direction.
385  reverse(aSCellContour2D.begin(), aSCellContour2D.end());
386  if ( b != start_surfel )
387  { // the contour is necessarily open.
388  b = start_surfel;
389  bool hasNextNeighbor = true;
390  while ( hasNextNeighbor )
391  {
392  hasNextNeighbor=false;
393  Dimension track_dir = *(K.sDirs( b ));
394  SN.setSurfel( b );
395  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir,
396  K.sDirect( b, track_dir ) ) )
397  {
398  // if ( setSurface.find( bn ) == setSurface.end() )
399  // {
400  aSCellContour2D.push_back( bn );
401  hasNextNeighbor=true;
402  // setSurface.insert(bn);
403  // }
404  }
405  b=bn;
406  }
407  }
408 }
409 
410 
411 
412 //-----------------------------------------------------------------------------
413 template <typename TKSpace>
414 template <typename PointPredicate>
415 void
417 ( std::vector<SCell> & aSCellContour2D,
418  const KSpace & K,
419  const Dimension & trackDir,
420  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
421  const PointPredicate & pp,
422  const SCell & start_surfel )
423 {
424  BOOST_CONCEPT_ASSERT(( CPointPredicate<PointPredicate> ));
425  SCell b= start_surfel; // current surfel
426  SCell bn; // neighboring surfel
427  ASSERT( K.sIsSurfel( start_surfel ) );
428  // std::set<SCell> setSurface;
429  // setSurface.insert(start_surfel);
430  aSCellContour2D.clear(); // boundary being extracted.
431  aSCellContour2D.push_back(start_surfel);
433  SN.init( &K, &surfel_adj, start_surfel );
434  SN.setSurfel( b );
435  Dimension orthDir = K.sOrthDir( start_surfel );
436  bool hasPrevNeighbor = true;
437  while ( hasPrevNeighbor )
438  {
439  hasPrevNeighbor=false;
440  // search a tracking direction compatible with track/orth direction
441  Dimension track_dir = K.sOrthDir( b ) == orthDir ? trackDir : orthDir;
442  SN.setSurfel( b );
443  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir,
444  !K.sDirect( b, track_dir ) ) )
445  {
446  if ( bn != start_surfel )
447  // if ( setSurface.find( bn ) == setSurface.end() )
448  {
449  hasPrevNeighbor=true;
450  aSCellContour2D.push_back( bn );
451  // setSurface.insert(bn);
452  }
453  }
454  b = bn;
455  }
456  // since the contour is not necessary closed we search in the other direction.
457  reverse(aSCellContour2D.begin(), aSCellContour2D.end());
458  if ( b != start_surfel )
459  { // the contour is necessarily open.
460  b = start_surfel;
461  bool hasNextNeighbor = true;
462  while ( hasNextNeighbor )
463  {
464  hasNextNeighbor=false;
465  // search a tracking direction compatible with constant direction
466  Dimension track_dir = K.sOrthDir( b ) == orthDir ? trackDir : orthDir;
467  SN.setSurfel( b );
468  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir,
469  K.sDirect( b, track_dir ) ) )
470  {
471  // if ( setSurface.find( bn ) == setSurface.end() )
472  // {
473  aSCellContour2D.push_back( bn );
474  // setSurface.insert(bn);
475  hasNextNeighbor=true;
476  // }
477  }
478  b=bn;
479  }
480  }
481 }
482 
483 //-----------------------------------------------------------------------------
484 template <typename TKSpace>
485 template <typename SurfelPredicate >
486 inline
487 void
489 track2DSurface( std::vector<SCell> & aSCellContour,
490  const KSpace & K,
491  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
492  const SurfelPredicate & sp,
493  const SCell & start_surfel )
494 {
495  BOOST_CONCEPT_ASSERT(( CSurfelPredicate<SurfelPredicate> ));
496  ASSERT( KSpace::dimension == 2 );
497 
498  SCell b= start_surfel; // current surfel
499  SCell bn; // neighboring surfel
500  ASSERT( K.sIsSurfel( start_surfel ) );
501  aSCellContour.clear(); // boundary being extracted.
502  aSCellContour.push_back(start_surfel);
504  SN.init( &K, &surfel_adj, start_surfel );
505  SN.setSurfel( b );
506  // search along indirect orientation.
507  bool hasPrevNeighbor = true;
508  while ( hasPrevNeighbor )
509  {
510  hasPrevNeighbor=false;
511  Dimension track_dir = *(K.sDirs( b ));
512  SN.setSurfel( b );
513  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir,
514  ! K.sDirect( b, track_dir ) ) )
515  {
516  if ( bn != start_surfel )
517  {
518  hasPrevNeighbor=true;
519  aSCellContour.push_back( bn );
520  }
521  }
522  b = bn;
523  }
524  // since the contour is not necessary closed we search in the other direction.
525  reverse( aSCellContour.begin(), aSCellContour.end() );
526  if ( b != start_surfel )
527  { // the contour is necessarily open.
528  b = start_surfel;
529  bool hasNextNeighbor = true;
530  while ( hasNextNeighbor )
531  {
532  hasNextNeighbor=false;
533  Dimension track_dir = *(K.sDirs( b ));
534  SN.setSurfel( b );
535  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir,
536  K.sDirect( b, track_dir ) ) )
537  {
538  aSCellContour.push_back( bn );
539  hasNextNeighbor=true;
540  }
541  b=bn;
542  }
543  }
544 }
545 
546 //-----------------------------------------------------------------------------
547 template <typename TKSpace>
548 template <typename SurfelPredicate >
549 inline
550 void
552 track2DSliceSurface( std::vector<SCell> & aSCellContour,
553  const KSpace & K,
554  const Dimension & trackDir,
555  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
556  const SurfelPredicate & sp,
557  const SCell & start_surfel )
558 {
559  BOOST_CONCEPT_ASSERT(( CSurfelPredicate<SurfelPredicate> ));
560  SCell b= start_surfel; // current surfel
561  SCell bn; // neighboring surfel
562  ASSERT( K.sIsSurfel( start_surfel ) );
563  aSCellContour.clear(); // boundary being extracted.
564  aSCellContour.push_back(start_surfel);
566  SN.init( &K, &surfel_adj, start_surfel );
567  SN.setSurfel( b );
568  Dimension orthDir = K.sOrthDir( start_surfel );
569  bool hasPrevNeighbor = true;
570  while ( hasPrevNeighbor )
571  {
572  hasPrevNeighbor=false;
573  // search a tracking direction compatible with track/orth direction
574  Dimension track_dir = K.sOrthDir( b ) == orthDir ? trackDir : orthDir;
575  SN.setSurfel( b );
576  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir,
577  !K.sDirect( b, track_dir ) ) )
578  {
579  if ( bn != start_surfel )
580  {
581  hasPrevNeighbor=true;
582  aSCellContour.push_back( bn );
583  }
584  }
585  b = bn;
586  }
587  // since the contour is not necessary closed we search in the other direction.
588  reverse( aSCellContour.begin(), aSCellContour.end() );
589  if ( b != start_surfel )
590  { // the contour is necessarily open.
591  b = start_surfel;
592  bool hasNextNeighbor = true;
593  while ( hasNextNeighbor )
594  {
595  hasNextNeighbor=false;
596  // search a tracking direction compatible with constant direction
597  Dimension track_dir = K.sOrthDir( b ) == orthDir ? trackDir : orthDir;
598  SN.setSurfel( b );
599  if ( SN.getAdjacentOnSurfelPredicate( bn, sp, track_dir,
600  K.sDirect( b, track_dir ) ) )
601  {
602  aSCellContour.push_back( bn );
603  hasNextNeighbor=true;
604  }
605  b=bn;
606  }
607  }
608 }
609 
610 
611 
612 //-----------------------------------------------------------------------------
613 template <typename TKSpace>
614 template <typename PointPredicate>
615 inline
616 void
618 ( std::vector<Point> & aVectorOfPoints,
619  const KSpace & K,
620  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
621  const PointPredicate & pp,
622  const SCell & start_surfel )
623 {
624  aVectorOfPoints.clear();
625 
626  // Getting the consecutive surfels of the 2D boundary
627  std::vector<SCell> vectBdrySCell;
628  Surfaces<KSpace>::track2DBoundary( vectBdrySCell,
629  K, surfel_adj, pp, start_surfel );
630  typedef typename std::vector<SCell>::const_iterator SCellConstIterator;
631  for ( SCellConstIterator it = vectBdrySCell.begin(),
632  it_end = vectBdrySCell.end();
633  it != it_end; ++it )
634  {
635  Dimension track = *( K.sDirs( *it ) );
636  SCell pointel = K.sIndirectIncident( *it, track );
637  aVectorOfPoints.push_back( K.sCoords( pointel ) );
638  }
639 }
640 
641 
642 
643 
644 //-----------------------------------------------------------------------------
645 template <typename TKSpace>
646 template <typename PointPredicate>
647 void
649 extractAll2DSCellContours( std::vector< std::vector<SCell> > & aVectSCellContour2D,
650  const KSpace & aKSpace,
651  const SurfelAdjacency<KSpace::dimension> & aSurfelAdj,
652  const PointPredicate & pp )
653 {
654  std::set<SCell> bdry;
655  sMakeBoundary( bdry, aKSpace, pp,
656  aKSpace.lowerBound(), aKSpace.upperBound() );
657  aVectSCellContour2D.clear();
658  while( ! bdry.empty() )
659  {
660  std::vector<SCell> aContour;
661  SCell aCell = *(bdry.begin());
662  track2DBoundary( aContour, aKSpace, aSurfelAdj, pp, aCell );
663  aVectSCellContour2D.push_back( aContour );
664  // removing cells from boundary;
665  for( unsigned int i = 0; i < aContour.size(); i++ )
666  {
667  SCell sc = aContour.at(i);
668  bdry.erase(sc);
669  }
670  }
671 }
672 
673 
674 
675 //-----------------------------------------------------------------------------
676 template <typename TKSpace>
677 template <typename PointPredicate>
678 void
679 DGtal::Surfaces<TKSpace>::orientSCellExterior(std::vector<SCell> & aVectOfSCell,
680  const KSpace & aKSpace, const PointPredicate & pp ){
681  for( typename vector<SCell>::iterator it = aVectOfSCell.begin();
682  it!=aVectOfSCell.end(); it++){
683  SCell incidUpperDim = aKSpace.sDirectIncident(*it, aKSpace.sOrthDir(*it));
684  if( pp( aKSpace.sCoords(incidUpperDim) )){
685  aKSpace.sSetSign (*it, !aKSpace.sDirect(*it, aKSpace.sOrthDir(*it)) );
686  }else{
687  aKSpace.sSetSign (*it, aKSpace.sDirect(*it, !aKSpace.sOrthDir(*it)) );
688  }
689  }
690 }
691 
692 
693 
694 
695 //-----------------------------------------------------------------------------
696 template <typename TKSpace>
697 template <typename PointPredicate>
698 void
701 ( std::vector< std::vector<SCell> > & aVectConnectedSCell,
702  const KSpace & aKSpace,
703  const SurfelAdjacency<KSpace::dimension> & aSurfelAdj,
704  const PointPredicate & pp,
705  bool forceOrientCellExterior )
706 {
707  set<SCell> bdry;
708 
709  sMakeBoundary( bdry, aKSpace, pp,
710  aKSpace.lowerBound(), aKSpace.upperBound() );
711  aVectConnectedSCell.clear();
712  while(!bdry.empty()){
713  set<SCell> aConnectedSCellSet;
714  SCell aCell = *(bdry.begin());
715  trackBoundary(aConnectedSCellSet, aKSpace, aSurfelAdj, pp, aCell );
716  //transform into vector<SCell>
717  vector<SCell> vCS;
718  for(typename set<SCell>::iterator it = aConnectedSCellSet.begin(); it!= aConnectedSCellSet.end(); ++it){
719  vCS.push_back(*it);
720  // removing cells from boundary;
721  bdry.erase(*it);
722  }
723  if(forceOrientCellExterior){
724  orientSCellExterior(vCS, aKSpace, pp);
725  }
726  aVectConnectedSCell.push_back(vCS);
727  }
728 }
729 
730 
731 
732 
733 //-----------------------------------------------------------------------------
734 template <typename TKSpace>
735 template <typename PointPredicate>
736 void
738 extractAllPointContours4C( std::vector< std::vector< Point > > & aVectPointContour2D,
739  const KSpace & aKSpace,
740  const PointPredicate & pp,
741  const SurfelAdjacency<2> & aSAdj)
742 {
743  aVectPointContour2D.clear();
744 
745  std::vector< std::vector<SCell> > vectContoursBdrySCell;
746  extractAll2DSCellContours( vectContoursBdrySCell,
747  aKSpace, aSAdj, pp );
748 
749  for(unsigned int i=0; i< vectContoursBdrySCell.size(); i++){
750  std::vector< Point > aContour;
751  for(unsigned int j=0; j< vectContoursBdrySCell.at(i).size(); j++){
752  SCell sc = vectContoursBdrySCell.at(i).at(j);
753  float x = (float)
754  ( NumberTraits<typename TKSpace::Integer>::castToInt64_t( sc.myCoordinates[0] ) >> 1 );
755  float y = (float)
756  ( NumberTraits<typename TKSpace::Integer>::castToInt64_t( sc.myCoordinates[1] ) >> 1 );
757  bool xodd = ( sc.myCoordinates[ 0 ] & 1 );
758  bool yodd = ( sc.myCoordinates[ 1 ] & 1 );
759  double x0 = !xodd ? x - 0.5 : (!aKSpace.sSign(sc)? x - 0.5: x + 0.5) ;
760  double y0 = !yodd ? y - 0.5 : (!aKSpace.sSign(sc)? y - 0.5: y + 0.5);
761  double x1 = !xodd ? x - 0.5 : (aKSpace.sSign(sc)? x - 0.5: x + 0.5) ;
762  double y1 = !yodd ? y - 0.5 : (aKSpace.sSign(sc)? y - 0.5: y + 0.5);
763 
764  Point ptA((const int)(x0+0.5), (const int)(y0-0.5));
765  Point ptB((const int)(x1+0.5), (const int)(y1-0.5)) ;
766  aContour.push_back(ptA);
767  if(sc== vectContoursBdrySCell.at(i).at(vectContoursBdrySCell.at(i).size()-1)){
768  aContour.push_back(ptB);
769  }
770  }
771  aVectPointContour2D.push_back(aContour);
772  }
773 }
774 
775 
776 
777 //-----------------------------------------------------------------------------
778 template <typename TKSpace>
779 template <typename SCellSet, typename PointPredicate >
780 void
782 trackClosedBoundary( SCellSet & surface,
783  const KSpace & K,
784  const SurfelAdjacency<KSpace::dimension> & surfel_adj,
785  const PointPredicate & pp,
786  const SCell & start_surfel )
787 {
788  SCell b; // current surfel
789  SCell bn; // neighboring surfel
790  ASSERT( K.sIsSurfel( start_surfel ) );
791  surface.clear(); // boundary being extracted.
792 
794  SN.init( &K, &surfel_adj, start_surfel );
795  std::queue<SCell> qbels;
796  qbels.push( start_surfel );
797  surface.insert( start_surfel );
798  // For all pending bels
799  while ( ! qbels.empty() )
800  {
801  b = qbels.front();
802  qbels.pop();
803  SN.setSurfel( b );
804  for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
805  {
806  Dimension track_dir = *q;
807  // ----- One pass, look for direct orientation ------
808  if ( SN.getAdjacentOnPointPredicate( bn, pp, track_dir,
809  K.sDirect( b, track_dir ) ) )
810  {
811  if ( surface.find( bn ) == surface.end() )
812  {
813  surface.insert( bn );
814  qbels.push( bn );
815  }
816  }
817  } // for ( DirIterator q = K.sDirs( b ); q != 0; ++q )
818  } // while ( ! qbels.empty() )
819 }
820 
821 //-----------------------------------------------------------------------------
822 template <typename TKSpace>
823 template <typename CellSet, typename PointPredicate >
824 void
826 uMakeBoundary( CellSet & aBoundary,
827  const KSpace & aKSpace,
828  const PointPredicate & pp,
829  const Point & aLowerBound,
830  const Point & aUpperBound )
831 {
832  unsigned int k;
833  bool in_here, in_further;
834  for ( k = 0; k < aKSpace.dimension; ++k )
835  {
836  Cell dir_low_uid = aKSpace.uSpel( aLowerBound );
837  Cell dir_up_uid = aKSpace.uGetDecr( aKSpace.uSpel( aUpperBound ), k);
838  Cell p = dir_low_uid;
839  do
840  {
841  in_here = pp( aKSpace.uCoords(p) );
842  in_further = pp( aKSpace.uCoords(aKSpace.uGetIncr( p, k )) );
843  if ( in_here != in_further ) // boundary element
844  { // add it to the set.
845  aBoundary.insert( aKSpace.uIncident( p, k, true ));
846  }
847  }
848  while ( aKSpace.uNext( p, dir_low_uid, dir_up_uid ) );
849  }
850 }
851 
852 
853 
854 //-----------------------------------------------------------------------------
855 template <typename TKSpace>
856 template <typename SCellSet, typename PointPredicate >
857 void
859 sMakeBoundary( SCellSet & aBoundary,
860  const KSpace & aKSpace,
861  const PointPredicate & pp,
862  const Point & aLowerBound,
863  const Point & aUpperBound )
864 {
865  unsigned int k;
866  bool in_here, in_further;
867 
868  for ( k = 0; k < aKSpace.dimension; ++k )
869  {
870  Cell dir_low_uid = aKSpace.uSpel( aLowerBound );
871  Cell dir_up_uid = aKSpace.uGetDecr( aKSpace.uSpel( aUpperBound ), k);
872  Cell p = dir_low_uid;
873  do
874  {
875  in_here = pp( aKSpace.uCoords(p) );
876  in_further = pp( aKSpace.uCoords(aKSpace.uGetIncr( p, k )) );
877  if ( in_here != in_further ) // boundary element
878  { // add it to the set.
879  aBoundary.insert( aKSpace.sIncident( aKSpace.signs( p, in_here ),
880  k, true ));
881  }
882  }
883  while ( aKSpace.uNext( p, dir_low_uid, dir_up_uid ) );
884  }
885 }
886 
887 
888 //-----------------------------------------------------------------------------
889 template <typename TKSpace>
890 template <typename OutputIterator, typename PointPredicate >
891 void
893 uWriteBoundary( OutputIterator & out_it,
894  const KSpace & aKSpace,
895  const PointPredicate & pp,
896  const Point & aLowerBound, const Point & aUpperBound )
897 {
898  unsigned int k;
899  bool in_here, in_further;
900  for ( k = 0; k < aKSpace.dimension; ++k )
901  {
902  Cell dir_low_uid = aKSpace.uSpel( aLowerBound );
903  Cell dir_up_uid = aKSpace.uGetDecr( aKSpace.uSpel( aUpperBound ), k);
904  Cell p = dir_low_uid;
905  do
906  {
907  in_here = pp( aKSpace.uCoords(p) );
908  in_further = pp( aKSpace.uCoords(aKSpace.uGetIncr( p, k )) );
909  if ( in_here != in_further ) // boundary element
910  { // writes it into the output iterator.
911  *out_it++ = aKSpace.uIncident( p, k, true );
912  }
913  }
914  while ( aKSpace.uNext( p, dir_low_uid, dir_up_uid ) );
915  }
916 }
917 
918 
919 
920 //-----------------------------------------------------------------------------
921 template <typename TKSpace>
922 template <typename OutputIterator, typename PointPredicate >
923 void
925 sWriteBoundary( OutputIterator & out_it,
926  const KSpace & aKSpace,
927  const PointPredicate & pp,
928  const Point & aLowerBound, const Point & aUpperBound )
929 {
930  Dimension k;
931  // bool in_here, in_further;
932  bool in_here, in_before;
933 
934  typedef typename KSpace::Space Space;
935  typedef HyperRectDomain<Space> Domain;
936  std::vector< Dimension > axes( aKSpace.dimension );
937  for ( k = 0; k < aKSpace.dimension; ++k )
938  axes[ k ] = k;
939  // We look for surfels in every direction.
940  for ( k = 0; k < aKSpace.dimension; ++k )
941  {
942  // When looking for surfels, the visiting must follow the k-th
943  // axis first so as to reuse the predicate "pp( p )".
944  std::swap( axes[ 0 ], axes[ k ] );
945  Point low = aLowerBound; ++low[ k ];
946  Point up = aUpperBound;
947  Domain domain( low, up );
948  Integer x = low[ k ];
949  typename Domain::ConstSubRange range = domain.subRange( axes );
950  for ( typename Domain::ConstSubRange::ConstIterator
951  it = range.begin(), it_end = range.end();
952  it != it_end; ++it )
953  {
954  const Point & p = *it;
955  if ( p[ k ] == x)
956  {
957  in_here = pp( p );
958  Point p2( p ); --p2[ k ];
959  in_before = pp( p2 );
960  }
961  else
962  {
963  in_before = in_here;
964  in_here = pp( p );
965  }
966  if ( in_here != in_before ) // boundary element
967  { // writes it into the output iterator.
968  *out_it++ = aKSpace.sIncident( aKSpace.sSpel( p, in_here ),
969  k, false );
970  }
971  }
972  }
973  // for ( k = 0; k < aKSpace.dimension; ++k )
974  // {
975  // Cell dir_low_uid = aKSpace.uSpel( aLowerBound );
976  // Cell dir_up_uid = aKSpace.uGetDecr( aKSpace.uSpel( aUpperBound ), k);
977  // Cell p = dir_low_uid;
978  // do
979  // {
980  // in_here = pp( aKSpace.uCoords(p) );
981  // in_further = pp( aKSpace.uCoords(aKSpace.uGetIncr( p, k )) );
982  // if ( in_here != in_further ) // boundary element
983  // { // writes it into the output iterator.
984  // *out_it++ = aKSpace.sIncident( aKSpace.signs( p, in_here ),
985  // k, true );
986  // }
987  // }
988  // while ( aKSpace.uNext( p, dir_low_uid, dir_up_uid ) );
989  // }
990 }
991 
992 
993 
994 
996 // Interface - public :
997 
1002 template <typename TKSpace>
1003 inline
1004 void
1005 DGtal::Surfaces<TKSpace>::selfDisplay ( std::ostream & out ) const
1006 {
1007  out << "[Surfaces]";
1008 }
1009 
1014 template <typename TKSpace>
1015 inline
1016 bool
1018 {
1019  return true;
1020 }
1021 
1022 
1023 
1025 // Implementation of inline functions //
1026 
1027 template <typename TKSpace>
1028 inline
1029 std::ostream&
1030 DGtal::operator<< ( std::ostream & out,
1031  const Surfaces<TKSpace> & object )
1032 {
1033  object.selfDisplay( out );
1034  return out;
1035 }
1036 
1037 // //
1039 
1040