# HG changeset patch # User alpar # Date 1109343022 0 # Node ID 3c176c65d33b872fe88d2c8debcc75320c7a155b # Parent e41c2907fb49104689d4553ef7b5b00cdd68bb5b - ColorSet become commonly usable - Possility to change the color of a node text (in GraphToEps). diff -r e41c2907fb49 -r 3c176c65d33b src/demo/graph_to_eps_demo.cc --- a/src/demo/graph_to_eps_demo.cc Thu Feb 24 17:48:25 2005 +0000 +++ b/src/demo/graph_to_eps_demo.cc Fri Feb 25 14:50:22 2005 +0000 @@ -23,25 +23,6 @@ using namespace std; using namespace lemon; -class ColorSet : public MapBase -{ -public: - Color operator[](int i) const - { - switch(i%8){ - case 0: return Color(0,0,0); - case 1: return Color(1,0,0); - case 2: return Color(0,1,0); - case 3: return Color(0,0,1); - case 4: return Color(1,1,0); - case 5: return Color(1,0,1); - case 6: return Color(0,1,1); - case 7: return Color(1,1,1); - } - return Color(0,0,0); - } -} colorSet; - class IdMap :public MapBase { const ListGraph &g; @@ -52,6 +33,8 @@ int main() { + ColorSet colorSet; + ListGraph g; typedef ListGraph::Node Node; typedef ListGraph::NodeIt NodeIt; @@ -165,4 +148,27 @@ drawArrows().arrowWidth(1).arrowLength(1). run(); + ListGraph h; + ListGraph::NodeMap hcolors(h); + ListGraph::NodeMap hcoords(h); + + int cols=int(sqrt(double(colorSet.size()))); + for(int i=0;iints to different \ref Color "Color"s + +///This map assing one of the predefined \ref Color "Color"s +///to each int. It is possible to change the colors as well as their +///number. The integer range is cyclically mapped to the provided set of colors. +/// +///This is a true \ref concept::ReferenceMap "reference map", so you can also +///change the actual colors. + +class ColorSet : public MapBase +{ + std::vector colors; +public: + ///Constructor + + ///Constructor + ///\param have_white indicates wheter white is + ///amongst the provided color (\c true) or not (\c false). If it is true, + ///white will be assigned to \c 0. + ///\param num the number of the allocated colors. If it is \c 0 + ///the default color configuration is set up (26 color plus the while). + ///If \c num is less then 26/27 then the default color list is cut. Otherwise + ///the color list is filled repeatedly with the default color list. + ColorSet(bool have_white=false,int num=0) + { + do { + if(have_white) colors.push_back(Color(1,1,1)); + + colors.push_back(Color(0,0,0)); + colors.push_back(Color(1,0,0)); + colors.push_back(Color(0,1,0)); + colors.push_back(Color(0,0,1)); + colors.push_back(Color(1,1,0)); + colors.push_back(Color(1,0,1)); + colors.push_back(Color(0,1,1)); + + colors.push_back(Color(.5,0,0)); + colors.push_back(Color(0,.5,0)); + colors.push_back(Color(0,0,.5)); + colors.push_back(Color(.5,.5,0)); + colors.push_back(Color(.5,0,.5)); + colors.push_back(Color(0,.5,.5)); + + colors.push_back(Color(.5,.5,.5)); + colors.push_back(Color(1,.5,.5)); + colors.push_back(Color(.5,1,.5)); + colors.push_back(Color(.5,.5,1)); + colors.push_back(Color(1,1,.5)); + colors.push_back(Color(1,.5,1)); + colors.push_back(Color(.5,1,1)); + + colors.push_back(Color(1,.5,0)); + colors.push_back(Color(.5,1,0)); + colors.push_back(Color(1,0,.5)); + colors.push_back(Color(0,1,.5)); + colors.push_back(Color(0,.5,1)); + colors.push_back(Color(.5,0,1)); + } while(int(colors.size())0) colors.resize(num); + } + ///\e + Color &operator[](int i) + { + return colors[i%colors.size()]; + } + ///\e + const Color &operator[](int i) const + { + return colors[i%colors.size()]; + } + ///\e + void set(int i,const Color &c) + { + colors[i%colors.size()]=c; + } + ///Sets the number of the exiting colors. + void resize(int s) { colors.resize(s);} + ///Returns the munber of the existing colors. + std::size_t size() { return colors.size();} +}; + +///Returns a visible distinct \ref Color + +///Returns a \ref Color which is as different from the given parameter +///as it is possible. +inline Color distantColor(const Color &c) +{ + return Color(c.getR()<.5?1:0,c.getG()<.5?1:0,c.getB()<.5?1:0); +} +///Returns black for light colors and white for the dark ones. + +///Returns black for light colors and white for the dark ones. +///\todo weighted average would be better +inline Color distantBW(const Color &c){ + double v=(c.getR()+c.getR()+c.getR())<1.5?1:0; + return Color(v,v,v); +} + ///Default traits class of \ref GraphToEps ///Default traits class of \ref GraphToEps @@ -125,7 +227,11 @@ std::string _title; std::string _copyright; - + + enum NodeTextColorType + { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType; + ConstMap _nodeTextColors; + ///Constructor ///Constructor @@ -149,7 +255,9 @@ _showNodeText(false), _nodeTexts(false), _nodeTextSize(1), _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0), _undir(false), - _pleaseRemoveOsStream(_pros), _scaleToA4(false) {} + _pleaseRemoveOsStream(_pros), _scaleToA4(false), + _nodeTextColorType(SAME_COL), _nodeTextColors(Color(0,0,0)) + {} }; ///Helper class to implement the named parameters of \ref graphToEps() @@ -223,13 +331,19 @@ { return xy(v.y,-v.x); } - template - static std::string psOut(const xy &p) + template + static std::string psOut(const xy &p) { std::ostringstream os; os << p.x << ' ' << p.y; return os.str(); } + static std::string psOut(const Color &c) + { + std::ostringstream os; + os << c.getR() << ' ' << c.getG() << ' ' << c.getB(); + return os.str(); + } public: GraphToEps(const T &t) : T(t), dontPrint(false) {}; @@ -344,6 +458,22 @@ dontPrint=true; return GraphToEps >(NodeColorsTraits(*this,x)); } + template struct NodeTextColorsTraits : public T { + const X &_nodeTextColors; + NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {} + }; + ///Sets the map of the node text colors + + ///Sets the map of the node text colors + ///\param x must be a node map with \ref Color values. + template GraphToEps > + nodeTextColors(const X &x) + { + dontPrint=true; + _nodeTextColorType=CUST_COL; + return GraphToEps > + (NodeTextColorsTraits(*this,x)); + } template struct EdgeColorsTraits : public T { const X &_edgeColors; EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {} @@ -435,6 +565,23 @@ ///Sets the size of the node texts /// GraphToEps &nodeTextSize(double d) {_nodeTextSize=d;return *this;} + + ///Sets the color of the node texts to be different from the node color + + ///Sets the color of the node texts to be as different from the node color + ///as it is possible + /// + GraphToEps &distantColorNodeTexts() + {_nodeTextColorType=DIST_COL;return *this;} + ///Sets the color of the node texts to be black or white and always visible. + + ///Sets the color of the node texts to be black or white according to + ///which is more + ///different from the node color + /// + GraphToEps &distantBWNodeTexts() + {_nodeTextColorType=DIST_BW;return *this;} + ///Gives a preamble block for node Postscript block. ///Gives a preamble block for node Postscript block. @@ -600,7 +747,8 @@ if(_enableParallel) { std::vector el; for(EdgeIt e(g);e!=INVALID;++e) - if(!_undir||g.source(e)0) + el.push_back(e); sort(el.begin(),el.end(),edgeLess(g)); typename std::vector::iterator j; @@ -686,7 +834,7 @@ } } else for(EdgeIt e(g);e!=INVALID;++e) - if(!_undir||g.source(e)0) if(_drawArrows) { xy d(_coords[g.target(e)]-_coords[g.source(e)]); double rn=_nodeSizes[g.target(e)]*_nodeScale; @@ -741,10 +889,23 @@ os << "%Node texts:\ngsave\n"; os << "/fosi " << _nodeTextSize << " def\n"; os << "(Helvetica) findfont fosi scalefont setfont\n"; - os << "0 0 0 setrgbcolor\n"; - for(NodeIt n(g);n!=INVALID;++n) + for(NodeIt n(g);n!=INVALID;++n) { + switch(_nodeTextColorType) { + case DIST_COL: + os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n"; + break; + case DIST_BW: + os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n"; + break; + case CUST_COL: + os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n"; + break; + default: + os << "0 0 0 setrgbcolor\n"; + } os << _coords[n].x << ' ' << _coords[n].y << " (" << _nodeTexts[n] << ") cshow\n"; + } os << "grestore\n"; } if(_showNodePsText) { @@ -776,7 +937,7 @@ ///they are declared as the members of class \ref GraphToEps. The following ///example shows how to use these parameters. ///\code -/// graphToEps(g).scale(10).coords(coords) +/// graphToEps(g,os).scale(10).coords(coords) /// .nodeScale(2).nodeSizes(sizes) /// .edgeWidthScale(.4).run(); ///\endcode diff -r e41c2907fb49 -r 3c176c65d33b src/lemon/maps.h --- a/src/lemon/maps.h Thu Feb 24 17:48:25 2005 +0000 +++ b/src/lemon/maps.h Fri Feb 25 14:50:22 2005 +0000 @@ -186,6 +186,49 @@ }; }; + ///Convert the \c Value of a maps to another type. + + ///This \ref concept::ReadMap "read only map" + ///converts the \c Value of a maps to type \c T. + ///Its \c Value is inherited from \c M. + /// + ///Actually, + ///\code + /// ConvertMap sh(x,v); + ///\endcode + ///it is equivalent with + ///\code + /// ConstMap c_tmp(v); + /// AddMap > sh(x,v); + ///\endcode + ///\bug wrong documentation + template + class ConvertMap + { + const M &m; + public: + typedef typename M::Key Key; + typedef T Value; + + ///Constructor + + ///Constructor + ///\param _m is the undelying map + ///\param _v is the convert value + ConvertMap(const M &_m) : m(_m) {}; + Value operator[](Key k) const {return m[k];} + }; + + ///Returns an \ref ConvertMap class + + ///This function just returns an \ref ConvertMap class. + ///\relates ConvertMap + ///\todo The order of the template parameters are changed. + template + inline ConvertMap convertMap(const M &m) + { + return ConvertMap(m); + } ///Sum of two maps