簡體   English   中英

Boost::Graph:如何使用自定義 Vertex 類導入 graphviz

[英]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 Vertexp字段? 我嘗試使用boost::dynamic_propertiesdp.property("p", boost::get(&Vertex::p, g)); 但它不起作用,因為類型不匹配(可能是因為用於write_graphviz )。

是的,你要求的是英雄。 dynamic_properties工具實際上假設您將訪問對象中的左值屬性,而不是轉換后的值。

我以前遇到過這個:

解決它

該庫是完全通用的。 Property Maps 是高度通用的並且不假設左值,這可以從區分ReadWritePropertyMapLvaluePropertyMap概念層次結構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);
    };
}

我將根據您預期的文本序列化格式快速填寫getput的一些合理實現。 我不會解釋細節,你可以用任何你認為合適的方式來寫:

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/xMKhz9G8ehttps://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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM