c++ - 如何在显示多个属性的 graphviz 中打印图形

标签 c++ boost graphviz boost-graph

我的问题基于:How to print a graph with a single property displayed

我正在使用捆绑属性:

 typedef struct vert{
   std::string name;
 };

 typedef struct edge{
   int capacity;
   int weight;
 }; 

typedef adjacency_list<listS, vecS, undirectedS, vert, edge> Graph;
Graph g;
vector<int,int> ele;

我在应该创建边缘的循环中调用了以下内容:

  edge prop;
  prop.weight = 5;
  prop.capacity = 4;
  add_edge(ele.first,ele.second, prop, g);

此段用于将图形打印为点格式。

ofstream dot("graph.dot");
write_graphviz(dot, g, 
  boost::make_label_writer(boost::get(&vert::name, g)),
  boost::make_label_writer(boost::get(&edge::weight, g)),
  boost::make_label_writer(boost::get(&edge::capacity, g)));

错误是:

/usr/include/boost/graph/graphviz.hpp: In function ‘void boost::write_graphviz(std::ostream&, const Graph&, VertexPropertiesWriter, EdgePropertiesWriter, GraphPropertiesWriter, VertexID) [with Graph = boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, VertexPropertiesWriter = boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, long unsigned int, vert, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, EdgePropertiesWriter = boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, boost::detail::edge_desc_impl<boost::undirected_tag, long unsigned int>, edge, int> >, GraphPropertiesWriter = boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, boost::detail::edge_desc_impl<boost::undirected_tag, long unsigned int>, edge, int> >, VertexID = boost::vec_adj_list_vertex_id_map<boost::property<boost::vertex_bundle_t, vert, boost::no_property>, long unsigned int>]’:
/usr/include/boost/graph/graphviz.hpp:260:   instantiated from ‘void boost::write_graphviz(std::ostream&, const Graph&, VertexPropertiesWriter, EdgePropertiesWriter, GraphPropertiesWriter) [with Graph = Graph, VertexPropertiesWriter = boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, long unsigned int, vert, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, EdgePropertiesWriter = boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, boost::detail::edge_desc_impl<boost::undirected_tag, long unsigned int>, edge, int> >, GraphPropertiesWriter = boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, boost::detail::edge_desc_impl<boost::undirected_tag, long unsigned int>, edge, int> >]’
file_format.cc:194:   instantiated from here
/usr/include/boost/graph/graphviz.hpp:236: error: no match for call to ‘(boost::label_writer<boost::bundle_property_map<boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, vert, edge, boost::no_property, boost::listS>, boost::detail::edge_desc_impl<boost::undirected_tag, long unsigned int>, edge, int> >) (std::basic_ostream<char, std::char_traits<char> >&)’

这对我来说很奇怪,因为它有效:

write_graphviz(dot, g,
  boost::make_label_writer(boost::get(&vert_info::name, g)));

并输出以下内容:

graph G {
0[label="0"];
1[label="1"];
2[label="2"];
3[label="3"];
4[label="4"];
5[label="5"];
6[label="6"];
7[label="7"];
8[label="8"];
9[label=""];  // this is another problem that I will have to fix but beside the point
0--9 ;
0--5 ;
0--2 ;
0--1 ;
...
...
}

我的目标是标记每个节点,并标记每条边的容量和权重。

最佳答案

你可以找到here write_graphviz 的所有重载列表。出现第一个错误的原因是您尝试使用的重载在其第五个参数中需要图形属性编写器。

辅助函数 make_label_writer 只是创建一个属性编写器,它将图形的顶点或边的单个属性分配给名为 label 的 graphviz 顶点或边属性.

为了实现您想要的效果,您需要创建自定义 property writer其中您将每个边缘属性分配给 graphviz attributes你需要。我个人会使用 weight->labelcapacity->taillabelheadlabel .

template <class WeightMap,class CapacityMap>
class edge_writer {
public:
  edge_writer(WeightMap w, CapacityMap c) : wm(w),cm(c) {}
  template <class Edge>
  void operator()(ostream &out, const Edge& e) const {
    out << "[label=\"" << wm[e] << "\", taillabel=\"" << cm[e] << "\"]";
  }
private:
  WeightMap wm;
  CapacityMap cm;
};

template <class WeightMap, class CapacityMap>
inline edge_writer<WeightMap,CapacityMap> 
make_edge_writer(WeightMap w,CapacityMap c) {
  return edge_writer<WeightMap,CapacityMap>(w,c);
}

最后,您的 write_graphviz 调用将是:

ofstream dot("graph.dot");
write_graphviz(dot, g, 
  boost::make_label_writer(boost::get(&vert::name, g)),
  make_edge_writer(boost::get(&edge::weight,g),boost::get(&edge::capacity,g)));

关于c++ - 如何在显示多个属性的 graphviz 中打印图形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11369115/

相关文章:

c++ - boost 测试

c++ - 多维数组实现

c++ - 为什么 boost::locale::to_title 没有返回预期的输出?

graphviz - 使用 gvpr 从 Graphviz 中提取图层和子图簇

r - 如何在 R 包中指定节点的垂直对齐方式 "DiagrammeR"

c++ - 对于需要生成一些图形的 C++ 项目,推荐使用哪个 graphviz 库 API?

c++ - C++11 中提出的无限制 union 是什么?

c++ - 对于 malloc() 失败是否有等效的 set_new_handler()?

c++ - MathGL BoxPlot 的数据格式

C++ Infix to Postfix 适用于某些输入但不适用于其他输入?