chrobak_payne_drawing.hpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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 __CHROBAK_PAYNE_DRAWING_HPP__
  9. #define __CHROBAK_PAYNE_DRAWING_HPP__
  10. #include <vector>
  11. #include <list>
  12. #include <stack>
  13. #include <boost/config.hpp>
  14. #include <boost/graph/graph_traits.hpp>
  15. #include <boost/property_map/property_map.hpp>
  16. namespace boost
  17. {
  18. namespace graph { namespace detail
  19. {
  20. template<typename Graph,
  21. typename VertexToVertexMap,
  22. typename VertexTo1DCoordMap>
  23. void accumulate_offsets(typename graph_traits<Graph>::vertex_descriptor v,
  24. std::size_t offset,
  25. const Graph& g,
  26. VertexTo1DCoordMap x,
  27. VertexTo1DCoordMap delta_x,
  28. VertexToVertexMap left,
  29. VertexToVertexMap right)
  30. {
  31. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  32. // Suggestion of explicit stack from Aaron Windsor to avoid system stack
  33. // overflows.
  34. typedef std::pair<vertex_descriptor, std::size_t> stack_entry;
  35. std::stack<stack_entry> st;
  36. st.push(stack_entry(v, offset));
  37. while (!st.empty()) {
  38. vertex_descriptor v = st.top().first;
  39. std::size_t offset = st.top().second;
  40. st.pop();
  41. if (v != graph_traits<Graph>::null_vertex()) {
  42. x[v] += delta_x[v] + offset;
  43. st.push(stack_entry(left[v], x[v]));
  44. st.push(stack_entry(right[v], x[v]));
  45. }
  46. }
  47. }
  48. } /*namespace detail*/ } /*namespace graph*/
  49. template<typename Graph,
  50. typename PlanarEmbedding,
  51. typename ForwardIterator,
  52. typename GridPositionMap,
  53. typename VertexIndexMap>
  54. void chrobak_payne_straight_line_drawing(const Graph& g,
  55. PlanarEmbedding embedding,
  56. ForwardIterator ordering_begin,
  57. ForwardIterator ordering_end,
  58. GridPositionMap drawing,
  59. VertexIndexMap vm
  60. )
  61. {
  62. typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
  63. typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator_t;
  64. typedef typename PlanarEmbedding::value_type::const_iterator
  65. edge_permutation_iterator_t;
  66. typedef typename graph_traits<Graph>::vertices_size_type v_size_t;
  67. typedef std::vector<vertex_t> vertex_vector_t;
  68. typedef std::vector<v_size_t> vsize_vector_t;
  69. typedef std::vector<bool> bool_vector_t;
  70. typedef boost::iterator_property_map
  71. <typename vertex_vector_t::iterator, VertexIndexMap>
  72. vertex_to_vertex_map_t;
  73. typedef boost::iterator_property_map
  74. <typename vsize_vector_t::iterator, VertexIndexMap>
  75. vertex_to_vsize_map_t;
  76. typedef boost::iterator_property_map
  77. <typename bool_vector_t::iterator, VertexIndexMap>
  78. vertex_to_bool_map_t;
  79. vertex_vector_t left_vector(num_vertices(g),
  80. graph_traits<Graph>::null_vertex()
  81. );
  82. vertex_vector_t right_vector(num_vertices(g),
  83. graph_traits<Graph>::null_vertex()
  84. );
  85. vsize_vector_t seen_as_right_vector(num_vertices(g), 0);
  86. vsize_vector_t seen_vector(num_vertices(g), 0);
  87. vsize_vector_t delta_x_vector(num_vertices(g),0);
  88. vsize_vector_t y_vector(num_vertices(g));
  89. vsize_vector_t x_vector(num_vertices(g),0);
  90. bool_vector_t installed_vector(num_vertices(g),false);
  91. vertex_to_vertex_map_t left(left_vector.begin(), vm);
  92. vertex_to_vertex_map_t right(right_vector.begin(), vm);
  93. vertex_to_vsize_map_t seen_as_right(seen_as_right_vector.begin(), vm);
  94. vertex_to_vsize_map_t seen(seen_vector.begin(), vm);
  95. vertex_to_vsize_map_t delta_x(delta_x_vector.begin(), vm);
  96. vertex_to_vsize_map_t y(y_vector.begin(), vm);
  97. vertex_to_vsize_map_t x(x_vector.begin(), vm);
  98. vertex_to_bool_map_t installed(installed_vector.begin(), vm);
  99. v_size_t timestamp = 1;
  100. vertex_vector_t installed_neighbors;
  101. ForwardIterator itr = ordering_begin;
  102. vertex_t v1 = *itr; ++itr;
  103. vertex_t v2 = *itr; ++itr;
  104. vertex_t v3 = *itr; ++itr;
  105. delta_x[v2] = 1;
  106. delta_x[v3] = 1;
  107. y[v1] = 0;
  108. y[v2] = 0;
  109. y[v3] = 1;
  110. right[v1] = v3;
  111. right[v3] = v2;
  112. installed[v1] = installed[v2] = installed[v3] = true;
  113. for(ForwardIterator itr_end = ordering_end; itr != itr_end; ++itr)
  114. {
  115. vertex_t v = *itr;
  116. // First, find the leftmost and rightmost neighbor of v on the outer
  117. // cycle of the embedding.
  118. // Note: since we're moving clockwise through the edges adjacent to v,
  119. // we're actually moving from right to left among v's neighbors on the
  120. // outer face (since v will be installed above them all) looking for
  121. // the leftmost and rightmost installed neigbhors
  122. vertex_t leftmost = graph_traits<Graph>::null_vertex();
  123. vertex_t rightmost = graph_traits<Graph>::null_vertex();
  124. installed_neighbors.clear();
  125. vertex_t prev_vertex = graph_traits<Graph>::null_vertex();
  126. edge_permutation_iterator_t pi, pi_end;
  127. pi_end = embedding[v].end();
  128. for(pi = embedding[v].begin(); pi != pi_end; ++pi)
  129. {
  130. vertex_t curr_vertex = source(*pi,g) == v ?
  131. target(*pi,g) : source(*pi,g);
  132. // Skip any self-loops or parallel edges
  133. if (curr_vertex == v || curr_vertex == prev_vertex)
  134. continue;
  135. if (installed[curr_vertex])
  136. {
  137. seen[curr_vertex] = timestamp;
  138. if (right[curr_vertex] != graph_traits<Graph>::null_vertex())
  139. {
  140. seen_as_right[right[curr_vertex]] = timestamp;
  141. }
  142. installed_neighbors.push_back(curr_vertex);
  143. }
  144. prev_vertex = curr_vertex;
  145. }
  146. typename vertex_vector_t::iterator vi, vi_end;
  147. vi_end = installed_neighbors.end();
  148. for(vi = installed_neighbors.begin(); vi != vi_end; ++vi)
  149. {
  150. if (right[*vi] == graph_traits<Graph>::null_vertex() ||
  151. seen[right[*vi]] != timestamp
  152. )
  153. rightmost = *vi;
  154. if (seen_as_right[*vi] != timestamp)
  155. leftmost = *vi;
  156. }
  157. ++timestamp;
  158. //stretch gaps
  159. ++delta_x[right[leftmost]];
  160. ++delta_x[rightmost];
  161. //adjust offsets
  162. std::size_t delta_p_q = 0;
  163. vertex_t stopping_vertex = right[rightmost];
  164. for(vertex_t temp = right[leftmost]; temp != stopping_vertex;
  165. temp = right[temp]
  166. )
  167. {
  168. delta_p_q += delta_x[temp];
  169. }
  170. delta_x[v] = ((y[rightmost] + delta_p_q) - y[leftmost])/2;
  171. y[v] = y[leftmost] + delta_x[v];
  172. delta_x[rightmost] = delta_p_q - delta_x[v];
  173. bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost;
  174. if (!leftmost_and_rightmost_adjacent)
  175. delta_x[right[leftmost]] -= delta_x[v];
  176. //install v
  177. if (!leftmost_and_rightmost_adjacent)
  178. {
  179. left[v] = right[leftmost];
  180. vertex_t next_to_rightmost;
  181. for(vertex_t temp = leftmost; temp != rightmost;
  182. temp = right[temp]
  183. )
  184. {
  185. next_to_rightmost = temp;
  186. }
  187. right[next_to_rightmost] = graph_traits<Graph>::null_vertex();
  188. }
  189. else
  190. {
  191. left[v] = graph_traits<Graph>::null_vertex();
  192. }
  193. right[leftmost] = v;
  194. right[v] = rightmost;
  195. installed[v] = true;
  196. }
  197. graph::detail::accumulate_offsets
  198. (*ordering_begin,0,g,x,delta_x,left,right);
  199. vertex_iterator_t vi, vi_end;
  200. for(boost::tie(vi,vi_end) = vertices(g); vi != vi_end; ++vi)
  201. {
  202. vertex_t v(*vi);
  203. drawing[v].x = x[v];
  204. drawing[v].y = y[v];
  205. }
  206. }
  207. template<typename Graph,
  208. typename PlanarEmbedding,
  209. typename ForwardIterator,
  210. typename GridPositionMap>
  211. inline void chrobak_payne_straight_line_drawing(const Graph& g,
  212. PlanarEmbedding embedding,
  213. ForwardIterator ord_begin,
  214. ForwardIterator ord_end,
  215. GridPositionMap drawing
  216. )
  217. {
  218. chrobak_payne_straight_line_drawing(g,
  219. embedding,
  220. ord_begin,
  221. ord_end,
  222. drawing,
  223. get(vertex_index,g)
  224. );
  225. }
  226. } // namespace boost
  227. #endif //__CHROBAK_PAYNE_DRAWING_HPP__