COIN-OR::LEMON - Graph Library

Changeset 1050:bcc0766a7b86 in lemon-0.x


Ignore:
Timestamp:
01/04/05 23:16:46 (20 years ago)
Author:
Alpar Juttner
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1444
Message:

Several new named parameters and documentation added to graphToEps().

Location:
src/work
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/work/Doxyfile

    r1006 r1050  
    408408                         marci/max_bipartite_matching.h \
    409409                         marci/bipartite_graph_wrapper.h \
     410                         alpar/graph_to_eps.cc \
    410411                         deba \
    411412                         
  • src/work/alpar/graph_to_eps.cc

    r1047 r1050  
     1#include<math.h>
    12#include<lemon/xy.h>
    23#include<lemon/maps.h>
    34#include<lemon/list_graph.h>
    45
    5 ///\file
     6
     7///\file \ingroup misc
    68///Simple graph drawer
    79
    810namespace lemon {
    911
    10   ///\e
     12///Data structure representing RGB colors.
     13
     14///Data structure representing RGB colors.
     15///\ingroup misc
    1116class Color
    1217{
    1318  double _r,_g,_b;
    1419public:
    15   ///\e
     20  ///Default constructor
    1621  Color() {}
    17   ///\e
     22  ///Constructor
    1823  Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
    19   ///\e
     24  ///Returns the red component
    2025  double getR() {return _r;}
    21   ///\e
     26  ///Returns the green component
    2227  double getG() {return _g;}
    23   ///\e
     28  ///Returns the blue component
    2429  double getB() {return _b;}
    25   ///\e
     30  ///Set the color components
    2631  void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
    2732};
    2833 
    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.
    3039template<class G>
    3140struct DefaultGraphToEpsTraits
     
    4150
    4251  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) {}
    5581};
    5682
    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///
    5888template<class T> class GraphToEps : public T
    5989{
     
    71101  GraphToEps(const T &t) : T(t), dontPrint(false) {};
    72102 
    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;}
    116212 
    117213  ~GraphToEps()
     
    122218    //\todo: Chech whether the graph is empty.
    123219    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];
    130225      }
    131226    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";
    136233    cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
    137234    // x y r cr cg cb
    138235    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"
    140239         << "   } 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";
    142260    cout << "%Edges:\ngsave\n";
    143261    for(NodeIt n(g);n!=INVALID;++n)
    144262      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";
    150286    cout << "grestore\n%Nodes:\ngsave\n";
    151287    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";
    158294  }
    159295};
    160296
    161297
     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
    162312template<class G>
    163313GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g)
     
    195345  typedef ListGraph::NodeIt NodeIt;
    196346  typedef ListGraph::Edge Edge;
    197   typedef xy<double> Xy;
     347  typedef xy<int> Xy;
    198348 
    199349  Node n1=g.addNode();
     
    207357  ListGraph::NodeMap<int> colors(g);
    208358  ListGraph::EdgeMap<int> ecolors(g);
     359  ListGraph::EdgeMap<int> widths(g);
    209360 
    210361  coords[n1]=Xy(50,50);  sizes[n1]=1; colors[n1]=1;
     
    216367  Edge e;
    217368
    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    ;
    230384}
Note: See TracChangeset for help on using the changeset viewer.