Changeset 1062:8226427845bc in lemon0.x
 Timestamp:
 01/08/05 21:16:56 (17 years ago)
 Branch:
 default
 Phase:
 public
 Convert:
 svn:c9d7d8f590d60310b91f818b3a526b0e/lemon/trunk@1458
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

src/work/alpar/graph_to_eps.cc
r1055 r1062 1 /* * C++ * 2 * src/lemon/graph_to_eps.h  Part of LEMON, a generic C++ optimization library 3 * 4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 5 * (Egervary Combinatorial Optimization Research Group, EGRES). 6 * 7 * Permission to use, modify and distribute this software is granted 8 * provided that this copyright notice appears in all copies. For 9 * precise terms see the accompanying LICENSE file. 10 * 11 * This software is provided "AS IS" with no warranty of any kind, 12 * express or implied, and with no claim as to its suitability for any 13 * purpose. 14 * 15 */ 16 1 17 #include <iostream> 2 18 #include <fstream> … … 9 25 10 26 11 ///\file \ingroup misc 12 ///Simple graph drawer 27 ///\ingroup misc 28 ///\file 29 ///\brief Simple graph drawer 13 30 14 31 namespace lemon { … … 75 92 double _arrowLength, _arrowWidth; 76 93 94 bool _showNodes, _showEdges; 95 77 96 bool _enableParallel; 97 double _parEdgeDist; 98 99 bool _showNodeText; 100 ConstMap<typename Graph::Node,bool > _nodeTexts; 101 double _nodeTextSize; 78 102 79 103 bool _pleaseRemoveOsStream; … … 96 120 _nodeBorderQuotient(.1), 97 121 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), 98 _enableParallel(false), _pleaseRemoveOsStream(_pros) {} 122 _showNodes(true), _showEdges(true), 123 _enableParallel(false), _parEdgeDist(1), 124 _showNodeText(false), _nodeTexts(false), _nodeTextSize(1), 125 _pleaseRemoveOsStream(_pros) {} 99 126 }; 100 127 … … 131 158 } 132 159 }; 133 160 bool isParallel(Edge e,Edge f) const 161 { 162 return (g.source(e)==g.source(f)&&g.target(e)==g.target(f)) 163 (g.source(e)==g.target(f)&&g.target(e)==g.source(f)); 164 } 165 static xy<double> rot(xy<double> v) 166 { 167 return xy<double>(v.y,v.x); 168 } 169 134 170 public: 135 171 GraphToEps(const T &t) : T(t), dontPrint(false) {}; … … 160 196 return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x)); 161 197 } 198 template<class X> struct NodeTextsTraits : public T { 199 const X &_nodeTexts; 200 NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {} 201 }; 202 ///Sets the text printed on the nodes 203 204 ///Sets the text printed on the nodes 205 ///\param x must be a node map with type that can be pushed to a standard 206 ///ostream. 207 template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x) 208 { 209 dontPrint=true; 210 _showNodeText=true; 211 return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x)); 212 } 162 213 template<class X> struct EdgeWidthsTraits : public T { 163 214 const X &_edgeWidths; … … 248 299 249 300 ///Enables parallel edges 250 ///\todo Unimplemented301 ///\todo Partially implemented 251 302 GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;} 303 304 ///Sets the distance 305 306 ///Sets the distance 307 /// 308 GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;} 309 310 ///Hides the edges 311 312 ///Hides the edges 313 /// 314 GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;} 315 ///Hides the nodes 316 317 ///Hides the nodes 318 /// 319 GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;} 320 321 ///Sets the size of the node texts 322 323 ///Sets the size of the node texts 324 /// 325 GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;} 326 252 327 253 328 ~GraphToEps() … … 269 344 << bb.right()* _scale+_xBorder << ' ' 270 345 << bb.top()* _scale+_yBorder << '\n'; 271 //x1 y1 x2 y2 cr cg cb w 346 //x1 y1 x2 y2 x3 y3 cr cg cb w 347 os << "/lb { setlinewidth setrgbcolor newpath moveto\n" 348 << " 4 2 roll 1 index 1 index curveto stroke } bind def\n"; 272 349 os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; 273 os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";350 os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n"; 274 351 // x y r cr cg cb 275 352 os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" 276 277 278 279 353 << " 0 0 0 setrgbcolor dup " 354 << _nodeBorderQuotient << " mul setlinewidth " 355 << 1+_nodeBorderQuotient/2 << " div c stroke\n" 356 << " } bind def\n"; 280 357 os << "/arrl " << _arrowLength << " def\n"; 281 358 os << "/arrw " << _arrowWidth << " def\n"; … … 284 361 //len w dx_norm dy_norm x1 y1 cr cg cb 285 362 os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" 286 363 << " /w exch def /len exch def\n" 287 364 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" 288 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" 289 << " len w sub arrl sub dx dy lrl\n" 290 << " arrw dy dx neg lrl\n" 291 << " dx arrl w add mul dy w 2 div arrw add mul sub\n" 292 << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n" 293 << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" 294 << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" 295 << " arrw dy dx neg lrl\n" 296 << " len w sub arrl sub neg dx dy lrl\n" 297 << " closepath fill } bind def\n"; 365 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" 366 << " len w sub arrl sub dx dy lrl\n" 367 << " arrw dy dx neg lrl\n" 368 << " dx arrl w add mul dy w 2 div arrw add mul sub\n" 369 << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n" 370 << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" 371 << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" 372 << " arrw dy dx neg lrl\n" 373 << " len w sub arrl sub neg dx dy lrl\n" 374 << " closepath fill } bind def\n"; 375 os << "/cshow { 2 index 2 index moveto\n" 376 << " dup stringwidth pop neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n"; 377 298 378 os << "\ngsave\n"; 299 379 if(_scale!=1.0) os << _scale << " dup scale\n"; … … 301 381 os << "%Edges:\ngsave\n"; 302 382 303 vector<Edge> el; 304 if(_enableParallel) { 305 for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e); 306 sort(el.begin(),el.end(),edgeLess(g)); 307 } 308 309 for(NodeIt n(g);n!=INVALID;++n) 310 for(OutEdgeIt e(g,n);e!=INVALID;++e) 311 if(_drawArrows) { 312 xy<double> d(_coords[g.target(e)]_coords[g.source(e)]); 313 double l=sqrt(d.normSquare()); 314 d/=l; 315 xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ 316 _coords[g.source(e)]); 317 os << l(_nodeSizes[g.source(e)]+ 383 if(_showEdges) 384 if(_enableParallel) { 385 vector<Edge> el; 386 for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e); 387 sort(el.begin(),el.end(),edgeLess(g)); 388 389 typename vector<Edge>::iterator j; 390 for(typename vector<Edge>::iterator i=el.begin();i!=el.end();i=j) { 391 for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; 392 393 if(_drawArrows) { 394 // xy<double> d(_coords[g.target(e)]_coords[g.source(e)]); 395 // double l=sqrt(d.normSquare()); 396 // d/=l; 397 // xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ 398 // _coords[g.source(e)]); 399 // os << l(_nodeSizes[g.source(e)]+ 400 // _nodeSizes[g.target(e)])*_nodeScale << ' ' 401 // << _edgeWidths[e]*_edgeWidthScale << ' ' 402 // << d.x << ' ' << d.y << ' ' 403 // << x1.x << ' ' << x1.y << ' ' 404 // << _edgeColors[e].getR() << ' ' 405 // << _edgeColors[e].getG() << ' ' 406 // << _edgeColors[e].getB() << " arr\n"; 407 } 408 else { 409 double sw=0; 410 for(typename vector<Edge>::iterator e=i;e!=j;++e) 411 sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist; 412 sw=_parEdgeDist; 413 sw/=2.0; 414 xy<double> d(_coords[g.target(*i)]_coords[g.source(*i)]); 415 double l=sqrt(d.normSquare()); 416 d/=l; 417 for(typename vector<Edge>::iterator e=i;e!=j;++e) { 418 sw+=_edgeWidths[*e]*_edgeWidthScale/2.0; 419 xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]); 420 m=m/2.0+rot(d)*sw/.75; 421 os << _coords[g.source(*e)].x << ' ' 422 << _coords[g.source(*e)].y << ' ' 423 << m.x << ' ' << m.y << ' ' 424 << _coords[g.target(*e)].x << ' ' 425 << _coords[g.target(*e)].y << ' ' 426 << _edgeColors[*e].getR() << ' ' 427 << _edgeColors[*e].getG() << ' ' 428 << _edgeColors[*e].getB() << ' ' 429 << _edgeWidths[*e]*_edgeWidthScale << " lb\n"; 430 sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist; 431 } 432 } 433 } 434 } 435 else for(NodeIt n(g);n!=INVALID;++n) 436 for(OutEdgeIt e(g,n);e!=INVALID;++e) 437 if(_drawArrows) { 438 xy<double> d(_coords[g.target(e)]_coords[g.source(e)]); 439 double l=sqrt(d.normSquare()); 440 d/=l; 441 xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ 442 _coords[g.source(e)]); 443 os << l(_nodeSizes[g.source(e)]+ 318 444 _nodeSizes[g.target(e)])*_nodeScale << ' ' 319 445 << _edgeWidths[e]*_edgeWidthScale << ' ' … … 323 449 << _edgeColors[e].getG() << ' ' 324 450 << _edgeColors[e].getB() << " arr\n"; 325 }326 451 } 452 else os << _coords[g.source(e)].x << ' ' 327 453 << _coords[g.source(e)].y << ' ' 328 454 << _coords[g.target(e)].x << ' ' … … 333 459 << _edgeWidths[e]*_edgeWidthScale << " l\n"; 334 460 os << "grestore\n%Nodes:\ngsave\n"; 335 for(NodeIt n(g);n!=INVALID;++n) 336 os << _coords[n].x << ' ' << _coords[n].y << ' ' 461 if(_showNodes) 462 for(NodeIt n(g);n!=INVALID;++n) 463 os << _coords[n].x << ' ' << _coords[n].y << ' ' 337 464 << _nodeSizes[n]*_nodeScale << ' ' 338 465 << _nodeColors[n].getR() << ' ' 339 466 << _nodeColors[n].getG() << ' ' 340 467 << _nodeColors[n].getB() << " n\n"; 468 if(_showNodeText) { 469 os << "grestore\n%Node texts:\ngsave\n"; 470 os << "/fosi " << _nodeTextSize << " def\n"; 471 os << "(Helvetica) findfont fosi scalefont setfont\n"; 472 os << "0 0 0 setrgbcolor\n"; 473 for(NodeIt n(g);n!=INVALID;++n) 474 os << _coords[n].x << ' ' << _coords[n].y 475 << " (" << _nodeTexts[n] << ") cshow\n"; 476 } 341 477 os << "grestore\ngrestore\n"; 342 343 478 344 479 //CleanUp: … … 365 500 ///\endcode 366 501 ///\sa GraphToEps 502 ///\sa graphToEps(G &g, char *file_name) 367 503 template<class G> 368 504 GraphToEps<DefaultGraphToEpsTraits<G> > 369 graphToEps(G &g, std::ostream& os=std::cout)505 graphToEps(G &g, std::ostream& os=std::cout) 370 506 { 371 507 return … … 375 511 ///Generates an EPS file from a graph 376 512 377 ///\ingroup misc 378 ///Generates an EPS file from a graph. 379 ///\param g is a reference to the graph to be printed 380 ///\param file_name is the output file_name. 381 /// 382 ///This function also has a lot of \ref namedtemplparam "named parameters", 383 ///they are declared as the members of class \ref GraphToEps. The following 384 ///example shows how to use these parameters. 385 ///\code 386 /// graphToEps(g).scale(10).coords(coords) 387 /// .nodeScale(2).nodeSizes(sizes) 388 /// .edgeWidthScale(.4); 389 ///\endcode 390 ///\sa GraphToEps 391 ///\todo Avoid duplicated documentation 392 ///\bug Exception handling is missing? (Or we can just ignore it?) 513 //\ingroup misc 514 ///This function does the same as 515 ///\ref graphToEps(G &g,std::ostream& os) 516 ///but it writes its output into the file \c file_name 517 ///instead of a stream. 518 ///\sa graphToEps(G &g, std::ostream& os) 393 519 template<class G> 394 520 GraphToEps<DefaultGraphToEpsTraits<G> > … … 399 525 } 400 526 527 //Generates an EPS file from a graph. 528 //\param g is a reference to the graph to be printed 529 //\param file_name is the output file_name. 530 // 531 //This function also has a lot of \ref namedtemplparam "named parameters", 532 //they are declared as the members of class \ref GraphToEps. The following 533 //example shows how to use these parameters. 534 //\code 535 // graphToEps(g).scale(10).coords(coords) 536 // .nodeScale(2).nodeSizes(sizes) 537 // .edgeWidthScale(.4); 538 //\endcode 539 //\sa GraphToEps 540 //\todo Avoid duplicated documentation 541 //\bug Exception handling is missing? (Or we can just ignore it?) 401 542 402 543 } … … 423 564 } colorSet; 424 565 566 class IdMap :public MapBase<ListGraph::Node,int> 567 { 568 const ListGraph &g; 569 public: 570 IdMap(const ListGraph &_g) :g(_g) {} 571 Value operator[](Key n) const { return g.id(n); } 572 }; 573 574 575 425 576 int main() 426 577 { … … 459 610 e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1; 460 611 612 IdMap id(g); 613 461 614 graphToEps(g,"proba.eps").scale(10).coords(coords). 462 615 nodeScale(2).nodeSizes(sizes). 463 616 nodeColors(composeMap(colorSet,colors)). 464 617 edgeColors(composeMap(colorSet,ecolors)). 465 edgeWidthScale(.4).edgeWidths(widths); 618 edgeWidthScale(.4).edgeWidths(widths). 619 nodeTexts(id).nodeTextSize(3); 620 466 621 graphToEps(g,"proba_arr.eps").scale(10).coords(coords). 467 622 nodeScale(2).nodeSizes(sizes). … … 469 624 edgeColors(composeMap(colorSet,ecolors)). 470 625 edgeWidthScale(.4).edgeWidths(widths). 471 drawArrows().arrowWidth(1).arrowLength(1) 472 ; 626 nodeTexts(id).nodeTextSize(3). 627 drawArrows().arrowWidth(1).arrowLength(1); 628 629 e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1; 630 e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2; 631 632 e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1; 633 e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1; 634 e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1; 635 e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1; 636 e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1; 637 e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1; 638 e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1; 639 640 graphToEps(g,"proba_par.eps").scale(10).coords(coords). 641 nodeScale(2).nodeSizes(sizes). 642 nodeColors(composeMap(colorSet,colors)). 643 edgeColors(composeMap(colorSet,ecolors)). 644 edgeWidthScale(.4).edgeWidths(widths). 645 nodeTexts(id).nodeTextSize(3). 646 enableParallel().parEdgeDist(1.5); 473 647 }
Note: See TracChangeset
for help on using the changeset viewer.