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