src/work/alpar/graph_to_eps.cc
author alpar
Sat, 08 Jan 2005 20:16:56 +0000
changeset 1062 8226427845bc
parent 1055 f901ff02b2d7
permissions -rw-r--r--
- Parallel edge support (without arrowheads)
- Texts on the nodes
alpar@1062
     1
/* -*- C++ -*-
alpar@1062
     2
 * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library
alpar@1062
     3
 *
alpar@1062
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1062
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
alpar@1062
     6
 *
alpar@1062
     7
 * Permission to use, modify and distribute this software is granted
alpar@1062
     8
 * provided that this copyright notice appears in all copies. For
alpar@1062
     9
 * precise terms see the accompanying LICENSE file.
alpar@1062
    10
 *
alpar@1062
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@1062
    12
 * express or implied, and with no claim as to its suitability for any
alpar@1062
    13
 * purpose.
alpar@1062
    14
 *
alpar@1062
    15
 */
alpar@1062
    16
alpar@1051
    17
#include <iostream>
alpar@1055
    18
#include <fstream>
alpar@1055
    19
#include <algorithm>
alpar@1050
    20
#include<math.h>
alpar@1051
    21
alpar@1046
    22
#include<lemon/xy.h>
alpar@1046
    23
#include<lemon/maps.h>
alpar@1046
    24
#include<lemon/list_graph.h>
alpar@1046
    25
alpar@1050
    26
alpar@1062
    27
///\ingroup misc
alpar@1062
    28
///\file
alpar@1062
    29
///\brief Simple graph drawer
alpar@1046
    30
alpar@1046
    31
namespace lemon {
alpar@1046
    32
alpar@1050
    33
///Data structure representing RGB colors.
alpar@1050
    34
alpar@1050
    35
///Data structure representing RGB colors.
alpar@1050
    36
///\ingroup misc
alpar@1046
    37
class Color
alpar@1046
    38
{
alpar@1046
    39
  double _r,_g,_b;
alpar@1046
    40
public:
alpar@1050
    41
  ///Default constructor
alpar@1046
    42
  Color() {}
alpar@1050
    43
  ///Constructor
alpar@1046
    44
  Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
alpar@1050
    45
  ///Returns the red component
alpar@1046
    46
  double getR() {return _r;}
alpar@1050
    47
  ///Returns the green component
alpar@1046
    48
  double getG() {return _g;}
alpar@1050
    49
  ///Returns the blue component
alpar@1046
    50
  double getB() {return _b;}
alpar@1050
    51
  ///Set the color components
alpar@1046
    52
  void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
alpar@1046
    53
};
alpar@1046
    54
  
alpar@1050
    55
///Default traits class of \ref GraphToEps
alpar@1050
    56
alpar@1050
    57
///Default traits class of \ref GraphToEps
alpar@1050
    58
///
alpar@1050
    59
///\c G is the type of the underlying graph.
alpar@1046
    60
template<class G>
alpar@1046
    61
struct DefaultGraphToEpsTraits
alpar@1046
    62
{
alpar@1046
    63
  typedef G Graph;
alpar@1046
    64
  typedef typename Graph::Node Node;
alpar@1046
    65
  typedef typename Graph::NodeIt NodeIt;
alpar@1046
    66
  typedef typename Graph::Edge Edge;
alpar@1046
    67
  typedef typename Graph::EdgeIt EdgeIt;
alpar@1046
    68
  typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1046
    69
  typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1046
    70
  
alpar@1046
    71
alpar@1046
    72
  const Graph &g;
alpar@1051
    73
alpar@1051
    74
  std::ostream& os;
alpar@1051
    75
  
alpar@1050
    76
  ConstMap<typename Graph::Node,xy<double> > _coords;
alpar@1050
    77
  ConstMap<typename Graph::Node,double > _nodeSizes;
alpar@1046
    78
alpar@1050
    79
  ConstMap<typename Graph::Node,Color > _nodeColors;
alpar@1050
    80
  ConstMap<typename Graph::Edge,Color > _edgeColors;
alpar@1050
    81
alpar@1050
    82
  ConstMap<typename Graph::Edge,double > _edgeWidths;
alpar@1050
    83
  
alpar@1050
    84
  double _edgeWidthScale;
alpar@1050
    85
  
alpar@1050
    86
  double _nodeScale;
alpar@1050
    87
  double _xBorder, _yBorder;
alpar@1050
    88
  double _scale;
alpar@1050
    89
  double _nodeBorderQuotient;
alpar@1050
    90
  
alpar@1050
    91
  bool _drawArrows;
alpar@1050
    92
  double _arrowLength, _arrowWidth;
alpar@1050
    93
  
alpar@1062
    94
  bool _showNodes, _showEdges;
alpar@1062
    95
alpar@1055
    96
  bool _enableParallel;
alpar@1062
    97
  double _parEdgeDist;
alpar@1062
    98
alpar@1062
    99
  bool _showNodeText;
alpar@1062
   100
  ConstMap<typename Graph::Node,bool > _nodeTexts;  
alpar@1062
   101
  double _nodeTextSize;
alpar@1055
   102
alpar@1055
   103
  bool _pleaseRemoveOsStream;
alpar@1050
   104
  ///Constructor
alpar@1050
   105
alpar@1050
   106
  ///Constructor
alpar@1051
   107
  ///\param _g is a reference to the graph to be printed
alpar@1051
   108
  ///\param _os is a reference to the output stream.
alpar@1055
   109
  ///\param _os is a reference to the output stream.
alpar@1055
   110
  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
alpar@1055
   111
  ///will be explicitly deallocated by the destructor.
alpar@1051
   112
  ///By default it is <tt>std::cout</tt>
alpar@1055
   113
  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
alpar@1055
   114
			  bool _pros=false) :
alpar@1051
   115
    g(_g), os(_os),
alpar@1051
   116
    _coords(xy<double>(1,1)), _nodeSizes(1.0),
alpar@1050
   117
    _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
alpar@1050
   118
    _edgeWidths(1), _edgeWidthScale(0.3),
alpar@1050
   119
    _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
alpar@1050
   120
    _nodeBorderQuotient(.1),
alpar@1055
   121
    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
alpar@1062
   122
    _showNodes(true), _showEdges(true),
alpar@1062
   123
    _enableParallel(false), _parEdgeDist(1),
alpar@1062
   124
    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
alpar@1062
   125
    _pleaseRemoveOsStream(_pros) {}
alpar@1046
   126
};
alpar@1046
   127
alpar@1050
   128
///Helper class to implement the named parameters of \ref graphToEps()
alpar@1050
   129
alpar@1050
   130
///Helper class to implement the named parameters of \ref graphToEps()
alpar@1050
   131
///\todo Is 'helper class' a good name for this?
alpar@1050
   132
///
alpar@1046
   133
template<class T> class GraphToEps : public T 
alpar@1046
   134
{
alpar@1046
   135
  typedef typename T::Graph Graph;
alpar@1046
   136
  typedef typename Graph::Node Node;
alpar@1046
   137
  typedef typename Graph::NodeIt NodeIt;
alpar@1046
   138
  typedef typename Graph::Edge Edge;
alpar@1046
   139
  typedef typename Graph::EdgeIt EdgeIt;
alpar@1046
   140
  typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1046
   141
  typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1046
   142
alpar@1046
   143
  bool dontPrint;
alpar@1046
   144
alpar@1055
   145
  class edgeLess {
alpar@1055
   146
    const Graph &g;
alpar@1055
   147
  public:
alpar@1055
   148
    edgeLess(const Graph &_g) : g(_g) {}
alpar@1055
   149
    bool operator()(Edge a,Edge b) const 
alpar@1055
   150
    {
alpar@1055
   151
      Node ai=min(g.source(a),g.target(a));
alpar@1055
   152
      Node aa=max(g.source(a),g.target(a));
alpar@1055
   153
      Node bi=min(g.source(b),g.target(b));
alpar@1055
   154
      Node ba=max(g.source(b),g.target(b));
alpar@1055
   155
      return ai<bi ||
alpar@1055
   156
	(ai==bi && (aa < ba || 
alpar@1055
   157
		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
alpar@1055
   158
    }
alpar@1055
   159
  };
alpar@1062
   160
  bool isParallel(Edge e,Edge f) const
alpar@1062
   161
  {
alpar@1062
   162
    return (g.source(e)==g.source(f)&&g.target(e)==g.target(f))||
alpar@1062
   163
      (g.source(e)==g.target(f)&&g.target(e)==g.source(f));
alpar@1062
   164
  }
alpar@1062
   165
  static xy<double> rot(xy<double> v) 
alpar@1062
   166
  {
alpar@1062
   167
    return xy<double>(v.y,-v.x);
alpar@1062
   168
  }
alpar@1062
   169
  
alpar@1046
   170
public:
alpar@1046
   171
  GraphToEps(const T &t) : T(t), dontPrint(false) {};
alpar@1046
   172
  
alpar@1050
   173
  template<class X> struct CoordsTraits : public T {
alpar@1050
   174
    const X &_coords;
alpar@1050
   175
    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
alpar@1046
   176
  };
alpar@1050
   177
  ///Sets the map of the node coordinates
alpar@1050
   178
alpar@1050
   179
  ///Sets the map of the node coordinates.
alpar@1050
   180
  ///\param x must be a node map with xy<double> or xy<int> values. 
alpar@1050
   181
  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
alpar@1046
   182
    dontPrint=true;
alpar@1050
   183
    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
alpar@1046
   184
  }
alpar@1050
   185
  template<class X> struct NodeSizesTraits : public T {
alpar@1050
   186
    const X &_nodeSizes;
alpar@1050
   187
    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
alpar@1046
   188
  };
alpar@1050
   189
  ///Sets the map of the node sizes
alpar@1050
   190
alpar@1050
   191
  ///Sets the map of the node sizes
alpar@1050
   192
  ///\param x must be a node map with \c double (or convertible) values. 
alpar@1050
   193
  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
alpar@1046
   194
  {
alpar@1046
   195
    dontPrint=true;
alpar@1050
   196
    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
alpar@1046
   197
  }
alpar@1062
   198
  template<class X> struct NodeTextsTraits : public T {
alpar@1062
   199
    const X &_nodeTexts;
alpar@1062
   200
    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
alpar@1062
   201
  };
alpar@1062
   202
  ///Sets the text printed on the nodes
alpar@1062
   203
alpar@1062
   204
  ///Sets the text printed on the nodes
alpar@1062
   205
  ///\param x must be a node map with type that can be pushed to a standard
alpar@1062
   206
  ///ostream. 
alpar@1062
   207
  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
alpar@1062
   208
  {
alpar@1062
   209
    dontPrint=true;
alpar@1062
   210
    _showNodeText=true;
alpar@1062
   211
    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
alpar@1062
   212
  }
alpar@1050
   213
   template<class X> struct EdgeWidthsTraits : public T {
alpar@1050
   214
    const X &_edgeWidths;
alpar@1050
   215
    EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
alpar@1046
   216
  };
alpar@1050
   217
  ///Sets the map of the edge widths
alpar@1050
   218
alpar@1050
   219
  ///Sets the map of the edge widths
alpar@1050
   220
  ///\param x must be a edge map with \c double (or convertible) values. 
alpar@1050
   221
  template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x)
alpar@1046
   222
  {
alpar@1046
   223
    dontPrint=true;
alpar@1050
   224
    return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x));
alpar@1046
   225
  }
alpar@1050
   226
alpar@1050
   227
  template<class X> struct NodeColorsTraits : public T {
alpar@1050
   228
    const X &_nodeColors;
alpar@1050
   229
    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
alpar@1046
   230
  };
alpar@1050
   231
  ///Sets the map of the node colors
alpar@1050
   232
alpar@1050
   233
  ///Sets the map of the node colors
alpar@1050
   234
  ///\param x must be a node map with \ref Color values. 
alpar@1050
   235
  template<class X> GraphToEps<NodeColorsTraits<X> >
alpar@1050
   236
  nodeColors(const X &x)
alpar@1046
   237
  {
alpar@1046
   238
    dontPrint=true;
alpar@1050
   239
    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
alpar@1046
   240
  }
alpar@1050
   241
  template<class X> struct EdgeColorsTraits : public T {
alpar@1050
   242
    const X &_edgeColors;
alpar@1050
   243
    EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
alpar@1050
   244
  };
alpar@1050
   245
  ///Sets the map of the edge colors
alpar@1050
   246
alpar@1050
   247
  ///Sets the map of the edge colors
alpar@1050
   248
  ///\param x must be a edge map with \ref Color values. 
alpar@1050
   249
  template<class X> GraphToEps<EdgeColorsTraits<X> >
alpar@1050
   250
  edgeColors(const X &x)
alpar@1050
   251
  {
alpar@1050
   252
    dontPrint=true;
alpar@1050
   253
    return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x));
alpar@1050
   254
  }
alpar@1050
   255
  ///Sets a global scale factor for node sizes
alpar@1050
   256
alpar@1050
   257
  ///Sets a global scale factor for node sizes
alpar@1050
   258
  ///
alpar@1050
   259
  GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
alpar@1050
   260
  ///Sets a global scale factor for edge widths
alpar@1050
   261
alpar@1050
   262
  ///Sets a global scale factor for edge widths
alpar@1050
   263
  ///
alpar@1050
   264
  GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;}
alpar@1050
   265
  ///Sets a global scale factor for the whole picture
alpar@1050
   266
alpar@1050
   267
  ///Sets a global scale factor for the whole picture
alpar@1050
   268
  ///
alpar@1050
   269
  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
alpar@1050
   270
  ///Sets the width of the border around the picture
alpar@1050
   271
alpar@1050
   272
  ///Sets the width of the border around the picture
alpar@1050
   273
  ///
alpar@1050
   274
  GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
alpar@1050
   275
  ///Sets the width of the border around the picture
alpar@1050
   276
alpar@1050
   277
  ///Sets the width of the border around the picture
alpar@1050
   278
  ///
alpar@1050
   279
  GraphToEps<T> &border(double x, double y) {
alpar@1050
   280
    _xBorder=x;_yBorder=y;return *this;
alpar@1050
   281
  }
alpar@1050
   282
  ///Sets whether to draw arrows
alpar@1050
   283
alpar@1050
   284
  ///Sets whether to draw arrows
alpar@1050
   285
  ///
alpar@1050
   286
  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
alpar@1050
   287
  ///Sets the length of the arrowheads
alpar@1050
   288
alpar@1050
   289
  ///Sets the length of the arrowheads
alpar@1050
   290
  ///
alpar@1050
   291
  GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
alpar@1050
   292
  ///Sets the width of the arrowheads
alpar@1050
   293
alpar@1050
   294
  ///Sets the width of the arrowheads
alpar@1050
   295
  ///
alpar@1050
   296
  GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
alpar@1046
   297
  
alpar@1055
   298
  ///Enables parallel edges
alpar@1055
   299
alpar@1055
   300
  ///Enables parallel edges
alpar@1062
   301
  ///\todo Partially implemented
alpar@1055
   302
  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
alpar@1055
   303
  
alpar@1062
   304
  ///Sets the distance 
alpar@1062
   305
  
alpar@1062
   306
  ///Sets the distance 
alpar@1062
   307
  ///
alpar@1062
   308
  GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;}
alpar@1062
   309
  
alpar@1062
   310
  ///Hides the edges
alpar@1062
   311
  
alpar@1062
   312
  ///Hides the edges
alpar@1062
   313
  ///
alpar@1062
   314
  GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;}
alpar@1062
   315
  ///Hides the nodes
alpar@1062
   316
  
alpar@1062
   317
  ///Hides the nodes
alpar@1062
   318
  ///
alpar@1062
   319
  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
alpar@1062
   320
  
alpar@1062
   321
  ///Sets the size of the node texts
alpar@1062
   322
  
alpar@1062
   323
  ///Sets the size of the node texts
alpar@1062
   324
  ///
alpar@1062
   325
  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
alpar@1062
   326
alpar@1062
   327
  
alpar@1046
   328
  ~GraphToEps() 
alpar@1046
   329
  {
alpar@1046
   330
    if(dontPrint) return;
alpar@1046
   331
    
alpar@1051
   332
    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
alpar@1046
   333
    //\todo: Chech whether the graph is empty.
alpar@1046
   334
    BoundingBox<double> bb;
alpar@1050
   335
    for(NodeIt n(g);n!=INVALID;++n) {
alpar@1050
   336
      double ns=_nodeSizes[n]*_nodeScale;
alpar@1050
   337
      xy<double> p(ns,ns);
alpar@1050
   338
      bb+=p+_coords[n];
alpar@1050
   339
      bb+=-p+_coords[n];
alpar@1046
   340
      }
alpar@1051
   341
    os << "%%BoundingBox: "
alpar@1050
   342
	 << bb.left()*  _scale-_xBorder << ' '
alpar@1050
   343
	 << bb.bottom()*_scale-_yBorder << ' '
alpar@1050
   344
	 << bb.right()* _scale+_xBorder << ' '
alpar@1050
   345
	 << bb.top()*   _scale+_yBorder << '\n';
alpar@1062
   346
    //x1 y1 x2 y2 x3 y3 cr cg cb w
alpar@1062
   347
    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
alpar@1062
   348
       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
alpar@1051
   349
    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
alpar@1062
   350
    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
alpar@1046
   351
    // x y r cr cg cb
alpar@1051
   352
    os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
alpar@1062
   353
       << "     0 0 0 setrgbcolor dup "
alpar@1062
   354
       << _nodeBorderQuotient << " mul setlinewidth "
alpar@1062
   355
       << 1+_nodeBorderQuotient/2 << " div c stroke\n"
alpar@1062
   356
       << "   } bind def\n";
alpar@1051
   357
    os << "/arrl " << _arrowLength << " def\n";
alpar@1051
   358
    os << "/arrw " << _arrowWidth << " def\n";
alpar@1050
   359
    // l dx_norm dy_norm
alpar@1051
   360
    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
alpar@1050
   361
    //len w dx_norm dy_norm x1 y1 cr cg cb
alpar@1051
   362
    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
alpar@1062
   363
       << "       /w exch def /len exch def\n"
alpar@1050
   364
      //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
alpar@1062
   365
       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
alpar@1062
   366
       << "       len w sub arrl sub dx dy lrl\n"
alpar@1062
   367
       << "       arrw dy dx neg lrl\n"
alpar@1062
   368
       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
alpar@1062
   369
       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
alpar@1062
   370
       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
alpar@1062
   371
       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
alpar@1062
   372
       << "       arrw dy dx neg lrl\n"
alpar@1062
   373
       << "       len w sub arrl sub neg dx dy lrl\n"
alpar@1062
   374
       << "       closepath fill } bind def\n";
alpar@1062
   375
    os << "/cshow { 2 index 2 index moveto\n"
alpar@1062
   376
       << "         dup stringwidth pop neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
alpar@1062
   377
alpar@1051
   378
    os << "\ngsave\n";
alpar@1051
   379
    if(_scale!=1.0) os << _scale << " dup scale\n";
alpar@1055
   380
    
alpar@1051
   381
    os << "%Edges:\ngsave\n";
alpar@1055
   382
    
alpar@1062
   383
    if(_showEdges)
alpar@1062
   384
      if(_enableParallel) {
alpar@1062
   385
	vector<Edge> el;
alpar@1062
   386
	for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e);
alpar@1062
   387
	sort(el.begin(),el.end(),edgeLess(g));
alpar@1062
   388
	
alpar@1062
   389
	typename vector<Edge>::iterator j;
alpar@1062
   390
	for(typename vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
alpar@1062
   391
	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
alpar@1062
   392
	  
alpar@1062
   393
	  if(_drawArrows) {
alpar@1062
   394
	    // 	  xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
alpar@1062
   395
	    // 	  double l=sqrt(d.normSquare());
alpar@1062
   396
	    // 	  d/=l;
alpar@1062
   397
	    // 	  xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
alpar@1062
   398
	    // 			_coords[g.source(e)]);
alpar@1062
   399
	    // 	  os << l-(_nodeSizes[g.source(e)]+
alpar@1062
   400
	    // 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
alpar@1062
   401
	    // 	       << _edgeWidths[e]*_edgeWidthScale << ' '
alpar@1062
   402
	    // 	       << d.x << ' ' << d.y << ' '
alpar@1062
   403
	    // 	       << x1.x << ' ' << x1.y << ' '
alpar@1062
   404
	    // 	       << _edgeColors[e].getR() << ' '
alpar@1062
   405
	    // 	       << _edgeColors[e].getG() << ' '
alpar@1062
   406
	    // 	       << _edgeColors[e].getB() << " arr\n";
alpar@1062
   407
	  }
alpar@1062
   408
	  else {
alpar@1062
   409
	    double sw=0;
alpar@1062
   410
	    for(typename vector<Edge>::iterator e=i;e!=j;++e)
alpar@1062
   411
	      sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
alpar@1062
   412
	    sw-=_parEdgeDist;
alpar@1062
   413
	    sw/=-2.0;
alpar@1062
   414
	    xy<double> d(_coords[g.target(*i)]-_coords[g.source(*i)]);
alpar@1062
   415
	    double l=sqrt(d.normSquare());
alpar@1062
   416
	    d/=l;
alpar@1062
   417
	    for(typename vector<Edge>::iterator e=i;e!=j;++e) {
alpar@1062
   418
	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
alpar@1062
   419
	      xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]);
alpar@1062
   420
	      m=m/2.0+rot(d)*sw/.75;
alpar@1062
   421
	      os << _coords[g.source(*e)].x << ' '
alpar@1062
   422
		 << _coords[g.source(*e)].y << ' '
alpar@1062
   423
		 << m.x << ' ' << m.y << ' '
alpar@1062
   424
		 << _coords[g.target(*e)].x << ' '
alpar@1062
   425
		 << _coords[g.target(*e)].y << ' '
alpar@1062
   426
		 << _edgeColors[*e].getR() << ' '
alpar@1062
   427
		 << _edgeColors[*e].getG() << ' '
alpar@1062
   428
		 << _edgeColors[*e].getB() << ' '
alpar@1062
   429
		 << _edgeWidths[*e]*_edgeWidthScale << " lb\n";
alpar@1062
   430
	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
alpar@1062
   431
	    }
alpar@1062
   432
	  }
alpar@1062
   433
	}
alpar@1062
   434
      }
alpar@1062
   435
      else for(NodeIt n(g);n!=INVALID;++n)
alpar@1062
   436
	for(OutEdgeIt e(g,n);e!=INVALID;++e)
alpar@1062
   437
	  if(_drawArrows) {
alpar@1062
   438
	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
alpar@1062
   439
	    double l=sqrt(d.normSquare());
alpar@1062
   440
	    d/=l;
alpar@1062
   441
	    xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
alpar@1062
   442
			  _coords[g.source(e)]);
alpar@1062
   443
	    os << l-(_nodeSizes[g.source(e)]+
alpar@1050
   444
		     _nodeSizes[g.target(e)])*_nodeScale << ' '
alpar@1050
   445
	       << _edgeWidths[e]*_edgeWidthScale << ' '
alpar@1050
   446
	       << d.x << ' ' << d.y << ' '
alpar@1050
   447
	       << x1.x << ' ' << x1.y << ' '
alpar@1050
   448
	       << _edgeColors[e].getR() << ' '
alpar@1050
   449
	       << _edgeColors[e].getG() << ' '
alpar@1050
   450
	       << _edgeColors[e].getB() << " arr\n";
alpar@1062
   451
	  }
alpar@1062
   452
	  else os << _coords[g.source(e)].x << ' '
alpar@1050
   453
		  << _coords[g.source(e)].y << ' '
alpar@1050
   454
		  << _coords[g.target(e)].x << ' '
alpar@1050
   455
		  << _coords[g.target(e)].y << ' '
alpar@1050
   456
		  << _edgeColors[e].getR() << ' '
alpar@1050
   457
		  << _edgeColors[e].getG() << ' '
alpar@1050
   458
		  << _edgeColors[e].getB() << ' '
alpar@1050
   459
		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
alpar@1051
   460
    os << "grestore\n%Nodes:\ngsave\n";
alpar@1062
   461
    if(_showNodes)
alpar@1062
   462
      for(NodeIt n(g);n!=INVALID;++n)
alpar@1062
   463
	os << _coords[n].x << ' ' << _coords[n].y << ' '
alpar@1050
   464
	   << _nodeSizes[n]*_nodeScale << ' '
alpar@1050
   465
	   << _nodeColors[n].getR() << ' '
alpar@1050
   466
	   << _nodeColors[n].getG() << ' '
alpar@1050
   467
	   << _nodeColors[n].getB() << " n\n"; 
alpar@1062
   468
    if(_showNodeText) {
alpar@1062
   469
      os << "grestore\n%Node texts:\ngsave\n";
alpar@1062
   470
      os << "/fosi " << _nodeTextSize << " def\n";
alpar@1062
   471
      os << "(Helvetica) findfont fosi scalefont setfont\n";
alpar@1062
   472
      os << "0 0 0 setrgbcolor\n";
alpar@1062
   473
      for(NodeIt n(g);n!=INVALID;++n)
alpar@1062
   474
	os << _coords[n].x << ' ' << _coords[n].y
alpar@1062
   475
	   << " (" << _nodeTexts[n] << ") cshow\n";
alpar@1062
   476
    }
alpar@1051
   477
    os << "grestore\ngrestore\n";
alpar@1055
   478
alpar@1055
   479
    //CleanUp:
alpar@1055
   480
    if(_pleaseRemoveOsStream) {delete &os;}
alpar@1046
   481
  } 
alpar@1046
   482
};
alpar@1046
   483
alpar@1046
   484
alpar@1050
   485
///Generates an EPS file from a graph
alpar@1050
   486
alpar@1050
   487
///\ingroup misc
alpar@1050
   488
///Generates an EPS file from a graph.
alpar@1051
   489
///\param g is a reference to the graph to be printed
alpar@1051
   490
///\param os is a reference to the output stream.
alpar@1051
   491
///By default it is <tt>std::cout</tt>
alpar@1050
   492
///
alpar@1051
   493
///This function also has a lot of \ref named-templ-param "named parameters",
alpar@1050
   494
///they are declared as the members of class \ref GraphToEps. The following
alpar@1050
   495
///example shows how to use these parameters.
alpar@1050
   496
///\code
alpar@1050
   497
/// graphToEps(g).scale(10).coords(coords)
alpar@1050
   498
///              .nodeScale(2).nodeSizes(sizes)
alpar@1050
   499
///              .edgeWidthScale(.4);
alpar@1050
   500
///\endcode
alpar@1050
   501
///\sa GraphToEps
alpar@1062
   502
///\sa graphToEps(G &g, char *file_name)
alpar@1046
   503
template<class G>
alpar@1055
   504
GraphToEps<DefaultGraphToEpsTraits<G> > 
alpar@1062
   505
graphToEps(G &g, std::ostream& os=std::cout)
alpar@1046
   506
{
alpar@1055
   507
  return 
alpar@1055
   508
    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
alpar@1046
   509
}
alpar@1046
   510
 
alpar@1055
   511
///Generates an EPS file from a graph
alpar@1055
   512
alpar@1062
   513
//\ingroup misc
alpar@1062
   514
///This function does the same as
alpar@1062
   515
///\ref graphToEps(G &g,std::ostream& os)
alpar@1062
   516
///but it writes its output into the file \c file_name
alpar@1062
   517
///instead of a stream.
alpar@1062
   518
///\sa graphToEps(G &g, std::ostream& os)
alpar@1055
   519
template<class G>
alpar@1055
   520
GraphToEps<DefaultGraphToEpsTraits<G> > 
alpar@1055
   521
graphToEps(G &g,char *file_name)
alpar@1055
   522
{
alpar@1055
   523
  return GraphToEps<DefaultGraphToEpsTraits<G> >
alpar@1055
   524
    (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true));
alpar@1055
   525
}
alpar@1055
   526
alpar@1062
   527
//Generates an EPS file from a graph.
alpar@1062
   528
//\param g is a reference to the graph to be printed
alpar@1062
   529
//\param file_name is the output file_name.
alpar@1062
   530
//
alpar@1062
   531
//This function also has a lot of \ref named-templ-param "named parameters",
alpar@1062
   532
//they are declared as the members of class \ref GraphToEps. The following
alpar@1062
   533
//example shows how to use these parameters.
alpar@1062
   534
//\code
alpar@1062
   535
// graphToEps(g).scale(10).coords(coords)
alpar@1062
   536
//              .nodeScale(2).nodeSizes(sizes)
alpar@1062
   537
//              .edgeWidthScale(.4);
alpar@1062
   538
//\endcode
alpar@1062
   539
//\sa GraphToEps
alpar@1062
   540
//\todo Avoid duplicated documentation
alpar@1062
   541
//\bug Exception handling is missing? (Or we can just ignore it?)
alpar@1055
   542
alpar@1046
   543
}
alpar@1046
   544
alpar@1046
   545
using namespace lemon;
alpar@1046
   546
alpar@1046
   547
class ColorSet : public MapBase<int,Color>
alpar@1046
   548
{
alpar@1046
   549
public:
alpar@1046
   550
  Color operator[](int i) const
alpar@1046
   551
  {
alpar@1046
   552
    switch(i%8){
alpar@1046
   553
    case 0: return Color(0,0,0);
alpar@1046
   554
    case 1: return Color(1,0,0);
alpar@1046
   555
    case 2: return Color(0,1,0);
alpar@1046
   556
    case 3: return Color(0,0,1);
alpar@1046
   557
    case 4: return Color(1,1,0);
alpar@1046
   558
    case 5: return Color(1,0,1);
alpar@1046
   559
    case 6: return Color(0,1,1);
alpar@1046
   560
    case 7: return Color(1,1,1);
alpar@1046
   561
    }
alpar@1046
   562
    return Color(0,0,0);
alpar@1046
   563
  }
alpar@1046
   564
} colorSet;
alpar@1046
   565
alpar@1062
   566
class IdMap :public MapBase<ListGraph::Node,int>
alpar@1062
   567
{
alpar@1062
   568
  const ListGraph &g;
alpar@1062
   569
public:
alpar@1062
   570
  IdMap(const ListGraph &_g) :g(_g) {}
alpar@1062
   571
  Value operator[](Key n) const { return g.id(n); }
alpar@1062
   572
};
alpar@1062
   573
alpar@1062
   574
alpar@1062
   575
alpar@1046
   576
int main()
alpar@1046
   577
{
alpar@1046
   578
  ListGraph g;
alpar@1046
   579
  typedef ListGraph::Node Node;
alpar@1046
   580
  typedef ListGraph::NodeIt NodeIt;
alpar@1046
   581
  typedef ListGraph::Edge Edge;
alpar@1050
   582
  typedef xy<int> Xy;
alpar@1046
   583
  
alpar@1046
   584
  Node n1=g.addNode();
alpar@1046
   585
  Node n2=g.addNode();
alpar@1046
   586
  Node n3=g.addNode();
alpar@1046
   587
  Node n4=g.addNode();
alpar@1046
   588
  Node n5=g.addNode();
alpar@1046
   589
alpar@1046
   590
  ListGraph::NodeMap<Xy> coords(g);
alpar@1046
   591
  ListGraph::NodeMap<double> sizes(g);
alpar@1046
   592
  ListGraph::NodeMap<int> colors(g);
alpar@1047
   593
  ListGraph::EdgeMap<int> ecolors(g);
alpar@1050
   594
  ListGraph::EdgeMap<int> widths(g);
alpar@1046
   595
  
alpar@1046
   596
  coords[n1]=Xy(50,50);  sizes[n1]=1; colors[n1]=1;
alpar@1046
   597
  coords[n2]=Xy(50,70);  sizes[n2]=2; colors[n2]=2;
alpar@1046
   598
  coords[n3]=Xy(70,70);  sizes[n3]=1; colors[n3]=3;
alpar@1046
   599
  coords[n4]=Xy(70,50);  sizes[n4]=2; colors[n4]=4;
alpar@1046
   600
  coords[n5]=Xy(85,60);  sizes[n5]=3; colors[n5]=5;
alpar@1046
   601
  
alpar@1046
   602
  Edge e;
alpar@1046
   603
alpar@1050
   604
  e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1;
alpar@1050
   605
  e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1;
alpar@1050
   606
  e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3;
alpar@1050
   607
  e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
alpar@1050
   608
  e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
alpar@1050
   609
  e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
alpar@1050
   610
  e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
alpar@1046
   611
  
alpar@1062
   612
  IdMap id(g);
alpar@1062
   613
alpar@1055
   614
  graphToEps(g,"proba.eps").scale(10).coords(coords).
alpar@1055
   615
    nodeScale(2).nodeSizes(sizes).
alpar@1055
   616
    nodeColors(composeMap(colorSet,colors)).
alpar@1055
   617
    edgeColors(composeMap(colorSet,ecolors)).
alpar@1062
   618
    edgeWidthScale(.4).edgeWidths(widths).
alpar@1062
   619
    nodeTexts(id).nodeTextSize(3);
alpar@1062
   620
alpar@1055
   621
  graphToEps(g,"proba_arr.eps").scale(10).coords(coords).
alpar@1050
   622
    nodeScale(2).nodeSizes(sizes).
alpar@1050
   623
    nodeColors(composeMap(colorSet,colors)).
alpar@1050
   624
    edgeColors(composeMap(colorSet,ecolors)).
alpar@1050
   625
    edgeWidthScale(.4).edgeWidths(widths).
alpar@1062
   626
    nodeTexts(id).nodeTextSize(3).
alpar@1062
   627
    drawArrows().arrowWidth(1).arrowLength(1);
alpar@1062
   628
alpar@1062
   629
  e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1;
alpar@1062
   630
  e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2;
alpar@1062
   631
alpar@1062
   632
  e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1;
alpar@1062
   633
  e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1;
alpar@1062
   634
  e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1;
alpar@1062
   635
  e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1;
alpar@1062
   636
  e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1;
alpar@1062
   637
  e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1;
alpar@1062
   638
  e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1;
alpar@1062
   639
alpar@1062
   640
  graphToEps(g,"proba_par.eps").scale(10).coords(coords).
alpar@1062
   641
    nodeScale(2).nodeSizes(sizes).
alpar@1062
   642
    nodeColors(composeMap(colorSet,colors)).
alpar@1062
   643
    edgeColors(composeMap(colorSet,ecolors)).
alpar@1062
   644
    edgeWidthScale(.4).edgeWidths(widths).
alpar@1062
   645
    nodeTexts(id).nodeTextSize(3).
alpar@1062
   646
    enableParallel().parEdgeDist(1.5);
alpar@1046
   647
}