gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Resolve several MSVC related compilation problems
0 3 0
default
3 files changed with 6 insertions and 1 deletions:
↑ Collapse diff ↑
Ignore white space 3072 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 Demonstrating graph input and output
22 22
///
23 23
/// This simple demo program gives an example of how to read and write
24 24
/// a graph and additional maps (on the nodes or the edges) from/to a
25 25
/// stream. 
26 26
///
27 27
/// \include reader_writer_demo.cc
28 28

	
29 29
#include <iostream>
30 30
#include <lemon/smart_graph.h>
31 31
#include <lemon/lgf_reader.h>
32 32
#include <lemon/lgf_writer.h>
33 33
#include <lemon/random.h>
34 34

	
35 35

	
36 36
using namespace lemon;
37 37

	
38 38
int main(int argc, const char *argv[]) {
39 39
  const int n = argc > 1 ? std::atoi(argv[1]) : 20;
40
  const int e = argc > 2 ? std::atoi(argv[2]) : static_cast<int>(n * log(n));
40
  const int e = argc > 2 ? std::atoi(argv[2]) : static_cast<int>(n * std::log(double(n)));
41 41
  const int m = argc > 3 ? std::atoi(argv[3]) : 100;
42 42

	
43 43
  SmartDigraph digraph;
44 44

	
45 45
  std::stringstream ss;
46 46

	
47 47
  try {
48 48

	
49 49
    typedef SmartDigraph Digraph;
50 50
    typedef Digraph::Node Node;
51 51
    typedef Digraph::Arc Arc;
52 52
    typedef Digraph::ArcIt ArcIt;
53 53

	
54 54
    typedef Digraph::NodeMap<int> PotentialMap;
55 55
    typedef Digraph::ArcMap<int> CapacityMap;
56 56
    typedef Digraph::ArcMap<std::string> NameMap;
57 57

	
58 58
    Digraph digraph;
59 59
    PotentialMap potential(digraph);
60 60
    CapacityMap capacity(digraph);
61 61
    NameMap name(digraph);
62 62

	
63 63
    std::vector<Node> nodes;
64 64
    for (int i = 0; i < n; ++i) {
65 65
      Node node = digraph.addNode();
66 66
      potential[node] = rnd[m];
67 67
      nodes.push_back(node);
68 68
    }
69 69

	
70 70
    std::vector<Arc> arcs;
71 71
    for (int i = 0; i < e; ++i) {
72 72
      int s = rnd[n];
73 73
      int t = rnd[n];
74 74
      int c = rnd[m];
75 75
      Arc arc = digraph.addArc(nodes[s], nodes[t]);
76 76
      capacity[arc] = c;
77 77
      std::ostringstream os;
78 78
      os << "arc \t" << i << std::endl;
79 79
      name[arc] = os.str();
80 80
      arcs.push_back(arc);
81 81
    }
82 82

	
83 83

	
84 84
    DigraphWriter<Digraph>(ss, digraph).
85 85
      nodeMap("potential", potential).
86 86
      arcMap("capacity", capacity).
87 87
      arcMap("name", name).
88 88
      node("source", nodes[0]).
89 89
      node("target", nodes[1]).
90 90
      arc("bottleneck", arcs[e / 2]).
91 91
      attribute("creator", "lemon library").
92 92
      run();
93 93

	
94 94
  } catch (DataFormatError& error) {
95 95
    std::cerr << error.what() << std::endl;
96 96
  }
97 97

	
98 98
  try {
99 99

	
100 100
    typedef SmartDigraph Digraph;
101 101
    typedef Digraph::Node Node;
102 102
    typedef Digraph::Arc Arc;
103 103
    typedef Digraph::ArcIt ArcIt;
104 104

	
105 105
    typedef Digraph::NodeMap<int> LabelMap;
106 106
    typedef Digraph::NodeMap<int> PotentialMap;
107 107
    typedef Digraph::ArcMap<int> CapacityMap;
108 108
    typedef Digraph::ArcMap<std::string> NameMap;
109 109

	
110 110
    Digraph digraph;
111 111
    LabelMap label(digraph);
112 112
    PotentialMap potential(digraph);
113 113
    CapacityMap capacity(digraph);
114 114
    NameMap name(digraph);
115 115

	
116 116
    Node s, t;
117 117
    Arc a;
118 118
    
119 119
    std::string creator;
120 120

	
121 121
    for (int i = 0; i < n; ++i) {
122 122
      Node node = digraph.addNode();
123 123
      label[node] = i;
124 124
    }
125 125
    
126 126
    DigraphReader<Digraph>(ss, digraph).
127 127
      useNodes(label).
128 128
      nodeMap("potential", potential).
129 129
      arcMap("capacity", capacity).
130 130
      arcMap("name", name).
131 131
      node("source", s).
132 132
      node("target", t).
133 133
      arc("bottleneck", a).
134 134
      attribute("creator", creator).
135 135
      run();
136 136

	
137 137
    DigraphWriter<Digraph>(std::cout, digraph).
138 138
      nodeMap("potential", potential).
139 139
      arcMap("capacity", capacity).
140 140
      arcMap("name", name).
141 141
      node("source", s).
142 142
      node("target", t).
143 143
      arc("bottleneck", a).
144 144
      attribute("creator", creator).
145 145
      run();
146 146

	
147 147
  } catch (DataFormatError& error) {
148 148
    std::cerr << error.what() << std::endl;
149 149
  }
150 150

	
151 151

	
152 152
  return 0;
153 153
}
Ignore white space 3072 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
#ifndef LEMON_GRAPH_TO_EPS_H
20 20
#define LEMON_GRAPH_TO_EPS_H
21 21

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

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

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

	
42 44

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

	
47 49
namespace lemon {
48 50

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

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

	
79 81
  const Graph &g;
80 82

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

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

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

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

	
105 107
  bool _enableParallel;
106 108
  double _parArcDist;
107 109

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

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

	
118 120
  bool _pleaseRemoveOsStream;
119 121

	
120 122
  bool _scaleToA4;
121 123

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

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

	
129 131
  bool _autoNodeScale;
130 132
  bool _autoArcWidthScale;
131 133

	
132 134
  bool _absoluteNodeSizes;
133 135
  bool _absoluteArcWidths;
134 136

	
135 137
  bool _negY;
136 138

	
137 139
  bool _preScale;
138 140
  ///Constructor
139 141

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

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

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

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

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

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

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

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

	
215 217
  using T::_pleaseRemoveOsStream;
216 218

	
217 219
  using T::_scaleToA4;
218 220

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

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

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

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

	
235 237

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

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

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

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

	
254 256
  bool dontPrint;
255 257

	
256 258
public:
257 259
  ///Node shapes
258 260

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
508 510
  ///Negates the Y coordinates.
509 511

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	
1111 1113
  ///@{
1112 1114

	
1113 1115
  ///An alias for arcWidths()
1114 1116

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

	
1122 1124
  ///An alias for arcColors()
1123 1125

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

	
1132 1134
  ///An alias for arcWidthScale()
1133 1135

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

	
1138 1140
  ///An alias for autoArcWidthScale()
1139 1141

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

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

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

	
1168 1170
  ///@}
1169 1171
};
1170 1172

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

	
1180 1182

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

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

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

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

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

	
1242 1244
} //END OF NAMESPACE LEMON
1243 1245

	
1244 1246
#endif // LEMON_GRAPH_TO_EPS_H
Ignore white space 3072 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
#ifndef LEMON_TIME_MEASURE_H
20 20
#define LEMON_TIME_MEASURE_H
21 21

	
22 22
///\ingroup timecount
23 23
///\file
24 24
///\brief Tools for measuring cpu usage
25 25

	
26 26
#ifdef WIN32
27
#define WIN32_LEAN_AND_MEAN
28
#define NOMINMAX
27 29
#include <windows.h>
28 30
#include <cmath>
29 31
#else
30 32
#include <sys/times.h>
31 33
#include <sys/time.h>
32 34
#endif
33 35

	
36
#include <string>
34 37
#include <fstream>
35 38
#include <iostream>
36 39

	
37 40
namespace lemon {
38 41

	
39 42
  /// \addtogroup timecount
40 43
  /// @{
41 44

	
42 45
  /// A class to store (cpu)time instances.
43 46

	
44 47
  /// This class stores five time values.
45 48
  /// - a real time
46 49
  /// - a user cpu time
47 50
  /// - a system cpu time
48 51
  /// - a user cpu time of children
49 52
  /// - a system cpu time of children
50 53
  ///
51 54
  /// TimeStamp's can be added to or substracted from each other and
52 55
  /// they can be pushed to a stream.
53 56
  ///
54 57
  /// In most cases, perhaps the \ref Timer or the \ref TimeReport
55 58
  /// class is what you want to use instead.
56 59
  ///
57 60
  ///\author Alpar Juttner
58 61

	
59 62
  class TimeStamp
60 63
  {
61 64
    double utime;
62 65
    double stime;
63 66
    double cutime;
64 67
    double cstime;
65 68
    double rtime;
66 69
  
67 70
    void _reset() { 
68 71
      utime = stime = cutime = cstime = rtime = 0;
69 72
    }
70 73

	
71 74
  public:
72 75

	
73 76
    ///Read the current time values of the process
74 77
    void stamp()
75 78
    {
76 79
#ifndef WIN32
77 80
      timeval tv;
78 81
      gettimeofday(&tv, 0);
79 82
      rtime=tv.tv_sec+double(tv.tv_usec)/1e6;
80 83

	
81 84
      tms ts;
82 85
      double tck=sysconf(_SC_CLK_TCK);
83 86
      times(&ts);
84 87
      utime=ts.tms_utime/tck;
85 88
      stime=ts.tms_stime/tck;
86 89
      cutime=ts.tms_cutime/tck;
87 90
      cstime=ts.tms_cstime/tck;
88 91
#else
89 92
      static const double ch = 4294967296.0e-7;
90 93
      static const double cl = 1.0e-7;
91 94

	
92 95
      FILETIME system;
93 96
      GetSystemTimeAsFileTime(&system);
94 97
      rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime;
95 98

	
96 99
      FILETIME create, exit, kernel, user;
97 100
      if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
98 101
	utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
99 102
	stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
100 103
	cutime = 0;
101 104
	cstime = 0;
102 105
      } else {
103 106
	rtime = 0;
104 107
	utime = 0;
105 108
	stime = 0;
106 109
	cutime = 0;
107 110
	cstime = 0;
108 111
      }
109 112
#endif      
110 113
    }
111 114
  
112 115
    /// Constructor initializing with zero
113 116
    TimeStamp()
114 117
    { _reset(); }
115 118
    ///Constructor initializing with the current time values of the process
116 119
    TimeStamp(void *) { stamp();}
117 120
  
118 121
    ///Set every time value to zero
119 122
    TimeStamp &reset() {_reset();return *this;}
120 123

	
121 124
    ///\e
122 125
    TimeStamp &operator+=(const TimeStamp &b)
123 126
    {
124 127
      utime+=b.utime;
125 128
      stime+=b.stime;
126 129
      cutime+=b.cutime;
127 130
      cstime+=b.cstime;
128 131
      rtime+=b.rtime;
129 132
      return *this;
130 133
    }
131 134
    ///\e
132 135
    TimeStamp operator+(const TimeStamp &b) const
133 136
    {
134 137
      TimeStamp t(*this);
135 138
      return t+=b;
136 139
    }
137 140
    ///\e
138 141
    TimeStamp &operator-=(const TimeStamp &b)
139 142
    {
140 143
      utime-=b.utime;
141 144
      stime-=b.stime;
142 145
      cutime-=b.cutime;
143 146
      cstime-=b.cstime;
144 147
      rtime-=b.rtime;
145 148
      return *this;
146 149
    }
147 150
    ///\e
148 151
    TimeStamp operator-(const TimeStamp &b) const
149 152
    {
150 153
      TimeStamp t(*this);
151 154
      return t-=b;
152 155
    }
153 156
    ///\e
154 157
    TimeStamp &operator*=(double b)
155 158
    {
156 159
      utime*=b;
157 160
      stime*=b;
158 161
      cutime*=b;
159 162
      cstime*=b;
160 163
      rtime*=b;
161 164
      return *this;
162 165
    }
163 166
    ///\e
164 167
    TimeStamp operator*(double b) const
165 168
    {
166 169
      TimeStamp t(*this);
167 170
      return t*=b;
168 171
    }
169 172
    friend TimeStamp operator*(double b,const TimeStamp &t);
170 173
    ///\e
171 174
    TimeStamp &operator/=(double b)
172 175
    {
173 176
      utime/=b;
174 177
      stime/=b;
175 178
      cutime/=b;
176 179
      cstime/=b;
177 180
      rtime/=b;
178 181
      return *this;
179 182
    }
180 183
    ///\e
181 184
    TimeStamp operator/(double b) const
182 185
    {
183 186
      TimeStamp t(*this);
184 187
      return t/=b;
185 188
    }
186 189
    ///The time ellapsed since the last call of stamp()
187 190
    TimeStamp ellapsed() const
188 191
    {
189 192
      TimeStamp t(NULL);
190 193
      return t-*this;
191 194
    }
192 195
  
193 196
    friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t);
194 197
  
195 198
    ///Gives back the user time of the process
196 199
    double userTime() const
197 200
    {
198 201
      return utime;
199 202
    }
200 203
    ///Gives back the system time of the process
201 204
    double systemTime() const
202 205
    {
203 206
      return stime;
204 207
    }
205 208
    ///Gives back the user time of the process' children
206 209

	
207 210
    ///\note On <tt>WIN32</tt> platform this value is not calculated. 
208 211
    ///
209 212
    double cUserTime() const
210 213
    {
211 214
      return cutime;
212 215
    }
213 216
    ///Gives back the user time of the process' children
214 217

	
215 218
    ///\note On <tt>WIN32</tt> platform this value is not calculated. 
216 219
    ///
217 220
    double cSystemTime() const
218 221
    {
219 222
      return cstime;
220 223
    }
221 224
    ///Gives back the real time
222 225
    double realTime() const {return rtime;}
223 226
  };
224 227

	
225 228
  TimeStamp operator*(double b,const TimeStamp &t) 
226 229
  {
227 230
    return t*b;
228 231
  }
229 232
  
230 233
  ///Prints the time counters
231 234

	
232 235
  ///Prints the time counters in the following form:
233 236
  ///
234 237
  /// <tt>u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs</tt>
235 238
  ///
236 239
  /// where the values are the
237 240
  /// \li \c u: user cpu time,
238 241
  /// \li \c s: system cpu time,
239 242
  /// \li \c cu: user cpu time of children,
240 243
  /// \li \c cs: system cpu time of children,
241 244
  /// \li \c real: real time.
242 245
  /// \relates TimeStamp
243 246
  /// \note On <tt>WIN32</tt> platform the cummulative values are not
244 247
  /// calculated.
245 248
  inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t)
246 249
  {
247 250
    os << "u: " << t.userTime() <<
248 251
      "s, s: " << t.systemTime() <<
249 252
      "s, cu: " << t.cUserTime() <<
250 253
      "s, cs: " << t.cSystemTime() <<
251 254
      "s, real: " << t.realTime() << "s";
252 255
    return os;
253 256
  }
254 257

	
255 258
  ///Class for measuring the cpu time and real time usage of the process
256 259

	
257 260
  ///Class for measuring the cpu time and real time usage of the process.
258 261
  ///It is quite easy-to-use, here is a short example.
259 262
  ///\code
260 263
  /// #include<lemon/time_measure.h>
261 264
  /// #include<iostream>
262 265
  ///
263 266
  /// int main()
264 267
  /// {
265 268
  ///
266 269
  ///   ...
267 270
  ///
268 271
  ///   Timer t;
269 272
  ///   doSomething();
270 273
  ///   std::cout << t << '\n';
271 274
  ///   t.restart();
272 275
  ///   doSomethingElse();
273 276
  ///   std::cout << t << '\n';
274 277
  ///
275 278
  ///   ...
276 279
  ///
277 280
  /// }
278 281
  ///\endcode
279 282
  ///
280 283
  ///The \ref Timer can also be \ref stop() "stopped" and
281 284
  ///\ref start() "started" again, so it is possible to compute collected
282 285
  ///running times.
283 286
  ///
284 287
  ///\warning Depending on the operation system and its actual configuration
285 288
  ///the time counters have a certain (10ms on a typical Linux system)
286 289
  ///granularity.
287 290
  ///Therefore this tool is not appropriate to measure very short times.
288 291
  ///Also, if you start and stop the timer very frequently, it could lead to
289 292
  ///distorted results.
290 293
  ///
291 294
  ///\note If you want to measure the running time of the execution of a certain
292 295
  ///function, consider the usage of \ref TimeReport instead.
293 296
  ///
294 297
  ///\todo This shouldn't be Unix (Linux) specific.
295 298
  ///\sa TimeReport
296 299
  ///
297 300
  ///\author Alpar Juttner
298 301
  class Timer
299 302
  {
300 303
    int _running; //Timer is running iff _running>0; (_running>=0 always holds)
301 304
    TimeStamp start_time; //This is the relativ start-time if the timer
302 305
                          //is _running, the collected _running time otherwise.
303 306
    
304 307
    void _reset() {if(_running) start_time.stamp(); else start_time.reset();}
305 308
  
306 309
  public: 
307 310
    ///Constructor.
308 311

	
309 312
    ///\param run indicates whether or not the timer starts immediately.
310 313
    ///
311 314
    Timer(bool run=true) :_running(run) {_reset();}
312 315

	
313 316
    ///\name Control the state of the timer
314 317
    ///Basically a Timer can be either running or stopped,
315 318
    ///but it provides a bit finer control on the execution.
316 319
    ///The \ref Timer also counts the number of \ref start()
317 320
    ///executions, and is stops only after the same amount (or more)
318 321
    ///\ref stop() "stop()"s. This can be useful e.g. to compute the running time
319 322
    ///of recursive functions.
320 323
    ///
321 324

	
322 325
    ///@{
323 326

	
324 327
    ///Reset and stop the time counters
325 328

	
326 329
    ///This function resets and stops the time counters
327 330
    ///\sa restart()
328 331
    void reset()
329 332
    {
330 333
      _running=0;
331 334
      _reset();
332 335
    }
333 336

	
334 337
    ///Start the time counters
335 338
    
336 339
    ///This function starts the time counters.
337 340
    ///
338 341
    ///If the timer is started more than ones, it will remain running
339 342
    ///until the same amount of \ref stop() is called.
340 343
    ///\sa stop()
341 344
    void start() 
342 345
    {
343 346
      if(_running) _running++;
344 347
      else {
345 348
	_running=1;
346 349
	TimeStamp t;
347 350
	t.stamp();
348 351
	start_time=t-start_time;
349 352
      }
350 353
    }
351 354

	
352 355
    
353 356
    ///Stop the time counters
354 357

	
355 358
    ///This function stops the time counters. If start() was executed more than
356 359
    ///once, then the same number of stop() execution is necessary the really
357 360
    ///stop the timer.
358 361
    /// 
359 362
    ///\sa halt()
360 363
    ///\sa start()
361 364
    ///\sa restart()
362 365
    ///\sa reset()
363 366

	
364 367
    void stop() 
365 368
    {
366 369
      if(_running && !--_running) {
367 370
	TimeStamp t;
368 371
	t.stamp();
369 372
	start_time=t-start_time;
370 373
      }
371 374
    }
372 375

	
373 376
    ///Halt (i.e stop immediately) the time counters
374 377

	
375 378
    ///This function stops immediately the time counters, i.e. <tt>t.halt()</tt>
376 379
    ///is a faster
377 380
    ///equivalent of the following.
378 381
    ///\code
379 382
    ///  while(t.running()) t.stop()
380 383
    ///\endcode
381 384
    ///
382 385
    ///
383 386
    ///\sa stop()
384 387
    ///\sa restart()
385 388
    ///\sa reset()
386 389

	
387 390
    void halt() 
388 391
    {
389 392
      if(_running) {
390 393
	_running=0;
391 394
	TimeStamp t;
392 395
	t.stamp();
393 396
	start_time=t-start_time;
394 397
      }
395 398
    }
396 399

	
397 400
    ///Returns the running state of the timer
398 401

	
399 402
    ///This function returns the number of stop() exections that is
400 403
    ///necessary to really stop the timer.
401 404
    ///For example the timer
402 405
    ///is running if and only if the return value is \c true
403 406
    ///(i.e. greater than
404 407
    ///zero).
405 408
    int running()  { return _running; }
406 409
    
407 410
    
408 411
    ///Restart the time counters
409 412

	
410 413
    ///This function is a shorthand for
411 414
    ///a reset() and a start() calls.
412 415
    ///
413 416
    void restart() 
414 417
    {
415 418
      reset();
416 419
      start();
417 420
    }
418 421
    
419 422
    ///@}
420 423

	
421 424
    ///\name Query Functions for the ellapsed time
422 425

	
423 426
    ///@{
424 427

	
425 428
    ///Gives back the ellapsed user time of the process
426 429
    double userTime() const
427 430
    {
428 431
      return operator TimeStamp().userTime();
429 432
    }
430 433
    ///Gives back the ellapsed system time of the process
431 434
    double systemTime() const
432 435
    {
433 436
      return operator TimeStamp().systemTime();
434 437
    }
435 438
    ///Gives back the ellapsed user time of the process' children
436 439

	
437 440
    ///\note On <tt>WIN32</tt> platform this value is not calculated. 
438 441
    ///
439 442
    double cUserTime() const
440 443
    {
441 444
      return operator TimeStamp().cUserTime();
442 445
    }
443 446
    ///Gives back the ellapsed user time of the process' children
444 447

	
445 448
    ///\note On <tt>WIN32</tt> platform this value is not calculated. 
446 449
    ///
447 450
    double cSystemTime() const
448 451
    {
449 452
      return operator TimeStamp().cSystemTime();
450 453
    }
451 454
    ///Gives back the ellapsed real time
452 455
    double realTime() const
453 456
    {
454 457
      return operator TimeStamp().realTime();
455 458
    }
456 459
    ///Computes the ellapsed time
457 460

	
458 461
    ///This conversion computes the ellapsed time, therefore you can print
459 462
    ///the ellapsed time like this.
460 463
    ///\code
461 464
    ///  Timer t;
462 465
    ///  doSomething();
463 466
    ///  std::cout << t << '\n';
464 467
    ///\endcode
465 468
    operator TimeStamp () const
466 469
    {
467 470
      TimeStamp t;
468 471
      t.stamp();
469 472
      return _running?t-start_time:start_time;
470 473
    }
471 474

	
472 475

	
473 476
    ///@}
474 477
  };
475 478

	
476 479
  ///Same as \ref Timer but prints a report on destruction.
477 480

	
478 481
  ///Same as \ref Timer but prints a report on destruction.
479 482
  ///This example shows its usage.
480 483
  ///\code
481 484
  ///  void myAlg(ListGraph &g,int n)
482 485
  ///  {
483 486
  ///    TimeReport tr("Running time of myAlg: ");
484 487
  ///    ... //Here comes the algorithm
485 488
  ///  }
486 489
  ///\endcode
487 490
  ///
488 491
  ///\sa Timer
489 492
  ///\sa NoTimeReport
490 493
  ///\todo There is no test case for this
491 494
  class TimeReport : public Timer 
492 495
  {
493 496
    std::string _title;
494 497
    std::ostream &_os;
495 498
  public:
496 499
    ///\e
497 500

	
498 501
    ///\param title This text will be printed before the ellapsed time.
499 502
    ///\param os The stream to print the report to.
500 503
    ///\param run Sets whether the timer should start immediately.
501 504

	
502 505
    TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true) 
503 506
      : Timer(run), _title(title), _os(os){}
504 507
    ///\e Prints the ellapsed time on destruction.
505 508
    ~TimeReport() 
506 509
    {
507 510
      _os << _title << *this << std::endl;
508 511
    }
509 512
  };
510 513
      
511 514
  ///'Do nothing' version of \ref TimeReport
512 515

	
513 516
  ///\sa TimeReport
514 517
  ///
515 518
  class NoTimeReport
516 519
  {
517 520
  public:
518 521
    ///\e
519 522
    NoTimeReport(std::string,std::ostream &,bool) {}
520 523
    ///\e
521 524
    NoTimeReport(std::string,std::ostream &) {}
522 525
    ///\e
523 526
    NoTimeReport(std::string) {}
524 527
    ///\e Do nothing.
525 528
    ~NoTimeReport() {}
526 529

	
527 530
    operator TimeStamp () const { return TimeStamp(); }
528 531
    void reset() {}
529 532
    void start() {}
530 533
    void stop() {}
531 534
    void halt() {} 
532 535
    int running() { return 0; }
533 536
    void restart() {}
534 537
    double userTime() const { return 0; }
535 538
    double systemTime() const { return 0; }
536 539
    double cUserTime() const { return 0; }
537 540
    double cSystemTime() const { return 0; }
538 541
    double realTime() const { return 0; }
539 542
  };
540 543
      
541 544
  ///Tool to measure the running time more exactly.
542 545
  
543 546
  ///This function calls \c f several times and returns the average
544 547
  ///running time. The number of the executions will be choosen in such a way
545 548
  ///that the full real running time will be roughly between \c min_time
546 549
  ///and <tt>2*min_time</tt>.
547 550
  ///\param f the function object to be measured.
548 551
  ///\param min_time the minimum total running time.
549 552
  ///\retval num if it is not \c NULL, then the actual
550 553
  ///        number of execution of \c f will be written into <tt>*num</tt>.
551 554
  ///\retval full_time if it is not \c NULL, then the actual
552 555
  ///        total running time will be written into <tt>*full_time</tt>.
553 556
  ///\return The average running time of \c f.
554 557
  
555 558
  template<class F>
556 559
  TimeStamp runningTimeTest(F f,double min_time=10,unsigned int *num = NULL,
557 560
                            TimeStamp *full_time=NULL)
558 561
  {
559 562
    TimeStamp full;
560 563
    unsigned int total=0;
561 564
    Timer t;
562 565
    for(unsigned int tn=1;tn <= 1U<<31 && full.realTime()<=min_time; tn*=2) {
563 566
      for(;total<tn;total++) f();
564 567
      full=t;
565 568
    }
566 569
    if(num) *num=total;
567 570
    if(full_time) *full_time=full;
568 571
    return full/total;
569 572
  }
570 573
  
571 574
  /// @}  
572 575

	
573 576

	
574 577
} //namespace lemon
575 578

	
576 579
#endif //LEMON_TIME_MEASURE_H
0 comments (0 inline)