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 27 insertions and 34 deletions:
↑ Collapse diff ↑
Ignore white space 24 line context
... ...
@@ -102,32 +102,32 @@
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));
... ...
@@ -164,37 +164,37 @@
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;
Ignore white space 24 line context
... ...
@@ -34,27 +34,25 @@
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) {}
... ...
@@ -163,34 +161,27 @@
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;
... ...
@@ -360,25 +351,25 @@
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
  };
... ...
@@ -402,26 +393,24 @@
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

	
... ...
@@ -512,31 +501,29 @@
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

	
... ...
@@ -569,47 +556,47 @@
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
  
... ...
@@ -653,46 +640,52 @@
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
  ///
667
  GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
654
  ///This setting is the default for undirected graphs.
655
  ///
656
  ///\sa directed()
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;
... ...
@@ -700,28 +693,28 @@
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
    
... ...
@@ -921,25 +914,25 @@
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) {
0 comments (0 inline)