gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge with graph_to_eps.h & Co.
0 5 5
merge default
2 files changed with 1890 insertions and 2 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1
/* -*- C++ -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
/// \ingroup demos
20
/// \file
21
/// \brief Demo of the graph grawing function \ref graphToEps()
22
///
23
/// This demo program shows examples how to  use the function \ref
24
/// graphToEps(). It takes no input but simply creates  six
25
/// <tt>.eps</tt> files demonstrating the capability of \ref
26
/// graphToEps(), and showing how to draw directed/graphs,
27
/// how to handle parallel egdes, how to change the properties (like
28
/// color, shape, size, title etc.) of nodes and arcs individually
29
/// using appropriate \ref maps-page "graph maps".
30
///
31
/// \include graph_to_eps_demo.cc
32

	
33
#include <lemon/math.h>
34

	
35
#include<lemon/graph_to_eps.h>
36
#include<lemon/list_graph.h>
37
#include<lemon/graph_utils.h>
38

	
39
using namespace std;
40
using namespace lemon;
41

	
42
int main()
43
{
44
  Palette palette;
45
  Palette paletteW(true);
46

	
47
  ListDigraph g;
48
  typedef ListDigraph::Node Node;
49
  typedef ListDigraph::NodeIt NodeIt;
50
  typedef ListDigraph::Arc Arc;
51
  typedef dim2::Point<int> Point;
52
  
53
  Node n1=g.addNode();
54
  Node n2=g.addNode();
55
  Node n3=g.addNode();
56
  Node n4=g.addNode();
57
  Node n5=g.addNode();
58

	
59
  ListDigraph::NodeMap<Point> coords(g);
60
  ListDigraph::NodeMap<double> sizes(g);
61
  ListDigraph::NodeMap<int> colors(g);
62
  ListDigraph::NodeMap<int> shapes(g);
63
  ListDigraph::ArcMap<int> ecolors(g);
64
  ListDigraph::ArcMap<int> widths(g);
65
  
66
  coords[n1]=Point(50,50);  sizes[n1]=1; colors[n1]=1; shapes[n1]=0;
67
  coords[n2]=Point(50,70);  sizes[n2]=2; colors[n2]=2; shapes[n2]=2;
68
  coords[n3]=Point(70,70);  sizes[n3]=1; colors[n3]=3; shapes[n3]=0;
69
  coords[n4]=Point(70,50);  sizes[n4]=2; colors[n4]=4; shapes[n4]=1;
70
  coords[n5]=Point(85,60);  sizes[n5]=3; colors[n5]=5; shapes[n5]=2;
71
  
72
  Arc e;
73

	
74
  e=g.addArc(n1,n2); ecolors[e]=0; widths[e]=1;
75
  e=g.addArc(n2,n3); ecolors[e]=0; widths[e]=1;
76
  e=g.addArc(n3,n5); ecolors[e]=0; widths[e]=3;
77
  e=g.addArc(n5,n4); ecolors[e]=0; widths[e]=1;
78
  e=g.addArc(n4,n1); ecolors[e]=0; widths[e]=1;
79
  e=g.addArc(n2,n4); ecolors[e]=1; widths[e]=2;
80
  e=g.addArc(n3,n4); ecolors[e]=2; widths[e]=1;
81
  
82
  IdMap<ListDigraph,Node> id(g);
83

	
84
  cout << "Create 'graph_to_eps_demo_out_pure.eps'" << endl;
85
  graphToEps(g,"graph_to_eps_demo_out_pure.eps").
86
    //scale(10).
87
    coords(coords).
88
    title("Sample .eps figure").
89
    copyright("(C) 2003-2007 LEMON Project").
90
    run();
91

	
92
  cout << "Create 'graph_to_eps_demo_out.eps'" << endl;
93
  graphToEps(g,"graph_to_eps_demo_out.eps").
94
    //scale(10).
95
    coords(coords).
96
    title("Sample .eps figure").
97
    copyright("(C) 2003-2007 LEMON Project").
98
    absoluteNodeSizes().absoluteArcWidths().
99
    nodeScale(2).nodeSizes(sizes).
100
    nodeShapes(shapes).
101
    nodeColors(composeMap(palette,colors)).
102
    arcColors(composeMap(palette,ecolors)).
103
    arcWidthScale(.4).arcWidths(widths).
104
    nodeTexts(id).nodeTextSize(3).
105
    run();
106

	
107

	
108
  cout << "Create 'graph_to_eps_demo_out_arr.eps'" << endl;
109
  graphToEps(g,"graph_to_eps_demo_out_arr.eps").
110
    //scale(10).
111
    title("Sample .eps figure (with arrowheads)").
112
    copyright("(C) 2003-2007 LEMON Project").
113
    absoluteNodeSizes().absoluteArcWidths().
114
    nodeColors(composeMap(palette,colors)).
115
    coords(coords).
116
    nodeScale(2).nodeSizes(sizes).
117
    nodeShapes(shapes).
118
    arcColors(composeMap(palette,ecolors)).
119
    arcWidthScale(.4).arcWidths(widths).
120
    nodeTexts(id).nodeTextSize(3).
121
    drawArrows().arrowWidth(1).arrowLength(1).
122
    run();
123

	
124
  e=g.addArc(n1,n4); ecolors[e]=2; widths[e]=1;
125
  e=g.addArc(n4,n1); ecolors[e]=1; widths[e]=2;
126

	
127
  e=g.addArc(n1,n2); ecolors[e]=1; widths[e]=1;
128
  e=g.addArc(n1,n2); ecolors[e]=2; widths[e]=1;
129
  e=g.addArc(n1,n2); ecolors[e]=3; widths[e]=1;
130
  e=g.addArc(n1,n2); ecolors[e]=4; widths[e]=1;
131
  e=g.addArc(n1,n2); ecolors[e]=5; widths[e]=1;
132
  e=g.addArc(n1,n2); ecolors[e]=6; widths[e]=1;
133
  e=g.addArc(n1,n2); ecolors[e]=7; widths[e]=1;
134

	
135
  cout << "Create 'graph_to_eps_demo_out_par.eps'" << endl;
136
  graphToEps(g,"graph_to_eps_demo_out_par.eps").
137
    //scale(10).
138
    title("Sample .eps figure (parallel arcs)").
139
    copyright("(C) 2003-2007 LEMON Project").
140
    absoluteNodeSizes().absoluteArcWidths().
141
    nodeShapes(shapes).
142
    coords(coords).
143
    nodeScale(2).nodeSizes(sizes).
144
    nodeColors(composeMap(palette,colors)).
145
    arcColors(composeMap(palette,ecolors)).
146
    arcWidthScale(.4).arcWidths(widths).
147
    nodeTexts(id).nodeTextSize(3).
148
    enableParallel().parArcDist(1.5).
149
    run();
150
  
151
  cout << "Create 'graph_to_eps_demo_out_par_arr.eps'" << endl;
152
  graphToEps(g,"graph_to_eps_demo_out_par_arr.eps").
153
    //scale(10).
154
    title("Sample .eps figure (parallel arcs and arrowheads)").
155
    copyright("(C) 2003-2007 LEMON Project").
156
    absoluteNodeSizes().absoluteArcWidths().
157
    nodeScale(2).nodeSizes(sizes).
158
    coords(coords).
159
    nodeShapes(shapes).
160
    nodeColors(composeMap(palette,colors)).
161
    arcColors(composeMap(palette,ecolors)).
162
    arcWidthScale(.3).arcWidths(widths).
163
    nodeTexts(id).nodeTextSize(3).
164
    enableParallel().parArcDist(1).
165
    drawArrows().arrowWidth(1).arrowLength(1).
166
    run();
167

	
168
  cout << "Create 'graph_to_eps_demo_out_a4.eps'" << endl;
169
  graphToEps(g,"graph_to_eps_demo_out_a4.eps").scaleToA4().
170
    title("Sample .eps figure (fits to A4)").
171
    copyright("(C) 2003-2007 LEMON Project").
172
    absoluteNodeSizes().absoluteArcWidths().
173
    nodeScale(2).nodeSizes(sizes).
174
    coords(coords).
175
    nodeShapes(shapes).
176
    nodeColors(composeMap(palette,colors)).
177
    arcColors(composeMap(palette,ecolors)).
178
    arcWidthScale(.3).arcWidths(widths).
179
    nodeTexts(id).nodeTextSize(3).
180
    enableParallel().parArcDist(1).
181
    drawArrows().arrowWidth(1).arrowLength(1).
182
    run();
183

	
184
  ListDigraph h;
185
  ListDigraph::NodeMap<int> hcolors(h);
186
  ListDigraph::NodeMap<Point> hcoords(h);
187
  
188
  int cols=int(sqrt(double(palette.size())));
189
  for(int i=0;i<int(paletteW.size());i++) {
190
    Node n=h.addNode();
191
    hcoords[n]=Point(i%cols,i/cols);
192
    hcolors[n]=i;
193
  }
194
  
195
  cout << "Create 'graph_to_eps_demo_out_colors.eps'" << endl;
196
  graphToEps(h,"graph_to_eps_demo_out_colors.eps").
197
    //scale(60).
198
    title("Sample .eps figure (Palette demo)").
199
    copyright("(C) 2003-2007 LEMON Project").
200
    coords(hcoords).
201
    absoluteNodeSizes().absoluteArcWidths().
202
    nodeScale(.45).
203
    distantColorNodeTexts().
204
    //    distantBWNodeTexts().
205
    nodeTexts(hcolors).nodeTextSize(.6).
206
    nodeColors(composeMap(paletteW,hcolors)).
207
    run();
208
}
Ignore white space 6 line context
1
/* -*- C++ -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_BEZIER_H
20
#define LEMON_BEZIER_H
21

	
22
///\ingroup misc
23
///\file
24
///\brief Classes to compute with Bezier curves.
25
///
26
///Up to now this file is used internally by \ref graph_to_eps.h
27
///
28
///\author Alpar Juttner
29

	
30
#include<lemon/dim2.h>
31

	
32
namespace lemon {
33
  namespace dim2 {
34

	
35
class BezierBase {
36
public:
37
  typedef Point<double> Point;
38
protected:
39
  static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
40
};
41

	
42
class Bezier1 : public BezierBase
43
{
44
public:
45
  Point p1,p2;
46

	
47
  Bezier1() {}
48
  Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
49
  
50
  Point operator()(double t) const
51
  {
52
    //    return conv(conv(p1,p2,t),conv(p2,p3,t),t);
53
    return conv(p1,p2,t);
54
  }
55
  Bezier1 before(double t) const
56
  {
57
    return Bezier1(p1,conv(p1,p2,t));
58
  }
59
  
60
  Bezier1 after(double t) const
61
  {
62
    return Bezier1(conv(p1,p2,t),p2);
63
  }
64

	
65
  Bezier1 revert() const { return Bezier1(p2,p1);}
66
  Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
67
  Point grad() const { return p2-p1; }
68
  Point norm() const { return rot90(p2-p1); }
69
  Point grad(double) const { return grad(); }
70
  Point norm(double t) const { return rot90(grad(t)); }
71
};
72

	
73
class Bezier2 : public BezierBase
74
{
75
public:
76
  Point p1,p2,p3;
77

	
78
  Bezier2() {}
79
  Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
80
  Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
81
  Point operator()(double t) const
82
  {
83
    //    return conv(conv(p1,p2,t),conv(p2,p3,t),t);
84
    return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
85
  }
86
  Bezier2 before(double t) const
87
  {
88
    Point q(conv(p1,p2,t));
89
    Point r(conv(p2,p3,t));
90
    return Bezier2(p1,q,conv(q,r,t));
91
  }
92
  
93
  Bezier2 after(double t) const
94
  {
95
    Point q(conv(p1,p2,t));
96
    Point r(conv(p2,p3,t));
97
    return Bezier2(conv(q,r,t),r,p3);
98
  }
99
  Bezier2 revert() const { return Bezier2(p3,p2,p1);}
100
  Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
101
  Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
102
  Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
103
  Point grad(double t) const { return grad()(t); }
104
  Point norm(double t) const { return rot90(grad(t)); }
105
};
106

	
107
class Bezier3 : public BezierBase
108
{
109
public:
110
  Point p1,p2,p3,p4;
111

	
112
  Bezier3() {}
113
  Bezier3(Point _p1, Point _p2, Point _p3, Point _p4)
114
    : p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
115
  Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), 
116
			      p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
117
  Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
118
			      p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
119
  
120
  Point operator()(double t) const 
121
    {
122
      //    return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
123
      return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
124
	(3*t*t*(1-t))*p3+(t*t*t)*p4;
125
    }
126
  Bezier3 before(double t) const
127
    {
128
      Point p(conv(p1,p2,t));
129
      Point q(conv(p2,p3,t));
130
      Point r(conv(p3,p4,t));
131
      Point a(conv(p,q,t));
132
      Point b(conv(q,r,t));
133
      Point c(conv(a,b,t));
134
      return Bezier3(p1,p,a,c);
135
    }
136
  
137
  Bezier3 after(double t) const
138
    {
139
      Point p(conv(p1,p2,t));
140
      Point q(conv(p2,p3,t));
141
      Point r(conv(p3,p4,t));
142
      Point a(conv(p,q,t));
143
      Point b(conv(q,r,t));
144
      Point c(conv(a,b,t));
145
      return Bezier3(c,b,r,p4);
146
    }
147
  Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
148
  Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
149
  Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
150
  Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
151
				  3.0*rot90(p3-p2),
152
				  3.0*rot90(p4-p3)); }
153
  Point grad(double t) const { return grad()(t); }
154
  Point norm(double t) const { return rot90(grad(t)); }
155

	
156
  template<class R,class F,class S,class D>
157
  R recSplit(F &_f,const S &_s,D _d) const 
158
  {
159
    const Point a=(p1+p2)/2;
160
    const Point b=(p2+p3)/2;
161
    const Point c=(p3+p4)/2;
162
    const Point d=(a+b)/2;
163
    const Point e=(b+c)/2;
164
    const Point f=(d+e)/2;
165
    R f1=_f(Bezier3(p1,a,d,e),_d);
166
    R f2=_f(Bezier3(e,d,c,p4),_d);
167
    return _s(f1,f2);
168
  }
169
  
170
};
171

	
172

	
173
} //END OF NAMESPACE dim2
174
} //END OF NAMESPACE lemon
175

	
176
#endif // LEMON_BEZIER_H
Ignore white space 6 line context
1
/* -*- C++ -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
///\file
20
///\brief Color constants
21

	
22
#include<lemon/color.h>
23

	
24
namespace lemon {
25

	
26
  const Color WHITE(1,1,1);
27
  
28
  const Color BLACK(0,0,0);
29
  const Color RED(1,0,0);
30
  const Color GREEN(0,1,0);
31
  const Color BLUE(0,0,1);
32
  const Color YELLOW(1,1,0);
33
  const Color MAGENTA(1,0,1);
34
  const Color CYAN(0,1,1);
35

	
36
  const Color GREY(0,0,0);
37
  const Color DARK_RED(.5,0,0);
38
  const Color DARK_GREEN(0,.5,0);
39
  const Color DARK_BLUE(0,0,.5);
40
  const Color DARK_YELLOW(.5,.5,0);
41
  const Color DARK_MAGENTA(.5,0,.5);
42
  const Color DARK_CYAN(0,.5,.5);
43
    
44
} //namespace lemon
Ignore white space 6 line context
1
/* -*- C++ -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_COLOR_H
20
#define LEMON_COLOR_H
21

	
22
#include<vector>
23
#include<lemon/math.h>
24
#include<lemon/maps.h>
25

	
26

	
27
///\ingroup misc
28
///\file
29
///\brief Tools to manage RGB colors.
30
///
31
///\author Alpar Juttner
32

	
33
namespace lemon {
34

	
35

	
36
  /// \addtogroup misc
37
  /// @{
38

	
39
  ///Data structure representing RGB colors.
40

	
41
  ///Data structure representing RGB colors.
42
  class Color
43
  {
44
    double _r,_g,_b;
45
  public:
46
    ///Default constructor
47
    Color() {}
48
    ///Constructor
49
    Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
50
    ///Set the red component
51
    double & red() {return _r;}
52
    ///Return the red component
53
    const double & red() const {return _r;}
54
    ///Set the green component
55
    double & green() {return _g;}
56
    ///Return the green component
57
    const double & green() const {return _g;}
58
    ///Set the blue component
59
    double & blue() {return _b;}
60
    ///Return the blue component
61
    const double & blue() const {return _b;}
62
    ///Set the color components
63
    void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
64
  };
65

	
66
  /// White color constant
67
  extern const Color WHITE;  
68
  /// Black color constant
69
  extern const Color BLACK;
70
  /// Red color constant
71
  extern const Color RED;
72
  /// Green color constant
73
  extern const Color GREEN;
74
  /// Blue color constant
75
  extern const Color BLUE;
76
  /// Yellow color constant
77
  extern const Color YELLOW;
78
  /// Magenta color constant
79
  extern const Color MAGENTA;
80
  /// Cyan color constant
81
  extern const Color CYAN;
82
  /// Grey color constant
83
  extern const Color GREY;
84
  /// Dark red color constant
85
  extern const Color DARK_RED;
86
  /// Dark green color constant
87
  extern const Color DARK_GREEN;
88
  /// Drak blue color constant
89
  extern const Color DARK_BLUE;
90
  /// Dark yellow color constant
91
  extern const Color DARK_YELLOW;
92
  /// Dark magenta color constant
93
  extern const Color DARK_MAGENTA;
94
  /// Dark cyan color constant
95
  extern const Color DARK_CYAN;
96

	
97
  ///Map <tt>int</tt>s to different \ref Color "Color"s
98

	
99
  ///This map assigns one of the predefined \ref Color "Color"s to
100
  ///each <tt>int</tt>. It is possible to change the colors as well as
101
  ///their number. The integer range is cyclically mapped to the
102
  ///provided set of colors.
103
  ///
104
  ///This is a true \ref concepts::ReferenceMap "reference map", so
105
  ///you can also change the actual colors.
106

	
107
  class Palette : public MapBase<int,Color>
108
  {
109
    std::vector<Color> colors;
110
  public:
111
    ///Constructor
112

	
113
    ///Constructor 
114
    ///\param have_white indicates whether white is amongst the
115
    ///provided initial colors (\c true) or not (\c false). If it is true,
116
    ///white will be assigned to \c 0.
117
    ///\param num the number of the allocated colors. If it is \c -1,
118
    ///the default color configuration is set up (26 color plus optionaly the
119
    ///white).  If \c num is less then 26/27 then the default color
120
    ///list is cut. Otherwise the color list is filled repeatedly with
121
    ///the default color list.  (The colors can be changed later on.)
122
    Palette(bool have_white=false,int num=-1)
123
    {
124
      if (num==0) return;
125
      do {
126
        if(have_white) colors.push_back(Color(1,1,1));
127

	
128
        colors.push_back(Color(0,0,0));
129
        colors.push_back(Color(1,0,0));
130
        colors.push_back(Color(0,1,0));
131
        colors.push_back(Color(0,0,1));
132
        colors.push_back(Color(1,1,0));
133
        colors.push_back(Color(1,0,1));
134
        colors.push_back(Color(0,1,1));
135
      
136
        colors.push_back(Color(.5,0,0));
137
        colors.push_back(Color(0,.5,0));
138
        colors.push_back(Color(0,0,.5));
139
        colors.push_back(Color(.5,.5,0));
140
        colors.push_back(Color(.5,0,.5));
141
        colors.push_back(Color(0,.5,.5));
142
      
143
        colors.push_back(Color(.5,.5,.5));
144
        colors.push_back(Color(1,.5,.5));
145
        colors.push_back(Color(.5,1,.5));
146
        colors.push_back(Color(.5,.5,1));
147
        colors.push_back(Color(1,1,.5));
148
        colors.push_back(Color(1,.5,1));
149
        colors.push_back(Color(.5,1,1));
150
      
151
        colors.push_back(Color(1,.5,0));
152
        colors.push_back(Color(.5,1,0));
153
        colors.push_back(Color(1,0,.5));
154
        colors.push_back(Color(0,1,.5));
155
        colors.push_back(Color(0,.5,1));
156
        colors.push_back(Color(.5,0,1));
157
      } while(int(colors.size())<num);
158
      //    colors.push_back(Color(1,1,1));
159
      if(num>=0) colors.resize(num);
160
    }
161
    ///\e
162
    Color &operator[](int i)
163
    {
164
      return colors[i%colors.size()];
165
    }
166
    ///\e
167
    const Color &operator[](int i) const
168
    {
169
      return colors[i%colors.size()];
170
    }
171
    ///\e
172
    void set(int i,const Color &c)
173
    {
174
      colors[i%colors.size()]=c;
175
    }
176
    ///Add a new color to the end of the color list.
177
    void add(const Color &c) 
178
    {
179
      colors.push_back(c);
180
    }
181

	
182
    ///Sets the number of the exiting colors.
183
    void resize(int s) { colors.resize(s);}
184
    ///Returns the number of the existing colors.
185
    int size() const { return int(colors.size());}
186
  };
187

	
188
  ///Returns a visibly distinct \ref Color
189

	
190
  ///Returns a \ref Color which is as different from the given parameter
191
  ///as it is possible.
192
  inline Color distantColor(const Color &c) 
193
  {
194
    return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0);
195
  }
196
  ///Returns black for light colors and white for the dark ones.
197

	
198
  ///Returns black for light colors and white for the dark ones.
199
  inline Color distantBW(const Color &c){
200
    return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK;
201
  }
202

	
203
  /// @}
204

	
205
} //END OF NAMESPACE LEMON
206

	
207
#endif // LEMON_COLOR_H
Ignore white space 6 line context
1
/* -*- C++ -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_GRAPH_TO_EPS_H
20
#define LEMON_GRAPH_TO_EPS_H
21

	
22
#include<iostream>
23
#include<fstream>
24
#include<sstream>
25
#include<algorithm>
26
#include<vector>
27

	
28
#ifndef WIN32
29
#include<sys/time.h>
30
#include<ctime>
31
#else
32
#include<windows.h>
33
#endif
34

	
35
#include<lemon/math.h>
36
#include<lemon/bits/invalid.h>
37
#include<lemon/dim2.h>
38
#include<lemon/maps.h>
39
#include<lemon/color.h>
40
#include<lemon/bits/bezier.h>
41

	
42

	
43
///\ingroup eps_io
44
///\file
45
///\brief A well configurable tool for visualizing graphs
46

	
47
namespace lemon {
48

	
49
  namespace _graph_to_eps_bits {
50
    template<class MT>
51
    class _NegY {
52
    public:
53
      typedef typename MT::Key Key;
54
      typedef typename MT::Value Value;
55
      const MT &map;
56
      int yscale;
57
      _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
58
      Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
59
    };
60
  }
61
  
62
///Default traits class of \ref GraphToEps
63

	
64
///Default traits class of \ref GraphToEps
65
///
66
///\c G is the type of the underlying graph.
67
template<class G>
68
struct DefaultGraphToEpsTraits
69
{
70
  typedef G Graph;
71
  typedef typename Graph::Node Node;
72
  typedef typename Graph::NodeIt NodeIt;
73
  typedef typename Graph::Arc Arc;
74
  typedef typename Graph::ArcIt ArcIt;
75
  typedef typename Graph::InArcIt InArcIt;
76
  typedef typename Graph::OutArcIt OutArcIt;
77
  
78

	
79
  const Graph &g;
80

	
81
  std::ostream& os;
82
  
83
  typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
84
  CoordsMapType _coords;
85
  ConstMap<typename Graph::Node,double > _nodeSizes;
86
  ConstMap<typename Graph::Node,int > _nodeShapes;
87

	
88
  ConstMap<typename Graph::Node,Color > _nodeColors;
89
  ConstMap<typename Graph::Arc,Color > _arcColors;
90

	
91
  ConstMap<typename Graph::Arc,double > _arcWidths;
92

	
93
  double _arcWidthScale;
94
  
95
  double _nodeScale;
96
  double _xBorder, _yBorder;
97
  double _scale;
98
  double _nodeBorderQuotient;
99
  
100
  bool _drawArrows;
101
  double _arrowLength, _arrowWidth;
102
  
103
  bool _showNodes, _showArcs;
104

	
105
  bool _enableParallel;
106
  double _parArcDist;
107

	
108
  bool _showNodeText;
109
  ConstMap<typename Graph::Node,bool > _nodeTexts;  
110
  double _nodeTextSize;
111

	
112
  bool _showNodePsText;
113
  ConstMap<typename Graph::Node,bool > _nodePsTexts;  
114
  char *_nodePsTextsPreamble;
115
  
116
  bool _undirected;
117

	
118
  bool _pleaseRemoveOsStream;
119

	
120
  bool _scaleToA4;
121

	
122
  std::string _title;
123
  std::string _copyright;
124

	
125
  enum NodeTextColorType 
126
    { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
127
  ConstMap<typename Graph::Node,Color > _nodeTextColors;
128

	
129
  bool _autoNodeScale;
130
  bool _autoArcWidthScale;
131

	
132
  bool _absoluteNodeSizes;
133
  bool _absoluteArcWidths;
134

	
135
  bool _negY;
136

	
137
  bool _preScale;
138
  ///Constructor
139

	
140
  ///Constructor
141
  ///\param _g is a reference to the graph to be printed
142
  ///\param _os is a reference to the output stream.
143
  ///\param _os is a reference to the output stream.
144
  ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
145
  ///will be explicitly deallocated by the destructor.
146
  ///By default it is <tt>std::cout</tt>
147
  DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
148
			  bool _pros=false) :
149
    g(_g), os(_os),
150
    _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
151
    _nodeColors(WHITE), _arcColors(BLACK),
152
    _arcWidths(1.0), _arcWidthScale(0.003),
153
    _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
154
    _nodeBorderQuotient(.1),
155
    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
156
    _showNodes(true), _showArcs(true),
157
    _enableParallel(false), _parArcDist(1),
158
    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
159
    _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
160
    _undirected(lemon::UndirectedTagIndicator<G>::value),
161
    _pleaseRemoveOsStream(_pros), _scaleToA4(false),
162
    _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
163
    _autoNodeScale(false),
164
    _autoArcWidthScale(false),
165
    _absoluteNodeSizes(false),
166
    _absoluteArcWidths(false),
167
    _negY(false),
168
    _preScale(true)
169
  {}
170
};
171

	
172
///Auxiliary class to implement the named parameters of \ref graphToEps()
173

	
174
///Auxiliary class to implement the named parameters of \ref graphToEps()
175
template<class T> class GraphToEps : public T 
176
{
177
  // Can't believe it is required by the C++ standard
178
  using T::g;
179
  using T::os;
180

	
181
  using T::_coords;
182
  using T::_nodeSizes;
183
  using T::_nodeShapes;
184
  using T::_nodeColors;
185
  using T::_arcColors;
186
  using T::_arcWidths;
187

	
188
  using T::_arcWidthScale;
189
  using T::_nodeScale;
190
  using T::_xBorder;
191
  using T::_yBorder;
192
  using T::_scale;
193
  using T::_nodeBorderQuotient;
194
  
195
  using T::_drawArrows;
196
  using T::_arrowLength;
197
  using T::_arrowWidth;
198
  
199
  using T::_showNodes;
200
  using T::_showArcs;
201

	
202
  using T::_enableParallel;
203
  using T::_parArcDist;
204

	
205
  using T::_showNodeText;
206
  using T::_nodeTexts;  
207
  using T::_nodeTextSize;
208

	
209
  using T::_showNodePsText;
210
  using T::_nodePsTexts;  
211
  using T::_nodePsTextsPreamble;
212
  
213
  using T::_undirected;
214

	
215
  using T::_pleaseRemoveOsStream;
216

	
217
  using T::_scaleToA4;
218

	
219
  using T::_title;
220
  using T::_copyright;
221

	
222
  using T::NodeTextColorType;
223
  using T::CUST_COL;
224
  using T::DIST_COL;
225
  using T::DIST_BW;
226
  using T::_nodeTextColorType;
227
  using T::_nodeTextColors;
228

	
229
  using T::_autoNodeScale;
230
  using T::_autoArcWidthScale;
231

	
232
  using T::_absoluteNodeSizes;
233
  using T::_absoluteArcWidths;
234

	
235

	
236
  using T::_negY;
237
  using T::_preScale;
238

	
239
  // dradnats ++C eht yb deriuqer si ti eveileb t'naC
240

	
241
  typedef typename T::Graph Graph;
242
  typedef typename Graph::Node Node;
243
  typedef typename Graph::NodeIt NodeIt;
244
  typedef typename Graph::Arc Arc;
245
  typedef typename Graph::ArcIt ArcIt;
246
  typedef typename Graph::InArcIt InArcIt;
247
  typedef typename Graph::OutArcIt OutArcIt;
248

	
249
  static const int INTERPOL_PREC;
250
  static const double A4HEIGHT;
251
  static const double A4WIDTH;
252
  static const double A4BORDER;
253

	
254
  bool dontPrint;
255

	
256
public:
257
  ///Node shapes
258

	
259
  ///Node shapes
260
  ///
261
  enum NodeShapes { 
262
    /// = 0
263
    ///\image html nodeshape_0.png
264
    ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
265
    CIRCLE=0, 
266
    /// = 1
267
    ///\image html nodeshape_1.png
268
    ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
269
    ///
270
    SQUARE=1, 
271
    /// = 2
272
    ///\image html nodeshape_2.png
273
    ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
274
    ///
275
    DIAMOND=2,
276
    /// = 3
277
    ///\image html nodeshape_3.png
278
    ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
279
    ///
280
    MALE=3,
281
    /// = 4
282
    ///\image html nodeshape_4.png
283
    ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
284
    ///
285
    FEMALE=4
286
  };
287

	
288
private:
289
  class arcLess {
290
    const Graph &g;
291
  public:
292
    arcLess(const Graph &_g) : g(_g) {}
293
    bool operator()(Arc a,Arc b) const 
294
    {
295
      Node ai=std::min(g.source(a),g.target(a));
296
      Node aa=std::max(g.source(a),g.target(a));
297
      Node bi=std::min(g.source(b),g.target(b));
298
      Node ba=std::max(g.source(b),g.target(b));
299
      return ai<bi ||
300
	(ai==bi && (aa < ba || 
301
		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
302
    }
303
  };
304
  bool isParallel(Arc e,Arc f) const
305
  {
306
    return (g.source(e)==g.source(f)&&
307
	    g.target(e)==g.target(f)) ||
308
      (g.source(e)==g.target(f)&&
309
       g.target(e)==g.source(f));
310
  }
311
  template<class TT>
312
  static std::string psOut(const dim2::Point<TT> &p) 
313
    {
314
      std::ostringstream os;	
315
      os << p.x << ' ' << p.y;
316
      return os.str();
317
    }
318
  static std::string psOut(const Color &c) 
319
    {
320
      std::ostringstream os;	
321
      os << c.red() << ' ' << c.green() << ' ' << c.blue();
322
      return os.str();
323
    }
324
  
325
public:
326
  GraphToEps(const T &t) : T(t), dontPrint(false) {};
327
  
328
  template<class X> struct CoordsTraits : public T {
329
  typedef X CoordsMapType;
330
    const X &_coords;
331
    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
332
  };
333
  ///Sets the map of the node coordinates
334

	
335
  ///Sets the map of the node coordinates.
336
  ///\param x must be a node map with dim2::Point<double> or
337
  ///\ref dim2::Point "dim2::Point<int>" values. 
338
  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
339
    dontPrint=true;
340
    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
341
  }
342
  template<class X> struct NodeSizesTraits : public T {
343
    const X &_nodeSizes;
344
    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
345
  };
346
  ///Sets the map of the node sizes
347

	
348
  ///Sets the map of the node sizes
349
  ///\param x must be a node map with \c double (or convertible) values. 
350
  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
351
  {
352
    dontPrint=true;
353
    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
354
  }
355
  template<class X> struct NodeShapesTraits : public T {
356
    const X &_nodeShapes;
357
    NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
358
  };
359
  ///Sets the map of the node shapes
360

	
361
  ///Sets the map of the node shapes.
362
  ///The available shape values
363
  ///can be found in \ref NodeShapes "enum NodeShapes".
364
  ///\param x must be a node map with \c int (or convertible) values. 
365
  ///\sa NodeShapes
366
  template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
367
  {
368
    dontPrint=true;
369
    return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
370
  }
371
  template<class X> struct NodeTextsTraits : public T {
372
    const X &_nodeTexts;
373
    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
374
  };
375
  ///Sets the text printed on the nodes
376

	
377
  ///Sets the text printed on the nodes
378
  ///\param x must be a node map with type that can be pushed to a standard
379
  ///ostream. 
380
  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
381
  {
382
    dontPrint=true;
383
    _showNodeText=true;
384
    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
385
  }
386
  template<class X> struct NodePsTextsTraits : public T {
387
    const X &_nodePsTexts;
388
    NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
389
  };
390
  ///Inserts a PostScript block to the nodes
391

	
392
  ///With this command it is possible to insert a verbatim PostScript
393
  ///block to the nodes.
394
  ///The PS current point will be moved to the centre of the node before
395
  ///the PostScript block inserted.
396
  ///
397
  ///Before and after the block a newline character is inserted so you
398
  ///don't have to bother with the separators.
399
  ///
400
  ///\param x must be a node map with type that can be pushed to a standard
401
  ///ostream.
402
  ///
403
  ///\sa nodePsTextsPreamble()
404
  template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
405
  {
406
    dontPrint=true;
407
    _showNodePsText=true;
408
    return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
409
  }
410
  template<class X> struct ArcWidthsTraits : public T {
411
    const X &_arcWidths;
412
    ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
413
  };
414
  ///Sets the map of the arc widths
415

	
416
  ///Sets the map of the arc widths
417
  ///\param x must be a arc map with \c double (or convertible) values. 
418
  template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
419
  {
420
    dontPrint=true;
421
    return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
422
  }
423

	
424
  template<class X> struct NodeColorsTraits : public T {
425
    const X &_nodeColors;
426
    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
427
  };
428
  ///Sets the map of the node colors
429

	
430
  ///Sets the map of the node colors
431
  ///\param x must be a node map with \ref Color values.
432
  ///
433
  ///\sa Palette
434
  template<class X> GraphToEps<NodeColorsTraits<X> >
435
  nodeColors(const X &x)
436
  {
437
    dontPrint=true;
438
    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
439
  }
440
  template<class X> struct NodeTextColorsTraits : public T {
441
    const X &_nodeTextColors;
442
    NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
443
  };
444
  ///Sets the map of the node text colors
445

	
446
  ///Sets the map of the node text colors
447
  ///\param x must be a node map with \ref Color values. 
448
  ///
449
  ///\sa Palette
450
  template<class X> GraphToEps<NodeTextColorsTraits<X> >
451
  nodeTextColors(const X &x)
452
  {
453
    dontPrint=true;
454
    _nodeTextColorType=CUST_COL;
455
    return GraphToEps<NodeTextColorsTraits<X> >
456
      (NodeTextColorsTraits<X>(*this,x));
457
  }
458
  template<class X> struct ArcColorsTraits : public T {
459
    const X &_arcColors;
460
    ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
461
  };
462
  ///Sets the map of the arc colors
463

	
464
  ///Sets the map of the arc colors
465
  ///\param x must be a arc map with \ref Color values. 
466
  ///
467
  ///\sa Palette
468
  template<class X> GraphToEps<ArcColorsTraits<X> >
469
  arcColors(const X &x)
470
  {
471
    dontPrint=true;
472
    return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
473
  }
474
  ///Sets a global scale factor for node sizes
475

	
476
  ///Sets a global scale factor for node sizes.
477
  /// 
478
  /// If nodeSizes() is not given, this function simply sets the node
479
  /// sizes to \c d.  If nodeSizes() is given, but
480
  /// autoNodeScale() is not, then the node size given by
481
  /// nodeSizes() will be multiplied by the value \c d.
482
  /// If both nodeSizes() and autoNodeScale() are used, then the
483
  /// node sizes will be scaled in such a way that the greatest size will be
484
  /// equal to \c d.
485
  /// \sa nodeSizes()
486
  /// \sa autoNodeScale()
487
  GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
488
  ///Turns on/off the automatic node width scaling.
489

	
490
  ///Turns on/off the automatic node width scaling.
491
  ///
492
  ///\sa nodeScale()
493
  ///
494
  GraphToEps<T> &autoNodeScale(bool b=true) {
495
    _autoNodeScale=b;return *this;
496
  }
497

	
498
  ///Turns on/off the absolutematic node width scaling.
499

	
500
  ///Turns on/off the absolutematic node width scaling.
501
  ///
502
  ///\sa nodeScale()
503
  ///
504
  GraphToEps<T> &absoluteNodeSizes(bool b=true) {
505
    _absoluteNodeSizes=b;return *this;
506
  }
507

	
508
  ///Negates the Y coordinates.
509

	
510
  ///Negates the Y coordinates.
511
  ///
512
  GraphToEps<T> &negateY(bool b=true) {
513
    _negY=b;return *this;
514
  }
515

	
516
  ///Turn on/off pre-scaling
517

	
518
  ///By default graphToEps() rescales the whole image in order to avoid
519
  ///very big or very small bounding boxes.
520
  ///
521
  ///This (p)rescaling can be turned off with this function.
522
  ///
523
  GraphToEps<T> &preScale(bool b=true) {
524
    _preScale=b;return *this;
525
  }
526

	
527
  ///Sets a global scale factor for arc widths
528

	
529
  /// Sets a global scale factor for arc widths.
530
  ///
531
  /// If arcWidths() is not given, this function simply sets the arc
532
  /// widths to \c d.  If arcWidths() is given, but
533
  /// autoArcWidthScale() is not, then the arc withs given by
534
  /// arcWidths() will be multiplied by the value \c d.
535
  /// If both arcWidths() and autoArcWidthScale() are used, then the
536
  /// arc withs will be scaled in such a way that the greatest width will be
537
  /// equal to \c d.
538
  GraphToEps<T> &arcWidthScale(double d=.003) {_arcWidthScale=d;return *this;}
539
  ///Turns on/off the automatic arc width scaling.
540

	
541
  ///Turns on/off the automatic arc width scaling.
542
  ///
543
  ///\sa arcWidthScale()
544
  ///
545
  GraphToEps<T> &autoArcWidthScale(bool b=true) {
546
    _autoArcWidthScale=b;return *this;
547
  }
548
  ///Turns on/off the absolutematic arc width scaling.
549

	
550
  ///Turns on/off the absolutematic arc width scaling.
551
  ///
552
  ///\sa arcWidthScale()
553
  ///
554
  GraphToEps<T> &absoluteArcWidths(bool b=true) {
555
    _absoluteArcWidths=b;return *this;
556
  }
557
  ///Sets a global scale factor for the whole picture
558

	
559
  ///Sets a global scale factor for the whole picture
560
  ///
561

	
562
  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
563
  ///Sets the width of the border around the picture
564

	
565
  ///Sets the width of the border around the picture
566
  ///
567
  GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
568
  ///Sets the width of the border around the picture
569

	
570
  ///Sets the width of the border around the picture
571
  ///
572
  GraphToEps<T> &border(double x, double y) {
573
    _xBorder=x;_yBorder=y;return *this;
574
  }
575
  ///Sets whether to draw arrows
576

	
577
  ///Sets whether to draw arrows
578
  ///
579
  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
580
  ///Sets the length of the arrowheads
581

	
582
  ///Sets the length of the arrowheads
583
  ///
584
  GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
585
  ///Sets the width of the arrowheads
586

	
587
  ///Sets the width of the arrowheads
588
  ///
589
  GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
590
  
591
  ///Scales the drawing to fit to A4 page
592

	
593
  ///Scales the drawing to fit to A4 page
594
  ///
595
  GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
596
  
597
  ///Enables parallel arcs
598

	
599
  ///Enables parallel arcs
600
  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
601
  
602
  ///Sets the distance 
603
  
604
  ///Sets the distance 
605
  ///
606
  GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
607
  
608
  ///Hides the arcs
609
  
610
  ///Hides the arcs
611
  ///
612
  GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
613
  ///Hides the nodes
614
  
615
  ///Hides the nodes
616
  ///
617
  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
618
  
619
  ///Sets the size of the node texts
620
  
621
  ///Sets the size of the node texts
622
  ///
623
  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
624

	
625
  ///Sets the color of the node texts to be different from the node color
626

	
627
  ///Sets the color of the node texts to be as different from the node color
628
  ///as it is possible
629
  ///
630
  GraphToEps<T> &distantColorNodeTexts()
631
  {_nodeTextColorType=DIST_COL;return *this;}
632
  ///Sets the color of the node texts to be black or white and always visible.
633

	
634
  ///Sets the color of the node texts to be black or white according to
635
  ///which is more 
636
  ///different from the node color
637
  ///
638
  GraphToEps<T> &distantBWNodeTexts()
639
  {_nodeTextColorType=DIST_BW;return *this;}
640

	
641
  ///Gives a preamble block for node Postscript block.
642
  
643
  ///Gives a preamble block for node Postscript block.
644
  ///
645
  ///\sa nodePsTexts()
646
  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
647
    _nodePsTextsPreamble=str ;return *this;
648
  }
649
  ///Sets whether the the graph is undirected
650

	
651
  ///Sets whether the the graph is undirected.
652
  ///
653
  ///This setting is the default for undirected graphs.
654
  ///
655
  ///\sa directed()
656
   GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
657

	
658
  ///Sets whether the the graph is directed
659

	
660
  ///Sets whether the the graph is directed.
661
  ///Use it to show the edges as a pair of directed ones.
662
  ///
663
  ///This setting is the default for digraphs.
664
  ///
665
  ///\sa undirected()
666
  GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
667
  
668
  ///Sets the title.
669

	
670
  ///Sets the title of the generated image,
671
  ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
672
  ///the EPS file.
673
  GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
674
  ///Sets the copyright statement.
675

	
676
  ///Sets the copyright statement of the generated image,
677
  ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
678
  ///the EPS file.
679
  GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
680

	
681
protected:
682
  bool isInsideNode(dim2::Point<double> p, double r,int t) 
683
  {
684
    switch(t) {
685
    case CIRCLE:
686
    case MALE:
687
    case FEMALE:
688
      return p.normSquare()<=r*r;
689
    case SQUARE:
690
      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
691
    case DIAMOND:
692
      return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
693
    }
694
    return false;
695
  }
696

	
697
public:
698
  ~GraphToEps() { }
699
  
700
  ///Draws the graph.
701

	
702
  ///Like other functions using
703
  ///\ref named-templ-func-param "named template parameters",
704
  ///this function calls the algorithm itself, i.e. in this case
705
  ///it draws the graph.
706
  void run() {
707
    //\todo better 'epsilon' would be nice here.
708
    const double EPSILON=1e-9;
709
    if(dontPrint) return;
710
    
711
    _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
712
      mycoords(_coords,_negY);
713

	
714
    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
715
    if(_title.size()>0) os << "%%Title: " << _title << '\n';
716
     if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
717
//        << "%%Copyright: XXXX\n"
718
    os << "%%Creator: LEMON, graphToEps()\n";
719

	
720
    {    
721
#ifndef WIN32 
722
      timeval tv;
723
      gettimeofday(&tv, 0);
724

	
725
      char cbuf[26];
726
      ctime_r(&tv.tv_sec,cbuf);
727
      os << "%%CreationDate: " << cbuf;
728
#else
729
      SYSTEMTIME time;
730
      char buf1[11], buf2[9], buf3[5];
731
      
732
      GetSystemTime(&time);
733
      if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, 
734
			"ddd MMM dd", buf1, 11) &&
735
	  GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time, 
736
			"HH':'mm':'ss", buf2, 9) &&
737
	  GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, 
738
				"yyyy", buf3, 5)) {
739
	os << "%%CreationDate: " << buf1 << ' ' 
740
	   << buf2 << ' ' << buf3 << std::endl;
741
      }	  
742
#endif
743
    }
744

	
745
    if (_autoArcWidthScale) {
746
      double max_w=0;
747
      for(ArcIt e(g);e!=INVALID;++e)
748
	max_w=std::max(double(_arcWidths[e]),max_w);
749
      ///\todo better 'epsilon' would be nice here.
750
      if(max_w>EPSILON) {
751
	_arcWidthScale/=max_w;
752
      }
753
    }
754

	
755
    if (_autoNodeScale) {
756
      double max_s=0;
757
      for(NodeIt n(g);n!=INVALID;++n)
758
	max_s=std::max(double(_nodeSizes[n]),max_s);
759
      ///\todo better 'epsilon' would be nice here.
760
      if(max_s>EPSILON) {
761
	_nodeScale/=max_s;
762
      }
763
    }
764

	
765
    double diag_len = 1;
766
    if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
767
      dim2::BoundingBox<double> bb;
768
      for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
769
      if (bb.empty()) {
770
	bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
771
      }
772
      diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
773
      if(diag_len<EPSILON) diag_len = 1;
774
      if(!_absoluteNodeSizes) _nodeScale*=diag_len;
775
      if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
776
    }
777
    
778
    dim2::BoundingBox<double> bb;
779
    for(NodeIt n(g);n!=INVALID;++n) {
780
      double ns=_nodeSizes[n]*_nodeScale;
781
      dim2::Point<double> p(ns,ns);
782
      switch(_nodeShapes[n]) {
783
      case CIRCLE:
784
      case SQUARE:
785
      case DIAMOND:
786
	bb.add(p+mycoords[n]);
787
	bb.add(-p+mycoords[n]);
788
	break;
789
      case MALE:
790
	bb.add(-p+mycoords[n]);
791
	bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
792
	break;
793
      case FEMALE:
794
	bb.add(p+mycoords[n]);
795
	bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
796
	break;
797
      }
798
    }
799
    if (bb.empty()) {
800
      bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
801
    }
802
    
803
    if(_scaleToA4)
804
      os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
805
    else {
806
      if(_preScale) {
807
	//Rescale so that BoundingBox won't be neither to big nor too small.
808
	while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
809
	while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
810
      }
811
      
812
      os << "%%BoundingBox: "
813
	 << int(floor(bb.left()   * _scale - _xBorder)) << ' '
814
	 << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
815
	 << int(ceil(bb.right()  * _scale + _xBorder)) << ' '
816
	 << int(ceil(bb.top()    * _scale + _yBorder)) << '\n';
817
    }
818
    
819
    os << "%%EndComments\n";
820
    
821
    //x1 y1 x2 y2 x3 y3 cr cg cb w
822
    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
823
       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
824
    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
825
    //x y r
826
    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
827
    //x y r
828
    os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
829
       << "      2 index 1 index sub 2 index 2 index add lineto\n"
830
       << "      2 index 1 index sub 2 index 2 index sub lineto\n"
831
       << "      2 index 1 index add 2 index 2 index sub lineto\n"
832
       << "      closepath pop pop pop} bind def\n";
833
    //x y r
834
    os << "/di { newpath 2 index 1 index add 2 index moveto\n"
835
       << "      2 index             2 index 2 index add lineto\n"
836
       << "      2 index 1 index sub 2 index             lineto\n"
837
       << "      2 index             2 index 2 index sub lineto\n"
838
       << "      closepath pop pop pop} bind def\n";
839
    // x y r cr cg cb
840
    os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
841
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
842
       << "   } bind def\n";
843
    os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
844
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
845
       << "   } bind def\n";
846
    os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
847
       << "     setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
848
       << "   } bind def\n";
849
    os << "/nfemale { 0 0 0 setrgbcolor 3 index "
850
       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
851
       << " 1.5 mul mul setlinewidth\n"
852
       << "  newpath 5 index 5 index moveto "
853
       << "5 index 5 index 5 index 3.01 mul sub\n"
854
       << "  lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto\n"
855
       << "  5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke\n"
856
       << "  5 index 5 index 5 index c fill\n"
857
       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
858
       << "  } bind def\n";
859
    os << "/nmale {\n"
860
       << "  0 0 0 setrgbcolor 3 index "
861
       << _nodeBorderQuotient/(1+_nodeBorderQuotient)
862
       <<" 1.5 mul mul setlinewidth\n"
863
       << "  newpath 5 index 5 index moveto\n"
864
       << "  5 index 4 index 1 mul 1.5 mul add\n"
865
       << "  5 index 5 index 3 sqrt 1.5 mul mul add\n"
866
       << "  1 index 1 index lineto\n"
867
       << "  1 index 1 index 7 index sub moveto\n"
868
       << "  1 index 1 index lineto\n"
869
       << "  exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto\n"
870
       << "  stroke\n"
871
       << "  5 index 5 index 5 index c fill\n"
872
       << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
873
       << "  } bind def\n";
874
    
875

	
876
    os << "/arrl " << _arrowLength << " def\n";
877
    os << "/arrw " << _arrowWidth << " def\n";
878
    // l dx_norm dy_norm
879
    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
880
    //len w dx_norm dy_norm x1 y1 cr cg cb
881
    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
882
       << "       /w exch def /len exch def\n"
883
      //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
884
       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
885
       << "       len w sub arrl sub dx dy lrl\n"
886
       << "       arrw dy dx neg lrl\n"
887
       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
888
       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
889
       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
890
       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
891
       << "       arrw dy dx neg lrl\n"
892
       << "       len w sub arrl sub neg dx dy lrl\n"
893
       << "       closepath fill } bind def\n";
894
    os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
895
       << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
896

	
897
    os << "\ngsave\n";
898
    if(_scaleToA4)
899
      if(bb.height()>bb.width()) {
900
	double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
901
		  (A4WIDTH-2*A4BORDER)/bb.width());
902
	os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
903
	   << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
904
	   << " translate\n"
905
	   << sc << " dup scale\n"
906
	   << -bb.left() << ' ' << -bb.bottom() << " translate\n";
907
      }
908
      else {
909
	//\todo Verify centering
910
	double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
911
		  (A4WIDTH-2*A4BORDER)/bb.height());
912
	os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
913
	   << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER 
914
	   << " translate\n"
915
	   << sc << " dup scale\n90 rotate\n"
916
	   << -bb.left() << ' ' << -bb.top() << " translate\n";	
917
	}
918
    else if(_scale!=1.0) os << _scale << " dup scale\n";
919
    
920
    if(_showArcs) {
921
      os << "%Arcs:\ngsave\n";      
922
      if(_enableParallel) {
923
	std::vector<Arc> el;
924
	for(ArcIt e(g);e!=INVALID;++e)
925
	  if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
926
	     &&g.source(e)!=g.target(e))
927
	    el.push_back(e);
928
	std::sort(el.begin(),el.end(),arcLess(g));
929
	
930
	typename std::vector<Arc>::iterator j;
931
	for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
932
	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
933

	
934
	  double sw=0;
935
	  for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
936
	    sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
937
	  sw-=_parArcDist;
938
	  sw/=-2.0;
939
	  dim2::Point<double>
940
	    dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
941
	  double l=std::sqrt(dvec.normSquare()); 
942
	  //\todo better 'epsilon' would be nice here.
943
	  dim2::Point<double> d(dvec/std::max(l,EPSILON));
944
 	  dim2::Point<double> m;
945
// 	  m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
946

	
947
//  	  m=dim2::Point<double>(mycoords[g.source(*i)])+
948
// 	    dvec*(double(_nodeSizes[g.source(*i)])/
949
// 	       (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
950

	
951
 	  m=dim2::Point<double>(mycoords[g.source(*i)])+
952
	    d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
953

	
954
	  for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
955
	    sw+=_arcWidths[*e]*_arcWidthScale/2.0;
956
	    dim2::Point<double> mm=m+rot90(d)*sw/.75;
957
	    if(_drawArrows) {
958
	      int node_shape;
959
	      dim2::Point<double> s=mycoords[g.source(*e)];
960
	      dim2::Point<double> t=mycoords[g.target(*e)];
961
	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
962
	      node_shape=_nodeShapes[g.target(*e)];
963
	      dim2::Bezier3 bez(s,mm,mm,t);
964
	      double t1=0,t2=1;
965
	      for(int ii=0;ii<INTERPOL_PREC;++ii)
966
		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
967
		else t1=(t1+t2)/2;
968
	      dim2::Point<double> apoint=bez((t1+t2)/2);
969
	      rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
970
	      rn*=rn;
971
	      t2=(t1+t2)/2;t1=0;
972
	      for(int ii=0;ii<INTERPOL_PREC;++ii)
973
		if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
974
		else t2=(t1+t2)/2;
975
	      dim2::Point<double> linend=bez((t1+t2)/2);	      
976
	      bez=bez.before((t1+t2)/2);
977
// 	      rn=_nodeSizes[g.source(*e)]*_nodeScale;
978
// 	      node_shape=_nodeShapes[g.source(*e)];
979
// 	      t1=0;t2=1;
980
// 	      for(int i=0;i<INTERPOL_PREC;++i)
981
// 		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
982
// 		else t2=(t1+t2)/2;
983
// 	      bez=bez.after((t1+t2)/2);
984
	      os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
985
		 << _arcColors[*e].red() << ' '
986
		 << _arcColors[*e].green() << ' '
987
		 << _arcColors[*e].blue() << " setrgbcolor newpath\n"
988
		 << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
989
		 << bez.p2.x << ' ' << bez.p2.y << ' '
990
		 << bez.p3.x << ' ' << bez.p3.y << ' '
991
		 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
992
	      dim2::Point<double> dd(rot90(linend-apoint));
993
	      dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
994
		std::sqrt(dd.normSquare());
995
	      os << "newpath " << psOut(apoint) << " moveto "
996
		 << psOut(linend+dd) << " lineto "
997
		 << psOut(linend-dd) << " lineto closepath fill\n";
998
	    }
999
	    else {
1000
	      os << mycoords[g.source(*e)].x << ' '
1001
		 << mycoords[g.source(*e)].y << ' '
1002
		 << mm.x << ' ' << mm.y << ' '
1003
		 << mycoords[g.target(*e)].x << ' '
1004
		 << mycoords[g.target(*e)].y << ' '
1005
		 << _arcColors[*e].red() << ' '
1006
		 << _arcColors[*e].green() << ' '
1007
		 << _arcColors[*e].blue() << ' '
1008
		 << _arcWidths[*e]*_arcWidthScale << " lb\n";
1009
	    }
1010
	    sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
1011
	  }
1012
	}
1013
      }
1014
      else for(ArcIt e(g);e!=INVALID;++e)
1015
	if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
1016
	   &&g.source(e)!=g.target(e))
1017
	  if(_drawArrows) {
1018
	    dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
1019
	    double rn=_nodeSizes[g.target(e)]*_nodeScale;
1020
	    int node_shape=_nodeShapes[g.target(e)];
1021
	    double t1=0,t2=1;
1022
	    for(int i=0;i<INTERPOL_PREC;++i)
1023
	      if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
1024
	      else t2=(t1+t2)/2;
1025
	    double l=std::sqrt(d.normSquare());
1026
	    d/=l;
1027
	    
1028
	    os << l*(1-(t1+t2)/2) << ' '
1029
	       << _arcWidths[e]*_arcWidthScale << ' '
1030
	       << d.x << ' ' << d.y << ' '
1031
	       << mycoords[g.source(e)].x << ' '
1032
	       << mycoords[g.source(e)].y << ' '
1033
	       << _arcColors[e].red() << ' '
1034
	       << _arcColors[e].green() << ' '
1035
	       << _arcColors[e].blue() << " arr\n";
1036
	  }
1037
	  else os << mycoords[g.source(e)].x << ' '
1038
		  << mycoords[g.source(e)].y << ' '
1039
		  << mycoords[g.target(e)].x << ' '
1040
		  << mycoords[g.target(e)].y << ' '
1041
		  << _arcColors[e].red() << ' '
1042
		  << _arcColors[e].green() << ' '
1043
		  << _arcColors[e].blue() << ' '
1044
		  << _arcWidths[e]*_arcWidthScale << " l\n";
1045
      os << "grestore\n";
1046
    }
1047
    if(_showNodes) {
1048
      os << "%Nodes:\ngsave\n";
1049
      for(NodeIt n(g);n!=INVALID;++n) {
1050
	os << mycoords[n].x << ' ' << mycoords[n].y << ' '
1051
	   << _nodeSizes[n]*_nodeScale << ' '
1052
	   << _nodeColors[n].red() << ' '
1053
	   << _nodeColors[n].green() << ' '
1054
	   << _nodeColors[n].blue() << ' ';
1055
	switch(_nodeShapes[n]) {
1056
	case CIRCLE:
1057
	  os<< "nc";break;
1058
	case SQUARE:
1059
	  os<< "nsq";break;
1060
	case DIAMOND:
1061
	  os<< "ndi";break;
1062
	case MALE:
1063
	  os<< "nmale";break;
1064
	case FEMALE:
1065
	  os<< "nfemale";break;
1066
	}
1067
	os<<'\n';
1068
      }
1069
      os << "grestore\n";
1070
    }
1071
    if(_showNodeText) {
1072
      os << "%Node texts:\ngsave\n";
1073
      os << "/fosi " << _nodeTextSize << " def\n";
1074
      os << "(Helvetica) findfont fosi scalefont setfont\n";
1075
      for(NodeIt n(g);n!=INVALID;++n) {
1076
	switch(_nodeTextColorType) {
1077
	case DIST_COL:
1078
	  os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
1079
	  break;
1080
	case DIST_BW:
1081
	  os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
1082
	  break;
1083
	case CUST_COL:
1084
	  os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
1085
	  break;
1086
	default:
1087
	  os << "0 0 0 setrgbcolor\n";
1088
	}
1089
	os << mycoords[n].x << ' ' << mycoords[n].y
1090
	   << " (" << _nodeTexts[n] << ") cshow\n";
1091
      }
1092
      os << "grestore\n";
1093
    }
1094
    if(_showNodePsText) {
1095
      os << "%Node PS blocks:\ngsave\n";
1096
      for(NodeIt n(g);n!=INVALID;++n)
1097
	os << mycoords[n].x << ' ' << mycoords[n].y
1098
	   << " moveto\n" << _nodePsTexts[n] << "\n";
1099
      os << "grestore\n";
1100
    }
1101
    
1102
    os << "grestore\nshowpage\n";
1103

	
1104
    //CleanUp:
1105
    if(_pleaseRemoveOsStream) {delete &os;}
1106
  }
1107

	
1108
  ///\name Aliases
1109
  ///These are just some aliases to other parameter setting functions.
1110

	
1111
  ///@{
1112

	
1113
  ///An alias for arcWidths()
1114

	
1115
  ///An alias for arcWidths()
1116
  ///
1117
  template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x)
1118
  {
1119
    return arcWidths(x);
1120
  }
1121

	
1122
  ///An alias for arcColors()
1123

	
1124
  ///An alias for arcColors()
1125
  ///
1126
  template<class X> GraphToEps<ArcColorsTraits<X> >
1127
  edgeColors(const X &x)
1128
  {
1129
    return arcColors(x);
1130
  }
1131

	
1132
  ///An alias for arcWidthScale()
1133

	
1134
  ///An alias for arcWidthScale()
1135
  ///
1136
  GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
1137

	
1138
  ///An alias for autoArcWidthScale()
1139

	
1140
  ///An alias for autoArcWidthScale()
1141
  ///
1142
  GraphToEps<T> &autoEdgeWidthScale(bool b=true)
1143
  {
1144
    return autoArcWidthScale(b);
1145
  }
1146
  
1147
  ///An alias for absoluteArcWidths()
1148

	
1149
  ///An alias for absoluteArcWidths()
1150
  ///
1151
  GraphToEps<T> &absoluteEdgeWidths(bool b=true)
1152
  {
1153
    return absoluteArcWidths(b);
1154
  }
1155
  
1156
  ///An alias for parArcDist()
1157

	
1158
  ///An alias for parArcDist()
1159
  ///
1160
  GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
1161
  
1162
  ///An alias for hideArcs()
1163
  
1164
  ///An alias for hideArcs()
1165
  ///
1166
  GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
1167

	
1168
  ///@}
1169
};
1170

	
1171
template<class T>
1172
const int GraphToEps<T>::INTERPOL_PREC = 20;
1173
template<class T>
1174
const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
1175
template<class T>
1176
const double GraphToEps<T>::A4WIDTH  = 595.275590551181;
1177
template<class T>
1178
const double GraphToEps<T>::A4BORDER = 15;
1179

	
1180

	
1181
///Generates an EPS file from a graph
1182

	
1183
///\ingroup eps_io
1184
///Generates an EPS file from a graph.
1185
///\param g is a reference to the graph to be printed
1186
///\param os is a reference to the output stream.
1187
///By default it is <tt>std::cout</tt>
1188
///
1189
///This function also has a lot of
1190
///\ref named-templ-func-param "named parameters",
1191
///they are declared as the members of class \ref GraphToEps. The following
1192
///example shows how to use these parameters.
1193
///\code
1194
/// graphToEps(g,os).scale(10).coords(coords)
1195
///              .nodeScale(2).nodeSizes(sizes)
1196
///              .arcWidthScale(.4).run();
1197
///\endcode
1198
///\warning Don't forget to put the \ref GraphToEps::run() "run()"
1199
///to the end of the parameter list.
1200
///\sa GraphToEps
1201
///\sa graphToEps(G &g, const char *file_name)
1202
template<class G>
1203
GraphToEps<DefaultGraphToEpsTraits<G> > 
1204
graphToEps(G &g, std::ostream& os=std::cout)
1205
{
1206
  return 
1207
    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
1208
}
1209
 
1210
///Generates an EPS file from a graph
1211

	
1212
///\ingroup eps_io
1213
///This function does the same as
1214
///\ref graphToEps(G &g,std::ostream& os)
1215
///but it writes its output into the file \c file_name
1216
///instead of a stream.
1217
///\sa graphToEps(G &g, std::ostream& os)
1218
template<class G>
1219
GraphToEps<DefaultGraphToEpsTraits<G> > 
1220
graphToEps(G &g,const char *file_name)
1221
{
1222
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1223
    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
1224
}
1225

	
1226
///Generates an EPS file from a graph
1227

	
1228
///\ingroup eps_io
1229
///This function does the same as
1230
///\ref graphToEps(G &g,std::ostream& os)
1231
///but it writes its output into the file \c file_name
1232
///instead of a stream.
1233
///\sa graphToEps(G &g, std::ostream& os)
1234
template<class G>
1235
GraphToEps<DefaultGraphToEpsTraits<G> > 
1236
graphToEps(G &g,const std::string& file_name)
1237
{
1238
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1239
    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true));
1240
}
1241

	
1242
} //END OF NAMESPACE LEMON
1243

	
1244
#endif // LEMON_GRAPH_TO_EPS_H
Ignore white space 6 line context
1 1
syntax: glob
2 2
*.obj
3 3
*.orig
4 4
*.rej
5 5
*~
6 6
*.o
7 7
*.log
8 8
*.lo
9 9
*.tar.*
10 10
Makefile.in
11 11
aclocal.m4
12 12
config.h.in
13 13
configure
14 14
Makefile
15 15
config.h
16 16
config.log
17 17
config.status
18 18
libtool
19 19
stamp-h1
20 20
lemon/lemon.pc
21 21
lemon/libemon.la
22 22
lemon/stamp-h2
23 23
doc/Doxyfile
24 24
.dirstamp
25 25
.libs/*
26 26
.deps/*
27
demo/*.eps
27 28

	
28 29
syntax: regexp
29 30
(.*/)?\#[^/]*\#$
30 31
^doc/html/.*
31 32
^autom4te.cache/.*
32 33
^build-aux/.*
33 34
^objs.*/.*
34 35
^test/[a-z_]*$
35 36
^demo/.*_demo$
Ignore white space 6 line context
1 1
EXTRA_DIST += \
2 2
	demo/Makefile
3 3

	
4 4
if WANT_DEMO
5 5

	
6 6
noinst_PROGRAMS += \
7
        demo/arg_parser_demo \
7
	demo/arg_parser_demo \
8
	demo/graph_to_eps_demo \
8 9
	demo/lgf_demo
9 10

	
10 11
endif WANT_DEMO
11 12

	
12 13
demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc
14
demo_graph_to_eps_demo_SOURCES = demo/graph_to_eps_demo.cc
13 15
demo_lgf_demo_SOURCES = demo/lgf_demo.cc
14 16

	
Ignore white space 192 line context
1 1
/* -*- C++ -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup demos
20 20
///\file
21 21
///\brief Argument parser demo
22 22
///
23 23
/// This example shows how the argument parser can be used.
24 24
///
25 25
/// \include arg_parser_demo.cc
26 26

	
27 27
#include <lemon/arg_parser.h>
28 28

	
29 29
using namespace lemon;
30 30
int main(int argc, const char **argv)
31 31
{
32 32
  ArgParser ap(argc,argv);
33 33
  int i;
34 34
  std::string s;
35 35
  double d;
36 36
  bool b,sil;
37 37
  bool g1,g2,g3;
38 38
  ap.refOption("n", "An integer input.", i, true)
39 39
    .refOption("val", "A double input.", d)
40
    .doubleOption("val2", "A double input.", d)
40 41
    .synonym("vals","val")
41 42
    .refOption("name", "A string input.", s)
42 43
    .refOption("f", "A switch.", b)
43 44
    .refOption("nohelp", "", sil)
44 45
    .refOption("gra","Choice A",g1)
45 46
    .refOption("grb","Choice B",g2)
46 47
    .refOption("grc","Choice C",g3)
47 48
    .optionGroup("gr","gra")
48
    .optionGroup("gr","grb")
49
    .optionGroup("gr","grbkk")
49 50
    .optionGroup("gr","grc")
50 51
    .mandatoryGroup("gr")
51 52
    .onlyOneGroup("gr")
52 53
    .other("infile","The input file.")
53 54
    .other("...");
54 55
  
55 56
  ap.parse();
56 57

	
57 58
  std::cout << "Parameters of '" << ap.commandName() << "':\n";
58 59

	
59 60
  if(ap.given("n")) std::cout << "  Value of -n: " << i << std::endl;
60 61
  if(ap.given("val")) std::cout << "  Value of -val: " << d << std::endl;
61 62
  if(ap.given("name")) std::cout << "  Value of -name: " << s << std::endl;
62 63
  if(ap.given("f")) std::cout << "  -f is given\n";
63 64
  if(ap.given("nohelp")) std::cout << "  Value of -nohelp: " << sil << std::endl;
64 65
  if(ap.given("gra")) std::cout << "  -gra is given\n";
65 66
  if(ap.given("grb")) std::cout << "  -grb is given\n";
66 67
  if(ap.given("grc")) std::cout << "  -grc is given\n";
67 68
                                     
68 69
  switch(ap.files().size()) {
69 70
  case 0:
70 71
    std::cout << "  No file argument was given.\n";
71 72
    break;
72 73
  case 1:
73 74
    std::cout << "  1 file argument was given. It is:\n";
74 75
    break;
75 76
  default:
76 77
    std::cout << "  "
77 78
	      << ap.files().size() << " file arguments were given. They are:\n";
78 79
  }
79 80
  for(unsigned int i=0;i<ap.files().size();++i)
80 81
    std::cout << "    '" << ap.files()[i] << "'\n";
81 82
  
82 83
}
Ignore white space 6 line context
1 1
EXTRA_DIST += \
2 2
	lemon/Makefile \
3 3
	lemon/lemon.pc.in
4 4

	
5 5
pkgconfig_DATA += lemon/lemon.pc
6 6

	
7 7
lib_LTLIBRARIES += lemon/libemon.la
8 8

	
9 9
lemon_libemon_la_SOURCES = \
10 10
        lemon/arg_parser.cc \
11 11
        lemon/base.cc \
12
        lemon/color.cc \
12 13
        lemon/random.cc
13 14

	
14 15

	
15 16
lemon_libemon_la_CXXFLAGS = $(GLPK_CFLAGS) $(CPLEX_CFLAGS) $(SOPLEX_CXXFLAGS)
16 17
lemon_libemon_la_LDFLAGS = $(GLPK_LIBS) $(CPLEX_LIBS) $(SOPLEX_LIBS)
17 18

	
18 19
lemon_HEADERS += \
19 20
        lemon/arg_parser.h \
20 21
	lemon/assert.h \
21 22
        lemon/bfs.h \
22 23
        lemon/bin_heap.h \
24
        lemon/color.h \
23 25
        lemon/counter.h \
24 26
        lemon/dfs.h \
25 27
        lemon/dijkstra.h \
26 28
        lemon/dim2.h \
27 29
	lemon/error.h \
30
        lemon/graph_to_eps.h \
28 31
	lemon/graph_utils.h \
29 32
	lemon/kruskal.h \
30 33
	lemon/lgf_reader.h \
31 34
	lemon/list_graph.h \
32 35
	lemon/maps.h \
33 36
	lemon/math.h \
34 37
	lemon/path.h \
35 38
        lemon/random.h \
36 39
	lemon/smart_graph.h \
37 40
        lemon/time_measure.h \
38 41
        lemon/tolerance.h \
39 42
	lemon/unionfind.h
40 43

	
41 44
bits_HEADERS += \
42 45
	lemon/bits/alteration_notifier.h \
43 46
	lemon/bits/array_map.h \
44 47
	lemon/bits/base_extender.h \
48
        lemon/bits/bezier.h \
45 49
	lemon/bits/default_map.h \
46 50
	lemon/bits/graph_extender.h \
47 51
        lemon/bits/invalid.h \
48 52
	lemon/bits/map_extender.h \
49 53
	lemon/bits/path_dump.h \
50 54
	lemon/bits/traits.h \
51 55
        lemon/bits/utility.h \
52 56
	lemon/bits/vector_map.h
53 57

	
54 58
concept_HEADERS += \
55 59
	lemon/concept_check.h \
56 60
	lemon/concepts/digraph.h \
57 61
	lemon/concepts/graph.h \
58 62
	lemon/concepts/heap.h \
59 63
	lemon/concepts/maps.h \
60 64
	lemon/concepts/path.h \
61 65
	lemon/concepts/graph_components.h
Ignore white space 6 line context
... ...
@@ -101,192 +101,193 @@
101 101
    return *this;
102 102
  }
103 103

	
104 104
  ArgParser &ArgParser::stringOption(const std::string &name,
105 105
			       const std::string &help,
106 106
			       std::string value, bool obl)
107 107
  {
108 108
    ParData p;
109 109
    p.string_p=new std::string(value);
110 110
    p.self_delete=true;
111 111
    p.help=help;
112 112
    p.type=STRING;
113 113
    p.mandatory=obl;
114 114
    _opts[name]=p;
115 115
    return *this;
116 116
  }
117 117

	
118 118
  ArgParser &ArgParser::refOption(const std::string &name,
119 119
			       const std::string &help,
120 120
			       int &ref, bool obl)
121 121
  {
122 122
    ParData p;
123 123
    p.int_p=&ref;
124 124
    p.self_delete=false;
125 125
    p.help=help;
126 126
    p.type=INTEGER;
127 127
    p.mandatory=obl;
128 128
    _opts[name]=p;
129 129
    return *this;
130 130
  }
131 131

	
132 132
  ArgParser &ArgParser::refOption(const std::string &name,
133 133
                                  const std::string &help,
134 134
                                  double &ref, bool obl)
135 135
  {
136 136
    ParData p;
137 137
    p.double_p=&ref;
138 138
    p.self_delete=false;
139 139
    p.help=help;
140 140
    p.type=DOUBLE;
141 141
    p.mandatory=obl;
142 142
    _opts[name]=p;
143 143
    return *this;
144 144
  }
145 145

	
146 146
  ArgParser &ArgParser::refOption(const std::string &name,
147 147
                                  const std::string &help,
148 148
                                  bool &ref, bool obl)
149 149
  {
150 150
    ParData p;
151 151
    p.bool_p=&ref;
152 152
    p.self_delete=false;
153 153
    p.help=help;
154 154
    p.type=BOOL;
155 155
    p.mandatory=obl;
156 156
    _opts[name]=p;
157 157

	
158 158
    ref = false;
159 159

	
160 160
    return *this;
161 161
  }
162 162

	
163 163
  ArgParser &ArgParser::refOption(const std::string &name,
164 164
			       const std::string &help,
165 165
			       std::string &ref, bool obl)
166 166
  {
167 167
    ParData p;
168 168
    p.string_p=&ref;
169 169
    p.self_delete=false;
170 170
    p.help=help;
171 171
    p.type=STRING;
172 172
    p.mandatory=obl;
173 173
    _opts[name]=p;
174 174
    return *this;
175 175
  }
176 176

	
177 177
  ArgParser &ArgParser::funcOption(const std::string &name,
178 178
			       const std::string &help,
179 179
			       void (*func)(void *),void *data)
180 180
  {
181 181
    ParData p;
182 182
    p.func_p.p=func;
183 183
    p.func_p.data=data;
184 184
    p.self_delete=false;
185 185
    p.help=help;
186 186
    p.type=FUNC;
187 187
    p.mandatory=false;
188 188
    _opts[name]=p;
189 189
    return *this;
190 190
  }
191 191

	
192 192
  ArgParser &ArgParser::optionGroup(const std::string &group,
193 193
				    const std::string &opt)
194 194
  {
195 195
    Opts::iterator i = _opts.find(opt);
196 196
    LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
197
    if(i==_opts.end()) std::cout << "JAJJJJJJJJ\n";
197 198
    LEMON_ASSERT(!(i->second.ingroup), 
198 199
                 "Option already in option group: '"+opt+"'");
199 200
    GroupData &g=_groups[group];
200 201
    g.opts.push_back(opt);
201 202
    i->second.ingroup=true;
202 203
    return *this;
203 204
  }
204 205

	
205 206
  ArgParser &ArgParser::onlyOneGroup(const std::string &group)
206 207
  {
207 208
    GroupData &g=_groups[group];
208 209
    g.only_one=true;
209 210
    return *this;
210 211
  }
211 212

	
212 213
  ArgParser &ArgParser::synonym(const std::string &syn,
213 214
				const std::string &opt)
214 215
  {
215 216
    Opts::iterator o = _opts.find(opt);
216 217
    Opts::iterator s = _opts.find(syn);
217 218
    LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'");
218 219
    LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'");
219 220
    ParData p;
220 221
    p.help=opt;
221 222
    p.mandatory=false;
222 223
    p.syn=true;
223 224
    _opts[syn]=p;
224 225
    o->second.has_syn=true;
225 226
    return *this;
226 227
  }
227 228

	
228 229
  ArgParser &ArgParser::mandatoryGroup(const std::string &group)
229 230
  {
230 231
    GroupData &g=_groups[group];
231 232
    g.mandatory=true;
232 233
    return *this;
233 234
  }
234 235

	
235 236
  ArgParser &ArgParser::other(const std::string &name,
236 237
			      const std::string &help)
237 238
  {
238 239
    _others_help.push_back(OtherArg(name,help));
239 240
    return *this;
240 241
  }
241 242

	
242 243
  void ArgParser::show(std::ostream &os,Opts::iterator i)
243 244
  {
244 245
    os << "-" << i->first;
245 246
    if(i->second.has_syn)
246 247
      for(Opts::iterator j=_opts.begin();j!=_opts.end();++j)
247 248
	if(j->second.syn&&j->second.help==i->first)
248 249
	  os << "|-" << j->first;
249 250
    switch(i->second.type) {
250 251
    case STRING:
251 252
      os << " str";
252 253
      break;
253 254
    case INTEGER:
254 255
      os << " int";
255 256
      break;
256 257
    case DOUBLE:
257 258
      os << " num";
258 259
      break;
259 260
    default:
260 261
      break;
261 262
    }
262 263
  }
263 264

	
264 265
  void ArgParser::show(std::ostream &os,Groups::iterator i)
265 266
  {
266 267
    GroupData::Opts::iterator o=i->second.opts.begin();
267 268
    while(o!=i->second.opts.end()) {
268 269
      show(os,_opts.find(*o));
269 270
      ++o;
270 271
      if(o!=i->second.opts.end()) os<<'|';
271 272
    }
272 273
  }
273 274
    
274 275
  void ArgParser::showHelp(Opts::iterator i)
275 276
  {
276 277
    if(i->second.help.size()==0||i->second.syn) return;
277 278
    std::cerr << "  ";
278 279
    show(std::cerr,i);
279 280
    std::cerr << std::endl;
280 281
    std::cerr << "     " << i->second.help << std::endl;
281 282
  }
282 283
  void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::iterator i)
283 284
  {
284 285
    if(i->help.size()==0) return;
285 286
    std::cerr << "  " << i->name << std::endl
286 287
	      << "     " << i->help << std::endl;
287 288
  }
288 289
    
289 290
  void ArgParser::shortHelp()
290 291
  {
291 292
    const unsigned int LINE_LEN=77;
292 293
    const std::string indent("    ");
0 comments (0 inline)