planar_face_traversal.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //=======================================================================
  2. // Copyright (c) Aaron Windsor 2007
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //=======================================================================
  8. #ifndef __PLANAR_FACE_TRAVERSAL_HPP__
  9. #define __PLANAR_FACE_TRAVERSAL_HPP__
  10. #include <vector>
  11. #include <set>
  12. #include <map>
  13. #include <boost/next_prior.hpp>
  14. #include <boost/graph/graph_traits.hpp>
  15. #include <boost/graph/properties.hpp>
  16. namespace boost
  17. {
  18. struct planar_face_traversal_visitor
  19. {
  20. void begin_traversal()
  21. {}
  22. void begin_face()
  23. {}
  24. template <typename Edge>
  25. void next_edge(Edge)
  26. {}
  27. template <typename Vertex>
  28. void next_vertex(Vertex)
  29. {}
  30. void end_face()
  31. {}
  32. void end_traversal()
  33. {}
  34. };
  35. template<typename Graph,
  36. typename PlanarEmbedding,
  37. typename Visitor,
  38. typename EdgeIndexMap>
  39. void planar_face_traversal(const Graph& g,
  40. PlanarEmbedding embedding,
  41. Visitor& visitor, EdgeIndexMap em
  42. )
  43. {
  44. typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
  45. typedef typename graph_traits<Graph>::edge_descriptor edge_t;
  46. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
  47. typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t;
  48. typedef typename
  49. property_traits<PlanarEmbedding>::value_type embedding_value_t;
  50. typedef typename embedding_value_t::const_iterator embedding_iterator_t;
  51. typedef typename
  52. std::vector< std::set<vertex_t> > distinguished_edge_storage_t;
  53. typedef typename
  54. std::vector< std::map<vertex_t, edge_t> >
  55. distinguished_edge_to_edge_storage_t;
  56. typedef typename
  57. boost::iterator_property_map
  58. <typename distinguished_edge_storage_t::iterator, EdgeIndexMap>
  59. distinguished_edge_map_t;
  60. typedef typename
  61. boost::iterator_property_map
  62. <typename distinguished_edge_to_edge_storage_t::iterator, EdgeIndexMap>
  63. distinguished_edge_to_edge_map_t;
  64. distinguished_edge_storage_t visited_vector(num_edges(g));
  65. distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g));
  66. distinguished_edge_map_t visited(visited_vector.begin(), em);
  67. distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em);
  68. vertex_iterator_t vi, vi_end;
  69. typename std::vector<edge_t>::iterator ei, ei_end;
  70. edge_iterator_t fi, fi_end;
  71. embedding_iterator_t pi, pi_begin, pi_end;
  72. visitor.begin_traversal();
  73. // Initialize the next_edge property map. This map is initialized from the
  74. // PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes
  75. // after e in the clockwise embedding around vertex v.
  76. for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  77. {
  78. vertex_t v(*vi);
  79. pi_begin = embedding[v].begin();
  80. pi_end = embedding[v].end();
  81. for(pi = pi_begin; pi != pi_end; ++pi)
  82. {
  83. edge_t e(*pi);
  84. std::map<vertex_t, edge_t> m = get(next_edge, e);
  85. m[v] = boost::next(pi) == pi_end ? *pi_begin : *boost::next(pi);
  86. put(next_edge, e, m);
  87. }
  88. }
  89. // Take a copy of the edges in the graph here, since we want to accomodate
  90. // face traversals that add edges to the graph (for triangulation, in
  91. // particular) and don't want to use invalidated edge iterators.
  92. // Also, while iterating over all edges in the graph, we single out
  93. // any self-loops, which need some special treatment in the face traversal.
  94. std::vector<edge_t> self_loops;
  95. std::vector<edge_t> edges_cache;
  96. std::vector<vertex_t> vertices_in_edge;
  97. for(boost::tie(fi,fi_end) = edges(g); fi != fi_end; ++fi)
  98. {
  99. edge_t e(*fi);
  100. edges_cache.push_back(e);
  101. if (source(e,g) == target(e,g))
  102. self_loops.push_back(e);
  103. }
  104. // Iterate over all edges in the graph
  105. ei_end = edges_cache.end();
  106. for(ei = edges_cache.begin(); ei != ei_end; ++ei)
  107. {
  108. edge_t e(*ei);
  109. vertices_in_edge.clear();
  110. vertices_in_edge.push_back(source(e,g));
  111. vertices_in_edge.push_back(target(e,g));
  112. typename std::vector<vertex_t>::iterator vi, vi_end;
  113. vi_end = vertices_in_edge.end();
  114. //Iterate over both vertices in the current edge
  115. for(vi = vertices_in_edge.begin(); vi != vi_end; ++vi)
  116. {
  117. vertex_t v(*vi);
  118. std::set<vertex_t> e_visited = get(visited, e);
  119. typename std::set<vertex_t>::iterator e_visited_found
  120. = e_visited.find(v);
  121. if (e_visited_found == e_visited.end())
  122. visitor.begin_face();
  123. while (e_visited.find(v) == e_visited.end())
  124. {
  125. visitor.next_vertex(v);
  126. visitor.next_edge(e);
  127. e_visited.insert(v);
  128. put(visited, e, e_visited);
  129. v = source(e,g) == v ? target(e,g) : source(e,g);
  130. e = get(next_edge, e)[v];
  131. e_visited = get(visited, e);
  132. }
  133. if (e_visited_found == e_visited.end())
  134. visitor.end_face();
  135. }
  136. }
  137. // Iterate over all self-loops, visiting them once separately
  138. // (they've already been visited once, this visitation is for
  139. // the "inside" of the self-loop)
  140. ei_end = self_loops.end();
  141. for(ei = self_loops.begin(); ei != ei_end; ++ei)
  142. {
  143. visitor.begin_face();
  144. visitor.next_edge(*ei);
  145. visitor.next_vertex(source(*ei,g));
  146. visitor.end_face();
  147. }
  148. visitor.end_traversal();
  149. }
  150. template<typename Graph, typename PlanarEmbedding, typename Visitor>
  151. inline void planar_face_traversal(const Graph& g,
  152. PlanarEmbedding embedding,
  153. Visitor& visitor
  154. )
  155. {
  156. planar_face_traversal(g, embedding, visitor, get(edge_index, g));
  157. }
  158. } //namespace boost
  159. #endif //__PLANAR_FACE_TRAVERSAL_HPP__