Several new named parameters and documentation added to graphToEps().
1.1 --- a/src/work/Doxyfile Tue Jan 04 22:14:42 2005 +0000
1.2 +++ b/src/work/Doxyfile Tue Jan 04 22:16:46 2005 +0000
1.3 @@ -407,6 +407,7 @@
1.4 jacint/graph_gen.h \
1.5 marci/max_bipartite_matching.h \
1.6 marci/bipartite_graph_wrapper.h \
1.7 + alpar/graph_to_eps.cc \
1.8 deba \
1.9
1.10
2.1 --- a/src/work/alpar/graph_to_eps.cc Tue Jan 04 22:14:42 2005 +0000
2.2 +++ b/src/work/alpar/graph_to_eps.cc Tue Jan 04 22:16:46 2005 +0000
2.3 @@ -1,32 +1,41 @@
2.4 +#include<math.h>
2.5 #include<lemon/xy.h>
2.6 #include<lemon/maps.h>
2.7 #include<lemon/list_graph.h>
2.8
2.9 -///\file
2.10 +
2.11 +///\file \ingroup misc
2.12 ///Simple graph drawer
2.13
2.14 namespace lemon {
2.15
2.16 - ///\e
2.17 +///Data structure representing RGB colors.
2.18 +
2.19 +///Data structure representing RGB colors.
2.20 +///\ingroup misc
2.21 class Color
2.22 {
2.23 double _r,_g,_b;
2.24 public:
2.25 - ///\e
2.26 + ///Default constructor
2.27 Color() {}
2.28 - ///\e
2.29 + ///Constructor
2.30 Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
2.31 - ///\e
2.32 + ///Returns the red component
2.33 double getR() {return _r;}
2.34 - ///\e
2.35 + ///Returns the green component
2.36 double getG() {return _g;}
2.37 - ///\e
2.38 + ///Returns the blue component
2.39 double getB() {return _b;}
2.40 - ///\e
2.41 + ///Set the color components
2.42 void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
2.43 };
2.44
2.45 - ///\e
2.46 +///Default traits class of \ref GraphToEps
2.47 +
2.48 +///Default traits class of \ref GraphToEps
2.49 +///
2.50 +///\c G is the type of the underlying graph.
2.51 template<class G>
2.52 struct DefaultGraphToEpsTraits
2.53 {
2.54 @@ -40,21 +49,42 @@
2.55
2.56
2.57 const Graph &g;
2.58 - ConstMap<typename Graph::Node,xy<double> > coords;
2.59 - ConstMap<typename Graph::Node,double > nodeSizes;
2.60 + ConstMap<typename Graph::Node,xy<double> > _coords;
2.61 + ConstMap<typename Graph::Node,double > _nodeSizes;
2.62
2.63 - ConstMap<typename Graph::Node,Color > nodeColors;
2.64 - ConstMap<typename Graph::Edge,Color > edgeColors;
2.65 - double nodeSizeScalar;
2.66 - double xBorder, yBorder;
2.67 -
2.68 - DefaultGraphToEpsTraits(G &_g) :
2.69 - g(_g), coords(xy<double>(1,1)), nodeSizes(1.0),
2.70 - nodeColors(Color(1,1,1)), edgeColors(Color(0,0,0)),
2.71 - nodeSizeScalar(1.0), xBorder(10), yBorder(10) {}
2.72 + ConstMap<typename Graph::Node,Color > _nodeColors;
2.73 + ConstMap<typename Graph::Edge,Color > _edgeColors;
2.74 +
2.75 + ConstMap<typename Graph::Edge,double > _edgeWidths;
2.76 +
2.77 + double _edgeWidthScale;
2.78 +
2.79 + double _nodeScale;
2.80 + double _xBorder, _yBorder;
2.81 + double _scale;
2.82 + double _nodeBorderQuotient;
2.83 +
2.84 + bool _drawArrows;
2.85 + double _arrowLength, _arrowWidth;
2.86 +
2.87 + ///Constructor
2.88 +
2.89 + ///Constructor
2.90 + ///\param _g is a reference to the underlying graph
2.91 + DefaultGraphToEpsTraits(const G &_g) :
2.92 + g(_g), _coords(xy<double>(1,1)), _nodeSizes(1.0),
2.93 + _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
2.94 + _edgeWidths(1), _edgeWidthScale(0.3),
2.95 + _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
2.96 + _nodeBorderQuotient(.1),
2.97 + _drawArrows(false), _arrowLength(1), _arrowWidth(0.3) {}
2.98 };
2.99
2.100 - ///\e
2.101 +///Helper class to implement the named parameters of \ref graphToEps()
2.102 +
2.103 +///Helper class to implement the named parameters of \ref graphToEps()
2.104 +///\todo Is 'helper class' a good name for this?
2.105 +///
2.106 template<class T> class GraphToEps : public T
2.107 {
2.108 typedef typename T::Graph Graph;
2.109 @@ -70,49 +100,115 @@
2.110 public:
2.111 GraphToEps(const T &t) : T(t), dontPrint(false) {};
2.112
2.113 - template<class X> struct SetCoordsTraits : public T {
2.114 - const X &coords;
2.115 - SetCoordsTraits(const T &t,const X &x) : T(t), coords(x) {}
2.116 + template<class X> struct CoordsTraits : public T {
2.117 + const X &_coords;
2.118 + CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
2.119 };
2.120 - ///\e
2.121 - template<class X> GraphToEps<SetCoordsTraits<X> > setCoords(const X &x) {
2.122 + ///Sets the map of the node coordinates
2.123 +
2.124 + ///Sets the map of the node coordinates.
2.125 + ///\param x must be a node map with xy<double> or xy<int> values.
2.126 + template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
2.127 dontPrint=true;
2.128 - return GraphToEps<SetCoordsTraits<X> >(SetCoordsTraits<X>(*this,x));
2.129 + return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
2.130 }
2.131 - template<class X> struct SetNodeSizesTraits : public T {
2.132 - const X &nodeSizes;
2.133 - SetNodeSizesTraits(const T &t,const X &x) : T(t), nodeSizes(x) {}
2.134 + template<class X> struct NodeSizesTraits : public T {
2.135 + const X &_nodeSizes;
2.136 + NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
2.137 };
2.138 - ///\e
2.139 - template<class X> GraphToEps<SetNodeSizesTraits<X> > setNodeSizes(const X &x)
2.140 + ///Sets the map of the node sizes
2.141 +
2.142 + ///Sets the map of the node sizes
2.143 + ///\param x must be a node map with \c double (or convertible) values.
2.144 + template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
2.145 {
2.146 dontPrint=true;
2.147 - return GraphToEps<SetNodeSizesTraits<X> >(SetNodeSizesTraits<X>(*this,x));
2.148 + return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
2.149 }
2.150 - template<class X> struct SetNodeColorsTraits : public T {
2.151 - const X &nodeColors;
2.152 - SetNodeColorsTraits(const T &t,const X &x) : T(t), nodeColors(x) {}
2.153 + template<class X> struct EdgeWidthsTraits : public T {
2.154 + const X &_edgeWidths;
2.155 + EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
2.156 };
2.157 - ///\e
2.158 - template<class X> GraphToEps<SetNodeColorsTraits<X> >
2.159 - setNodeColors(const X &x)
2.160 + ///Sets the map of the edge widths
2.161 +
2.162 + ///Sets the map of the edge widths
2.163 + ///\param x must be a edge map with \c double (or convertible) values.
2.164 + template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x)
2.165 {
2.166 dontPrint=true;
2.167 - return GraphToEps<SetNodeColorsTraits<X> >(SetNodeColorsTraits<X>(*this,x));
2.168 + return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x));
2.169 }
2.170 - template<class X> struct SetEdgeColorsTraits : public T {
2.171 - const X &edgeColors;
2.172 - SetEdgeColorsTraits(const T &t,const X &x) : T(t), edgeColors(x) {}
2.173 +
2.174 + template<class X> struct NodeColorsTraits : public T {
2.175 + const X &_nodeColors;
2.176 + NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
2.177 };
2.178 - ///\e
2.179 - template<class X> GraphToEps<SetEdgeColorsTraits<X> >
2.180 - setEdgeColors(const X &x)
2.181 + ///Sets the map of the node colors
2.182 +
2.183 + ///Sets the map of the node colors
2.184 + ///\param x must be a node map with \ref Color values.
2.185 + template<class X> GraphToEps<NodeColorsTraits<X> >
2.186 + nodeColors(const X &x)
2.187 {
2.188 dontPrint=true;
2.189 - return GraphToEps<SetEdgeColorsTraits<X> >(SetEdgeColorsTraits<X>(*this,x));
2.190 + return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
2.191 }
2.192 - ///\e
2.193 - GraphToEps<T> &scaleNodeSize(double d) {nodeSizeScalar=d;return *this;}
2.194 + template<class X> struct EdgeColorsTraits : public T {
2.195 + const X &_edgeColors;
2.196 + EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
2.197 + };
2.198 + ///Sets the map of the edge colors
2.199 +
2.200 + ///Sets the map of the edge colors
2.201 + ///\param x must be a edge map with \ref Color values.
2.202 + template<class X> GraphToEps<EdgeColorsTraits<X> >
2.203 + edgeColors(const X &x)
2.204 + {
2.205 + dontPrint=true;
2.206 + return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x));
2.207 + }
2.208 + ///Sets a global scale factor for node sizes
2.209 +
2.210 + ///Sets a global scale factor for node sizes
2.211 + ///
2.212 + GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
2.213 + ///Sets a global scale factor for edge widths
2.214 +
2.215 + ///Sets a global scale factor for edge widths
2.216 + ///
2.217 + GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;}
2.218 + ///Sets a global scale factor for the whole picture
2.219 +
2.220 + ///Sets a global scale factor for the whole picture
2.221 + ///
2.222 + GraphToEps<T> &scale(double d) {_scale=d;return *this;}
2.223 + ///Sets the width of the border around the picture
2.224 +
2.225 + ///Sets the width of the border around the picture
2.226 + ///
2.227 + GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
2.228 + ///Sets the width of the border around the picture
2.229 +
2.230 + ///Sets the width of the border around the picture
2.231 + ///
2.232 + GraphToEps<T> &border(double x, double y) {
2.233 + _xBorder=x;_yBorder=y;return *this;
2.234 + }
2.235 + ///Sets whether to draw arrows
2.236 +
2.237 + ///Sets whether to draw arrows
2.238 + ///
2.239 + GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
2.240 + ///Sets the length of the arrowheads
2.241 +
2.242 + ///Sets the length of the arrowheads
2.243 + ///
2.244 + GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
2.245 + ///Sets the width of the arrowheads
2.246 +
2.247 + ///Sets the width of the arrowheads
2.248 + ///
2.249 + GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
2.250
2.251 ~GraphToEps()
2.252 {
2.253 @@ -121,44 +217,98 @@
2.254 cout << "%!PS-Adobe-2.0 EPSF-2.0\n";
2.255 //\todo: Chech whether the graph is empty.
2.256 BoundingBox<double> bb;
2.257 - for(NodeIt n(g);
2.258 - n!=INVALID;
2.259 - ++n) {
2.260 - xy<double> p(nodeSizes[n]*nodeSizeScalar,nodeSizes[n]*nodeSizeScalar);
2.261 - bb+=coords[n]+p;
2.262 - bb+=coords[n]-p;
2.263 + for(NodeIt n(g);n!=INVALID;++n) {
2.264 + double ns=_nodeSizes[n]*_nodeScale;
2.265 + xy<double> p(ns,ns);
2.266 + bb+=p+_coords[n];
2.267 + bb+=-p+_coords[n];
2.268 }
2.269 cout << "%%BoundingBox: "
2.270 - << bb.left()-xBorder << ' ' << bb.bottom()-yBorder << ' '
2.271 - << bb.right()+xBorder << ' ' << bb.top()+yBorder << '\n';
2.272 - //x1 y1 x2 y2 cr cg cb
2.273 - cout << "/l { setrgbcolor newpath moveto lineto stroke } bind def\n";
2.274 + << bb.left()* _scale-_xBorder << ' '
2.275 + << bb.bottom()*_scale-_yBorder << ' '
2.276 + << bb.right()* _scale+_xBorder << ' '
2.277 + << bb.top()* _scale+_yBorder << '\n';
2.278 + //x1 y1 x2 y2 cr cg cb w
2.279 + cout << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
2.280 cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
2.281 // x y r cr cg cb
2.282 cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
2.283 - << " 0 0 0 setrgbcolor dup 10 div setlinewidth c stroke\n"
2.284 + << " 0 0 0 setrgbcolor dup "
2.285 + << _nodeBorderQuotient << " mul setlinewidth "
2.286 + << 1+_nodeBorderQuotient/2 << " div c stroke\n"
2.287 << " } bind def\n";
2.288 -
2.289 + cout << "/arrl " << _arrowLength << " def\n";
2.290 + cout << "/arrw " << _arrowWidth << " def\n";
2.291 + // l dx_norm dy_norm
2.292 + cout << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
2.293 + //len w dx_norm dy_norm x1 y1 cr cg cb
2.294 + cout << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
2.295 + << " /w exch def /len exch def\n"
2.296 + // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
2.297 + << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
2.298 + << " len w sub arrl sub dx dy lrl\n"
2.299 + << " arrw dy dx neg lrl\n"
2.300 + << " dx arrl w add mul dy w 2 div arrw add mul sub\n"
2.301 + << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
2.302 + << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
2.303 + << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
2.304 + << " arrw dy dx neg lrl\n"
2.305 + << " len w sub arrl sub neg dx dy lrl\n"
2.306 + << " closepath fill } bind def\n";
2.307 + cout << "\ngsave\n";
2.308 + if(_scale!=1.0) cout << _scale << " dup scale\n";
2.309 cout << "%Edges:\ngsave\n";
2.310 for(NodeIt n(g);n!=INVALID;++n)
2.311 for(OutEdgeIt e(g,n);e!=INVALID;++e)
2.312 - cout << coords[g.source(e)].x << ' ' << coords[g.source(e)].y << ' '
2.313 - << coords[g.target(e)].x << ' ' << coords[g.target(e)].y << ' '
2.314 - << edgeColors[e].getR() << ' '
2.315 - << edgeColors[e].getG() << ' '
2.316 - << edgeColors[e].getB() << " l\n";
2.317 + if(_drawArrows) {
2.318 + xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
2.319 + double l=sqrt(d.normSquare());
2.320 + d/=l;
2.321 + xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
2.322 + _coords[g.source(e)]);
2.323 + cout << l-(_nodeSizes[g.source(e)]+
2.324 + _nodeSizes[g.target(e)])*_nodeScale << ' '
2.325 + << _edgeWidths[e]*_edgeWidthScale << ' '
2.326 + << d.x << ' ' << d.y << ' '
2.327 + << x1.x << ' ' << x1.y << ' '
2.328 + << _edgeColors[e].getR() << ' '
2.329 + << _edgeColors[e].getG() << ' '
2.330 + << _edgeColors[e].getB() << " arr\n";
2.331 + }
2.332 + else cout << _coords[g.source(e)].x << ' '
2.333 + << _coords[g.source(e)].y << ' '
2.334 + << _coords[g.target(e)].x << ' '
2.335 + << _coords[g.target(e)].y << ' '
2.336 + << _edgeColors[e].getR() << ' '
2.337 + << _edgeColors[e].getG() << ' '
2.338 + << _edgeColors[e].getB() << ' '
2.339 + << _edgeWidths[e]*_edgeWidthScale << " l\n";
2.340 cout << "grestore\n%Nodes:\ngsave\n";
2.341 for(NodeIt n(g);n!=INVALID;++n)
2.342 - cout << coords[n].x << ' ' << coords[n].y << ' '
2.343 - << nodeSizes[n]*nodeSizeScalar << ' '
2.344 - << nodeColors[n].getR() << ' '
2.345 - << nodeColors[n].getG() << ' '
2.346 - << nodeColors[n].getB() << " n\n";
2.347 - cout << "grestore\n";
2.348 + cout << _coords[n].x << ' ' << _coords[n].y << ' '
2.349 + << _nodeSizes[n]*_nodeScale << ' '
2.350 + << _nodeColors[n].getR() << ' '
2.351 + << _nodeColors[n].getG() << ' '
2.352 + << _nodeColors[n].getB() << " n\n";
2.353 + cout << "grestore\ngrestore\n";
2.354 }
2.355 };
2.356
2.357
2.358 +///Generates an EPS file from a graph
2.359 +
2.360 +///\ingroup misc
2.361 +///Generates an EPS file from a graph.
2.362 +///
2.363 +///This function has a lot of \ref named-templ-param "named parameters",
2.364 +///they are declared as the members of class \ref GraphToEps. The following
2.365 +///example shows how to use these parameters.
2.366 +///\code
2.367 +/// graphToEps(g).scale(10).coords(coords)
2.368 +/// .nodeScale(2).nodeSizes(sizes)
2.369 +/// .edgeWidthScale(.4);
2.370 +///\endcode
2.371 +///\sa GraphToEps
2.372 template<class G>
2.373 GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g)
2.374 {
2.375 @@ -194,7 +344,7 @@
2.376 typedef ListGraph::Node Node;
2.377 typedef ListGraph::NodeIt NodeIt;
2.378 typedef ListGraph::Edge Edge;
2.379 - typedef xy<double> Xy;
2.380 + typedef xy<int> Xy;
2.381
2.382 Node n1=g.addNode();
2.383 Node n2=g.addNode();
2.384 @@ -206,6 +356,7 @@
2.385 ListGraph::NodeMap<double> sizes(g);
2.386 ListGraph::NodeMap<int> colors(g);
2.387 ListGraph::EdgeMap<int> ecolors(g);
2.388 + ListGraph::EdgeMap<int> widths(g);
2.389
2.390 coords[n1]=Xy(50,50); sizes[n1]=1; colors[n1]=1;
2.391 coords[n2]=Xy(50,70); sizes[n2]=2; colors[n2]=2;
2.392 @@ -215,16 +366,19 @@
2.393
2.394 Edge e;
2.395
2.396 - e=g.addEdge(n1,n2); ecolors[e]=0;
2.397 - e=g.addEdge(n2,n3); ecolors[e]=0;
2.398 - e=g.addEdge(n3,n5); ecolors[e]=0;
2.399 - e=g.addEdge(n5,n4); ecolors[e]=0;
2.400 - e=g.addEdge(n4,n1); ecolors[e]=0;
2.401 - e=g.addEdge(n2,n4); ecolors[e]=1;
2.402 - e=g.addEdge(n3,n4); ecolors[e]=2;
2.403 + e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1;
2.404 + e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1;
2.405 + e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3;
2.406 + e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
2.407 + e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
2.408 + e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
2.409 + e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
2.410
2.411 - graphToEps(g).setCoords(coords).
2.412 - scaleNodeSize(2).setNodeSizes(sizes).
2.413 - setNodeColors(composeMap(colorSet,colors)).
2.414 - setEdgeColors(composeMap(colorSet,ecolors));
2.415 + graphToEps(g).scale(10).coords(coords).
2.416 + nodeScale(2).nodeSizes(sizes).
2.417 + nodeColors(composeMap(colorSet,colors)).
2.418 + edgeColors(composeMap(colorSet,ecolors)).
2.419 + edgeWidthScale(.4).edgeWidths(widths).
2.420 + drawArrows().arrowWidth(1).arrowLength(1)
2.421 + ;
2.422 }