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