face_handles.hpp 16 KB

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