sl@0: //======================================================================= sl@0: // Copyright 2001 University of Notre Dame. sl@0: // Copyright 2003 Jeremy Siek sl@0: // Authors: Lie-Quan Lee and Jeremy Siek sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: //======================================================================= sl@0: #ifndef BOOST_GRAPHVIZ_HPP sl@0: #define BOOST_GRAPHVIZ_HPP sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include // for FILE sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #ifdef BOOST_HAS_DECLSPEC sl@0: # if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_GRAPH_DYN_LINK) sl@0: # ifdef BOOST_GRAPH_SOURCE sl@0: # define BOOST_GRAPH_DECL __declspec(dllexport) sl@0: # else sl@0: # define BOOST_GRAPH_DECL __declspec(dllimport) sl@0: # endif // BOOST_GRAPH_SOURCE sl@0: # endif // DYN_LINK sl@0: #endif // BOOST_HAS_DECLSPEC sl@0: sl@0: #ifndef BOOST_GRAPH_DECL sl@0: # define BOOST_GRAPH_DECL sl@0: #endif sl@0: sl@0: namespace boost { sl@0: sl@0: template sl@0: struct graphviz_io_traits { sl@0: static std::string name() { sl@0: return "digraph"; sl@0: } sl@0: static std::string delimiter() { sl@0: return "->"; sl@0: } }; sl@0: sl@0: template <> sl@0: struct graphviz_io_traits { sl@0: static std::string name() { sl@0: return "graph"; sl@0: } sl@0: static std::string delimiter() { sl@0: return "--"; sl@0: } sl@0: }; sl@0: sl@0: struct default_writer { sl@0: void operator()(std::ostream&) const { sl@0: } sl@0: template sl@0: void operator()(std::ostream&, const VorE&) const { sl@0: } sl@0: }; sl@0: sl@0: template sl@0: class label_writer { sl@0: public: sl@0: label_writer(Name _name) : name(_name) {} sl@0: template sl@0: void operator()(std::ostream& out, const VertexOrEdge& v) const { sl@0: out << "[label=\"" << get(name, v) << "\"]"; sl@0: } sl@0: private: sl@0: Name name; sl@0: }; sl@0: template sl@0: inline label_writer sl@0: make_label_writer(Name n) { sl@0: return label_writer(n); sl@0: } sl@0: sl@0: enum edge_attribute_t { edge_attribute = 1111 }; sl@0: enum vertex_attribute_t { vertex_attribute = 2222 }; sl@0: enum graph_graph_attribute_t { graph_graph_attribute = 3333 }; sl@0: enum graph_vertex_attribute_t { graph_vertex_attribute = 4444 }; sl@0: enum graph_edge_attribute_t { graph_edge_attribute = 5555 }; sl@0: sl@0: BOOST_INSTALL_PROPERTY(edge, attribute); sl@0: BOOST_INSTALL_PROPERTY(vertex, attribute); sl@0: BOOST_INSTALL_PROPERTY(graph, graph_attribute); sl@0: BOOST_INSTALL_PROPERTY(graph, vertex_attribute); sl@0: BOOST_INSTALL_PROPERTY(graph, edge_attribute); sl@0: sl@0: sl@0: template sl@0: inline void write_attributes(const Attribute& attr, std::ostream& out) { sl@0: typename Attribute::const_iterator i, iend; sl@0: i = attr.begin(); sl@0: iend = attr.end(); sl@0: sl@0: while ( i != iend ) { sl@0: out << i->first << "=\"" << i->second << "\""; sl@0: ++i; sl@0: if ( i != iend ) sl@0: out << ", "; sl@0: } sl@0: } sl@0: sl@0: template sl@0: inline void write_all_attributes(Attributes attributes, sl@0: const std::string& name, sl@0: std::ostream& out) sl@0: { sl@0: typename Attributes::const_iterator i = attributes.begin(), sl@0: end = attributes.end(); sl@0: if (i != end) { sl@0: out << name << " [\n"; sl@0: write_attributes(attributes, out); sl@0: out << "];\n"; sl@0: } sl@0: } sl@0: sl@0: inline void write_all_attributes(detail::error_property_not_found, sl@0: const std::string&, sl@0: std::ostream&) sl@0: { sl@0: // Do nothing - no attributes exist sl@0: } sl@0: sl@0: sl@0: sl@0: sl@0: template sl@0: struct graph_attributes_writer sl@0: { sl@0: graph_attributes_writer(GraphGraphAttributes gg, sl@0: GraphNodeAttributes gn, sl@0: GraphEdgeAttributes ge) sl@0: : g_attributes(gg), n_attributes(gn), e_attributes(ge) { } sl@0: sl@0: void operator()(std::ostream& out) const { sl@0: write_all_attributes(g_attributes, "graph", out); sl@0: write_all_attributes(n_attributes, "node", out); sl@0: write_all_attributes(e_attributes, "edge", out); sl@0: } sl@0: GraphGraphAttributes g_attributes; sl@0: GraphNodeAttributes n_attributes; sl@0: GraphEdgeAttributes e_attributes; sl@0: }; sl@0: sl@0: template sl@0: graph_attributes_writer sl@0: make_graph_attributes_writer(const GAttrMap& g_attr, const NAttrMap& n_attr, sl@0: const EAttrMap& e_attr) { sl@0: return graph_attributes_writer sl@0: (g_attr, n_attr, e_attr); sl@0: } sl@0: sl@0: sl@0: template sl@0: graph_attributes_writer sl@0: ::type, sl@0: typename graph_property::type, sl@0: typename graph_property::type> sl@0: make_graph_attributes_writer(const Graph& g) sl@0: { sl@0: typedef typename graph_property::type sl@0: GAttrMap; sl@0: typedef typename graph_property::type sl@0: NAttrMap; sl@0: typedef typename graph_property::type sl@0: EAttrMap; sl@0: GAttrMap gam = get_property(g, graph_graph_attribute); sl@0: NAttrMap nam = get_property(g, graph_vertex_attribute); sl@0: EAttrMap eam = get_property(g, graph_edge_attribute); sl@0: graph_attributes_writer writer(gam, nam, eam); sl@0: return writer; sl@0: } sl@0: sl@0: template sl@0: struct attributes_writer { sl@0: attributes_writer(AttributeMap attr) sl@0: : attributes(attr) { } sl@0: sl@0: template sl@0: void operator()(std::ostream& out, const VorE& e) const { sl@0: this->write_attribute(out, attributes[e]); sl@0: } sl@0: sl@0: private: sl@0: template sl@0: void write_attribute(std::ostream& out, sl@0: const AttributeSequence& seq) const sl@0: { sl@0: if (!seq.empty()) { sl@0: out << "["; sl@0: write_attributes(seq, out); sl@0: out << "]"; sl@0: } sl@0: } sl@0: sl@0: void write_attribute(std::ostream&, sl@0: detail::error_property_not_found) const sl@0: { sl@0: } sl@0: AttributeMap attributes; sl@0: }; sl@0: sl@0: template sl@0: attributes_writer sl@0: ::const_type> sl@0: make_edge_attributes_writer(const Graph& g) sl@0: { sl@0: typedef typename property_map::const_type sl@0: EdgeAttributeMap; sl@0: return attributes_writer(get(edge_attribute, g)); sl@0: } sl@0: sl@0: template sl@0: attributes_writer sl@0: ::const_type> sl@0: make_vertex_attributes_writer(const Graph& g) sl@0: { sl@0: typedef typename property_map::const_type sl@0: VertexAttributeMap; sl@0: return attributes_writer(get(vertex_attribute, g)); sl@0: } sl@0: sl@0: template sl@0: inline void write_graphviz(std::ostream& out, const Graph& g, sl@0: VertexPropertiesWriter vpw, sl@0: EdgePropertiesWriter epw, sl@0: GraphPropertiesWriter gpw, sl@0: VertexID vertex_id) sl@0: { sl@0: typedef typename graph_traits::directed_category cat_type; sl@0: typedef graphviz_io_traits Traits; sl@0: std::string name = "G"; sl@0: out << Traits::name() << " " << name << " {" << std::endl; sl@0: sl@0: gpw(out); //print graph properties sl@0: sl@0: typename graph_traits::vertex_iterator i, end; sl@0: sl@0: for(tie(i,end) = vertices(g); i != end; ++i) { sl@0: out << get(vertex_id, *i); sl@0: vpw(out, *i); //print vertex attributes sl@0: out << ";" << std::endl; sl@0: } sl@0: typename graph_traits::edge_iterator ei, edge_end; sl@0: for(tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { sl@0: out << get(vertex_id, source(*ei, g)) << Traits::delimiter() << get(vertex_id, target(*ei, g)) << " "; sl@0: epw(out, *ei); //print edge attributes sl@0: out << ";" << std::endl; sl@0: } sl@0: out << "}" << std::endl; sl@0: } sl@0: sl@0: template sl@0: inline void write_graphviz(std::ostream& out, const Graph& g, sl@0: VertexPropertiesWriter vpw, sl@0: EdgePropertiesWriter epw, sl@0: GraphPropertiesWriter gpw) sl@0: { write_graphviz(out, g, vpw, epw, gpw, get(vertex_index, g)); } sl@0: sl@0: #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 sl@0: // ambiguous overload problem with VC++ sl@0: template sl@0: inline void sl@0: write_graphviz(std::ostream& out, const Graph& g) { sl@0: default_writer dw; sl@0: default_writer gw; sl@0: write_graphviz(out, g, dw, dw, gw); sl@0: } sl@0: #endif sl@0: sl@0: template sl@0: inline void sl@0: write_graphviz(std::ostream& out, const Graph& g, VertexWriter vw) { sl@0: default_writer dw; sl@0: default_writer gw; sl@0: write_graphviz(out, g, vw, dw, gw); sl@0: } sl@0: sl@0: template sl@0: inline void sl@0: write_graphviz(std::ostream& out, const Graph& g, sl@0: VertexWriter vw, EdgeWriter ew) { sl@0: default_writer gw; sl@0: write_graphviz(out, g, vw, ew, gw); sl@0: } sl@0: sl@0: namespace detail { sl@0: sl@0: template sl@0: void write_graphviz_subgraph (std::ostream& out, sl@0: const subgraph& g, sl@0: RandomAccessIterator vertex_marker, sl@0: RandomAccessIterator edge_marker, sl@0: VertexID vertex_id) sl@0: { sl@0: typedef subgraph Graph; sl@0: typedef typename graph_traits::vertex_descriptor Vertex; sl@0: typedef typename graph_traits::directed_category cat_type; sl@0: typedef graphviz_io_traits Traits; sl@0: sl@0: typedef typename graph_property::type NameType; sl@0: const NameType& g_name = get_property(g, graph_name); sl@0: sl@0: if ( g.is_root() ) sl@0: out << Traits::name() ; sl@0: else sl@0: out << "subgraph"; sl@0: sl@0: out << " " << g_name << " {" << std::endl; sl@0: sl@0: typename Graph::const_children_iterator i_child, j_child; sl@0: sl@0: //print graph/node/edge attributes sl@0: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 sl@0: typedef typename graph_property::type sl@0: GAttrMap; sl@0: typedef typename graph_property::type sl@0: NAttrMap; sl@0: typedef typename graph_property::type sl@0: EAttrMap; sl@0: GAttrMap gam = get_property(g, graph_graph_attribute); sl@0: NAttrMap nam = get_property(g, graph_vertex_attribute); sl@0: EAttrMap eam = get_property(g, graph_edge_attribute); sl@0: graph_attributes_writer writer(gam, nam, eam); sl@0: writer(out); sl@0: #else sl@0: make_graph_attributes_writer(g)(out); sl@0: #endif sl@0: sl@0: //print subgraph sl@0: for ( tie(i_child,j_child) = g.children(); sl@0: i_child != j_child; ++i_child ) sl@0: write_graphviz_subgraph(out, *i_child, vertex_marker, edge_marker, sl@0: vertex_id); sl@0: sl@0: // Print out vertices and edges not in the subgraphs. sl@0: sl@0: typename graph_traits::vertex_iterator i, end; sl@0: typename graph_traits::edge_iterator ei, edge_end; sl@0: sl@0: for(tie(i,end) = vertices(g); i != end; ++i) { sl@0: Vertex v = g.local_to_global(*i); sl@0: int pos = get(vertex_id, v); sl@0: if ( vertex_marker[pos] ) { sl@0: vertex_marker[pos] = false; sl@0: out << pos; sl@0: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 sl@0: typedef typename property_map::const_type sl@0: VertexAttributeMap; sl@0: attributes_writer vawriter(get(vertex_attribute, sl@0: g.root())); sl@0: vawriter(out, v); sl@0: #else sl@0: make_vertex_attributes_writer(g.root())(out, v); sl@0: #endif sl@0: out << ";" << std::endl; sl@0: } sl@0: } sl@0: sl@0: for (tie(ei, edge_end) = edges(g); ei != edge_end; ++ei) { sl@0: Vertex u = g.local_to_global(source(*ei,g)), sl@0: v = g.local_to_global(target(*ei, g)); sl@0: int pos = get(get(edge_index, g.root()), g.local_to_global(*ei)); sl@0: if ( edge_marker[pos] ) { sl@0: edge_marker[pos] = false; sl@0: out << get(vertex_id, u) << " " << Traits::delimiter() sl@0: << " " << get(vertex_id, v); sl@0: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 sl@0: typedef typename property_map::const_type sl@0: EdgeAttributeMap; sl@0: attributes_writer eawriter(get(edge_attribute, g)); sl@0: eawriter(out, *ei); sl@0: #else sl@0: make_edge_attributes_writer(g)(out, *ei); //print edge properties sl@0: #endif sl@0: out << ";" << std::endl; sl@0: } sl@0: } sl@0: out << "}" << std::endl; sl@0: } sl@0: } // namespace detail sl@0: sl@0: // requires graph_name graph property sl@0: template sl@0: void write_graphviz(std::ostream& out, const subgraph& g) { sl@0: std::vector edge_marker(num_edges(g), true); sl@0: std::vector vertex_marker(num_vertices(g), true); sl@0: sl@0: detail::write_graphviz_subgraph(out, g, sl@0: vertex_marker.begin(), sl@0: edge_marker.begin(), sl@0: get(vertex_index, g)); sl@0: } sl@0: sl@0: template sl@0: void write_graphviz(const std::string& filename, const subgraph& g) { sl@0: std::ofstream out(filename.c_str()); sl@0: std::vector edge_marker(num_edges(g), true); sl@0: std::vector vertex_marker(num_vertices(g), true); sl@0: sl@0: detail::write_graphviz_subgraph(out, g, sl@0: vertex_marker.begin(), sl@0: edge_marker.begin(), sl@0: get(vertex_index, g)); sl@0: } sl@0: sl@0: template sl@0: void write_graphviz(std::ostream& out, const subgraph& g, sl@0: VertexID vertex_id) sl@0: { sl@0: std::vector edge_marker(num_edges(g), true); sl@0: std::vector vertex_marker(num_vertices(g), true); sl@0: sl@0: detail::write_graphviz_subgraph(out, g, sl@0: vertex_marker.begin(), sl@0: edge_marker.begin(), sl@0: vertex_id); sl@0: } sl@0: sl@0: template sl@0: void write_graphviz(const std::string& filename, const subgraph& g, sl@0: VertexID vertex_id) sl@0: { sl@0: std::ofstream out(filename.c_str()); sl@0: std::vector edge_marker(num_edges(g), true); sl@0: std::vector vertex_marker(num_vertices(g), true); sl@0: sl@0: detail::write_graphviz_subgraph(out, g, sl@0: vertex_marker.begin(), sl@0: edge_marker.begin(), sl@0: vertex_id); sl@0: } sl@0: sl@0: typedef std::map GraphvizAttrList; sl@0: sl@0: typedef property sl@0: GraphvizVertexProperty; sl@0: sl@0: typedef property > sl@0: GraphvizEdgeProperty; sl@0: sl@0: typedef property > > > sl@0: GraphvizGraphProperty; sl@0: sl@0: typedef subgraph > sl@0: GraphvizDigraph; sl@0: sl@0: typedef subgraph > sl@0: GraphvizGraph; sl@0: sl@0: sl@0: // These four require linking the BGL-Graphviz library: libbgl-viz.a sl@0: // from the /src directory. sl@0: extern void read_graphviz(const std::string& file, GraphvizDigraph& g); sl@0: extern void read_graphviz(FILE* file, GraphvizDigraph& g); sl@0: sl@0: extern void read_graphviz(const std::string& file, GraphvizGraph& g); sl@0: extern void read_graphviz(FILE* file, GraphvizGraph& g); sl@0: sl@0: class dynamic_properties_writer sl@0: { sl@0: public: sl@0: dynamic_properties_writer(const dynamic_properties& dp) : dp(&dp) { } sl@0: sl@0: template sl@0: void operator()(std::ostream& out, Descriptor key) const sl@0: { sl@0: bool first = true; sl@0: for (dynamic_properties::const_iterator i = dp->begin(); sl@0: i != dp->end(); ++i) { sl@0: if (typeid(key) == i->second->key()) { sl@0: if (first) out << " ["; sl@0: else out << ", "; sl@0: first = false; sl@0: sl@0: out << i->first << "=\"" << i->second->get_string(key) << "\""; sl@0: } sl@0: } sl@0: sl@0: if (!first) out << "]"; sl@0: } sl@0: sl@0: private: sl@0: const dynamic_properties* dp; sl@0: }; sl@0: sl@0: class dynamic_vertex_properties_writer sl@0: { sl@0: public: sl@0: dynamic_vertex_properties_writer(const dynamic_properties& dp, sl@0: const std::string& node_id) sl@0: : dp(&dp), node_id(&node_id) { } sl@0: sl@0: template sl@0: void operator()(std::ostream& out, Descriptor key) const sl@0: { sl@0: bool first = true; sl@0: for (dynamic_properties::const_iterator i = dp->begin(); sl@0: i != dp->end(); ++i) { sl@0: if (typeid(key) == i->second->key() sl@0: && i->first != *node_id) { sl@0: if (first) out << " ["; sl@0: else out << ", "; sl@0: first = false; sl@0: sl@0: out << i->first << "=\"" << i->second->get_string(key) << "\""; sl@0: } sl@0: } sl@0: sl@0: if (!first) out << "]"; sl@0: } sl@0: sl@0: private: sl@0: const dynamic_properties* dp; sl@0: const std::string* node_id; sl@0: }; sl@0: sl@0: namespace graph { namespace detail { sl@0: sl@0: template sl@0: struct node_id_property_map sl@0: { sl@0: typedef std::string value_type; sl@0: typedef value_type reference; sl@0: typedef Vertex key_type; sl@0: typedef readable_property_map_tag category; sl@0: sl@0: node_id_property_map() {} sl@0: sl@0: node_id_property_map(const dynamic_properties& dp, sl@0: const std::string& node_id) sl@0: : dp(&dp), node_id(&node_id) { } sl@0: sl@0: const dynamic_properties* dp; sl@0: const std::string* node_id; sl@0: }; sl@0: sl@0: template sl@0: inline std::string sl@0: get(node_id_property_map pm, sl@0: typename node_id_property_map::key_type v) sl@0: { return get(*pm.node_id, *pm.dp, v); } sl@0: sl@0: } } // end namespace graph::detail sl@0: sl@0: template sl@0: inline void sl@0: write_graphviz(std::ostream& out, const Graph& g, sl@0: const dynamic_properties& dp, sl@0: const std::string& node_id = "node_id") sl@0: { sl@0: typedef typename graph_traits::vertex_descriptor Vertex; sl@0: write_graphviz(out, g, dp, node_id, sl@0: graph::detail::node_id_property_map(dp, node_id)); sl@0: } sl@0: sl@0: template sl@0: void sl@0: write_graphviz(std::ostream& out, const Graph& g, sl@0: const dynamic_properties& dp, const std::string& node_id, sl@0: VertexID id) sl@0: { sl@0: write_graphviz sl@0: (out, g, sl@0: /*vertex_writer=*/dynamic_vertex_properties_writer(dp, node_id), sl@0: /*edge_writer=*/dynamic_properties_writer(dp), sl@0: /*graph_writer=*/default_writer(), sl@0: id); sl@0: } sl@0: sl@0: ///////////////////////////////////////////////////////////////////////////// sl@0: // Graph reader exceptions sl@0: ///////////////////////////////////////////////////////////////////////////// sl@0: struct graph_exception : public std::exception { sl@0: virtual ~graph_exception() throw() {} sl@0: virtual const char* what() const throw() = 0; sl@0: }; sl@0: sl@0: struct bad_parallel_edge : public graph_exception { sl@0: std::string from; sl@0: std::string to; sl@0: mutable std::string statement; sl@0: bad_parallel_edge(const std::string& i, const std::string& j) : sl@0: from(i), to(j) {} sl@0: sl@0: virtual ~bad_parallel_edge() throw() {} sl@0: const char* what() const throw() { sl@0: if(statement.empty()) sl@0: statement = sl@0: std::string("Failed to add parallel edge: (") sl@0: + from + "," + to + ")\n"; sl@0: sl@0: return statement.c_str(); sl@0: } sl@0: }; sl@0: sl@0: struct directed_graph_error : public graph_exception { sl@0: virtual ~directed_graph_error() throw() {} sl@0: virtual const char* what() const throw() { sl@0: return sl@0: "read_graphviz: " sl@0: "Tried to read a directed graph into an undirected graph."; sl@0: } sl@0: }; sl@0: sl@0: struct undirected_graph_error : public graph_exception { sl@0: virtual ~undirected_graph_error() throw() {} sl@0: virtual const char* what() const throw() { sl@0: return sl@0: "read_graphviz: " sl@0: "Tried to read an undirected graph into a directed graph."; sl@0: } sl@0: }; sl@0: sl@0: namespace detail { namespace graph { sl@0: sl@0: typedef std::string id_t; sl@0: typedef id_t node_t; sl@0: sl@0: // edges are not uniquely determined by adjacent nodes sl@0: class edge_t { sl@0: int idx_; sl@0: explicit edge_t(int i) : idx_(i) {} sl@0: public: sl@0: static edge_t new_edge() { sl@0: static int idx = 0; sl@0: return edge_t(idx++); sl@0: }; sl@0: sl@0: bool operator==(const edge_t& rhs) const { sl@0: return idx_ == rhs.idx_; sl@0: } sl@0: bool operator<(const edge_t& rhs) const { sl@0: return idx_ < rhs.idx_; sl@0: } sl@0: }; sl@0: sl@0: class mutate_graph sl@0: { sl@0: public: sl@0: virtual ~mutate_graph() {} sl@0: virtual bool is_directed() const = 0; sl@0: virtual void do_add_vertex(const node_t& node) = 0; sl@0: sl@0: virtual void sl@0: do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) sl@0: = 0; sl@0: sl@0: virtual void sl@0: set_node_property(const id_t& key, const node_t& node, const id_t& value) = 0; sl@0: sl@0: virtual void sl@0: set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) = 0; sl@0: }; sl@0: sl@0: template sl@0: class mutate_graph_impl : public mutate_graph sl@0: { sl@0: typedef typename graph_traits::vertex_descriptor bgl_vertex_t; sl@0: typedef typename graph_traits::edge_descriptor bgl_edge_t; sl@0: sl@0: public: sl@0: mutate_graph_impl(MutableGraph& graph, dynamic_properties& dp, sl@0: std::string node_id_prop) sl@0: : graph_(graph), dp_(dp), node_id_prop_(node_id_prop) { } sl@0: sl@0: ~mutate_graph_impl() {} sl@0: sl@0: bool is_directed() const sl@0: { sl@0: return sl@0: boost::is_convertible< sl@0: typename boost::graph_traits::directed_category, sl@0: boost::directed_tag>::value; sl@0: } sl@0: sl@0: virtual void do_add_vertex(const node_t& node) sl@0: { sl@0: // Add the node to the graph. sl@0: bgl_vertex_t v = add_vertex(graph_); sl@0: sl@0: // Set up a mapping from name to BGL vertex. sl@0: bgl_nodes.insert(std::make_pair(node, v)); sl@0: sl@0: // node_id_prop_ allows the caller to see the real id names for nodes. sl@0: put(node_id_prop_, dp_, v, node); sl@0: } sl@0: sl@0: void sl@0: do_add_edge(const edge_t& edge, const node_t& source, const node_t& target) sl@0: { sl@0: std::pair result = sl@0: add_edge(bgl_nodes[source], bgl_nodes[target], graph_); sl@0: sl@0: if(!result.second) { sl@0: // In the case of no parallel edges allowed sl@0: throw bad_parallel_edge(source, target); sl@0: } else { sl@0: bgl_edges.insert(std::make_pair(edge, result.first)); sl@0: } sl@0: } sl@0: sl@0: void sl@0: set_node_property(const id_t& key, const node_t& node, const id_t& value) sl@0: { sl@0: put(key, dp_, bgl_nodes[node], value); sl@0: } sl@0: sl@0: void sl@0: set_edge_property(const id_t& key, const edge_t& edge, const id_t& value) sl@0: { sl@0: put(key, dp_, bgl_edges[edge], value); sl@0: } sl@0: sl@0: protected: sl@0: MutableGraph& graph_; sl@0: dynamic_properties& dp_; sl@0: std::string node_id_prop_; sl@0: std::map bgl_nodes; sl@0: std::map bgl_edges; sl@0: }; sl@0: sl@0: BOOST_GRAPH_DECL sl@0: bool read_graphviz(std::istream& in, mutate_graph& graph); sl@0: sl@0: } } // end namespace detail::graph sl@0: sl@0: // Parse the passed stream as a GraphViz dot file. sl@0: template sl@0: bool read_graphviz(std::istream& in, MutableGraph& graph, sl@0: dynamic_properties& dp, sl@0: std::string const& node_id = "node_id") sl@0: { sl@0: detail::graph::mutate_graph_impl m_graph(graph, dp, node_id); sl@0: return detail::graph::read_graphviz(in, m_graph); sl@0: } sl@0: sl@0: } // namespace boost sl@0: sl@0: #ifdef BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS sl@0: # include sl@0: #endif // BOOST_GRAPH_READ_GRAPHVIZ_ITERATORS sl@0: sl@0: #endif // BOOST_GRAPHVIZ_HPP