gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Port graph_to_eps() and Color from svn -r3482.
0 5 5
default
10 files changed with 1817 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(-1,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 num the number of the allocated colors. If it is \c -1,
115
    ///the default color configuration is set up (26 color plus the
116
    ///white).  If \c num is less then 26/27 then the default color
117
    ///list is cut. Otherwise the color list is filled repeatedly with
118
    ///the default color list.  (The colors can be changed later on.)
119
    ///\param have_white indicates whether white is amongst the
120
    ///provided color (\c true) or not (\c false). If it is true,
121
    ///white will be assigned to \c 0.
122
    Palette(int num=-1,bool have_white=false)
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
    ///\e
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 visible 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 <sys/time.h>
23

	
24
#ifdef WIN32
25
#include <lemon/bits/mingw32_time.h>
26
#endif
27

	
28
#include<iostream>
29
#include<fstream>
30
#include<sstream>
31
#include<algorithm>
32
#include<vector>
33

	
34
#include<ctime>
35

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

	
43

	
44
///\ingroup eps_io
45
///\file
46
///\brief Simple graph drawer
47
///
48
///\author Alpar Juttner
49

	
50
namespace lemon {
51

	
52
template<class MT>
53
class _NegY {
54
public:
55
  typedef typename MT::Key Key;
56
  typedef typename MT::Value Value;
57
  const MT &map;
58
  int yscale;
59
  _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
60
  Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
61
};
62

	
63
///Default traits class of \ref GraphToEps
64

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

	
80
  const Graph &g;
81

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

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

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

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

	
106
  bool _enableParallel;
107
  double _parArcDist;
108

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

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

	
119
  bool _pleaseRemoveOsStream;
120

	
121
  bool _scaleToA4;
122

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

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

	
130
  bool _autoNodeScale;
131
  bool _autoArcWidthScale;
132

	
133
  bool _absoluteNodeSizes;
134
  bool _absoluteArcWidths;
135

	
136
  bool _negY;
137

	
138
  bool _preScale;
139
  ///Constructor
140

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

	
173
///Helper class to implement the named parameters of \ref graphToEps()
174

	
175
///Helper class to implement the named parameters of \ref graphToEps()
176
///\todo Is 'helper class' a good name for this?
177
///
178
///\todo Follow PostScript's DSC.
179
/// Use own dictionary.
180
///\todo Useful new features.
181
/// - Linestyles: dotted, dashed etc.
182
/// - A second color and percent value for the lines.
183
template<class T> class GraphToEps : public T 
184
{
185
  // Can't believe it is required by the C++ standard
186
  using T::g;
187
  using T::os;
188

	
189
  using T::_coords;
190
  using T::_nodeSizes;
191
  using T::_nodeShapes;
192
  using T::_nodeColors;
193
  using T::_arcColors;
194
  using T::_arcWidths;
195

	
196
  using T::_arcWidthScale;
197
  using T::_nodeScale;
198
  using T::_xBorder;
199
  using T::_yBorder;
200
  using T::_scale;
201
  using T::_nodeBorderQuotient;
202
  
203
  using T::_drawArrows;
204
  using T::_arrowLength;
205
  using T::_arrowWidth;
206
  
207
  using T::_showNodes;
208
  using T::_showArcs;
209

	
210
  using T::_enableParallel;
211
  using T::_parArcDist;
212

	
213
  using T::_showNodeText;
214
  using T::_nodeTexts;  
215
  using T::_nodeTextSize;
216

	
217
  using T::_showNodePsText;
218
  using T::_nodePsTexts;  
219
  using T::_nodePsTextsPreamble;
220
  
221
  using T::_undirected;
222

	
223
  using T::_pleaseRemoveOsStream;
224

	
225
  using T::_scaleToA4;
226

	
227
  using T::_title;
228
  using T::_copyright;
229

	
230
  using T::NodeTextColorType;
231
  using T::CUST_COL;
232
  using T::DIST_COL;
233
  using T::DIST_BW;
234
  using T::_nodeTextColorType;
235
  using T::_nodeTextColors;
236

	
237
  using T::_autoNodeScale;
238
  using T::_autoArcWidthScale;
239

	
240
  using T::_absoluteNodeSizes;
241
  using T::_absoluteArcWidths;
242

	
243

	
244
  using T::_negY;
245
  using T::_preScale;
246

	
247
  // dradnats ++C eht yb deriuqer si ti eveileb t'naC
248

	
249
  typedef typename T::Graph Graph;
250
  typedef typename Graph::Node Node;
251
  typedef typename Graph::NodeIt NodeIt;
252
  typedef typename Graph::Arc Arc;
253
  typedef typename Graph::ArcIt ArcIt;
254
  typedef typename Graph::InArcIt InArcIt;
255
  typedef typename Graph::OutArcIt OutArcIt;
256

	
257
  static const int INTERPOL_PREC;
258
  static const double A4HEIGHT;
259
  static const double A4WIDTH;
260
  static const double A4BORDER;
261

	
262
  bool dontPrint;
263

	
264
public:
265
  ///Node shapes
266

	
267
  ///Node shapes
268
  ///
269
  enum NodeShapes { 
270
    /// = 0
271
    ///\image html nodeshape_0.png
272
    ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
273
    CIRCLE=0, 
274
    /// = 1
275
    ///\image html nodeshape_1.png
276
    ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
277
    ///
278
    SQUARE=1, 
279
    /// = 2
280
    ///\image html nodeshape_2.png
281
    ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
282
    ///
283
    DIAMOND=2,
284
    /// = 3
285
    ///\image html nodeshape_3.png
286
    ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
287
    ///
288
    MALE=3,
289
    /// = 4
290
    ///\image html nodeshape_4.png
291
    ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
292
    ///
293
    FEMALE=4
294
  };
295

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

	
343
  ///Sets the map of the node coordinates.
344
  ///\param x must be a node map with dim2::Point<double> or
345
  ///\ref dim2::Point "dim2::Point<int>" values. 
346
  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
347
    dontPrint=true;
348
    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
349
  }
350
  template<class X> struct NodeSizesTraits : public T {
351
    const X &_nodeSizes;
352
    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
353
  };
354
  ///Sets the map of the node sizes
355

	
356
  ///Sets the map of the node sizes
357
  ///\param x must be a node map with \c double (or convertible) values. 
358
  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
359
  {
360
    dontPrint=true;
361
    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
362
  }
363
  template<class X> struct NodeShapesTraits : public T {
364
    const X &_nodeShapes;
365
    NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
366
  };
367
  ///Sets the map of the node shapes
368

	
369
  ///Sets the map of the node shapes.
370
  ///The availabe shape values
371
  ///can be found in \ref NodeShapes "enum NodeShapes".
372
  ///\param x must be a node map with \c int (or convertible) values. 
373
  ///\sa NodeShapes
374
  template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
375
  {
376
    dontPrint=true;
377
    return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
378
  }
379
  template<class X> struct NodeTextsTraits : public T {
380
    const X &_nodeTexts;
381
    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
382
  };
383
  ///Sets the text printed on the nodes
384

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

	
400
  ///With this command it is possible to insert a verbatim PostScript
401
  ///block to the nodes.
402
  ///The PS current point will be moved to the centre of the node before
403
  ///the PostScript block inserted.
404
  ///
405
  ///Before and after the block a newline character is inserted so you
406
  ///don't have to bother with the separators.
407
  ///
408
  ///\param x must be a node map with type that can be pushed to a standard
409
  ///ostream.
410
  ///
411
  ///\sa nodePsTextsPreamble()
412
  ///\todo Offer the choise not to move to the centre but pass the coordinates
413
  ///to the Postscript block inserted.
414
  template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
415
  {
416
    dontPrint=true;
417
    _showNodePsText=true;
418
    return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
419
  }
420
  template<class X> struct ArcWidthsTraits : public T {
421
    const X &_arcWidths;
422
    ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
423
  };
424
  ///Sets the map of the arc widths
425

	
426
  ///Sets the map of the arc widths
427
  ///\param x must be a arc map with \c double (or convertible) values. 
428
  template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
429
  {
430
    dontPrint=true;
431
    return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
432
  }
433

	
434
  template<class X> struct NodeColorsTraits : public T {
435
    const X &_nodeColors;
436
    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
437
  };
438
  ///Sets the map of the node colors
439

	
440
  ///Sets the map of the node colors
441
  ///\param x must be a node map with \ref Color values.
442
  ///
443
  ///\sa Palette
444
  template<class X> GraphToEps<NodeColorsTraits<X> >
445
  nodeColors(const X &x)
446
  {
447
    dontPrint=true;
448
    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
449
  }
450
  template<class X> struct NodeTextColorsTraits : public T {
451
    const X &_nodeTextColors;
452
    NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
453
  };
454
  ///Sets the map of the node text colors
455

	
456
  ///Sets the map of the node text colors
457
  ///\param x must be a node map with \ref Color values. 
458
  ///
459
  ///\sa Palette
460
  template<class X> GraphToEps<NodeTextColorsTraits<X> >
461
  nodeTextColors(const X &x)
462
  {
463
    dontPrint=true;
464
    _nodeTextColorType=CUST_COL;
465
    return GraphToEps<NodeTextColorsTraits<X> >
466
      (NodeTextColorsTraits<X>(*this,x));
467
  }
468
  template<class X> struct ArcColorsTraits : public T {
469
    const X &_arcColors;
470
    ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
471
  };
472
  ///Sets the map of the arc colors
473

	
474
  ///Sets the map of the arc colors
475
  ///\param x must be a arc map with \ref Color values. 
476
  ///
477
  ///\sa Palette
478
  template<class X> GraphToEps<ArcColorsTraits<X> >
479
  arcColors(const X &x)
480
  {
481
    dontPrint=true;
482
    return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
483
  }
484
  ///Sets a global scale factor for node sizes
485

	
486
  ///Sets a global scale factor for node sizes.
487
  /// 
488
  /// If nodeSizes() is not given, this function simply sets the node
489
  /// sizes to \c d.  If nodeSizes() is given, but
490
  /// autoNodeScale() is not, then the node size given by
491
  /// nodeSizes() will be multiplied by the value \c d.
492
  /// If both nodeSizes() and autoNodeScale() are used, then the
493
  /// node sizes will be scaled in such a way that the greatest size will be
494
  /// equal to \c d.
495
  /// \sa nodeSizes()
496
  /// \sa autoNodeScale()
497
  GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
498
  ///Turns on/off the automatic node width scaling.
499

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

	
508
  ///Turns on/off the absolutematic node width scaling.
509

	
510
  ///Turns on/off the absolutematic node width scaling.
511
  ///
512
  ///\sa nodeScale()
513
  ///
514
  GraphToEps<T> &absoluteNodeSizes(bool b=true) {
515
    _absoluteNodeSizes=b;return *this;
516
  }
517

	
518
  ///Negates the Y coordinates.
519

	
520
  ///Negates the Y coordinates.
521
  ///
522
  ///\todo More docs.
523
  ///
524
  GraphToEps<T> &negateY(bool b=true) {
525
    _negY=b;return *this;
526
  }
527

	
528
  ///Turn on/off prescaling
529

	
530
  ///By default graphToEps() rescales the whole image in order to avoid
531
  ///very big or very small bounding boxes.
532
  ///
533
  ///This (p)rescaling can be turned off with this function.
534
  ///
535
  GraphToEps<T> &preScale(bool b=true) {
536
    _preScale=b;return *this;
537
  }
538

	
539
  ///Sets a global scale factor for arc widths
540

	
541
  /// Sets a global scale factor for arc widths.
542
  ///
543
  /// If arcWidths() is not given, this function simply sets the arc
544
  /// widths to \c d.  If arcWidths() is given, but
545
  /// autoArcWidthScale() is not, then the arc withs given by
546
  /// arcWidths() will be multiplied by the value \c d.
547
  /// If both arcWidths() and autoArcWidthScale() are used, then the
548
  /// arc withs will be scaled in such a way that the greatest width will be
549
  /// equal to \c d.
550
  GraphToEps<T> &arcWidthScale(double d) {_arcWidthScale=d;return *this;}
551
  ///Turns on/off the automatic arc width scaling.
552

	
553
  ///Turns on/off the automatic arc width scaling.
554
  ///
555
  ///\sa arcWidthScale()
556
  ///
557
  GraphToEps<T> &autoArcWidthScale(bool b=true) {
558
    _autoArcWidthScale=b;return *this;
559
  }
560
  ///Turns on/off the absolutematic arc width scaling.
561

	
562
  ///Turns on/off the absolutematic arc width scaling.
563
  ///
564
  ///\sa arcWidthScale()
565
  ///
566
  GraphToEps<T> &absoluteArcWidths(bool b=true) {
567
    _absoluteArcWidths=b;return *this;
568
  }
569
  ///Sets a global scale factor for the whole picture
570

	
571
  ///Sets a global scale factor for the whole picture
572
  ///
573

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

	
577
  ///Sets the width of the border around the picture
578
  ///
579
  GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
580
  ///Sets the width of the border around the picture
581

	
582
  ///Sets the width of the border around the picture
583
  ///
584
  GraphToEps<T> &border(double x, double y) {
585
    _xBorder=x;_yBorder=y;return *this;
586
  }
587
  ///Sets whether to draw arrows
588

	
589
  ///Sets whether to draw arrows
590
  ///
591
  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
592
  ///Sets the length of the arrowheads
593

	
594
  ///Sets the length of the arrowheads
595
  ///
596
  GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
597
  ///Sets the width of the arrowheads
598

	
599
  ///Sets the width of the arrowheads
600
  ///
601
  GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
602
  
603
  ///Scales the drawing to fit to A4 page
604

	
605
  ///Scales the drawing to fit to A4 page
606
  ///
607
  GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
608
  
609
  ///Enables parallel arcs
610

	
611
  ///Enables parallel arcs
612
  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
613
  
614
  ///Sets the distance 
615
  
616
  ///Sets the distance 
617
  ///
618
  GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
619
  
620
  ///Hides the arcs
621
  
622
  ///Hides the arcs
623
  ///
624
  GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
625
  ///Hides the nodes
626
  
627
  ///Hides the nodes
628
  ///
629
  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
630
  
631
  ///Sets the size of the node texts
632
  
633
  ///Sets the size of the node texts
634
  ///
635
  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
636

	
637
  ///Sets the color of the node texts to be different from the node color
638

	
639
  ///Sets the color of the node texts to be as different from the node color
640
  ///as it is possible
641
  ///
642
  GraphToEps<T> &distantColorNodeTexts()
643
  {_nodeTextColorType=DIST_COL;return *this;}
644
  ///Sets the color of the node texts to be black or white and always visible.
645

	
646
  ///Sets the color of the node texts to be black or white according to
647
  ///which is more 
648
  ///different from the node color
649
  ///
650
  GraphToEps<T> &distantBWNodeTexts()
651
  {_nodeTextColorType=DIST_BW;return *this;}
652

	
653
  ///Gives a preamble block for node Postscript block.
654
  
655
  ///Gives a preamble block for node Postscript block.
656
  ///
657
  ///\sa nodePsTexts()
658
  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
659
    _nodePsTextsPreamble=str ;return *this;
660
  }
661
  ///Sets whether the the graph is undirected
662

	
663
  ///Sets whether the the graph is undirected
664
  ///
665
  GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
666

	
667
  ///Sets whether the the graph is directed
668

	
669
  ///Sets whether the the graph is directed.
670
  ///Use it to show the edges as a pair of directed ones.
671
  GraphToEps<T> &bidir(bool b=true) {_undirected=!b;return *this;}
672

	
673
  ///Sets the title.
674

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

	
681
  ///Sets the copyright statement of the generated image,
682
  ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
683
  ///the EPS file.
684
  ///\todo Multiline copyright notice could be supported.
685
  GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
686

	
687
protected:
688
  bool isInsideNode(dim2::Point<double> p, double r,int t) 
689
  {
690
    switch(t) {
691
    case CIRCLE:
692
    case MALE:
693
    case FEMALE:
694
      return p.normSquare()<=r*r;
695
    case SQUARE:
696
      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
697
    case DIAMOND:
698
      return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
699
    }
700
    return false;
701
  }
702

	
703
public:
704
  ~GraphToEps() { }
705
  
706
  ///Draws the graph.
707

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

	
719
    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
720
    if(_title.size()>0) os << "%%Title: " << _title << '\n';
721
     if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
722
//        << "%%Copyright: XXXX\n"
723
    os << "%%Creator: LEMON, graphToEps()\n";
724
    
725
    {
726
      char cbuf[50];
727
      timeval tv;
728
      gettimeofday(&tv, 0);
729
      ctime_r(&tv.tv_sec,cbuf);
730
      os << "%%CreationDate: " << cbuf;
731
    }
732

	
733
    if (_autoArcWidthScale) {
734
      double max_w=0;
735
      for(ArcIt e(g);e!=INVALID;++e)
736
	max_w=std::max(double(_arcWidths[e]),max_w);
737
      ///\todo better 'epsilon' would be nice here.
738
      if(max_w>EPSILON) {
739
	_arcWidthScale/=max_w;
740
      }
741
    }
742

	
743
    if (_autoNodeScale) {
744
      double max_s=0;
745
      for(NodeIt n(g);n!=INVALID;++n)
746
	max_s=std::max(double(_nodeSizes[n]),max_s);
747
      ///\todo better 'epsilon' would be nice here.
748
      if(max_s>EPSILON) {
749
	_nodeScale/=max_s;
750
      }
751
    }
752

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

	
864
    os << "/arrl " << _arrowLength << " def\n";
865
    os << "/arrw " << _arrowWidth << " def\n";
866
    // l dx_norm dy_norm
867
    os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
868
    //len w dx_norm dy_norm x1 y1 cr cg cb
869
    os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
870
       << "       /w exch def /len exch def\n"
871
      //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
872
       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
873
       << "       len w sub arrl sub dx dy lrl\n"
874
       << "       arrw dy dx neg lrl\n"
875
       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
876
       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
877
       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
878
       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
879
       << "       arrw dy dx neg lrl\n"
880
       << "       len w sub arrl sub neg dx dy lrl\n"
881
       << "       closepath fill } bind def\n";
882
    os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
883
       << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
884

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

	
922
	  double sw=0;
923
	  for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
924
	    sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
925
	  sw-=_parArcDist;
926
	  sw/=-2.0;
927
	  dim2::Point<double>
928
	    dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
929
	  double l=std::sqrt(dvec.normSquare()); 
930
	  ///\todo better 'epsilon' would be nice here.
931
	  dim2::Point<double> d(dvec/std::max(l,EPSILON));
932
 	  dim2::Point<double> m;
933
// 	  m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
934

	
935
//  	  m=dim2::Point<double>(mycoords[g.source(*i)])+
936
// 	    dvec*(double(_nodeSizes[g.source(*i)])/
937
// 	       (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
938

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

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

	
1092
    //CleanUp:
1093
    if(_pleaseRemoveOsStream) {delete &os;}
1094
  } 
1095
};
1096

	
1097
template<class T>
1098
const int GraphToEps<T>::INTERPOL_PREC = 20;
1099
template<class T>
1100
const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
1101
template<class T>
1102
const double GraphToEps<T>::A4WIDTH  = 595.275590551181;
1103
template<class T>
1104
const double GraphToEps<T>::A4BORDER = 15;
1105

	
1106

	
1107
///Generates an EPS file from a graph
1108

	
1109
///\ingroup eps_io
1110
///Generates an EPS file from a graph.
1111
///\param g is a reference to the graph to be printed
1112
///\param os is a reference to the output stream.
1113
///By default it is <tt>std::cout</tt>
1114
///
1115
///This function also has a lot of
1116
///\ref named-templ-func-param "named parameters",
1117
///they are declared as the members of class \ref GraphToEps. The following
1118
///example shows how to use these parameters.
1119
///\code
1120
/// graphToEps(g,os).scale(10).coords(coords)
1121
///              .nodeScale(2).nodeSizes(sizes)
1122
///              .arcWidthScale(.4).run();
1123
///\endcode
1124
///\warning Don't forget to put the \ref GraphToEps::run() "run()"
1125
///to the end of the parameter list.
1126
///\sa GraphToEps
1127
///\sa graphToEps(G &g, const char *file_name)
1128
template<class G>
1129
GraphToEps<DefaultGraphToEpsTraits<G> > 
1130
graphToEps(G &g, std::ostream& os=std::cout)
1131
{
1132
  return 
1133
    GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
1134
}
1135
 
1136
///Generates an EPS file from a graph
1137

	
1138
///\ingroup eps_io
1139
///This function does the same as
1140
///\ref graphToEps(G &g,std::ostream& os)
1141
///but it writes its output into the file \c file_name
1142
///instead of a stream.
1143
///\sa graphToEps(G &g, std::ostream& os)
1144
template<class G>
1145
GraphToEps<DefaultGraphToEpsTraits<G> > 
1146
graphToEps(G &g,const char *file_name)
1147
{
1148
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1149
    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
1150
}
1151

	
1152
///Generates an EPS file from a graph
1153

	
1154
///\ingroup eps_io
1155
///This function does the same as
1156
///\ref graphToEps(G &g,std::ostream& os)
1157
///but it writes its output into the file \c file_name
1158
///instead of a stream.
1159
///\sa graphToEps(G &g, std::ostream& os)
1160
template<class G>
1161
GraphToEps<DefaultGraphToEpsTraits<G> > 
1162
graphToEps(G &g,const std::string& file_name)
1163
{
1164
  return GraphToEps<DefaultGraphToEpsTraits<G> >
1165
    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true));
1166
}
1167

	
1168
} //END OF NAMESPACE LEMON
1169

	
1170
#endif // LEMON_GRAPH_TO_EPS_H
Ignore white space 6 line context
... ...
@@ -3,33 +3,34 @@
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

	
9 10
endif WANT_DEMO
10 11

	
11 12
demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc
12 13

	
14
demo_graph_to_eps_demo_SOURCES = demo/graph_to_eps_demo.cc
15

	
Ignore white space 48 line context
... ...
@@ -16,57 +16,58 @@
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:
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/dfs.h \
24 26
        lemon/dijkstra.h \
25 27
        lemon/dim2.h \
26 28
	lemon/error.h \
29
        lemon/graph_to_eps.h \
27 30
	lemon/graph_utils.h \
28 31
	lemon/kruskal.h \
29 32
	lemon/list_graph.h \
30 33
	lemon/maps.h \
31 34
	lemon/math.h \
32 35
	lemon/path.h \
33 36
        lemon/random.h \
34 37
	lemon/smart_graph.h \
35 38
        lemon/tolerance.h \
36 39
	lemon/unionfind.h
37 40

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

	
51 55
concept_HEADERS += \
52 56
	lemon/concept_check.h \
53 57
	lemon/concepts/digraph.h \
54 58
	lemon/concepts/graph.h \
55 59
	lemon/concepts/heap.h \
56 60
	lemon/concepts/maps.h \
57 61
	lemon/concepts/path.h \
58 62
	lemon/concepts/graph_components.h
Ignore white space 6 line context
... ...
@@ -173,48 +173,49 @@
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;
0 comments (0 inline)