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