changeset 1178 | 3c176c65d33b |
parent 1164 | 80bb73097736 |
child 1180 | f772c360b466 |
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. |