src/lemon/graph_to_eps.h
changeset 1178 3c176c65d33b
parent 1164 80bb73097736
child 1180 f772c360b466
equal deleted inserted replaced
10:718d40cdad63 11:d5f5a09e1e0b
    49   ///Default constructor
    49   ///Default constructor
    50   Color() {}
    50   Color() {}
    51   ///Constructor
    51   ///Constructor
    52   Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
    52   Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
    53   ///Returns the red component
    53   ///Returns the red component
    54   double getR() {return _r;}
    54 
       
    55   ///\todo \c red() could be a better name...
       
    56   double getR() const {return _r;}
    55   ///Returns the green component
    57   ///Returns the green component
    56   double getG() {return _g;}
    58   double getG() const {return _g;}
    57   ///Returns the blue component
    59   ///Returns the blue component
    58   double getB() {return _b;}
    60   double getB() const {return _b;}
    59   ///Set the color components
    61   ///Set the color components
    60   void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    62   void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    61 };
    63 };
    62   
    64 
       
    65 ///Maps <tt>int</tt>s to different \ref Color "Color"s
       
    66 
       
    67 ///This map assing one of the predefined \ref Color "Color"s
       
    68 ///to each <tt>int</tt>. It is possible to change the colors as well as their
       
    69 ///number. The integer range is cyclically mapped to the provided set of colors.
       
    70 ///
       
    71 ///This is a true \ref concept::ReferenceMap "reference map", so you can also
       
    72 ///change the actual colors.
       
    73 
       
    74 class ColorSet : public MapBase<int,Color>
       
    75 {
       
    76   std::vector<Color> colors;
       
    77 public:
       
    78   ///Constructor
       
    79 
       
    80   ///Constructor
       
    81   ///\param have_white indicates wheter white is
       
    82   ///amongst the provided color (\c true) or not (\c false). If it is true,
       
    83   ///white will be assigned to \c 0.
       
    84   ///\param num the number of the allocated colors. If it is \c 0
       
    85   ///the default color configuration is set up (26 color plus the while).
       
    86   ///If \c num is less then 26/27 then the default color list is cut. Otherwise
       
    87   ///the color list is filled repeatedly with the default color list.
       
    88   ColorSet(bool have_white=false,int num=0)
       
    89   {
       
    90     do {
       
    91       if(have_white) colors.push_back(Color(1,1,1));
       
    92 
       
    93       colors.push_back(Color(0,0,0));
       
    94       colors.push_back(Color(1,0,0));
       
    95       colors.push_back(Color(0,1,0));
       
    96       colors.push_back(Color(0,0,1));
       
    97       colors.push_back(Color(1,1,0));
       
    98       colors.push_back(Color(1,0,1));
       
    99       colors.push_back(Color(0,1,1));
       
   100       
       
   101       colors.push_back(Color(.5,0,0));
       
   102       colors.push_back(Color(0,.5,0));
       
   103       colors.push_back(Color(0,0,.5));
       
   104       colors.push_back(Color(.5,.5,0));
       
   105       colors.push_back(Color(.5,0,.5));
       
   106       colors.push_back(Color(0,.5,.5));
       
   107       
       
   108       colors.push_back(Color(.5,.5,.5));
       
   109       colors.push_back(Color(1,.5,.5));
       
   110       colors.push_back(Color(.5,1,.5));
       
   111       colors.push_back(Color(.5,.5,1));
       
   112       colors.push_back(Color(1,1,.5));
       
   113       colors.push_back(Color(1,.5,1));
       
   114       colors.push_back(Color(.5,1,1));
       
   115       
       
   116       colors.push_back(Color(1,.5,0));
       
   117       colors.push_back(Color(.5,1,0));
       
   118       colors.push_back(Color(1,0,.5));
       
   119       colors.push_back(Color(0,1,.5));
       
   120       colors.push_back(Color(0,.5,1));
       
   121       colors.push_back(Color(.5,0,1));
       
   122     } while(int(colors.size())<num);
       
   123     //    colors.push_back(Color(1,1,1));
       
   124     if(num>0) colors.resize(num);
       
   125   }
       
   126   ///\e
       
   127   Color &operator[](int i)
       
   128   {
       
   129     return colors[i%colors.size()];
       
   130   }
       
   131   ///\e
       
   132   const Color &operator[](int i) const
       
   133   {
       
   134     return colors[i%colors.size()];
       
   135   }
       
   136   ///\e
       
   137   void set(int i,const Color &c)
       
   138   {
       
   139     colors[i%colors.size()]=c;
       
   140   }
       
   141   ///Sets the number of the exiting colors.
       
   142   void resize(int s) { colors.resize(s);}
       
   143   ///Returns the munber of the existing colors.
       
   144   std::size_t size() { return colors.size();}
       
   145 };
       
   146 
       
   147 ///Returns a visible distinct \ref Color
       
   148 
       
   149 ///Returns a \ref Color which is as different from the given parameter
       
   150 ///as it is possible.
       
   151 inline Color distantColor(const Color &c) 
       
   152 {
       
   153   return Color(c.getR()<.5?1:0,c.getG()<.5?1:0,c.getB()<.5?1:0);
       
   154 }
       
   155 ///Returns black for light colors and white for the dark ones.
       
   156 
       
   157 ///Returns black for light colors and white for the dark ones.
       
   158 ///\todo weighted average would be better
       
   159 inline Color distantBW(const Color &c){
       
   160   double v=(c.getR()+c.getR()+c.getR())<1.5?1:0;
       
   161   
       
   162   return Color(v,v,v);
       
   163 }
       
   164 
    63 ///Default traits class of \ref GraphToEps
   165 ///Default traits class of \ref GraphToEps
    64 
   166 
    65 ///Default traits class of \ref GraphToEps
   167 ///Default traits class of \ref GraphToEps
    66 ///
   168 ///
    67 ///\c G is the type of the underlying graph.
   169 ///\c G is the type of the underlying graph.
   123 
   225 
   124   bool _scaleToA4;
   226   bool _scaleToA4;
   125 
   227 
   126   std::string _title;
   228   std::string _title;
   127   std::string _copyright;
   229   std::string _copyright;
   128   
   230 
       
   231   enum NodeTextColorType 
       
   232     { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
       
   233   ConstMap<typename Graph::Node,Color > _nodeTextColors;
       
   234 
   129   ///Constructor
   235   ///Constructor
   130 
   236 
   131   ///Constructor
   237   ///Constructor
   132   ///\param _g is a reference to the graph to be printed
   238   ///\param _g is a reference to the graph to be printed
   133   ///\param _os is a reference to the output stream.
   239   ///\param _os is a reference to the output stream.
   147     _showNodes(true), _showEdges(true),
   253     _showNodes(true), _showEdges(true),
   148     _enableParallel(false), _parEdgeDist(1),
   254     _enableParallel(false), _parEdgeDist(1),
   149     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
   255     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
   150     _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
   256     _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
   151     _undir(false),
   257     _undir(false),
   152     _pleaseRemoveOsStream(_pros), _scaleToA4(false) {}
   258     _pleaseRemoveOsStream(_pros), _scaleToA4(false),
       
   259     _nodeTextColorType(SAME_COL), _nodeTextColors(Color(0,0,0))
       
   260   {}
   153 };
   261 };
   154 
   262 
   155 ///Helper class to implement the named parameters of \ref graphToEps()
   263 ///Helper class to implement the named parameters of \ref graphToEps()
   156 
   264 
   157 ///Helper class to implement the named parameters of \ref graphToEps()
   265 ///Helper class to implement the named parameters of \ref graphToEps()
   221   }
   329   }
   222   static xy<double> rot(xy<double> v) 
   330   static xy<double> rot(xy<double> v) 
   223   {
   331   {
   224     return xy<double>(v.y,-v.x);
   332     return xy<double>(v.y,-v.x);
   225   }
   333   }
   226   template<class xy>
   334   template<class TT>
   227   static std::string psOut(const xy &p) 
   335   static std::string psOut(const xy<TT> &p) 
   228     {
   336     {
   229       std::ostringstream os;	
   337       std::ostringstream os;	
   230       os << p.x << ' ' << p.y;
   338       os << p.x << ' ' << p.y;
       
   339       return os.str();
       
   340     }
       
   341   static std::string psOut(const Color &c) 
       
   342     {
       
   343       std::ostringstream os;	
       
   344       os << c.getR() << ' ' << c.getG() << ' ' << c.getB();
   231       return os.str();
   345       return os.str();
   232     }
   346     }
   233   
   347   
   234 public:
   348 public:
   235   GraphToEps(const T &t) : T(t), dontPrint(false) {};
   349   GraphToEps(const T &t) : T(t), dontPrint(false) {};
   342   nodeColors(const X &x)
   456   nodeColors(const X &x)
   343   {
   457   {
   344     dontPrint=true;
   458     dontPrint=true;
   345     return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
   459     return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
   346   }
   460   }
       
   461   template<class X> struct NodeTextColorsTraits : public T {
       
   462     const X &_nodeTextColors;
       
   463     NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
       
   464   };
       
   465   ///Sets the map of the node text colors
       
   466 
       
   467   ///Sets the map of the node text colors
       
   468   ///\param x must be a node map with \ref Color values. 
       
   469   template<class X> GraphToEps<NodeTextColorsTraits<X> >
       
   470   nodeTextColors(const X &x)
       
   471   {
       
   472     dontPrint=true;
       
   473     _nodeTextColorType=CUST_COL;
       
   474     return GraphToEps<NodeTextColorsTraits<X> >
       
   475       (NodeTextColorsTraits<X>(*this,x));
       
   476   }
   347   template<class X> struct EdgeColorsTraits : public T {
   477   template<class X> struct EdgeColorsTraits : public T {
   348     const X &_edgeColors;
   478     const X &_edgeColors;
   349     EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
   479     EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
   350   };
   480   };
   351   ///Sets the map of the edge colors
   481   ///Sets the map of the edge colors
   433   ///Sets the size of the node texts
   563   ///Sets the size of the node texts
   434   
   564   
   435   ///Sets the size of the node texts
   565   ///Sets the size of the node texts
   436   ///
   566   ///
   437   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
   567   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
       
   568 
       
   569   ///Sets the color of the node texts to be different from the node color
       
   570 
       
   571   ///Sets the color of the node texts to be as different from the node color
       
   572   ///as it is possible
       
   573     ///
       
   574   GraphToEps<T> &distantColorNodeTexts()
       
   575   {_nodeTextColorType=DIST_COL;return *this;}
       
   576   ///Sets the color of the node texts to be black or white and always visible.
       
   577 
       
   578   ///Sets the color of the node texts to be black or white according to
       
   579   ///which is more 
       
   580   ///different from the node color
       
   581   ///
       
   582   GraphToEps<T> &distantBWNodeTexts()
       
   583   {_nodeTextColorType=DIST_BW;return *this;}
       
   584 
   438   ///Gives a preamble block for node Postscript block.
   585   ///Gives a preamble block for node Postscript block.
   439   
   586   
   440   ///Gives a preamble block for node Postscript block.
   587   ///Gives a preamble block for node Postscript block.
   441   ///
   588   ///
   442   ///\sa nodePsTexts()
   589   ///\sa nodePsTexts()
   598     if(_showEdges) {
   745     if(_showEdges) {
   599       os << "%Edges:\ngsave\n";      
   746       os << "%Edges:\ngsave\n";      
   600       if(_enableParallel) {
   747       if(_enableParallel) {
   601 	std::vector<Edge> el;
   748 	std::vector<Edge> el;
   602 	for(EdgeIt e(g);e!=INVALID;++e)
   749 	for(EdgeIt e(g);e!=INVALID;++e)
   603 	  if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
   750 	  if((!_undir||g.source(e)<g.target(e))&&_edgeWidths[e]>0)
       
   751 	    el.push_back(e);
   604 	sort(el.begin(),el.end(),edgeLess(g));
   752 	sort(el.begin(),el.end(),edgeLess(g));
   605 	
   753 	
   606 	typename std::vector<Edge>::iterator j;
   754 	typename std::vector<Edge>::iterator j;
   607 	for(typename std::vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
   755 	for(typename std::vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
   608 	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
   756 	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
   684 	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
   832 	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
   685 	  }
   833 	  }
   686 	}
   834 	}
   687       }
   835       }
   688       else for(EdgeIt e(g);e!=INVALID;++e)
   836       else for(EdgeIt e(g);e!=INVALID;++e)
   689 	if(!_undir||g.source(e)<g.target(e))
   837 	if((!_undir||g.source(e)<g.target(e))&&_edgeWidths[e]>0)
   690 	  if(_drawArrows) {
   838 	  if(_drawArrows) {
   691 	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   839 	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   692 	    double rn=_nodeSizes[g.target(e)]*_nodeScale;
   840 	    double rn=_nodeSizes[g.target(e)]*_nodeScale;
   693 	    int node_shape=_nodeShapes[g.target(e)];
   841 	    int node_shape=_nodeShapes[g.target(e)];
   694 	    double t1=0,t2=1;
   842 	    double t1=0,t2=1;
   739     }
   887     }
   740     if(_showNodeText) {
   888     if(_showNodeText) {
   741       os << "%Node texts:\ngsave\n";
   889       os << "%Node texts:\ngsave\n";
   742       os << "/fosi " << _nodeTextSize << " def\n";
   890       os << "/fosi " << _nodeTextSize << " def\n";
   743       os << "(Helvetica) findfont fosi scalefont setfont\n";
   891       os << "(Helvetica) findfont fosi scalefont setfont\n";
   744       os << "0 0 0 setrgbcolor\n";
   892       for(NodeIt n(g);n!=INVALID;++n) {
   745       for(NodeIt n(g);n!=INVALID;++n)
   893 	switch(_nodeTextColorType) {
       
   894 	case DIST_COL:
       
   895 	  os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
       
   896 	  break;
       
   897 	case DIST_BW:
       
   898 	  os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
       
   899 	  break;
       
   900 	case CUST_COL:
       
   901 	  os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
       
   902 	  break;
       
   903 	default:
       
   904 	  os << "0 0 0 setrgbcolor\n";
       
   905 	}
   746 	os << _coords[n].x << ' ' << _coords[n].y
   906 	os << _coords[n].x << ' ' << _coords[n].y
   747 	   << " (" << _nodeTexts[n] << ") cshow\n";
   907 	   << " (" << _nodeTexts[n] << ") cshow\n";
       
   908       }
   748       os << "grestore\n";
   909       os << "grestore\n";
   749     }
   910     }
   750     if(_showNodePsText) {
   911     if(_showNodePsText) {
   751       os << "%Node PS blocks:\ngsave\n";
   912       os << "%Node PS blocks:\ngsave\n";
   752       for(NodeIt n(g);n!=INVALID;++n)
   913       for(NodeIt n(g);n!=INVALID;++n)
   774 ///This function also has a lot of
   935 ///This function also has a lot of
   775 ///\ref named-templ-func-param "named parameters",
   936 ///\ref named-templ-func-param "named parameters",
   776 ///they are declared as the members of class \ref GraphToEps. The following
   937 ///they are declared as the members of class \ref GraphToEps. The following
   777 ///example shows how to use these parameters.
   938 ///example shows how to use these parameters.
   778 ///\code
   939 ///\code
   779 /// graphToEps(g).scale(10).coords(coords)
   940 /// graphToEps(g,os).scale(10).coords(coords)
   780 ///              .nodeScale(2).nodeSizes(sizes)
   941 ///              .nodeScale(2).nodeSizes(sizes)
   781 ///              .edgeWidthScale(.4).run();
   942 ///              .edgeWidthScale(.4).run();
   782 ///\endcode
   943 ///\endcode
   783 ///\warning Don't forget to put the \ref GraphToEps::run() "run()"
   944 ///\warning Don't forget to put the \ref GraphToEps::run() "run()"
   784 ///to the end of the parameter list.
   945 ///to the end of the parameter list.