gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Several doc improvements + new default parameter values * * * Several minor improvements in graph_to_eps.h * * * Several minor improvements in graph_to_eps.h
0 2 0
default
2 files changed with 25 insertions and 32 deletions:
↑ Collapse diff ↑
Show white space 48 line context
... ...
@@ -90,56 +90,56 @@
90 90
  /// Dark yellow color constant
91 91
  extern const Color DARK_YELLOW;
92 92
  /// Dark magenta color constant
93 93
  extern const Color DARK_MAGENTA;
94 94
  /// Dark cyan color constant
95 95
  extern const Color DARK_CYAN;
96 96

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

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

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

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

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

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

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

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

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

	
203 203
  /// @}
204 204

	
205 205
} //END OF NAMESPACE LEMON
206 206

	
207 207
#endif // LEMON_COLOR_H
Show white space 48 line context
... ...
@@ -22,51 +22,49 @@
22 22
#include <sys/time.h>
23 23

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

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

	
34 34
#include<ctime>
35 35

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

	
43 43

	
44 44
///\ingroup eps_io
45 45
///\file
46
///\brief Simple graph drawer
47
///
48
///\author Alpar Juttner
46
///\brief A well configurable tool for visualizing graphs
49 47

	
50 48
namespace lemon {
51 49

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

	
67 65
///Default traits class of \ref GraphToEps
68 66
///
69 67
///\c G is the type of the underlying graph.
70 68
template<class G>
71 69
struct DefaultGraphToEpsTraits
72 70
{
... ...
@@ -151,58 +149,51 @@
151 149
			  bool _pros=false) :
152 150
    g(_g), os(_os),
153 151
    _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
154 152
    _nodeColors(WHITE), _arcColors(BLACK),
155 153
    _arcWidths(1.0), _arcWidthScale(0.003),
156 154
    _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
157 155
    _nodeBorderQuotient(.1),
158 156
    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
159 157
    _showNodes(true), _showArcs(true),
160 158
    _enableParallel(false), _parArcDist(1),
161 159
    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
162 160
    _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
163 161
    _undirected(lemon::UndirectedTagIndicator<G>::value),
164 162
    _pleaseRemoveOsStream(_pros), _scaleToA4(false),
165 163
    _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
166 164
    _autoNodeScale(false),
167 165
    _autoArcWidthScale(false),
168 166
    _absoluteNodeSizes(false),
169 167
    _absoluteArcWidths(false),
170 168
    _negY(false),
171 169
    _preScale(true)
172 170
  {}
173 171
};
174 172

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

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

	
191 182
  using T::_coords;
192 183
  using T::_nodeSizes;
193 184
  using T::_nodeShapes;
194 185
  using T::_nodeColors;
195 186
  using T::_arcColors;
196 187
  using T::_arcWidths;
197 188

	
198 189
  using T::_arcWidthScale;
199 190
  using T::_nodeScale;
200 191
  using T::_xBorder;
201 192
  using T::_yBorder;
202 193
  using T::_scale;
203 194
  using T::_nodeBorderQuotient;
204 195
  
205 196
  using T::_drawArrows;
206 197
  using T::_arrowLength;
207 198
  using T::_arrowWidth;
208 199
  
... ...
@@ -348,92 +339,90 @@
348 339
  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
349 340
    dontPrint=true;
350 341
    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
351 342
  }
352 343
  template<class X> struct NodeSizesTraits : public T {
353 344
    const X &_nodeSizes;
354 345
    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
355 346
  };
356 347
  ///Sets the map of the node sizes
357 348

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

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

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

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

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

	
436 425
  template<class X> struct NodeColorsTraits : public T {
437 426
    const X &_nodeColors;
438 427
    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
439 428
  };
... ...
@@ -500,55 +489,53 @@
500 489
  ///Turns on/off the automatic node width scaling.
501 490

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

	
510 499
  ///Turns on/off the absolutematic node width scaling.
511 500

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

	
520 509
  ///Negates the Y coordinates.
521 510

	
522 511
  ///Negates the Y coordinates.
523 512
  ///
524
  ///\todo More docs.
525
  ///
526 513
  GraphToEps<T> &negateY(bool b=true) {
527 514
    _negY=b;return *this;
528 515
  }
529 516

	
530
  ///Turn on/off prescaling
517
  ///Turn on/off pre-scaling
531 518

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

	
541 528
  ///Sets a global scale factor for arc widths
542 529

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

	
... ...
@@ -557,71 +544,71 @@
557 544
  ///\sa arcWidthScale()
558 545
  ///
559 546
  GraphToEps<T> &autoArcWidthScale(bool b=true) {
560 547
    _autoArcWidthScale=b;return *this;
561 548
  }
562 549
  ///Turns on/off the absolutematic arc width scaling.
563 550

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

	
573 560
  ///Sets a global scale factor for the whole picture
574 561
  ///
575 562

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

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

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

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

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

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

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

	
613 600
  ///Enables parallel arcs
614 601
  GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
615 602
  
616 603
  ///Sets the distance 
617 604
  
618 605
  ///Sets the distance 
619 606
  ///
620 607
  GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
621 608
  
622 609
  ///Hides the arcs
623 610
  
624 611
  ///Hides the arcs
625 612
  ///
626 613
  GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
627 614
  ///Hides the nodes
... ...
@@ -641,99 +628,105 @@
641 628
  ///Sets the color of the node texts to be as different from the node color
642 629
  ///as it is possible
643 630
  ///
644 631
  GraphToEps<T> &distantColorNodeTexts()
645 632
  {_nodeTextColorType=DIST_COL;return *this;}
646 633
  ///Sets the color of the node texts to be black or white and always visible.
647 634

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

	
655 642
  ///Gives a preamble block for node Postscript block.
656 643
  
657 644
  ///Gives a preamble block for node Postscript block.
658 645
  ///
659 646
  ///\sa nodePsTexts()
660 647
  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
661 648
    _nodePsTextsPreamble=str ;return *this;
662 649
  }
663 650
  ///Sets whether the the graph is undirected
664 651

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

	
669 659
  ///Sets whether the the graph is directed
670 660

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

	
675 669
  ///Sets the title.
676 670

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

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

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

	
705 698
public:
706 699
  ~GraphToEps() { }
707 700
  
708 701
  ///Draws the graph.
709 702

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

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

	
736 729
    if (_autoArcWidthScale) {
737 730
      double max_w=0;
738 731
      for(ArcIt e(g);e!=INVALID;++e)
739 732
	max_w=std::max(double(_arcWidths[e]),max_w);
... ...
@@ -909,49 +902,49 @@
909 902
    else if(_scale!=1.0) os << _scale << " dup scale\n";
910 903
    
911 904
    if(_showArcs) {
912 905
      os << "%Arcs:\ngsave\n";      
913 906
      if(_enableParallel) {
914 907
	std::vector<Arc> el;
915 908
	for(ArcIt e(g);e!=INVALID;++e)
916 909
	  if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
917 910
	     &&g.source(e)!=g.target(e))
918 911
	    el.push_back(e);
919 912
	std::sort(el.begin(),el.end(),arcLess(g));
920 913
	
921 914
	typename std::vector<Arc>::iterator j;
922 915
	for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
923 916
	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
924 917

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

	
938 931
//  	  m=dim2::Point<double>(mycoords[g.source(*i)])+
939 932
// 	    dvec*(double(_nodeSizes[g.source(*i)])/
940 933
// 	       (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
941 934

	
942 935
 	  m=dim2::Point<double>(mycoords[g.source(*i)])+
943 936
	    d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
944 937

	
945 938
	  for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
946 939
	    sw+=_arcWidths[*e]*_arcWidthScale/2.0;
947 940
	    dim2::Point<double> mm=m+rot90(d)*sw/.75;
948 941
	    if(_drawArrows) {
949 942
	      int node_shape;
950 943
	      dim2::Point<double> s=mycoords[g.source(*e)];
951 944
	      dim2::Point<double> t=mycoords[g.target(*e)];
952 945
	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
953 946
	      node_shape=_nodeShapes[g.target(*e)];
954 947
	      dim2::Bezier3 bez(s,mm,mm,t);
955 948
	      double t1=0,t2=1;
956 949
	      for(int ii=0;ii<INTERPOL_PREC;++ii)
957 950
		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
0 comments (0 inline)