Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

graph_to_eps.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00005  * (Egervary Combinatorial Optimization Research Group, EGRES).
00006  *
00007  * Permission to use, modify and distribute this software is granted
00008  * provided that this copyright notice appears in all copies. For
00009  * precise terms see the accompanying LICENSE file.
00010  *
00011  * This software is provided "AS IS" with no warranty of any kind,
00012  * express or implied, and with no claim as to its suitability for any
00013  * purpose.
00014  *
00015  */
00016 
00017 #ifndef LEMON_GRAPH_TO_EPS_H
00018 #define LEMON_GRAPH_TO_EPS_H
00019 
00020 #include <sys/time.h>
00021 #include <time.h>
00022 
00023 #include<iostream>
00024 #include<fstream>
00025 #include<sstream>
00026 #include<algorithm>
00027 #include<vector>
00028 
00029 #include<lemon/xy.h>
00030 #include<lemon/maps.h>
00031 #include<lemon/bezier.h>
00032 
00038 
00039 namespace lemon {
00040 
00042 
00045 class Color
00046 {
00047   double _r,_g,_b;
00048 public:
00050   Color() {}
00052   Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
00054   double getR() {return _r;}
00056   double getG() {return _g;}
00058   double getB() {return _b;}
00060   void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
00061 };
00062   
00064 
00068 template<class G>
00069 struct DefaultGraphToEpsTraits
00070 {
00071   typedef G Graph;
00072   typedef typename Graph::Node Node;
00073   typedef typename Graph::NodeIt NodeIt;
00074   typedef typename Graph::Edge Edge;
00075   typedef typename Graph::EdgeIt EdgeIt;
00076   typedef typename Graph::InEdgeIt InEdgeIt;
00077   typedef typename Graph::OutEdgeIt OutEdgeIt;
00078   
00079 
00080   const Graph &g;
00081 
00082   std::ostream& os;
00083   
00084   ConstMap<typename Graph::Node,xy<double> > _coords;
00085   ConstMap<typename Graph::Node,double > _nodeSizes;
00086   ConstMap<typename Graph::Node,int > _nodeShapes;
00087 
00088   ConstMap<typename Graph::Node,Color > _nodeColors;
00089   ConstMap<typename Graph::Edge,Color > _edgeColors;
00090 
00091   ConstMap<typename Graph::Edge,double > _edgeWidths;
00092 
00093   static const double A4HEIGHT = 841.8897637795276;
00094   static const double A4WIDTH  = 595.275590551181;
00095   static const double A4BORDER = 15;
00096 
00097   
00098   double _edgeWidthScale;
00099   
00100   double _nodeScale;
00101   double _xBorder, _yBorder;
00102   double _scale;
00103   double _nodeBorderQuotient;
00104   
00105   bool _drawArrows;
00106   double _arrowLength, _arrowWidth;
00107   
00108   bool _showNodes, _showEdges;
00109 
00110   bool _enableParallel;
00111   double _parEdgeDist;
00112 
00113   bool _showNodeText;
00114   ConstMap<typename Graph::Node,bool > _nodeTexts;  
00115   double _nodeTextSize;
00116 
00117   bool _showNodePsText;
00118   ConstMap<typename Graph::Node,bool > _nodePsTexts;  
00119   char *_nodePsTextsPreamble;
00120   
00121   bool _undir;
00122   bool _pleaseRemoveOsStream;
00123 
00124   bool _scaleToA4;
00125 
00126   std::string _title;
00127   std::string _copyright;
00128   
00130 
00138   DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
00139                           bool _pros=false) :
00140     g(_g), os(_os),
00141     _coords(xy<double>(1,1)), _nodeSizes(1.0), _nodeShapes(0),
00142     _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
00143     _edgeWidths(1), _edgeWidthScale(0.3),
00144     _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
00145     _nodeBorderQuotient(.1),
00146     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
00147     _showNodes(true), _showEdges(true),
00148     _enableParallel(false), _parEdgeDist(1),
00149     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
00150     _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
00151     _undir(false),
00152     _pleaseRemoveOsStream(_pros), _scaleToA4(false) {}
00153 };
00154 
00156 
00165 template<class T> class GraphToEps : public T 
00166 {
00167   typedef typename T::Graph Graph;
00168   typedef typename Graph::Node Node;
00169   typedef typename Graph::NodeIt NodeIt;
00170   typedef typename Graph::Edge Edge;
00171   typedef typename Graph::EdgeIt EdgeIt;
00172   typedef typename Graph::InEdgeIt InEdgeIt;
00173   typedef typename Graph::OutEdgeIt OutEdgeIt;
00174 
00175   static const int INTERPOL_PREC=20;
00176 
00177   bool dontPrint;
00178 
00179 public:
00181 
00184   enum NodeShapes { 
00188     CIRCLE=0, 
00193     SQUARE=1, 
00198     DIAMOND=2
00199   };
00200 
00201 private:
00202   class edgeLess {
00203     const Graph &g;
00204   public:
00205     edgeLess(const Graph &_g) : g(_g) {}
00206     bool operator()(Edge a,Edge b) const 
00207     {
00208       Node ai=min(g.source(a),g.target(a));
00209       Node aa=max(g.source(a),g.target(a));
00210       Node bi=min(g.source(b),g.target(b));
00211       Node ba=max(g.source(b),g.target(b));
00212       return ai<bi ||
00213         (ai==bi && (aa < ba || 
00214                     (aa==ba && ai==g.source(a) && bi==g.target(b))));
00215     }
00216   };
00217   bool isParallel(Edge e,Edge f) const
00218   {
00219     return (g.source(e)==g.source(f)&&g.target(e)==g.target(f))||
00220       (g.source(e)==g.target(f)&&g.target(e)==g.source(f));
00221   }
00222   static xy<double> rot(xy<double> v) 
00223   {
00224     return xy<double>(v.y,-v.x);
00225   }
00226   template<class xy>
00227   static std::string psOut(const xy &p) 
00228     {
00229       std::ostringstream os;    
00230       os << p.x << ' ' << p.y;
00231       return os.str();
00232     }
00233   
00234 public:
00235   GraphToEps(const T &t) : T(t), dontPrint(false) {};
00236   
00237   template<class X> struct CoordsTraits : public T {
00238     const X &_coords;
00239     CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
00240   };
00242 
00245   template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
00246     dontPrint=true;
00247     return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
00248   }
00249   template<class X> struct NodeSizesTraits : public T {
00250     const X &_nodeSizes;
00251     NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
00252   };
00254 
00257   template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
00258   {
00259     dontPrint=true;
00260     return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
00261   }
00262   template<class X> struct NodeShapesTraits : public T {
00263     const X &_nodeShapes;
00264     NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
00265   };
00267 
00273   template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
00274   {
00275     dontPrint=true;
00276     return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
00277   }
00278   template<class X> struct NodeTextsTraits : public T {
00279     const X &_nodeTexts;
00280     NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
00281   };
00283 
00287   template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
00288   {
00289     dontPrint=true;
00290     _showNodeText=true;
00291     return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
00292   }
00293   template<class X> struct NodePsTextsTraits : public T {
00294     const X &_nodePsTexts;
00295     NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
00296   };
00298 
00313   template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
00314   {
00315     dontPrint=true;
00316     _showNodePsText=true;
00317     return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
00318   }
00319   template<class X> struct EdgeWidthsTraits : public T {
00320     const X &_edgeWidths;
00321     EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
00322   };
00324 
00327   template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x)
00328   {
00329     dontPrint=true;
00330     return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x));
00331   }
00332 
00333   template<class X> struct NodeColorsTraits : public T {
00334     const X &_nodeColors;
00335     NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
00336   };
00338 
00341   template<class X> GraphToEps<NodeColorsTraits<X> >
00342   nodeColors(const X &x)
00343   {
00344     dontPrint=true;
00345     return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
00346   }
00347   template<class X> struct EdgeColorsTraits : public T {
00348     const X &_edgeColors;
00349     EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
00350   };
00352 
00355   template<class X> GraphToEps<EdgeColorsTraits<X> >
00356   edgeColors(const X &x)
00357   {
00358     dontPrint=true;
00359     return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x));
00360   }
00362 
00365   GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
00367 
00370   GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;}
00372 
00375   GraphToEps<T> &scale(double d) {_scale=d;return *this;}
00377 
00380   GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
00382 
00385   GraphToEps<T> &border(double x, double y) {
00386     _xBorder=x;_yBorder=y;return *this;
00387   }
00389 
00392   GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
00394 
00397   GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
00399 
00402   GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
00403   
00405 
00408   GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
00409   
00411 
00414   GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
00415   
00417   
00420   GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;}
00421   
00423   
00426   GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;}
00428   
00431   GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
00432   
00434   
00437   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
00439   
00443   GraphToEps<T> & nodePsTextsPreamble(const char *str) {
00444     _nodePsTextsPreamble=s ;return *this;
00445   }
00447 
00450   GraphToEps<T> &undir(bool b=true) {_undir=b;return *this;}
00452 
00455   GraphToEps<T> &bidir(bool b=true) {_undir=!b;return *this;}
00456 
00458 
00462   GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
00464 
00469   GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
00470 
00471 protected:
00472   bool isInsideNode(xy<double> p, double r,int t) 
00473   {
00474     switch(t) {
00475     case CIRCLE:
00476       return p.normSquare()<=r*r;
00477     case SQUARE:
00478       return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
00479     case DIAMOND:
00480       return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
00481     }
00482     return false;
00483   }
00484 
00485 public:
00486   ~GraphToEps() { }
00487   
00489 
00494   void run() {
00495     if(dontPrint) return;
00496     
00497     os << "%!PS-Adobe-2.0 EPSF-2.0\n";
00498     if(_title.size()>0) os << "%%Title: " << _title << '\n';
00499      if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
00500 //        << "%%Copyright: XXXX\n"
00501     os << "%%Creator: LEMON GraphToEps function\n";
00502     
00503     {
00504       char cbuf[50];
00505       timeval tv;
00506       gettimeofday(&tv, 0);
00507       ctime_r(&tv.tv_sec,cbuf);
00508       os << "%%CreationDate: " << cbuf;
00509     }
00511     BoundingBox<double> bb;
00512     for(NodeIt n(g);n!=INVALID;++n) {
00513       double ns=_nodeSizes[n]*_nodeScale;
00514       xy<double> p(ns,ns);
00515       bb+=p+_coords[n];
00516       bb+=-p+_coords[n];
00517       }
00518     if(_scaleToA4)
00519       os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
00520     else os << "%%BoundingBox: "
00521             << bb.left()*  _scale-_xBorder << ' '
00522             << bb.bottom()*_scale-_yBorder << ' '
00523             << bb.right()* _scale+_xBorder << ' '
00524             << bb.top()*   _scale+_yBorder << '\n';
00525     
00526     os << "%%EndComments\n";
00527     
00528     //x1 y1 x2 y2 x3 y3 cr cg cb w
00529     os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
00530        << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
00531     os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
00532     //x y r
00533     os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
00534     //x y r
00535     os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
00536        << "      2 index 1 index sub 2 index 2 index add lineto\n"
00537        << "      2 index 1 index sub 2 index 2 index sub lineto\n"
00538        << "      2 index 1 index add 2 index 2 index sub lineto\n"
00539        << "      closepath pop pop pop} bind def\n";
00540     //x y r
00541     os << "/di { newpath 2 index 1 index add 2 index moveto\n"
00542        << "      2 index             2 index 2 index add lineto\n"
00543        << "      2 index 1 index sub 2 index             lineto\n"
00544        << "      2 index             2 index 2 index sub lineto\n"
00545        << "      closepath pop pop pop} bind def\n";
00546     // x y r cr cg cb
00547     os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
00548        << "     setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
00549        << "   } bind def\n";
00550     os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
00551        << "     setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
00552        << "   } bind def\n";
00553     os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
00554        << "     setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
00555        << "   } bind def\n";
00556     os << "/arrl " << _arrowLength << " def\n";
00557     os << "/arrw " << _arrowWidth << " def\n";
00558     // l dx_norm dy_norm
00559     os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
00560     //len w dx_norm dy_norm x1 y1 cr cg cb
00561     os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
00562        << "       /w exch def /len exch def\n"
00563       //         << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
00564        << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
00565        << "       len w sub arrl sub dx dy lrl\n"
00566        << "       arrw dy dx neg lrl\n"
00567        << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
00568        << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
00569        << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
00570        << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
00571        << "       arrw dy dx neg lrl\n"
00572        << "       len w sub arrl sub neg dx dy lrl\n"
00573        << "       closepath fill } bind def\n";
00574     os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
00575        << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
00576 
00577     os << "\ngsave\n";
00578     if(_scaleToA4)
00579       if(bb.height()>bb.width()) {
00580         double sc= min((A4HEIGHT-2*A4BORDER)/bb.height(),
00581                   (A4WIDTH-2*A4BORDER)/bb.width());
00582         os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
00583            << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER << " translate\n"
00584            << sc << " dup scale\n"
00585            << -bb.left() << ' ' << -bb.bottom() << " translate\n";
00586       }
00587       else {
00588         //\todo Verify centering
00589         double sc= min((A4HEIGHT-2*A4BORDER)/bb.width(),
00590                   (A4WIDTH-2*A4BORDER)/bb.height());
00591         os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
00592            << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER  << " translate\n"
00593            << sc << " dup scale\n90 rotate\n"
00594            << -bb.left() << ' ' << -bb.top() << " translate\n"; 
00595         }
00596     else if(_scale!=1.0) os << _scale << " dup scale\n";
00597     
00598     if(_showEdges) {
00599       os << "%Edges:\ngsave\n";      
00600       if(_enableParallel) {
00601         std::vector<Edge> el;
00602         for(EdgeIt e(g);e!=INVALID;++e)
00603           if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
00604         sort(el.begin(),el.end(),edgeLess(g));
00605         
00606         typename std::vector<Edge>::iterator j;
00607         for(typename std::vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
00608           for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
00609 
00610           double sw=0;
00611           for(typename std::vector<Edge>::iterator e=i;e!=j;++e)
00612             sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
00613           sw-=_parEdgeDist;
00614           sw/=-2.0;
00615           xy<double> dvec(_coords[g.target(*i)]-_coords[g.source(*i)]);
00616           double l=sqrt(dvec.normSquare());
00617           xy<double> d(dvec/l);
00618           xy<double> m;
00619 //        m=xy<double>(_coords[g.target(*i)]+_coords[g.source(*i)])/2.0;
00620 
00621 //        m=xy<double>(_coords[g.source(*i)])+
00622 //          dvec*(double(_nodeSizes[g.source(*i)])/
00623 //             (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
00624 
00625           m=xy<double>(_coords[g.source(*i)])+
00626             d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
00627 
00628           for(typename std::vector<Edge>::iterator e=i;e!=j;++e) {
00629             sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
00630             xy<double> mm=m+rot(d)*sw/.75;
00631             if(_drawArrows) {
00632               int node_shape;
00633               xy<double> s=_coords[g.source(*e)];
00634               xy<double> t=_coords[g.target(*e)];
00635               double rn=_nodeSizes[g.target(*e)]*_nodeScale;
00636               node_shape=_nodeShapes[g.target(*e)];
00637               Bezier3 bez(s,mm,mm,t);
00638               double t1=0,t2=1;
00639               for(int i=0;i<INTERPOL_PREC;++i)
00640                 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
00641                 else t1=(t1+t2)/2;
00642               xy<double> apoint=bez((t1+t2)/2);
00643               rn = _arrowLength+_edgeWidths[*e]*_edgeWidthScale;
00644               rn*=rn;
00645               t2=(t1+t2)/2;t1=0;
00646               for(int i=0;i<INTERPOL_PREC;++i)
00647                 if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
00648                 else t2=(t1+t2)/2;
00649               xy<double> linend=bez((t1+t2)/2);       
00650               bez=bez.before((t1+t2)/2);
00651 //            rn=_nodeSizes[g.source(*e)]*_nodeScale;
00652 //            node_shape=_nodeShapes[g.source(*e)];
00653 //            t1=0;t2=1;
00654 //            for(int i=0;i<INTERPOL_PREC;++i)
00655 //              if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
00656 //              else t2=(t1+t2)/2;
00657 //            bez=bez.after((t1+t2)/2);
00658               os << _edgeWidths[*e]*_edgeWidthScale << " setlinewidth "
00659                  << _edgeColors[*e].getR() << ' '
00660                  << _edgeColors[*e].getG() << ' '
00661                  << _edgeColors[*e].getB() << " setrgbcolor newpath\n"
00662                  << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
00663                  << bez.p2.x << ' ' << bez.p2.y << ' '
00664                  << bez.p3.x << ' ' << bez.p3.y << ' '
00665                  << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
00666               xy<double> dd(rot(linend-apoint));
00667               dd*=(.5*_edgeWidths[*e]*_edgeWidthScale+_arrowWidth)/
00668                 sqrt(dd.normSquare());
00669               os << "newpath " << psOut(apoint) << " moveto "
00670                  << psOut(linend+dd) << " lineto "
00671                  << psOut(linend-dd) << " lineto closepath fill\n";
00672             }
00673             else {
00674               os << _coords[g.source(*e)].x << ' '
00675                  << _coords[g.source(*e)].y << ' '
00676                  << mm.x << ' ' << mm.y << ' '
00677                  << _coords[g.target(*e)].x << ' '
00678                  << _coords[g.target(*e)].y << ' '
00679                  << _edgeColors[*e].getR() << ' '
00680                  << _edgeColors[*e].getG() << ' '
00681                  << _edgeColors[*e].getB() << ' '
00682                  << _edgeWidths[*e]*_edgeWidthScale << " lb\n";
00683             }
00684             sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
00685           }
00686         }
00687       }
00688       else for(EdgeIt e(g);e!=INVALID;++e)
00689         if(!_undir||g.source(e)<g.target(e))
00690           if(_drawArrows) {
00691             xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
00692             double rn=_nodeSizes[g.target(e)]*_nodeScale;
00693             int node_shape=_nodeShapes[g.target(e)];
00694             double t1=0,t2=1;
00695             for(int i=0;i<INTERPOL_PREC;++i)
00696               if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
00697               else t2=(t1+t2)/2;
00698             double l=sqrt(d.normSquare());
00699             d/=l;
00700             
00701             os << l*(1-(t1+t2)/2) << ' '
00702                << _edgeWidths[e]*_edgeWidthScale << ' '
00703                << d.x << ' ' << d.y << ' '
00704                << _coords[g.source(e)].x << ' '
00705                << _coords[g.source(e)].y << ' '
00706                << _edgeColors[e].getR() << ' '
00707                << _edgeColors[e].getG() << ' '
00708                << _edgeColors[e].getB() << " arr\n";
00709           }
00710           else os << _coords[g.source(e)].x << ' '
00711                   << _coords[g.source(e)].y << ' '
00712                   << _coords[g.target(e)].x << ' '
00713                   << _coords[g.target(e)].y << ' '
00714                   << _edgeColors[e].getR() << ' '
00715                   << _edgeColors[e].getG() << ' '
00716                   << _edgeColors[e].getB() << ' '
00717                   << _edgeWidths[e]*_edgeWidthScale << " l\n";
00718       os << "grestore\n";
00719     }
00720     if(_showNodes) {
00721       os << "%Nodes:\ngsave\n";
00722       for(NodeIt n(g);n!=INVALID;++n) {
00723         os << _coords[n].x << ' ' << _coords[n].y << ' '
00724            << _nodeSizes[n]*_nodeScale << ' '
00725            << _nodeColors[n].getR() << ' '
00726            << _nodeColors[n].getG() << ' '
00727            << _nodeColors[n].getB() << ' ';
00728         switch(_nodeShapes[n]) {
00729         case CIRCLE:
00730           os<< "nc";break;
00731         case SQUARE:
00732           os<< "nsq";break;
00733         case DIAMOND:
00734           os<< "ndi";break;
00735         }
00736         os<<'\n';
00737       }
00738       os << "grestore\n";
00739     }
00740     if(_showNodeText) {
00741       os << "%Node texts:\ngsave\n";
00742       os << "/fosi " << _nodeTextSize << " def\n";
00743       os << "(Helvetica) findfont fosi scalefont setfont\n";
00744       os << "0 0 0 setrgbcolor\n";
00745       for(NodeIt n(g);n!=INVALID;++n)
00746         os << _coords[n].x << ' ' << _coords[n].y
00747            << " (" << _nodeTexts[n] << ") cshow\n";
00748       os << "grestore\n";
00749     }
00750     if(_showNodePsText) {
00751       os << "%Node PS blocks:\ngsave\n";
00752       for(NodeIt n(g);n!=INVALID;++n)
00753         os << _coords[n].x << ' ' << _coords[n].y
00754            << " moveto\n" << _nodePsTexts[n] << "\n";
00755       os << "grestore\n";
00756     }
00757     
00758     os << "grestore\nshowpage\n";
00759 
00760     //CleanUp:
00761     if(_pleaseRemoveOsStream) {delete &os;}
00762   } 
00763 };
00764 
00765 
00767 
00787 template<class G>
00788 GraphToEps<DefaultGraphToEpsTraits<G> > 
00789 graphToEps(G &g, std::ostream& os=std::cout)
00790 {
00791   return 
00792     GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
00793 }
00794  
00796 
00803 template<class G>
00804 GraphToEps<DefaultGraphToEpsTraits<G> > 
00805 graphToEps(G &g,const char *file_name)
00806 {
00807   return GraphToEps<DefaultGraphToEpsTraits<G> >
00808     (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
00809 }
00810 
00811 } //END OF NAMESPACE LEMON
00812 
00813 #endif // LEMON_GRAPH_TO_EPS_H

Generated on Sat Mar 19 10:58:40 2005 for LEMON by  doxygen 1.4.1