Changeset 1050:bcc0766a7b86 in lemon-0.x
- Timestamp:
- 01/04/05 23:16:46 (20 years ago)
- Branch:
- default
- Phase:
- public
- Convert:
- svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1444
- Location:
- src/work
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
src/work/Doxyfile
r1006 r1050 408 408 marci/max_bipartite_matching.h \ 409 409 marci/bipartite_graph_wrapper.h \ 410 alpar/graph_to_eps.cc \ 410 411 deba \ 411 412 -
src/work/alpar/graph_to_eps.cc
r1047 r1050 1 #include<math.h> 1 2 #include<lemon/xy.h> 2 3 #include<lemon/maps.h> 3 4 #include<lemon/list_graph.h> 4 5 5 ///\file 6 7 ///\file \ingroup misc 6 8 ///Simple graph drawer 7 9 8 10 namespace lemon { 9 11 10 ///\e 12 ///Data structure representing RGB colors. 13 14 ///Data structure representing RGB colors. 15 ///\ingroup misc 11 16 class Color 12 17 { 13 18 double _r,_g,_b; 14 19 public: 15 /// \e20 ///Default constructor 16 21 Color() {} 17 /// \e22 ///Constructor 18 23 Color(double r,double g,double b) :_r(r),_g(g),_b(b) {}; 19 /// \e24 ///Returns the red component 20 25 double getR() {return _r;} 21 /// \e26 ///Returns the green component 22 27 double getG() {return _g;} 23 /// \e28 ///Returns the blue component 24 29 double getB() {return _b;} 25 /// \e30 ///Set the color components 26 31 void set(double r,double g,double b) { _r=r;_g=g;_b=b; }; 27 32 }; 28 33 29 ///\e 34 ///Default traits class of \ref GraphToEps 35 36 ///Default traits class of \ref GraphToEps 37 /// 38 ///\c G is the type of the underlying graph. 30 39 template<class G> 31 40 struct DefaultGraphToEpsTraits … … 41 50 42 51 const Graph &g; 43 ConstMap<typename Graph::Node,xy<double> > coords; 44 ConstMap<typename Graph::Node,double > nodeSizes; 45 46 ConstMap<typename Graph::Node,Color > nodeColors; 47 ConstMap<typename Graph::Edge,Color > edgeColors; 48 double nodeSizeScalar; 49 double xBorder, yBorder; 50 51 DefaultGraphToEpsTraits(G &_g) : 52 g(_g), coords(xy<double>(1,1)), nodeSizes(1.0), 53 nodeColors(Color(1,1,1)), edgeColors(Color(0,0,0)), 54 nodeSizeScalar(1.0), xBorder(10), yBorder(10) {} 52 ConstMap<typename Graph::Node,xy<double> > _coords; 53 ConstMap<typename Graph::Node,double > _nodeSizes; 54 55 ConstMap<typename Graph::Node,Color > _nodeColors; 56 ConstMap<typename Graph::Edge,Color > _edgeColors; 57 58 ConstMap<typename Graph::Edge,double > _edgeWidths; 59 60 double _edgeWidthScale; 61 62 double _nodeScale; 63 double _xBorder, _yBorder; 64 double _scale; 65 double _nodeBorderQuotient; 66 67 bool _drawArrows; 68 double _arrowLength, _arrowWidth; 69 70 ///Constructor 71 72 ///Constructor 73 ///\param _g is a reference to the underlying graph 74 DefaultGraphToEpsTraits(const G &_g) : 75 g(_g), _coords(xy<double>(1,1)), _nodeSizes(1.0), 76 _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), 77 _edgeWidths(1), _edgeWidthScale(0.3), 78 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), 79 _nodeBorderQuotient(.1), 80 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3) {} 55 81 }; 56 82 57 ///\e 83 ///Helper class to implement the named parameters of \ref graphToEps() 84 85 ///Helper class to implement the named parameters of \ref graphToEps() 86 ///\todo Is 'helper class' a good name for this? 87 /// 58 88 template<class T> class GraphToEps : public T 59 89 { … … 71 101 GraphToEps(const T &t) : T(t), dontPrint(false) {}; 72 102 73 template<class X> struct SetCoordsTraits : public T { 74 const X &coords; 75 SetCoordsTraits(const T &t,const X &x) : T(t), coords(x) {} 76 }; 77 ///\e 78 template<class X> GraphToEps<SetCoordsTraits<X> > setCoords(const X &x) { 79 dontPrint=true; 80 return GraphToEps<SetCoordsTraits<X> >(SetCoordsTraits<X>(*this,x)); 81 } 82 template<class X> struct SetNodeSizesTraits : public T { 83 const X &nodeSizes; 84 SetNodeSizesTraits(const T &t,const X &x) : T(t), nodeSizes(x) {} 85 }; 86 ///\e 87 template<class X> GraphToEps<SetNodeSizesTraits<X> > setNodeSizes(const X &x) 88 { 89 dontPrint=true; 90 return GraphToEps<SetNodeSizesTraits<X> >(SetNodeSizesTraits<X>(*this,x)); 91 } 92 template<class X> struct SetNodeColorsTraits : public T { 93 const X &nodeColors; 94 SetNodeColorsTraits(const T &t,const X &x) : T(t), nodeColors(x) {} 95 }; 96 ///\e 97 template<class X> GraphToEps<SetNodeColorsTraits<X> > 98 setNodeColors(const X &x) 99 { 100 dontPrint=true; 101 return GraphToEps<SetNodeColorsTraits<X> >(SetNodeColorsTraits<X>(*this,x)); 102 } 103 template<class X> struct SetEdgeColorsTraits : public T { 104 const X &edgeColors; 105 SetEdgeColorsTraits(const T &t,const X &x) : T(t), edgeColors(x) {} 106 }; 107 ///\e 108 template<class X> GraphToEps<SetEdgeColorsTraits<X> > 109 setEdgeColors(const X &x) 110 { 111 dontPrint=true; 112 return GraphToEps<SetEdgeColorsTraits<X> >(SetEdgeColorsTraits<X>(*this,x)); 113 } 114 ///\e 115 GraphToEps<T> &scaleNodeSize(double d) {nodeSizeScalar=d;return *this;} 103 template<class X> struct CoordsTraits : public T { 104 const X &_coords; 105 CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {} 106 }; 107 ///Sets the map of the node coordinates 108 109 ///Sets the map of the node coordinates. 110 ///\param x must be a node map with xy<double> or xy<int> values. 111 template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) { 112 dontPrint=true; 113 return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x)); 114 } 115 template<class X> struct NodeSizesTraits : public T { 116 const X &_nodeSizes; 117 NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {} 118 }; 119 ///Sets the map of the node sizes 120 121 ///Sets the map of the node sizes 122 ///\param x must be a node map with \c double (or convertible) values. 123 template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x) 124 { 125 dontPrint=true; 126 return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x)); 127 } 128 template<class X> struct EdgeWidthsTraits : public T { 129 const X &_edgeWidths; 130 EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {} 131 }; 132 ///Sets the map of the edge widths 133 134 ///Sets the map of the edge widths 135 ///\param x must be a edge map with \c double (or convertible) values. 136 template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x) 137 { 138 dontPrint=true; 139 return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x)); 140 } 141 142 template<class X> struct NodeColorsTraits : public T { 143 const X &_nodeColors; 144 NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {} 145 }; 146 ///Sets the map of the node colors 147 148 ///Sets the map of the node colors 149 ///\param x must be a node map with \ref Color values. 150 template<class X> GraphToEps<NodeColorsTraits<X> > 151 nodeColors(const X &x) 152 { 153 dontPrint=true; 154 return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x)); 155 } 156 template<class X> struct EdgeColorsTraits : public T { 157 const X &_edgeColors; 158 EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {} 159 }; 160 ///Sets the map of the edge colors 161 162 ///Sets the map of the edge colors 163 ///\param x must be a edge map with \ref Color values. 164 template<class X> GraphToEps<EdgeColorsTraits<X> > 165 edgeColors(const X &x) 166 { 167 dontPrint=true; 168 return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x)); 169 } 170 ///Sets a global scale factor for node sizes 171 172 ///Sets a global scale factor for node sizes 173 /// 174 GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;} 175 ///Sets a global scale factor for edge widths 176 177 ///Sets a global scale factor for edge widths 178 /// 179 GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;} 180 ///Sets a global scale factor for the whole picture 181 182 ///Sets a global scale factor for the whole picture 183 /// 184 GraphToEps<T> &scale(double d) {_scale=d;return *this;} 185 ///Sets the width of the border around the picture 186 187 ///Sets the width of the border around the picture 188 /// 189 GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;} 190 ///Sets the width of the border around the picture 191 192 ///Sets the width of the border around the picture 193 /// 194 GraphToEps<T> &border(double x, double y) { 195 _xBorder=x;_yBorder=y;return *this; 196 } 197 ///Sets whether to draw arrows 198 199 ///Sets whether to draw arrows 200 /// 201 GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;} 202 ///Sets the length of the arrowheads 203 204 ///Sets the length of the arrowheads 205 /// 206 GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;} 207 ///Sets the width of the arrowheads 208 209 ///Sets the width of the arrowheads 210 /// 211 GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;} 116 212 117 213 ~GraphToEps() … … 122 218 //\todo: Chech whether the graph is empty. 123 219 BoundingBox<double> bb; 124 for(NodeIt n(g); 125 n!=INVALID; 126 ++n) { 127 xy<double> p(nodeSizes[n]*nodeSizeScalar,nodeSizes[n]*nodeSizeScalar); 128 bb+=coords[n]+p; 129 bb+=coords[n]-p; 220 for(NodeIt n(g);n!=INVALID;++n) { 221 double ns=_nodeSizes[n]*_nodeScale; 222 xy<double> p(ns,ns); 223 bb+=p+_coords[n]; 224 bb+=-p+_coords[n]; 130 225 } 131 226 cout << "%%BoundingBox: " 132 << bb.left()-xBorder << ' ' << bb.bottom()-yBorder << ' ' 133 << bb.right()+xBorder << ' ' << bb.top()+yBorder << '\n'; 134 //x1 y1 x2 y2 cr cg cb 135 cout << "/l { setrgbcolor newpath moveto lineto stroke } bind def\n"; 227 << bb.left()* _scale-_xBorder << ' ' 228 << bb.bottom()*_scale-_yBorder << ' ' 229 << bb.right()* _scale+_xBorder << ' ' 230 << bb.top()* _scale+_yBorder << '\n'; 231 //x1 y1 x2 y2 cr cg cb w 232 cout << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; 136 233 cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n"; 137 234 // x y r cr cg cb 138 235 cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" 139 << " 0 0 0 setrgbcolor dup 10 div setlinewidth c stroke\n" 236 << " 0 0 0 setrgbcolor dup " 237 << _nodeBorderQuotient << " mul setlinewidth " 238 << 1+_nodeBorderQuotient/2 << " div c stroke\n" 140 239 << " } bind def\n"; 141 240 cout << "/arrl " << _arrowLength << " def\n"; 241 cout << "/arrw " << _arrowWidth << " def\n"; 242 // l dx_norm dy_norm 243 cout << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; 244 //len w dx_norm dy_norm x1 y1 cr cg cb 245 cout << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" 246 << " /w exch def /len exch def\n" 247 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" 248 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" 249 << " len w sub arrl sub dx dy lrl\n" 250 << " arrw dy dx neg lrl\n" 251 << " dx arrl w add mul dy w 2 div arrw add mul sub\n" 252 << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n" 253 << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" 254 << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" 255 << " arrw dy dx neg lrl\n" 256 << " len w sub arrl sub neg dx dy lrl\n" 257 << " closepath fill } bind def\n"; 258 cout << "\ngsave\n"; 259 if(_scale!=1.0) cout << _scale << " dup scale\n"; 142 260 cout << "%Edges:\ngsave\n"; 143 261 for(NodeIt n(g);n!=INVALID;++n) 144 262 for(OutEdgeIt e(g,n);e!=INVALID;++e) 145 cout << coords[g.source(e)].x << ' ' << coords[g.source(e)].y << ' ' 146 << coords[g.target(e)].x << ' ' << coords[g.target(e)].y << ' ' 147 << edgeColors[e].getR() << ' ' 148 << edgeColors[e].getG() << ' ' 149 << edgeColors[e].getB() << " l\n"; 263 if(_drawArrows) { 264 xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]); 265 double l=sqrt(d.normSquare()); 266 d/=l; 267 xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ 268 _coords[g.source(e)]); 269 cout << l-(_nodeSizes[g.source(e)]+ 270 _nodeSizes[g.target(e)])*_nodeScale << ' ' 271 << _edgeWidths[e]*_edgeWidthScale << ' ' 272 << d.x << ' ' << d.y << ' ' 273 << x1.x << ' ' << x1.y << ' ' 274 << _edgeColors[e].getR() << ' ' 275 << _edgeColors[e].getG() << ' ' 276 << _edgeColors[e].getB() << " arr\n"; 277 } 278 else cout << _coords[g.source(e)].x << ' ' 279 << _coords[g.source(e)].y << ' ' 280 << _coords[g.target(e)].x << ' ' 281 << _coords[g.target(e)].y << ' ' 282 << _edgeColors[e].getR() << ' ' 283 << _edgeColors[e].getG() << ' ' 284 << _edgeColors[e].getB() << ' ' 285 << _edgeWidths[e]*_edgeWidthScale << " l\n"; 150 286 cout << "grestore\n%Nodes:\ngsave\n"; 151 287 for(NodeIt n(g);n!=INVALID;++n) 152 cout << coords[n].x << ' ' <<coords[n].y << ' '153 << nodeSizes[n]*nodeSizeScalar<< ' '154 << nodeColors[n].getR() << ' '155 << nodeColors[n].getG() << ' '156 << nodeColors[n].getB() << " n\n";157 cout << "grestore\n ";288 cout << _coords[n].x << ' ' << _coords[n].y << ' ' 289 << _nodeSizes[n]*_nodeScale << ' ' 290 << _nodeColors[n].getR() << ' ' 291 << _nodeColors[n].getG() << ' ' 292 << _nodeColors[n].getB() << " n\n"; 293 cout << "grestore\ngrestore\n"; 158 294 } 159 295 }; 160 296 161 297 298 ///Generates an EPS file from a graph 299 300 ///\ingroup misc 301 ///Generates an EPS file from a graph. 302 /// 303 ///This function has a lot of \ref named-templ-param "named parameters", 304 ///they are declared as the members of class \ref GraphToEps. The following 305 ///example shows how to use these parameters. 306 ///\code 307 /// graphToEps(g).scale(10).coords(coords) 308 /// .nodeScale(2).nodeSizes(sizes) 309 /// .edgeWidthScale(.4); 310 ///\endcode 311 ///\sa GraphToEps 162 312 template<class G> 163 313 GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g) … … 195 345 typedef ListGraph::NodeIt NodeIt; 196 346 typedef ListGraph::Edge Edge; 197 typedef xy< double> Xy;347 typedef xy<int> Xy; 198 348 199 349 Node n1=g.addNode(); … … 207 357 ListGraph::NodeMap<int> colors(g); 208 358 ListGraph::EdgeMap<int> ecolors(g); 359 ListGraph::EdgeMap<int> widths(g); 209 360 210 361 coords[n1]=Xy(50,50); sizes[n1]=1; colors[n1]=1; … … 216 367 Edge e; 217 368 218 e=g.addEdge(n1,n2); ecolors[e]=0; 219 e=g.addEdge(n2,n3); ecolors[e]=0; 220 e=g.addEdge(n3,n5); ecolors[e]=0; 221 e=g.addEdge(n5,n4); ecolors[e]=0; 222 e=g.addEdge(n4,n1); ecolors[e]=0; 223 e=g.addEdge(n2,n4); ecolors[e]=1; 224 e=g.addEdge(n3,n4); ecolors[e]=2; 225 226 graphToEps(g).setCoords(coords). 227 scaleNodeSize(2).setNodeSizes(sizes). 228 setNodeColors(composeMap(colorSet,colors)). 229 setEdgeColors(composeMap(colorSet,ecolors)); 369 e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1; 370 e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1; 371 e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3; 372 e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1; 373 e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1; 374 e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2; 375 e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1; 376 377 graphToEps(g).scale(10).coords(coords). 378 nodeScale(2).nodeSizes(sizes). 379 nodeColors(composeMap(colorSet,colors)). 380 edgeColors(composeMap(colorSet,ecolors)). 381 edgeWidthScale(.4).edgeWidths(widths). 382 drawArrows().arrowWidth(1).arrowLength(1) 383 ; 230 384 }
Note: See TracChangeset
for help on using the changeset viewer.