src/lemon/graph_to_eps.h
changeset 1178 3c176c65d33b
parent 1164 80bb73097736
child 1180 f772c360b466
     1.1 --- a/src/lemon/graph_to_eps.h	Thu Feb 24 17:48:25 2005 +0000
     1.2 +++ b/src/lemon/graph_to_eps.h	Fri Feb 25 14:50:22 2005 +0000
     1.3 @@ -51,15 +51,117 @@
     1.4    ///Constructor
     1.5    Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
     1.6    ///Returns the red component
     1.7 -  double getR() {return _r;}
     1.8 +
     1.9 +  ///\todo \c red() could be a better name...
    1.10 +  double getR() const {return _r;}
    1.11    ///Returns the green component
    1.12 -  double getG() {return _g;}
    1.13 +  double getG() const {return _g;}
    1.14    ///Returns the blue component
    1.15 -  double getB() {return _b;}
    1.16 +  double getB() const {return _b;}
    1.17    ///Set the color components
    1.18    void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    1.19  };
    1.20 +
    1.21 +///Maps <tt>int</tt>s to different \ref Color "Color"s
    1.22 +
    1.23 +///This map assing one of the predefined \ref Color "Color"s
    1.24 +///to each <tt>int</tt>. It is possible to change the colors as well as their
    1.25 +///number. The integer range is cyclically mapped to the provided set of colors.
    1.26 +///
    1.27 +///This is a true \ref concept::ReferenceMap "reference map", so you can also
    1.28 +///change the actual colors.
    1.29 +
    1.30 +class ColorSet : public MapBase<int,Color>
    1.31 +{
    1.32 +  std::vector<Color> colors;
    1.33 +public:
    1.34 +  ///Constructor
    1.35 +
    1.36 +  ///Constructor
    1.37 +  ///\param have_white indicates wheter white is
    1.38 +  ///amongst the provided color (\c true) or not (\c false). If it is true,
    1.39 +  ///white will be assigned to \c 0.
    1.40 +  ///\param num the number of the allocated colors. If it is \c 0
    1.41 +  ///the default color configuration is set up (26 color plus the while).
    1.42 +  ///If \c num is less then 26/27 then the default color list is cut. Otherwise
    1.43 +  ///the color list is filled repeatedly with the default color list.
    1.44 +  ColorSet(bool have_white=false,int num=0)
    1.45 +  {
    1.46 +    do {
    1.47 +      if(have_white) colors.push_back(Color(1,1,1));
    1.48 +
    1.49 +      colors.push_back(Color(0,0,0));
    1.50 +      colors.push_back(Color(1,0,0));
    1.51 +      colors.push_back(Color(0,1,0));
    1.52 +      colors.push_back(Color(0,0,1));
    1.53 +      colors.push_back(Color(1,1,0));
    1.54 +      colors.push_back(Color(1,0,1));
    1.55 +      colors.push_back(Color(0,1,1));
    1.56 +      
    1.57 +      colors.push_back(Color(.5,0,0));
    1.58 +      colors.push_back(Color(0,.5,0));
    1.59 +      colors.push_back(Color(0,0,.5));
    1.60 +      colors.push_back(Color(.5,.5,0));
    1.61 +      colors.push_back(Color(.5,0,.5));
    1.62 +      colors.push_back(Color(0,.5,.5));
    1.63 +      
    1.64 +      colors.push_back(Color(.5,.5,.5));
    1.65 +      colors.push_back(Color(1,.5,.5));
    1.66 +      colors.push_back(Color(.5,1,.5));
    1.67 +      colors.push_back(Color(.5,.5,1));
    1.68 +      colors.push_back(Color(1,1,.5));
    1.69 +      colors.push_back(Color(1,.5,1));
    1.70 +      colors.push_back(Color(.5,1,1));
    1.71 +      
    1.72 +      colors.push_back(Color(1,.5,0));
    1.73 +      colors.push_back(Color(.5,1,0));
    1.74 +      colors.push_back(Color(1,0,.5));
    1.75 +      colors.push_back(Color(0,1,.5));
    1.76 +      colors.push_back(Color(0,.5,1));
    1.77 +      colors.push_back(Color(.5,0,1));
    1.78 +    } while(int(colors.size())<num);
    1.79 +    //    colors.push_back(Color(1,1,1));
    1.80 +    if(num>0) colors.resize(num);
    1.81 +  }
    1.82 +  ///\e
    1.83 +  Color &operator[](int i)
    1.84 +  {
    1.85 +    return colors[i%colors.size()];
    1.86 +  }
    1.87 +  ///\e
    1.88 +  const Color &operator[](int i) const
    1.89 +  {
    1.90 +    return colors[i%colors.size()];
    1.91 +  }
    1.92 +  ///\e
    1.93 +  void set(int i,const Color &c)
    1.94 +  {
    1.95 +    colors[i%colors.size()]=c;
    1.96 +  }
    1.97 +  ///Sets the number of the exiting colors.
    1.98 +  void resize(int s) { colors.resize(s);}
    1.99 +  ///Returns the munber of the existing colors.
   1.100 +  std::size_t size() { return colors.size();}
   1.101 +};
   1.102 +
   1.103 +///Returns a visible distinct \ref Color
   1.104 +
   1.105 +///Returns a \ref Color which is as different from the given parameter
   1.106 +///as it is possible.
   1.107 +inline Color distantColor(const Color &c) 
   1.108 +{
   1.109 +  return Color(c.getR()<.5?1:0,c.getG()<.5?1:0,c.getB()<.5?1:0);
   1.110 +}
   1.111 +///Returns black for light colors and white for the dark ones.
   1.112 +
   1.113 +///Returns black for light colors and white for the dark ones.
   1.114 +///\todo weighted average would be better
   1.115 +inline Color distantBW(const Color &c){
   1.116 +  double v=(c.getR()+c.getR()+c.getR())<1.5?1:0;
   1.117    
   1.118 +  return Color(v,v,v);
   1.119 +}
   1.120 +
   1.121  ///Default traits class of \ref GraphToEps
   1.122  
   1.123  ///Default traits class of \ref GraphToEps
   1.124 @@ -125,7 +227,11 @@
   1.125  
   1.126    std::string _title;
   1.127    std::string _copyright;
   1.128 -  
   1.129 +
   1.130 +  enum NodeTextColorType 
   1.131 +    { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
   1.132 +  ConstMap<typename Graph::Node,Color > _nodeTextColors;
   1.133 +
   1.134    ///Constructor
   1.135  
   1.136    ///Constructor
   1.137 @@ -149,7 +255,9 @@
   1.138      _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
   1.139      _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
   1.140      _undir(false),
   1.141 -    _pleaseRemoveOsStream(_pros), _scaleToA4(false) {}
   1.142 +    _pleaseRemoveOsStream(_pros), _scaleToA4(false),
   1.143 +    _nodeTextColorType(SAME_COL), _nodeTextColors(Color(0,0,0))
   1.144 +  {}
   1.145  };
   1.146  
   1.147  ///Helper class to implement the named parameters of \ref graphToEps()
   1.148 @@ -223,13 +331,19 @@
   1.149    {
   1.150      return xy<double>(v.y,-v.x);
   1.151    }
   1.152 -  template<class xy>
   1.153 -  static std::string psOut(const xy &p) 
   1.154 +  template<class TT>
   1.155 +  static std::string psOut(const xy<TT> &p) 
   1.156      {
   1.157        std::ostringstream os;	
   1.158        os << p.x << ' ' << p.y;
   1.159        return os.str();
   1.160      }
   1.161 +  static std::string psOut(const Color &c) 
   1.162 +    {
   1.163 +      std::ostringstream os;	
   1.164 +      os << c.getR() << ' ' << c.getG() << ' ' << c.getB();
   1.165 +      return os.str();
   1.166 +    }
   1.167    
   1.168  public:
   1.169    GraphToEps(const T &t) : T(t), dontPrint(false) {};
   1.170 @@ -344,6 +458,22 @@
   1.171      dontPrint=true;
   1.172      return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
   1.173    }
   1.174 +  template<class X> struct NodeTextColorsTraits : public T {
   1.175 +    const X &_nodeTextColors;
   1.176 +    NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
   1.177 +  };
   1.178 +  ///Sets the map of the node text colors
   1.179 +
   1.180 +  ///Sets the map of the node text colors
   1.181 +  ///\param x must be a node map with \ref Color values. 
   1.182 +  template<class X> GraphToEps<NodeTextColorsTraits<X> >
   1.183 +  nodeTextColors(const X &x)
   1.184 +  {
   1.185 +    dontPrint=true;
   1.186 +    _nodeTextColorType=CUST_COL;
   1.187 +    return GraphToEps<NodeTextColorsTraits<X> >
   1.188 +      (NodeTextColorsTraits<X>(*this,x));
   1.189 +  }
   1.190    template<class X> struct EdgeColorsTraits : public T {
   1.191      const X &_edgeColors;
   1.192      EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
   1.193 @@ -435,6 +565,23 @@
   1.194    ///Sets the size of the node texts
   1.195    ///
   1.196    GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
   1.197 +
   1.198 +  ///Sets the color of the node texts to be different from the node color
   1.199 +
   1.200 +  ///Sets the color of the node texts to be as different from the node color
   1.201 +  ///as it is possible
   1.202 +    ///
   1.203 +  GraphToEps<T> &distantColorNodeTexts()
   1.204 +  {_nodeTextColorType=DIST_COL;return *this;}
   1.205 +  ///Sets the color of the node texts to be black or white and always visible.
   1.206 +
   1.207 +  ///Sets the color of the node texts to be black or white according to
   1.208 +  ///which is more 
   1.209 +  ///different from the node color
   1.210 +  ///
   1.211 +  GraphToEps<T> &distantBWNodeTexts()
   1.212 +  {_nodeTextColorType=DIST_BW;return *this;}
   1.213 +
   1.214    ///Gives a preamble block for node Postscript block.
   1.215    
   1.216    ///Gives a preamble block for node Postscript block.
   1.217 @@ -600,7 +747,8 @@
   1.218        if(_enableParallel) {
   1.219  	std::vector<Edge> el;
   1.220  	for(EdgeIt e(g);e!=INVALID;++e)
   1.221 -	  if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
   1.222 +	  if((!_undir||g.source(e)<g.target(e))&&_edgeWidths[e]>0)
   1.223 +	    el.push_back(e);
   1.224  	sort(el.begin(),el.end(),edgeLess(g));
   1.225  	
   1.226  	typename std::vector<Edge>::iterator j;
   1.227 @@ -686,7 +834,7 @@
   1.228  	}
   1.229        }
   1.230        else for(EdgeIt e(g);e!=INVALID;++e)
   1.231 -	if(!_undir||g.source(e)<g.target(e))
   1.232 +	if((!_undir||g.source(e)<g.target(e))&&_edgeWidths[e]>0)
   1.233  	  if(_drawArrows) {
   1.234  	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
   1.235  	    double rn=_nodeSizes[g.target(e)]*_nodeScale;
   1.236 @@ -741,10 +889,23 @@
   1.237        os << "%Node texts:\ngsave\n";
   1.238        os << "/fosi " << _nodeTextSize << " def\n";
   1.239        os << "(Helvetica) findfont fosi scalefont setfont\n";
   1.240 -      os << "0 0 0 setrgbcolor\n";
   1.241 -      for(NodeIt n(g);n!=INVALID;++n)
   1.242 +      for(NodeIt n(g);n!=INVALID;++n) {
   1.243 +	switch(_nodeTextColorType) {
   1.244 +	case DIST_COL:
   1.245 +	  os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
   1.246 +	  break;
   1.247 +	case DIST_BW:
   1.248 +	  os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
   1.249 +	  break;
   1.250 +	case CUST_COL:
   1.251 +	  os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
   1.252 +	  break;
   1.253 +	default:
   1.254 +	  os << "0 0 0 setrgbcolor\n";
   1.255 +	}
   1.256  	os << _coords[n].x << ' ' << _coords[n].y
   1.257  	   << " (" << _nodeTexts[n] << ") cshow\n";
   1.258 +      }
   1.259        os << "grestore\n";
   1.260      }
   1.261      if(_showNodePsText) {
   1.262 @@ -776,7 +937,7 @@
   1.263  ///they are declared as the members of class \ref GraphToEps. The following
   1.264  ///example shows how to use these parameters.
   1.265  ///\code
   1.266 -/// graphToEps(g).scale(10).coords(coords)
   1.267 +/// graphToEps(g,os).scale(10).coords(coords)
   1.268  ///              .nodeScale(2).nodeSizes(sizes)
   1.269  ///              .edgeWidthScale(.4).run();
   1.270  ///\endcode