void V3Graph::dumpDotFile(const string& filename, bool colorAsSubgraph) { // This generates a file used by graphviz, http://www.graphviz.org // "hardcoded" parameters: const auto_ptr<ofstream> logp (V3File::new_ofstream(filename)); if (logp->fail()) v3fatalSrc("Can't write "<<filename); // Header *logp<<"digraph v3graph {\n"; *logp<<"\tgraph\t[label=\""<<filename<<"\",\n"; *logp<<"\t\t labelloc=t, labeljust=l,\n"; *logp<<"\t\t //size="<<"\"7.5,10\","<<"\n"; *logp<<"\t\t rankdir="<<dotRankDir()<<"];\n"; // List of all possible subgraphs typedef multimap<string,V3GraphVertex*> SubgraphMmap; SubgraphMmap subgraphs; for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { string vertexSubgraph = (colorAsSubgraph && vertexp->color()) ? cvtToStr(vertexp->color()) : ""; subgraphs.insert(make_pair(vertexSubgraph, vertexp)); } // We use a map here, as we don't want to corrupt anything (userp) in the graph, // and we don't care if this is slow. map<V3GraphVertex*,int> numMap; // Print vertices int n=0; string subgr; for (SubgraphMmap::iterator it = subgraphs.begin(); it!=subgraphs.end(); ++it) { string vertexSubgraph = it->first; V3GraphVertex* vertexp = it->second; numMap[vertexp] = n; if (subgr != vertexSubgraph) { if (subgr!="") *logp<<"\t};\n"; subgr = vertexSubgraph; if (subgr!="") *logp<<"\tsubgraph cluster_"<<subgr<<" {\n"; } if (subgr!="") *logp<<"\t"; *logp<<"\tn"<<vertexp->dotName()<<(n++) <<"\t[fontsize=8 " <<"label=\""<<(vertexp->name()!="" ? vertexp->name() : "\\N"); if (vertexp->rank()) *logp<<" r"<<vertexp->rank(); if (vertexp->fanout()) *logp<<" f"<<vertexp->fanout(); if (vertexp->color()) *logp<<"\\n c"<<vertexp->color(); *logp<<"\""; *logp<<", color="<<vertexp->dotColor(); if (vertexp->dotStyle()!="") *logp<<", style="<<vertexp->dotStyle(); if (vertexp->dotShape()!="") *logp<<", shape="<<vertexp->dotShape(); *logp<<"];\n"; } if (subgr!="") *logp<<"\t};\n"; // Print edges for (V3GraphVertex* vertexp = verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) { for (V3GraphEdge* edgep = vertexp->outBeginp(); edgep; edgep=edgep->outNextp()) { if (edgep->weight()) { int fromVnum = numMap[edgep->fromp()]; int toVnum = numMap[edgep->top()]; *logp<<"\tn"<<edgep->fromp()->dotName()<<fromVnum <<" -> n"<<edgep->top()->dotName()<<toVnum <<" [" //<<"fontsize=8 label=\""<<(edgep->name()!="" ? edgep->name() : "\\E")<<"\"" <<"fontsize=8 label=\""<<(edgep->dotLabel()!="" ? edgep->dotLabel() : "")<<"\"" <<" weight="<<edgep->weight() <<" color="<<edgep->dotColor(); if (edgep->dotStyle()!="") *logp<<" style="<<edgep->dotStyle(); //if (edgep->cutable()) { *logp<<",constraint=false"; } // to rank without following edges *logp<<"];\n"; } } } // Vertex::m_user end, now unused // Trailer *logp << "}\n"; logp->close(); cout << "dot -Tpdf -o ~/a.pdf "<<filename<<endl; }