fr_layout.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Copyright 2004 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Authors: Douglas Gregor
  6. // Andrew Lumsdaine
  7. #include <boost/graph/fruchterman_reingold.hpp>
  8. #include <boost/graph/random_layout.hpp>
  9. #include <boost/graph/adjacency_list.hpp>
  10. #include <boost/graph/topology.hpp>
  11. #include <boost/lexical_cast.hpp>
  12. #include <string>
  13. #include <iostream>
  14. #include <map>
  15. #include <vector>
  16. #include <boost/random/linear_congruential.hpp>
  17. #include <boost/progress.hpp>
  18. #include <boost/shared_ptr.hpp>
  19. using namespace boost;
  20. void usage()
  21. {
  22. std::cerr << "Usage: fr_layout [options] <width> <height>\n"
  23. << "Arguments:\n"
  24. << "\t<width>\tWidth of the display area (floating point)\n"
  25. << "\t<Height>\tHeight of the display area (floating point)\n\n"
  26. << "Options:\n"
  27. << "\t--iterations n\tNumber of iterations to execute.\n"
  28. << "\t\t\tThe default value is 100.\n"
  29. << "Input:\n"
  30. << " Input is read from standard input as a list of edges, one per line.\n"
  31. << " Each edge contains two string labels (the endpoints) separated by a space.\n\n"
  32. << "Output:\n"
  33. << " Vertices and their positions are written to standard output with the label,\n x-position, and y-position of a vertex on each line, separated by spaces.\n";
  34. }
  35. typedef boost::rectangle_topology<> topology_type;
  36. typedef topology_type::point_type point_type;
  37. typedef adjacency_list<listS, vecS, undirectedS,
  38. property<vertex_name_t, std::string> > Graph;
  39. typedef graph_traits<Graph>::vertex_descriptor Vertex;
  40. typedef std::map<std::string, Vertex> NameToVertex;
  41. Vertex get_vertex(const std::string& name, Graph& g, NameToVertex& names)
  42. {
  43. NameToVertex::iterator i = names.find(name);
  44. if (i == names.end())
  45. i = names.insert(std::make_pair(name, add_vertex(name, g))).first;
  46. return i->second;
  47. }
  48. class progress_cooling : public linear_cooling<double>
  49. {
  50. typedef linear_cooling<double> inherited;
  51. public:
  52. explicit progress_cooling(std::size_t iterations) : inherited(iterations)
  53. {
  54. display.reset(new progress_display(iterations + 1, std::cerr));
  55. }
  56. double operator()()
  57. {
  58. ++(*display);
  59. return inherited::operator()();
  60. }
  61. private:
  62. shared_ptr<boost::progress_display> display;
  63. };
  64. int main(int argc, char* argv[])
  65. {
  66. int iterations = 100;
  67. if (argc < 3) { usage(); return -1; }
  68. double width = 0;
  69. double height = 0;
  70. for (int arg_idx = 1; arg_idx < argc; ++arg_idx) {
  71. std::string arg = argv[arg_idx];
  72. if (arg == "--iterations") {
  73. ++arg_idx;
  74. if (arg_idx >= argc) { usage(); return -1; }
  75. iterations = lexical_cast<int>(argv[arg_idx]);
  76. } else {
  77. if (width == 0.0) width = lexical_cast<double>(arg);
  78. else if (height == 0.0) height = lexical_cast<double>(arg);
  79. else {
  80. usage();
  81. return -1;
  82. }
  83. }
  84. }
  85. if (width == 0.0 || height == 0.0) {
  86. usage();
  87. return -1;
  88. }
  89. Graph g;
  90. NameToVertex names;
  91. std::string source, target;
  92. while (std::cin >> source >> target) {
  93. add_edge(get_vertex(source, g, names), get_vertex(target, g, names), g);
  94. }
  95. typedef std::vector<point_type> PositionVec;
  96. PositionVec position_vec(num_vertices(g));
  97. typedef iterator_property_map<PositionVec::iterator,
  98. property_map<Graph, vertex_index_t>::type>
  99. PositionMap;
  100. PositionMap position(position_vec.begin(), get(vertex_index, g));
  101. minstd_rand gen;
  102. topology_type topo(gen, -width/2, -height/2, width/2, height/2);
  103. random_graph_layout(g, position, topo);
  104. fruchterman_reingold_force_directed_layout
  105. (g, position, topo,
  106. cooling(progress_cooling(iterations)));
  107. graph_traits<Graph>::vertex_iterator vi, vi_end;
  108. for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
  109. std::cout << get(vertex_name, g, *vi) << '\t'
  110. << position[*vi][0] << '\t' << position[*vi][1] << std::endl;
  111. }
  112. return 0;
  113. }