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 __FACE_HANDLES_HPP__
|
Chris@16
|
10 #define __FACE_HANDLES_HPP__
|
Chris@16
|
11
|
Chris@16
|
12
|
Chris@16
|
13 #include <list>
|
Chris@16
|
14 #include <boost/graph/graph_traits.hpp>
|
Chris@16
|
15 #include <boost/shared_ptr.hpp>
|
Chris@16
|
16
|
Chris@16
|
17
|
Chris@16
|
18 // A "face handle" is an optimization meant to serve two purposes in
|
Chris@16
|
19 // the implementation of the Boyer-Myrvold planarity test: (1) it holds
|
Chris@16
|
20 // the partial planar embedding of a particular vertex as it's being
|
Chris@16
|
21 // constructed, and (2) it allows for efficient traversal around the
|
Chris@16
|
22 // outer face of the partial embedding at that particular vertex. A face
|
Chris@16
|
23 // handle is lightweight, just a shared pointer to the actual implementation,
|
Chris@16
|
24 // since it is passed around/copied liberally in the algorithm. It consists
|
Chris@16
|
25 // of an "anchor" (the actual vertex it's associated with) as well as a
|
Chris@16
|
26 // sequence of edges. The functions first_vertex/second_vertex and
|
Chris@16
|
27 // first_edge/second_edge allow fast access to the beginning and end of the
|
Chris@16
|
28 // stored sequence, which allows one to traverse the outer face of the partial
|
Chris@16
|
29 // planar embedding as it's being created.
|
Chris@16
|
30 //
|
Chris@16
|
31 // There are some policies below that define the contents of the face handles:
|
Chris@16
|
32 // in the case no embedding is needed (for example, if one just wants to use
|
Chris@16
|
33 // the Boyer-Myrvold algorithm as a true/false test for planarity, the
|
Chris@16
|
34 // no_embedding class can be passed as the StoreEmbedding policy. Otherwise,
|
Chris@16
|
35 // either std_list (which uses as std::list) or recursive_lazy_list can be
|
Chris@16
|
36 // passed as this policy. recursive_lazy_list has the best theoretical
|
Chris@16
|
37 // performance (O(n) for a sequence of interleaved concatenations and reversals
|
Chris@16
|
38 // of the underlying list), but I've noticed little difference between std_list
|
Chris@16
|
39 // and recursive_lazy_list in my tests, even though using std_list changes
|
Chris@16
|
40 // the worst-case complexity of the planarity test to O(n^2)
|
Chris@16
|
41 //
|
Chris@16
|
42 // Another policy is StoreOldHandlesPolicy, which specifies whether or not
|
Chris@16
|
43 // to keep a record of the previous first/second vertex/edge - this is needed
|
Chris@16
|
44 // if a Kuratowski subgraph needs to be isolated.
|
Chris@16
|
45
|
Chris@16
|
46
|
Chris@16
|
47 namespace boost { namespace graph { namespace detail {
|
Chris@16
|
48
|
Chris@16
|
49
|
Chris@16
|
50 //face handle policies
|
Chris@16
|
51
|
Chris@16
|
52 //EmbeddingStorage policy
|
Chris@16
|
53 struct store_embedding {};
|
Chris@16
|
54 struct recursive_lazy_list : public store_embedding {};
|
Chris@16
|
55 struct std_list : public store_embedding {};
|
Chris@16
|
56 struct no_embedding {};
|
Chris@16
|
57
|
Chris@16
|
58 //StoreOldHandlesPolicy
|
Chris@16
|
59 struct store_old_handles {};
|
Chris@16
|
60 struct no_old_handles {};
|
Chris@16
|
61
|
Chris@16
|
62
|
Chris@16
|
63
|
Chris@16
|
64
|
Chris@16
|
65 template<typename DataType>
|
Chris@16
|
66 struct lazy_list_node
|
Chris@16
|
67 {
|
Chris@16
|
68 typedef shared_ptr< lazy_list_node<DataType> > ptr_t;
|
Chris@16
|
69
|
Chris@16
|
70 lazy_list_node(const DataType& data) :
|
Chris@16
|
71 m_reversed(false),
|
Chris@16
|
72 m_data(data),
|
Chris@16
|
73 m_has_data(true)
|
Chris@16
|
74 {}
|
Chris@16
|
75
|
Chris@16
|
76 lazy_list_node(ptr_t left_child, ptr_t right_child) :
|
Chris@16
|
77 m_reversed(false),
|
Chris@16
|
78 m_has_data(false),
|
Chris@16
|
79 m_left_child(left_child),
|
Chris@16
|
80 m_right_child(right_child)
|
Chris@16
|
81 {}
|
Chris@16
|
82
|
Chris@16
|
83 bool m_reversed;
|
Chris@16
|
84 DataType m_data;
|
Chris@16
|
85 bool m_has_data;
|
Chris@16
|
86 shared_ptr<lazy_list_node> m_left_child;
|
Chris@16
|
87 shared_ptr<lazy_list_node> m_right_child;
|
Chris@16
|
88 };
|
Chris@16
|
89
|
Chris@16
|
90
|
Chris@16
|
91
|
Chris@16
|
92 template <typename StoreOldHandlesPolicy, typename Vertex, typename Edge>
|
Chris@16
|
93 struct old_handles_storage;
|
Chris@16
|
94
|
Chris@16
|
95 template <typename Vertex, typename Edge>
|
Chris@16
|
96 struct old_handles_storage<store_old_handles, Vertex, Edge>
|
Chris@16
|
97 {
|
Chris@16
|
98 Vertex first_vertex;
|
Chris@16
|
99 Vertex second_vertex;
|
Chris@16
|
100 Edge first_edge;
|
Chris@16
|
101 Edge second_edge;
|
Chris@16
|
102 };
|
Chris@16
|
103
|
Chris@16
|
104 template <typename Vertex, typename Edge>
|
Chris@16
|
105 struct old_handles_storage<no_old_handles, Vertex, Edge>
|
Chris@16
|
106 {};
|
Chris@16
|
107
|
Chris@16
|
108
|
Chris@16
|
109
|
Chris@16
|
110
|
Chris@16
|
111
|
Chris@16
|
112
|
Chris@16
|
113 template <typename StoreEmbeddingPolicy, typename Edge>
|
Chris@16
|
114 struct edge_list_storage;
|
Chris@16
|
115
|
Chris@16
|
116
|
Chris@16
|
117
|
Chris@16
|
118
|
Chris@16
|
119
|
Chris@16
|
120 template <typename Edge>
|
Chris@16
|
121 struct edge_list_storage<no_embedding, Edge>
|
Chris@16
|
122 {
|
Chris@16
|
123 typedef void type;
|
Chris@16
|
124
|
Chris@16
|
125 void push_back(Edge) {}
|
Chris@16
|
126 void push_front(Edge) {}
|
Chris@16
|
127 void reverse() {}
|
Chris@16
|
128 void concat_front(edge_list_storage<no_embedding,Edge>) {}
|
Chris@16
|
129 void concat_back(edge_list_storage<no_embedding,Edge>) {}
|
Chris@16
|
130 template <typename OutputIterator>
|
Chris@16
|
131 void get_list(OutputIterator) {}
|
Chris@16
|
132 };
|
Chris@16
|
133
|
Chris@16
|
134
|
Chris@16
|
135
|
Chris@16
|
136
|
Chris@16
|
137
|
Chris@16
|
138 template <typename Edge>
|
Chris@16
|
139 struct edge_list_storage<recursive_lazy_list, Edge>
|
Chris@16
|
140 {
|
Chris@16
|
141 typedef lazy_list_node<Edge> node_type;
|
Chris@16
|
142 typedef shared_ptr< node_type > type;
|
Chris@16
|
143 type value;
|
Chris@16
|
144
|
Chris@16
|
145 void push_back(Edge e)
|
Chris@16
|
146 {
|
Chris@16
|
147 type new_node(new node_type(e));
|
Chris@16
|
148 value = type(new node_type(value, new_node));
|
Chris@16
|
149 }
|
Chris@16
|
150
|
Chris@16
|
151 void push_front(Edge e)
|
Chris@16
|
152 {
|
Chris@16
|
153 type new_node(new node_type(e));
|
Chris@16
|
154 value = type(new node_type(new_node, value));
|
Chris@16
|
155 }
|
Chris@16
|
156
|
Chris@16
|
157 void reverse()
|
Chris@16
|
158 {
|
Chris@16
|
159 value->m_reversed = !value->m_reversed;
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@16
|
162 void concat_front(edge_list_storage<recursive_lazy_list, Edge> other)
|
Chris@16
|
163 {
|
Chris@16
|
164 value = type(new node_type(other.value, value));
|
Chris@16
|
165 }
|
Chris@16
|
166
|
Chris@16
|
167 void concat_back(edge_list_storage<recursive_lazy_list, Edge> other)
|
Chris@16
|
168 {
|
Chris@16
|
169 value = type(new node_type(value, other.value));
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 template <typename OutputIterator>
|
Chris@16
|
173 void get_list(OutputIterator out)
|
Chris@16
|
174 {
|
Chris@16
|
175 get_list_helper(out, value);
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 private:
|
Chris@16
|
179
|
Chris@16
|
180 template <typename OutputIterator>
|
Chris@16
|
181 void get_list_helper(OutputIterator o_itr,
|
Chris@16
|
182 type root,
|
Chris@16
|
183 bool flipped = false
|
Chris@16
|
184 )
|
Chris@16
|
185 {
|
Chris@16
|
186 if (!root)
|
Chris@16
|
187 return;
|
Chris@16
|
188
|
Chris@16
|
189 if (root->m_has_data)
|
Chris@16
|
190 *o_itr = root->m_data;
|
Chris@16
|
191
|
Chris@16
|
192 if ((flipped && !root->m_reversed) ||
|
Chris@16
|
193 (!flipped && root->m_reversed)
|
Chris@16
|
194 )
|
Chris@16
|
195 {
|
Chris@16
|
196 get_list_helper(o_itr, root->m_right_child, true);
|
Chris@16
|
197 get_list_helper(o_itr, root->m_left_child, true);
|
Chris@16
|
198 }
|
Chris@16
|
199 else
|
Chris@16
|
200 {
|
Chris@16
|
201 get_list_helper(o_itr, root->m_left_child, false);
|
Chris@16
|
202 get_list_helper(o_itr, root->m_right_child, false);
|
Chris@16
|
203 }
|
Chris@16
|
204
|
Chris@16
|
205 }
|
Chris@16
|
206
|
Chris@16
|
207 };
|
Chris@16
|
208
|
Chris@16
|
209
|
Chris@16
|
210
|
Chris@16
|
211
|
Chris@16
|
212
|
Chris@16
|
213 template <typename Edge>
|
Chris@16
|
214 struct edge_list_storage<std_list, Edge>
|
Chris@16
|
215 {
|
Chris@16
|
216 typedef std::list<Edge> type;
|
Chris@16
|
217 type value;
|
Chris@16
|
218
|
Chris@16
|
219 void push_back(Edge e)
|
Chris@16
|
220 {
|
Chris@16
|
221 value.push_back(e);
|
Chris@16
|
222 }
|
Chris@16
|
223
|
Chris@16
|
224 void push_front(Edge e)
|
Chris@16
|
225 {
|
Chris@16
|
226 value.push_front(e);
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 void reverse()
|
Chris@16
|
230 {
|
Chris@16
|
231 value.reverse();
|
Chris@16
|
232 }
|
Chris@16
|
233
|
Chris@16
|
234 void concat_front(edge_list_storage<std_list,Edge> other)
|
Chris@16
|
235 {
|
Chris@16
|
236 value.splice(value.begin(), other.value);
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 void concat_back(edge_list_storage<std_list, Edge> other)
|
Chris@16
|
240 {
|
Chris@16
|
241 value.splice(value.end(), other.value);
|
Chris@16
|
242 }
|
Chris@16
|
243
|
Chris@16
|
244 template <typename OutputIterator>
|
Chris@16
|
245 void get_list(OutputIterator out)
|
Chris@16
|
246 {
|
Chris@16
|
247 std::copy(value.begin(), value.end(), out);
|
Chris@16
|
248 }
|
Chris@16
|
249
|
Chris@16
|
250 };
|
Chris@16
|
251
|
Chris@16
|
252
|
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 StoreOldHandlesPolicy,
|
Chris@16
|
260 typename StoreEmbeddingPolicy
|
Chris@16
|
261 >
|
Chris@16
|
262 struct face_handle_impl
|
Chris@16
|
263 {
|
Chris@16
|
264 typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
Chris@16
|
265 typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
Chris@16
|
266 typedef typename edge_list_storage<StoreEmbeddingPolicy, edge_t>::type
|
Chris@16
|
267 edge_list_storage_t;
|
Chris@16
|
268
|
Chris@16
|
269
|
Chris@16
|
270 face_handle_impl() :
|
Chris@16
|
271 cached_first_vertex(graph_traits<Graph>::null_vertex()),
|
Chris@16
|
272 cached_second_vertex(graph_traits<Graph>::null_vertex()),
|
Chris@16
|
273 true_first_vertex(graph_traits<Graph>::null_vertex()),
|
Chris@16
|
274 true_second_vertex(graph_traits<Graph>::null_vertex()),
|
Chris@16
|
275 anchor(graph_traits<Graph>::null_vertex())
|
Chris@16
|
276 {
|
Chris@16
|
277 initialize_old_vertices_dispatch(StoreOldHandlesPolicy());
|
Chris@16
|
278 }
|
Chris@16
|
279
|
Chris@16
|
280 void initialize_old_vertices_dispatch(store_old_handles)
|
Chris@16
|
281 {
|
Chris@16
|
282 old_handles.first_vertex = graph_traits<Graph>::null_vertex();
|
Chris@16
|
283 old_handles.second_vertex = graph_traits<Graph>::null_vertex();
|
Chris@16
|
284 }
|
Chris@16
|
285
|
Chris@16
|
286 void initialize_old_vertices_dispatch(no_old_handles) {}
|
Chris@16
|
287
|
Chris@16
|
288 vertex_t cached_first_vertex;
|
Chris@16
|
289 vertex_t cached_second_vertex;
|
Chris@16
|
290 vertex_t true_first_vertex;
|
Chris@16
|
291 vertex_t true_second_vertex;
|
Chris@16
|
292 vertex_t anchor;
|
Chris@16
|
293 edge_t cached_first_edge;
|
Chris@16
|
294 edge_t cached_second_edge;
|
Chris@16
|
295
|
Chris@16
|
296 edge_list_storage<StoreEmbeddingPolicy, edge_t> edge_list;
|
Chris@16
|
297 old_handles_storage<StoreOldHandlesPolicy, vertex_t, edge_t> old_handles;
|
Chris@16
|
298
|
Chris@16
|
299 };
|
Chris@16
|
300
|
Chris@16
|
301
|
Chris@16
|
302
|
Chris@16
|
303
|
Chris@16
|
304
|
Chris@16
|
305
|
Chris@16
|
306
|
Chris@16
|
307
|
Chris@16
|
308
|
Chris@16
|
309
|
Chris@16
|
310
|
Chris@16
|
311 template <typename Graph,
|
Chris@16
|
312 typename StoreOldHandlesPolicy = store_old_handles,
|
Chris@16
|
313 typename StoreEmbeddingPolicy = recursive_lazy_list
|
Chris@16
|
314 >
|
Chris@16
|
315 class face_handle
|
Chris@16
|
316 {
|
Chris@16
|
317 public:
|
Chris@16
|
318 typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
Chris@16
|
319 typedef typename graph_traits<Graph>::edge_descriptor edge_t;
|
Chris@16
|
320 typedef face_handle_impl
|
Chris@16
|
321 <Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> impl_t;
|
Chris@16
|
322 typedef face_handle
|
Chris@16
|
323 <Graph, StoreOldHandlesPolicy, StoreEmbeddingPolicy> self_t;
|
Chris@16
|
324
|
Chris@16
|
325 face_handle(vertex_t anchor = graph_traits<Graph>::null_vertex()) :
|
Chris@16
|
326 pimpl(new impl_t())
|
Chris@16
|
327 {
|
Chris@16
|
328 pimpl->anchor = anchor;
|
Chris@16
|
329 }
|
Chris@16
|
330
|
Chris@16
|
331 face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) :
|
Chris@16
|
332 pimpl(new impl_t())
|
Chris@16
|
333 {
|
Chris@16
|
334 vertex_t s(source(initial_edge,g));
|
Chris@16
|
335 vertex_t t(target(initial_edge,g));
|
Chris@16
|
336 vertex_t other_vertex = s == anchor ? t : s;
|
Chris@16
|
337 pimpl->anchor = anchor;
|
Chris@16
|
338 pimpl->cached_first_edge = initial_edge;
|
Chris@16
|
339 pimpl->cached_second_edge = initial_edge;
|
Chris@16
|
340 pimpl->cached_first_vertex = other_vertex;
|
Chris@16
|
341 pimpl->cached_second_vertex = other_vertex;
|
Chris@16
|
342 pimpl->true_first_vertex = other_vertex;
|
Chris@16
|
343 pimpl->true_second_vertex = other_vertex;
|
Chris@16
|
344
|
Chris@16
|
345 pimpl->edge_list.push_back(initial_edge);
|
Chris@16
|
346 store_old_face_handles_dispatch(StoreOldHandlesPolicy());
|
Chris@16
|
347 }
|
Chris@16
|
348
|
Chris@16
|
349 //default copy construction, assignment okay.
|
Chris@16
|
350
|
Chris@16
|
351 void push_first(edge_t e, const Graph& g)
|
Chris@16
|
352 {
|
Chris@16
|
353 pimpl->edge_list.push_front(e);
|
Chris@16
|
354 pimpl->cached_first_vertex = pimpl->true_first_vertex =
|
Chris@16
|
355 source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
|
Chris@16
|
356 pimpl->cached_first_edge = e;
|
Chris@16
|
357 }
|
Chris@16
|
358
|
Chris@16
|
359 void push_second(edge_t e, const Graph& g)
|
Chris@16
|
360 {
|
Chris@16
|
361 pimpl->edge_list.push_back(e);
|
Chris@16
|
362 pimpl->cached_second_vertex = pimpl->true_second_vertex =
|
Chris@16
|
363 source(e, g) == pimpl->anchor ? target(e,g) : source(e,g);
|
Chris@16
|
364 pimpl->cached_second_edge = e;
|
Chris@16
|
365 }
|
Chris@16
|
366
|
Chris@16
|
367 inline void store_old_face_handles()
|
Chris@16
|
368 {
|
Chris@16
|
369 store_old_face_handles_dispatch(StoreOldHandlesPolicy());
|
Chris@16
|
370 }
|
Chris@16
|
371
|
Chris@16
|
372 inline vertex_t first_vertex() const
|
Chris@16
|
373 {
|
Chris@16
|
374 return pimpl->cached_first_vertex;
|
Chris@16
|
375 }
|
Chris@16
|
376
|
Chris@16
|
377 inline vertex_t second_vertex() const
|
Chris@16
|
378 {
|
Chris@16
|
379 return pimpl->cached_second_vertex;
|
Chris@16
|
380 }
|
Chris@16
|
381
|
Chris@16
|
382 inline vertex_t true_first_vertex() const
|
Chris@16
|
383 {
|
Chris@16
|
384 return pimpl->true_first_vertex;
|
Chris@16
|
385 }
|
Chris@16
|
386
|
Chris@16
|
387 inline vertex_t true_second_vertex() const
|
Chris@16
|
388 {
|
Chris@16
|
389 return pimpl->true_second_vertex;
|
Chris@16
|
390 }
|
Chris@16
|
391
|
Chris@16
|
392 inline vertex_t old_first_vertex() const
|
Chris@16
|
393 {
|
Chris@16
|
394 return pimpl->old_handles.first_vertex;
|
Chris@16
|
395 }
|
Chris@16
|
396
|
Chris@16
|
397 inline vertex_t old_second_vertex() const
|
Chris@16
|
398 {
|
Chris@16
|
399 return pimpl->old_handles.second_vertex;
|
Chris@16
|
400 }
|
Chris@16
|
401
|
Chris@16
|
402 inline edge_t old_first_edge() const
|
Chris@16
|
403 {
|
Chris@16
|
404 return pimpl->old_handles.first_edge;
|
Chris@16
|
405 }
|
Chris@16
|
406
|
Chris@16
|
407 inline edge_t old_second_edge() const
|
Chris@16
|
408 {
|
Chris@16
|
409 return pimpl->old_handles.second_edge;
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 inline edge_t first_edge() const
|
Chris@16
|
413 {
|
Chris@16
|
414 return pimpl->cached_first_edge;
|
Chris@16
|
415 }
|
Chris@16
|
416
|
Chris@16
|
417 inline edge_t second_edge() const
|
Chris@16
|
418 {
|
Chris@16
|
419 return pimpl->cached_second_edge;
|
Chris@16
|
420 }
|
Chris@16
|
421
|
Chris@16
|
422 inline vertex_t get_anchor() const
|
Chris@16
|
423 {
|
Chris@16
|
424 return pimpl->anchor;
|
Chris@16
|
425 }
|
Chris@16
|
426
|
Chris@16
|
427 void glue_first_to_second
|
Chris@16
|
428 (face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
|
Chris@16
|
429 {
|
Chris@16
|
430 pimpl->edge_list.concat_front(bottom.pimpl->edge_list);
|
Chris@16
|
431 pimpl->true_first_vertex = bottom.pimpl->true_first_vertex;
|
Chris@16
|
432 pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex;
|
Chris@16
|
433 pimpl->cached_first_edge = bottom.pimpl->cached_first_edge;
|
Chris@16
|
434 }
|
Chris@16
|
435
|
Chris@16
|
436 void glue_second_to_first
|
Chris@16
|
437 (face_handle<Graph,StoreOldHandlesPolicy,StoreEmbeddingPolicy>& bottom)
|
Chris@16
|
438 {
|
Chris@16
|
439 pimpl->edge_list.concat_back(bottom.pimpl->edge_list);
|
Chris@16
|
440 pimpl->true_second_vertex = bottom.pimpl->true_second_vertex;
|
Chris@16
|
441 pimpl->cached_second_vertex = bottom.pimpl->cached_second_vertex;
|
Chris@16
|
442 pimpl->cached_second_edge = bottom.pimpl->cached_second_edge;
|
Chris@16
|
443 }
|
Chris@16
|
444
|
Chris@16
|
445 void flip()
|
Chris@16
|
446 {
|
Chris@16
|
447 pimpl->edge_list.reverse();
|
Chris@16
|
448 std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex);
|
Chris@16
|
449 std::swap(pimpl->cached_first_vertex, pimpl->cached_second_vertex);
|
Chris@16
|
450 std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge);
|
Chris@16
|
451 }
|
Chris@16
|
452
|
Chris@16
|
453 template <typename OutputIterator>
|
Chris@16
|
454 void get_list(OutputIterator o_itr)
|
Chris@16
|
455 {
|
Chris@16
|
456 pimpl->edge_list.get_list(o_itr);
|
Chris@16
|
457 }
|
Chris@16
|
458
|
Chris@16
|
459 void reset_vertex_cache()
|
Chris@16
|
460 {
|
Chris@16
|
461 pimpl->cached_first_vertex = pimpl->true_first_vertex;
|
Chris@16
|
462 pimpl->cached_second_vertex = pimpl->true_second_vertex;
|
Chris@16
|
463 }
|
Chris@16
|
464
|
Chris@16
|
465 inline void set_first_vertex(vertex_t v)
|
Chris@16
|
466 {
|
Chris@16
|
467 pimpl->cached_first_vertex = v;
|
Chris@16
|
468 }
|
Chris@16
|
469
|
Chris@16
|
470 inline void set_second_vertex(vertex_t v)
|
Chris@16
|
471 {
|
Chris@16
|
472 pimpl->cached_second_vertex = v;
|
Chris@16
|
473 }
|
Chris@16
|
474
|
Chris@16
|
475 private:
|
Chris@16
|
476
|
Chris@16
|
477 void store_old_face_handles_dispatch(store_old_handles)
|
Chris@16
|
478 {
|
Chris@16
|
479 pimpl->old_handles.first_vertex = pimpl->true_first_vertex;
|
Chris@16
|
480 pimpl->old_handles.second_vertex = pimpl->true_second_vertex;
|
Chris@16
|
481 pimpl->old_handles.first_edge = pimpl->cached_first_edge;
|
Chris@16
|
482 pimpl->old_handles.second_edge = pimpl->cached_second_edge;
|
Chris@16
|
483 }
|
Chris@16
|
484
|
Chris@16
|
485 void store_old_face_handles_dispatch(no_old_handles) {}
|
Chris@16
|
486
|
Chris@16
|
487
|
Chris@16
|
488
|
Chris@16
|
489 boost::shared_ptr<impl_t> pimpl;
|
Chris@16
|
490
|
Chris@16
|
491 };
|
Chris@16
|
492
|
Chris@16
|
493
|
Chris@16
|
494 } /* namespace detail */ } /* namespace graph */ } /* namespace boost */
|
Chris@16
|
495
|
Chris@16
|
496
|
Chris@16
|
497 #endif //__FACE_HANDLES_HPP__
|