如何通过boost :: read_graphviz保持图形的所有属性?

时间:2015-07-24 22:22:44

标签: graphviz

假设您想要将.dot图形读入boost,其中可能存在您无法识别的属性。很容易忽略它们(通过将ignore_other_properties传递给dynamic_properties构造函数)但是如果你想要将所有属性添加到dynamic_properties呢?

以下代码演示了此问题。 handle_custom_properties是ignore_other_properties的副本,代码将编译/运行,报告" 3个顶点,2个边缘。"需要添加到handle_custom_properties的内容,以便在返回时,dp将包含一个属性" label"并且节点A将具有值" x"对于标签属性?

#include <iostream>
#include <string>

#include <boost/graph/graphviz.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/diagnostic_information.hpp>

struct vertex_p {
    std::string node_id;
};

typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::undirectedS, vertex_p> graph_t;

boost::shared_ptr<boost::dynamic_property_map>
handle_custom_properties(const std::string& s,
    const boost::any& k,
    const boost::any& v) {

    // What goes in here to add dynamic property map for property "s" which key-value pair <k,v>?

    // What ignore_other_properties does
    return boost::shared_ptr<boost::dynamic_property_map>();
}

int main() {
    std::string str(R"(graph {
    A [ label="x" ]
    B
    C

    A -- B
    A -- C
}
)");

    try {
        graph_t g;
        boost::dynamic_properties dp{handle_custom_properties};
        dp.property("node_id", get(&vertex_p::node_id, g));

        if (boost::read_graphviz(str, g, dp)) {
            std::cout << "read_graphviz returned success" << std::endl;
            std::cout << "graph stats:" << std::endl;
            std::cout << "  " << g.m_vertices.size() << " vertices" << std::endl;
            std::cout << "  " << g.m_edges.size() << " edges" << std::endl;

        }
        else {
            std::cout << "read_graphviz returned failure" << std::endl;
        }
    }
    catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }
    catch (boost::exception& e) {
        std::cerr << boost::diagnostic_information(e) << std::endl;
    }
}

1 个答案:

答案 0 :(得分:1)

我无法找到现有的类来解决这个问题,但根据std :: map实现了dynamic_property_map:

template<typename TKey, typename TValue>
class dynamic_property_map_impl : public boost::dynamic_property_map {
    std::map<TKey, TValue>  map_;

public:
    boost::any get(const boost::any& key) override { return map_[boost::any_cast<TKey>(key)]; }
    std::string get_string(const boost::any& key) override { std::ostringstream s; s << map_[boost::any_cast<TKey>(key)]; return s.str(); }
    void put(const boost::any& key, const boost::any& value) override { map_[boost::any_cast<TKey>(key)] = boost::any_cast<TValue>(value); }
    const std::type_info& key() const override { return typeid(TKey); }
    const std::type_info& value() const override { return typeid(TValue); }
};

boost::shared_ptr<boost::dynamic_property_map>
handle_custom_properties(const std::string&,
    const boost::any&,
    const boost::any&) {

    return boost::make_shared<dynamic_property_map_impl<unsigned, std::string>>();
}

更改图表并打印出属性会显示所有属性贴图已添加:

    std::string str(R"(graph {
    A [ label="x", stuff="y" ]
    B
    C [ happy="yes" ]

    A -- B
    A -- C
}
)");

...
           std::cout << "properties:" << std::endl;
           for (const auto& p : dp) {
                std::cout << "  " << p.first << std::endl;
           }

输出

read_graphviz returned success
graph stats:
  3 vertices
  2 edges
properties:
  happy
  label
  node_id
  stuff