From dc0687dc26587870e3b805ce653d9dc4c758fe18 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 11 Feb 2015 17:24:08 +0100 Subject: [PATCH 1/2] Use iterator_adaptor instead derivation from transform_iterator With transform iterator we would have to rewrite operator++ as it does not return the derived class. This led to a compilation bug when using connected_components. --- .../BGL_surface_mesh/connected_components.cpp | 30 ++ BGL/examples/BGL_surface_mesh/data/prim.off | 7 +- BGL/include/CGAL/boost/graph/iterator.h | 262 ++++++++++++------ BGL/test/BGL/test_circulator.cpp | 23 +- 4 files changed, 240 insertions(+), 82 deletions(-) create mode 100644 BGL/examples/BGL_surface_mesh/connected_components.cpp diff --git a/BGL/examples/BGL_surface_mesh/connected_components.cpp b/BGL/examples/BGL_surface_mesh/connected_components.cpp new file mode 100644 index 00000000000..2f0084b8262 --- /dev/null +++ b/BGL/examples/BGL_surface_mesh/connected_components.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#include +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point; +typedef CGAL::Surface_mesh Mesh; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + +int main(int argc, char* argv[]) +{ + Mesh sm; + std::ifstream in((argc>1)?argv[1]:"data/prim.off"); + in >> sm; + + Mesh::Property_map ccmap; + ccmap = sm.add_property_map("v:CC").first; + int num = connected_components(sm, ccmap); + + BOOST_FOREACH(vertex_descriptor v, vertices(sm)){ + std::cout << v << " is in component " << ccmap[v] << "\n"; + } + + return 0; +} diff --git a/BGL/examples/BGL_surface_mesh/data/prim.off b/BGL/examples/BGL_surface_mesh/data/prim.off index 7476f26cc46..da9ee71038c 100644 --- a/BGL/examples/BGL_surface_mesh/data/prim.off +++ b/BGL/examples/BGL_surface_mesh/data/prim.off @@ -1,5 +1,5 @@ OFF -8 7 0 +11 7 0 # vertices -1 -1 1 -1 1 1 @@ -9,6 +9,10 @@ OFF -1 1 -1 1 1 -1 1 -1 -1 + 2 2 2 + 3 2 2 + 3 3 3 + # facets 3 3 2 1 3 3 1 0 @@ -17,3 +21,4 @@ OFF 4 3 7 6 2 4 4 7 3 0 4 4 5 6 7 + 3 8 9 10 diff --git a/BGL/include/CGAL/boost/graph/iterator.h b/BGL/include/CGAL/boost/graph/iterator.h index 2fe16ebf751..c1cd3a46279 100644 --- a/BGL/include/CGAL/boost/graph/iterator.h +++ b/BGL/include/CGAL/boost/graph/iterator.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include @@ -477,11 +477,18 @@ class Halfedge_around_target_circulator; template class Halfedge_around_source_circulator #ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_target_circulator > + : public boost::iterator_adaptor< + Halfedge_around_source_circulator // Derived + , Halfedge_around_target_circulator // Base + , typename boost::graph_traits::halfedge_descriptor // Value + , Bidirectional_circulator_tag // CategoryOrTraversal + , typename boost::graph_traits::halfedge_descriptor // Reference + > #endif { +private: + internal::OppositeHalfedge opp; #ifndef DOXYGEN_RUNNING - typedef boost::transform_iterator, Halfedge_around_target_circulator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; #endif @@ -489,7 +496,6 @@ class Halfedge_around_source_circulator public: #ifndef DOXYGEN_RUNNING - typedef Bidirectional_circulator_tag iterator_category; typedef std::size_t size_type; #endif @@ -497,12 +503,32 @@ public: {} Halfedge_around_source_circulator(halfedge_descriptor hd, const Graph& g) - : Base(Halfedge_around_target_circulator(hd,g), internal::OppositeHalfedge(g)) + : Halfedge_around_source_circulator::iterator_adaptor_(Halfedge_around_target_circulator(hd,g)), opp(g) {} Halfedge_around_source_circulator(vertex_descriptor vd, const Graph& g) - : Base(Halfedge_around_target_circulator(halfedge(vd,g),g), internal::OppositeHalfedge(g)) + : Halfedge_around_source_circulator::iterator_adaptor_(Halfedge_around_target_circulator(halfedge(vd,g),g)), opp(g) {} + // design patter: "safe bool" + // will be replaced by explicit operator bool with C++11 + typedef void (Halfedge_around_source_circulator::*bool_type)() const; + + void this_type_does_not_support_comparisons() const {} + + operator bool_type() const + { + return (! (this->base_reference() == NULL)) ? + &Halfedge_around_source_circulator::this_type_does_not_support_comparisons : 0; + } + + bool operator== (void*) const + { + return this->base_reference() == NULL; + } + +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::halfedge_descriptor dereference() const { return opp(*this->base_reference()); } }; @@ -518,11 +544,17 @@ public: template class Face_around_target_circulator #ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_target_circulator > + : public boost::iterator_adaptor< + Face_around_target_circulator // Derived + , Halfedge_around_target_circulator // Base + , typename boost::graph_traits::face_descriptor // Value + , Bidirectional_circulator_tag // CategoryOrTraversal + , typename boost::graph_traits::face_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_target_circulator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + internal::Face fct; public: @@ -530,10 +562,9 @@ public: {} Face_around_target_circulator(halfedge_descriptor hd, const Graph& g) - : Base(Halfedge_around_target_circulator(hd,g), internal::Face(g)) + : Face_around_target_circulator::iterator_adaptor_(Halfedge_around_target_circulator(hd,g)), fct(g) {} #ifndef DOXYGEN_RUNNING - typedef Bidirectional_circulator_tag iterator_category; typedef std::size_t size_type; // design patter: "safe bool" @@ -544,14 +575,19 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &Face_around_target_circulator::this_type_does_not_support_comparisons : 0; } bool operator== (void*) const { - return this->base() == NULL; + return this->base_reference() == NULL; } + + +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::face_descriptor dereference() const { return fct(*this->base_reference()); } #endif }; @@ -711,7 +747,7 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (g == NULL)) ? &Halfedge_around_face_circulator::this_type_does_not_support_comparisons : 0; } @@ -819,23 +855,28 @@ halfedges_around_face(typename boost::graph_traits::halfedge_descriptor h template class Face_around_face_iterator #ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_face_iterator > + : public boost::iterator_adaptor< + Face_around_face_iterator // Derived + , Halfedge_around_face_iterator // Base + , typename boost::graph_traits::face_descriptor // Value + , std::bidirectional_iterator_tag // CategoryOrTraversal + , typename boost::graph_traits::face_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_face_iterator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - + internal::Face fct; public: -#ifndef DOXYGEN_RUNNING - typedef std::bidirectional_iterator_tag iterator_category; -#endif Face_around_face_iterator() {} Face_around_face_iterator(halfedge_descriptor h, const Graph& g, int n = 0) - : Base(Halfedge_around_face_iterator(h,g,(h==halfedge_descriptor())?1:n), internal::Face(g)) + : Face_around_face_iterator::iterator_adaptor_(Halfedge_around_face_iterator(h,g,(h==halfedge_descriptor())?1:n)), fct(g) {} +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::face_descriptor dereference() const { return fct(*this->base_reference()); } }; @@ -859,24 +900,32 @@ class Face_around_face_circulator template class Face_around_target_iterator -#ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_target_iterator > +#ifndef DOXYGEN_RUNNING + : public boost::iterator_adaptor< + Face_around_target_iterator // Derived + , Halfedge_around_target_iterator // Base + , typename boost::graph_traits::face_descriptor // Value + , std::bidirectional_iterator_tag // CategoryOrTraversal + , typename boost::graph_traits::face_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_target_iterator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + internal::Face fct; + public: -#ifndef DOXYGEN_RUNNING - typedef std::bidirectional_iterator_tag iterator_category; -#endif Face_around_target_iterator() {} Face_around_target_iterator(halfedge_descriptor h, const Graph& g, int n = 0) - : Base(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n), internal::Face(g)) + : Face_around_target_iterator::iterator_adaptor_(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n)), fct(g) {} + +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::face_descriptor dereference() const { return fct(*this->base_reference()); } }; /** @@ -905,16 +954,21 @@ faces_around_face(typename boost::graph_traits::halfedge_descriptor h, co template class Vertex_around_face_circulator -#ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_face_circulator > +#ifndef DOXYGEN_RUNNING + : public boost::iterator_adaptor< + Vertex_around_face_circulator // Derived + , Halfedge_around_face_circulator // Base + , typename boost::graph_traits::vertex_descriptor // Value + , Bidirectional_circulator_tag // CategoryOrTraversal + , typename boost::graph_traits::vertex_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_face_circulator > Base; + internal::Target fct; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; public: #ifndef DOXYGEN_RUNNING - typedef Bidirectional_circulator_tag iterator_category; typedef std::size_t size_type; #endif @@ -922,7 +976,7 @@ public: {} Vertex_around_face_circulator(halfedge_descriptor h, const Graph& g) - : Base(Halfedge_around_face_circulator(h,g), internal::Target(g)) + : Vertex_around_face_circulator::iterator_adaptor_(Halfedge_around_face_circulator(h,g)), fct(g) {} #ifndef DOXYGEN_RUNNING @@ -934,36 +988,42 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &Vertex_around_face_circulator::this_type_does_not_support_comparisons : 0; } bool operator== (void*) const { - return this->base()== NULL; + return this->base_reference()== NULL; } +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::vertex_descriptor dereference() const { return fct(*this->base_reference()); } #endif }; template class Vertex_around_face_iterator #ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_face_iterator > + : public boost::iterator_adaptor< + Vertex_around_face_iterator // Derived + , Halfedge_around_face_iterator // Base + , typename boost::graph_traits::vertex_descriptor // Value + , std::bidirectional_iterator_tag // CategoryOrTraversal + , typename boost::graph_traits::vertex_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_face_iterator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + internal::Target fct; public: -#ifndef DOXYGEN_RUNNING - typedef std::bidirectional_iterator_tag iterator_category; -#endif Vertex_around_face_iterator() {} Vertex_around_face_iterator(halfedge_descriptor h, const Graph& g, int n = 0) - : Base(Halfedge_around_face_iterator(h,g,(h==halfedge_descriptor())?1:n), internal::Target(g)) + : Vertex_around_face_iterator::iterator_adaptor_(Halfedge_around_face_iterator(h,g,(h==halfedge_descriptor())?1:n)), fct(g) {} #ifndef DOXYGEN_RUNNING @@ -975,14 +1035,17 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &Vertex_around_face_iterator::this_type_does_not_support_comparisons : 0; } bool operator== (void*) const { - return this->base()== NULL; + return this->base_reference()== NULL; } +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::vertex_descriptor dereference() const { return fct(*this->base_reference()); } #endif }; @@ -999,15 +1062,19 @@ public: template class Vertex_around_target_circulator #ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_target_circulator > + : public boost::iterator_adaptor< + Vertex_around_target_circulator // Derived + , Halfedge_around_target_circulator // Base + , typename boost::graph_traits::vertex_descriptor // Value + , Bidirectional_circulator_tag // CategoryOrTraversal + , typename boost::graph_traits::vertex_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_target_circulator > Base; - + internal::Source fct; public: #ifndef DOXYGEN_RUNNING typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef Bidirectional_circulator_tag iterator_category; typedef std::size_t size_type; #endif @@ -1015,7 +1082,7 @@ public: {} Vertex_around_target_circulator(halfedge_descriptor h, const Graph& g) - : Base(Halfedge_around_target_circulator(h,g), internal::Source(g)) + : Vertex_around_target_circulator::iterator_adaptor_(Halfedge_around_target_circulator(h,g)), fct(g) {} #ifndef DOXYGEN_RUNNING @@ -1027,9 +1094,18 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &Vertex_around_target_circulator::this_type_does_not_support_comparisons : 0; } + + bool operator== (void*) const + { + return this->base_reference()== NULL; + } + +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::vertex_descriptor dereference() const { return fct(*this->base_reference()); } #endif }; @@ -1039,20 +1115,25 @@ public: template class Vertex_around_target_iterator #ifndef DOXYGEN_RUNNING - : public boost::transform_iterator, Halfedge_around_target_iterator > + : public boost::iterator_adaptor< + Vertex_around_target_iterator // Derived + , Halfedge_around_target_iterator // Base + , typename boost::graph_traits::vertex_descriptor // Value + , std::bidirectional_iterator_tag // CategoryOrTraversal + , typename boost::graph_traits::vertex_descriptor // Reference + > #endif { - typedef boost::transform_iterator, Halfedge_around_target_iterator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + internal::Source fct; public: - typedef std::bidirectional_iterator_tag iterator_category; Vertex_around_target_iterator() {} Vertex_around_target_iterator(halfedge_descriptor h, const Graph& g, int n = 0) - : Base(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n), internal::Source(g)) + : Vertex_around_target_iterator::iterator_adaptor_(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n)), fct(g) {} #ifndef DOXYGEN_RUNNING @@ -1064,9 +1145,12 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &Vertex_around_target_iterator::this_type_does_not_support_comparisons : 0; } +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::vertex_descriptor dereference() const { return fct(*this->base_reference()); } #endif }; @@ -1119,57 +1203,69 @@ vertices_around_face(typename boost::graph_traits::halfedge_descriptor h, return make_range(I(h,g), I(h,g,1)); } -template + +template class Out_edge_iterator - : public boost::transform_iterator, Halfedge_around_target_iterator > + : public boost::iterator_adaptor< + Out_edge_iterator // Derived + , Halfedge_around_target_iterator // Base + , typename boost::graph_traits::edge_descriptor // Value + , std::bidirectional_iterator_tag // CategoryOrTraversal + , typename boost::graph_traits::edge_descriptor // Reference + > { - typedef boost::transform_iterator, Halfedge_around_target_iterator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - +private: + internal::OppositeEdge opp; public: - typedef std::bidirectional_iterator_tag iterator_category; - Out_edge_iterator() {} - + Out_edge_iterator(halfedge_descriptor h, const Graph& g, int n = 0) - : Base(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n), internal::OppositeEdge(g)) - {} - - + : Out_edge_iterator::iterator_adaptor_(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n)), opp(g) {} + // design patter: "safe bool" // will be replaced by explicit operator bool with C++11 typedef void (Out_edge_iterator::*bool_type)() const; - + void this_type_does_not_support_comparisons() const {} - + operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &Out_edge_iterator::this_type_does_not_support_comparisons : 0; } - -}; + + +private: + friend class boost::iterator_core_access; + typename boost::graph_traits::edge_descriptor dereference() const { return opp(*this->base_reference()); } +}; -template + + +template class In_edge_iterator - : public boost::transform_iterator, Halfedge_around_target_iterator > + : public boost::iterator_adaptor< + In_edge_iterator // Derived + , Halfedge_around_target_iterator // Base + , typename boost::graph_traits::edge_descriptor // Value + , std::bidirectional_iterator_tag // CategoryOrTraversal + , typename boost::graph_traits::edge_descriptor // Reference + > { - typedef boost::transform_iterator, Halfedge_around_target_iterator > Base; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - +private: + internal::Edge fct; public: - typedef std::bidirectional_iterator_tag iterator_category; - In_edge_iterator() {} - + In_edge_iterator(halfedge_descriptor h, const Graph& g, int n = 0) - : Base(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n), internal::Edge(g)) + : In_edge_iterator::iterator_adaptor_(Halfedge_around_target_iterator(h,g,(h==halfedge_descriptor())?1:n)), fct(g) {} - // design patter: "safe bool" // will be replaced by explicit operator bool with C++11 typedef void (In_edge_iterator::*bool_type)() const; @@ -1178,11 +1274,17 @@ public: operator bool_type() const { - return (! (this->base() == NULL)) ? + return (! (this->base_reference() == NULL)) ? &In_edge_iterator::this_type_does_not_support_comparisons : 0; } -}; + private: + friend class boost::iterator_core_access; + typename boost::graph_traits::edge_descriptor dereference() const { return fct(*this->base_reference()); } +}; + + + diff --git a/BGL/test/BGL/test_circulator.cpp b/BGL/test/BGL/test_circulator.cpp index 1614444c984..b0ba2375fe8 100644 --- a/BGL/test/BGL/test_circulator.cpp +++ b/BGL/test/BGL/test_circulator.cpp @@ -5,6 +5,8 @@ #include #include +#include +#include #include #include @@ -17,6 +19,7 @@ typedef GraphTraits::vertex_descriptor vertex_descriptor; typedef GraphTraits::halfedge_descriptor halfedge_descriptor; typedef GraphTraits::edge_descriptor edge_descriptor; typedef GraphTraits::out_edge_iterator out_edge_iterator; +typedef GraphTraits::in_edge_iterator in_edge_iterator; typedef CGAL::Halfedge_around_face_circulator halfedge_around_face_circulator; typedef CGAL::Halfedge_around_target_circulator halfedge_around_target_circulator; @@ -27,9 +30,27 @@ typedef CGAL::Halfedge_around_source_circulator halfedge_around_sour typedef CGAL::Halfedge_around_target_iterator halfedge_around_target_iterator; typedef CGAL::Halfedge_around_face_iterator halfedge_around_face_iterator; - +typedef CGAL::Face_around_face_iterator face_around_face_iterator; +typedef CGAL::Vertex_around_target_iterator vertex_around_target_iterator; int main(int, char* argv[]) { + + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)) CGAL_UNUSED; + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)) CGAL_UNUSED; + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)) CGAL_UNUSED; + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)) CGAL_UNUSED; + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)) CGAL_UNUSED; + + BOOST_CONCEPT_ASSERT((CGAL::Concepts::BidirectionalCirculator)) CGAL_UNUSED; + + BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); + BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); + BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); + BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); + + BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); + BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); + std::ifstream in(argv[1]); Polyhedron P; in >> P; From cc953a0ac7f325f2f89d71e11468207ec8aedcb3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 12 Feb 2015 15:40:44 +0100 Subject: [PATCH 2/2] remove warning in example, and improve output --- BGL/examples/BGL_surface_mesh/connected_components.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/BGL/examples/BGL_surface_mesh/connected_components.cpp b/BGL/examples/BGL_surface_mesh/connected_components.cpp index 2f0084b8262..9923c25a44a 100644 --- a/BGL/examples/BGL_surface_mesh/connected_components.cpp +++ b/BGL/examples/BGL_surface_mesh/connected_components.cpp @@ -19,11 +19,12 @@ int main(int argc, char* argv[]) in >> sm; Mesh::Property_map ccmap; - ccmap = sm.add_property_map("v:CC").first; - int num = connected_components(sm, ccmap); + ccmap = sm.add_property_map("v:CC").first; + int num = connected_components(sm, ccmap); + std::cout << num << " connected components" << std::endl; BOOST_FOREACH(vertex_descriptor v, vertices(sm)){ - std::cout << v << " is in component " << ccmap[v] << "\n"; + std::cout << v << " is in component " << ccmap[v] << std::endl; } return 0;