Port graph_to_eps() and Color from svn -r3482.
authorAlpar Juttner <alpar@cs.elte.hu>
Thu, 03 Apr 2008 11:10:49 +0100
changeset 1287cd965d2257f
parent 115 7b44eea654d0
child 129 e99385bca9fe
Port graph_to_eps() and Color from svn -r3482.
.hgignore
demo/Makefile.am
demo/arg_parser_demo.cc
demo/graph_to_eps_demo.cc
lemon/Makefile.am
lemon/arg_parser.cc
lemon/bits/bezier.h
lemon/color.cc
lemon/color.h
lemon/graph_to_eps.h
     1.1 --- a/.hgignore	Tue Apr 01 16:25:51 2008 +0100
     1.2 +++ b/.hgignore	Thu Apr 03 11:10:49 2008 +0100
     1.3 @@ -24,6 +24,7 @@
     1.4  .dirstamp
     1.5  .libs/*
     1.6  .deps/*
     1.7 +demo/*.eps
     1.8  
     1.9  syntax: regexp
    1.10  (.*/)?\#[^/]*\#$
     2.1 --- a/demo/Makefile.am	Tue Apr 01 16:25:51 2008 +0100
     2.2 +++ b/demo/Makefile.am	Thu Apr 03 11:10:49 2008 +0100
     2.3 @@ -4,9 +4,12 @@
     2.4  if WANT_DEMO
     2.5  
     2.6  noinst_PROGRAMS += \
     2.7 -        demo/arg_parser_demo
     2.8 +        demo/arg_parser_demo \
     2.9 +        demo/graph_to_eps_demo
    2.10  
    2.11  endif WANT_DEMO
    2.12  
    2.13  demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc
    2.14  
    2.15 +demo_graph_to_eps_demo_SOURCES = demo/graph_to_eps_demo.cc
    2.16 +
     3.1 --- a/demo/arg_parser_demo.cc	Tue Apr 01 16:25:51 2008 +0100
     3.2 +++ b/demo/arg_parser_demo.cc	Thu Apr 03 11:10:49 2008 +0100
     3.3 @@ -37,6 +37,7 @@
     3.4    bool g1,g2,g3;
     3.5    ap.refOption("n", "An integer input.", i, true)
     3.6      .refOption("val", "A double input.", d)
     3.7 +    .doubleOption("val2", "A double input.", d)
     3.8      .synonym("vals","val")
     3.9      .refOption("name", "A string input.", s)
    3.10      .refOption("f", "A switch.", b)
    3.11 @@ -45,7 +46,7 @@
    3.12      .refOption("grb","Choice B",g2)
    3.13      .refOption("grc","Choice C",g3)
    3.14      .optionGroup("gr","gra")
    3.15 -    .optionGroup("gr","grb")
    3.16 +    .optionGroup("gr","grbkk")
    3.17      .optionGroup("gr","grc")
    3.18      .mandatoryGroup("gr")
    3.19      .onlyOneGroup("gr")
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/demo/graph_to_eps_demo.cc	Thu Apr 03 11:10:49 2008 +0100
     4.3 @@ -0,0 +1,208 @@
     4.4 +/* -*- C++ -*-
     4.5 + *
     4.6 + * This file is a part of LEMON, a generic C++ optimization library
     4.7 + *
     4.8 + * Copyright (C) 2003-2008
     4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    4.11 + *
    4.12 + * Permission to use, modify and distribute this software is granted
    4.13 + * provided that this copyright notice appears in all copies. For
    4.14 + * precise terms see the accompanying LICENSE file.
    4.15 + *
    4.16 + * This software is provided "AS IS" with no warranty of any kind,
    4.17 + * express or implied, and with no claim as to its suitability for any
    4.18 + * purpose.
    4.19 + *
    4.20 + */
    4.21 +
    4.22 +/// \ingroup demos
    4.23 +/// \file
    4.24 +/// \brief Demo of the graph grawing function \ref graphToEps()
    4.25 +///
    4.26 +/// This demo program shows examples how to  use the function \ref
    4.27 +/// graphToEps(). It takes no input but simply creates  six
    4.28 +/// <tt>.eps</tt> files demonstrating the capability of \ref
    4.29 +/// graphToEps(), and showing how to draw directed/graphs,
    4.30 +/// how to handle parallel egdes, how to change the properties (like
    4.31 +/// color, shape, size, title etc.) of nodes and arcs individually
    4.32 +/// using appropriate \ref maps-page "graph maps".
    4.33 +///
    4.34 +/// \include graph_to_eps_demo.cc
    4.35 +
    4.36 +#include <lemon/math.h>
    4.37 +
    4.38 +#include<lemon/graph_to_eps.h>
    4.39 +#include<lemon/list_graph.h>
    4.40 +#include<lemon/graph_utils.h>
    4.41 +
    4.42 +using namespace std;
    4.43 +using namespace lemon;
    4.44 +
    4.45 +int main()
    4.46 +{
    4.47 +  Palette palette;
    4.48 +  Palette paletteW(-1,true);
    4.49 +
    4.50 +  ListDigraph g;
    4.51 +  typedef ListDigraph::Node Node;
    4.52 +  typedef ListDigraph::NodeIt NodeIt;
    4.53 +  typedef ListDigraph::Arc Arc;
    4.54 +  typedef dim2::Point<int> Point;
    4.55 +  
    4.56 +  Node n1=g.addNode();
    4.57 +  Node n2=g.addNode();
    4.58 +  Node n3=g.addNode();
    4.59 +  Node n4=g.addNode();
    4.60 +  Node n5=g.addNode();
    4.61 +
    4.62 +  ListDigraph::NodeMap<Point> coords(g);
    4.63 +  ListDigraph::NodeMap<double> sizes(g);
    4.64 +  ListDigraph::NodeMap<int> colors(g);
    4.65 +  ListDigraph::NodeMap<int> shapes(g);
    4.66 +  ListDigraph::ArcMap<int> ecolors(g);
    4.67 +  ListDigraph::ArcMap<int> widths(g);
    4.68 +  
    4.69 +  coords[n1]=Point(50,50);  sizes[n1]=1; colors[n1]=1; shapes[n1]=0;
    4.70 +  coords[n2]=Point(50,70);  sizes[n2]=2; colors[n2]=2; shapes[n2]=2;
    4.71 +  coords[n3]=Point(70,70);  sizes[n3]=1; colors[n3]=3; shapes[n3]=0;
    4.72 +  coords[n4]=Point(70,50);  sizes[n4]=2; colors[n4]=4; shapes[n4]=1;
    4.73 +  coords[n5]=Point(85,60);  sizes[n5]=3; colors[n5]=5; shapes[n5]=2;
    4.74 +  
    4.75 +  Arc e;
    4.76 +
    4.77 +  e=g.addArc(n1,n2); ecolors[e]=0; widths[e]=1;
    4.78 +  e=g.addArc(n2,n3); ecolors[e]=0; widths[e]=1;
    4.79 +  e=g.addArc(n3,n5); ecolors[e]=0; widths[e]=3;
    4.80 +  e=g.addArc(n5,n4); ecolors[e]=0; widths[e]=1;
    4.81 +  e=g.addArc(n4,n1); ecolors[e]=0; widths[e]=1;
    4.82 +  e=g.addArc(n2,n4); ecolors[e]=1; widths[e]=2;
    4.83 +  e=g.addArc(n3,n4); ecolors[e]=2; widths[e]=1;
    4.84 +  
    4.85 +  IdMap<ListDigraph,Node> id(g);
    4.86 +
    4.87 +  cout << "Create 'graph_to_eps_demo_out_pure.eps'" << endl;
    4.88 +  graphToEps(g,"graph_to_eps_demo_out_pure.eps").
    4.89 +    //scale(10).
    4.90 +    coords(coords).
    4.91 +    title("Sample .eps figure").
    4.92 +    copyright("(C) 2003-2007 LEMON Project").
    4.93 +    run();
    4.94 +
    4.95 +  cout << "Create 'graph_to_eps_demo_out.eps'" << endl;
    4.96 +  graphToEps(g,"graph_to_eps_demo_out.eps").
    4.97 +    //scale(10).
    4.98 +    coords(coords).
    4.99 +    title("Sample .eps figure").
   4.100 +    copyright("(C) 2003-2007 LEMON Project").
   4.101 +    absoluteNodeSizes().absoluteArcWidths().
   4.102 +    nodeScale(2).nodeSizes(sizes).
   4.103 +    nodeShapes(shapes).
   4.104 +    nodeColors(composeMap(palette,colors)).
   4.105 +    arcColors(composeMap(palette,ecolors)).
   4.106 +    arcWidthScale(.4).arcWidths(widths).
   4.107 +    nodeTexts(id).nodeTextSize(3).
   4.108 +    run();
   4.109 +
   4.110 +
   4.111 +  cout << "Create 'graph_to_eps_demo_out_arr.eps'" << endl;
   4.112 +  graphToEps(g,"graph_to_eps_demo_out_arr.eps").
   4.113 +    //scale(10).
   4.114 +    title("Sample .eps figure (with arrowheads)").
   4.115 +    copyright("(C) 2003-2007 LEMON Project").
   4.116 +    absoluteNodeSizes().absoluteArcWidths().
   4.117 +    nodeColors(composeMap(palette,colors)).
   4.118 +    coords(coords).
   4.119 +    nodeScale(2).nodeSizes(sizes).
   4.120 +    nodeShapes(shapes).
   4.121 +    arcColors(composeMap(palette,ecolors)).
   4.122 +    arcWidthScale(.4).arcWidths(widths).
   4.123 +    nodeTexts(id).nodeTextSize(3).
   4.124 +    drawArrows().arrowWidth(1).arrowLength(1).
   4.125 +    run();
   4.126 +
   4.127 +  e=g.addArc(n1,n4); ecolors[e]=2; widths[e]=1;
   4.128 +  e=g.addArc(n4,n1); ecolors[e]=1; widths[e]=2;
   4.129 +
   4.130 +  e=g.addArc(n1,n2); ecolors[e]=1; widths[e]=1;
   4.131 +  e=g.addArc(n1,n2); ecolors[e]=2; widths[e]=1;
   4.132 +  e=g.addArc(n1,n2); ecolors[e]=3; widths[e]=1;
   4.133 +  e=g.addArc(n1,n2); ecolors[e]=4; widths[e]=1;
   4.134 +  e=g.addArc(n1,n2); ecolors[e]=5; widths[e]=1;
   4.135 +  e=g.addArc(n1,n2); ecolors[e]=6; widths[e]=1;
   4.136 +  e=g.addArc(n1,n2); ecolors[e]=7; widths[e]=1;
   4.137 +
   4.138 +  cout << "Create 'graph_to_eps_demo_out_par.eps'" << endl;
   4.139 +  graphToEps(g,"graph_to_eps_demo_out_par.eps").
   4.140 +    //scale(10).
   4.141 +    title("Sample .eps figure (parallel arcs)").
   4.142 +    copyright("(C) 2003-2007 LEMON Project").
   4.143 +    absoluteNodeSizes().absoluteArcWidths().
   4.144 +    nodeShapes(shapes).
   4.145 +    coords(coords).
   4.146 +    nodeScale(2).nodeSizes(sizes).
   4.147 +    nodeColors(composeMap(palette,colors)).
   4.148 +    arcColors(composeMap(palette,ecolors)).
   4.149 +    arcWidthScale(.4).arcWidths(widths).
   4.150 +    nodeTexts(id).nodeTextSize(3).
   4.151 +    enableParallel().parArcDist(1.5).
   4.152 +    run();
   4.153 +  
   4.154 +  cout << "Create 'graph_to_eps_demo_out_par_arr.eps'" << endl;
   4.155 +  graphToEps(g,"graph_to_eps_demo_out_par_arr.eps").
   4.156 +    //scale(10).
   4.157 +    title("Sample .eps figure (parallel arcs and arrowheads)").
   4.158 +    copyright("(C) 2003-2007 LEMON Project").
   4.159 +    absoluteNodeSizes().absoluteArcWidths().
   4.160 +    nodeScale(2).nodeSizes(sizes).
   4.161 +    coords(coords).
   4.162 +    nodeShapes(shapes).
   4.163 +    nodeColors(composeMap(palette,colors)).
   4.164 +    arcColors(composeMap(palette,ecolors)).
   4.165 +    arcWidthScale(.3).arcWidths(widths).
   4.166 +    nodeTexts(id).nodeTextSize(3).
   4.167 +    enableParallel().parArcDist(1).
   4.168 +    drawArrows().arrowWidth(1).arrowLength(1).
   4.169 +    run();
   4.170 +
   4.171 +  cout << "Create 'graph_to_eps_demo_out_a4.eps'" << endl;
   4.172 +  graphToEps(g,"graph_to_eps_demo_out_a4.eps").scaleToA4().
   4.173 +    title("Sample .eps figure (fits to A4)").
   4.174 +    copyright("(C) 2003-2007 LEMON Project").
   4.175 +    absoluteNodeSizes().absoluteArcWidths().
   4.176 +    nodeScale(2).nodeSizes(sizes).
   4.177 +    coords(coords).
   4.178 +    nodeShapes(shapes).
   4.179 +    nodeColors(composeMap(palette,colors)).
   4.180 +    arcColors(composeMap(palette,ecolors)).
   4.181 +    arcWidthScale(.3).arcWidths(widths).
   4.182 +    nodeTexts(id).nodeTextSize(3).
   4.183 +    enableParallel().parArcDist(1).
   4.184 +    drawArrows().arrowWidth(1).arrowLength(1).
   4.185 +    run();
   4.186 +
   4.187 +  ListDigraph h;
   4.188 +  ListDigraph::NodeMap<int> hcolors(h);
   4.189 +  ListDigraph::NodeMap<Point> hcoords(h);
   4.190 +  
   4.191 +  int cols=int(sqrt(double(palette.size())));
   4.192 +  for(int i=0;i<int(paletteW.size());i++) {
   4.193 +    Node n=h.addNode();
   4.194 +    hcoords[n]=Point(i%cols,i/cols);
   4.195 +    hcolors[n]=i;
   4.196 +  }
   4.197 +  
   4.198 +  cout << "Create 'graph_to_eps_demo_out_colors.eps'" << endl;
   4.199 +  graphToEps(h,"graph_to_eps_demo_out_colors.eps").
   4.200 +    //scale(60).
   4.201 +    title("Sample .eps figure (Palette demo)").
   4.202 +    copyright("(C) 2003-2007 LEMON Project").
   4.203 +    coords(hcoords).
   4.204 +    absoluteNodeSizes().absoluteArcWidths().
   4.205 +    nodeScale(45).
   4.206 +    distantColorNodeTexts().
   4.207 +    //    distantBWNodeTexts().
   4.208 +    nodeTexts(hcolors).nodeTextSize(.6).
   4.209 +    nodeColors(composeMap(paletteW,hcolors)).
   4.210 +    run();
   4.211 +}
     5.1 --- a/lemon/Makefile.am	Tue Apr 01 16:25:51 2008 +0100
     5.2 +++ b/lemon/Makefile.am	Thu Apr 03 11:10:49 2008 +0100
     5.3 @@ -9,6 +9,7 @@
     5.4  lemon_libemon_la_SOURCES = \
     5.5          lemon/arg_parser.cc \
     5.6          lemon/base.cc \
     5.7 +        lemon/color.cc \
     5.8          lemon/random.cc
     5.9  
    5.10  
    5.11 @@ -20,10 +21,12 @@
    5.12  	lemon/assert.h \
    5.13          lemon/bfs.h \
    5.14          lemon/bin_heap.h \
    5.15 +        lemon/color.h \
    5.16          lemon/dfs.h \
    5.17          lemon/dijkstra.h \
    5.18          lemon/dim2.h \
    5.19  	lemon/error.h \
    5.20 +        lemon/graph_to_eps.h \
    5.21  	lemon/graph_utils.h \
    5.22  	lemon/kruskal.h \
    5.23  	lemon/list_graph.h \
    5.24 @@ -39,6 +42,7 @@
    5.25  	lemon/bits/alteration_notifier.h \
    5.26  	lemon/bits/array_map.h \
    5.27  	lemon/bits/base_extender.h \
    5.28 +        lemon/bits/bezier.h \
    5.29  	lemon/bits/default_map.h \
    5.30  	lemon/bits/graph_extender.h \
    5.31          lemon/bits/invalid.h \
     6.1 --- a/lemon/arg_parser.cc	Tue Apr 01 16:25:51 2008 +0100
     6.2 +++ b/lemon/arg_parser.cc	Thu Apr 03 11:10:49 2008 +0100
     6.3 @@ -194,6 +194,7 @@
     6.4    {
     6.5      Opts::iterator i = _opts.find(opt);
     6.6      LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
     6.7 +    if(i==_opts.end()) std::cout << "JAJJJJJJJJ\n";
     6.8      LEMON_ASSERT(!(i->second.ingroup), 
     6.9                   "Option already in option group: '"+opt+"'");
    6.10      GroupData &g=_groups[group];
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/lemon/bits/bezier.h	Thu Apr 03 11:10:49 2008 +0100
     7.3 @@ -0,0 +1,176 @@
     7.4 +/* -*- C++ -*-
     7.5 + *
     7.6 + * This file is a part of LEMON, a generic C++ optimization library
     7.7 + *
     7.8 + * Copyright (C) 2003-2008
     7.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    7.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    7.11 + *
    7.12 + * Permission to use, modify and distribute this software is granted
    7.13 + * provided that this copyright notice appears in all copies. For
    7.14 + * precise terms see the accompanying LICENSE file.
    7.15 + *
    7.16 + * This software is provided "AS IS" with no warranty of any kind,
    7.17 + * express or implied, and with no claim as to its suitability for any
    7.18 + * purpose.
    7.19 + *
    7.20 + */
    7.21 +
    7.22 +#ifndef LEMON_BEZIER_H
    7.23 +#define LEMON_BEZIER_H
    7.24 +
    7.25 +///\ingroup misc
    7.26 +///\file
    7.27 +///\brief Classes to compute with Bezier curves.
    7.28 +///
    7.29 +///Up to now this file is used internally by \ref graph_to_eps.h
    7.30 +///
    7.31 +///\author Alpar Juttner
    7.32 +
    7.33 +#include<lemon/dim2.h>
    7.34 +
    7.35 +namespace lemon {
    7.36 +  namespace dim2 {
    7.37 +
    7.38 +class BezierBase {
    7.39 +public:
    7.40 +  typedef Point<double> Point;
    7.41 +protected:
    7.42 +  static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
    7.43 +};
    7.44 +
    7.45 +class Bezier1 : public BezierBase
    7.46 +{
    7.47 +public:
    7.48 +  Point p1,p2;
    7.49 +
    7.50 +  Bezier1() {}
    7.51 +  Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
    7.52 +  
    7.53 +  Point operator()(double t) const
    7.54 +  {
    7.55 +    //    return conv(conv(p1,p2,t),conv(p2,p3,t),t);
    7.56 +    return conv(p1,p2,t);
    7.57 +  }
    7.58 +  Bezier1 before(double t) const
    7.59 +  {
    7.60 +    return Bezier1(p1,conv(p1,p2,t));
    7.61 +  }
    7.62 +  
    7.63 +  Bezier1 after(double t) const
    7.64 +  {
    7.65 +    return Bezier1(conv(p1,p2,t),p2);
    7.66 +  }
    7.67 +
    7.68 +  Bezier1 revert() const { return Bezier1(p2,p1);}
    7.69 +  Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
    7.70 +  Point grad() const { return p2-p1; }
    7.71 +  Point norm() const { return rot90(p2-p1); }
    7.72 +  Point grad(double) const { return grad(); }
    7.73 +  Point norm(double t) const { return rot90(grad(t)); }
    7.74 +};
    7.75 +
    7.76 +class Bezier2 : public BezierBase
    7.77 +{
    7.78 +public:
    7.79 +  Point p1,p2,p3;
    7.80 +
    7.81 +  Bezier2() {}
    7.82 +  Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
    7.83 +  Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
    7.84 +  Point operator()(double t) const
    7.85 +  {
    7.86 +    //    return conv(conv(p1,p2,t),conv(p2,p3,t),t);
    7.87 +    return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
    7.88 +  }
    7.89 +  Bezier2 before(double t) const
    7.90 +  {
    7.91 +    Point q(conv(p1,p2,t));
    7.92 +    Point r(conv(p2,p3,t));
    7.93 +    return Bezier2(p1,q,conv(q,r,t));
    7.94 +  }
    7.95 +  
    7.96 +  Bezier2 after(double t) const
    7.97 +  {
    7.98 +    Point q(conv(p1,p2,t));
    7.99 +    Point r(conv(p2,p3,t));
   7.100 +    return Bezier2(conv(q,r,t),r,p3);
   7.101 +  }
   7.102 +  Bezier2 revert() const { return Bezier2(p3,p2,p1);}
   7.103 +  Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
   7.104 +  Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
   7.105 +  Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
   7.106 +  Point grad(double t) const { return grad()(t); }
   7.107 +  Point norm(double t) const { return rot90(grad(t)); }
   7.108 +};
   7.109 +
   7.110 +class Bezier3 : public BezierBase
   7.111 +{
   7.112 +public:
   7.113 +  Point p1,p2,p3,p4;
   7.114 +
   7.115 +  Bezier3() {}
   7.116 +  Bezier3(Point _p1, Point _p2, Point _p3, Point _p4)
   7.117 +    : p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
   7.118 +  Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), 
   7.119 +			      p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
   7.120 +  Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
   7.121 +			      p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
   7.122 +  
   7.123 +  Point operator()(double t) const 
   7.124 +    {
   7.125 +      //    return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
   7.126 +      return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
   7.127 +	(3*t*t*(1-t))*p3+(t*t*t)*p4;
   7.128 +    }
   7.129 +  Bezier3 before(double t) const
   7.130 +    {
   7.131 +      Point p(conv(p1,p2,t));
   7.132 +      Point q(conv(p2,p3,t));
   7.133 +      Point r(conv(p3,p4,t));
   7.134 +      Point a(conv(p,q,t));
   7.135 +      Point b(conv(q,r,t));
   7.136 +      Point c(conv(a,b,t));
   7.137 +      return Bezier3(p1,p,a,c);
   7.138 +    }
   7.139 +  
   7.140 +  Bezier3 after(double t) const
   7.141 +    {
   7.142 +      Point p(conv(p1,p2,t));
   7.143 +      Point q(conv(p2,p3,t));
   7.144 +      Point r(conv(p3,p4,t));
   7.145 +      Point a(conv(p,q,t));
   7.146 +      Point b(conv(q,r,t));
   7.147 +      Point c(conv(a,b,t));
   7.148 +      return Bezier3(c,b,r,p4);
   7.149 +    }
   7.150 +  Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
   7.151 +  Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
   7.152 +  Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
   7.153 +  Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
   7.154 +				  3.0*rot90(p3-p2),
   7.155 +				  3.0*rot90(p4-p3)); }
   7.156 +  Point grad(double t) const { return grad()(t); }
   7.157 +  Point norm(double t) const { return rot90(grad(t)); }
   7.158 +
   7.159 +  template<class R,class F,class S,class D>
   7.160 +  R recSplit(F &_f,const S &_s,D _d) const 
   7.161 +  {
   7.162 +    const Point a=(p1+p2)/2;
   7.163 +    const Point b=(p2+p3)/2;
   7.164 +    const Point c=(p3+p4)/2;
   7.165 +    const Point d=(a+b)/2;
   7.166 +    const Point e=(b+c)/2;
   7.167 +    const Point f=(d+e)/2;
   7.168 +    R f1=_f(Bezier3(p1,a,d,e),_d);
   7.169 +    R f2=_f(Bezier3(e,d,c,p4),_d);
   7.170 +    return _s(f1,f2);
   7.171 +  }
   7.172 +  
   7.173 +};
   7.174 +
   7.175 +
   7.176 +} //END OF NAMESPACE dim2
   7.177 +} //END OF NAMESPACE lemon
   7.178 +
   7.179 +#endif // LEMON_BEZIER_H
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/lemon/color.cc	Thu Apr 03 11:10:49 2008 +0100
     8.3 @@ -0,0 +1,44 @@
     8.4 +/* -*- C++ -*-
     8.5 + *
     8.6 + * This file is a part of LEMON, a generic C++ optimization library
     8.7 + *
     8.8 + * Copyright (C) 2003-2008
     8.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    8.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    8.11 + *
    8.12 + * Permission to use, modify and distribute this software is granted
    8.13 + * provided that this copyright notice appears in all copies. For
    8.14 + * precise terms see the accompanying LICENSE file.
    8.15 + *
    8.16 + * This software is provided "AS IS" with no warranty of any kind,
    8.17 + * express or implied, and with no claim as to its suitability for any
    8.18 + * purpose.
    8.19 + *
    8.20 + */
    8.21 +
    8.22 +///\file
    8.23 +///\brief Color constants
    8.24 +
    8.25 +#include<lemon/color.h>
    8.26 +
    8.27 +namespace lemon {
    8.28 +
    8.29 +  const Color WHITE(1,1,1);
    8.30 +  
    8.31 +  const Color BLACK(0,0,0);
    8.32 +  const Color RED(1,0,0);
    8.33 +  const Color GREEN(0,1,0);
    8.34 +  const Color BLUE(0,0,1);
    8.35 +  const Color YELLOW(1,1,0);
    8.36 +  const Color MAGENTA(1,0,1);
    8.37 +  const Color CYAN(0,1,1);
    8.38 +
    8.39 +  const Color GREY(0,0,0);
    8.40 +  const Color DARK_RED(.5,0,0);
    8.41 +  const Color DARK_GREEN(0,.5,0);
    8.42 +  const Color DARK_BLUE(0,0,.5);
    8.43 +  const Color DARK_YELLOW(.5,.5,0);
    8.44 +  const Color DARK_MAGENTA(.5,0,.5);
    8.45 +  const Color DARK_CYAN(0,.5,.5);
    8.46 +    
    8.47 +} //namespace lemon
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/lemon/color.h	Thu Apr 03 11:10:49 2008 +0100
     9.3 @@ -0,0 +1,207 @@
     9.4 +/* -*- C++ -*-
     9.5 + *
     9.6 + * This file is a part of LEMON, a generic C++ optimization library
     9.7 + *
     9.8 + * Copyright (C) 2003-2008
     9.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    9.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    9.11 + *
    9.12 + * Permission to use, modify and distribute this software is granted
    9.13 + * provided that this copyright notice appears in all copies. For
    9.14 + * precise terms see the accompanying LICENSE file.
    9.15 + *
    9.16 + * This software is provided "AS IS" with no warranty of any kind,
    9.17 + * express or implied, and with no claim as to its suitability for any
    9.18 + * purpose.
    9.19 + *
    9.20 + */
    9.21 +
    9.22 +#ifndef LEMON_COLOR_H
    9.23 +#define LEMON_COLOR_H
    9.24 +
    9.25 +#include<vector>
    9.26 +#include<lemon/math.h>
    9.27 +#include<lemon/maps.h>
    9.28 +
    9.29 +
    9.30 +///\ingroup misc
    9.31 +///\file
    9.32 +///\brief Tools to manage RGB colors.
    9.33 +///
    9.34 +///\author Alpar Juttner
    9.35 +
    9.36 +namespace lemon {
    9.37 +
    9.38 +
    9.39 +  /// \addtogroup misc
    9.40 +  /// @{
    9.41 +
    9.42 +  ///Data structure representing RGB colors.
    9.43 +
    9.44 +  ///Data structure representing RGB colors.
    9.45 +  class Color
    9.46 +  {
    9.47 +    double _r,_g,_b;
    9.48 +  public:
    9.49 +    ///Default constructor
    9.50 +    Color() {}
    9.51 +    ///Constructor
    9.52 +    Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
    9.53 +    ///Set the red component
    9.54 +    double & red() {return _r;}
    9.55 +    ///Return the red component
    9.56 +    const double & red() const {return _r;}
    9.57 +    ///Set the green component
    9.58 +    double & green() {return _g;}
    9.59 +    ///Return the green component
    9.60 +    const double & green() const {return _g;}
    9.61 +    ///Set the blue component
    9.62 +    double & blue() {return _b;}
    9.63 +    ///Return the blue component
    9.64 +    const double & blue() const {return _b;}
    9.65 +    ///Set the color components
    9.66 +    void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    9.67 +  };
    9.68 +
    9.69 +  /// White color constant
    9.70 +  extern const Color WHITE;  
    9.71 +  /// Black color constant
    9.72 +  extern const Color BLACK;
    9.73 +  /// Red color constant
    9.74 +  extern const Color RED;
    9.75 +  /// Green color constant
    9.76 +  extern const Color GREEN;
    9.77 +  /// Blue color constant
    9.78 +  extern const Color BLUE;
    9.79 +  /// Yellow color constant
    9.80 +  extern const Color YELLOW;
    9.81 +  /// Magenta color constant
    9.82 +  extern const Color MAGENTA;
    9.83 +  /// Cyan color constant
    9.84 +  extern const Color CYAN;
    9.85 +  /// Grey color constant
    9.86 +  extern const Color GREY;
    9.87 +  /// Dark red color constant
    9.88 +  extern const Color DARK_RED;
    9.89 +  /// Dark green color constant
    9.90 +  extern const Color DARK_GREEN;
    9.91 +  /// Drak blue color constant
    9.92 +  extern const Color DARK_BLUE;
    9.93 +  /// Dark yellow color constant
    9.94 +  extern const Color DARK_YELLOW;
    9.95 +  /// Dark magenta color constant
    9.96 +  extern const Color DARK_MAGENTA;
    9.97 +  /// Dark cyan color constant
    9.98 +  extern const Color DARK_CYAN;
    9.99 +
   9.100 +  ///Map <tt>int</tt>s to different \ref Color "Color"s
   9.101 +
   9.102 +  ///This map assigns one of the predefined \ref Color "Color"s to
   9.103 +  ///each <tt>int</tt>. It is possible to change the colors as well as
   9.104 +  ///their number. The integer range is cyclically mapped to the
   9.105 +  ///provided set of colors.
   9.106 +  ///
   9.107 +  ///This is a true \ref concepts::ReferenceMap "reference map", so
   9.108 +  ///you can also change the actual colors.
   9.109 +
   9.110 +  class Palette : public MapBase<int,Color>
   9.111 +  {
   9.112 +    std::vector<Color> colors;
   9.113 +  public:
   9.114 +    ///Constructor
   9.115 +
   9.116 +    ///Constructor 
   9.117 +    ///\param num the number of the allocated colors. If it is \c -1,
   9.118 +    ///the default color configuration is set up (26 color plus the
   9.119 +    ///white).  If \c num is less then 26/27 then the default color
   9.120 +    ///list is cut. Otherwise the color list is filled repeatedly with
   9.121 +    ///the default color list.  (The colors can be changed later on.)
   9.122 +    ///\param have_white indicates whether white is amongst the
   9.123 +    ///provided color (\c true) or not (\c false). If it is true,
   9.124 +    ///white will be assigned to \c 0.
   9.125 +    Palette(int num=-1,bool have_white=false)
   9.126 +    {
   9.127 +      if (num==0) return;
   9.128 +      do {
   9.129 +        if(have_white) colors.push_back(Color(1,1,1));
   9.130 +
   9.131 +        colors.push_back(Color(0,0,0));
   9.132 +        colors.push_back(Color(1,0,0));
   9.133 +        colors.push_back(Color(0,1,0));
   9.134 +        colors.push_back(Color(0,0,1));
   9.135 +        colors.push_back(Color(1,1,0));
   9.136 +        colors.push_back(Color(1,0,1));
   9.137 +        colors.push_back(Color(0,1,1));
   9.138 +      
   9.139 +        colors.push_back(Color(.5,0,0));
   9.140 +        colors.push_back(Color(0,.5,0));
   9.141 +        colors.push_back(Color(0,0,.5));
   9.142 +        colors.push_back(Color(.5,.5,0));
   9.143 +        colors.push_back(Color(.5,0,.5));
   9.144 +        colors.push_back(Color(0,.5,.5));
   9.145 +      
   9.146 +        colors.push_back(Color(.5,.5,.5));
   9.147 +        colors.push_back(Color(1,.5,.5));
   9.148 +        colors.push_back(Color(.5,1,.5));
   9.149 +        colors.push_back(Color(.5,.5,1));
   9.150 +        colors.push_back(Color(1,1,.5));
   9.151 +        colors.push_back(Color(1,.5,1));
   9.152 +        colors.push_back(Color(.5,1,1));
   9.153 +      
   9.154 +        colors.push_back(Color(1,.5,0));
   9.155 +        colors.push_back(Color(.5,1,0));
   9.156 +        colors.push_back(Color(1,0,.5));
   9.157 +        colors.push_back(Color(0,1,.5));
   9.158 +        colors.push_back(Color(0,.5,1));
   9.159 +        colors.push_back(Color(.5,0,1));
   9.160 +      } while(int(colors.size())<num);
   9.161 +      //    colors.push_back(Color(1,1,1));
   9.162 +      if(num>=0) colors.resize(num);
   9.163 +    }
   9.164 +    ///\e
   9.165 +    Color &operator[](int i)
   9.166 +    {
   9.167 +      return colors[i%colors.size()];
   9.168 +    }
   9.169 +    ///\e
   9.170 +    const Color &operator[](int i) const
   9.171 +    {
   9.172 +      return colors[i%colors.size()];
   9.173 +    }
   9.174 +    ///\e
   9.175 +    void set(int i,const Color &c)
   9.176 +    {
   9.177 +      colors[i%colors.size()]=c;
   9.178 +    }
   9.179 +    ///\e
   9.180 +    void add(const Color &c) 
   9.181 +    {
   9.182 +      colors.push_back(c);
   9.183 +    }
   9.184 +
   9.185 +    ///Sets the number of the exiting colors.
   9.186 +    void resize(int s) { colors.resize(s);}
   9.187 +    ///Returns the number of the existing colors.
   9.188 +    int size() const { return int(colors.size());}
   9.189 +  };
   9.190 +
   9.191 +  ///Returns a visible distinct \ref Color
   9.192 +
   9.193 +  ///Returns a \ref Color which is as different from the given parameter
   9.194 +  ///as it is possible.
   9.195 +  inline Color distantColor(const Color &c) 
   9.196 +  {
   9.197 +    return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0);
   9.198 +  }
   9.199 +  ///Returns black for light colors and white for the dark ones.
   9.200 +
   9.201 +  ///Returns black for light colors and white for the dark ones.
   9.202 +  inline Color distantBW(const Color &c){
   9.203 +    return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK;
   9.204 +  }
   9.205 +
   9.206 +  /// @}
   9.207 +
   9.208 +} //END OF NAMESPACE LEMON
   9.209 +
   9.210 +#endif // LEMON_COLOR_H
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/lemon/graph_to_eps.h	Thu Apr 03 11:10:49 2008 +0100
    10.3 @@ -0,0 +1,1170 @@
    10.4 +/* -*- C++ -*-
    10.5 + *
    10.6 + * This file is a part of LEMON, a generic C++ optimization library
    10.7 + *
    10.8 + * Copyright (C) 2003-2008
    10.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
   10.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
   10.11 + *
   10.12 + * Permission to use, modify and distribute this software is granted
   10.13 + * provided that this copyright notice appears in all copies. For
   10.14 + * precise terms see the accompanying LICENSE file.
   10.15 + *
   10.16 + * This software is provided "AS IS" with no warranty of any kind,
   10.17 + * express or implied, and with no claim as to its suitability for any
   10.18 + * purpose.
   10.19 + *
   10.20 + */
   10.21 +
   10.22 +#ifndef LEMON_GRAPH_TO_EPS_H
   10.23 +#define LEMON_GRAPH_TO_EPS_H
   10.24 +
   10.25 +#include <sys/time.h>
   10.26 +
   10.27 +#ifdef WIN32
   10.28 +#include <lemon/bits/mingw32_time.h>
   10.29 +#endif
   10.30 +
   10.31 +#include<iostream>
   10.32 +#include<fstream>
   10.33 +#include<sstream>
   10.34 +#include<algorithm>
   10.35 +#include<vector>
   10.36 +
   10.37 +#include<ctime>
   10.38 +
   10.39 +#include<lemon/math.h>
   10.40 +#include<lemon/bits/invalid.h>
   10.41 +#include<lemon/dim2.h>
   10.42 +#include<lemon/maps.h>
   10.43 +#include<lemon/color.h>
   10.44 +#include<lemon/bits/bezier.h>
   10.45 +
   10.46 +
   10.47 +///\ingroup eps_io
   10.48 +///\file
   10.49 +///\brief Simple graph drawer
   10.50 +///
   10.51 +///\author Alpar Juttner
   10.52 +
   10.53 +namespace lemon {
   10.54 +
   10.55 +template<class MT>
   10.56 +class _NegY {
   10.57 +public:
   10.58 +  typedef typename MT::Key Key;
   10.59 +  typedef typename MT::Value Value;
   10.60 +  const MT &map;
   10.61 +  int yscale;
   10.62 +  _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
   10.63 +  Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
   10.64 +};
   10.65 +
   10.66 +///Default traits class of \ref GraphToEps
   10.67 +
   10.68 +///Default traits class of \ref GraphToEps
   10.69 +///
   10.70 +///\c G is the type of the underlying graph.
   10.71 +template<class G>
   10.72 +struct DefaultGraphToEpsTraits
   10.73 +{
   10.74 +  typedef G Graph;
   10.75 +  typedef typename Graph::Node Node;
   10.76 +  typedef typename Graph::NodeIt NodeIt;
   10.77 +  typedef typename Graph::Arc Arc;
   10.78 +  typedef typename Graph::ArcIt ArcIt;
   10.79 +  typedef typename Graph::InArcIt InArcIt;
   10.80 +  typedef typename Graph::OutArcIt OutArcIt;
   10.81 +  
   10.82 +
   10.83 +  const Graph &g;
   10.84 +
   10.85 +  std::ostream& os;
   10.86 +  
   10.87 +  typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
   10.88 +  CoordsMapType _coords;
   10.89 +  ConstMap<typename Graph::Node,double > _nodeSizes;
   10.90 +  ConstMap<typename Graph::Node,int > _nodeShapes;
   10.91 +
   10.92 +  ConstMap<typename Graph::Node,Color > _nodeColors;
   10.93 +  ConstMap<typename Graph::Arc,Color > _arcColors;
   10.94 +
   10.95 +  ConstMap<typename Graph::Arc,double > _arcWidths;
   10.96 +
   10.97 +  double _arcWidthScale;
   10.98 +  
   10.99 +  double _nodeScale;
  10.100 +  double _xBorder, _yBorder;
  10.101 +  double _scale;
  10.102 +  double _nodeBorderQuotient;
  10.103 +  
  10.104 +  bool _drawArrows;
  10.105 +  double _arrowLength, _arrowWidth;
  10.106 +  
  10.107 +  bool _showNodes, _showArcs;
  10.108 +
  10.109 +  bool _enableParallel;
  10.110 +  double _parArcDist;
  10.111 +
  10.112 +  bool _showNodeText;
  10.113 +  ConstMap<typename Graph::Node,bool > _nodeTexts;  
  10.114 +  double _nodeTextSize;
  10.115 +
  10.116 +  bool _showNodePsText;
  10.117 +  ConstMap<typename Graph::Node,bool > _nodePsTexts;  
  10.118 +  char *_nodePsTextsPreamble;
  10.119 +  
  10.120 +  bool _undirected;
  10.121 +
  10.122 +  bool _pleaseRemoveOsStream;
  10.123 +
  10.124 +  bool _scaleToA4;
  10.125 +
  10.126 +  std::string _title;
  10.127 +  std::string _copyright;
  10.128 +
  10.129 +  enum NodeTextColorType 
  10.130 +    { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
  10.131 +  ConstMap<typename Graph::Node,Color > _nodeTextColors;
  10.132 +
  10.133 +  bool _autoNodeScale;
  10.134 +  bool _autoArcWidthScale;
  10.135 +
  10.136 +  bool _absoluteNodeSizes;
  10.137 +  bool _absoluteArcWidths;
  10.138 +
  10.139 +  bool _negY;
  10.140 +
  10.141 +  bool _preScale;
  10.142 +  ///Constructor
  10.143 +
  10.144 +  ///Constructor
  10.145 +  ///\param _g is a reference to the graph to be printed
  10.146 +  ///\param _os is a reference to the output stream.
  10.147 +  ///\param _os is a reference to the output stream.
  10.148 +  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
  10.149 +  ///will be explicitly deallocated by the destructor.
  10.150 +  ///By default it is <tt>std::cout</tt>
  10.151 +  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
  10.152 +			  bool _pros=false) :
  10.153 +    g(_g), os(_os),
  10.154 +    _coords(dim2::Point<double>(1,1)), _nodeSizes(.01), _nodeShapes(0),
  10.155 +    _nodeColors(WHITE), _arcColors(BLACK),
  10.156 +    _arcWidths(1.0), _arcWidthScale(0.003),
  10.157 +    _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
  10.158 +    _nodeBorderQuotient(.1),
  10.159 +    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
  10.160 +    _showNodes(true), _showArcs(true),
  10.161 +    _enableParallel(false), _parArcDist(1),
  10.162 +    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
  10.163 +    _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
  10.164 +    _undirected(false),
  10.165 +    _pleaseRemoveOsStream(_pros), _scaleToA4(false),
  10.166 +    _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
  10.167 +    _autoNodeScale(false),
  10.168 +    _autoArcWidthScale(false),
  10.169 +    _absoluteNodeSizes(false),
  10.170 +    _absoluteArcWidths(false),
  10.171 +    _negY(false),
  10.172 +    _preScale(true)
  10.173 +  {}
  10.174 +};
  10.175 +
  10.176 +///Helper class to implement the named parameters of \ref graphToEps()
  10.177 +
  10.178 +///Helper class to implement the named parameters of \ref graphToEps()
  10.179 +///\todo Is 'helper class' a good name for this?
  10.180 +///
  10.181 +///\todo Follow PostScript's DSC.
  10.182 +/// Use own dictionary.
  10.183 +///\todo Useful new features.
  10.184 +/// - Linestyles: dotted, dashed etc.
  10.185 +/// - A second color and percent value for the lines.
  10.186 +template<class T> class GraphToEps : public T 
  10.187 +{
  10.188 +  // Can't believe it is required by the C++ standard
  10.189 +  using T::g;
  10.190 +  using T::os;
  10.191 +
  10.192 +  using T::_coords;
  10.193 +  using T::_nodeSizes;
  10.194 +  using T::_nodeShapes;
  10.195 +  using T::_nodeColors;
  10.196 +  using T::_arcColors;
  10.197 +  using T::_arcWidths;
  10.198 +
  10.199 +  using T::_arcWidthScale;
  10.200 +  using T::_nodeScale;
  10.201 +  using T::_xBorder;
  10.202 +  using T::_yBorder;
  10.203 +  using T::_scale;
  10.204 +  using T::_nodeBorderQuotient;
  10.205 +  
  10.206 +  using T::_drawArrows;
  10.207 +  using T::_arrowLength;
  10.208 +  using T::_arrowWidth;
  10.209 +  
  10.210 +  using T::_showNodes;
  10.211 +  using T::_showArcs;
  10.212 +
  10.213 +  using T::_enableParallel;
  10.214 +  using T::_parArcDist;
  10.215 +
  10.216 +  using T::_showNodeText;
  10.217 +  using T::_nodeTexts;  
  10.218 +  using T::_nodeTextSize;
  10.219 +
  10.220 +  using T::_showNodePsText;
  10.221 +  using T::_nodePsTexts;  
  10.222 +  using T::_nodePsTextsPreamble;
  10.223 +  
  10.224 +  using T::_undirected;
  10.225 +
  10.226 +  using T::_pleaseRemoveOsStream;
  10.227 +
  10.228 +  using T::_scaleToA4;
  10.229 +
  10.230 +  using T::_title;
  10.231 +  using T::_copyright;
  10.232 +
  10.233 +  using T::NodeTextColorType;
  10.234 +  using T::CUST_COL;
  10.235 +  using T::DIST_COL;
  10.236 +  using T::DIST_BW;
  10.237 +  using T::_nodeTextColorType;
  10.238 +  using T::_nodeTextColors;
  10.239 +
  10.240 +  using T::_autoNodeScale;
  10.241 +  using T::_autoArcWidthScale;
  10.242 +
  10.243 +  using T::_absoluteNodeSizes;
  10.244 +  using T::_absoluteArcWidths;
  10.245 +
  10.246 +
  10.247 +  using T::_negY;
  10.248 +  using T::_preScale;
  10.249 +
  10.250 +  // dradnats ++C eht yb deriuqer si ti eveileb t'naC
  10.251 +
  10.252 +  typedef typename T::Graph Graph;
  10.253 +  typedef typename Graph::Node Node;
  10.254 +  typedef typename Graph::NodeIt NodeIt;
  10.255 +  typedef typename Graph::Arc Arc;
  10.256 +  typedef typename Graph::ArcIt ArcIt;
  10.257 +  typedef typename Graph::InArcIt InArcIt;
  10.258 +  typedef typename Graph::OutArcIt OutArcIt;
  10.259 +
  10.260 +  static const int INTERPOL_PREC;
  10.261 +  static const double A4HEIGHT;
  10.262 +  static const double A4WIDTH;
  10.263 +  static const double A4BORDER;
  10.264 +
  10.265 +  bool dontPrint;
  10.266 +
  10.267 +public:
  10.268 +  ///Node shapes
  10.269 +
  10.270 +  ///Node shapes
  10.271 +  ///
  10.272 +  enum NodeShapes { 
  10.273 +    /// = 0
  10.274 +    ///\image html nodeshape_0.png
  10.275 +    ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
  10.276 +    CIRCLE=0, 
  10.277 +    /// = 1
  10.278 +    ///\image html nodeshape_1.png
  10.279 +    ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
  10.280 +    ///
  10.281 +    SQUARE=1, 
  10.282 +    /// = 2
  10.283 +    ///\image html nodeshape_2.png
  10.284 +    ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
  10.285 +    ///
  10.286 +    DIAMOND=2,
  10.287 +    /// = 3
  10.288 +    ///\image html nodeshape_3.png
  10.289 +    ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
  10.290 +    ///
  10.291 +    MALE=3,
  10.292 +    /// = 4
  10.293 +    ///\image html nodeshape_4.png
  10.294 +    ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
  10.295 +    ///
  10.296 +    FEMALE=4
  10.297 +  };
  10.298 +
  10.299 +private:
  10.300 +  class arcLess {
  10.301 +    const Graph &g;
  10.302 +  public:
  10.303 +    arcLess(const Graph &_g) : g(_g) {}
  10.304 +    bool operator()(Arc a,Arc b) const 
  10.305 +    {
  10.306 +      Node ai=std::min(g.source(a),g.target(a));
  10.307 +      Node aa=std::max(g.source(a),g.target(a));
  10.308 +      Node bi=std::min(g.source(b),g.target(b));
  10.309 +      Node ba=std::max(g.source(b),g.target(b));
  10.310 +      return ai<bi ||
  10.311 +	(ai==bi && (aa < ba || 
  10.312 +		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
  10.313 +    }
  10.314 +  };
  10.315 +  bool isParallel(Arc e,Arc f) const
  10.316 +  {
  10.317 +    return (g.source(e)==g.source(f)&&
  10.318 +	    g.target(e)==g.target(f)) ||
  10.319 +      (g.source(e)==g.target(f)&&
  10.320 +       g.target(e)==g.source(f));
  10.321 +  }
  10.322 +  template<class TT>
  10.323 +  static std::string psOut(const dim2::Point<TT> &p) 
  10.324 +    {
  10.325 +      std::ostringstream os;	
  10.326 +      os << p.x << ' ' << p.y;
  10.327 +      return os.str();
  10.328 +    }
  10.329 +  static std::string psOut(const Color &c) 
  10.330 +    {
  10.331 +      std::ostringstream os;	
  10.332 +      os << c.red() << ' ' << c.green() << ' ' << c.blue();
  10.333 +      return os.str();
  10.334 +    }
  10.335 +  
  10.336 +public:
  10.337 +  GraphToEps(const T &t) : T(t), dontPrint(false) {};
  10.338 +  
  10.339 +  template<class X> struct CoordsTraits : public T {
  10.340 +  typedef X CoordsMapType;
  10.341 +    const X &_coords;
  10.342 +    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
  10.343 +  };
  10.344 +  ///Sets the map of the node coordinates
  10.345 +
  10.346 +  ///Sets the map of the node coordinates.
  10.347 +  ///\param x must be a node map with dim2::Point<double> or
  10.348 +  ///\ref dim2::Point "dim2::Point<int>" values. 
  10.349 +  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
  10.350 +    dontPrint=true;
  10.351 +    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
  10.352 +  }
  10.353 +  template<class X> struct NodeSizesTraits : public T {
  10.354 +    const X &_nodeSizes;
  10.355 +    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
  10.356 +  };
  10.357 +  ///Sets the map of the node sizes
  10.358 +
  10.359 +  ///Sets the map of the node sizes
  10.360 +  ///\param x must be a node map with \c double (or convertible) values. 
  10.361 +  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
  10.362 +  {
  10.363 +    dontPrint=true;
  10.364 +    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
  10.365 +  }
  10.366 +  template<class X> struct NodeShapesTraits : public T {
  10.367 +    const X &_nodeShapes;
  10.368 +    NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
  10.369 +  };
  10.370 +  ///Sets the map of the node shapes
  10.371 +
  10.372 +  ///Sets the map of the node shapes.
  10.373 +  ///The availabe shape values
  10.374 +  ///can be found in \ref NodeShapes "enum NodeShapes".
  10.375 +  ///\param x must be a node map with \c int (or convertible) values. 
  10.376 +  ///\sa NodeShapes
  10.377 +  template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
  10.378 +  {
  10.379 +    dontPrint=true;
  10.380 +    return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
  10.381 +  }
  10.382 +  template<class X> struct NodeTextsTraits : public T {
  10.383 +    const X &_nodeTexts;
  10.384 +    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
  10.385 +  };
  10.386 +  ///Sets the text printed on the nodes
  10.387 +
  10.388 +  ///Sets the text printed on the nodes
  10.389 +  ///\param x must be a node map with type that can be pushed to a standard
  10.390 +  ///ostream. 
  10.391 +  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
  10.392 +  {
  10.393 +    dontPrint=true;
  10.394 +    _showNodeText=true;
  10.395 +    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
  10.396 +  }
  10.397 +  template<class X> struct NodePsTextsTraits : public T {
  10.398 +    const X &_nodePsTexts;
  10.399 +    NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
  10.400 +  };
  10.401 +  ///Inserts a PostScript block to the nodes
  10.402 +
  10.403 +  ///With this command it is possible to insert a verbatim PostScript
  10.404 +  ///block to the nodes.
  10.405 +  ///The PS current point will be moved to the centre of the node before
  10.406 +  ///the PostScript block inserted.
  10.407 +  ///
  10.408 +  ///Before and after the block a newline character is inserted so you
  10.409 +  ///don't have to bother with the separators.
  10.410 +  ///
  10.411 +  ///\param x must be a node map with type that can be pushed to a standard
  10.412 +  ///ostream.
  10.413 +  ///
  10.414 +  ///\sa nodePsTextsPreamble()
  10.415 +  ///\todo Offer the choise not to move to the centre but pass the coordinates
  10.416 +  ///to the Postscript block inserted.
  10.417 +  template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
  10.418 +  {
  10.419 +    dontPrint=true;
  10.420 +    _showNodePsText=true;
  10.421 +    return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
  10.422 +  }
  10.423 +  template<class X> struct ArcWidthsTraits : public T {
  10.424 +    const X &_arcWidths;
  10.425 +    ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
  10.426 +  };
  10.427 +  ///Sets the map of the arc widths
  10.428 +
  10.429 +  ///Sets the map of the arc widths
  10.430 +  ///\param x must be a arc map with \c double (or convertible) values. 
  10.431 +  template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
  10.432 +  {
  10.433 +    dontPrint=true;
  10.434 +    return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
  10.435 +  }
  10.436 +
  10.437 +  template<class X> struct NodeColorsTraits : public T {
  10.438 +    const X &_nodeColors;
  10.439 +    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
  10.440 +  };
  10.441 +  ///Sets the map of the node colors
  10.442 +
  10.443 +  ///Sets the map of the node colors
  10.444 +  ///\param x must be a node map with \ref Color values.
  10.445 +  ///
  10.446 +  ///\sa Palette
  10.447 +  template<class X> GraphToEps<NodeColorsTraits<X> >
  10.448 +  nodeColors(const X &x)
  10.449 +  {
  10.450 +    dontPrint=true;
  10.451 +    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
  10.452 +  }
  10.453 +  template<class X> struct NodeTextColorsTraits : public T {
  10.454 +    const X &_nodeTextColors;
  10.455 +    NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
  10.456 +  };
  10.457 +  ///Sets the map of the node text colors
  10.458 +
  10.459 +  ///Sets the map of the node text colors
  10.460 +  ///\param x must be a node map with \ref Color values. 
  10.461 +  ///
  10.462 +  ///\sa Palette
  10.463 +  template<class X> GraphToEps<NodeTextColorsTraits<X> >
  10.464 +  nodeTextColors(const X &x)
  10.465 +  {
  10.466 +    dontPrint=true;
  10.467 +    _nodeTextColorType=CUST_COL;
  10.468 +    return GraphToEps<NodeTextColorsTraits<X> >
  10.469 +      (NodeTextColorsTraits<X>(*this,x));
  10.470 +  }
  10.471 +  template<class X> struct ArcColorsTraits : public T {
  10.472 +    const X &_arcColors;
  10.473 +    ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
  10.474 +  };
  10.475 +  ///Sets the map of the arc colors
  10.476 +
  10.477 +  ///Sets the map of the arc colors
  10.478 +  ///\param x must be a arc map with \ref Color values. 
  10.479 +  ///
  10.480 +  ///\sa Palette
  10.481 +  template<class X> GraphToEps<ArcColorsTraits<X> >
  10.482 +  arcColors(const X &x)
  10.483 +  {
  10.484 +    dontPrint=true;
  10.485 +    return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
  10.486 +  }
  10.487 +  ///Sets a global scale factor for node sizes
  10.488 +
  10.489 +  ///Sets a global scale factor for node sizes.
  10.490 +  /// 
  10.491 +  /// If nodeSizes() is not given, this function simply sets the node
  10.492 +  /// sizes to \c d.  If nodeSizes() is given, but
  10.493 +  /// autoNodeScale() is not, then the node size given by
  10.494 +  /// nodeSizes() will be multiplied by the value \c d.
  10.495 +  /// If both nodeSizes() and autoNodeScale() are used, then the
  10.496 +  /// node sizes will be scaled in such a way that the greatest size will be
  10.497 +  /// equal to \c d.
  10.498 +  /// \sa nodeSizes()
  10.499 +  /// \sa autoNodeScale()
  10.500 +  GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
  10.501 +  ///Turns on/off the automatic node width scaling.
  10.502 +
  10.503 +  ///Turns on/off the automatic node width scaling.
  10.504 +  ///
  10.505 +  ///\sa nodeScale()
  10.506 +  ///
  10.507 +  GraphToEps<T> &autoNodeScale(bool b=true) {
  10.508 +    _autoNodeScale=b;return *this;
  10.509 +  }
  10.510 +
  10.511 +  ///Turns on/off the absolutematic node width scaling.
  10.512 +
  10.513 +  ///Turns on/off the absolutematic node width scaling.
  10.514 +  ///
  10.515 +  ///\sa nodeScale()
  10.516 +  ///
  10.517 +  GraphToEps<T> &absoluteNodeSizes(bool b=true) {
  10.518 +    _absoluteNodeSizes=b;return *this;
  10.519 +  }
  10.520 +
  10.521 +  ///Negates the Y coordinates.
  10.522 +
  10.523 +  ///Negates the Y coordinates.
  10.524 +  ///
  10.525 +  ///\todo More docs.
  10.526 +  ///
  10.527 +  GraphToEps<T> &negateY(bool b=true) {
  10.528 +    _negY=b;return *this;
  10.529 +  }
  10.530 +
  10.531 +  ///Turn on/off prescaling
  10.532 +
  10.533 +  ///By default graphToEps() rescales the whole image in order to avoid
  10.534 +  ///very big or very small bounding boxes.
  10.535 +  ///
  10.536 +  ///This (p)rescaling can be turned off with this function.
  10.537 +  ///
  10.538 +  GraphToEps<T> &preScale(bool b=true) {
  10.539 +    _preScale=b;return *this;
  10.540 +  }
  10.541 +
  10.542 +  ///Sets a global scale factor for arc widths
  10.543 +
  10.544 +  /// Sets a global scale factor for arc widths.
  10.545 +  ///
  10.546 +  /// If arcWidths() is not given, this function simply sets the arc
  10.547 +  /// widths to \c d.  If arcWidths() is given, but
  10.548 +  /// autoArcWidthScale() is not, then the arc withs given by
  10.549 +  /// arcWidths() will be multiplied by the value \c d.
  10.550 +  /// If both arcWidths() and autoArcWidthScale() are used, then the
  10.551 +  /// arc withs will be scaled in such a way that the greatest width will be
  10.552 +  /// equal to \c d.
  10.553 +  GraphToEps<T> &arcWidthScale(double d) {_arcWidthScale=d;return *this;}
  10.554 +  ///Turns on/off the automatic arc width scaling.
  10.555 +
  10.556 +  ///Turns on/off the automatic arc width scaling.
  10.557 +  ///
  10.558 +  ///\sa arcWidthScale()
  10.559 +  ///
  10.560 +  GraphToEps<T> &autoArcWidthScale(bool b=true) {
  10.561 +    _autoArcWidthScale=b;return *this;
  10.562 +  }
  10.563 +  ///Turns on/off the absolutematic arc width scaling.
  10.564 +
  10.565 +  ///Turns on/off the absolutematic arc width scaling.
  10.566 +  ///
  10.567 +  ///\sa arcWidthScale()
  10.568 +  ///
  10.569 +  GraphToEps<T> &absoluteArcWidths(bool b=true) {
  10.570 +    _absoluteArcWidths=b;return *this;
  10.571 +  }
  10.572 +  ///Sets a global scale factor for the whole picture
  10.573 +
  10.574 +  ///Sets a global scale factor for the whole picture
  10.575 +  ///
  10.576 +
  10.577 +  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
  10.578 +  ///Sets the width of the border around the picture
  10.579 +
  10.580 +  ///Sets the width of the border around the picture
  10.581 +  ///
  10.582 +  GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
  10.583 +  ///Sets the width of the border around the picture
  10.584 +
  10.585 +  ///Sets the width of the border around the picture
  10.586 +  ///
  10.587 +  GraphToEps<T> &border(double x, double y) {
  10.588 +    _xBorder=x;_yBorder=y;return *this;
  10.589 +  }
  10.590 +  ///Sets whether to draw arrows
  10.591 +
  10.592 +  ///Sets whether to draw arrows
  10.593 +  ///
  10.594 +  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
  10.595 +  ///Sets the length of the arrowheads
  10.596 +
  10.597 +  ///Sets the length of the arrowheads
  10.598 +  ///
  10.599 +  GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
  10.600 +  ///Sets the width of the arrowheads
  10.601 +
  10.602 +  ///Sets the width of the arrowheads
  10.603 +  ///
  10.604 +  GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
  10.605 +  
  10.606 +  ///Scales the drawing to fit to A4 page
  10.607 +
  10.608 +  ///Scales the drawing to fit to A4 page
  10.609 +  ///
  10.610 +  GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
  10.611 +  
  10.612 +  ///Enables parallel arcs
  10.613 +
  10.614 +  ///Enables parallel arcs
  10.615 +  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
  10.616 +  
  10.617 +  ///Sets the distance 
  10.618 +  
  10.619 +  ///Sets the distance 
  10.620 +  ///
  10.621 +  GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
  10.622 +  
  10.623 +  ///Hides the arcs
  10.624 +  
  10.625 +  ///Hides the arcs
  10.626 +  ///
  10.627 +  GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
  10.628 +  ///Hides the nodes
  10.629 +  
  10.630 +  ///Hides the nodes
  10.631 +  ///
  10.632 +  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
  10.633 +  
  10.634 +  ///Sets the size of the node texts
  10.635 +  
  10.636 +  ///Sets the size of the node texts
  10.637 +  ///
  10.638 +  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
  10.639 +
  10.640 +  ///Sets the color of the node texts to be different from the node color
  10.641 +
  10.642 +  ///Sets the color of the node texts to be as different from the node color
  10.643 +  ///as it is possible
  10.644 +  ///
  10.645 +  GraphToEps<T> &distantColorNodeTexts()
  10.646 +  {_nodeTextColorType=DIST_COL;return *this;}
  10.647 +  ///Sets the color of the node texts to be black or white and always visible.
  10.648 +
  10.649 +  ///Sets the color of the node texts to be black or white according to
  10.650 +  ///which is more 
  10.651 +  ///different from the node color
  10.652 +  ///
  10.653 +  GraphToEps<T> &distantBWNodeTexts()
  10.654 +  {_nodeTextColorType=DIST_BW;return *this;}
  10.655 +
  10.656 +  ///Gives a preamble block for node Postscript block.
  10.657 +  
  10.658 +  ///Gives a preamble block for node Postscript block.
  10.659 +  ///
  10.660 +  ///\sa nodePsTexts()
  10.661 +  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
  10.662 +    _nodePsTextsPreamble=str ;return *this;
  10.663 +  }
  10.664 +  ///Sets whether the the graph is undirected
  10.665 +
  10.666 +  ///Sets whether the the graph is undirected
  10.667 +  ///
  10.668 +  GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
  10.669 +
  10.670 +  ///Sets whether the the graph is directed
  10.671 +
  10.672 +  ///Sets whether the the graph is directed.
  10.673 +  ///Use it to show the edges as a pair of directed ones.
  10.674 +  GraphToEps<T> &bidir(bool b=true) {_undirected=!b;return *this;}
  10.675 +
  10.676 +  ///Sets the title.
  10.677 +
  10.678 +  ///Sets the title of the generated image,
  10.679 +  ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
  10.680 +  ///the EPS file.
  10.681 +  GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
  10.682 +  ///Sets the copyright statement.
  10.683 +
  10.684 +  ///Sets the copyright statement of the generated image,
  10.685 +  ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
  10.686 +  ///the EPS file.
  10.687 +  ///\todo Multiline copyright notice could be supported.
  10.688 +  GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
  10.689 +
  10.690 +protected:
  10.691 +  bool isInsideNode(dim2::Point<double> p, double r,int t) 
  10.692 +  {
  10.693 +    switch(t) {
  10.694 +    case CIRCLE:
  10.695 +    case MALE:
  10.696 +    case FEMALE:
  10.697 +      return p.normSquare()<=r*r;
  10.698 +    case SQUARE:
  10.699 +      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
  10.700 +    case DIAMOND:
  10.701 +      return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
  10.702 +    }
  10.703 +    return false;
  10.704 +  }
  10.705 +
  10.706 +public:
  10.707 +  ~GraphToEps() { }
  10.708 +  
  10.709 +  ///Draws the graph.
  10.710 +
  10.711 +  ///Like other functions using
  10.712 +  ///\ref named-templ-func-param "named template parameters",
  10.713 +  ///this function calles the algorithm itself, i.e. in this case
  10.714 +  ///it draws the graph.
  10.715 +  void run() {
  10.716 +    ///\todo better 'epsilon' would be nice here.
  10.717 +    const double EPSILON=1e-9;
  10.718 +    if(dontPrint) return;
  10.719 +    
  10.720 +    _NegY<typename T::CoordsMapType> mycoords(_coords,_negY);
  10.721 +
  10.722 +    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
  10.723 +    if(_title.size()>0) os << "%%Title: " << _title << '\n';
  10.724 +     if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
  10.725 +//        << "%%Copyright: XXXX\n"
  10.726 +    os << "%%Creator: LEMON, graphToEps()\n";
  10.727 +    
  10.728 +    {
  10.729 +      char cbuf[50];
  10.730 +      timeval tv;
  10.731 +      gettimeofday(&tv, 0);
  10.732 +      ctime_r(&tv.tv_sec,cbuf);
  10.733 +      os << "%%CreationDate: " << cbuf;
  10.734 +    }
  10.735 +
  10.736 +    if (_autoArcWidthScale) {
  10.737 +      double max_w=0;
  10.738 +      for(ArcIt e(g);e!=INVALID;++e)
  10.739 +	max_w=std::max(double(_arcWidths[e]),max_w);
  10.740 +      ///\todo better 'epsilon' would be nice here.
  10.741 +      if(max_w>EPSILON) {
  10.742 +	_arcWidthScale/=max_w;
  10.743 +      }
  10.744 +    }
  10.745 +
  10.746 +    if (_autoNodeScale) {
  10.747 +      double max_s=0;
  10.748 +      for(NodeIt n(g);n!=INVALID;++n)
  10.749 +	max_s=std::max(double(_nodeSizes[n]),max_s);
  10.750 +      ///\todo better 'epsilon' would be nice here.
  10.751 +      if(max_s>EPSILON) {
  10.752 +	_nodeScale/=max_s;
  10.753 +      }
  10.754 +    }
  10.755 +
  10.756 +    double diag_len = 1;
  10.757 +    if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
  10.758 +      dim2::BoundingBox<double> bb;
  10.759 +      for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
  10.760 +      if (bb.empty()) {
  10.761 +	bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
  10.762 +      }
  10.763 +      diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
  10.764 +      if(diag_len<EPSILON) diag_len = 1;
  10.765 +      if(!_absoluteNodeSizes) _nodeScale*=diag_len;
  10.766 +      if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
  10.767 +    }
  10.768 +    
  10.769 +    dim2::BoundingBox<double> bb;
  10.770 +    for(NodeIt n(g);n!=INVALID;++n) {
  10.771 +      double ns=_nodeSizes[n]*_nodeScale;
  10.772 +      dim2::Point<double> p(ns,ns);
  10.773 +      switch(_nodeShapes[n]) {
  10.774 +      case CIRCLE:
  10.775 +      case SQUARE:
  10.776 +      case DIAMOND:
  10.777 +	bb.add(p+mycoords[n]);
  10.778 +	bb.add(-p+mycoords[n]);
  10.779 +	break;
  10.780 +      case MALE:
  10.781 +	bb.add(-p+mycoords[n]);
  10.782 +	bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
  10.783 +	break;
  10.784 +      case FEMALE:
  10.785 +	bb.add(p+mycoords[n]);
  10.786 +	bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
  10.787 +	break;
  10.788 +      }
  10.789 +    }
  10.790 +    if (bb.empty()) {
  10.791 +      bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
  10.792 +    }
  10.793 +    
  10.794 +    if(_scaleToA4)
  10.795 +      os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
  10.796 +    else {
  10.797 +      if(_preScale) {
  10.798 +	//Rescale so that BoundingBox won't be neither to big nor too small.
  10.799 +	while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
  10.800 +	while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
  10.801 +      }
  10.802 +      
  10.803 +      os << "%%BoundingBox: "
  10.804 +	 << int(floor(bb.left()   * _scale - _xBorder)) << ' '
  10.805 +	 << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
  10.806 +	 << int(ceil(bb.right()  * _scale + _xBorder)) << ' '
  10.807 +	 << int(ceil(bb.top()    * _scale + _yBorder)) << '\n';
  10.808 +    }
  10.809 +    
  10.810 +    os << "%%EndComments\n";
  10.811 +    
  10.812 +    //x1 y1 x2 y2 x3 y3 cr cg cb w
  10.813 +    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
  10.814 +       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
  10.815 +    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
  10.816 +    //x y r
  10.817 +    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
  10.818 +    //x y r
  10.819 +    os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
  10.820 +       << "      2 index 1 index sub 2 index 2 index add lineto\n"
  10.821 +       << "      2 index 1 index sub 2 index 2 index sub lineto\n"
  10.822 +       << "      2 index 1 index add 2 index 2 index sub lineto\n"
  10.823 +       << "      closepath pop pop pop} bind def\n";
  10.824 +    //x y r
  10.825 +    os << "/di { newpath 2 index 1 index add 2 index moveto\n"
  10.826 +       << "      2 index             2 index 2 index add lineto\n"
  10.827 +       << "      2 index 1 index sub 2 index             lineto\n"
  10.828 +       << "      2 index             2 index 2 index sub lineto\n"
  10.829 +       << "      closepath pop pop pop} bind def\n";
  10.830 +    // x y r cr cg cb
  10.831 +    os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
  10.832 +       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
  10.833 +       << "   } bind def\n";
  10.834 +    os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
  10.835 +       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
  10.836 +       << "   } bind def\n";
  10.837 +    os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
  10.838 +       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
  10.839 +       << "   } bind def\n";
  10.840 +    os << "/nfemale { 0 0 0 setrgbcolor 3 index "
  10.841 +       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
  10.842 +       << " 1.5 mul mul setlinewidth\n"
  10.843 +       << "  newpath 5 index 5 index moveto "
  10.844 +       << "5 index 5 index 5 index 3.01 mul sub\n"
  10.845 +       << "  lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto\n"
  10.846 +       << "  5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke\n"
  10.847 +       << "  5 index 5 index 5 index c fill\n"
  10.848 +       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
  10.849 +       << "  } bind def\n";
  10.850 +    os << "/nmale {\n"
  10.851 +       << "  0 0 0 setrgbcolor 3 index "
  10.852 +       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
  10.853 +       <<" 1.5 mul mul setlinewidth\n"
  10.854 +       << "  newpath 5 index 5 index moveto\n"
  10.855 +       << "  5 index 4 index 1 mul 1.5 mul add\n"
  10.856 +       << "  5 index 5 index 3 sqrt 1.5 mul mul add\n"
  10.857 +       << "  1 index 1 index lineto\n"
  10.858 +       << "  1 index 1 index 7 index sub moveto\n"
  10.859 +       << "  1 index 1 index lineto\n"
  10.860 +       << "  exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto\n"
  10.861 +       << "  stroke\n"
  10.862 +       << "  5 index 5 index 5 index c fill\n"
  10.863 +       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
  10.864 +       << "  } bind def\n";
  10.865 +    
  10.866 +
  10.867 +    os << "/arrl " << _arrowLength << " def\n";
  10.868 +    os << "/arrw " << _arrowWidth << " def\n";
  10.869 +    // l dx_norm dy_norm
  10.870 +    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
  10.871 +    //len w dx_norm dy_norm x1 y1 cr cg cb
  10.872 +    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
  10.873 +       << "       /w exch def /len exch def\n"
  10.874 +      //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
  10.875 +       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
  10.876 +       << "       len w sub arrl sub dx dy lrl\n"
  10.877 +       << "       arrw dy dx neg lrl\n"
  10.878 +       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
  10.879 +       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
  10.880 +       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
  10.881 +       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
  10.882 +       << "       arrw dy dx neg lrl\n"
  10.883 +       << "       len w sub arrl sub neg dx dy lrl\n"
  10.884 +       << "       closepath fill } bind def\n";
  10.885 +    os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
  10.886 +       << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
  10.887 +
  10.888 +    os << "\ngsave\n";
  10.889 +    if(_scaleToA4)
  10.890 +      if(bb.height()>bb.width()) {
  10.891 +	double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
  10.892 +		  (A4WIDTH-2*A4BORDER)/bb.width());
  10.893 +	os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
  10.894 +	   << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
  10.895 +	   << " translate\n"
  10.896 +	   << sc << " dup scale\n"
  10.897 +	   << -bb.left() << ' ' << -bb.bottom() << " translate\n";
  10.898 +      }
  10.899 +      else {
  10.900 +	//\todo Verify centering
  10.901 +	double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
  10.902 +		  (A4WIDTH-2*A4BORDER)/bb.height());
  10.903 +	os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
  10.904 +	   << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER 
  10.905 +	   << " translate\n"
  10.906 +	   << sc << " dup scale\n90 rotate\n"
  10.907 +	   << -bb.left() << ' ' << -bb.top() << " translate\n";	
  10.908 +	}
  10.909 +    else if(_scale!=1.0) os << _scale << " dup scale\n";
  10.910 +    
  10.911 +    if(_showArcs) {
  10.912 +      os << "%Arcs:\ngsave\n";      
  10.913 +      if(_enableParallel) {
  10.914 +	std::vector<Arc> el;
  10.915 +	for(ArcIt e(g);e!=INVALID;++e)
  10.916 +	  if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
  10.917 +	     &&g.source(e)!=g.target(e))
  10.918 +	    el.push_back(e);
  10.919 +	std::sort(el.begin(),el.end(),arcLess(g));
  10.920 +	
  10.921 +	typename std::vector<Arc>::iterator j;
  10.922 +	for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
  10.923 +	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
  10.924 +
  10.925 +	  double sw=0;
  10.926 +	  for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
  10.927 +	    sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
  10.928 +	  sw-=_parArcDist;
  10.929 +	  sw/=-2.0;
  10.930 +	  dim2::Point<double>
  10.931 +	    dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
  10.932 +	  double l=std::sqrt(dvec.normSquare()); 
  10.933 +	  ///\todo better 'epsilon' would be nice here.
  10.934 +	  dim2::Point<double> d(dvec/std::max(l,EPSILON));
  10.935 + 	  dim2::Point<double> m;
  10.936 +// 	  m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
  10.937 +
  10.938 +//  	  m=dim2::Point<double>(mycoords[g.source(*i)])+
  10.939 +// 	    dvec*(double(_nodeSizes[g.source(*i)])/
  10.940 +// 	       (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
  10.941 +
  10.942 + 	  m=dim2::Point<double>(mycoords[g.source(*i)])+
  10.943 +	    d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
  10.944 +
  10.945 +	  for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
  10.946 +	    sw+=_arcWidths[*e]*_arcWidthScale/2.0;
  10.947 +	    dim2::Point<double> mm=m+rot90(d)*sw/.75;
  10.948 +	    if(_drawArrows) {
  10.949 +	      int node_shape;
  10.950 +	      dim2::Point<double> s=mycoords[g.source(*e)];
  10.951 +	      dim2::Point<double> t=mycoords[g.target(*e)];
  10.952 +	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
  10.953 +	      node_shape=_nodeShapes[g.target(*e)];
  10.954 +	      dim2::Bezier3 bez(s,mm,mm,t);
  10.955 +	      double t1=0,t2=1;
  10.956 +	      for(int ii=0;ii<INTERPOL_PREC;++ii)
  10.957 +		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
  10.958 +		else t1=(t1+t2)/2;
  10.959 +	      dim2::Point<double> apoint=bez((t1+t2)/2);
  10.960 +	      rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
  10.961 +	      rn*=rn;
  10.962 +	      t2=(t1+t2)/2;t1=0;
  10.963 +	      for(int ii=0;ii<INTERPOL_PREC;++ii)
  10.964 +		if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
  10.965 +		else t2=(t1+t2)/2;
  10.966 +	      dim2::Point<double> linend=bez((t1+t2)/2);	      
  10.967 +	      bez=bez.before((t1+t2)/2);
  10.968 +// 	      rn=_nodeSizes[g.source(*e)]*_nodeScale;
  10.969 +// 	      node_shape=_nodeShapes[g.source(*e)];
  10.970 +// 	      t1=0;t2=1;
  10.971 +// 	      for(int i=0;i<INTERPOL_PREC;++i)
  10.972 +// 		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
  10.973 +// 		else t2=(t1+t2)/2;
  10.974 +// 	      bez=bez.after((t1+t2)/2);
  10.975 +	      os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
  10.976 +		 << _arcColors[*e].red() << ' '
  10.977 +		 << _arcColors[*e].green() << ' '
  10.978 +		 << _arcColors[*e].blue() << " setrgbcolor newpath\n"
  10.979 +		 << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
  10.980 +		 << bez.p2.x << ' ' << bez.p2.y << ' '
  10.981 +		 << bez.p3.x << ' ' << bez.p3.y << ' '
  10.982 +		 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
  10.983 +	      dim2::Point<double> dd(rot90(linend-apoint));
  10.984 +	      dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
  10.985 +		std::sqrt(dd.normSquare());
  10.986 +	      os << "newpath " << psOut(apoint) << " moveto "
  10.987 +		 << psOut(linend+dd) << " lineto "
  10.988 +		 << psOut(linend-dd) << " lineto closepath fill\n";
  10.989 +	    }
  10.990 +	    else {
  10.991 +	      os << mycoords[g.source(*e)].x << ' '
  10.992 +		 << mycoords[g.source(*e)].y << ' '
  10.993 +		 << mm.x << ' ' << mm.y << ' '
  10.994 +		 << mycoords[g.target(*e)].x << ' '
  10.995 +		 << mycoords[g.target(*e)].y << ' '
  10.996 +		 << _arcColors[*e].red() << ' '
  10.997 +		 << _arcColors[*e].green() << ' '
  10.998 +		 << _arcColors[*e].blue() << ' '
  10.999 +		 << _arcWidths[*e]*_arcWidthScale << " lb\n";
 10.1000 +	    }
 10.1001 +	    sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
 10.1002 +	  }
 10.1003 +	}
 10.1004 +      }
 10.1005 +      else for(ArcIt e(g);e!=INVALID;++e)
 10.1006 +	if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
 10.1007 +	   &&g.source(e)!=g.target(e))
 10.1008 +	  if(_drawArrows) {
 10.1009 +	    dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
 10.1010 +	    double rn=_nodeSizes[g.target(e)]*_nodeScale;
 10.1011 +	    int node_shape=_nodeShapes[g.target(e)];
 10.1012 +	    double t1=0,t2=1;
 10.1013 +	    for(int i=0;i<INTERPOL_PREC;++i)
 10.1014 +	      if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
 10.1015 +	      else t2=(t1+t2)/2;
 10.1016 +	    double l=std::sqrt(d.normSquare());
 10.1017 +	    d/=l;
 10.1018 +	    
 10.1019 +	    os << l*(1-(t1+t2)/2) << ' '
 10.1020 +	       << _arcWidths[e]*_arcWidthScale << ' '
 10.1021 +	       << d.x << ' ' << d.y << ' '
 10.1022 +	       << mycoords[g.source(e)].x << ' '
 10.1023 +	       << mycoords[g.source(e)].y << ' '
 10.1024 +	       << _arcColors[e].red() << ' '
 10.1025 +	       << _arcColors[e].green() << ' '
 10.1026 +	       << _arcColors[e].blue() << " arr\n";
 10.1027 +	  }
 10.1028 +	  else os << mycoords[g.source(e)].x << ' '
 10.1029 +		  << mycoords[g.source(e)].y << ' '
 10.1030 +		  << mycoords[g.target(e)].x << ' '
 10.1031 +		  << mycoords[g.target(e)].y << ' '
 10.1032 +		  << _arcColors[e].red() << ' '
 10.1033 +		  << _arcColors[e].green() << ' '
 10.1034 +		  << _arcColors[e].blue() << ' '
 10.1035 +		  << _arcWidths[e]*_arcWidthScale << " l\n";
 10.1036 +      os << "grestore\n";
 10.1037 +    }
 10.1038 +    if(_showNodes) {
 10.1039 +      os << "%Nodes:\ngsave\n";
 10.1040 +      for(NodeIt n(g);n!=INVALID;++n) {
 10.1041 +	os << mycoords[n].x << ' ' << mycoords[n].y << ' '
 10.1042 +	   << _nodeSizes[n]*_nodeScale << ' '
 10.1043 +	   << _nodeColors[n].red() << ' '
 10.1044 +	   << _nodeColors[n].green() << ' '
 10.1045 +	   << _nodeColors[n].blue() << ' ';
 10.1046 +	switch(_nodeShapes[n]) {
 10.1047 +	case CIRCLE:
 10.1048 +	  os<< "nc";break;
 10.1049 +	case SQUARE:
 10.1050 +	  os<< "nsq";break;
 10.1051 +	case DIAMOND:
 10.1052 +	  os<< "ndi";break;
 10.1053 +	case MALE:
 10.1054 +	  os<< "nmale";break;
 10.1055 +	case FEMALE:
 10.1056 +	  os<< "nfemale";break;
 10.1057 +	}
 10.1058 +	os<<'\n';
 10.1059 +      }
 10.1060 +      os << "grestore\n";
 10.1061 +    }
 10.1062 +    if(_showNodeText) {
 10.1063 +      os << "%Node texts:\ngsave\n";
 10.1064 +      os << "/fosi " << _nodeTextSize << " def\n";
 10.1065 +      os << "(Helvetica) findfont fosi scalefont setfont\n";
 10.1066 +      for(NodeIt n(g);n!=INVALID;++n) {
 10.1067 +	switch(_nodeTextColorType) {
 10.1068 +	case DIST_COL:
 10.1069 +	  os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
 10.1070 +	  break;
 10.1071 +	case DIST_BW:
 10.1072 +	  os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
 10.1073 +	  break;
 10.1074 +	case CUST_COL:
 10.1075 +	  os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
 10.1076 +	  break;
 10.1077 +	default:
 10.1078 +	  os << "0 0 0 setrgbcolor\n";
 10.1079 +	}
 10.1080 +	os << mycoords[n].x << ' ' << mycoords[n].y
 10.1081 +	   << " (" << _nodeTexts[n] << ") cshow\n";
 10.1082 +      }
 10.1083 +      os << "grestore\n";
 10.1084 +    }
 10.1085 +    if(_showNodePsText) {
 10.1086 +      os << "%Node PS blocks:\ngsave\n";
 10.1087 +      for(NodeIt n(g);n!=INVALID;++n)
 10.1088 +	os << mycoords[n].x << ' ' << mycoords[n].y
 10.1089 +	   << " moveto\n" << _nodePsTexts[n] << "\n";
 10.1090 +      os << "grestore\n";
 10.1091 +    }
 10.1092 +    
 10.1093 +    os << "grestore\nshowpage\n";
 10.1094 +
 10.1095 +    //CleanUp:
 10.1096 +    if(_pleaseRemoveOsStream) {delete &os;}
 10.1097 +  } 
 10.1098 +};
 10.1099 +
 10.1100 +template<class T>
 10.1101 +const int GraphToEps<T>::INTERPOL_PREC = 20;
 10.1102 +template<class T>
 10.1103 +const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
 10.1104 +template<class T>
 10.1105 +const double GraphToEps<T>::A4WIDTH  = 595.275590551181;
 10.1106 +template<class T>
 10.1107 +const double GraphToEps<T>::A4BORDER = 15;
 10.1108 +
 10.1109 +
 10.1110 +///Generates an EPS file from a graph
 10.1111 +
 10.1112 +///\ingroup eps_io
 10.1113 +///Generates an EPS file from a graph.
 10.1114 +///\param g is a reference to the graph to be printed
 10.1115 +///\param os is a reference to the output stream.
 10.1116 +///By default it is <tt>std::cout</tt>
 10.1117 +///
 10.1118 +///This function also has a lot of
 10.1119 +///\ref named-templ-func-param "named parameters",
 10.1120 +///they are declared as the members of class \ref GraphToEps. The following
 10.1121 +///example shows how to use these parameters.
 10.1122 +///\code
 10.1123 +/// graphToEps(g,os).scale(10).coords(coords)
 10.1124 +///              .nodeScale(2).nodeSizes(sizes)
 10.1125 +///              .arcWidthScale(.4).run();
 10.1126 +///\endcode
 10.1127 +///\warning Don't forget to put the \ref GraphToEps::run() "run()"
 10.1128 +///to the end of the parameter list.
 10.1129 +///\sa GraphToEps
 10.1130 +///\sa graphToEps(G &g, const char *file_name)
 10.1131 +template<class G>
 10.1132 +GraphToEps<DefaultGraphToEpsTraits<G> > 
 10.1133 +graphToEps(G &g, std::ostream& os=std::cout)
 10.1134 +{
 10.1135 +  return 
 10.1136 +    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
 10.1137 +}
 10.1138 + 
 10.1139 +///Generates an EPS file from a graph
 10.1140 +
 10.1141 +///\ingroup eps_io
 10.1142 +///This function does the same as
 10.1143 +///\ref graphToEps(G &g,std::ostream& os)
 10.1144 +///but it writes its output into the file \c file_name
 10.1145 +///instead of a stream.
 10.1146 +///\sa graphToEps(G &g, std::ostream& os)
 10.1147 +template<class G>
 10.1148 +GraphToEps<DefaultGraphToEpsTraits<G> > 
 10.1149 +graphToEps(G &g,const char *file_name)
 10.1150 +{
 10.1151 +  return GraphToEps<DefaultGraphToEpsTraits<G> >
 10.1152 +    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
 10.1153 +}
 10.1154 +
 10.1155 +///Generates an EPS file from a graph
 10.1156 +
 10.1157 +///\ingroup eps_io
 10.1158 +///This function does the same as
 10.1159 +///\ref graphToEps(G &g,std::ostream& os)
 10.1160 +///but it writes its output into the file \c file_name
 10.1161 +///instead of a stream.
 10.1162 +///\sa graphToEps(G &g, std::ostream& os)
 10.1163 +template<class G>
 10.1164 +GraphToEps<DefaultGraphToEpsTraits<G> > 
 10.1165 +graphToEps(G &g,const std::string& file_name)
 10.1166 +{
 10.1167 +  return GraphToEps<DefaultGraphToEpsTraits<G> >
 10.1168 +    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true));
 10.1169 +}
 10.1170 +
 10.1171 +} //END OF NAMESPACE LEMON
 10.1172 +
 10.1173 +#endif // LEMON_GRAPH_TO_EPS_H