1.1 --- a/src/demo/graph_to_eps_demo.cc Thu Feb 24 17:48:25 2005 +0000
1.2 +++ b/src/demo/graph_to_eps_demo.cc Fri Feb 25 14:50:22 2005 +0000
1.3 @@ -23,25 +23,6 @@
1.4 using namespace std;
1.5 using namespace lemon;
1.6
1.7 -class ColorSet : public MapBase<int,Color>
1.8 -{
1.9 -public:
1.10 - Color operator[](int i) const
1.11 - {
1.12 - switch(i%8){
1.13 - case 0: return Color(0,0,0);
1.14 - case 1: return Color(1,0,0);
1.15 - case 2: return Color(0,1,0);
1.16 - case 3: return Color(0,0,1);
1.17 - case 4: return Color(1,1,0);
1.18 - case 5: return Color(1,0,1);
1.19 - case 6: return Color(0,1,1);
1.20 - case 7: return Color(1,1,1);
1.21 - }
1.22 - return Color(0,0,0);
1.23 - }
1.24 -} colorSet;
1.25 -
1.26 class IdMap :public MapBase<ListGraph::Node,int>
1.27 {
1.28 const ListGraph &g;
1.29 @@ -52,6 +33,8 @@
1.30
1.31 int main()
1.32 {
1.33 + ColorSet colorSet;
1.34 +
1.35 ListGraph g;
1.36 typedef ListGraph::Node Node;
1.37 typedef ListGraph::NodeIt NodeIt;
1.38 @@ -165,4 +148,27 @@
1.39 drawArrows().arrowWidth(1).arrowLength(1).
1.40 run();
1.41
1.42 + ListGraph h;
1.43 + ListGraph::NodeMap<int> hcolors(h);
1.44 + ListGraph::NodeMap<Xy> hcoords(h);
1.45 +
1.46 + int cols=int(sqrt(double(colorSet.size())));
1.47 + for(int i=0;i<int(colorSet.size());i++) {
1.48 + Node n=h.addNode();
1.49 + hcoords[n]=Xy(i%cols,i/cols);
1.50 + hcolors[n]=i;
1.51 + }
1.52 +
1.53 + graphToEps(h,"graph_to_eps_demo_out_colors.eps").scale(60).
1.54 + title("Sample .eps figure (parallel edges and arrowheads)").
1.55 + copyright("(C) 2005 LEMON Project").
1.56 + coords(hcoords).
1.57 + nodeScale(.45).
1.58 + distantColorNodeTexts().
1.59 + // distantBWNodeTexts().
1.60 + nodeTexts(hcolors).nodeTextSize(.6).
1.61 + nodeColors(composeMap(colorSet,hcolors)).
1.62 + run();
1.63 +
1.64 +
1.65 }
2.1 --- a/src/lemon/graph_to_eps.h Thu Feb 24 17:48:25 2005 +0000
2.2 +++ b/src/lemon/graph_to_eps.h Fri Feb 25 14:50:22 2005 +0000
2.3 @@ -51,15 +51,117 @@
2.4 ///Constructor
2.5 Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
2.6 ///Returns the red component
2.7 - double getR() {return _r;}
2.8 +
2.9 + ///\todo \c red() could be a better name...
2.10 + double getR() const {return _r;}
2.11 ///Returns the green component
2.12 - double getG() {return _g;}
2.13 + double getG() const {return _g;}
2.14 ///Returns the blue component
2.15 - double getB() {return _b;}
2.16 + double getB() const {return _b;}
2.17 ///Set the color components
2.18 void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
2.19 };
2.20 +
2.21 +///Maps <tt>int</tt>s to different \ref Color "Color"s
2.22 +
2.23 +///This map assing one of the predefined \ref Color "Color"s
2.24 +///to each <tt>int</tt>. It is possible to change the colors as well as their
2.25 +///number. The integer range is cyclically mapped to the provided set of colors.
2.26 +///
2.27 +///This is a true \ref concept::ReferenceMap "reference map", so you can also
2.28 +///change the actual colors.
2.29 +
2.30 +class ColorSet : public MapBase<int,Color>
2.31 +{
2.32 + std::vector<Color> colors;
2.33 +public:
2.34 + ///Constructor
2.35 +
2.36 + ///Constructor
2.37 + ///\param have_white indicates wheter white is
2.38 + ///amongst the provided color (\c true) or not (\c false). If it is true,
2.39 + ///white will be assigned to \c 0.
2.40 + ///\param num the number of the allocated colors. If it is \c 0
2.41 + ///the default color configuration is set up (26 color plus the while).
2.42 + ///If \c num is less then 26/27 then the default color list is cut. Otherwise
2.43 + ///the color list is filled repeatedly with the default color list.
2.44 + ColorSet(bool have_white=false,int num=0)
2.45 + {
2.46 + do {
2.47 + if(have_white) colors.push_back(Color(1,1,1));
2.48 +
2.49 + colors.push_back(Color(0,0,0));
2.50 + colors.push_back(Color(1,0,0));
2.51 + colors.push_back(Color(0,1,0));
2.52 + colors.push_back(Color(0,0,1));
2.53 + colors.push_back(Color(1,1,0));
2.54 + colors.push_back(Color(1,0,1));
2.55 + colors.push_back(Color(0,1,1));
2.56 +
2.57 + colors.push_back(Color(.5,0,0));
2.58 + colors.push_back(Color(0,.5,0));
2.59 + colors.push_back(Color(0,0,.5));
2.60 + colors.push_back(Color(.5,.5,0));
2.61 + colors.push_back(Color(.5,0,.5));
2.62 + colors.push_back(Color(0,.5,.5));
2.63 +
2.64 + colors.push_back(Color(.5,.5,.5));
2.65 + colors.push_back(Color(1,.5,.5));
2.66 + colors.push_back(Color(.5,1,.5));
2.67 + colors.push_back(Color(.5,.5,1));
2.68 + colors.push_back(Color(1,1,.5));
2.69 + colors.push_back(Color(1,.5,1));
2.70 + colors.push_back(Color(.5,1,1));
2.71 +
2.72 + colors.push_back(Color(1,.5,0));
2.73 + colors.push_back(Color(.5,1,0));
2.74 + colors.push_back(Color(1,0,.5));
2.75 + colors.push_back(Color(0,1,.5));
2.76 + colors.push_back(Color(0,.5,1));
2.77 + colors.push_back(Color(.5,0,1));
2.78 + } while(int(colors.size())<num);
2.79 + // colors.push_back(Color(1,1,1));
2.80 + if(num>0) colors.resize(num);
2.81 + }
2.82 + ///\e
2.83 + Color &operator[](int i)
2.84 + {
2.85 + return colors[i%colors.size()];
2.86 + }
2.87 + ///\e
2.88 + const Color &operator[](int i) const
2.89 + {
2.90 + return colors[i%colors.size()];
2.91 + }
2.92 + ///\e
2.93 + void set(int i,const Color &c)
2.94 + {
2.95 + colors[i%colors.size()]=c;
2.96 + }
2.97 + ///Sets the number of the exiting colors.
2.98 + void resize(int s) { colors.resize(s);}
2.99 + ///Returns the munber of the existing colors.
2.100 + std::size_t size() { return colors.size();}
2.101 +};
2.102 +
2.103 +///Returns a visible distinct \ref Color
2.104 +
2.105 +///Returns a \ref Color which is as different from the given parameter
2.106 +///as it is possible.
2.107 +inline Color distantColor(const Color &c)
2.108 +{
2.109 + return Color(c.getR()<.5?1:0,c.getG()<.5?1:0,c.getB()<.5?1:0);
2.110 +}
2.111 +///Returns black for light colors and white for the dark ones.
2.112 +
2.113 +///Returns black for light colors and white for the dark ones.
2.114 +///\todo weighted average would be better
2.115 +inline Color distantBW(const Color &c){
2.116 + double v=(c.getR()+c.getR()+c.getR())<1.5?1:0;
2.117
2.118 + return Color(v,v,v);
2.119 +}
2.120 +
2.121 ///Default traits class of \ref GraphToEps
2.122
2.123 ///Default traits class of \ref GraphToEps
2.124 @@ -125,7 +227,11 @@
2.125
2.126 std::string _title;
2.127 std::string _copyright;
2.128 -
2.129 +
2.130 + enum NodeTextColorType
2.131 + { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
2.132 + ConstMap<typename Graph::Node,Color > _nodeTextColors;
2.133 +
2.134 ///Constructor
2.135
2.136 ///Constructor
2.137 @@ -149,7 +255,9 @@
2.138 _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
2.139 _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
2.140 _undir(false),
2.141 - _pleaseRemoveOsStream(_pros), _scaleToA4(false) {}
2.142 + _pleaseRemoveOsStream(_pros), _scaleToA4(false),
2.143 + _nodeTextColorType(SAME_COL), _nodeTextColors(Color(0,0,0))
2.144 + {}
2.145 };
2.146
2.147 ///Helper class to implement the named parameters of \ref graphToEps()
2.148 @@ -223,13 +331,19 @@
2.149 {
2.150 return xy<double>(v.y,-v.x);
2.151 }
2.152 - template<class xy>
2.153 - static std::string psOut(const xy &p)
2.154 + template<class TT>
2.155 + static std::string psOut(const xy<TT> &p)
2.156 {
2.157 std::ostringstream os;
2.158 os << p.x << ' ' << p.y;
2.159 return os.str();
2.160 }
2.161 + static std::string psOut(const Color &c)
2.162 + {
2.163 + std::ostringstream os;
2.164 + os << c.getR() << ' ' << c.getG() << ' ' << c.getB();
2.165 + return os.str();
2.166 + }
2.167
2.168 public:
2.169 GraphToEps(const T &t) : T(t), dontPrint(false) {};
2.170 @@ -344,6 +458,22 @@
2.171 dontPrint=true;
2.172 return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
2.173 }
2.174 + template<class X> struct NodeTextColorsTraits : public T {
2.175 + const X &_nodeTextColors;
2.176 + NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
2.177 + };
2.178 + ///Sets the map of the node text colors
2.179 +
2.180 + ///Sets the map of the node text colors
2.181 + ///\param x must be a node map with \ref Color values.
2.182 + template<class X> GraphToEps<NodeTextColorsTraits<X> >
2.183 + nodeTextColors(const X &x)
2.184 + {
2.185 + dontPrint=true;
2.186 + _nodeTextColorType=CUST_COL;
2.187 + return GraphToEps<NodeTextColorsTraits<X> >
2.188 + (NodeTextColorsTraits<X>(*this,x));
2.189 + }
2.190 template<class X> struct EdgeColorsTraits : public T {
2.191 const X &_edgeColors;
2.192 EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
2.193 @@ -435,6 +565,23 @@
2.194 ///Sets the size of the node texts
2.195 ///
2.196 GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
2.197 +
2.198 + ///Sets the color of the node texts to be different from the node color
2.199 +
2.200 + ///Sets the color of the node texts to be as different from the node color
2.201 + ///as it is possible
2.202 + ///
2.203 + GraphToEps<T> &distantColorNodeTexts()
2.204 + {_nodeTextColorType=DIST_COL;return *this;}
2.205 + ///Sets the color of the node texts to be black or white and always visible.
2.206 +
2.207 + ///Sets the color of the node texts to be black or white according to
2.208 + ///which is more
2.209 + ///different from the node color
2.210 + ///
2.211 + GraphToEps<T> &distantBWNodeTexts()
2.212 + {_nodeTextColorType=DIST_BW;return *this;}
2.213 +
2.214 ///Gives a preamble block for node Postscript block.
2.215
2.216 ///Gives a preamble block for node Postscript block.
2.217 @@ -600,7 +747,8 @@
2.218 if(_enableParallel) {
2.219 std::vector<Edge> el;
2.220 for(EdgeIt e(g);e!=INVALID;++e)
2.221 - if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
2.222 + if((!_undir||g.source(e)<g.target(e))&&_edgeWidths[e]>0)
2.223 + el.push_back(e);
2.224 sort(el.begin(),el.end(),edgeLess(g));
2.225
2.226 typename std::vector<Edge>::iterator j;
2.227 @@ -686,7 +834,7 @@
2.228 }
2.229 }
2.230 else for(EdgeIt e(g);e!=INVALID;++e)
2.231 - if(!_undir||g.source(e)<g.target(e))
2.232 + if((!_undir||g.source(e)<g.target(e))&&_edgeWidths[e]>0)
2.233 if(_drawArrows) {
2.234 xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
2.235 double rn=_nodeSizes[g.target(e)]*_nodeScale;
2.236 @@ -741,10 +889,23 @@
2.237 os << "%Node texts:\ngsave\n";
2.238 os << "/fosi " << _nodeTextSize << " def\n";
2.239 os << "(Helvetica) findfont fosi scalefont setfont\n";
2.240 - os << "0 0 0 setrgbcolor\n";
2.241 - for(NodeIt n(g);n!=INVALID;++n)
2.242 + for(NodeIt n(g);n!=INVALID;++n) {
2.243 + switch(_nodeTextColorType) {
2.244 + case DIST_COL:
2.245 + os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
2.246 + break;
2.247 + case DIST_BW:
2.248 + os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
2.249 + break;
2.250 + case CUST_COL:
2.251 + os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
2.252 + break;
2.253 + default:
2.254 + os << "0 0 0 setrgbcolor\n";
2.255 + }
2.256 os << _coords[n].x << ' ' << _coords[n].y
2.257 << " (" << _nodeTexts[n] << ") cshow\n";
2.258 + }
2.259 os << "grestore\n";
2.260 }
2.261 if(_showNodePsText) {
2.262 @@ -776,7 +937,7 @@
2.263 ///they are declared as the members of class \ref GraphToEps. The following
2.264 ///example shows how to use these parameters.
2.265 ///\code
2.266 -/// graphToEps(g).scale(10).coords(coords)
2.267 +/// graphToEps(g,os).scale(10).coords(coords)
2.268 /// .nodeScale(2).nodeSizes(sizes)
2.269 /// .edgeWidthScale(.4).run();
2.270 ///\endcode
3.1 --- a/src/lemon/maps.h Thu Feb 24 17:48:25 2005 +0000
3.2 +++ b/src/lemon/maps.h Fri Feb 25 14:50:22 2005 +0000
3.3 @@ -186,6 +186,49 @@
3.4 };
3.5 };
3.6
3.7 + ///Convert the \c Value of a maps to another type.
3.8 +
3.9 + ///This \ref concept::ReadMap "read only map"
3.10 + ///converts the \c Value of a maps to type \c T.
3.11 + ///Its \c Value is inherited from \c M.
3.12 + ///
3.13 + ///Actually,
3.14 + ///\code
3.15 + /// ConvertMap<X> sh(x,v);
3.16 + ///\endcode
3.17 + ///it is equivalent with
3.18 + ///\code
3.19 + /// ConstMap<X::Key, X::Value> c_tmp(v);
3.20 + /// AddMap<X, ConstMap<X::Key, X::Value> > sh(x,v);
3.21 + ///\endcode
3.22 + ///\bug wrong documentation
3.23 + template<class M, class T>
3.24 + class ConvertMap
3.25 + {
3.26 + const M &m;
3.27 + public:
3.28 + typedef typename M::Key Key;
3.29 + typedef T Value;
3.30 +
3.31 + ///Constructor
3.32 +
3.33 + ///Constructor
3.34 + ///\param _m is the undelying map
3.35 + ///\param _v is the convert value
3.36 + ConvertMap(const M &_m) : m(_m) {};
3.37 + Value operator[](Key k) const {return m[k];}
3.38 + };
3.39 +
3.40 + ///Returns an \ref ConvertMap class
3.41 +
3.42 + ///This function just returns an \ref ConvertMap class.
3.43 + ///\relates ConvertMap
3.44 + ///\todo The order of the template parameters are changed.
3.45 + template<class T, class M>
3.46 + inline ConvertMap<M,T> convertMap(const M &m)
3.47 + {
3.48 + return ConvertMap<M,T>(m);
3.49 + }
3.50
3.51 ///Sum of two maps
3.52