# HG changeset patch # User alpar # Date 1104858425 0 # Node ID 1bb1d4c87331131e1619f9fe1ebacda8deff256c # Parent 1bf336c63f25a8dd5747dd7dc4a99c476c80678b An experimental graph-to-eps exporter. diff -r 1bf336c63f25 -r 1bb1d4c87331 src/work/alpar/graph_to_eps.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/alpar/graph_to_eps.cc Tue Jan 04 17:07:05 2005 +0000 @@ -0,0 +1,230 @@ +#include +#include +#include + +///\file +///Simple graph drawer + +namespace lemon { + + ///\e +class Color +{ + double _r,_g,_b; +public: + ///\e + Color() {} + ///\e + Color(double r,double g,double b) :_r(r),_g(g),_b(b) {}; + ///\e + double getR() {return _r;} + ///\e + double getG() {return _g;} + ///\e + double getB() {return _b;} + ///\e + void set(double r,double g,double b) { _r=r;_g=g;_b=b; }; +}; + + ///\e +template +struct DefaultGraphToEpsTraits +{ + typedef G Graph; + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + + const Graph &g; + ConstMap > coords; + ConstMap nodeSizes; + + ConstMap nodeColors; + ConstMap edgeColors; + double nodeSizeScalar; + double xBorder, yBorder; + + DefaultGraphToEpsTraits(G &_g) : + g(_g), coords(xy(1,1)), nodeSizes(1.0), + nodeColors(Color(1,1,1)), edgeColors(Color(0,0,0)), + nodeSizeScalar(1.0), xBorder(10), yBorder(10) {} +}; + + ///\e +template class GraphToEps : public T +{ + typedef typename T::Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::Edge Edge; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + + bool dontPrint; + +public: + GraphToEps(const T &t) : T(t), dontPrint(false) {}; + + template struct SetCoordsTraits : public T { + const X &coords; + SetCoordsTraits(const T &t,const X &x) : T(t), coords(x) {} + }; + ///\e + template GraphToEps > setCoords(const X &x) { + dontPrint=true; + return GraphToEps >(SetCoordsTraits(*this,x)); + } + template struct SetNodeSizesTraits : public T { + const X &nodeSizes; + SetNodeSizesTraits(const T &t,const X &x) : T(t), nodeSizes(x) {} + }; + ///\e + template GraphToEps > setNodeSizes(const X &x) + { + dontPrint=true; + return GraphToEps >(SetNodeSizesTraits(*this,x)); + } + template struct SetNodeColorsTraits : public T { + const X &nodeColors; + SetNodeColorsTraits(const T &t,const X &x) : T(t), nodeColors(x) {} + }; + ///\e + template GraphToEps > + setNodeColors(const X &x) + { + dontPrint=true; + return GraphToEps >(SetNodeColorsTraits(*this,x)); + } + template struct SetEdgeColorsTraits : public T { + const X &edgeColors; + SetEdgeColorsTraits(const T &t,const X &x) : T(t), edgeColors(x) {} + }; + ///\e + template GraphToEps > + setEdgeColors(const X &x) + { + dontPrint=true; + return GraphToEps >(SetEdgeColorsTraits(*this,x)); + } + ///\e + GraphToEps &scaleNodeSize(double d) {nodeSizeScalar=d;return *this;} + + ~GraphToEps() + { + if(dontPrint) return; + + cout << "%!PS-Adobe-2.0 EPSF-2.0\n"; + //\todo: Chech whether the graph is empty. + BoundingBox bb; + for(NodeIt n(g); + n!=INVALID; + ++n) { + xy p(nodeSizes[n]*nodeSizeScalar,nodeSizes[n]*nodeSizeScalar); + bb+=coords[n]+p; + bb+=coords[n]-p; + } + cout << "%%BoundingBox: " + << bb.left()-xBorder << ' ' << bb.bottom()-yBorder << ' ' + << bb.right()+xBorder << ' ' << bb.top()+yBorder << '\n'; + //x1 y1 x2 y2 cr cg cb + cout << "/l { setrgbcolor newpath moveto lineto stroke } bind def\n"; + cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n"; + // x y r cr cg cb + cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" + << " 0 0 0 setrgbcolor dup 10 div setlinewidth c stroke\n" + << " } bind def\n"; + + cout << "%Edges:\ngsave\n"; + for(NodeIt n(g);n!=INVALID;++n) + for(OutEdgeIt e(g,n);e!=INVALID;++e) + cout << coords[g.source(e)].x << ' ' << coords[g.source(e)].y << ' ' + << coords[g.target(e)].x << ' ' << coords[g.target(e)].y << ' ' + << edgeColors[e].getR() << ' ' + << edgeColors[e].getG() << ' ' + << edgeColors[e].getB() << " l\n"; + cout << "grestore\n%Nodes:\ngsave\n"; + for(NodeIt n(g);n!=INVALID;++n) + cout << coords[n].x << ' ' << coords[n].y << ' ' + << nodeSizes[n]*nodeSizeScalar << ' ' + << nodeColors[n].getR() << ' ' + << nodeColors[n].getG() << ' ' + << nodeColors[n].getB() << " n\n"; + cout << "grestore\n"; + } +}; + + +template +GraphToEps > graphToEps(G &g) +{ + return GraphToEps >(DefaultGraphToEpsTraits(g)); +} + +} + +using namespace lemon; + +class ColorSet : public MapBase +{ +public: + Color operator[](int i) const + { + switch(i%8){ + case 0: return Color(0,0,0); + case 1: return Color(1,0,0); + case 2: return Color(0,1,0); + case 3: return Color(0,0,1); + case 4: return Color(1,1,0); + case 5: return Color(1,0,1); + case 6: return Color(0,1,1); + case 7: return Color(1,1,1); + } + return Color(0,0,0); + } +} colorSet; + +int main() +{ + ListGraph g; + typedef ListGraph::Node Node; + typedef ListGraph::NodeIt NodeIt; + typedef ListGraph::Edge Edge; + typedef xy Xy; + + Node n1=g.addNode(); + Node n2=g.addNode(); + Node n3=g.addNode(); + Node n4=g.addNode(); + Node n5=g.addNode(); + + ListGraph::NodeMap coords(g); + ListGraph::NodeMap sizes(g); + ListGraph::NodeMap colors(g); + ListGraph::EdgeMap ecolors(g,0); + + coords[n1]=Xy(50,50); sizes[n1]=1; colors[n1]=1; + coords[n2]=Xy(50,70); sizes[n2]=2; colors[n2]=2; + coords[n3]=Xy(70,70); sizes[n3]=1; colors[n3]=3; + coords[n4]=Xy(70,50); sizes[n4]=2; colors[n4]=4; + coords[n5]=Xy(85,60); sizes[n5]=3; colors[n5]=5; + + Edge e; + + e=g.addEdge(n1,n2); + e=g.addEdge(n2,n3); + e=g.addEdge(n3,n5); + e=g.addEdge(n5,n4); + e=g.addEdge(n4,n1); + e=g.addEdge(n2,n4); ecolors[e]=1; + e=g.addEdge(n3,n4); ecolors[e]=2; + + graphToEps(g).setCoords(coords). + scaleNodeSize(2).setNodeSizes(sizes). + setNodeColors(composeMap(colorSet,colors)). + setEdgeColors(composeMap(colorSet,ecolors)); +}