1 | //======================================================================= |
2 | // Copyright 2007 Aaron Windsor |
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 __MAKE_MAXIMAL_PLANAR_HPP__ |
9 | #define __MAKE_MAXIMAL_PLANAR_HPP__ |
10 | |
11 | #include <boost/config.hpp> |
12 | #include <boost/tuple/tuple.hpp> //for tie |
13 | #include <boost/graph/biconnected_components.hpp> |
14 | #include <boost/property_map/property_map.hpp> |
15 | #include <vector> |
16 | #include <iterator> |
17 | #include <algorithm> |
18 | |
19 | #include <boost/graph/planar_face_traversal.hpp> |
20 | #include <boost/graph/planar_detail/add_edge_visitors.hpp> |
21 | |
22 | |
23 | namespace boost |
24 | { |
25 | |
26 | |
27 | template <typename Graph, typename VertexIndexMap, typename AddEdgeVisitor> |
28 | struct triangulation_visitor : public planar_face_traversal_visitor |
29 | { |
30 | |
31 | typedef typename graph_traits<Graph>::vertex_descriptor vertex_t; |
32 | typedef typename graph_traits<Graph>::edge_descriptor edge_t; |
33 | typedef typename graph_traits<Graph>::vertices_size_type v_size_t; |
34 | typedef typename graph_traits<Graph>::degree_size_type degree_size_t; |
35 | typedef typename graph_traits<Graph>::edge_iterator edge_iterator_t; |
36 | typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t; |
37 | typedef typename graph_traits<Graph>::adjacency_iterator |
38 | adjacency_iterator_t; |
39 | typedef typename std::vector<vertex_t> vertex_vector_t; |
40 | typedef typename std::vector<v_size_t> v_size_vector_t; |
41 | typedef typename std::vector<degree_size_t> degree_size_vector_t; |
42 | typedef iterator_property_map |
43 | < typename v_size_vector_t::iterator, VertexIndexMap > |
44 | vertex_to_v_size_map_t; |
45 | typedef iterator_property_map |
46 | < typename degree_size_vector_t::iterator, VertexIndexMap > |
47 | vertex_to_degree_size_map_t; |
48 | typedef typename vertex_vector_t::iterator face_iterator; |
49 | |
50 | |
51 | triangulation_visitor(Graph& arg_g, |
52 | VertexIndexMap arg_vm, |
53 | AddEdgeVisitor arg_add_edge_visitor |
54 | ) : |
55 | g(arg_g), |
56 | vm(arg_vm), |
57 | add_edge_visitor(arg_add_edge_visitor), |
58 | timestamp(0), |
59 | marked_vector(num_vertices(g), timestamp), |
60 | degree_vector(num_vertices(g), 0), |
61 | marked(marked_vector.begin(), vm), |
62 | degree(degree_vector.begin(), vm) |
63 | { |
64 | vertex_iterator_t vi, vi_end; |
65 | for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi) |
66 | put(degree, *vi, out_degree(*vi, g)); |
67 | } |
68 | |
69 | template <typename Vertex> |
70 | void next_vertex(Vertex v) |
71 | { |
72 | // Self-loops will appear as consecutive vertices in the list of |
73 | // vertices on a face. We want to skip these. |
74 | if (!vertices_on_face.empty() && |
75 | (vertices_on_face.back() == v || vertices_on_face.front() == v) |
76 | ) |
77 | return; |
78 | |
79 | vertices_on_face.push_back(v); |
80 | } |
81 | |
82 | void end_face() |
83 | { |
84 | ++timestamp; |
85 | |
86 | if (vertices_on_face.size() <= 3) |
87 | { |
88 | // At most three vertices on this face - don't need to triangulate |
89 | vertices_on_face.clear(); |
90 | return; |
91 | } |
92 | |
93 | // Find vertex on face of minimum degree |
94 | degree_size_t min_degree = num_vertices(g); |
95 | typename vertex_vector_t::iterator min_degree_vertex_itr; |
96 | face_iterator fi_end = vertices_on_face.end(); |
97 | for(face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi) |
98 | { |
99 | degree_size_t deg = get(degree,*fi); |
100 | if (deg < min_degree) |
101 | { |
102 | min_degree_vertex_itr = fi; |
103 | min_degree = deg; |
104 | } |
105 | } |
106 | |
107 | // To simplify some of the manipulations, we'll re-arrange |
108 | // vertices_on_face so that it still contains the same |
109 | // (counter-clockwise) order of the vertices on this face, but now the |
110 | // min_degree_vertex is the first element in vertices_on_face. |
111 | vertex_vector_t temp_vector; |
112 | std::copy(min_degree_vertex_itr, vertices_on_face.end(), |
113 | std::back_inserter(temp_vector)); |
114 | std::copy(vertices_on_face.begin(), min_degree_vertex_itr, |
115 | std::back_inserter(temp_vector)); |
116 | vertices_on_face.swap(temp_vector); |
117 | |
118 | // Mark all of the min degree vertex's neighbors |
119 | adjacency_iterator_t ai, ai_end; |
120 | for(boost::tie(ai,ai_end) = adjacent_vertices(vertices_on_face.front(),g); |
121 | ai != ai_end; ++ai |
122 | ) |
123 | { |
124 | put(marked, *ai, timestamp); |
125 | } |
126 | |
127 | typename vertex_vector_t::iterator marked_neighbor |
128 | = vertices_on_face.end(); |
129 | |
130 | // The iterator manipulations on the next two lines are safe because |
131 | // vertices_on_face.size() > 3 (from the first test in this function) |
132 | fi_end = prior(vertices_on_face.end()); |
133 | for(face_iterator fi = boost::next(boost::next(vertices_on_face.begin())); |
134 | fi != fi_end; ++fi |
135 | ) |
136 | { |
137 | if (get(marked, *fi) == timestamp) |
138 | { |
139 | marked_neighbor = fi; |
140 | break; |
141 | } |
142 | } |
143 | |
144 | if (marked_neighbor == vertices_on_face.end()) |
145 | { |
146 | add_edge_range( |
147 | anchor: vertices_on_face[0], |
148 | fi: boost::next(boost::next(vertices_on_face.begin())), |
149 | fi_end: prior(vertices_on_face.end()) |
150 | ); |
151 | } |
152 | else |
153 | { |
154 | add_edge_range( |
155 | anchor: vertices_on_face[1], |
156 | fi: boost::next(marked_neighbor), |
157 | fi_end: vertices_on_face.end() |
158 | ); |
159 | |
160 | add_edge_range( |
161 | anchor: *boost::next(marked_neighbor), |
162 | fi: boost::next(boost::next(vertices_on_face.begin())), |
163 | fi_end: marked_neighbor |
164 | ); |
165 | } |
166 | |
167 | //reset for the next face |
168 | vertices_on_face.clear(); |
169 | |
170 | } |
171 | |
172 | private: |
173 | |
174 | |
175 | void add_edge_range(vertex_t anchor, |
176 | face_iterator fi, |
177 | face_iterator fi_end |
178 | ) |
179 | { |
180 | for (; fi != fi_end; ++fi) |
181 | { |
182 | vertex_t v(*fi); |
183 | add_edge_visitor.visit_vertex_pair(anchor, v, g); |
184 | put(degree, anchor, get(degree, anchor) + 1); |
185 | put(degree, v, get(degree, v) + 1); |
186 | } |
187 | } |
188 | |
189 | |
190 | Graph& g; |
191 | VertexIndexMap vm; |
192 | AddEdgeVisitor add_edge_visitor; |
193 | v_size_t timestamp; |
194 | vertex_vector_t vertices_on_face; |
195 | v_size_vector_t marked_vector; |
196 | degree_size_vector_t degree_vector; |
197 | vertex_to_v_size_map_t marked; |
198 | vertex_to_degree_size_map_t degree; |
199 | |
200 | }; |
201 | |
202 | |
203 | |
204 | |
205 | template <typename Graph, |
206 | typename PlanarEmbedding, |
207 | typename VertexIndexMap, |
208 | typename EdgeIndexMap, |
209 | typename AddEdgeVisitor |
210 | > |
211 | void make_maximal_planar(Graph& g, |
212 | PlanarEmbedding embedding, |
213 | VertexIndexMap vm, |
214 | EdgeIndexMap em, |
215 | AddEdgeVisitor& vis) |
216 | { |
217 | triangulation_visitor<Graph,VertexIndexMap,AddEdgeVisitor> |
218 | visitor(g, vm, vis); |
219 | planar_face_traversal(g, embedding, visitor, em); |
220 | } |
221 | |
222 | |
223 | |
224 | |
225 | template <typename Graph, |
226 | typename PlanarEmbedding, |
227 | typename VertexIndexMap, |
228 | typename EdgeIndexMap |
229 | > |
230 | void make_maximal_planar(Graph& g, |
231 | PlanarEmbedding embedding, |
232 | VertexIndexMap vm, |
233 | EdgeIndexMap em |
234 | ) |
235 | { |
236 | default_add_edge_visitor vis; |
237 | make_maximal_planar(g, embedding, vm, em, vis); |
238 | } |
239 | |
240 | |
241 | |
242 | |
243 | template <typename Graph, |
244 | typename PlanarEmbedding, |
245 | typename VertexIndexMap |
246 | > |
247 | void make_maximal_planar(Graph& g, |
248 | PlanarEmbedding embedding, |
249 | VertexIndexMap vm |
250 | ) |
251 | { |
252 | make_maximal_planar(g, embedding, vm, get(edge_index,g)); |
253 | } |
254 | |
255 | |
256 | |
257 | |
258 | template <typename Graph, |
259 | typename PlanarEmbedding |
260 | > |
261 | void make_maximal_planar(Graph& g, |
262 | PlanarEmbedding embedding |
263 | ) |
264 | { |
265 | make_maximal_planar(g, embedding, get(vertex_index,g)); |
266 | } |
267 | |
268 | |
269 | |
270 | |
271 | } // namespace boost |
272 | |
273 | |
274 | |
275 | #endif //__MAKE_MAXIMAL_PLANAR_HPP__ |
276 | |