gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 2 0
merge default
2 files changed with 26 insertions and 5 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
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
#ifndef WIN32_LEAN_AND_MEAN
32 33
#define WIN32_LEAN_AND_MEAN
34
#endif
35
#ifndef NOMINMAX
33 36
#define NOMINMAX
37
#endif
34 38
#include<windows.h>
35 39
#endif
36 40

	
37 41
#include<lemon/math.h>
38 42
#include<lemon/core.h>
39 43
#include<lemon/dim2.h>
40 44
#include<lemon/maps.h>
41 45
#include<lemon/color.h>
42 46
#include<lemon/bits/bezier.h>
43 47
#include<lemon/error.h>
44 48

	
45 49

	
46 50
///\ingroup eps_io
47 51
///\file
48 52
///\brief A well configurable tool for visualizing graphs
49 53

	
50 54
namespace lemon {
51 55

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

	
65 69
///Default traits class of GraphToEps
66 70

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

	
81 85

	
82 86
  const Graph &g;
83 87

	
84 88
  std::ostream& os;
85 89

	
86 90
  typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
87 91
  CoordsMapType _coords;
88 92
  ConstMap<typename Graph::Node,double > _nodeSizes;
89 93
  ConstMap<typename Graph::Node,int > _nodeShapes;
90 94

	
91 95
  ConstMap<typename Graph::Node,Color > _nodeColors;
92 96
  ConstMap<typename Graph::Arc,Color > _arcColors;
93 97

	
94 98
  ConstMap<typename Graph::Arc,double > _arcWidths;
95 99

	
96 100
  double _arcWidthScale;
97 101

	
98 102
  double _nodeScale;
99 103
  double _xBorder, _yBorder;
100 104
  double _scale;
101 105
  double _nodeBorderQuotient;
102 106

	
103 107
  bool _drawArrows;
104 108
  double _arrowLength, _arrowWidth;
105 109

	
106 110
  bool _showNodes, _showArcs;
107 111

	
108 112
  bool _enableParallel;
109 113
  double _parArcDist;
110 114

	
111 115
  bool _showNodeText;
112 116
  ConstMap<typename Graph::Node,bool > _nodeTexts;
113 117
  double _nodeTextSize;
114 118

	
115 119
  bool _showNodePsText;
116 120
  ConstMap<typename Graph::Node,bool > _nodePsTexts;
117 121
  char *_nodePsTextsPreamble;
118 122

	
119 123
  bool _undirected;
120 124

	
121 125
  bool _pleaseRemoveOsStream;
122 126

	
123 127
  bool _scaleToA4;
124 128

	
125 129
  std::string _title;
126 130
  std::string _copyright;
127 131

	
128 132
  enum NodeTextColorType
129 133
    { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
... ...
@@ -595,204 +599,216 @@
595 599
  GraphToEps<T> &distantColorNodeTexts()
596 600
  {_nodeTextColorType=DIST_COL;return *this;}
597 601
  ///Sets the color of the node texts to be black or white and always visible.
598 602

	
599 603
  ///Sets the color of the node texts to be black or white according to
600 604
  ///which is more different from the node color.
601 605
  GraphToEps<T> &distantBWNodeTexts()
602 606
  {_nodeTextColorType=DIST_BW;return *this;}
603 607

	
604 608
  ///Gives a preamble block for node Postscript block.
605 609

	
606 610
  ///Gives a preamble block for node Postscript block.
607 611
  ///
608 612
  ///\sa nodePsTexts()
609 613
  GraphToEps<T> & nodePsTextsPreamble(const char *str) {
610 614
    _nodePsTextsPreamble=str ;return *this;
611 615
  }
612 616
  ///Sets whether the graph is undirected
613 617

	
614 618
  ///Sets whether the graph is undirected.
615 619
  ///
616 620
  ///This setting is the default for undirected graphs.
617 621
  ///
618 622
  ///\sa directed()
619 623
   GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
620 624

	
621 625
  ///Sets whether the graph is directed
622 626

	
623 627
  ///Sets whether the graph is directed.
624 628
  ///Use it to show the edges as a pair of directed ones.
625 629
  ///
626 630
  ///This setting is the default for digraphs.
627 631
  ///
628 632
  ///\sa undirected()
629 633
  GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
630 634

	
631 635
  ///Sets the title.
632 636

	
633 637
  ///Sets the title of the generated image,
634 638
  ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
635 639
  ///the EPS file.
636 640
  GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
637 641
  ///Sets the copyright statement.
638 642

	
639 643
  ///Sets the copyright statement of the generated image,
640 644
  ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
641 645
  ///the EPS file.
642 646
  GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
643 647

	
644 648
protected:
645 649
  bool isInsideNode(dim2::Point<double> p, double r,int t)
646 650
  {
647 651
    switch(t) {
648 652
    case CIRCLE:
649 653
    case MALE:
650 654
    case FEMALE:
651 655
      return p.normSquare()<=r*r;
652 656
    case SQUARE:
653 657
      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
654 658
    case DIAMOND:
655 659
      return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
656 660
    }
657 661
    return false;
658 662
  }
659 663

	
660 664
public:
661 665
  ~GraphToEps() { }
662 666

	
663 667
  ///Draws the graph.
664 668

	
665 669
  ///Like other functions using
666 670
  ///\ref named-templ-func-param "named template parameters",
667 671
  ///this function calls the algorithm itself, i.e. in this case
668 672
  ///it draws the graph.
669 673
  void run() {
670 674
    const double EPSILON=1e-9;
671 675
    if(dontPrint) return;
672 676

	
673 677
    _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
674 678
      mycoords(_coords,_negY);
675 679

	
676 680
    os << "%!PS-Adobe-2.0 EPSF-2.0\n";
677 681
    if(_title.size()>0) os << "%%Title: " << _title << '\n';
678 682
     if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
679 683
    os << "%%Creator: LEMON, graphToEps()\n";
680 684

	
681 685
    {
682 686
#ifndef WIN32
683 687
      timeval tv;
684 688
      gettimeofday(&tv, 0);
685 689

	
686 690
      char cbuf[26];
687 691
      ctime_r(&tv.tv_sec,cbuf);
688 692
      os << "%%CreationDate: " << cbuf;
689 693
#else
690 694
      SYSTEMTIME time;
691
      char buf1[11], buf2[9], buf3[5];
692

	
693 695
      GetSystemTime(&time);
696
#if defined(_MSC_VER) && (_MSC_VER < 1500)
697
      LPWSTR buf1, buf2, buf3;
694 698
      if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
695
                        "ddd MMM dd", buf1, 11) &&
699
                        L"ddd MMM dd", buf1, 11) &&
696 700
          GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
697
                        "HH':'mm':'ss", buf2, 9) &&
701
                        L"HH':'mm':'ss", buf2, 9) &&
698 702
          GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
699
                                "yyyy", buf3, 5)) {
703
                        L"yyyy", buf3, 5)) {
700 704
        os << "%%CreationDate: " << buf1 << ' '
701 705
           << buf2 << ' ' << buf3 << std::endl;
702 706
      }
707
#else
708
        char buf1[11], buf2[9], buf3[5];
709
        if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
710
                          "ddd MMM dd", buf1, 11) &&
711
            GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
712
                          "HH':'mm':'ss", buf2, 9) &&
713
            GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
714
                          "yyyy", buf3, 5)) {
715
          os << "%%CreationDate: " << buf1 << ' '
716
             << buf2 << ' ' << buf3 << std::endl;
717
        }
718
#endif
703 719
#endif
704 720
    }
705 721

	
706 722
    if (_autoArcWidthScale) {
707 723
      double max_w=0;
708 724
      for(ArcIt e(g);e!=INVALID;++e)
709 725
        max_w=std::max(double(_arcWidths[e]),max_w);
710 726
      if(max_w>EPSILON) {
711 727
        _arcWidthScale/=max_w;
712 728
      }
713 729
    }
714 730

	
715 731
    if (_autoNodeScale) {
716 732
      double max_s=0;
717 733
      for(NodeIt n(g);n!=INVALID;++n)
718 734
        max_s=std::max(double(_nodeSizes[n]),max_s);
719 735
      if(max_s>EPSILON) {
720 736
        _nodeScale/=max_s;
721 737
      }
722 738
    }
723 739

	
724 740
    double diag_len = 1;
725 741
    if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
726 742
      dim2::Box<double> bb;
727 743
      for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
728 744
      if (bb.empty()) {
729 745
        bb = dim2::Box<double>(dim2::Point<double>(0,0));
730 746
      }
731 747
      diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
732 748
      if(diag_len<EPSILON) diag_len = 1;
733 749
      if(!_absoluteNodeSizes) _nodeScale*=diag_len;
734 750
      if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
735 751
    }
736 752

	
737 753
    dim2::Box<double> bb;
738 754
    for(NodeIt n(g);n!=INVALID;++n) {
739 755
      double ns=_nodeSizes[n]*_nodeScale;
740 756
      dim2::Point<double> p(ns,ns);
741 757
      switch(_nodeShapes[n]) {
742 758
      case CIRCLE:
743 759
      case SQUARE:
744 760
      case DIAMOND:
745 761
        bb.add(p+mycoords[n]);
746 762
        bb.add(-p+mycoords[n]);
747 763
        break;
748 764
      case MALE:
749 765
        bb.add(-p+mycoords[n]);
750 766
        bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
751 767
        break;
752 768
      case FEMALE:
753 769
        bb.add(p+mycoords[n]);
754 770
        bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
755 771
        break;
756 772
      }
757 773
    }
758 774
    if (bb.empty()) {
759 775
      bb = dim2::Box<double>(dim2::Point<double>(0,0));
760 776
    }
761 777

	
762 778
    if(_scaleToA4)
763 779
      os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
764 780
    else {
765 781
      if(_preScale) {
766 782
        //Rescale so that BoundingBox won't be neither to big nor too small.
767 783
        while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
768 784
        while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
769 785
      }
770 786

	
771 787
      os << "%%BoundingBox: "
772 788
         << int(floor(bb.left()   * _scale - _xBorder)) << ' '
773 789
         << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
774 790
         << int(ceil(bb.right()  * _scale + _xBorder)) << ' '
775 791
         << int(ceil(bb.top()    * _scale + _yBorder)) << '\n';
776 792
    }
777 793

	
778 794
    os << "%%EndComments\n";
779 795

	
780 796
    //x1 y1 x2 y2 x3 y3 cr cg cb w
781 797
    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
782 798
       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
783 799
    os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke }"
784 800
       << " bind def\n";
785 801
    //x y r
786 802
    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath }"
787 803
       << " bind def\n";
788 804
    //x y r
789 805
    os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
790 806
       << "      2 index 1 index sub 2 index 2 index add lineto\n"
791 807
       << "      2 index 1 index sub 2 index 2 index sub lineto\n"
792 808
       << "      2 index 1 index add 2 index 2 index sub lineto\n"
793 809
       << "      closepath pop pop pop} bind def\n";
794 810
    //x y r
795 811
    os << "/di { newpath 2 index 1 index add 2 index moveto\n"
796 812
       << "      2 index             2 index 2 index add lineto\n"
797 813
       << "      2 index 1 index sub 2 index             lineto\n"
798 814
       << "      2 index             2 index 2 index sub lineto\n"
Ignore white space 192 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
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
#ifndef WIN32_LEAN_AND_MEAN
27 28
#define WIN32_LEAN_AND_MEAN
29
#endif
30
#ifndef NOMINMAX
28 31
#define NOMINMAX
32
#endif
29 33
#include <windows.h>
30 34
#include <cmath>
31 35
#else
36
#include <unistd.h>
32 37
#include <sys/times.h>
33 38
#include <sys/time.h>
34 39
#endif
35 40

	
36 41
#include <string>
37 42
#include <fstream>
38 43
#include <iostream>
39 44

	
40 45
namespace lemon {
41 46

	
42 47
  /// \addtogroup timecount
43 48
  /// @{
44 49

	
45 50
  /// A class to store (cpu)time instances.
46 51

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

	
60 65
  class TimeStamp
61 66
  {
62 67
    double utime;
63 68
    double stime;
64 69
    double cutime;
65 70
    double cstime;
66 71
    double rtime;
67 72

	
68 73
    void _reset() {
69 74
      utime = stime = cutime = cstime = rtime = 0;
70 75
    }
71 76

	
72 77
  public:
73 78

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

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

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

	
97 102
      FILETIME create, exit, kernel, user;
98 103
      if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
99 104
        utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime;
100 105
        stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime;
101 106
        cutime = 0;
102 107
        cstime = 0;
103 108
      } else {
104 109
        rtime = 0;
105 110
        utime = 0;
106 111
        stime = 0;
107 112
        cutime = 0;
108 113
        cstime = 0;
109 114
      }
110 115
#endif
111 116
    }
112 117

	
113 118
    /// Constructor initializing with zero
114 119
    TimeStamp()
115 120
    { _reset(); }
116 121
    ///Constructor initializing with the current time values of the process
117 122
    TimeStamp(void *) { stamp();}
118 123

	
119 124
    ///Set every time value to zero
120 125
    TimeStamp &reset() {_reset();return *this;}
121 126

	
122 127
    ///\e
123 128
    TimeStamp &operator+=(const TimeStamp &b)
124 129
    {
125 130
      utime+=b.utime;
126 131
      stime+=b.stime;
127 132
      cutime+=b.cutime;
0 comments (0 inline)