[英]Boost::Graph: how to import graphviz with custom Vertex class
我有這個graphviz輸入:
graph G {
0[p="(30, 3, 2)"];
1[p="(29, 3, 2)"];
2[p="(30, 2, 2)"];
3[p="(30, 3, 3)"];
4[p="(30, 2, 3)"];
5[p="(29, 3, 3)"];
6[p="(29, 2, 3)"];
0--1;
2--0;
3--4;
5--3;
6--5;
5--1;
3--0;
4--6;
2--4;
}
類型是:
struct Vertex
{
glm::vec3 p = {};
// ...
};
typedef
boost::adjacency_list<
boost::setS,
boost::vecS,
boost::undirectedS,
Vertex,
Edge>
Graph;
如何使用boost::read_graphviz
並將其設置為正確地將 graphviz 中的p
屬性調整為 struct Vertex
的p
字段? 我嘗試使用boost::dynamic_properties
和dp.property("p", boost::get(&Vertex::p, g));
但它不起作用,因為類型不匹配(可能是因為用於write_graphviz
)。
是的,你要求的是英雄。 dynamic_properties
工具實際上假設您將訪問對象中的左值屬性,而不是轉換后的值。
我以前遇到過這個:
dynamic_properties
答案中搜索您可能會找到更多位置該庫是完全通用的。 Property Maps 是高度通用的並且不假設左值,這可以從區分ReadWritePropertyMap
和LvaluePropertyMap
的概念層次結構中LvaluePropertyMap
。
因此,您實際上可以“僅”編寫自己的屬性映射適配器:
namespace Adapt {
template <typename Prop> struct Vec3 {
Prop inner;
Vec3(Prop map) : inner(map) { }
// traits
using value_type = std::string;
using reference = std::string;
using key_type = typename boost::property_traits<Prop>::key_type;
using category = boost::read_write_property_map_tag;
friend std::string get(Vec3 adapt, key_type const& key);
friend void put(Vec3 adapt, key_type const& key, value_type const& value);
};
}
我將根據您預期的文本序列化格式快速填寫get
和put
的一些合理實現。 我不會解釋細節,你可以用任何你認為合適的方式來寫:
friend std::string get(Vec3 adapt, key_type const& key) {
auto const& v = get(adapt.inner, key);
std::ostringstream oss;
oss << "(" << v.x << "," << v.y << "," << v.z << ")";
return oss.str();
}
friend void put(Vec3 adapt, key_type const& key, std::string const& value) {
using namespace boost::spirit::x3;
float x,y,z;
auto attr = std::tie(x,y,z);
phrase_parse( //
begin(value), end(value),
'(' > double_ > ',' > double_ > ',' > double_ > ')' > eoi,
space, attr);
put(adapt.inner, key, glm::vec3{x,y,z});
}
現在您可以使用調整后的屬性映射:
Graph g;
auto id = boost::get(&Vertex::id, g);
auto p = Adapt::Vec3{boost::get(&Vertex::p, g)};
boost::dynamic_properties dp;
dp.property("node_id", id);
dp.property("p", p);
如果我們來回圖:
{
std::ifstream ifs("input.txt", std::ios::binary);
boost::read_graphviz(ifs, g, dp);
}
boost::write_graphviz_dp(std::cout, g, dp);
我們可以看到輸入被保留了。 可悲的是不在線的編譯器可以支持升壓和GLM在寫作的時候,所以你必須要運行示例自己(見https://godbolt.org/z/xMKhz9G8e , https://wandbox.org/permlink/ RkulvhWxcRnl1RbC等)。
為此目的的完整列表:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <glm/glm.hpp>
#include <iostream>
#include <iomanip>
struct Vertex {
glm::vec3 p = {};
int id;
};
struct Edge { };
using Graph = boost::adjacency_list<boost::setS, boost::vecS,
boost::undirectedS, Vertex, Edge>;
using VD = Graph::vertex_descriptor;
using ED = Graph::edge_descriptor;
namespace Adapt {
template <typename Prop> struct Vec3 {
Prop inner;
Vec3(Prop map) : inner(map) { }
// traits
using value_type = std::string;
using reference = std::string;
using key_type = typename boost::property_traits<Prop>::key_type;
using category = boost::read_write_property_map_tag;
friend std::string get(Vec3 adapt, key_type const& key) {
auto const& v = get(adapt.inner, key);
std::ostringstream oss;
oss << "(" << v.x << "," << v.y << "," << v.z << ")";
return oss.str();
}
friend void put(Vec3 adapt, key_type const& key, std::string const& value) {
using namespace boost::spirit::x3;
float x,y,z;
auto attr = std::tie(x,y,z);
phrase_parse( //
begin(value), end(value),
'(' > double_ > ',' > double_ > ',' > double_ > ')' > eoi,
space, attr);
put(adapt.inner, key, glm::vec3{x,y,z});
}
};
}
int main()
{
Graph g;
auto id = boost::get(&Vertex::id, g);
auto p = Adapt::Vec3{boost::get(&Vertex::p, g)};
boost::dynamic_properties dp;
dp.property("node_id", id);
dp.property("p", p);
{
std::istringstream iss(R"~(
graph G {
0[p="(30, 3, 2)"]; 1[p="(29, 3, 2)"]; 2[p="(30, 2, 2)"]; 3[p="(30, 3, 3)"];
4[p="(30, 2, 3)"]; 5[p="(29, 3, 3)"]; 6[p="(29, 2, 3)"];
0--1; 2--0; 3--4; 5--3; 6--5; 5--1; 3--0; 4--6; 2--4; })~");
boost::read_graphviz(iss, g, dp);
}
boost::write_graphviz_dp(std::cout, g, dp);
}
印刷
graph G {
0 [p="(30,3,2)"];
1 [p="(29,3,2)"];
2 [p="(30,2,2)"];
3 [p="(30,3,3)"];
4 [p="(30,2,3)"];
5 [p="(29,3,3)"];
6 [p="(29,2,3)"];
0--1 ;
2--0 ;
3--4 ;
5--3 ;
6--5 ;
5--1 ;
3--0 ;
4--6 ;
2--4 ;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.