COIN-OR::LEMON - Graph Library

Changeset 1062:8226427845bc in lemon-0.x


Ignore:
Timestamp:
01/08/05 21:16:56 (15 years ago)
Author:
Alpar Juttner
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1458
Message:
  • Parallel edge support (without arrowheads)
  • Texts on the nodes
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
    117#include <iostream>
    218#include <fstream>
     
    925
    1026
    11 ///\file \ingroup misc
    12 ///Simple graph drawer
     27///\ingroup misc
     28///\file
     29///\brief Simple graph drawer
    1330
    1431namespace lemon {
     
    7592  double _arrowLength, _arrowWidth;
    7693 
     94  bool _showNodes, _showEdges;
     95
    7796  bool _enableParallel;
     97  double _parEdgeDist;
     98
     99  bool _showNodeText;
     100  ConstMap<typename Graph::Node,bool > _nodeTexts; 
     101  double _nodeTextSize;
    78102
    79103  bool _pleaseRemoveOsStream;
     
    96120    _nodeBorderQuotient(.1),
    97121    _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) {}
    99126};
    100127
     
    131158    }
    132159  };
    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 
    134170public:
    135171  GraphToEps(const T &t) : T(t), dontPrint(false) {};
     
    160196    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
    161197  }
     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  }
    162213   template<class X> struct EdgeWidthsTraits : public T {
    163214    const X &_edgeWidths;
     
    248299
    249300  ///Enables parallel edges
    250   ///\todo Unimplemented
     301  ///\todo Partially implemented
    251302  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
    252327 
    253328  ~GraphToEps()
     
    269344         << bb.right()* _scale+_xBorder << ' '
    270345         << 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";
    272349    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";
    274351    // x y r cr cg cb
    275352    os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
    276         << "     0 0 0 setrgbcolor dup "
    277         << _nodeBorderQuotient << " mul setlinewidth "
    278         << 1+_nodeBorderQuotient/2 << " div c stroke\n"
    279         << "   } bind def\n";
     353      << "     0 0 0 setrgbcolor dup "
     354      << _nodeBorderQuotient << " mul setlinewidth "
     355      << 1+_nodeBorderQuotient/2 << " div c stroke\n"
     356      << "   } bind def\n";
    280357    os << "/arrl " << _arrowLength << " def\n";
    281358    os << "/arrw " << _arrowWidth << " def\n";
     
    284361    //len w dx_norm dy_norm x1 y1 cr cg cb
    285362    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"
    287364      //         << "       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
    298378    os << "\ngsave\n";
    299379    if(_scale!=1.0) os << _scale << " dup scale\n";
     
    301381    os << "%Edges:\ngsave\n";
    302382   
    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)]+
    318444                     _nodeSizes[g.target(e)])*_nodeScale << ' '
    319445               << _edgeWidths[e]*_edgeWidthScale << ' '
     
    323449               << _edgeColors[e].getG() << ' '
    324450               << _edgeColors[e].getB() << " arr\n";
    325         }
    326         else os << _coords[g.source(e)].x << ' '
     451          }
     452          else os << _coords[g.source(e)].x << ' '
    327453                  << _coords[g.source(e)].y << ' '
    328454                  << _coords[g.target(e)].x << ' '
     
    333459                  << _edgeWidths[e]*_edgeWidthScale << " l\n";
    334460    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 << ' '
    337464           << _nodeSizes[n]*_nodeScale << ' '
    338465           << _nodeColors[n].getR() << ' '
    339466           << _nodeColors[n].getG() << ' '
    340467           << _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    }
    341477    os << "grestore\ngrestore\n";
    342 
    343478
    344479    //CleanUp:
     
    365500///\endcode
    366501///\sa GraphToEps
     502///\sa graphToEps(G &g, char *file_name)
    367503template<class G>
    368504GraphToEps<DefaultGraphToEpsTraits<G> >
    369 graphToEps(G &g,std::ostream& os=std::cout)
     505graphToEps(G &g, std::ostream& os=std::cout)
    370506{
    371507  return
     
    375511///Generates an EPS file from a graph
    376512
    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 named-templ-param "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)
    393519template<class G>
    394520GraphToEps<DefaultGraphToEpsTraits<G> >
     
    399525}
    400526
     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?)
    401542
    402543}
     
    423564} colorSet;
    424565
     566class IdMap :public MapBase<ListGraph::Node,int>
     567{
     568  const ListGraph &g;
     569public:
     570  IdMap(const ListGraph &_g) :g(_g) {}
     571  Value operator[](Key n) const { return g.id(n); }
     572};
     573
     574
     575
    425576int main()
    426577{
     
    459610  e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
    460611 
     612  IdMap id(g);
     613
    461614  graphToEps(g,"proba.eps").scale(10).coords(coords).
    462615    nodeScale(2).nodeSizes(sizes).
    463616    nodeColors(composeMap(colorSet,colors)).
    464617    edgeColors(composeMap(colorSet,ecolors)).
    465     edgeWidthScale(.4).edgeWidths(widths);
     618    edgeWidthScale(.4).edgeWidths(widths).
     619    nodeTexts(id).nodeTextSize(3);
     620
    466621  graphToEps(g,"proba_arr.eps").scale(10).coords(coords).
    467622    nodeScale(2).nodeSizes(sizes).
     
    469624    edgeColors(composeMap(colorSet,ecolors)).
    470625    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);
    473647}
Note: See TracChangeset for help on using the changeset viewer.