src/work/alpar/graph_to_eps.cc
changeset 1062 8226427845bc
parent 1055 f901ff02b2d7
equal deleted inserted replaced
4:d12575401621 5:e634a401dbde
       
     1 /* -*- C++ -*-
       
     2  * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library
       
     3  *
       
     4  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
       
     5  * (Egervary Combinatorial Optimization Research Group, EGRES).
       
     6  *
       
     7  * Permission to use, modify and distribute this software is granted
       
     8  * provided that this copyright notice appears in all copies. For
       
     9  * precise terms see the accompanying LICENSE file.
       
    10  *
       
    11  * This software is provided "AS IS" with no warranty of any kind,
       
    12  * express or implied, and with no claim as to its suitability for any
       
    13  * purpose.
       
    14  *
       
    15  */
       
    16 
     1 #include <iostream>
    17 #include <iostream>
     2 #include <fstream>
    18 #include <fstream>
     3 #include <algorithm>
    19 #include <algorithm>
     4 #include<math.h>
    20 #include<math.h>
     5 
    21 
     6 #include<lemon/xy.h>
    22 #include<lemon/xy.h>
     7 #include<lemon/maps.h>
    23 #include<lemon/maps.h>
     8 #include<lemon/list_graph.h>
    24 #include<lemon/list_graph.h>
     9 
    25 
    10 
    26 
    11 ///\file \ingroup misc
    27 ///\ingroup misc
    12 ///Simple graph drawer
    28 ///\file
       
    29 ///\brief Simple graph drawer
    13 
    30 
    14 namespace lemon {
    31 namespace lemon {
    15 
    32 
    16 ///Data structure representing RGB colors.
    33 ///Data structure representing RGB colors.
    17 
    34 
    72   double _nodeBorderQuotient;
    89   double _nodeBorderQuotient;
    73   
    90   
    74   bool _drawArrows;
    91   bool _drawArrows;
    75   double _arrowLength, _arrowWidth;
    92   double _arrowLength, _arrowWidth;
    76   
    93   
       
    94   bool _showNodes, _showEdges;
       
    95 
    77   bool _enableParallel;
    96   bool _enableParallel;
       
    97   double _parEdgeDist;
       
    98 
       
    99   bool _showNodeText;
       
   100   ConstMap<typename Graph::Node,bool > _nodeTexts;  
       
   101   double _nodeTextSize;
    78 
   102 
    79   bool _pleaseRemoveOsStream;
   103   bool _pleaseRemoveOsStream;
    80   ///Constructor
   104   ///Constructor
    81 
   105 
    82   ///Constructor
   106   ///Constructor
    93     _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
   117     _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
    94     _edgeWidths(1), _edgeWidthScale(0.3),
   118     _edgeWidths(1), _edgeWidthScale(0.3),
    95     _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
   119     _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
    96     _nodeBorderQuotient(.1),
   120     _nodeBorderQuotient(.1),
    97     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   121     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
    98     _enableParallel(false), _pleaseRemoveOsStream(_pros) {}
   122     _showNodes(true), _showEdges(true),
       
   123     _enableParallel(false), _parEdgeDist(1),
       
   124     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
       
   125     _pleaseRemoveOsStream(_pros) {}
    99 };
   126 };
   100 
   127 
   101 ///Helper class to implement the named parameters of \ref graphToEps()
   128 ///Helper class to implement the named parameters of \ref graphToEps()
   102 
   129 
   103 ///Helper class to implement the named parameters of \ref graphToEps()
   130 ///Helper class to implement the named parameters of \ref graphToEps()
   128       return ai<bi ||
   155       return ai<bi ||
   129 	(ai==bi && (aa < ba || 
   156 	(ai==bi && (aa < ba || 
   130 		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
   157 		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
   131     }
   158     }
   132   };
   159   };
   133     
   160   bool isParallel(Edge e,Edge f) const
       
   161   {
       
   162     return (g.source(e)==g.source(f)&&g.target(e)==g.target(f))||
       
   163       (g.source(e)==g.target(f)&&g.target(e)==g.source(f));
       
   164   }
       
   165   static xy<double> rot(xy<double> v) 
       
   166   {
       
   167     return xy<double>(v.y,-v.x);
       
   168   }
       
   169   
   134 public:
   170 public:
   135   GraphToEps(const T &t) : T(t), dontPrint(false) {};
   171   GraphToEps(const T &t) : T(t), dontPrint(false) {};
   136   
   172   
   137   template<class X> struct CoordsTraits : public T {
   173   template<class X> struct CoordsTraits : public T {
   138     const X &_coords;
   174     const X &_coords;
   157   template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
   193   template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
   158   {
   194   {
   159     dontPrint=true;
   195     dontPrint=true;
   160     return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
   196     return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
   161   }
   197   }
       
   198   template<class X> struct NodeTextsTraits : public T {
       
   199     const X &_nodeTexts;
       
   200     NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
       
   201   };
       
   202   ///Sets the text printed on the nodes
       
   203 
       
   204   ///Sets the text printed on the nodes
       
   205   ///\param x must be a node map with type that can be pushed to a standard
       
   206   ///ostream. 
       
   207   template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
       
   208   {
       
   209     dontPrint=true;
       
   210     _showNodeText=true;
       
   211     return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
       
   212   }
   162    template<class X> struct EdgeWidthsTraits : public T {
   213    template<class X> struct EdgeWidthsTraits : public T {
   163     const X &_edgeWidths;
   214     const X &_edgeWidths;
   164     EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   215     EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   165   };
   216   };
   166   ///Sets the map of the edge widths
   217   ///Sets the map of the edge widths
   245   GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
   296   GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
   246   
   297   
   247   ///Enables parallel edges
   298   ///Enables parallel edges
   248 
   299 
   249   ///Enables parallel edges
   300   ///Enables parallel edges
   250   ///\todo Unimplemented
   301   ///\todo Partially implemented
   251   GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
   302   GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
       
   303   
       
   304   ///Sets the distance 
       
   305   
       
   306   ///Sets the distance 
       
   307   ///
       
   308   GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;}
       
   309   
       
   310   ///Hides the edges
       
   311   
       
   312   ///Hides the edges
       
   313   ///
       
   314   GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;}
       
   315   ///Hides the nodes
       
   316   
       
   317   ///Hides the nodes
       
   318   ///
       
   319   GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
       
   320   
       
   321   ///Sets the size of the node texts
       
   322   
       
   323   ///Sets the size of the node texts
       
   324   ///
       
   325   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
       
   326 
   252   
   327   
   253   ~GraphToEps() 
   328   ~GraphToEps() 
   254   {
   329   {
   255     if(dontPrint) return;
   330     if(dontPrint) return;
   256     
   331     
   266     os << "%%BoundingBox: "
   341     os << "%%BoundingBox: "
   267 	 << bb.left()*  _scale-_xBorder << ' '
   342 	 << bb.left()*  _scale-_xBorder << ' '
   268 	 << bb.bottom()*_scale-_yBorder << ' '
   343 	 << bb.bottom()*_scale-_yBorder << ' '
   269 	 << bb.right()* _scale+_xBorder << ' '
   344 	 << bb.right()* _scale+_xBorder << ' '
   270 	 << bb.top()*   _scale+_yBorder << '\n';
   345 	 << bb.top()*   _scale+_yBorder << '\n';
   271     //x1 y1 x2 y2 cr cg cb w
   346     //x1 y1 x2 y2 x3 y3 cr cg cb w
       
   347     os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
       
   348        << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
   272     os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
   349     os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
   273     os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
   350     os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
   274     // x y r cr cg cb
   351     // x y r cr cg cb
   275     os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
   352     os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
   276 	 << "     0 0 0 setrgbcolor dup "
   353        << "     0 0 0 setrgbcolor dup "
   277 	 << _nodeBorderQuotient << " mul setlinewidth "
   354        << _nodeBorderQuotient << " mul setlinewidth "
   278 	 << 1+_nodeBorderQuotient/2 << " div c stroke\n"
   355        << 1+_nodeBorderQuotient/2 << " div c stroke\n"
   279 	 << "   } bind def\n";
   356        << "   } bind def\n";
   280     os << "/arrl " << _arrowLength << " def\n";
   357     os << "/arrl " << _arrowLength << " def\n";
   281     os << "/arrw " << _arrowWidth << " def\n";
   358     os << "/arrw " << _arrowWidth << " def\n";
   282     // l dx_norm dy_norm
   359     // l dx_norm dy_norm
   283     os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
   360     os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
   284     //len w dx_norm dy_norm x1 y1 cr cg cb
   361     //len w dx_norm dy_norm x1 y1 cr cg cb
   285     os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
   362     os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
   286 	 << "       /w exch def /len exch def\n"
   363        << "       /w exch def /len exch def\n"
   287       //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
   364       //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
   288 	 << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
   365        << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
   289 	 << "       len w sub arrl sub dx dy lrl\n"
   366        << "       len w sub arrl sub dx dy lrl\n"
   290 	 << "       arrw dy dx neg lrl\n"
   367        << "       arrw dy dx neg lrl\n"
   291 	 << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
   368        << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
   292 	 << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
   369        << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
   293 	 << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
   370        << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
   294 	 << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
   371        << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
   295 	 << "       arrw dy dx neg lrl\n"
   372        << "       arrw dy dx neg lrl\n"
   296 	 << "       len w sub arrl sub neg dx dy lrl\n"
   373        << "       len w sub arrl sub neg dx dy lrl\n"
   297 	 << "       closepath fill } bind def\n";
   374        << "       closepath fill } bind def\n";
       
   375     os << "/cshow { 2 index 2 index moveto\n"
       
   376        << "         dup stringwidth pop neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
       
   377 
   298     os << "\ngsave\n";
   378     os << "\ngsave\n";
   299     if(_scale!=1.0) os << _scale << " dup scale\n";
   379     if(_scale!=1.0) os << _scale << " dup scale\n";
   300     
   380     
   301     os << "%Edges:\ngsave\n";
   381     os << "%Edges:\ngsave\n";
   302     
   382     
   303     vector<Edge> el;
   383     if(_showEdges)
   304     if(_enableParallel) {
   384       if(_enableParallel) {
   305       for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e);
   385 	vector<Edge> el;
   306       sort(el.begin(),el.end(),edgeLess(g));
   386 	for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e);
   307     }
   387 	sort(el.begin(),el.end(),edgeLess(g));
   308     
   388 	
   309     for(NodeIt n(g);n!=INVALID;++n)
   389 	typename vector<Edge>::iterator j;
   310       for(OutEdgeIt e(g,n);e!=INVALID;++e)
   390 	for(typename vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
   311 	if(_drawArrows) {
   391 	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
   312 	  xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   392 	  
   313 	  double l=sqrt(d.normSquare());
   393 	  if(_drawArrows) {
   314 	  d/=l;
   394 	    // 	  xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   315 	  xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
   395 	    // 	  double l=sqrt(d.normSquare());
   316 			_coords[g.source(e)]);
   396 	    // 	  d/=l;
   317 	  os << l-(_nodeSizes[g.source(e)]+
   397 	    // 	  xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
       
   398 	    // 			_coords[g.source(e)]);
       
   399 	    // 	  os << l-(_nodeSizes[g.source(e)]+
       
   400 	    // 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
       
   401 	    // 	       << _edgeWidths[e]*_edgeWidthScale << ' '
       
   402 	    // 	       << d.x << ' ' << d.y << ' '
       
   403 	    // 	       << x1.x << ' ' << x1.y << ' '
       
   404 	    // 	       << _edgeColors[e].getR() << ' '
       
   405 	    // 	       << _edgeColors[e].getG() << ' '
       
   406 	    // 	       << _edgeColors[e].getB() << " arr\n";
       
   407 	  }
       
   408 	  else {
       
   409 	    double sw=0;
       
   410 	    for(typename vector<Edge>::iterator e=i;e!=j;++e)
       
   411 	      sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
       
   412 	    sw-=_parEdgeDist;
       
   413 	    sw/=-2.0;
       
   414 	    xy<double> d(_coords[g.target(*i)]-_coords[g.source(*i)]);
       
   415 	    double l=sqrt(d.normSquare());
       
   416 	    d/=l;
       
   417 	    for(typename vector<Edge>::iterator e=i;e!=j;++e) {
       
   418 	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
       
   419 	      xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]);
       
   420 	      m=m/2.0+rot(d)*sw/.75;
       
   421 	      os << _coords[g.source(*e)].x << ' '
       
   422 		 << _coords[g.source(*e)].y << ' '
       
   423 		 << m.x << ' ' << m.y << ' '
       
   424 		 << _coords[g.target(*e)].x << ' '
       
   425 		 << _coords[g.target(*e)].y << ' '
       
   426 		 << _edgeColors[*e].getR() << ' '
       
   427 		 << _edgeColors[*e].getG() << ' '
       
   428 		 << _edgeColors[*e].getB() << ' '
       
   429 		 << _edgeWidths[*e]*_edgeWidthScale << " lb\n";
       
   430 	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
       
   431 	    }
       
   432 	  }
       
   433 	}
       
   434       }
       
   435       else for(NodeIt n(g);n!=INVALID;++n)
       
   436 	for(OutEdgeIt e(g,n);e!=INVALID;++e)
       
   437 	  if(_drawArrows) {
       
   438 	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
       
   439 	    double l=sqrt(d.normSquare());
       
   440 	    d/=l;
       
   441 	    xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
       
   442 			  _coords[g.source(e)]);
       
   443 	    os << l-(_nodeSizes[g.source(e)]+
   318 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
   444 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
   319 	       << _edgeWidths[e]*_edgeWidthScale << ' '
   445 	       << _edgeWidths[e]*_edgeWidthScale << ' '
   320 	       << d.x << ' ' << d.y << ' '
   446 	       << d.x << ' ' << d.y << ' '
   321 	       << x1.x << ' ' << x1.y << ' '
   447 	       << x1.x << ' ' << x1.y << ' '
   322 	       << _edgeColors[e].getR() << ' '
   448 	       << _edgeColors[e].getR() << ' '
   323 	       << _edgeColors[e].getG() << ' '
   449 	       << _edgeColors[e].getG() << ' '
   324 	       << _edgeColors[e].getB() << " arr\n";
   450 	       << _edgeColors[e].getB() << " arr\n";
   325 	}
   451 	  }
   326     	else os << _coords[g.source(e)].x << ' '
   452 	  else os << _coords[g.source(e)].x << ' '
   327 		  << _coords[g.source(e)].y << ' '
   453 		  << _coords[g.source(e)].y << ' '
   328 		  << _coords[g.target(e)].x << ' '
   454 		  << _coords[g.target(e)].x << ' '
   329 		  << _coords[g.target(e)].y << ' '
   455 		  << _coords[g.target(e)].y << ' '
   330 		  << _edgeColors[e].getR() << ' '
   456 		  << _edgeColors[e].getR() << ' '
   331 		  << _edgeColors[e].getG() << ' '
   457 		  << _edgeColors[e].getG() << ' '
   332 		  << _edgeColors[e].getB() << ' '
   458 		  << _edgeColors[e].getB() << ' '
   333 		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
   459 		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
   334     os << "grestore\n%Nodes:\ngsave\n";
   460     os << "grestore\n%Nodes:\ngsave\n";
   335     for(NodeIt n(g);n!=INVALID;++n)
   461     if(_showNodes)
   336       os << _coords[n].x << ' ' << _coords[n].y << ' '
   462       for(NodeIt n(g);n!=INVALID;++n)
       
   463 	os << _coords[n].x << ' ' << _coords[n].y << ' '
   337 	   << _nodeSizes[n]*_nodeScale << ' '
   464 	   << _nodeSizes[n]*_nodeScale << ' '
   338 	   << _nodeColors[n].getR() << ' '
   465 	   << _nodeColors[n].getR() << ' '
   339 	   << _nodeColors[n].getG() << ' '
   466 	   << _nodeColors[n].getG() << ' '
   340 	   << _nodeColors[n].getB() << " n\n"; 
   467 	   << _nodeColors[n].getB() << " n\n"; 
       
   468     if(_showNodeText) {
       
   469       os << "grestore\n%Node texts:\ngsave\n";
       
   470       os << "/fosi " << _nodeTextSize << " def\n";
       
   471       os << "(Helvetica) findfont fosi scalefont setfont\n";
       
   472       os << "0 0 0 setrgbcolor\n";
       
   473       for(NodeIt n(g);n!=INVALID;++n)
       
   474 	os << _coords[n].x << ' ' << _coords[n].y
       
   475 	   << " (" << _nodeTexts[n] << ") cshow\n";
       
   476     }
   341     os << "grestore\ngrestore\n";
   477     os << "grestore\ngrestore\n";
   342 
       
   343 
   478 
   344     //CleanUp:
   479     //CleanUp:
   345     if(_pleaseRemoveOsStream) {delete &os;}
   480     if(_pleaseRemoveOsStream) {delete &os;}
   346   } 
   481   } 
   347 };
   482 };
   362 /// graphToEps(g).scale(10).coords(coords)
   497 /// graphToEps(g).scale(10).coords(coords)
   363 ///              .nodeScale(2).nodeSizes(sizes)
   498 ///              .nodeScale(2).nodeSizes(sizes)
   364 ///              .edgeWidthScale(.4);
   499 ///              .edgeWidthScale(.4);
   365 ///\endcode
   500 ///\endcode
   366 ///\sa GraphToEps
   501 ///\sa GraphToEps
       
   502 ///\sa graphToEps(G &g, char *file_name)
   367 template<class G>
   503 template<class G>
   368 GraphToEps<DefaultGraphToEpsTraits<G> > 
   504 GraphToEps<DefaultGraphToEpsTraits<G> > 
   369 graphToEps(G &g,std::ostream& os=std::cout)
   505 graphToEps(G &g, std::ostream& os=std::cout)
   370 {
   506 {
   371   return 
   507   return 
   372     GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
   508     GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
   373 }
   509 }
   374  
   510  
   375 ///Generates an EPS file from a graph
   511 ///Generates an EPS file from a graph
   376 
   512 
   377 ///\ingroup misc
   513 //\ingroup misc
   378 ///Generates an EPS file from a graph.
   514 ///This function does the same as
   379 ///\param g is a reference to the graph to be printed
   515 ///\ref graphToEps(G &g,std::ostream& os)
   380 ///\param file_name is the output file_name.
   516 ///but it writes its output into the file \c file_name
   381 ///
   517 ///instead of a stream.
   382 ///This function also has a lot of \ref named-templ-param "named parameters",
   518 ///\sa graphToEps(G &g, std::ostream& os)
   383 ///they are declared as the members of class \ref GraphToEps. The following
       
   384 ///example shows how to use these parameters.
       
   385 ///\code
       
   386 /// graphToEps(g).scale(10).coords(coords)
       
   387 ///              .nodeScale(2).nodeSizes(sizes)
       
   388 ///              .edgeWidthScale(.4);
       
   389 ///\endcode
       
   390 ///\sa GraphToEps
       
   391 ///\todo Avoid duplicated documentation
       
   392 ///\bug Exception handling is missing? (Or we can just ignore it?)
       
   393 template<class G>
   519 template<class G>
   394 GraphToEps<DefaultGraphToEpsTraits<G> > 
   520 GraphToEps<DefaultGraphToEpsTraits<G> > 
   395 graphToEps(G &g,char *file_name)
   521 graphToEps(G &g,char *file_name)
   396 {
   522 {
   397   return GraphToEps<DefaultGraphToEpsTraits<G> >
   523   return GraphToEps<DefaultGraphToEpsTraits<G> >
   398     (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true));
   524     (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true));
   399 }
   525 }
   400 
   526 
       
   527 //Generates an EPS file from a graph.
       
   528 //\param g is a reference to the graph to be printed
       
   529 //\param file_name is the output file_name.
       
   530 //
       
   531 //This function also has a lot of \ref named-templ-param "named parameters",
       
   532 //they are declared as the members of class \ref GraphToEps. The following
       
   533 //example shows how to use these parameters.
       
   534 //\code
       
   535 // graphToEps(g).scale(10).coords(coords)
       
   536 //              .nodeScale(2).nodeSizes(sizes)
       
   537 //              .edgeWidthScale(.4);
       
   538 //\endcode
       
   539 //\sa GraphToEps
       
   540 //\todo Avoid duplicated documentation
       
   541 //\bug Exception handling is missing? (Or we can just ignore it?)
   401 
   542 
   402 }
   543 }
   403 
   544 
   404 using namespace lemon;
   545 using namespace lemon;
   405 
   546 
   420     }
   561     }
   421     return Color(0,0,0);
   562     return Color(0,0,0);
   422   }
   563   }
   423 } colorSet;
   564 } colorSet;
   424 
   565 
       
   566 class IdMap :public MapBase<ListGraph::Node,int>
       
   567 {
       
   568   const ListGraph &g;
       
   569 public:
       
   570   IdMap(const ListGraph &_g) :g(_g) {}
       
   571   Value operator[](Key n) const { return g.id(n); }
       
   572 };
       
   573 
       
   574 
       
   575 
   425 int main()
   576 int main()
   426 {
   577 {
   427   ListGraph g;
   578   ListGraph g;
   428   typedef ListGraph::Node Node;
   579   typedef ListGraph::Node Node;
   429   typedef ListGraph::NodeIt NodeIt;
   580   typedef ListGraph::NodeIt NodeIt;
   456   e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
   607   e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
   457   e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
   608   e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
   458   e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
   609   e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
   459   e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
   610   e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
   460   
   611   
       
   612   IdMap id(g);
       
   613 
   461   graphToEps(g,"proba.eps").scale(10).coords(coords).
   614   graphToEps(g,"proba.eps").scale(10).coords(coords).
   462     nodeScale(2).nodeSizes(sizes).
   615     nodeScale(2).nodeSizes(sizes).
   463     nodeColors(composeMap(colorSet,colors)).
   616     nodeColors(composeMap(colorSet,colors)).
   464     edgeColors(composeMap(colorSet,ecolors)).
   617     edgeColors(composeMap(colorSet,ecolors)).
   465     edgeWidthScale(.4).edgeWidths(widths);
   618     edgeWidthScale(.4).edgeWidths(widths).
       
   619     nodeTexts(id).nodeTextSize(3);
       
   620 
   466   graphToEps(g,"proba_arr.eps").scale(10).coords(coords).
   621   graphToEps(g,"proba_arr.eps").scale(10).coords(coords).
   467     nodeScale(2).nodeSizes(sizes).
   622     nodeScale(2).nodeSizes(sizes).
   468     nodeColors(composeMap(colorSet,colors)).
   623     nodeColors(composeMap(colorSet,colors)).
   469     edgeColors(composeMap(colorSet,ecolors)).
   624     edgeColors(composeMap(colorSet,ecolors)).
   470     edgeWidthScale(.4).edgeWidths(widths).
   625     edgeWidthScale(.4).edgeWidths(widths).
   471     drawArrows().arrowWidth(1).arrowLength(1)
   626     nodeTexts(id).nodeTextSize(3).
   472     ;
   627     drawArrows().arrowWidth(1).arrowLength(1);
       
   628 
       
   629   e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1;
       
   630   e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2;
       
   631 
       
   632   e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1;
       
   633   e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1;
       
   634   e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1;
       
   635   e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1;
       
   636   e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1;
       
   637   e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1;
       
   638   e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1;
       
   639 
       
   640   graphToEps(g,"proba_par.eps").scale(10).coords(coords).
       
   641     nodeScale(2).nodeSizes(sizes).
       
   642     nodeColors(composeMap(colorSet,colors)).
       
   643     edgeColors(composeMap(colorSet,ecolors)).
       
   644     edgeWidthScale(.4).edgeWidths(widths).
       
   645     nodeTexts(id).nodeTextSize(3).
       
   646     enableParallel().parEdgeDist(1.5);
   473 }
   647 }