When loading a .dot file I want to read all properties without defining them before.
In the code snippet below I don't want to specify to read weight
for example. Other datasets have other properties and I don't want to keep adding those as variables to structs.
boost::dynamic_properties dp;
dp.property( "node_id", get( &Vertex::name, _graph.m_graph ) );
//dp.property("weight", get(&Edge::weight, _graph.m_graph));
boost::read_graphviz( file, _graph.m_graph, dp );
I found an other answer doing something similar, but I do not get it to work for my case. In my dataset the properties are on the edges and they are are numbers like [weight=1]
. I tried editing this line:
return boost::make_shared<dynamic_property_map_impl<unsigned int, std::string>>();
with different template types but I only get node_id:
return boost::make_shared<dynamic_property_map_impl<std::string, std::string>>();
return boost::make_shared<dynamic_property_map_impl<std::string, float>>();
The full code snippets looks as follows:
#include <boost/graph/graphviz.hpp>
#include <boost/program_options.hpp>
#include <boost/exception/exception.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include "read_graphviz_new.cpp"
template<typename TKey, typename TValue>
class dynamic_property_map_impl : public boost::dynamic_property_map {
std::map<TKey, TValue> m_map;
public:
boost::any get(const boost::any& key) override { return m_map[boost::any_cast<TKey>(key)]; }
std::string get_string(const boost::any& key) override { std::ostringstream s; s << m_map[boost::any_cast<TKey>(key)]; return s.str(); }
void put(const boost::any& key, const boost::any& value) override { m_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 int, std::string>>();
}
struct Vertex
{
std::string name;
};
struct Edge
{
float weight = 1.f;
};
typedef boost::property<boost::graph_name_t, std::string> graph_p;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Vertex, Edge, graph_p> graph_u;
void Graph::Load(std::string filepath) {
std::ifstream file(filepath);
graph_u graph;
try {
boost::dynamic_properties dp(handle_custom_properties);
dp.property("node_id", get(&Vertex::name, graph));
//dp.property("weight", get(&Edge::weight, graph));
boost::read_graphviz(file, graph, dp);
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
}
catch (boost::exception& e) {
std::cerr << boost::diagnostic_information(e) << std::endl;
}
}
My dataset looks as follows:
strict graph {
1;
2;
3;
...
1 -- 2 [weight=1];
2 -- 3 [weight=8];
...
}