93 _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), |
117 _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), |
94 _edgeWidths(1), _edgeWidthScale(0.3), |
118 _edgeWidths(1), _edgeWidthScale(0.3), |
95 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
119 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
96 _nodeBorderQuotient(.1), |
120 _nodeBorderQuotient(.1), |
97 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), |
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 |
101 ///Helper class to implement the named parameters of \ref graphToEps() |
128 ///Helper class to implement the named parameters of \ref graphToEps() |
102 |
129 |
103 ///Helper class to implement the named parameters of \ref graphToEps() |
130 ///Helper class to implement the named parameters of \ref graphToEps() |
266 os << "%%BoundingBox: " |
341 os << "%%BoundingBox: " |
267 << bb.left()* _scale-_xBorder << ' ' |
342 << bb.left()* _scale-_xBorder << ' ' |
268 << bb.bottom()*_scale-_yBorder << ' ' |
343 << bb.bottom()*_scale-_yBorder << ' ' |
269 << bb.right()* _scale+_xBorder << ' ' |
344 << bb.right()* _scale+_xBorder << ' ' |
270 << bb.top()* _scale+_yBorder << '\n'; |
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 os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; |
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 // x y r cr cg cb |
351 // x y r cr cg cb |
275 os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" |
352 os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" |
276 << " 0 0 0 setrgbcolor dup " |
353 << " 0 0 0 setrgbcolor dup " |
277 << _nodeBorderQuotient << " mul setlinewidth " |
354 << _nodeBorderQuotient << " mul setlinewidth " |
278 << 1+_nodeBorderQuotient/2 << " div c stroke\n" |
355 << 1+_nodeBorderQuotient/2 << " div c stroke\n" |
279 << " } bind def\n"; |
356 << " } bind def\n"; |
280 os << "/arrl " << _arrowLength << " def\n"; |
357 os << "/arrl " << _arrowLength << " def\n"; |
281 os << "/arrw " << _arrowWidth << " def\n"; |
358 os << "/arrw " << _arrowWidth << " def\n"; |
282 // l dx_norm dy_norm |
359 // l dx_norm dy_norm |
283 os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; |
360 os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; |
284 //len w dx_norm dy_norm x1 y1 cr cg cb |
361 //len w dx_norm dy_norm x1 y1 cr cg cb |
285 os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" |
362 os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" |
286 << " /w exch def /len exch def\n" |
363 << " /w exch def /len exch def\n" |
287 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" |
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" |
365 << " 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" |
366 << " len w sub arrl sub dx dy lrl\n" |
290 << " arrw dy dx neg lrl\n" |
367 << " arrw dy dx neg lrl\n" |
291 << " dx arrl w add mul dy w 2 div arrw add mul sub\n" |
368 << " 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" |
369 << " 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" |
370 << " 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" |
371 << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" |
295 << " arrw dy dx neg lrl\n" |
372 << " arrw dy dx neg lrl\n" |
296 << " len w sub arrl sub neg dx dy lrl\n" |
373 << " len w sub arrl sub neg dx dy lrl\n" |
297 << " closepath fill } bind def\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 os << "\ngsave\n"; |
378 os << "\ngsave\n"; |
299 if(_scale!=1.0) os << _scale << " dup scale\n"; |
379 if(_scale!=1.0) os << _scale << " dup scale\n"; |
300 |
380 |
301 os << "%Edges:\ngsave\n"; |
381 os << "%Edges:\ngsave\n"; |
302 |
382 |
303 vector<Edge> el; |
383 if(_showEdges) |
304 if(_enableParallel) { |
384 if(_enableParallel) { |
305 for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e); |
385 vector<Edge> el; |
306 sort(el.begin(),el.end(),edgeLess(g)); |
386 for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e); |
307 } |
387 sort(el.begin(),el.end(),edgeLess(g)); |
308 |
388 |
309 for(NodeIt n(g);n!=INVALID;++n) |
389 typename vector<Edge>::iterator j; |
310 for(OutEdgeIt e(g,n);e!=INVALID;++e) |
390 for(typename vector<Edge>::iterator i=el.begin();i!=el.end();i=j) { |
311 if(_drawArrows) { |
391 for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; |
312 xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]); |
392 |
313 double l=sqrt(d.normSquare()); |
393 if(_drawArrows) { |
314 d/=l; |
394 // xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]); |
315 xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ |
395 // double l=sqrt(d.normSquare()); |
316 _coords[g.source(e)]); |
396 // d/=l; |
317 os << l-(_nodeSizes[g.source(e)]+ |
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 _nodeSizes[g.target(e)])*_nodeScale << ' ' |
444 _nodeSizes[g.target(e)])*_nodeScale << ' ' |
319 << _edgeWidths[e]*_edgeWidthScale << ' ' |
445 << _edgeWidths[e]*_edgeWidthScale << ' ' |
320 << d.x << ' ' << d.y << ' ' |
446 << d.x << ' ' << d.y << ' ' |
321 << x1.x << ' ' << x1.y << ' ' |
447 << x1.x << ' ' << x1.y << ' ' |
322 << _edgeColors[e].getR() << ' ' |
448 << _edgeColors[e].getR() << ' ' |
323 << _edgeColors[e].getG() << ' ' |
449 << _edgeColors[e].getG() << ' ' |
324 << _edgeColors[e].getB() << " arr\n"; |
450 << _edgeColors[e].getB() << " arr\n"; |
325 } |
451 } |
326 else os << _coords[g.source(e)].x << ' ' |
452 else os << _coords[g.source(e)].x << ' ' |
327 << _coords[g.source(e)].y << ' ' |
453 << _coords[g.source(e)].y << ' ' |
328 << _coords[g.target(e)].x << ' ' |
454 << _coords[g.target(e)].x << ' ' |
329 << _coords[g.target(e)].y << ' ' |
455 << _coords[g.target(e)].y << ' ' |
330 << _edgeColors[e].getR() << ' ' |
456 << _edgeColors[e].getR() << ' ' |
331 << _edgeColors[e].getG() << ' ' |
457 << _edgeColors[e].getG() << ' ' |
332 << _edgeColors[e].getB() << ' ' |
458 << _edgeColors[e].getB() << ' ' |
333 << _edgeWidths[e]*_edgeWidthScale << " l\n"; |
459 << _edgeWidths[e]*_edgeWidthScale << " l\n"; |
334 os << "grestore\n%Nodes:\ngsave\n"; |
460 os << "grestore\n%Nodes:\ngsave\n"; |
335 for(NodeIt n(g);n!=INVALID;++n) |
461 if(_showNodes) |
336 os << _coords[n].x << ' ' << _coords[n].y << ' ' |
462 for(NodeIt n(g);n!=INVALID;++n) |
|
463 os << _coords[n].x << ' ' << _coords[n].y << ' ' |
337 << _nodeSizes[n]*_nodeScale << ' ' |
464 << _nodeSizes[n]*_nodeScale << ' ' |
338 << _nodeColors[n].getR() << ' ' |
465 << _nodeColors[n].getR() << ' ' |
339 << _nodeColors[n].getG() << ' ' |
466 << _nodeColors[n].getG() << ' ' |
340 << _nodeColors[n].getB() << " n\n"; |
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 os << "grestore\ngrestore\n"; |
477 os << "grestore\ngrestore\n"; |
342 |
|
343 |
478 |
344 //CleanUp: |
479 //CleanUp: |
345 if(_pleaseRemoveOsStream) {delete &os;} |
480 if(_pleaseRemoveOsStream) {delete &os;} |
346 } |
481 } |
347 }; |
482 }; |
362 /// graphToEps(g).scale(10).coords(coords) |
497 /// graphToEps(g).scale(10).coords(coords) |
363 /// .nodeScale(2).nodeSizes(sizes) |
498 /// .nodeScale(2).nodeSizes(sizes) |
364 /// .edgeWidthScale(.4); |
499 /// .edgeWidthScale(.4); |
365 ///\endcode |
500 ///\endcode |
366 ///\sa GraphToEps |
501 ///\sa GraphToEps |
|
502 ///\sa graphToEps(G &g, char *file_name) |
367 template<class G> |
503 template<class G> |
368 GraphToEps<DefaultGraphToEpsTraits<G> > |
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 return |
507 return |
372 GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os)); |
508 GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os)); |
373 } |
509 } |
374 |
510 |
375 ///Generates an EPS file from a graph |
511 ///Generates an EPS file from a graph |
376 |
512 |
377 ///\ingroup misc |
513 //\ingroup misc |
378 ///Generates an EPS file from a graph. |
514 ///This function does the same as |
379 ///\param g is a reference to the graph to be printed |
515 ///\ref graphToEps(G &g,std::ostream& os) |
380 ///\param file_name is the output file_name. |
516 ///but it writes its output into the file \c file_name |
381 /// |
517 ///instead of a stream. |
382 ///This function also has a lot of \ref named-templ-param "named parameters", |
518 ///\sa graphToEps(G &g, std::ostream& os) |
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?) |
|
393 template<class G> |
519 template<class G> |
394 GraphToEps<DefaultGraphToEpsTraits<G> > |
520 GraphToEps<DefaultGraphToEpsTraits<G> > |
395 graphToEps(G &g,char *file_name) |
521 graphToEps(G &g,char *file_name) |
396 { |
522 { |
397 return GraphToEps<DefaultGraphToEpsTraits<G> > |
523 return GraphToEps<DefaultGraphToEpsTraits<G> > |
398 (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true)); |
524 (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true)); |
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 named-templ-param "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 } |
403 |
544 |
404 using namespace lemon; |
545 using namespace lemon; |
405 |
546 |
456 e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1; |
607 e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1; |
457 e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1; |
608 e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1; |
458 e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2; |
609 e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2; |
459 e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1; |
610 e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1; |
460 |
611 |
|
612 IdMap id(g); |
|
613 |
461 graphToEps(g,"proba.eps").scale(10).coords(coords). |
614 graphToEps(g,"proba.eps").scale(10).coords(coords). |
462 nodeScale(2).nodeSizes(sizes). |
615 nodeScale(2).nodeSizes(sizes). |
463 nodeColors(composeMap(colorSet,colors)). |
616 nodeColors(composeMap(colorSet,colors)). |
464 edgeColors(composeMap(colorSet,ecolors)). |
617 edgeColors(composeMap(colorSet,ecolors)). |
465 edgeWidthScale(.4).edgeWidths(widths); |
618 edgeWidthScale(.4).edgeWidths(widths). |
|
619 nodeTexts(id).nodeTextSize(3); |
|
620 |
466 graphToEps(g,"proba_arr.eps").scale(10).coords(coords). |
621 graphToEps(g,"proba_arr.eps").scale(10).coords(coords). |
467 nodeScale(2).nodeSizes(sizes). |
622 nodeScale(2).nodeSizes(sizes). |
468 nodeColors(composeMap(colorSet,colors)). |
623 nodeColors(composeMap(colorSet,colors)). |
469 edgeColors(composeMap(colorSet,ecolors)). |
624 edgeColors(composeMap(colorSet,ecolors)). |
470 edgeWidthScale(.4).edgeWidths(widths). |
625 edgeWidthScale(.4).edgeWidths(widths). |
471 drawArrows().arrowWidth(1).arrowLength(1) |
626 nodeTexts(id).nodeTextSize(3). |
472 ; |
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 } |