graph_to_eps mission accomplished.
authoralpar
Tue, 11 Jan 2005 09:15:25 +0000
changeset 1073bedab8bd915f
parent 1072 ce824c6ffd5d
child 1074 4a24a46407db
graph_to_eps mission accomplished.
- lemon/graph_to_eps.h header created
- lemon/bezier.h: Tools to compute with bezier curves (unclean and undocumented
interface, used internally by graph_to_eps.h)
- demo/graph_to_eps_demo.cc: a simple demo for lemon/graph_to_eps.h
src/demo/Makefile.am
src/demo/graph_to_eps_demo.cc
src/lemon/Makefile.am
src/lemon/bezier.h
src/lemon/graph_to_eps.h
src/work/alpar/graph_to_eps.cc
     1.1 --- a/src/demo/Makefile.am	Tue Jan 11 09:09:50 2005 +0000
     1.2 +++ b/src/demo/Makefile.am	Tue Jan 11 09:15:25 2005 +0000
     1.3 @@ -2,8 +2,10 @@
     1.4  
     1.5  EXTRA_DIST = sub_graph_wrapper_demo.dim
     1.6  
     1.7 -noinst_PROGRAMS = dim_to_dot sub_graph_wrapper_demo
     1.8 +noinst_PROGRAMS = dim_to_dot sub_graph_wrapper_demo graph_to_eps_demo
     1.9  
    1.10  dim_to_dot_SOURCES = dim_to_dot.cc
    1.11  
    1.12  sub_graph_wrapper_demo_SOURCES = sub_graph_wrapper_demo.cc tight_edge_filter_map.h
    1.13 +
    1.14 +graph_to_eps_demo_SOURCES = graph_to_eps_demo.cc
    1.15 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/src/demo/graph_to_eps_demo.cc	Tue Jan 11 09:15:25 2005 +0000
     2.3 @@ -0,0 +1,133 @@
     2.4 +/* -*- C++ -*-
     2.5 + * src/lemon/demo/graph_to_eps.cc - 
     2.6 + * Part of LEMON, a generic C++ optimization library
     2.7 + *
     2.8 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     2.9 + * (Egervary Combinatorial Optimization Research Group, EGRES).
    2.10 + *
    2.11 + * Permission to use, modify and distribute this software is granted
    2.12 + * provided that this copyright notice appears in all copies. For
    2.13 + * precise terms see the accompanying LICENSE file.
    2.14 + *
    2.15 + * This software is provided "AS IS" with no warranty of any kind,
    2.16 + * express or implied, and with no claim as to its suitability for any
    2.17 + * purpose.
    2.18 + *
    2.19 + */
    2.20 +
    2.21 +#include<lemon/graph_to_eps.h>
    2.22 +#include<lemon/maps.h>
    2.23 +#include<lemon/list_graph.h>
    2.24 +
    2.25 +
    2.26 +using namespace std;
    2.27 +using namespace lemon;
    2.28 +
    2.29 +class ColorSet : public MapBase<int,Color>
    2.30 +{
    2.31 +public:
    2.32 +  Color operator[](int i) const
    2.33 +  {
    2.34 +    switch(i%8){
    2.35 +    case 0: return Color(0,0,0);
    2.36 +    case 1: return Color(1,0,0);
    2.37 +    case 2: return Color(0,1,0);
    2.38 +    case 3: return Color(0,0,1);
    2.39 +    case 4: return Color(1,1,0);
    2.40 +    case 5: return Color(1,0,1);
    2.41 +    case 6: return Color(0,1,1);
    2.42 +    case 7: return Color(1,1,1);
    2.43 +    }
    2.44 +    return Color(0,0,0);
    2.45 +  }
    2.46 +} colorSet;
    2.47 +
    2.48 +class IdMap :public MapBase<ListGraph::Node,int>
    2.49 +{
    2.50 +  const ListGraph &g;
    2.51 +public:
    2.52 +  IdMap(const ListGraph &_g) :g(_g) {}
    2.53 +  Value operator[](Key n) const { return g.id(n); }
    2.54 +};
    2.55 +
    2.56 +int main()
    2.57 +{
    2.58 +  ListGraph g;
    2.59 +  typedef ListGraph::Node Node;
    2.60 +  typedef ListGraph::NodeIt NodeIt;
    2.61 +  typedef ListGraph::Edge Edge;
    2.62 +  typedef xy<int> Xy;
    2.63 +  
    2.64 +  Node n1=g.addNode();
    2.65 +  Node n2=g.addNode();
    2.66 +  Node n3=g.addNode();
    2.67 +  Node n4=g.addNode();
    2.68 +  Node n5=g.addNode();
    2.69 +
    2.70 +  ListGraph::NodeMap<Xy> coords(g);
    2.71 +  ListGraph::NodeMap<double> sizes(g);
    2.72 +  ListGraph::NodeMap<int> colors(g);
    2.73 +  ListGraph::EdgeMap<int> ecolors(g);
    2.74 +  ListGraph::EdgeMap<int> widths(g);
    2.75 +  
    2.76 +  coords[n1]=Xy(50,50);  sizes[n1]=1; colors[n1]=1;
    2.77 +  coords[n2]=Xy(50,70);  sizes[n2]=2; colors[n2]=2;
    2.78 +  coords[n3]=Xy(70,70);  sizes[n3]=1; colors[n3]=3;
    2.79 +  coords[n4]=Xy(70,50);  sizes[n4]=2; colors[n4]=4;
    2.80 +  coords[n5]=Xy(85,60);  sizes[n5]=3; colors[n5]=5;
    2.81 +  
    2.82 +  Edge e;
    2.83 +
    2.84 +  e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1;
    2.85 +  e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1;
    2.86 +  e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3;
    2.87 +  e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
    2.88 +  e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
    2.89 +  e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
    2.90 +  e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
    2.91 +  
    2.92 +  IdMap id(g);
    2.93 +
    2.94 +  graphToEps(g,"graph_to_eps_demo_out.eps").scale(10).coords(coords).
    2.95 +    nodeScale(2).nodeSizes(sizes).
    2.96 +    nodeColors(composeMap(colorSet,colors)).
    2.97 +    edgeColors(composeMap(colorSet,ecolors)).
    2.98 +    edgeWidthScale(.4).edgeWidths(widths).
    2.99 +    nodeTexts(id).nodeTextSize(3);
   2.100 +
   2.101 +  graphToEps(g,"graph_to_eps_demo_out_arr.eps").scale(10).coords(coords).
   2.102 +    nodeScale(2).nodeSizes(sizes).
   2.103 +    nodeColors(composeMap(colorSet,colors)).
   2.104 +    edgeColors(composeMap(colorSet,ecolors)).
   2.105 +    edgeWidthScale(.4).edgeWidths(widths).
   2.106 +    nodeTexts(id).nodeTextSize(3).
   2.107 +    drawArrows().arrowWidth(1).arrowLength(1);
   2.108 +
   2.109 +  e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1;
   2.110 +  e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2;
   2.111 +
   2.112 +  e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1;
   2.113 +  e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1;
   2.114 +  e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1;
   2.115 +  e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1;
   2.116 +  e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1;
   2.117 +  e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1;
   2.118 +  e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1;
   2.119 +
   2.120 +  graphToEps(g,"graph_to_eps_demo_out_par.eps").scale(10).coords(coords).
   2.121 +    nodeScale(2).nodeSizes(sizes).
   2.122 +    nodeColors(composeMap(colorSet,colors)).
   2.123 +    edgeColors(composeMap(colorSet,ecolors)).
   2.124 +    edgeWidthScale(.4).edgeWidths(widths).
   2.125 +    nodeTexts(id).nodeTextSize(3).
   2.126 +    enableParallel().parEdgeDist(1.5);
   2.127 +
   2.128 +  graphToEps(g,"graph_to_eps_demo_out_par_arr.eps").scale(10).coords(coords).
   2.129 +    nodeScale(2).nodeSizes(sizes).
   2.130 +    nodeColors(composeMap(colorSet,colors)).
   2.131 +    edgeColors(composeMap(colorSet,ecolors)).
   2.132 +    edgeWidthScale(.3).edgeWidths(widths).
   2.133 +    nodeTexts(id).nodeTextSize(3).
   2.134 +    enableParallel().parEdgeDist(1).
   2.135 +    drawArrows().arrowWidth(1).arrowLength(1);
   2.136 +}
     3.1 --- a/src/lemon/Makefile.am	Tue Jan 11 09:09:50 2005 +0000
     3.2 +++ b/src/lemon/Makefile.am	Tue Jan 11 09:15:25 2005 +0000
     3.3 @@ -1,6 +1,7 @@
     3.4  pkginclude_HEADERS =							\
     3.5  	map_defines.h							\
     3.6  	array_map.h                                                     \
     3.7 +	bezier.h                                                        \
     3.8  	bfs.h                                                           \
     3.9  	dfs.h                                                           \
    3.10  	bin_heap.h							\
    3.11 @@ -11,6 +12,7 @@
    3.12  	full_graph.h							\
    3.13  	graph_wrapper.h							\
    3.14  	graph_utils.h							\
    3.15 +	graph_to_eps.h                                                  \
    3.16  	invalid.h							\
    3.17  	kruskal.h							\
    3.18  	list_graph.h							\
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/lemon/bezier.h	Tue Jan 11 09:15:25 2005 +0000
     4.3 @@ -0,0 +1,139 @@
     4.4 +/* -*- C++ -*-
     4.5 + * src/lemon/bezier.h - Part of LEMON, a generic C++ optimization library
     4.6 + *
     4.7 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     4.8 + * (Egervary Combinatorial Optimization Research Group, EGRES).
     4.9 + *
    4.10 + * Permission to use, modify and distribute this software is granted
    4.11 + * provided that this copyright notice appears in all copies. For
    4.12 + * precise terms see the accompanying LICENSE file.
    4.13 + *
    4.14 + * This software is provided "AS IS" with no warranty of any kind,
    4.15 + * express or implied, and with no claim as to its suitability for any
    4.16 + * purpose.
    4.17 + *
    4.18 + */
    4.19 +
    4.20 +#ifndef LEMON_BEZIER_H
    4.21 +#define LEMON_BEZIER_H
    4.22 +
    4.23 +///\ingroup misc
    4.24 +///\file
    4.25 +///\brief Classes to compute with Bezier curves.
    4.26 +///
    4.27 +///Up to now this file is internally used by \ref graph_to_eps.h
    4.28 +///
    4.29 +///\author Alpar Juttner
    4.30 +
    4.31 +#include<lemon/xy.h>
    4.32 +
    4.33 +namespace lemon {
    4.34 +
    4.35 +class BezierBase {
    4.36 +public:
    4.37 +  typedef xy<double> xy;
    4.38 +protected:
    4.39 +  static xy conv(xy x,xy y,double t) {return (1-t)*x+t*y;}
    4.40 +};
    4.41 +
    4.42 +class Bezier1 : public BezierBase
    4.43 +{
    4.44 +public:
    4.45 +  xy p1,p2;
    4.46 +
    4.47 +  Bezier1() {}
    4.48 +  Bezier1(xy _p1, xy _p2) :p1(_p1), p2(_p2) {}
    4.49 +  
    4.50 +  xy operator()(double t) const
    4.51 +  {
    4.52 +    //    return conv(conv(p1,p2,t),conv(p2,p3,t),t);
    4.53 +    return conv(p1,p2,t);
    4.54 +  }
    4.55 +  Bezier1 before(double t) const
    4.56 +  {
    4.57 +    return Bezier1(p1,conv(p1,p2,t));
    4.58 +  }
    4.59 +  
    4.60 +  Bezier1 after(double t) const
    4.61 +  {
    4.62 +    return Bezier1(conv(p1,p2,t),p2);
    4.63 +  }
    4.64 +  Bezier1 operator()(double a,double b) { return before(b).after(a/b); }  
    4.65 +};
    4.66 +
    4.67 +class Bezier2 : public BezierBase
    4.68 +{
    4.69 +public:
    4.70 +  xy p1,p2,p3;
    4.71 +
    4.72 +  Bezier2() {}
    4.73 +  Bezier2(xy _p1, xy _p2, xy _p3) :p1(_p1), p2(_p2), p3(_p3) {}
    4.74 +  Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
    4.75 +  xy operator()(double t) const
    4.76 +  {
    4.77 +    //    return conv(conv(p1,p2,t),conv(p2,p3,t),t);
    4.78 +    return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
    4.79 +  }
    4.80 +  Bezier2 before(double t) const
    4.81 +  {
    4.82 +    xy q(conv(p1,p2,t));
    4.83 +    xy r(conv(p2,p3,t));
    4.84 +    return Bezier2(p1,q,conv(q,r,t));
    4.85 +  }
    4.86 +  
    4.87 +  Bezier2 after(double t) const
    4.88 +  {
    4.89 +    xy q(conv(p1,p2,t));
    4.90 +    xy r(conv(p2,p3,t));
    4.91 +    return Bezier2(conv(q,r,t),r,p3);
    4.92 +  }
    4.93 +  Bezier2 operator()(double a,double b) { return before(b).after(a/b); }
    4.94 +  
    4.95 +};
    4.96 +
    4.97 +class Bezier3 : public BezierBase
    4.98 +{
    4.99 +public:
   4.100 +  xy p1,p2,p3,p4;
   4.101 +
   4.102 +  Bezier3() {}
   4.103 +  Bezier3(xy _p1, xy _p2, xy _p3, xy _p4) :p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
   4.104 +  Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), 
   4.105 +			      p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
   4.106 +  Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
   4.107 +			      p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
   4.108 +  
   4.109 +  xy operator()(double t) const 
   4.110 +    {
   4.111 +      //    return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
   4.112 +      return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
   4.113 +	(3*t*t*(1-t))*p3+(t*t*t)*p4;
   4.114 +    }
   4.115 +  Bezier3 before(double t) const
   4.116 +    {
   4.117 +      xy p(conv(p1,p2,t));
   4.118 +      xy q(conv(p2,p3,t));
   4.119 +      xy r(conv(p3,p4,t));
   4.120 +      xy a(conv(p,q,t));
   4.121 +      xy b(conv(q,r,t));
   4.122 +      xy c(conv(a,b,t));
   4.123 +      return Bezier3(p1,p,a,c);
   4.124 +    }
   4.125 +  
   4.126 +  Bezier3 after(double t) const
   4.127 +    {
   4.128 +      xy p(conv(p1,p2,t));
   4.129 +      xy q(conv(p2,p3,t));
   4.130 +      xy r(conv(p3,p4,t));
   4.131 +      xy a(conv(p,q,t));
   4.132 +      xy b(conv(q,r,t));
   4.133 +      xy c(conv(a,b,t));
   4.134 +      return Bezier3(c,b,r,p4);
   4.135 +    }
   4.136 +  Bezier3 operator()(double a,double b) { return before(b).after(a/b); }
   4.137 +  
   4.138 +};
   4.139 +
   4.140 +} //END OF NAMESPACE LEMON
   4.141 +
   4.142 +#endif // LEMON_BEZIER_H
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/lemon/graph_to_eps.h	Tue Jan 11 09:15:25 2005 +0000
     5.3 @@ -0,0 +1,597 @@
     5.4 +/* -*- C++ -*-
     5.5 + * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library
     5.6 + *
     5.7 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5.8 + * (Egervary Combinatorial Optimization Research Group, EGRES).
     5.9 + *
    5.10 + * Permission to use, modify and distribute this software is granted
    5.11 + * provided that this copyright notice appears in all copies. For
    5.12 + * precise terms see the accompanying LICENSE file.
    5.13 + *
    5.14 + * This software is provided "AS IS" with no warranty of any kind,
    5.15 + * express or implied, and with no claim as to its suitability for any
    5.16 + * purpose.
    5.17 + *
    5.18 + */
    5.19 +
    5.20 +#ifndef LEMON_GRAPH_TO_EPS_H
    5.21 +#define LEMON_GRAPH_TO_EPS_H
    5.22 +
    5.23 +#include<iostream>
    5.24 +#include<fstream>
    5.25 +#include<sstream>
    5.26 +#include<algorithm>
    5.27 +#include<vector>
    5.28 +
    5.29 +#include<lemon/xy.h>
    5.30 +#include<lemon/maps.h>
    5.31 +#include<lemon/bezier.h>
    5.32 +
    5.33 +///\ingroup misc
    5.34 +///\file
    5.35 +///\brief Simple graph drawer
    5.36 +///
    5.37 +///\author Alpar Juttner
    5.38 +
    5.39 +namespace lemon {
    5.40 +
    5.41 +///Data structure representing RGB colors.
    5.42 +
    5.43 +///Data structure representing RGB colors.
    5.44 +///\ingroup misc
    5.45 +class Color
    5.46 +{
    5.47 +  double _r,_g,_b;
    5.48 +public:
    5.49 +  ///Default constructor
    5.50 +  Color() {}
    5.51 +  ///Constructor
    5.52 +  Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
    5.53 +  ///Returns the red component
    5.54 +  double getR() {return _r;}
    5.55 +  ///Returns the green component
    5.56 +  double getG() {return _g;}
    5.57 +  ///Returns the blue component
    5.58 +  double getB() {return _b;}
    5.59 +  ///Set the color components
    5.60 +  void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    5.61 +};
    5.62 +  
    5.63 +///Default traits class of \ref GraphToEps
    5.64 +
    5.65 +///Default traits class of \ref GraphToEps
    5.66 +///
    5.67 +///\c G is the type of the underlying graph.
    5.68 +template<class G>
    5.69 +struct DefaultGraphToEpsTraits
    5.70 +{
    5.71 +  typedef G Graph;
    5.72 +  typedef typename Graph::Node Node;
    5.73 +  typedef typename Graph::NodeIt NodeIt;
    5.74 +  typedef typename Graph::Edge Edge;
    5.75 +  typedef typename Graph::EdgeIt EdgeIt;
    5.76 +  typedef typename Graph::InEdgeIt InEdgeIt;
    5.77 +  typedef typename Graph::OutEdgeIt OutEdgeIt;
    5.78 +  
    5.79 +
    5.80 +  const Graph &g;
    5.81 +
    5.82 +  std::ostream& os;
    5.83 +  
    5.84 +  ConstMap<typename Graph::Node,xy<double> > _coords;
    5.85 +  ConstMap<typename Graph::Node,double > _nodeSizes;
    5.86 +
    5.87 +  ConstMap<typename Graph::Node,Color > _nodeColors;
    5.88 +  ConstMap<typename Graph::Edge,Color > _edgeColors;
    5.89 +
    5.90 +  ConstMap<typename Graph::Edge,double > _edgeWidths;
    5.91 +  
    5.92 +  double _edgeWidthScale;
    5.93 +  
    5.94 +  double _nodeScale;
    5.95 +  double _xBorder, _yBorder;
    5.96 +  double _scale;
    5.97 +  double _nodeBorderQuotient;
    5.98 +  
    5.99 +  bool _drawArrows;
   5.100 +  double _arrowLength, _arrowWidth;
   5.101 +  
   5.102 +  bool _showNodes, _showEdges;
   5.103 +
   5.104 +  bool _enableParallel;
   5.105 +  double _parEdgeDist;
   5.106 +
   5.107 +  bool _showNodeText;
   5.108 +  ConstMap<typename Graph::Node,bool > _nodeTexts;  
   5.109 +  double _nodeTextSize;
   5.110 +
   5.111 +  bool _undir;
   5.112 +  bool _pleaseRemoveOsStream;
   5.113 +  ///Constructor
   5.114 +
   5.115 +  ///Constructor
   5.116 +  ///\param _g is a reference to the graph to be printed
   5.117 +  ///\param _os is a reference to the output stream.
   5.118 +  ///\param _os is a reference to the output stream.
   5.119 +  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
   5.120 +  ///will be explicitly deallocated by the destructor.
   5.121 +  ///By default it is <tt>std::cout</tt>
   5.122 +  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
   5.123 +			  bool _pros=false) :
   5.124 +    g(_g), os(_os),
   5.125 +    _coords(xy<double>(1,1)), _nodeSizes(1.0),
   5.126 +    _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
   5.127 +    _edgeWidths(1), _edgeWidthScale(0.3),
   5.128 +    _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
   5.129 +    _nodeBorderQuotient(.1),
   5.130 +    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   5.131 +    _showNodes(true), _showEdges(true),
   5.132 +    _enableParallel(false), _parEdgeDist(1),
   5.133 +    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
   5.134 +    _undir(false),
   5.135 +    _pleaseRemoveOsStream(_pros) {}
   5.136 +};
   5.137 +
   5.138 +///Helper class to implement the named parameters of \ref graphToEps()
   5.139 +
   5.140 +///Helper class to implement the named parameters of \ref graphToEps()
   5.141 +///\todo Is 'helper class' a good name for this?
   5.142 +///
   5.143 +template<class T> class GraphToEps : public T 
   5.144 +{
   5.145 +  typedef typename T::Graph Graph;
   5.146 +  typedef typename Graph::Node Node;
   5.147 +  typedef typename Graph::NodeIt NodeIt;
   5.148 +  typedef typename Graph::Edge Edge;
   5.149 +  typedef typename Graph::EdgeIt EdgeIt;
   5.150 +  typedef typename Graph::InEdgeIt InEdgeIt;
   5.151 +  typedef typename Graph::OutEdgeIt OutEdgeIt;
   5.152 +
   5.153 +  bool dontPrint;
   5.154 +
   5.155 +  class edgeLess {
   5.156 +    const Graph &g;
   5.157 +  public:
   5.158 +    edgeLess(const Graph &_g) : g(_g) {}
   5.159 +    bool operator()(Edge a,Edge b) const 
   5.160 +    {
   5.161 +      Node ai=min(g.source(a),g.target(a));
   5.162 +      Node aa=max(g.source(a),g.target(a));
   5.163 +      Node bi=min(g.source(b),g.target(b));
   5.164 +      Node ba=max(g.source(b),g.target(b));
   5.165 +      return ai<bi ||
   5.166 +	(ai==bi && (aa < ba || 
   5.167 +		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
   5.168 +    }
   5.169 +  };
   5.170 +  bool isParallel(Edge e,Edge f) const
   5.171 +  {
   5.172 +    return (g.source(e)==g.source(f)&&g.target(e)==g.target(f))||
   5.173 +      (g.source(e)==g.target(f)&&g.target(e)==g.source(f));
   5.174 +  }
   5.175 +  static xy<double> rot(xy<double> v) 
   5.176 +  {
   5.177 +    return xy<double>(v.y,-v.x);
   5.178 +  }
   5.179 +  template<class xy>
   5.180 +  static std::string psOut(const xy &p) 
   5.181 +    {
   5.182 +      std::ostringstream os;	
   5.183 +      os << p.x << ' ' << p.y;
   5.184 +      return os.str();
   5.185 +    }
   5.186 +  
   5.187 +public:
   5.188 +  GraphToEps(const T &t) : T(t), dontPrint(false) {};
   5.189 +  
   5.190 +  template<class X> struct CoordsTraits : public T {
   5.191 +    const X &_coords;
   5.192 +    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
   5.193 +  };
   5.194 +  ///Sets the map of the node coordinates
   5.195 +
   5.196 +  ///Sets the map of the node coordinates.
   5.197 +  ///\param x must be a node map with xy<double> or xy<int> values. 
   5.198 +  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
   5.199 +    dontPrint=true;
   5.200 +    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
   5.201 +  }
   5.202 +  template<class X> struct NodeSizesTraits : public T {
   5.203 +    const X &_nodeSizes;
   5.204 +    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
   5.205 +  };
   5.206 +  ///Sets the map of the node sizes
   5.207 +
   5.208 +  ///Sets the map of the node sizes
   5.209 +  ///\param x must be a node map with \c double (or convertible) values. 
   5.210 +  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
   5.211 +  {
   5.212 +    dontPrint=true;
   5.213 +    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
   5.214 +  }
   5.215 +  template<class X> struct NodeTextsTraits : public T {
   5.216 +    const X &_nodeTexts;
   5.217 +    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
   5.218 +  };
   5.219 +  ///Sets the text printed on the nodes
   5.220 +
   5.221 +  ///Sets the text printed on the nodes
   5.222 +  ///\param x must be a node map with type that can be pushed to a standard
   5.223 +  ///ostream. 
   5.224 +  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
   5.225 +  {
   5.226 +    dontPrint=true;
   5.227 +    _showNodeText=true;
   5.228 +    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
   5.229 +  }
   5.230 +   template<class X> struct EdgeWidthsTraits : public T {
   5.231 +    const X &_edgeWidths;
   5.232 +    EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   5.233 +  };
   5.234 +  ///Sets the map of the edge widths
   5.235 +
   5.236 +  ///Sets the map of the edge widths
   5.237 +  ///\param x must be a edge map with \c double (or convertible) values. 
   5.238 +  template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x)
   5.239 +  {
   5.240 +    dontPrint=true;
   5.241 +    return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x));
   5.242 +  }
   5.243 +
   5.244 +  template<class X> struct NodeColorsTraits : public T {
   5.245 +    const X &_nodeColors;
   5.246 +    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
   5.247 +  };
   5.248 +  ///Sets the map of the node colors
   5.249 +
   5.250 +  ///Sets the map of the node colors
   5.251 +  ///\param x must be a node map with \ref Color values. 
   5.252 +  template<class X> GraphToEps<NodeColorsTraits<X> >
   5.253 +  nodeColors(const X &x)
   5.254 +  {
   5.255 +    dontPrint=true;
   5.256 +    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
   5.257 +  }
   5.258 +  template<class X> struct EdgeColorsTraits : public T {
   5.259 +    const X &_edgeColors;
   5.260 +    EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
   5.261 +  };
   5.262 +  ///Sets the map of the edge colors
   5.263 +
   5.264 +  ///Sets the map of the edge colors
   5.265 +  ///\param x must be a edge map with \ref Color values. 
   5.266 +  template<class X> GraphToEps<EdgeColorsTraits<X> >
   5.267 +  edgeColors(const X &x)
   5.268 +  {
   5.269 +    dontPrint=true;
   5.270 +    return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x));
   5.271 +  }
   5.272 +  ///Sets a global scale factor for node sizes
   5.273 +
   5.274 +  ///Sets a global scale factor for node sizes
   5.275 +  ///
   5.276 +  GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
   5.277 +  ///Sets a global scale factor for edge widths
   5.278 +
   5.279 +  ///Sets a global scale factor for edge widths
   5.280 +  ///
   5.281 +  GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;}
   5.282 +  ///Sets a global scale factor for the whole picture
   5.283 +
   5.284 +  ///Sets a global scale factor for the whole picture
   5.285 +  ///
   5.286 +  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
   5.287 +  ///Sets the width of the border around the picture
   5.288 +
   5.289 +  ///Sets the width of the border around the picture
   5.290 +  ///
   5.291 +  GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
   5.292 +  ///Sets the width of the border around the picture
   5.293 +
   5.294 +  ///Sets the width of the border around the picture
   5.295 +  ///
   5.296 +  GraphToEps<T> &border(double x, double y) {
   5.297 +    _xBorder=x;_yBorder=y;return *this;
   5.298 +  }
   5.299 +  ///Sets whether to draw arrows
   5.300 +
   5.301 +  ///Sets whether to draw arrows
   5.302 +  ///
   5.303 +  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
   5.304 +  ///Sets the length of the arrowheads
   5.305 +
   5.306 +  ///Sets the length of the arrowheads
   5.307 +  ///
   5.308 +  GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
   5.309 +  ///Sets the width of the arrowheads
   5.310 +
   5.311 +  ///Sets the width of the arrowheads
   5.312 +  ///
   5.313 +  GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
   5.314 +  
   5.315 +  ///Enables parallel edges
   5.316 +
   5.317 +  ///Enables parallel edges
   5.318 +  ///\todo Partially implemented
   5.319 +  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
   5.320 +  
   5.321 +  ///Sets the distance 
   5.322 +  
   5.323 +  ///Sets the distance 
   5.324 +  ///
   5.325 +  GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;}
   5.326 +  
   5.327 +  ///Hides the edges
   5.328 +  
   5.329 +  ///Hides the edges
   5.330 +  ///
   5.331 +  GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;}
   5.332 +  ///Hides the nodes
   5.333 +  
   5.334 +  ///Hides the nodes
   5.335 +  ///
   5.336 +  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
   5.337 +  
   5.338 +  ///Sets the size of the node texts
   5.339 +  
   5.340 +  ///Sets the size of the node texts
   5.341 +  ///
   5.342 +  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
   5.343 +  ///Sets whether the the graph is undirected
   5.344 +
   5.345 +  ///Sets whether the the graph is undirected
   5.346 +  ///
   5.347 +  GraphToEps<T> &undir(bool b=true) {_undir=b;return *this;}
   5.348 +  ///Sets whether the the graph is directed
   5.349 +
   5.350 +  ///Sets whether the the graph is directed.
   5.351 +  ///Use it to show the undirected edges as a pair of directed ones.
   5.352 +  GraphToEps<T> &bidir(bool b=true) {_undir=!b;return *this;}
   5.353 +  
   5.354 +  ~GraphToEps() 
   5.355 +  {
   5.356 +    if(dontPrint) return;
   5.357 +    
   5.358 +    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
   5.359 +    //\todo: Chech whether the graph is empty.
   5.360 +    BoundingBox<double> bb;
   5.361 +    for(NodeIt n(g);n!=INVALID;++n) {
   5.362 +      double ns=_nodeSizes[n]*_nodeScale;
   5.363 +      xy<double> p(ns,ns);
   5.364 +      bb+=p+_coords[n];
   5.365 +      bb+=-p+_coords[n];
   5.366 +      }
   5.367 +    os << "%%BoundingBox: "
   5.368 +	 << bb.left()*  _scale-_xBorder << ' '
   5.369 +	 << bb.bottom()*_scale-_yBorder << ' '
   5.370 +	 << bb.right()* _scale+_xBorder << ' '
   5.371 +	 << bb.top()*   _scale+_yBorder << '\n';
   5.372 +    //x1 y1 x2 y2 x3 y3 cr cg cb w
   5.373 +    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
   5.374 +       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
   5.375 +    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
   5.376 +    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
   5.377 +    // x y r cr cg cb
   5.378 +    os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
   5.379 +       << "     0 0 0 setrgbcolor dup "
   5.380 +       << _nodeBorderQuotient << " mul setlinewidth "
   5.381 +       << 1+_nodeBorderQuotient/2 << " div c stroke\n"
   5.382 +       << "   } bind def\n";
   5.383 +    os << "/arrl " << _arrowLength << " def\n";
   5.384 +    os << "/arrw " << _arrowWidth << " def\n";
   5.385 +    // l dx_norm dy_norm
   5.386 +    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
   5.387 +    //len w dx_norm dy_norm x1 y1 cr cg cb
   5.388 +    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
   5.389 +       << "       /w exch def /len exch def\n"
   5.390 +      //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
   5.391 +       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
   5.392 +       << "       len w sub arrl sub dx dy lrl\n"
   5.393 +       << "       arrw dy dx neg lrl\n"
   5.394 +       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
   5.395 +       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
   5.396 +       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
   5.397 +       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
   5.398 +       << "       arrw dy dx neg lrl\n"
   5.399 +       << "       len w sub arrl sub neg dx dy lrl\n"
   5.400 +       << "       closepath fill } bind def\n";
   5.401 +    os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
   5.402 +       << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
   5.403 +
   5.404 +    os << "\ngsave\n";
   5.405 +    if(_scale!=1.0) os << _scale << " dup scale\n";
   5.406 +    
   5.407 +    os << "%Edges:\ngsave\n";
   5.408 +    
   5.409 +    if(_showEdges)
   5.410 +      if(_enableParallel) {
   5.411 +	std::vector<Edge> el;
   5.412 +	for(EdgeIt e(g);e!=INVALID;++e)
   5.413 +	  if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
   5.414 +	sort(el.begin(),el.end(),edgeLess(g));
   5.415 +	
   5.416 +	typename std::vector<Edge>::iterator j;
   5.417 +	for(typename std::vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
   5.418 +	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
   5.419 +
   5.420 +	  double sw=0;
   5.421 +	  for(typename std::vector<Edge>::iterator e=i;e!=j;++e)
   5.422 +	    sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
   5.423 +	  sw-=_parEdgeDist;
   5.424 +	  sw/=-2.0;
   5.425 +	  xy<double> d(_coords[g.target(*i)]-_coords[g.source(*i)]);
   5.426 +	  double l=sqrt(d.normSquare());
   5.427 +	  d/=l;
   5.428 +	  
   5.429 +	  for(typename std::vector<Edge>::iterator e=i;e!=j;++e) {
   5.430 +	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
   5.431 +	    xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]);
   5.432 +	    m=m/2.0+rot(d)*sw/.75;
   5.433 +	    if(_drawArrows) {
   5.434 +	      const int INERPOL_PREC=20;
   5.435 +	      xy<double> s=_coords[g.source(*e)];
   5.436 +	      xy<double> t=_coords[g.target(*e)];
   5.437 +	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
   5.438 +	      rn*=rn;
   5.439 +	      Bezier3 bez(s,m,m,t);
   5.440 +	      double t1=0,t2=1;
   5.441 +	      for(int i=0;i<INERPOL_PREC;++i)
   5.442 +		if((bez((t1+t2)/2)-t).normSquare()>rn) t1=(t1+t2)/2;
   5.443 +		else t2=(t1+t2)/2;
   5.444 +	      xy<double> apoint=bez((t1+t2)/2);
   5.445 +	      rn = _nodeSizes[g.target(*e)]*_nodeScale+_arrowLength+
   5.446 +		_edgeWidths[*e]*_edgeWidthScale;
   5.447 +	      rn*=rn;
   5.448 +	      t1=0;t2=1;
   5.449 +	      for(int i=0;i<INERPOL_PREC;++i)
   5.450 +		if((bez((t1+t2)/2)-t).normSquare()>rn) t1=(t1+t2)/2;
   5.451 +		else t2=(t1+t2)/2;
   5.452 +	      xy<double> linend=bez((t1+t2)/2);	      
   5.453 +	      bez=bez.before((t1+t2)/2);
   5.454 +	      rn=_nodeSizes[g.source(*e)]*_nodeScale; rn*=rn;
   5.455 +	      t1=0;t2=1;
   5.456 +	      for(int i=0;i<INERPOL_PREC;++i)
   5.457 +		if((bez((t1+t2)/2)-s).normSquare()>rn) t2=(t1+t2)/2;
   5.458 +		else t1=(t1+t2)/2;
   5.459 +	      bez=bez.after((t1+t2)/2);
   5.460 +	      os << _edgeWidths[*e]*_edgeWidthScale << " setlinewidth "
   5.461 +		 << _edgeColors[*e].getR() << ' '
   5.462 +		 << _edgeColors[*e].getG() << ' '
   5.463 +		 << _edgeColors[*e].getB() << " setrgbcolor newpath\n"
   5.464 +		 << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
   5.465 +		 << bez.p2.x << ' ' << bez.p2.y << ' '
   5.466 +		 << bez.p3.x << ' ' << bez.p3.y << ' '
   5.467 +		 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
   5.468 +	      xy<double> dd(rot(linend-apoint));
   5.469 +	      dd*=(_edgeWidths[*e]*_edgeWidthScale+_arrowWidth)/
   5.470 +		sqrt(dd.normSquare());
   5.471 +	      os << "newpath " << psOut(apoint) << " moveto "
   5.472 +		 << psOut(linend+dd) << " lineto "
   5.473 +		 << psOut(linend-dd) << " lineto closepath fill\n";
   5.474 +	    }
   5.475 +	    else {
   5.476 +	      os << _coords[g.source(*e)].x << ' '
   5.477 +		 << _coords[g.source(*e)].y << ' '
   5.478 +		 << m.x << ' ' << m.y << ' '
   5.479 +		 << _coords[g.target(*e)].x << ' '
   5.480 +		 << _coords[g.target(*e)].y << ' '
   5.481 +		 << _edgeColors[*e].getR() << ' '
   5.482 +		 << _edgeColors[*e].getG() << ' '
   5.483 +		 << _edgeColors[*e].getB() << ' '
   5.484 +		 << _edgeWidths[*e]*_edgeWidthScale << " lb\n";
   5.485 +	    }
   5.486 +	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
   5.487 +	  }
   5.488 +	}
   5.489 +      }
   5.490 +      else for(EdgeIt e(g);e!=INVALID;++e)
   5.491 +	if(!_undir||g.source(e)<g.target(e))
   5.492 +	  if(_drawArrows) {
   5.493 +	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   5.494 +	    double l=sqrt(d.normSquare());
   5.495 +	    d/=l;
   5.496 +	    xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
   5.497 +			  _coords[g.source(e)]);
   5.498 +	    os << l-(_nodeSizes[g.source(e)]+
   5.499 +		     _nodeSizes[g.target(e)])*_nodeScale << ' '
   5.500 +	       << _edgeWidths[e]*_edgeWidthScale << ' '
   5.501 +	       << d.x << ' ' << d.y << ' '
   5.502 +	       << x1.x << ' ' << x1.y << ' '
   5.503 +	       << _edgeColors[e].getR() << ' '
   5.504 +	       << _edgeColors[e].getG() << ' '
   5.505 +	       << _edgeColors[e].getB() << " arr\n";
   5.506 +	  }
   5.507 +	  else os << _coords[g.source(e)].x << ' '
   5.508 +		  << _coords[g.source(e)].y << ' '
   5.509 +		  << _coords[g.target(e)].x << ' '
   5.510 +		  << _coords[g.target(e)].y << ' '
   5.511 +		  << _edgeColors[e].getR() << ' '
   5.512 +		  << _edgeColors[e].getG() << ' '
   5.513 +		  << _edgeColors[e].getB() << ' '
   5.514 +		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
   5.515 +    os << "grestore\n%Nodes:\ngsave\n";
   5.516 +    if(_showNodes)
   5.517 +      for(NodeIt n(g);n!=INVALID;++n)
   5.518 +	os << _coords[n].x << ' ' << _coords[n].y << ' '
   5.519 +	   << _nodeSizes[n]*_nodeScale << ' '
   5.520 +	   << _nodeColors[n].getR() << ' '
   5.521 +	   << _nodeColors[n].getG() << ' '
   5.522 +	   << _nodeColors[n].getB() << " n\n"; 
   5.523 +    if(_showNodeText) {
   5.524 +      os << "grestore\n%Node texts:\ngsave\n";
   5.525 +      os << "/fosi " << _nodeTextSize << " def\n";
   5.526 +      os << "(Helvetica) findfont fosi scalefont setfont\n";
   5.527 +      os << "0 0 0 setrgbcolor\n";
   5.528 +      for(NodeIt n(g);n!=INVALID;++n)
   5.529 +	os << _coords[n].x << ' ' << _coords[n].y
   5.530 +	   << " (" << _nodeTexts[n] << ") cshow\n";
   5.531 +    }
   5.532 +    os << "grestore\ngrestore\n";
   5.533 +
   5.534 +    //CleanUp:
   5.535 +    if(_pleaseRemoveOsStream) {delete &os;}
   5.536 +  } 
   5.537 +};
   5.538 +
   5.539 +
   5.540 +///Generates an EPS file from a graph
   5.541 +
   5.542 +///\ingroup misc
   5.543 +///Generates an EPS file from a graph.
   5.544 +///\param g is a reference to the graph to be printed
   5.545 +///\param os is a reference to the output stream.
   5.546 +///By default it is <tt>std::cout</tt>
   5.547 +///
   5.548 +///This function also has a lot of \ref named-templ-param "named parameters",
   5.549 +///they are declared as the members of class \ref GraphToEps. The following
   5.550 +///example shows how to use these parameters.
   5.551 +///\code
   5.552 +/// graphToEps(g).scale(10).coords(coords)
   5.553 +///              .nodeScale(2).nodeSizes(sizes)
   5.554 +///              .edgeWidthScale(.4);
   5.555 +///\endcode
   5.556 +///\sa GraphToEps
   5.557 +///\sa graphToEps(G &g, char *file_name)
   5.558 +template<class G>
   5.559 +GraphToEps<DefaultGraphToEpsTraits<G> > 
   5.560 +graphToEps(G &g, std::ostream& os=std::cout)
   5.561 +{
   5.562 +  return 
   5.563 +    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
   5.564 +}
   5.565 + 
   5.566 +///Generates an EPS file from a graph
   5.567 +
   5.568 +//\ingroup misc
   5.569 +///This function does the same as
   5.570 +///\ref graphToEps(G &g,std::ostream& os)
   5.571 +///but it writes its output into the file \c file_name
   5.572 +///instead of a stream.
   5.573 +///\sa graphToEps(G &g, std::ostream& os)
   5.574 +template<class G>
   5.575 +GraphToEps<DefaultGraphToEpsTraits<G> > 
   5.576 +graphToEps(G &g,char *file_name)
   5.577 +{
   5.578 +  return GraphToEps<DefaultGraphToEpsTraits<G> >
   5.579 +    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
   5.580 +}
   5.581 +
   5.582 +//Generates an EPS file from a graph.
   5.583 +//\param g is a reference to the graph to be printed
   5.584 +//\param file_name is the output file_name.
   5.585 +//
   5.586 +//This function also has a lot of \ref named-templ-param "named parameters",
   5.587 +//they are declared as the members of class \ref GraphToEps. The following
   5.588 +//example shows how to use these parameters.
   5.589 +//\code
   5.590 +// graphToEps(g).scale(10).coords(coords)
   5.591 +//              .nodeScale(2).nodeSizes(sizes)
   5.592 +//              .edgeWidthScale(.4);
   5.593 +//\endcode
   5.594 +//\sa GraphToEps
   5.595 +//\todo Avoid duplicated documentation
   5.596 +//\bug Exception handling is missing? (Or we can just ignore it?)
   5.597 +
   5.598 +} //END OF NAMESPACE LEMON
   5.599 +
   5.600 +#endif // LEMON_GRAPH_TO_EPS_H
     6.1 --- a/src/work/alpar/graph_to_eps.cc	Tue Jan 11 09:09:50 2005 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,647 +0,0 @@
     6.4 -/* -*- C++ -*-
     6.5 - * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library
     6.6 - *
     6.7 - * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     6.8 - * (Egervary Combinatorial Optimization Research Group, EGRES).
     6.9 - *
    6.10 - * Permission to use, modify and distribute this software is granted
    6.11 - * provided that this copyright notice appears in all copies. For
    6.12 - * precise terms see the accompanying LICENSE file.
    6.13 - *
    6.14 - * This software is provided "AS IS" with no warranty of any kind,
    6.15 - * express or implied, and with no claim as to its suitability for any
    6.16 - * purpose.
    6.17 - *
    6.18 - */
    6.19 -
    6.20 -#include <iostream>
    6.21 -#include <fstream>
    6.22 -#include <algorithm>
    6.23 -#include<math.h>
    6.24 -
    6.25 -#include<lemon/xy.h>
    6.26 -#include<lemon/maps.h>
    6.27 -#include<lemon/list_graph.h>
    6.28 -
    6.29 -
    6.30 -///\ingroup misc
    6.31 -///\file
    6.32 -///\brief Simple graph drawer
    6.33 -
    6.34 -namespace lemon {
    6.35 -
    6.36 -///Data structure representing RGB colors.
    6.37 -
    6.38 -///Data structure representing RGB colors.
    6.39 -///\ingroup misc
    6.40 -class Color
    6.41 -{
    6.42 -  double _r,_g,_b;
    6.43 -public:
    6.44 -  ///Default constructor
    6.45 -  Color() {}
    6.46 -  ///Constructor
    6.47 -  Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
    6.48 -  ///Returns the red component
    6.49 -  double getR() {return _r;}
    6.50 -  ///Returns the green component
    6.51 -  double getG() {return _g;}
    6.52 -  ///Returns the blue component
    6.53 -  double getB() {return _b;}
    6.54 -  ///Set the color components
    6.55 -  void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    6.56 -};
    6.57 -  
    6.58 -///Default traits class of \ref GraphToEps
    6.59 -
    6.60 -///Default traits class of \ref GraphToEps
    6.61 -///
    6.62 -///\c G is the type of the underlying graph.
    6.63 -template<class G>
    6.64 -struct DefaultGraphToEpsTraits
    6.65 -{
    6.66 -  typedef G Graph;
    6.67 -  typedef typename Graph::Node Node;
    6.68 -  typedef typename Graph::NodeIt NodeIt;
    6.69 -  typedef typename Graph::Edge Edge;
    6.70 -  typedef typename Graph::EdgeIt EdgeIt;
    6.71 -  typedef typename Graph::InEdgeIt InEdgeIt;
    6.72 -  typedef typename Graph::OutEdgeIt OutEdgeIt;
    6.73 -  
    6.74 -
    6.75 -  const Graph &g;
    6.76 -
    6.77 -  std::ostream& os;
    6.78 -  
    6.79 -  ConstMap<typename Graph::Node,xy<double> > _coords;
    6.80 -  ConstMap<typename Graph::Node,double > _nodeSizes;
    6.81 -
    6.82 -  ConstMap<typename Graph::Node,Color > _nodeColors;
    6.83 -  ConstMap<typename Graph::Edge,Color > _edgeColors;
    6.84 -
    6.85 -  ConstMap<typename Graph::Edge,double > _edgeWidths;
    6.86 -  
    6.87 -  double _edgeWidthScale;
    6.88 -  
    6.89 -  double _nodeScale;
    6.90 -  double _xBorder, _yBorder;
    6.91 -  double _scale;
    6.92 -  double _nodeBorderQuotient;
    6.93 -  
    6.94 -  bool _drawArrows;
    6.95 -  double _arrowLength, _arrowWidth;
    6.96 -  
    6.97 -  bool _showNodes, _showEdges;
    6.98 -
    6.99 -  bool _enableParallel;
   6.100 -  double _parEdgeDist;
   6.101 -
   6.102 -  bool _showNodeText;
   6.103 -  ConstMap<typename Graph::Node,bool > _nodeTexts;  
   6.104 -  double _nodeTextSize;
   6.105 -
   6.106 -  bool _pleaseRemoveOsStream;
   6.107 -  ///Constructor
   6.108 -
   6.109 -  ///Constructor
   6.110 -  ///\param _g is a reference to the graph to be printed
   6.111 -  ///\param _os is a reference to the output stream.
   6.112 -  ///\param _os is a reference to the output stream.
   6.113 -  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
   6.114 -  ///will be explicitly deallocated by the destructor.
   6.115 -  ///By default it is <tt>std::cout</tt>
   6.116 -  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
   6.117 -			  bool _pros=false) :
   6.118 -    g(_g), os(_os),
   6.119 -    _coords(xy<double>(1,1)), _nodeSizes(1.0),
   6.120 -    _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
   6.121 -    _edgeWidths(1), _edgeWidthScale(0.3),
   6.122 -    _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
   6.123 -    _nodeBorderQuotient(.1),
   6.124 -    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   6.125 -    _showNodes(true), _showEdges(true),
   6.126 -    _enableParallel(false), _parEdgeDist(1),
   6.127 -    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
   6.128 -    _pleaseRemoveOsStream(_pros) {}
   6.129 -};
   6.130 -
   6.131 -///Helper class to implement the named parameters of \ref graphToEps()
   6.132 -
   6.133 -///Helper class to implement the named parameters of \ref graphToEps()
   6.134 -///\todo Is 'helper class' a good name for this?
   6.135 -///
   6.136 -template<class T> class GraphToEps : public T 
   6.137 -{
   6.138 -  typedef typename T::Graph Graph;
   6.139 -  typedef typename Graph::Node Node;
   6.140 -  typedef typename Graph::NodeIt NodeIt;
   6.141 -  typedef typename Graph::Edge Edge;
   6.142 -  typedef typename Graph::EdgeIt EdgeIt;
   6.143 -  typedef typename Graph::InEdgeIt InEdgeIt;
   6.144 -  typedef typename Graph::OutEdgeIt OutEdgeIt;
   6.145 -
   6.146 -  bool dontPrint;
   6.147 -
   6.148 -  class edgeLess {
   6.149 -    const Graph &g;
   6.150 -  public:
   6.151 -    edgeLess(const Graph &_g) : g(_g) {}
   6.152 -    bool operator()(Edge a,Edge b) const 
   6.153 -    {
   6.154 -      Node ai=min(g.source(a),g.target(a));
   6.155 -      Node aa=max(g.source(a),g.target(a));
   6.156 -      Node bi=min(g.source(b),g.target(b));
   6.157 -      Node ba=max(g.source(b),g.target(b));
   6.158 -      return ai<bi ||
   6.159 -	(ai==bi && (aa < ba || 
   6.160 -		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
   6.161 -    }
   6.162 -  };
   6.163 -  bool isParallel(Edge e,Edge f) const
   6.164 -  {
   6.165 -    return (g.source(e)==g.source(f)&&g.target(e)==g.target(f))||
   6.166 -      (g.source(e)==g.target(f)&&g.target(e)==g.source(f));
   6.167 -  }
   6.168 -  static xy<double> rot(xy<double> v) 
   6.169 -  {
   6.170 -    return xy<double>(v.y,-v.x);
   6.171 -  }
   6.172 -  
   6.173 -public:
   6.174 -  GraphToEps(const T &t) : T(t), dontPrint(false) {};
   6.175 -  
   6.176 -  template<class X> struct CoordsTraits : public T {
   6.177 -    const X &_coords;
   6.178 -    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
   6.179 -  };
   6.180 -  ///Sets the map of the node coordinates
   6.181 -
   6.182 -  ///Sets the map of the node coordinates.
   6.183 -  ///\param x must be a node map with xy<double> or xy<int> values. 
   6.184 -  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
   6.185 -    dontPrint=true;
   6.186 -    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
   6.187 -  }
   6.188 -  template<class X> struct NodeSizesTraits : public T {
   6.189 -    const X &_nodeSizes;
   6.190 -    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
   6.191 -  };
   6.192 -  ///Sets the map of the node sizes
   6.193 -
   6.194 -  ///Sets the map of the node sizes
   6.195 -  ///\param x must be a node map with \c double (or convertible) values. 
   6.196 -  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
   6.197 -  {
   6.198 -    dontPrint=true;
   6.199 -    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
   6.200 -  }
   6.201 -  template<class X> struct NodeTextsTraits : public T {
   6.202 -    const X &_nodeTexts;
   6.203 -    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
   6.204 -  };
   6.205 -  ///Sets the text printed on the nodes
   6.206 -
   6.207 -  ///Sets the text printed on the nodes
   6.208 -  ///\param x must be a node map with type that can be pushed to a standard
   6.209 -  ///ostream. 
   6.210 -  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
   6.211 -  {
   6.212 -    dontPrint=true;
   6.213 -    _showNodeText=true;
   6.214 -    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
   6.215 -  }
   6.216 -   template<class X> struct EdgeWidthsTraits : public T {
   6.217 -    const X &_edgeWidths;
   6.218 -    EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   6.219 -  };
   6.220 -  ///Sets the map of the edge widths
   6.221 -
   6.222 -  ///Sets the map of the edge widths
   6.223 -  ///\param x must be a edge map with \c double (or convertible) values. 
   6.224 -  template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x)
   6.225 -  {
   6.226 -    dontPrint=true;
   6.227 -    return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x));
   6.228 -  }
   6.229 -
   6.230 -  template<class X> struct NodeColorsTraits : public T {
   6.231 -    const X &_nodeColors;
   6.232 -    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
   6.233 -  };
   6.234 -  ///Sets the map of the node colors
   6.235 -
   6.236 -  ///Sets the map of the node colors
   6.237 -  ///\param x must be a node map with \ref Color values. 
   6.238 -  template<class X> GraphToEps<NodeColorsTraits<X> >
   6.239 -  nodeColors(const X &x)
   6.240 -  {
   6.241 -    dontPrint=true;
   6.242 -    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
   6.243 -  }
   6.244 -  template<class X> struct EdgeColorsTraits : public T {
   6.245 -    const X &_edgeColors;
   6.246 -    EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
   6.247 -  };
   6.248 -  ///Sets the map of the edge colors
   6.249 -
   6.250 -  ///Sets the map of the edge colors
   6.251 -  ///\param x must be a edge map with \ref Color values. 
   6.252 -  template<class X> GraphToEps<EdgeColorsTraits<X> >
   6.253 -  edgeColors(const X &x)
   6.254 -  {
   6.255 -    dontPrint=true;
   6.256 -    return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x));
   6.257 -  }
   6.258 -  ///Sets a global scale factor for node sizes
   6.259 -
   6.260 -  ///Sets a global scale factor for node sizes
   6.261 -  ///
   6.262 -  GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
   6.263 -  ///Sets a global scale factor for edge widths
   6.264 -
   6.265 -  ///Sets a global scale factor for edge widths
   6.266 -  ///
   6.267 -  GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;}
   6.268 -  ///Sets a global scale factor for the whole picture
   6.269 -
   6.270 -  ///Sets a global scale factor for the whole picture
   6.271 -  ///
   6.272 -  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
   6.273 -  ///Sets the width of the border around the picture
   6.274 -
   6.275 -  ///Sets the width of the border around the picture
   6.276 -  ///
   6.277 -  GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
   6.278 -  ///Sets the width of the border around the picture
   6.279 -
   6.280 -  ///Sets the width of the border around the picture
   6.281 -  ///
   6.282 -  GraphToEps<T> &border(double x, double y) {
   6.283 -    _xBorder=x;_yBorder=y;return *this;
   6.284 -  }
   6.285 -  ///Sets whether to draw arrows
   6.286 -
   6.287 -  ///Sets whether to draw arrows
   6.288 -  ///
   6.289 -  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
   6.290 -  ///Sets the length of the arrowheads
   6.291 -
   6.292 -  ///Sets the length of the arrowheads
   6.293 -  ///
   6.294 -  GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
   6.295 -  ///Sets the width of the arrowheads
   6.296 -
   6.297 -  ///Sets the width of the arrowheads
   6.298 -  ///
   6.299 -  GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
   6.300 -  
   6.301 -  ///Enables parallel edges
   6.302 -
   6.303 -  ///Enables parallel edges
   6.304 -  ///\todo Partially implemented
   6.305 -  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
   6.306 -  
   6.307 -  ///Sets the distance 
   6.308 -  
   6.309 -  ///Sets the distance 
   6.310 -  ///
   6.311 -  GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;}
   6.312 -  
   6.313 -  ///Hides the edges
   6.314 -  
   6.315 -  ///Hides the edges
   6.316 -  ///
   6.317 -  GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;}
   6.318 -  ///Hides the nodes
   6.319 -  
   6.320 -  ///Hides the nodes
   6.321 -  ///
   6.322 -  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
   6.323 -  
   6.324 -  ///Sets the size of the node texts
   6.325 -  
   6.326 -  ///Sets the size of the node texts
   6.327 -  ///
   6.328 -  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
   6.329 -
   6.330 -  
   6.331 -  ~GraphToEps() 
   6.332 -  {
   6.333 -    if(dontPrint) return;
   6.334 -    
   6.335 -    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
   6.336 -    //\todo: Chech whether the graph is empty.
   6.337 -    BoundingBox<double> bb;
   6.338 -    for(NodeIt n(g);n!=INVALID;++n) {
   6.339 -      double ns=_nodeSizes[n]*_nodeScale;
   6.340 -      xy<double> p(ns,ns);
   6.341 -      bb+=p+_coords[n];
   6.342 -      bb+=-p+_coords[n];
   6.343 -      }
   6.344 -    os << "%%BoundingBox: "
   6.345 -	 << bb.left()*  _scale-_xBorder << ' '
   6.346 -	 << bb.bottom()*_scale-_yBorder << ' '
   6.347 -	 << bb.right()* _scale+_xBorder << ' '
   6.348 -	 << bb.top()*   _scale+_yBorder << '\n';
   6.349 -    //x1 y1 x2 y2 x3 y3 cr cg cb w
   6.350 -    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
   6.351 -       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
   6.352 -    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
   6.353 -    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
   6.354 -    // x y r cr cg cb
   6.355 -    os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
   6.356 -       << "     0 0 0 setrgbcolor dup "
   6.357 -       << _nodeBorderQuotient << " mul setlinewidth "
   6.358 -       << 1+_nodeBorderQuotient/2 << " div c stroke\n"
   6.359 -       << "   } bind def\n";
   6.360 -    os << "/arrl " << _arrowLength << " def\n";
   6.361 -    os << "/arrw " << _arrowWidth << " def\n";
   6.362 -    // l dx_norm dy_norm
   6.363 -    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
   6.364 -    //len w dx_norm dy_norm x1 y1 cr cg cb
   6.365 -    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
   6.366 -       << "       /w exch def /len exch def\n"
   6.367 -      //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
   6.368 -       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
   6.369 -       << "       len w sub arrl sub dx dy lrl\n"
   6.370 -       << "       arrw dy dx neg lrl\n"
   6.371 -       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
   6.372 -       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
   6.373 -       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
   6.374 -       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
   6.375 -       << "       arrw dy dx neg lrl\n"
   6.376 -       << "       len w sub arrl sub neg dx dy lrl\n"
   6.377 -       << "       closepath fill } bind def\n";
   6.378 -    os << "/cshow { 2 index 2 index moveto\n"
   6.379 -       << "         dup stringwidth pop neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
   6.380 -
   6.381 -    os << "\ngsave\n";
   6.382 -    if(_scale!=1.0) os << _scale << " dup scale\n";
   6.383 -    
   6.384 -    os << "%Edges:\ngsave\n";
   6.385 -    
   6.386 -    if(_showEdges)
   6.387 -      if(_enableParallel) {
   6.388 -	vector<Edge> el;
   6.389 -	for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e);
   6.390 -	sort(el.begin(),el.end(),edgeLess(g));
   6.391 -	
   6.392 -	typename vector<Edge>::iterator j;
   6.393 -	for(typename vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
   6.394 -	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
   6.395 -	  
   6.396 -	  if(_drawArrows) {
   6.397 -	    // 	  xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   6.398 -	    // 	  double l=sqrt(d.normSquare());
   6.399 -	    // 	  d/=l;
   6.400 -	    // 	  xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
   6.401 -	    // 			_coords[g.source(e)]);
   6.402 -	    // 	  os << l-(_nodeSizes[g.source(e)]+
   6.403 -	    // 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
   6.404 -	    // 	       << _edgeWidths[e]*_edgeWidthScale << ' '
   6.405 -	    // 	       << d.x << ' ' << d.y << ' '
   6.406 -	    // 	       << x1.x << ' ' << x1.y << ' '
   6.407 -	    // 	       << _edgeColors[e].getR() << ' '
   6.408 -	    // 	       << _edgeColors[e].getG() << ' '
   6.409 -	    // 	       << _edgeColors[e].getB() << " arr\n";
   6.410 -	  }
   6.411 -	  else {
   6.412 -	    double sw=0;
   6.413 -	    for(typename vector<Edge>::iterator e=i;e!=j;++e)
   6.414 -	      sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
   6.415 -	    sw-=_parEdgeDist;
   6.416 -	    sw/=-2.0;
   6.417 -	    xy<double> d(_coords[g.target(*i)]-_coords[g.source(*i)]);
   6.418 -	    double l=sqrt(d.normSquare());
   6.419 -	    d/=l;
   6.420 -	    for(typename vector<Edge>::iterator e=i;e!=j;++e) {
   6.421 -	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
   6.422 -	      xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]);
   6.423 -	      m=m/2.0+rot(d)*sw/.75;
   6.424 -	      os << _coords[g.source(*e)].x << ' '
   6.425 -		 << _coords[g.source(*e)].y << ' '
   6.426 -		 << m.x << ' ' << m.y << ' '
   6.427 -		 << _coords[g.target(*e)].x << ' '
   6.428 -		 << _coords[g.target(*e)].y << ' '
   6.429 -		 << _edgeColors[*e].getR() << ' '
   6.430 -		 << _edgeColors[*e].getG() << ' '
   6.431 -		 << _edgeColors[*e].getB() << ' '
   6.432 -		 << _edgeWidths[*e]*_edgeWidthScale << " lb\n";
   6.433 -	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
   6.434 -	    }
   6.435 -	  }
   6.436 -	}
   6.437 -      }
   6.438 -      else for(NodeIt n(g);n!=INVALID;++n)
   6.439 -	for(OutEdgeIt e(g,n);e!=INVALID;++e)
   6.440 -	  if(_drawArrows) {
   6.441 -	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   6.442 -	    double l=sqrt(d.normSquare());
   6.443 -	    d/=l;
   6.444 -	    xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
   6.445 -			  _coords[g.source(e)]);
   6.446 -	    os << l-(_nodeSizes[g.source(e)]+
   6.447 -		     _nodeSizes[g.target(e)])*_nodeScale << ' '
   6.448 -	       << _edgeWidths[e]*_edgeWidthScale << ' '
   6.449 -	       << d.x << ' ' << d.y << ' '
   6.450 -	       << x1.x << ' ' << x1.y << ' '
   6.451 -	       << _edgeColors[e].getR() << ' '
   6.452 -	       << _edgeColors[e].getG() << ' '
   6.453 -	       << _edgeColors[e].getB() << " arr\n";
   6.454 -	  }
   6.455 -	  else os << _coords[g.source(e)].x << ' '
   6.456 -		  << _coords[g.source(e)].y << ' '
   6.457 -		  << _coords[g.target(e)].x << ' '
   6.458 -		  << _coords[g.target(e)].y << ' '
   6.459 -		  << _edgeColors[e].getR() << ' '
   6.460 -		  << _edgeColors[e].getG() << ' '
   6.461 -		  << _edgeColors[e].getB() << ' '
   6.462 -		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
   6.463 -    os << "grestore\n%Nodes:\ngsave\n";
   6.464 -    if(_showNodes)
   6.465 -      for(NodeIt n(g);n!=INVALID;++n)
   6.466 -	os << _coords[n].x << ' ' << _coords[n].y << ' '
   6.467 -	   << _nodeSizes[n]*_nodeScale << ' '
   6.468 -	   << _nodeColors[n].getR() << ' '
   6.469 -	   << _nodeColors[n].getG() << ' '
   6.470 -	   << _nodeColors[n].getB() << " n\n"; 
   6.471 -    if(_showNodeText) {
   6.472 -      os << "grestore\n%Node texts:\ngsave\n";
   6.473 -      os << "/fosi " << _nodeTextSize << " def\n";
   6.474 -      os << "(Helvetica) findfont fosi scalefont setfont\n";
   6.475 -      os << "0 0 0 setrgbcolor\n";
   6.476 -      for(NodeIt n(g);n!=INVALID;++n)
   6.477 -	os << _coords[n].x << ' ' << _coords[n].y
   6.478 -	   << " (" << _nodeTexts[n] << ") cshow\n";
   6.479 -    }
   6.480 -    os << "grestore\ngrestore\n";
   6.481 -
   6.482 -    //CleanUp:
   6.483 -    if(_pleaseRemoveOsStream) {delete &os;}
   6.484 -  } 
   6.485 -};
   6.486 -
   6.487 -
   6.488 -///Generates an EPS file from a graph
   6.489 -
   6.490 -///\ingroup misc
   6.491 -///Generates an EPS file from a graph.
   6.492 -///\param g is a reference to the graph to be printed
   6.493 -///\param os is a reference to the output stream.
   6.494 -///By default it is <tt>std::cout</tt>
   6.495 -///
   6.496 -///This function also has a lot of \ref named-templ-param "named parameters",
   6.497 -///they are declared as the members of class \ref GraphToEps. The following
   6.498 -///example shows how to use these parameters.
   6.499 -///\code
   6.500 -/// graphToEps(g).scale(10).coords(coords)
   6.501 -///              .nodeScale(2).nodeSizes(sizes)
   6.502 -///              .edgeWidthScale(.4);
   6.503 -///\endcode
   6.504 -///\sa GraphToEps
   6.505 -///\sa graphToEps(G &g, char *file_name)
   6.506 -template<class G>
   6.507 -GraphToEps<DefaultGraphToEpsTraits<G> > 
   6.508 -graphToEps(G &g, std::ostream& os=std::cout)
   6.509 -{
   6.510 -  return 
   6.511 -    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
   6.512 -}
   6.513 - 
   6.514 -///Generates an EPS file from a graph
   6.515 -
   6.516 -//\ingroup misc
   6.517 -///This function does the same as
   6.518 -///\ref graphToEps(G &g,std::ostream& os)
   6.519 -///but it writes its output into the file \c file_name
   6.520 -///instead of a stream.
   6.521 -///\sa graphToEps(G &g, std::ostream& os)
   6.522 -template<class G>
   6.523 -GraphToEps<DefaultGraphToEpsTraits<G> > 
   6.524 -graphToEps(G &g,char *file_name)
   6.525 -{
   6.526 -  return GraphToEps<DefaultGraphToEpsTraits<G> >
   6.527 -    (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true));
   6.528 -}
   6.529 -
   6.530 -//Generates an EPS file from a graph.
   6.531 -//\param g is a reference to the graph to be printed
   6.532 -//\param file_name is the output file_name.
   6.533 -//
   6.534 -//This function also has a lot of \ref named-templ-param "named parameters",
   6.535 -//they are declared as the members of class \ref GraphToEps. The following
   6.536 -//example shows how to use these parameters.
   6.537 -//\code
   6.538 -// graphToEps(g).scale(10).coords(coords)
   6.539 -//              .nodeScale(2).nodeSizes(sizes)
   6.540 -//              .edgeWidthScale(.4);
   6.541 -//\endcode
   6.542 -//\sa GraphToEps
   6.543 -//\todo Avoid duplicated documentation
   6.544 -//\bug Exception handling is missing? (Or we can just ignore it?)
   6.545 -
   6.546 -}
   6.547 -
   6.548 -using namespace lemon;
   6.549 -
   6.550 -class ColorSet : public MapBase<int,Color>
   6.551 -{
   6.552 -public:
   6.553 -  Color operator[](int i) const
   6.554 -  {
   6.555 -    switch(i%8){
   6.556 -    case 0: return Color(0,0,0);
   6.557 -    case 1: return Color(1,0,0);
   6.558 -    case 2: return Color(0,1,0);
   6.559 -    case 3: return Color(0,0,1);
   6.560 -    case 4: return Color(1,1,0);
   6.561 -    case 5: return Color(1,0,1);
   6.562 -    case 6: return Color(0,1,1);
   6.563 -    case 7: return Color(1,1,1);
   6.564 -    }
   6.565 -    return Color(0,0,0);
   6.566 -  }
   6.567 -} colorSet;
   6.568 -
   6.569 -class IdMap :public MapBase<ListGraph::Node,int>
   6.570 -{
   6.571 -  const ListGraph &g;
   6.572 -public:
   6.573 -  IdMap(const ListGraph &_g) :g(_g) {}
   6.574 -  Value operator[](Key n) const { return g.id(n); }
   6.575 -};
   6.576 -
   6.577 -
   6.578 -
   6.579 -int main()
   6.580 -{
   6.581 -  ListGraph g;
   6.582 -  typedef ListGraph::Node Node;
   6.583 -  typedef ListGraph::NodeIt NodeIt;
   6.584 -  typedef ListGraph::Edge Edge;
   6.585 -  typedef xy<int> Xy;
   6.586 -  
   6.587 -  Node n1=g.addNode();
   6.588 -  Node n2=g.addNode();
   6.589 -  Node n3=g.addNode();
   6.590 -  Node n4=g.addNode();
   6.591 -  Node n5=g.addNode();
   6.592 -
   6.593 -  ListGraph::NodeMap<Xy> coords(g);
   6.594 -  ListGraph::NodeMap<double> sizes(g);
   6.595 -  ListGraph::NodeMap<int> colors(g);
   6.596 -  ListGraph::EdgeMap<int> ecolors(g);
   6.597 -  ListGraph::EdgeMap<int> widths(g);
   6.598 -  
   6.599 -  coords[n1]=Xy(50,50);  sizes[n1]=1; colors[n1]=1;
   6.600 -  coords[n2]=Xy(50,70);  sizes[n2]=2; colors[n2]=2;
   6.601 -  coords[n3]=Xy(70,70);  sizes[n3]=1; colors[n3]=3;
   6.602 -  coords[n4]=Xy(70,50);  sizes[n4]=2; colors[n4]=4;
   6.603 -  coords[n5]=Xy(85,60);  sizes[n5]=3; colors[n5]=5;
   6.604 -  
   6.605 -  Edge e;
   6.606 -
   6.607 -  e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1;
   6.608 -  e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1;
   6.609 -  e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3;
   6.610 -  e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
   6.611 -  e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
   6.612 -  e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
   6.613 -  e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
   6.614 -  
   6.615 -  IdMap id(g);
   6.616 -
   6.617 -  graphToEps(g,"proba.eps").scale(10).coords(coords).
   6.618 -    nodeScale(2).nodeSizes(sizes).
   6.619 -    nodeColors(composeMap(colorSet,colors)).
   6.620 -    edgeColors(composeMap(colorSet,ecolors)).
   6.621 -    edgeWidthScale(.4).edgeWidths(widths).
   6.622 -    nodeTexts(id).nodeTextSize(3);
   6.623 -
   6.624 -  graphToEps(g,"proba_arr.eps").scale(10).coords(coords).
   6.625 -    nodeScale(2).nodeSizes(sizes).
   6.626 -    nodeColors(composeMap(colorSet,colors)).
   6.627 -    edgeColors(composeMap(colorSet,ecolors)).
   6.628 -    edgeWidthScale(.4).edgeWidths(widths).
   6.629 -    nodeTexts(id).nodeTextSize(3).
   6.630 -    drawArrows().arrowWidth(1).arrowLength(1);
   6.631 -
   6.632 -  e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1;
   6.633 -  e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2;
   6.634 -
   6.635 -  e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1;
   6.636 -  e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1;
   6.637 -  e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1;
   6.638 -  e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1;
   6.639 -  e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1;
   6.640 -  e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1;
   6.641 -  e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1;
   6.642 -
   6.643 -  graphToEps(g,"proba_par.eps").scale(10).coords(coords).
   6.644 -    nodeScale(2).nodeSizes(sizes).
   6.645 -    nodeColors(composeMap(colorSet,colors)).
   6.646 -    edgeColors(composeMap(colorSet,ecolors)).
   6.647 -    edgeWidthScale(.4).edgeWidths(widths).
   6.648 -    nodeTexts(id).nodeTextSize(3).
   6.649 -    enableParallel().parEdgeDist(1.5);
   6.650 -}