DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Object.ih
1 
30 
31 #include <cstdlib>
32 #include "DGtal/kernel/sets/DigitalSetDomain.h"
33 #include "DGtal/topology/DigitalTopology.h"
34 #include "DGtal/topology/MetricAdjacency.h"
35 #include "DGtal/topology/BreadthFirstVisitor.h"
37 
39 // IMPLEMENTATION of inline methods.
41 #include "DGtal/topology/Object.h"
42 
44 // ----------------------- Standard services ------------------------------
45 
55 template <typename TDigitalTopology, typename TDigitalSet>
56 inline
58  : myTopo( 0 ), myPointSet( 0 ), myConnectedness( UNKNOWN )
59 {
60 }
61 
71 template <typename TDigitalTopology, typename TDigitalSet>
72 inline
74 ( const DigitalTopology & aTopology,
75  const DigitalSet & aPointSet,
76  Connectedness cxn )
77  : myTopo( new DigitalTopology( aTopology ) ),
78  myPointSet( new DigitalSet( aPointSet ) ),
79  myConnectedness( cxn )
80 {
81 }
82 
92 template <typename TDigitalTopology, typename TDigitalSet>
93 inline
95 ( const CowPtr<DigitalTopology> & aTopology,
96  const DigitalSet & aPointSet,
97  Connectedness cxn )
98  : myTopo( aTopology ),
99  myPointSet( new DigitalSet( aPointSet ) ),
100  myConnectedness( cxn )
101 {
102 }
103 
113 template <typename TDigitalTopology, typename TDigitalSet>
114 inline
116 ( const TDigitalTopology & aTopology,
117  const CowPtr<DigitalSet> & aPointSet,
118  Connectedness cxn )
119  : myTopo( new DigitalTopology( aTopology ) ),
120  myPointSet( aPointSet ),
121  myConnectedness( cxn )
122 {
123 }
124 
135 template <typename TDigitalTopology, typename TDigitalSet>
136 inline
138 ( const TDigitalTopology & aTopology,
139  DigitalSet* aPointSetPtr,
140  Connectedness cxn )
141  : myTopo( new DigitalTopology( aTopology ) ),
142  myPointSet( pointSet ),
143  myConnectedness( cxn )
144 {
145 }
146 
154 template <typename TDigitalTopology, typename TDigitalSet>
155 inline
157 ( const Object & other )
158  : myTopo( other.myTopo ),
159  myPointSet( other.myPointSet ),
160  myConnectedness( other.myConnectedness )
161 {
162 }
163 
172 template <typename TDigitalTopology, typename TDigitalSet>
173 inline
175 ( const TDigitalTopology & aTopology,
176  const Domain & aDomain )
177  : myTopo( new DigitalTopology( aTopology ) ),
178  myPointSet( new DigitalSet( aDomain ) ),
179  myConnectedness( CONNECTED )
180 {
181 }
182 
190 template <typename TDigitalTopology, typename TDigitalSet>
191 inline
193 ( const CowPtr<DigitalTopology> & aTopology,
194  const Domain & aDomain )
195  : myTopo( aTopology ),
196  myPointSet( new DigitalSet( aDomain ) ),
197  myConnectedness( CONNECTED )
198 {
199 }
200 
204 template <typename TDigitalTopology, typename TDigitalSet>
205 inline
207 {
208 }
209 
215 template <typename TDigitalTopology, typename TDigitalSet>
216 inline
219 ( const Object & other )
220 {
221  if ( this != &other )
222  {
223  myTopo = other.myTopo;
224  myPointSet = other.myPointSet;
225  myConnectedness = other.myConnectedness;
226  }
227  return *this;
228 }
229 
233 template <typename TDigitalTopology, typename TDigitalSet>
234 inline
237 {
238  return myPointSet->size();
239 }
240 
244 template <typename TDigitalTopology, typename TDigitalSet>
245 inline
248 {
249  return myPointSet->domain();
250 }
251 
252 
257 template <typename TDigitalTopology, typename TDigitalSet>
258 inline
259 const TDigitalSet &
261 {
262  return *myPointSet;
263 }
264 
269 template <typename TDigitalTopology, typename TDigitalSet>
270 inline
271 TDigitalSet &
273 {
274  myConnectedness = UNKNOWN;
275  return *myPointSet;
276 }
277 
281 template <typename TDigitalTopology, typename TDigitalSet>
282 inline
283 const TDigitalTopology &
285 {
286  return *myTopo;
287 }
288 
292 template <typename TDigitalTopology, typename TDigitalSet>
293 inline
294 const typename TDigitalTopology::ForegroundAdjacency &
296 {
297  return myTopo->kappa();
298 }
299 
300 
302 // ----------------------- Object services --------------------------------
303 
313 template <typename TDigitalTopology, typename TDigitalSet>
314 inline
317 ( const Point & p ) const
318 {
319  typedef std::vector<Vertex> Container;
320  typedef typename Container::const_iterator ContainerConstIterator;
321  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
322 
323  // Intermediate container that is fast writable.
324  Container tmp_local_points;
325  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
326  adjacency().writeNeighbors( back_ins_it, p );
327  tmp_local_points.push_back( p );
328 
329  // A neighborhood is small, so is defined the digital object.
330  SmallObject neighA( myTopo, pointSet().domain() );
331  const ContainerConstIterator it_end( tmp_local_points.end() );
332  const DigitalSetConstIterator not_found( pointSet().end() );
333  SmallSet & neighASet = neighA.pointSet();
334  for ( ContainerConstIterator it = tmp_local_points.begin();
335  it != it_end;
336  ++it )
337  if ( pointSet().find( *it ) != not_found )
338  neighASet.insertNew( *it ); // insertNew is guaranteed by construction.
339  return neighA;
340 }
341 
352 template <typename TDigitalTopology, typename TDigitalSet>
353 inline
356 ::neighborhoodSize( const Point & p ) const
357 {
358  typedef std::vector<Vertex> Container;
359  typedef typename Container::const_iterator ContainerConstIterator;
360  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
361 
362  // Intermediate container that is fast writable.
363  Container tmp_local_points;
364  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
365  adjacency().writeNeighbors( back_ins_it, p );
366  tmp_local_points.push_back( p );
367 
368  // A neighborhood is small, so is defined the digital object.
369  const ContainerConstIterator it_end( tmp_local_points.end() );
370  const DigitalSetConstIterator not_found( pointSet().end() );
371  Size nb = 0;
372  for ( ContainerConstIterator it = tmp_local_points.begin();
373  it != it_end;
374  ++it )
375  if ( pointSet().find( *it ) != not_found )
376  ++nb;
377  return nb;
378 }
379 
380 
391 template <typename TDigitalTopology, typename TDigitalSet>
392 inline
395 ( const Point & p ) const
396 {
397  typedef std::vector<Vertex> Container;
398  typedef typename Container::const_iterator ContainerConstIterator;
399  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
400 
401  // Intermediate container that is fast writable.
402  Container tmp_local_points;
403  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
404  adjacency().writeNeighbors( back_ins_it, p );
405 
406  // A neighborhood is small, so is defined the digital object.
407  SmallObject neighA( myTopo, pointSet().domain() );
408  const ContainerConstIterator it_end( tmp_local_points.end() );
409  const DigitalSetConstIterator not_found( pointSet().end() );
410  SmallSet & neighASet = neighA.pointSet();
411  for ( ContainerConstIterator it = tmp_local_points.begin();
412  it != it_end;
413  ++it )
414  if ( pointSet().find( *it ) != not_found )
415  neighASet.insertNew( *it ); // insertNew is guaranteed by construction.
416  return neighA;
417 }
418 
430 template <typename TDigitalTopology, typename TDigitalSet>
431 inline
434 ::properNeighborhoodSize( const Point & p ) const
435 {
436  typedef std::vector<Vertex> Container;
437  typedef typename Container::const_iterator ContainerConstIterator;
438  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
439 
440  // Intermediate container that is fast writable.
441  Container tmp_local_points;
442 
443  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
444  adjacency().writeNeighbors( back_ins_it, p );
445 
446  // A neighborhood is small, so is defined the digital object.
447  const ContainerConstIterator it_end( tmp_local_points.end() );
448  const DigitalSetConstIterator not_found( pointSet().end() );
449  Size nb = 0;
450  for ( ContainerConstIterator it = tmp_local_points.begin();
451  it != it_end;
452  ++it )
453  if ( pointSet().find( *it ) != not_found )
454  ++nb;
455  return nb;
456 }
457 
458 
459 
464 template <typename TDigitalTopology, typename TDigitalSet>
465 inline
468 {
469  typedef std::vector<Vertex> Container;
470  typedef typename Container::const_iterator ContainerConstIterator;
471  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
472  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
473  //typedef typename Domain::Predicate Predicate;
474 
475  // Intermediate container that is fast writable.
476  const DigitalSet & mySet = pointSet();
477  Object<DigitalTopology, DigitalSet> output( topology(),
478  domain() );
479  DigitalSet & outputSet = output.pointSet();
480 
481  // Loop on all points of the set.
482  Container tmp_local_points;
483  const DigitalSetConstIterator it_end = mySet.end();
484  for ( DigitalSetConstIterator it = mySet.begin();
485  it != it_end;
486  ++it )
487  {
488  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
489  // Computing neighborhood within domain.
490  topology().lambda().writeNeighbors
491  ( back_ins_it, *it, domain().predicate() );
492  // Checks if any point is not in the object.
493  const ContainerConstIterator itc_end( tmp_local_points.end() );
494  for ( ContainerConstIterator itc = tmp_local_points.begin();
495  itc != itc_end;
496  ++itc )
497  if ( pointSet().find( *itc ) == it_end )
498  {
499  outputSet.insertNew( *it );
500  break;
501  }
502  tmp_local_points.clear();
503  }
504  return output;
505 }
506 
516 template <typename TDigitalTopology, typename TDigitalSet>
517 template <typename OutputObjectIterator>
518 inline
521 ::writeComponents( OutputObjectIterator & it ) const
522 {
523  Size nb_components = 0;
524  if ( pointSet().empty() )
525  {
526  myConnectedness = CONNECTED;
527  return nb_components;
528  }
529  else
530  if ( connectedness() == CONNECTED )
531  {
532  *it++ = *this;
533  return 1;
534  }
535  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
536  DigitalSetConstIterator it_object = pointSet().begin();
537  Point p( *it_object++ );
538 
539  // first component.
540  BreadthFirstVisitor< Object, std::set<Vertex> > visitor( *this, p );
541  while ( ! visitor.finished() ) visitor.expand();
542  DigitalSet visited( domain() );
543  visited.insertNew( visitor.markedVertices().begin(),
544  visitor.markedVertices().end() );
545  *it++ = Object( myTopo, visited, CONNECTED );
546  ++nb_components;
547  while ( it_object != pointSet().end() )
548  {
549  p = *it_object++;
550  if ( visited.find( p ) == visited.end() )
551  {
552  BreadthFirstVisitor< Object, std::set<Vertex> > visitor2( *this, p );
553  while ( ! visitor2.finished() ) visitor2.expand();
554  DigitalSet visited2( domain() );
555  visited2.insertNew( visitor2.markedVertices().begin(),
556  visitor2.markedVertices().end() );
557  *it++ = Object( myTopo, visited2, CONNECTED );
558  ++nb_components;
559  visited += visited2;
560  }
561  }
562  // Expander<Object> expander( *this, p );
563  // while ( expander.nextLayer() )
564  // ;
565  // Object component( myTopo, expander.core(), CONNECTED );
566  // *it++ = component;
567  // ++nb_components;
568  // DigitalSet visited( expander.core() );
569  // while ( it_object != pointSet().end() )
570  // {
571  // p = *it_object++;
572  // if ( visited.find( p ) == visited.end() )
573  // {
574  // Expander<Object> expander2( *this, p );
575  // while ( expander2.nextLayer() )
576  // ;
577  // Object component2( myTopo, expander2.core(), CONNECTED );
578  // *it++ = component2;
579  // ++nb_components;
580  // visited += expander2.core();
581  // }
582  // }
583  myConnectedness = nb_components == 1 ? CONNECTED : DISCONNECTED;
584  return nb_components;
585 }
586 
593 template <typename TDigitalTopology, typename TDigitalSet>
596 {
597  return myConnectedness;
598 }
599 
610 template <typename TDigitalTopology, typename TDigitalSet>
613 {
614  if ( myConnectedness == UNKNOWN )
615  {
616  if ( pointSet().empty() )
617  myConnectedness = CONNECTED;
618  else
619  {
620  // Take first point
621  Vertex p = *( pointSet().begin() );
622  BreadthFirstVisitor< Object, std::set<Vertex> > visitor( *this, p );
623  while ( ! visitor.finished() )
624  {
625  visitor.expand();
626  }
627  myConnectedness = ( visitor.visitedVertices().size() == pointSet().size() )
629  // JOL: 2012/11/16 There is apparently now a bug in expander !
630  // Very weird considering this was working in 2012/05. Perhaps
631  // this is related to some manipulations in predicates.
632  //
633  // Expander<Object> expander( *this, p );
634  // // and expand.
635  // while ( expander.nextLayer() )
636  // ;
637  // myConnectedness = ( expander.core().size() == pointSet().size() )
638  // ? CONNECTED : DISCONNECTED;
639  }
640  }
641  return myConnectedness;
642 }
643 
645 // ----------------------- Graph services ------------------------------
646 
647 template <typename TDigitalTopology, typename TDigitalSet>
648 inline
651 {
652  return myPointSet->begin();
653 }
654 
655 template <typename TDigitalTopology, typename TDigitalSet>
656 inline
659 {
660  return myPointSet->end();
661 }
662 
668 template <typename TDigitalTopology, typename TDigitalSet>
669 inline
672 ( const Vertex & v ) const
673 {
674  return neighborhoodSize( v );
675 }
676 
680 template <typename TDigitalTopology, typename TDigitalSet>
681 inline
684 {
685  return myTopo->kappa().bestCapacity();
686 }
687 
699 template <typename TDigitalTopology, typename TDigitalSet>
700 template <typename OutputIterator>
701 inline
702 void
704 writeNeighbors( OutputIterator & it,
705  const Vertex & v ) const
706 {
707  typedef std::vector<Vertex> Container;
708  typedef typename Container::const_iterator ContainerConstIterator;
709  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
710 
711  // Intermediate container that is fast writable.
712  Container tmp_local_points;
713  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
714  adjacency().writeNeighbors( back_ins_it, v );
715 
716  // A neighborhood is small, so is defined the digital object.
717  const ContainerConstIterator it_end( tmp_local_points.end() );
718  const DigitalSetConstIterator not_found( pointSet().end() );
719  for ( ContainerConstIterator cit = tmp_local_points.begin();
720  cit != it_end;
721  ++cit )
722  if ( pointSet().find( *cit ) != not_found )
723  *it++ = *cit;
724 }
725 
742 template <typename TDigitalTopology, typename TDigitalSet>
743 template <typename OutputIterator, typename VertexPredicate>
744 inline
745 void
747 writeNeighbors( OutputIterator & it,
748  const Vertex & v,
749  const VertexPredicate & pred ) const
750 {
751  typedef std::vector<Vertex> Container;
752  typedef typename Container::const_iterator ContainerConstIterator;
753  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
754 
755  // Intermediate container that is fast writable.
756  Container tmp_local_points;
757  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
758  adjacency().writeNeighbors( back_ins_it, v );
759 
760  // A neighborhood is small, so is defined the digital object.
761  const ContainerConstIterator it_end( tmp_local_points.end() );
762  const DigitalSetConstIterator not_found( pointSet().end() );
763  for ( ContainerConstIterator cit = tmp_local_points.begin();
764  cit != it_end;
765  ++cit )
766  if ( ( pointSet().find( *cit ) != not_found ) && pred(*cit) )
767  *it++ = *cit;
768 }
770 // ----------------------- Simple points -------------------------------
771 
776 template <typename TDigitalTopology, typename TDigitalSet>
777 template <typename TAdjacency>
778 inline
782 ( const TAdjacency & adj, const Point & p, unsigned int k ) const
783 {
784  // Local types.
785  typedef std::vector<Vertex> Container;
786  typedef MetricAdjacency<Space, Space::dimension> AlphaAdjacency;
787  typedef MetricAdjacency<Space, 1> OmegaAdjacency;
789  typedef typename Container::const_iterator ContainerConstIterator;
790  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
791  typedef Object<LocalTopology, SmallSet> LocalObject;
792  typedef HyperRectDomain<Space> LocalDomain;
793 
794  DigitalSetDomain<DigitalSet> limitedX( *myPointSet );
795  AlphaAdjacency alpha;
796  OmegaAdjacency omega;
797  // Intermediate container that is fast writable.
798  Container tmp_local_points;
799  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
800  alpha.writeNeighbors( back_ins_it, p, limitedX.predicate() );
801 
802  // Construct local domain.
803  Point p1( p );
804  for ( typename Point::Iterator it = p1.begin(); it != p1.end(); ++it )
805  --(*it);
806  Point p2( p );
807  for ( typename Point::Iterator it = p2.begin(); it != p2.end(); ++it )
808  ++(*it);
809  LocalDomain aDomain( p1, p2 );
810 
811  // Construct local X.
812  LocalTopology aTopology( adj, omega );
813  LocalObject X( aTopology, aDomain );
814  X.pointSet().insertNew( tmp_local_points.begin(), tmp_local_points.end() );
815 
816  // A neighborhood is small, so is defined the digital object.
817  typename LocalObject::SmallObject neighAdj = X.properNeighborhood( p );
818 
820  ( X, neighAdj.pointSet().begin(),
821  neighAdj.pointSet().end() );
822  while ( ! visitor.finished() )
823  visitor.expand();
824  SmallObject geodesicN( this->topology(), aDomain );
825  geodesicN.pointSet().insertNew( visitor.markedVertices().begin(),
826  visitor.markedVertices().end() );
827 
828  // JOL: 2012/11/16 There is apparently now a bug in expander !
829  // Very weird considering this was working in 2012/05. Perhaps
830  // this is related to some manipulations in predicates.
831  // Expander<LocalObject> expander( X,
832  // neighAdj.pointSet().begin(),
833  // neighAdj.pointSet().end() );
834  // for ( unsigned int i = 1; ( i < k ) && ( ! expander.finished() ); ++i )
835  // expander.nextLayer();
836  // SmallObject geodesicN( this->topology(), expander.core() );
837  return geodesicN;
838 
839 }
840 
845 template <typename TDigitalTopology, typename TDigitalSet>
846 template <typename TAdjacency>
847 inline
851 ( const TAdjacency & adj, const Point & p, unsigned int k ) const
852 {
853  // Local types.
854  typedef std::vector<Vertex> Container;
855  typedef MetricAdjacency<Space, Space::dimension> AlphaAdjacency;
856  typedef MetricAdjacency<Space, 1> OmegaAdjacency;
858  typedef typename Container::const_iterator ContainerConstIterator;
859  typedef typename DigitalSet::ConstIterator DigitalSetConstIterator;
860  typedef Object<LocalTopology, SmallSet> LocalObject;
861  typedef HyperRectDomain<Space> LocalDomain;
862  typedef typename DigitalSetDomain<DigitalSet>::Predicate PredicateIsInX;
863  DigitalSetDomain<DigitalSet> limitedX( *myPointSet );
864  AlphaAdjacency alpha;
865  OmegaAdjacency omega;
866  // Intermediate container that is fast writable.
867  Container tmp_local_points;
868  std::back_insert_iterator< Container > back_ins_it( tmp_local_points );
869  NotPointPredicate<PredicateIsInX> not_pred_is_in_X( limitedX.predicate() );
870  alpha.writeNeighbors( back_ins_it, p, not_pred_is_in_X );
871 
872  // Construct local domain.
873  Point p1( p );
874  for ( typename Point::Iterator it = p1.begin(); it != p1.end(); ++it )
875  --(*it);
876  Point p2( p );
877  for ( typename Point::Iterator it = p2.begin(); it != p2.end(); ++it )
878  ++(*it);
879  LocalDomain aDomain( p1, p2 );
880 
881  // Construct local Xcomp.
882  LocalTopology aTopology( adj, omega );
883  LocalObject Xcomp( aTopology, aDomain );
884  Xcomp.pointSet().insertNew( tmp_local_points.begin(), tmp_local_points.end() );
885 
886  // A neighborhood is small, so is defined the digital object.
887  typename LocalObject::SmallObject neighAdj = Xcomp.properNeighborhood( p );
888 
890  ( Xcomp, neighAdj.pointSet().begin(),
891  neighAdj.pointSet().end() );
892  while ( ! visitor.finished() )
893  visitor.expand();
894  SmallComplementObject geodesicN( this->topology().reverseTopology(),
895  aDomain );
896  geodesicN.pointSet().insertNew( visitor.markedVertices().begin(),
897  visitor.markedVertices().end() );
898 
899  // JOL: 2012/11/16 There is apparently now a bug in expander !
900  // Very weird considering this was working in 2012/05. Perhaps
901  // this is related to some manipulations in predicates.
902  // Expander<LocalObject> expander( Xcomp,
903  // neighAdj.pointSet().begin(),
904  // neighAdj.pointSet().end() );
905  // for ( unsigned int i = 1; ( i < k ) && ( ! expander.finished() ); ++i )
906  // expander.nextLayer();
907  // SmallComplementObject geodesicN( this->topology().reverseTopology(),
908  // expander.core() );
909  return geodesicN;
910 }
911 
923 template <typename TDigitalTopology, typename TDigitalSet>
924 inline
925 bool
927 ::isSimple( const Point & v ) const
928 {
929  SmallObject Gkappa_X
930  = geodesicNeighborhood( topology().kappa(),
931  v, Space::dimension );
932  if ( Gkappa_X.computeConnectedness() == CONNECTED )
933  {
934  if ( Gkappa_X.pointSet().empty() )
935  return false;
936  SmallComplementObject Glambda_compX
937  = geodesicNeighborhoodInComplement( topology().lambda(),
938  v, Space::dimension );
939  return ( Glambda_compX.computeConnectedness()
940  == CONNECTED )
941  && ( ! Glambda_compX.pointSet().empty() );
942  }
943  return false;
944 }
945 
946 
948 // Interface - public :
949 
954 template <typename TDigitalTopology, typename TDigitalSet>
955 inline
956 void
958 ::selfDisplay ( std::ostream & out ) const
959 {
960  out << "[Object"
961  << " topology=" << myTopo
962  << " counts=" << myPointSet.count()
963  << " set=" << *myPointSet
964  << " cxn=" << myConnectedness
965  << "]";
966 }
967 
972 template <typename TDigitalTopology, typename TDigitalSet>
973 inline
974 bool
976 {
977  return ( *myPointSet != 0 ) && (*myTopo != 0 );
978 }
979 
989 template <typename TDigitalTopology, typename TDigitalSet>
990 inline
991 std::string
993 {
994  return "Object";
995 }
996 
997 
998 
1000 // Implementation of inline functions //
1001 
1002 template <typename TDigitalTopology, typename TDigitalSet>
1003 inline
1004 std::ostream&
1005 DGtal::operator<< ( std::ostream & out,
1006  const Object<TDigitalTopology, TDigitalSet> & object )
1007 {
1008  object.selfDisplay( out );
1009  return out;
1010 }
1011 
1012 // //
1014 
1015