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