Changeset 209:765619b7cbb2 in lemon for lemon/graph_to_eps.h
- Timestamp:
- 07/13/08 20:51:02 (18 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
-
lemon/graph_to_eps.h (modified) (47 diffs)
Legend:
- Unmodified
- Added
- Removed
-
lemon/graph_to_eps.h
r206 r209 1 /* -*- C++-*-1 /* -*- mode: C++; indent-tabs-mode: nil; -*- 2 2 * 3 * This file is a part of LEMON, a generic C++ optimization library 3 * This file is a part of LEMON, a generic C++ optimization library. 4 4 * 5 5 * Copyright (C) 2003-2008 … … 61 61 }; 62 62 } 63 63 64 64 ///Default traits class of \ref GraphToEps 65 65 … … 77 77 typedef typename Graph::InArcIt InArcIt; 78 78 typedef typename Graph::OutArcIt OutArcIt; 79 79 80 80 81 81 const Graph &g; 82 82 83 83 std::ostream& os; 84 84 85 85 typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType; 86 86 CoordsMapType _coords; … … 94 94 95 95 double _arcWidthScale; 96 96 97 97 double _nodeScale; 98 98 double _xBorder, _yBorder; 99 99 double _scale; 100 100 double _nodeBorderQuotient; 101 101 102 102 bool _drawArrows; 103 103 double _arrowLength, _arrowWidth; 104 104 105 105 bool _showNodes, _showArcs; 106 106 … … 109 109 110 110 bool _showNodeText; 111 ConstMap<typename Graph::Node,bool > _nodeTexts; 111 ConstMap<typename Graph::Node,bool > _nodeTexts; 112 112 double _nodeTextSize; 113 113 114 114 bool _showNodePsText; 115 ConstMap<typename Graph::Node,bool > _nodePsTexts; 115 ConstMap<typename Graph::Node,bool > _nodePsTexts; 116 116 char *_nodePsTextsPreamble; 117 117 118 118 bool _undirected; 119 119 … … 125 125 std::string _copyright; 126 126 127 enum NodeTextColorType 127 enum NodeTextColorType 128 128 { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType; 129 129 ConstMap<typename Graph::Node,Color > _nodeTextColors; … … 147 147 ///will be explicitly deallocated by the destructor. 148 148 DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, 149 bool _pros=false) :149 bool _pros=false) : 150 150 g(_g), os(_os), 151 151 _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0), … … 176 176 /// 177 177 ///For detailed examples see the \ref graph_to_eps_demo.cc demo file. 178 template<class T> class GraphToEps : public T 178 template<class T> class GraphToEps : public T 179 179 { 180 180 // Can't believe it is required by the C++ standard … … 195 195 using T::_scale; 196 196 using T::_nodeBorderQuotient; 197 197 198 198 using T::_drawArrows; 199 199 using T::_arrowLength; 200 200 using T::_arrowWidth; 201 201 202 202 using T::_showNodes; 203 203 using T::_showArcs; … … 207 207 208 208 using T::_showNodeText; 209 using T::_nodeTexts; 209 using T::_nodeTexts; 210 210 using T::_nodeTextSize; 211 211 212 212 using T::_showNodePsText; 213 using T::_nodePsTexts; 213 using T::_nodePsTexts; 214 214 using T::_nodePsTextsPreamble; 215 215 216 216 using T::_undirected; 217 217 … … 262 262 ///Node shapes. 263 263 /// 264 enum NodeShapes { 264 enum NodeShapes { 265 265 /// = 0 266 266 ///\image html nodeshape_0.png 267 267 ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm 268 CIRCLE=0, 268 CIRCLE=0, 269 269 /// = 1 270 270 ///\image html nodeshape_1.png 271 271 ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm 272 272 /// 273 SQUARE=1, 273 SQUARE=1, 274 274 /// = 2 275 275 ///\image html nodeshape_2.png … … 294 294 public: 295 295 arcLess(const Graph &_g) : g(_g) {} 296 bool operator()(Arc a,Arc b) const 296 bool operator()(Arc a,Arc b) const 297 297 { 298 298 Node ai=std::min(g.source(a),g.target(a)); … … 301 301 Node ba=std::max(g.source(b),g.target(b)); 302 302 return ai<bi || 303 (ai==bi && (aa < ba || 304 (aa==ba && ai==g.source(a) && bi==g.target(b))));303 (ai==bi && (aa < ba || 304 (aa==ba && ai==g.source(a) && bi==g.target(b)))); 305 305 } 306 306 }; … … 308 308 { 309 309 return (g.source(e)==g.source(f)&& 310 g.target(e)==g.target(f)) ||310 g.target(e)==g.target(f)) || 311 311 (g.source(e)==g.target(f)&& 312 312 g.target(e)==g.source(f)); 313 313 } 314 314 template<class TT> 315 static std::string psOut(const dim2::Point<TT> &p) 315 static std::string psOut(const dim2::Point<TT> &p) 316 316 { 317 std::ostringstream os; 317 std::ostringstream os; 318 318 os << p.x << ' ' << p.y; 319 319 return os.str(); 320 320 } 321 static std::string psOut(const Color &c) 321 static std::string psOut(const Color &c) 322 322 { 323 std::ostringstream os; 323 std::ostringstream os; 324 324 os << c.red() << ' ' << c.green() << ' ' << c.blue(); 325 325 return os.str(); 326 326 } 327 327 328 328 public: 329 329 GraphToEps(const T &t) : T(t), dontPrint(false) {}; 330 330 331 331 template<class X> struct CoordsTraits : public T { 332 332 typedef X CoordsMapType; … … 338 338 ///Sets the map of the node coordinates. 339 339 ///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or 340 ///\ref dim2::Point "dim2::Point<int>" values. 340 ///\ref dim2::Point "dim2::Point<int>" values. 341 341 template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) { 342 342 dontPrint=true; … … 350 350 351 351 ///Sets the map of the node sizes. 352 ///\param x must be a node map with \c double (or convertible) values. 352 ///\param x must be a node map with \c double (or convertible) values. 353 353 template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x) 354 354 { … … 365 365 ///The available shape values 366 366 ///can be found in \ref NodeShapes "enum NodeShapes". 367 ///\param x must be a node map with \c int (or convertible) values. 367 ///\param x must be a node map with \c int (or convertible) values. 368 368 ///\sa NodeShapes 369 369 template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x) … … 380 380 ///Sets the text printed on the nodes. 381 381 ///\param x must be a node map with type that can be pushed to a standard 382 ///\c ostream. 382 ///\c ostream. 383 383 template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x) 384 384 { … … 418 418 419 419 ///Sets the map of the arc widths. 420 ///\param x must be an arc map with \c double (or convertible) values. 420 ///\param x must be an arc map with \c double (or convertible) values. 421 421 template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x) 422 422 { … … 448 448 449 449 ///Sets the map of the node text colors. 450 ///\param x must be a node map with \ref Color values. 450 ///\param x must be a node map with \ref Color values. 451 451 /// 452 452 ///\sa Palette … … 466 466 467 467 ///Sets the map of the arc colors. 468 ///\param x must be an arc map with \ref Color values. 468 ///\param x must be an arc map with \ref Color values. 469 469 /// 470 470 ///\sa Palette … … 478 478 479 479 ///Sets a global scale factor for node sizes. 480 /// 480 /// 481 481 /// If nodeSizes() is not given, this function simply sets the node 482 482 /// sizes to \c d. If nodeSizes() is given, but … … 569 569 ///Sets the width of the arrowheads 570 570 GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;} 571 571 572 572 ///Scales the drawing to fit to A4 page 573 573 GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;} 574 574 575 575 ///Enables parallel arcs 576 576 GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;} 577 577 578 578 ///Sets the distance between parallel arcs 579 579 GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;} 580 580 581 581 ///Hides the arcs 582 582 GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;} 583 583 ///Hides the nodes 584 584 GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;} 585 585 586 586 ///Sets the size of the node texts 587 587 GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;} … … 601 601 602 602 ///Gives a preamble block for node Postscript block. 603 603 604 604 ///Gives a preamble block for node Postscript block. 605 605 /// … … 626 626 ///\sa undirected() 627 627 GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;} 628 628 629 629 ///Sets the title. 630 630 … … 641 641 642 642 protected: 643 bool isInsideNode(dim2::Point<double> p, double r,int t) 643 bool isInsideNode(dim2::Point<double> p, double r,int t) 644 644 { 645 645 switch(t) { … … 658 658 public: 659 659 ~GraphToEps() { } 660 660 661 661 ///Draws the graph. 662 662 … … 669 669 const double EPSILON=1e-9; 670 670 if(dontPrint) return; 671 671 672 672 _graph_to_eps_bits::_NegY<typename T::CoordsMapType> 673 673 mycoords(_coords,_negY); … … 678 678 os << "%%Creator: LEMON, graphToEps()\n"; 679 679 680 { 681 #ifndef WIN32 680 { 681 #ifndef WIN32 682 682 timeval tv; 683 683 gettimeofday(&tv, 0); … … 689 689 SYSTEMTIME time; 690 690 char buf1[11], buf2[9], buf3[5]; 691 691 692 692 GetSystemTime(&time); 693 if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, 694 "ddd MMM dd", buf1, 11) &&695 GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time, 696 "HH':'mm':'ss", buf2, 9) &&697 GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, 698 "yyyy", buf3, 5)) {699 os << "%%CreationDate: " << buf1 << ' ' 700 << buf2 << ' ' << buf3 << std::endl;701 } 693 if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, 694 "ddd MMM dd", buf1, 11) && 695 GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time, 696 "HH':'mm':'ss", buf2, 9) && 697 GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, 698 "yyyy", buf3, 5)) { 699 os << "%%CreationDate: " << buf1 << ' ' 700 << buf2 << ' ' << buf3 << std::endl; 701 } 702 702 #endif 703 703 } … … 706 706 double max_w=0; 707 707 for(ArcIt e(g);e!=INVALID;++e) 708 max_w=std::max(double(_arcWidths[e]),max_w);708 max_w=std::max(double(_arcWidths[e]),max_w); 709 709 //\todo better 'epsilon' would be nice here. 710 710 if(max_w>EPSILON) { 711 _arcWidthScale/=max_w;711 _arcWidthScale/=max_w; 712 712 } 713 713 } … … 716 716 double max_s=0; 717 717 for(NodeIt n(g);n!=INVALID;++n) 718 max_s=std::max(double(_nodeSizes[n]),max_s);718 max_s=std::max(double(_nodeSizes[n]),max_s); 719 719 //\todo better 'epsilon' would be nice here. 720 720 if(max_s>EPSILON) { 721 _nodeScale/=max_s;721 _nodeScale/=max_s; 722 722 } 723 723 } … … 728 728 for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]); 729 729 if (bb.empty()) { 730 bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));730 bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0)); 731 731 } 732 732 diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare()); … … 735 735 if(!_absoluteArcWidths) _arcWidthScale*=diag_len; 736 736 } 737 737 738 738 dim2::BoundingBox<double> bb; 739 739 for(NodeIt n(g);n!=INVALID;++n) { … … 744 744 case SQUARE: 745 745 case DIAMOND: 746 bb.add(p+mycoords[n]);747 bb.add(-p+mycoords[n]);748 break;746 bb.add(p+mycoords[n]); 747 bb.add(-p+mycoords[n]); 748 break; 749 749 case MALE: 750 bb.add(-p+mycoords[n]);751 bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);752 break;750 bb.add(-p+mycoords[n]); 751 bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]); 752 break; 753 753 case FEMALE: 754 bb.add(p+mycoords[n]);755 bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);756 break;754 bb.add(p+mycoords[n]); 755 bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]); 756 break; 757 757 } 758 758 } … … 760 760 bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0)); 761 761 } 762 762 763 763 if(_scaleToA4) 764 764 os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n"; 765 765 else { 766 766 if(_preScale) { 767 //Rescale so that BoundingBox won't be neither to big nor too small.768 while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;769 while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;767 //Rescale so that BoundingBox won't be neither to big nor too small. 768 while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10; 769 while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10; 770 770 } 771 771 772 772 os << "%%BoundingBox: " 773 << int(floor(bb.left() * _scale - _xBorder)) << ' '774 << int(floor(bb.bottom() * _scale - _yBorder)) << ' '775 << int(ceil(bb.right() * _scale + _xBorder)) << ' '776 << int(ceil(bb.top() * _scale + _yBorder)) << '\n';777 } 778 773 << int(floor(bb.left() * _scale - _xBorder)) << ' ' 774 << int(floor(bb.bottom() * _scale - _yBorder)) << ' ' 775 << int(ceil(bb.right() * _scale + _xBorder)) << ' ' 776 << int(ceil(bb.top() * _scale + _yBorder)) << '\n'; 777 } 778 779 779 os << "%%EndComments\n"; 780 780 781 781 //x1 y1 x2 y2 x3 y3 cr cg cb w 782 782 os << "/lb { setlinewidth setrgbcolor newpath moveto\n" … … 832 832 << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n" 833 833 << " } bind def\n"; 834 834 835 835 836 836 os << "/arrl " << _arrowLength << " def\n"; … … 841 841 os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" 842 842 << " /w exch def /len exch def\n" 843 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"843 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" 844 844 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" 845 845 << " len w sub arrl sub dx dy lrl\n" … … 858 858 if(_scaleToA4) 859 859 if(bb.height()>bb.width()) { 860 double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),861 (A4WIDTH-2*A4BORDER)/bb.width());862 os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '863 << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER864 << " translate\n"865 << sc << " dup scale\n"866 << -bb.left() << ' ' << -bb.bottom() << " translate\n";860 double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(), 861 (A4WIDTH-2*A4BORDER)/bb.width()); 862 os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' ' 863 << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER 864 << " translate\n" 865 << sc << " dup scale\n" 866 << -bb.left() << ' ' << -bb.bottom() << " translate\n"; 867 867 } 868 868 else { 869 //\todo Verify centering870 double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),871 (A4WIDTH-2*A4BORDER)/bb.height());872 os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '873 << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER 874 << " translate\n"875 << sc << " dup scale\n90 rotate\n"876 << -bb.left() << ' ' << -bb.top() << " translate\n"; 877 }869 //\todo Verify centering 870 double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(), 871 (A4WIDTH-2*A4BORDER)/bb.height()); 872 os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' ' 873 << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER 874 << " translate\n" 875 << sc << " dup scale\n90 rotate\n" 876 << -bb.left() << ' ' << -bb.top() << " translate\n"; 877 } 878 878 else if(_scale!=1.0) os << _scale << " dup scale\n"; 879 879 880 880 if(_showArcs) { 881 os << "%Arcs:\ngsave\n"; 881 os << "%Arcs:\ngsave\n"; 882 882 if(_enableParallel) { 883 std::vector<Arc> el;884 for(ArcIt e(g);e!=INVALID;++e)885 if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0886 &&g.source(e)!=g.target(e))887 el.push_back(e);888 std::sort(el.begin(),el.end(),arcLess(g));889 890 typename std::vector<Arc>::iterator j;891 for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {892 for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;893 894 double sw=0;895 for(typename std::vector<Arc>::iterator e=i;e!=j;++e)896 sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;897 sw-=_parArcDist;898 sw/=-2.0;899 dim2::Point<double>900 dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);901 double l=std::sqrt(dvec.normSquare()); 902 //\todo better 'epsilon' would be nice here.903 dim2::Point<double> d(dvec/std::max(l,EPSILON));904 dim2::Point<double> m;905 // m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;906 907 // m=dim2::Point<double>(mycoords[g.source(*i)])+908 // dvec*(double(_nodeSizes[g.source(*i)])/909 // (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));910 911 m=dim2::Point<double>(mycoords[g.source(*i)])+912 d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;913 914 for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {915 sw+=_arcWidths[*e]*_arcWidthScale/2.0;916 dim2::Point<double> mm=m+rot90(d)*sw/.75;917 if(_drawArrows) {918 int node_shape;919 dim2::Point<double> s=mycoords[g.source(*e)];920 dim2::Point<double> t=mycoords[g.target(*e)];921 double rn=_nodeSizes[g.target(*e)]*_nodeScale;922 node_shape=_nodeShapes[g.target(*e)];923 dim2::Bezier3 bez(s,mm,mm,t);924 double t1=0,t2=1;925 for(int ii=0;ii<INTERPOL_PREC;++ii)926 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;927 else t1=(t1+t2)/2;928 dim2::Point<double> apoint=bez((t1+t2)/2);929 rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;930 rn*=rn;931 t2=(t1+t2)/2;t1=0;932 for(int ii=0;ii<INTERPOL_PREC;++ii)933 if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;934 else t2=(t1+t2)/2;935 dim2::Point<double> linend=bez((t1+t2)/2); 936 bez=bez.before((t1+t2)/2);937 // rn=_nodeSizes[g.source(*e)]*_nodeScale;938 // node_shape=_nodeShapes[g.source(*e)];939 // t1=0;t2=1;940 // for(int i=0;i<INTERPOL_PREC;++i)941 // if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;942 // else t2=(t1+t2)/2;943 // bez=bez.after((t1+t2)/2);944 os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "945 << _arcColors[*e].red() << ' '946 << _arcColors[*e].green() << ' '947 << _arcColors[*e].blue() << " setrgbcolor newpath\n"948 << bez.p1.x << ' ' << bez.p1.y << " moveto\n"949 << bez.p2.x << ' ' << bez.p2.y << ' '950 << bez.p3.x << ' ' << bez.p3.y << ' '951 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";952 dim2::Point<double> dd(rot90(linend-apoint));953 dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/954 std::sqrt(dd.normSquare());955 os << "newpath " << psOut(apoint) << " moveto "956 << psOut(linend+dd) << " lineto "957 << psOut(linend-dd) << " lineto closepath fill\n";958 }959 else {960 os << mycoords[g.source(*e)].x << ' '961 << mycoords[g.source(*e)].y << ' '962 << mm.x << ' ' << mm.y << ' '963 << mycoords[g.target(*e)].x << ' '964 << mycoords[g.target(*e)].y << ' '965 << _arcColors[*e].red() << ' '966 << _arcColors[*e].green() << ' '967 << _arcColors[*e].blue() << ' '968 << _arcWidths[*e]*_arcWidthScale << " lb\n";969 }970 sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;971 }972 }883 std::vector<Arc> el; 884 for(ArcIt e(g);e!=INVALID;++e) 885 if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0 886 &&g.source(e)!=g.target(e)) 887 el.push_back(e); 888 std::sort(el.begin(),el.end(),arcLess(g)); 889 890 typename std::vector<Arc>::iterator j; 891 for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) { 892 for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; 893 894 double sw=0; 895 for(typename std::vector<Arc>::iterator e=i;e!=j;++e) 896 sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist; 897 sw-=_parArcDist; 898 sw/=-2.0; 899 dim2::Point<double> 900 dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]); 901 double l=std::sqrt(dvec.normSquare()); 902 //\todo better 'epsilon' would be nice here. 903 dim2::Point<double> d(dvec/std::max(l,EPSILON)); 904 dim2::Point<double> m; 905 // m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0; 906 907 // m=dim2::Point<double>(mycoords[g.source(*i)])+ 908 // dvec*(double(_nodeSizes[g.source(*i)])/ 909 // (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)])); 910 911 m=dim2::Point<double>(mycoords[g.source(*i)])+ 912 d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0; 913 914 for(typename std::vector<Arc>::iterator e=i;e!=j;++e) { 915 sw+=_arcWidths[*e]*_arcWidthScale/2.0; 916 dim2::Point<double> mm=m+rot90(d)*sw/.75; 917 if(_drawArrows) { 918 int node_shape; 919 dim2::Point<double> s=mycoords[g.source(*e)]; 920 dim2::Point<double> t=mycoords[g.target(*e)]; 921 double rn=_nodeSizes[g.target(*e)]*_nodeScale; 922 node_shape=_nodeShapes[g.target(*e)]; 923 dim2::Bezier3 bez(s,mm,mm,t); 924 double t1=0,t2=1; 925 for(int ii=0;ii<INTERPOL_PREC;++ii) 926 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2; 927 else t1=(t1+t2)/2; 928 dim2::Point<double> apoint=bez((t1+t2)/2); 929 rn = _arrowLength+_arcWidths[*e]*_arcWidthScale; 930 rn*=rn; 931 t2=(t1+t2)/2;t1=0; 932 for(int ii=0;ii<INTERPOL_PREC;++ii) 933 if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2; 934 else t2=(t1+t2)/2; 935 dim2::Point<double> linend=bez((t1+t2)/2); 936 bez=bez.before((t1+t2)/2); 937 // rn=_nodeSizes[g.source(*e)]*_nodeScale; 938 // node_shape=_nodeShapes[g.source(*e)]; 939 // t1=0;t2=1; 940 // for(int i=0;i<INTERPOL_PREC;++i) 941 // if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2; 942 // else t2=(t1+t2)/2; 943 // bez=bez.after((t1+t2)/2); 944 os << _arcWidths[*e]*_arcWidthScale << " setlinewidth " 945 << _arcColors[*e].red() << ' ' 946 << _arcColors[*e].green() << ' ' 947 << _arcColors[*e].blue() << " setrgbcolor newpath\n" 948 << bez.p1.x << ' ' << bez.p1.y << " moveto\n" 949 << bez.p2.x << ' ' << bez.p2.y << ' ' 950 << bez.p3.x << ' ' << bez.p3.y << ' ' 951 << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n"; 952 dim2::Point<double> dd(rot90(linend-apoint)); 953 dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/ 954 std::sqrt(dd.normSquare()); 955 os << "newpath " << psOut(apoint) << " moveto " 956 << psOut(linend+dd) << " lineto " 957 << psOut(linend-dd) << " lineto closepath fill\n"; 958 } 959 else { 960 os << mycoords[g.source(*e)].x << ' ' 961 << mycoords[g.source(*e)].y << ' ' 962 << mm.x << ' ' << mm.y << ' ' 963 << mycoords[g.target(*e)].x << ' ' 964 << mycoords[g.target(*e)].y << ' ' 965 << _arcColors[*e].red() << ' ' 966 << _arcColors[*e].green() << ' ' 967 << _arcColors[*e].blue() << ' ' 968 << _arcWidths[*e]*_arcWidthScale << " lb\n"; 969 } 970 sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist; 971 } 972 } 973 973 } 974 974 else for(ArcIt e(g);e!=INVALID;++e) 975 if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0976 &&g.source(e)!=g.target(e)) {977 if(_drawArrows) {978 dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);979 double rn=_nodeSizes[g.target(e)]*_nodeScale;980 int node_shape=_nodeShapes[g.target(e)];981 double t1=0,t2=1;982 for(int i=0;i<INTERPOL_PREC;++i)983 if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;984 else t2=(t1+t2)/2;985 double l=std::sqrt(d.normSquare());986 d/=l;987 988 os << l*(1-(t1+t2)/2) << ' '989 << _arcWidths[e]*_arcWidthScale << ' '990 << d.x << ' ' << d.y << ' '991 << mycoords[g.source(e)].x << ' '992 << mycoords[g.source(e)].y << ' '993 << _arcColors[e].red() << ' '994 << _arcColors[e].green() << ' '995 << _arcColors[e].blue() << " arr\n";996 } 997 else os << mycoords[g.source(e)].x << ' '998 << mycoords[g.source(e)].y << ' '999 << mycoords[g.target(e)].x << ' '1000 << mycoords[g.target(e)].y << ' '1001 << _arcColors[e].red() << ' '1002 << _arcColors[e].green() << ' '1003 << _arcColors[e].blue() << ' '1004 << _arcWidths[e]*_arcWidthScale << " l\n";1005 }975 if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0 976 &&g.source(e)!=g.target(e)) { 977 if(_drawArrows) { 978 dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]); 979 double rn=_nodeSizes[g.target(e)]*_nodeScale; 980 int node_shape=_nodeShapes[g.target(e)]; 981 double t1=0,t2=1; 982 for(int i=0;i<INTERPOL_PREC;++i) 983 if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2; 984 else t2=(t1+t2)/2; 985 double l=std::sqrt(d.normSquare()); 986 d/=l; 987 988 os << l*(1-(t1+t2)/2) << ' ' 989 << _arcWidths[e]*_arcWidthScale << ' ' 990 << d.x << ' ' << d.y << ' ' 991 << mycoords[g.source(e)].x << ' ' 992 << mycoords[g.source(e)].y << ' ' 993 << _arcColors[e].red() << ' ' 994 << _arcColors[e].green() << ' ' 995 << _arcColors[e].blue() << " arr\n"; 996 } 997 else os << mycoords[g.source(e)].x << ' ' 998 << mycoords[g.source(e)].y << ' ' 999 << mycoords[g.target(e)].x << ' ' 1000 << mycoords[g.target(e)].y << ' ' 1001 << _arcColors[e].red() << ' ' 1002 << _arcColors[e].green() << ' ' 1003 << _arcColors[e].blue() << ' ' 1004 << _arcWidths[e]*_arcWidthScale << " l\n"; 1005 } 1006 1006 os << "grestore\n"; 1007 1007 } … … 1009 1009 os << "%Nodes:\ngsave\n"; 1010 1010 for(NodeIt n(g);n!=INVALID;++n) { 1011 os << mycoords[n].x << ' ' << mycoords[n].y << ' '1012 << _nodeSizes[n]*_nodeScale << ' '1013 << _nodeColors[n].red() << ' '1014 << _nodeColors[n].green() << ' '1015 << _nodeColors[n].blue() << ' ';1016 switch(_nodeShapes[n]) {1017 case CIRCLE:1018 os<< "nc";break;1019 case SQUARE:1020 os<< "nsq";break;1021 case DIAMOND:1022 os<< "ndi";break;1023 case MALE:1024 os<< "nmale";break;1025 case FEMALE:1026 os<< "nfemale";break;1027 }1028 os<<'\n';1011 os << mycoords[n].x << ' ' << mycoords[n].y << ' ' 1012 << _nodeSizes[n]*_nodeScale << ' ' 1013 << _nodeColors[n].red() << ' ' 1014 << _nodeColors[n].green() << ' ' 1015 << _nodeColors[n].blue() << ' '; 1016 switch(_nodeShapes[n]) { 1017 case CIRCLE: 1018 os<< "nc";break; 1019 case SQUARE: 1020 os<< "nsq";break; 1021 case DIAMOND: 1022 os<< "ndi";break; 1023 case MALE: 1024 os<< "nmale";break; 1025 case FEMALE: 1026 os<< "nfemale";break; 1027 } 1028 os<<'\n'; 1029 1029 } 1030 1030 os << "grestore\n"; … … 1035 1035 os << "(Helvetica) findfont fosi scalefont setfont\n"; 1036 1036 for(NodeIt n(g);n!=INVALID;++n) { 1037 switch(_nodeTextColorType) {1038 case DIST_COL:1039 os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";1040 break;1041 case DIST_BW:1042 os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";1043 break;1044 case CUST_COL:1045 os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";1046 break;1047 default:1048 os << "0 0 0 setrgbcolor\n";1049 }1050 os << mycoords[n].x << ' ' << mycoords[n].y1051 << " (" << _nodeTexts[n] << ") cshow\n";1037 switch(_nodeTextColorType) { 1038 case DIST_COL: 1039 os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n"; 1040 break; 1041 case DIST_BW: 1042 os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n"; 1043 break; 1044 case CUST_COL: 1045 os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n"; 1046 break; 1047 default: 1048 os << "0 0 0 setrgbcolor\n"; 1049 } 1050 os << mycoords[n].x << ' ' << mycoords[n].y 1051 << " (" << _nodeTexts[n] << ") cshow\n"; 1052 1052 } 1053 1053 os << "grestore\n"; … … 1056 1056 os << "%Node PS blocks:\ngsave\n"; 1057 1057 for(NodeIt n(g);n!=INVALID;++n) 1058 os << mycoords[n].x << ' ' << mycoords[n].y1059 << " moveto\n" << _nodePsTexts[n] << "\n";1058 os << mycoords[n].x << ' ' << mycoords[n].y 1059 << " moveto\n" << _nodePsTexts[n] << "\n"; 1060 1060 os << "grestore\n"; 1061 1061 } 1062 1062 1063 1063 os << "grestore\nshowpage\n"; 1064 1064 … … 1093 1093 return autoArcWidthScale(b); 1094 1094 } 1095 1095 1096 1096 ///An alias for absoluteArcWidths() 1097 1097 GraphToEps<T> &absoluteEdgeWidths(bool b=true) … … 1099 1099 return absoluteArcWidths(b); 1100 1100 } 1101 1101 1102 1102 ///An alias for parArcDist() 1103 1103 GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);} 1104 1104 1105 1105 ///An alias for hideArcs() 1106 1106 GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);} … … 1144 1144 ///\sa graphToEps(G &g, const char *file_name) 1145 1145 template<class G> 1146 GraphToEps<DefaultGraphToEpsTraits<G> > 1146 GraphToEps<DefaultGraphToEpsTraits<G> > 1147 1147 graphToEps(G &g, std::ostream& os=std::cout) 1148 1148 { 1149 return 1149 return 1150 1150 GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os)); 1151 1151 } 1152 1152 1153 1153 ///Generates an EPS file from a graph 1154 1154 … … 1160 1160 ///\sa graphToEps(G &g, std::ostream& os) 1161 1161 template<class G> 1162 GraphToEps<DefaultGraphToEpsTraits<G> > 1162 GraphToEps<DefaultGraphToEpsTraits<G> > 1163 1163 graphToEps(G &g,const char *file_name) 1164 1164 { … … 1176 1176 ///\sa graphToEps(G &g, std::ostream& os) 1177 1177 template<class G> 1178 GraphToEps<DefaultGraphToEpsTraits<G> > 1178 GraphToEps<DefaultGraphToEpsTraits<G> > 1179 1179 graphToEps(G &g,const std::string& file_name) 1180 1180 {
Note: See TracChangeset
for help on using the changeset viewer.

