Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/graph/test/layout_test.cpp @ 47

Last change on this file since 47 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 11.4 KB
Line 
1// Copyright 2004 The Trustees of Indiana University.
2
3// Use, modification and distribution is subject to the Boost Software
4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7//  Authors: Douglas Gregor
8//           Andrew Lumsdaine
9#include <boost/graph/fruchterman_reingold.hpp>
10#include <boost/graph/random_layout.hpp>
11#include <boost/graph/kamada_kawai_spring_layout.hpp>
12#include <boost/graph/circle_layout.hpp>
13#include <boost/graph/adjacency_list.hpp>
14#include <boost/random/linear_congruential.hpp>
15#include <boost/test/minimal.hpp>
16#include <iostream>
17#include <boost/limits.hpp>
18#include <fstream>
19#include <string>
20using namespace boost;
21
22enum vertex_position_t { vertex_position };
23namespace boost { BOOST_INSTALL_PROPERTY(vertex, position); }
24
25struct point
26{
27  double x;
28  double y;
29};
30
31template<typename Graph, typename PositionMap>
32void print_graph_layout(const Graph& g, PositionMap position)
33{
34  typename graph_traits<Graph>::vertex_iterator vi, vi_end;
35  int xmin = 0, xmax = 0, ymin = 0, ymax = 0;
36  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
37    if ((int)position[*vi].x < xmin) xmin = (int)position[*vi].x;
38    if ((int)position[*vi].x > xmax) xmax = (int)position[*vi].x;
39    if ((int)position[*vi].y < ymin) ymin = (int)position[*vi].y;
40    if ((int)position[*vi].y > ymax) ymax = (int)position[*vi].y;
41  }
42
43  for (int y = ymin; y <= ymax; ++y) {
44    for (int x = xmin; x <= xmax; ++x) {
45      // Find vertex at this position
46      typename graph_traits<Graph>::vertices_size_type index = 0;
47      for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi, ++index) {
48        if ((int)position[*vi].x == x && (int)position[*vi].y == y)
49          break;
50      }
51
52      if (vi == vi_end) std::cout << ' ';
53      else std::cout << (char)(index + 'A');
54    }
55    std::cout << std::endl;
56  }
57}
58
59template<typename Graph, typename PositionMap>
60void dump_graph_layout(std::string name, const Graph& g, PositionMap position)
61{
62  std::ofstream out((name + ".dot").c_str());
63  out << "graph " << name << " {" << std::endl;
64
65  typename graph_traits<Graph>::vertex_iterator vi, vi_end;
66  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
67    out << "  n" << get(vertex_index, g, *vi) << "[ pos=\"" 
68        << (int)position[*vi].x + 25 << ", " << (int)position[*vi].y + 25 
69        << "\" ];\n";
70  }
71
72  typename graph_traits<Graph>::edge_iterator ei, ei_end;
73  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
74    out << "  n" << get(vertex_index, g, source(*ei, g)) << " -- n"
75        << get(vertex_index, g, target(*ei, g)) << ";\n";
76  }
77  out << "}\n";
78}
79
80template<typename Graph>
81void 
82test_circle_layout(Graph*, typename graph_traits<Graph>::vertices_size_type n)
83{
84  typedef typename graph_traits<Graph>::vertex_descriptor vertex;
85  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
86  typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
87  typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
88
89  Graph g(n);
90
91  // Initialize vertex indices
92  vertex_iterator vi = vertices(g).first;
93  for (vertices_size_type i = 0; i < n; ++i, ++vi) 
94    put(vertex_index, g, *vi, i);
95
96  circle_graph_layout(g, get(vertex_position, g), 10.0);
97
98  std::cout << "Regular polygon layout with " << n << " points.\n";
99  print_graph_layout(g, get(vertex_position, g));
100}
101
102struct simple_edge
103{
104  int first, second;
105};
106
107struct kamada_kawai_done
108{
109  kamada_kawai_done() : last_delta() {}
110
111  template<typename Graph>
112  bool operator()(double delta_p, 
113                  typename boost::graph_traits<Graph>::vertex_descriptor p,
114                  const Graph& g,
115                  bool global)
116  {
117    if (global) {
118      double diff = last_delta - delta_p;
119      if (diff < 0) diff = -diff;
120      last_delta = delta_p;
121      return diff < 0.01;
122    } else {
123      return delta_p < 0.01;
124    }
125  }
126
127  double last_delta;
128};
129
130template<typename Graph>
131void
132test_triangle(Graph*)
133{
134  typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
135  typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
136
137  Graph g;
138 
139  vertex_descriptor u = add_vertex(g); put(vertex_index, g, u, 0);
140  vertex_descriptor v = add_vertex(g); put(vertex_index, g, v, 1);
141  vertex_descriptor w = add_vertex(g); put(vertex_index, g, w, 2);
142
143  edge_descriptor e1 = add_edge(u, v, g).first; put(edge_weight, g, e1, 1.0);
144  edge_descriptor e2 = add_edge(v, w, g).first; put(edge_weight, g, e2, 1.0);
145  edge_descriptor e3 = add_edge(w, u, g).first; put(edge_weight, g, e3, 1.0);
146
147  circle_graph_layout(g, get(vertex_position, g), 25.0);
148
149  bool ok = kamada_kawai_spring_layout(g, 
150                                       get(vertex_position, g),
151                                       get(edge_weight, g),
152                                       side_length(50.0));
153  BOOST_CHECK(ok);
154
155  std::cout << "Triangle layout (Kamada-Kawai).\n";
156  print_graph_layout(g, get(vertex_position, g));
157}
158
159template<typename Graph>
160void
161test_cube(Graph*)
162{
163  enum {A, B, C, D, E, F, G, H};
164  simple_edge cube_edges[12] = {
165    {A, E}, {A, B}, {A, D}, {B, F}, {B, C}, {C, D}, {C, G}, {D, H}, 
166    {E, H}, {E, F}, {F, G}, {G, H}
167  };
168
169  Graph g(&cube_edges[0], &cube_edges[12], 8);
170 
171  typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
172  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
173
174  vertex_iterator vi, vi_end;
175  int i = 0;
176  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
177    put(vertex_index, g, *vi, i++);
178
179  edge_iterator ei, ei_end;
180  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
181    put(edge_weight, g, *ei, 1.0);
182    std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A') 
183              << ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
184              << ") ";
185  }
186  std::cerr << std::endl;
187
188  circle_graph_layout(g, get(vertex_position, g), 25.0);
189
190  bool ok = kamada_kawai_spring_layout(g, 
191                                       get(vertex_position, g),
192                                       get(edge_weight, g),
193                                       side_length(50.0),
194                                       kamada_kawai_done());
195  BOOST_CHECK(ok);
196
197  std::cout << "Cube layout (Kamada-Kawai).\n";
198  print_graph_layout(g, get(vertex_position, g));
199
200  dump_graph_layout("cube", g, get(vertex_position, g));
201
202  minstd_rand gen;
203  random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, 
204                      gen);
205
206  std::vector<point> displacements(num_vertices(g));
207  fruchterman_reingold_force_directed_layout
208    (g,
209     get(vertex_position, g),
210     50.0,
211     50.0,
212     square_distance_attractive_force(),
213     square_distance_repulsive_force(),
214     all_force_pairs(),
215     linear_cooling<double>(100),
216     make_iterator_property_map(displacements.begin(),
217                                get(vertex_index, g),
218                                point()));
219
220  std::cout << "Cube layout (Fruchterman-Reingold).\n";
221  print_graph_layout(g, get(vertex_position, g));
222
223  dump_graph_layout("cube-fr", g, get(vertex_position, g));
224}
225
226template<typename Graph>
227void
228test_triangular(Graph*)
229{
230  enum {A, B, C, D, E, F, G, H, I, J};
231  simple_edge triangular_edges[18] = {
232    {A, B}, {A, C}, {B, C}, {B, D}, {B, E}, {C, E}, {C, F}, {D, E}, {D, G},
233    {D, H}, {E, F}, {E, H}, {E, I}, {F, I}, {F, J}, {G, H}, {H, I}, {I, J}
234  };
235
236  Graph g(&triangular_edges[0], &triangular_edges[18], 10);
237 
238  typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
239  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
240
241  vertex_iterator vi, vi_end;
242  int i = 0;
243  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
244    put(vertex_index, g, *vi, i++);
245
246  edge_iterator ei, ei_end;
247  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
248    put(edge_weight, g, *ei, 1.0);
249    std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A') 
250              << ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
251              << ") ";
252  }
253  std::cerr << std::endl;
254
255  circle_graph_layout(g, get(vertex_position, g), 25.0);
256
257  bool ok = kamada_kawai_spring_layout(g, 
258                                       get(vertex_position, g),
259                                       get(edge_weight, g),
260                                       side_length(50.0),
261                                       kamada_kawai_done());
262  BOOST_CHECK(ok);
263
264  std::cout << "Triangular layout (Kamada-Kawai).\n";
265  print_graph_layout(g, get(vertex_position, g));
266
267  dump_graph_layout("triangular-kk", g, get(vertex_position, g));
268
269  minstd_rand gen;
270  random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, 
271                      gen);
272
273  dump_graph_layout("random", g, get(vertex_position, g));
274
275  std::vector<point> displacements(num_vertices(g));
276  fruchterman_reingold_force_directed_layout
277    (g,
278     get(vertex_position, g),
279     50.0,
280     50.0,
281     attractive_force(square_distance_attractive_force()).
282     cooling(linear_cooling<double>(100)));
283
284  std::cout << "Triangular layout (Fruchterman-Reingold).\n";
285  print_graph_layout(g, get(vertex_position, g));
286
287  dump_graph_layout("triangular-fr", g, get(vertex_position, g));
288}
289
290template<typename Graph>
291void
292test_disconnected(Graph*)
293{
294  enum {A, B, C, D, E, F, G, H};
295  simple_edge triangular_edges[13] = {
296    {A, B}, {B, C}, {C, A}, 
297    {D, E}, {E, F}, {F, G}, {G, H}, {H, D},
298    {D, F}, {F, H}, {H, E}, {E, G}, {G, D}
299  };
300
301  Graph g(&triangular_edges[0], &triangular_edges[13], 8);
302 
303  typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
304  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
305
306  vertex_iterator vi, vi_end;
307  int i = 0;
308  for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
309    put(vertex_index, g, *vi, i++);
310
311  edge_iterator ei, ei_end;
312  for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
313    put(edge_weight, g, *ei, 1.0);
314    std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A') 
315              << ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
316              << ") ";
317  }
318  std::cerr << std::endl;
319
320  circle_graph_layout(g, get(vertex_position, g), 25.0);
321
322  bool ok = kamada_kawai_spring_layout(g, 
323                                       get(vertex_position, g),
324                                       get(edge_weight, g),
325                                       side_length(50.0),
326                                       kamada_kawai_done());
327  BOOST_CHECK(!ok);
328
329  minstd_rand gen;
330  random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0, 
331                      gen);
332
333  std::vector<point> displacements(num_vertices(g));
334  fruchterman_reingold_force_directed_layout
335    (g,
336     get(vertex_position, g),
337     50.0,
338     50.0,
339     attractive_force(square_distance_attractive_force()).
340     cooling(linear_cooling<double>(50)));
341
342  std::cout << "Disconnected layout (Fruchterman-Reingold).\n";
343  print_graph_layout(g, get(vertex_position, g));
344
345  dump_graph_layout("disconnected-fr", g, get(vertex_position, g));
346}
347
348int test_main(int, char*[])
349{
350  typedef adjacency_list<listS, listS, undirectedS, 
351                         // Vertex properties
352                         property<vertex_index_t, int,
353                         property<vertex_position_t, point> >,
354                         // Edge properties
355                         property<edge_weight_t, double> > Graph;
356
357  test_circle_layout((Graph*)0, 5);
358  test_cube((Graph*)0);
359  test_triangular((Graph*)0);
360  test_disconnected((Graph*)0);
361  return 0;
362}
Note: See TracBrowser for help on using the repository browser.