LCOV - code coverage report
Current view: top level - lemon/lemon - graph_to_eps.h (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 183 333 55.0 %
Date: 2020-07-01 15:24:36 Functions: 24 29 82.8 %
Branches: 318 1534 20.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- mode: C++; indent-tabs-mode: nil; -*-
       2                 :            :  *
       3                 :            :  * This file is a part of LEMON, a generic C++ optimization library.
       4                 :            :  *
       5                 :            :  * Copyright (C) 2003-2010
       6                 :            :  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
       7                 :            :  * (Egervary Research Group on Combinatorial Optimization, EGRES).
       8                 :            :  *
       9                 :            :  * Permission to use, modify and distribute this software is granted
      10                 :            :  * provided that this copyright notice appears in all copies. For
      11                 :            :  * precise terms see the accompanying LICENSE file.
      12                 :            :  *
      13                 :            :  * This software is provided "AS IS" with no warranty of any kind,
      14                 :            :  * express or implied, and with no claim as to its suitability for any
      15                 :            :  * purpose.
      16                 :            :  *
      17                 :            :  */
      18                 :            : 
      19                 :            : #ifndef LEMON_GRAPH_TO_EPS_H
      20                 :            : #define LEMON_GRAPH_TO_EPS_H
      21                 :            : 
      22                 :            : #include<iostream>
      23                 :            : #include<fstream>
      24                 :            : #include<sstream>
      25                 :            : #include<algorithm>
      26                 :            : #include<vector>
      27                 :            : 
      28                 :            : #ifndef _WIN32
      29                 :            : #include<sys/time.h>
      30                 :            : #include<ctime>
      31                 :            : #else
      32                 :            : #include<lemon/bits/windows.h>
      33                 :            : #endif
      34                 :            : 
      35                 :            : #include<lemon/math.h>
      36                 :            : #include<lemon/core.h>
      37                 :            : #include<lemon/dim2.h>
      38                 :            : #include<lemon/maps.h>
      39                 :            : #include<lemon/color.h>
      40                 :            : #include<lemon/bits/bezier.h>
      41                 :            : #include<lemon/error.h>
      42                 :            : 
      43                 :            : 
      44                 :            : ///\ingroup eps_io
      45                 :            : ///\file
      46                 :            : ///\brief A well configurable tool for visualizing graphs
      47                 :            : 
      48                 :            : namespace lemon {
      49                 :            : 
      50                 :            :   namespace _graph_to_eps_bits {
      51                 :            :     template<class MT>
      52                 :            :     class _NegY {
      53                 :            :     public:
      54                 :            :       typedef typename MT::Key Key;
      55                 :            :       typedef typename MT::Value Value;
      56                 :            :       const MT &map;
      57                 :            :       int yscale;
      58                 :         18 :       _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
      59                 :       5958 :       Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
      60                 :            :     };
      61                 :            :   }
      62                 :            : 
      63                 :            : ///Default traits class of GraphToEps
      64                 :            : 
      65                 :            : ///Default traits class of \ref GraphToEps.
      66                 :            : ///
      67                 :            : ///\param GR is the type of the underlying graph.
      68                 :            : template<class GR>
      69         [ +  - ]:        306 : struct DefaultGraphToEpsTraits
      70                 :            : {
      71                 :            :   typedef GR Graph;
      72                 :            :   typedef GR Digraph;
      73                 :            :   typedef typename Graph::Node Node;
      74                 :            :   typedef typename Graph::NodeIt NodeIt;
      75                 :            :   typedef typename Graph::Arc Arc;
      76                 :            :   typedef typename Graph::ArcIt ArcIt;
      77                 :            :   typedef typename Graph::InArcIt InArcIt;
      78                 :            :   typedef typename Graph::OutArcIt OutArcIt;
      79                 :            : 
      80                 :            : 
      81                 :            :   const Graph &g;
      82                 :            : 
      83                 :            :   std::ostream& os;
      84                 :            : 
      85                 :            :   typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
      86                 :            :   CoordsMapType _coords;
      87                 :            :   ConstMap<typename Graph::Node,double > _nodeSizes;
      88                 :            :   ConstMap<typename Graph::Node,int > _nodeShapes;
      89                 :            : 
      90                 :            :   ConstMap<typename Graph::Node,Color > _nodeColors;
      91                 :            :   ConstMap<typename Graph::Arc,Color > _arcColors;
      92                 :            : 
      93                 :            :   ConstMap<typename Graph::Arc,double > _arcWidths;
      94                 :            : 
      95                 :            :   double _arcWidthScale;
      96                 :            : 
      97                 :            :   double _nodeScale;
      98                 :            :   double _xBorder, _yBorder;
      99                 :            :   double _scale;
     100                 :            :   double _nodeBorderQuotient;
     101                 :            : 
     102                 :            :   bool _drawArrows;
     103                 :            :   double _arrowLength, _arrowWidth;
     104                 :            : 
     105                 :            :   bool _showNodes, _showArcs;
     106                 :            : 
     107                 :            :   bool _enableParallel;
     108                 :            :   double _parArcDist;
     109                 :            : 
     110                 :            :   bool _showNodeText;
     111                 :            :   ConstMap<typename Graph::Node,bool > _nodeTexts;
     112                 :            :   double _nodeTextSize;
     113                 :            : 
     114                 :            :   bool _showNodePsText;
     115                 :            :   ConstMap<typename Graph::Node,bool > _nodePsTexts;
     116                 :            :   char *_nodePsTextsPreamble;
     117                 :            : 
     118                 :            :   bool _undirected;
     119                 :            : 
     120                 :            :   bool _pleaseRemoveOsStream;
     121                 :            : 
     122                 :            :   bool _scaleToA4;
     123                 :            : 
     124                 :            :   std::string _title;
     125                 :            :   std::string _copyright;
     126                 :            : 
     127                 :            :   enum NodeTextColorType
     128                 :            :     { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
     129                 :            :   ConstMap<typename Graph::Node,Color > _nodeTextColors;
     130                 :            : 
     131                 :            :   bool _autoNodeScale;
     132                 :            :   bool _autoArcWidthScale;
     133                 :            : 
     134                 :            :   bool _absoluteNodeSizes;
     135                 :            :   bool _absoluteArcWidths;
     136                 :            : 
     137                 :            :   bool _negY;
     138                 :            : 
     139                 :            :   bool _preScale;
     140                 :            :   ///Constructor
     141                 :            : 
     142                 :            :   ///Constructor
     143                 :            :   ///\param gr  Reference to the graph to be printed.
     144                 :            :   ///\param ost Reference to the output stream.
     145                 :            :   ///By default, it is <tt>std::cout</tt>.
     146                 :            :   ///\param pros If it is \c true, then the \c ostream referenced by \c os
     147                 :            :   ///will be explicitly deallocated by the destructor.
     148                 :         18 :   DefaultGraphToEpsTraits(const GR &gr, std::ostream& ost = std::cout,
     149                 :            :                           bool pros = false) :
     150                 :            :     g(gr), os(ost),
     151                 :            :     _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
     152                 :            :     _nodeColors(WHITE), _arcColors(BLACK),
     153                 :            :     _arcWidths(1.0), _arcWidthScale(0.003),
     154                 :            :     _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
     155                 :            :     _nodeBorderQuotient(.1),
     156                 :            :     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
     157                 :            :     _showNodes(true), _showArcs(true),
     158                 :            :     _enableParallel(false), _parArcDist(1),
     159                 :            :     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
     160                 :            :     _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
     161                 :            :     _undirected(lemon::UndirectedTagIndicator<GR>::value),
     162                 :            :     _pleaseRemoveOsStream(pros), _scaleToA4(false),
     163                 :            :     _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
     164                 :            :     _autoNodeScale(false),
     165                 :            :     _autoArcWidthScale(false),
     166                 :            :     _absoluteNodeSizes(false),
     167                 :            :     _absoluteArcWidths(false),
     168                 :            :     _negY(false),
     169 [ +  - ][ +  - ]:         18 :     _preScale(true)
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     170                 :         18 :   {}
     171                 :            : };
     172                 :            : 
     173                 :            : ///Auxiliary class to implement the named parameters of \ref graphToEps()
     174                 :            : 
     175                 :            : ///Auxiliary class to implement the named parameters of \ref graphToEps().
     176                 :            : ///
     177                 :            : ///For detailed examples see the \ref graph_to_eps_demo.cc demo file.
     178                 :            : template<class T> class GraphToEps : public T
     179                 :            : {
     180                 :            :   // Can't believe it is required by the C++ standard
     181                 :            :   using T::g;
     182                 :            :   using T::os;
     183                 :            : 
     184                 :            :   using T::_coords;
     185                 :            :   using T::_nodeSizes;
     186                 :            :   using T::_nodeShapes;
     187                 :            :   using T::_nodeColors;
     188                 :            :   using T::_arcColors;
     189                 :            :   using T::_arcWidths;
     190                 :            : 
     191                 :            :   using T::_arcWidthScale;
     192                 :            :   using T::_nodeScale;
     193                 :            :   using T::_xBorder;
     194                 :            :   using T::_yBorder;
     195                 :            :   using T::_scale;
     196                 :            :   using T::_nodeBorderQuotient;
     197                 :            : 
     198                 :            :   using T::_drawArrows;
     199                 :            :   using T::_arrowLength;
     200                 :            :   using T::_arrowWidth;
     201                 :            : 
     202                 :            :   using T::_showNodes;
     203                 :            :   using T::_showArcs;
     204                 :            : 
     205                 :            :   using T::_enableParallel;
     206                 :            :   using T::_parArcDist;
     207                 :            : 
     208                 :            :   using T::_showNodeText;
     209                 :            :   using T::_nodeTexts;
     210                 :            :   using T::_nodeTextSize;
     211                 :            : 
     212                 :            :   using T::_showNodePsText;
     213                 :            :   using T::_nodePsTexts;
     214                 :            :   using T::_nodePsTextsPreamble;
     215                 :            : 
     216                 :            :   using T::_undirected;
     217                 :            : 
     218                 :            :   using T::_pleaseRemoveOsStream;
     219                 :            : 
     220                 :            :   using T::_scaleToA4;
     221                 :            : 
     222                 :            :   using T::_title;
     223                 :            :   using T::_copyright;
     224                 :            : 
     225                 :            :   using typename T::NodeTextColorType;
     226                 :            :   using T::CUST_COL;
     227                 :            :   using T::DIST_COL;
     228                 :            :   using T::DIST_BW;
     229                 :            :   using T::_nodeTextColorType;
     230                 :            :   using T::_nodeTextColors;
     231                 :            : 
     232                 :            :   using T::_autoNodeScale;
     233                 :            :   using T::_autoArcWidthScale;
     234                 :            : 
     235                 :            :   using T::_absoluteNodeSizes;
     236                 :            :   using T::_absoluteArcWidths;
     237                 :            : 
     238                 :            : 
     239                 :            :   using T::_negY;
     240                 :            :   using T::_preScale;
     241                 :            : 
     242                 :            :   // dradnats ++C eht yb deriuqer si ti eveileb t'naC
     243                 :            : 
     244                 :            :   typedef typename T::Graph Graph;
     245                 :            :   typedef typename T::Digraph Digraph;
     246                 :            :   typedef typename Graph::Node Node;
     247                 :            :   typedef typename Graph::NodeIt NodeIt;
     248                 :            :   typedef typename Graph::Arc Arc;
     249                 :            :   typedef typename Graph::ArcIt ArcIt;
     250                 :            :   typedef typename Graph::InArcIt InArcIt;
     251                 :            :   typedef typename Graph::OutArcIt OutArcIt;
     252                 :            : 
     253                 :            :   static const int INTERPOL_PREC;
     254                 :            :   static const double A4HEIGHT;
     255                 :            :   static const double A4WIDTH;
     256                 :            :   static const double A4BORDER;
     257                 :            : 
     258                 :            :   bool dontPrint;
     259                 :            : 
     260                 :            : public:
     261                 :            :   ///Node shapes
     262                 :            : 
     263                 :            :   ///Node shapes.
     264                 :            :   ///
     265                 :            :   enum NodeShapes {
     266                 :            :     /// = 0
     267                 :            :     ///\image html nodeshape_0.png
     268                 :            :     ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
     269                 :            :     CIRCLE=0,
     270                 :            :     /// = 1
     271                 :            :     ///\image html nodeshape_1.png
     272                 :            :     ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
     273                 :            :     SQUARE=1,
     274                 :            :     /// = 2
     275                 :            :     ///\image html nodeshape_2.png
     276                 :            :     ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
     277                 :            :     DIAMOND=2,
     278                 :            :     /// = 3
     279                 :            :     ///\image html nodeshape_3.png
     280                 :            :     ///\image latex nodeshape_3.eps "MALE shape (3)" width=2cm
     281                 :            :     MALE=3,
     282                 :            :     /// = 4
     283                 :            :     ///\image html nodeshape_4.png
     284                 :            :     ///\image latex nodeshape_4.eps "FEMALE shape (4)" width=2cm
     285                 :            :     FEMALE=4
     286                 :            :   };
     287                 :            : 
     288                 :            : private:
     289                 :            :   class arcLess {
     290                 :            :     const Graph &g;
     291                 :            :   public:
     292                 :          0 :     arcLess(const Graph &_g) : g(_g) {}
     293                 :          0 :     bool operator()(Arc a,Arc b) const
     294                 :            :     {
     295 [ #  # ][ #  # ]:          0 :       Node ai=std::min(g.source(a),g.target(a));
                 [ #  # ]
     296 [ #  # ][ #  # ]:          0 :       Node aa=std::max(g.source(a),g.target(a));
                 [ #  # ]
     297 [ #  # ][ #  # ]:          0 :       Node bi=std::min(g.source(b),g.target(b));
                 [ #  # ]
     298 [ #  # ][ #  # ]:          0 :       Node ba=std::max(g.source(b),g.target(b));
                 [ #  # ]
     299         [ #  # ]:          0 :       return ai<bi ||
     300 [ #  # ][ #  # ]:          0 :         (ai==bi && (aa < ba ||
     301 [ #  # ][ #  # ]:          0 :                     (aa==ba && ai==g.source(a) && bi==g.target(b))));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     302                 :            :     }
     303                 :            :   };
     304                 :          0 :   bool isParallel(Arc e,Arc f) const
     305                 :            :   {
     306 [ #  # ][ #  # ]:          0 :     return (g.source(e)==g.source(f)&&
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     307 [ #  # ][ #  # ]:          0 :             g.target(e)==g.target(f)) ||
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     308 [ #  # ][ #  # ]:          0 :       (g.source(e)==g.target(f)&&
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     309 [ #  # ][ #  # ]:          0 :        g.target(e)==g.source(f));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     310                 :            :   }
     311                 :            :   template<class TT>
     312                 :          0 :   static std::string psOut(const dim2::Point<TT> &p)
     313                 :            :     {
     314         [ #  # ]:          0 :       std::ostringstream os;
     315 [ #  # ][ #  # ]:          0 :       os << p.x << ' ' << p.y;
                 [ #  # ]
     316         [ #  # ]:          0 :       return os.str();
     317                 :            :     }
     318                 :          0 :   static std::string psOut(const Color &c)
     319                 :            :     {
     320         [ #  # ]:          0 :       std::ostringstream os;
     321 [ #  # ][ #  # ]:          0 :       os << c.red() << ' ' << c.green() << ' ' << c.blue();
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     322         [ #  # ]:          0 :       return os.str();
     323                 :            :     }
     324                 :            : 
     325                 :            : public:
     326                 :        108 :   GraphToEps(const T &t) : T(t), dontPrint(false) {};
     327                 :            : 
     328                 :        252 :   template<class X> struct CoordsTraits : public T {
     329                 :            :   typedef X CoordsMapType;
     330                 :            :     const X &_coords;
     331                 :         36 :     CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
     332                 :            :   };
     333                 :            :   ///Sets the map of the node coordinates
     334                 :            : 
     335                 :            :   ///Sets the map of the node coordinates.
     336                 :            :   ///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or
     337                 :            :   ///\ref dim2::Point "dim2::Point<int>" values.
     338                 :         18 :   template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
     339                 :         18 :     dontPrint=true;
     340         [ +  - ]:         18 :     return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
     341                 :            :   }
     342                 :            :   template<class X> struct NodeSizesTraits : public T {
     343                 :            :     const X &_nodeSizes;
     344                 :            :     NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
     345                 :            :   };
     346                 :            :   ///Sets the map of the node sizes
     347                 :            : 
     348                 :            :   ///Sets the map of the node sizes.
     349                 :            :   ///\param x must be a node map with \c double (or convertible) values.
     350                 :            :   template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
     351                 :            :   {
     352                 :            :     dontPrint=true;
     353                 :            :     return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
     354                 :            :   }
     355                 :            :   template<class X> struct NodeShapesTraits : public T {
     356                 :            :     const X &_nodeShapes;
     357                 :            :     NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
     358                 :            :   };
     359                 :            :   ///Sets the map of the node shapes
     360                 :            : 
     361                 :            :   ///Sets the map of the node shapes.
     362                 :            :   ///The available shape values
     363                 :            :   ///can be found in \ref NodeShapes "enum NodeShapes".
     364                 :            :   ///\param x must be a node map with \c int (or convertible) values.
     365                 :            :   ///\sa NodeShapes
     366                 :            :   template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
     367                 :            :   {
     368                 :            :     dontPrint=true;
     369                 :            :     return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
     370                 :            :   }
     371                 :        108 :   template<class X> struct NodeTextsTraits : public T {
     372                 :            :     const X &_nodeTexts;
     373                 :         36 :     NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
     374                 :            :   };
     375                 :            :   ///Sets the text printed on the nodes
     376                 :            : 
     377                 :            :   ///Sets the text printed on the nodes.
     378                 :            :   ///\param x must be a node map with type that can be pushed to a standard
     379                 :            :   ///\c ostream.
     380                 :         18 :   template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
     381                 :            :   {
     382                 :         18 :     dontPrint=true;
     383                 :         18 :     _showNodeText=true;
     384         [ +  - ]:         18 :     return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
     385                 :            :   }
     386                 :            :   template<class X> struct NodePsTextsTraits : public T {
     387                 :            :     const X &_nodePsTexts;
     388                 :            :     NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
     389                 :            :   };
     390                 :            :   ///Inserts a PostScript block to the nodes
     391                 :            : 
     392                 :            :   ///With this command it is possible to insert a verbatim PostScript
     393                 :            :   ///block to the nodes.
     394                 :            :   ///The PS current point will be moved to the center of the node before
     395                 :            :   ///the PostScript block inserted.
     396                 :            :   ///
     397                 :            :   ///Before and after the block a newline character is inserted so you
     398                 :            :   ///don't have to bother with the separators.
     399                 :            :   ///
     400                 :            :   ///\param x must be a node map with type that can be pushed to a standard
     401                 :            :   ///\c ostream.
     402                 :            :   ///
     403                 :            :   ///\sa nodePsTextsPreamble()
     404                 :            :   template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
     405                 :            :   {
     406                 :            :     dontPrint=true;
     407                 :            :     _showNodePsText=true;
     408                 :            :     return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
     409                 :            :   }
     410                 :            :   template<class X> struct ArcWidthsTraits : public T {
     411                 :            :     const X &_arcWidths;
     412                 :            :     ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
     413                 :            :   };
     414                 :            :   ///Sets the map of the arc widths
     415                 :            : 
     416                 :            :   ///Sets the map of the arc widths.
     417                 :            :   ///\param x must be an arc map with \c double (or convertible) values.
     418                 :            :   template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
     419                 :            :   {
     420                 :            :     dontPrint=true;
     421                 :            :     return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
     422                 :            :   }
     423                 :            : 
     424                 :            :   template<class X> struct NodeColorsTraits : public T {
     425                 :            :     const X &_nodeColors;
     426                 :            :     NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
     427                 :            :   };
     428                 :            :   ///Sets the map of the node colors
     429                 :            : 
     430                 :            :   ///Sets the map of the node colors.
     431                 :            :   ///\param x must be a node map with \ref Color values.
     432                 :            :   ///
     433                 :            :   ///\sa Palette
     434                 :            :   template<class X> GraphToEps<NodeColorsTraits<X> >
     435                 :            :   nodeColors(const X &x)
     436                 :            :   {
     437                 :            :     dontPrint=true;
     438                 :            :     return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
     439                 :            :   }
     440                 :            :   template<class X> struct NodeTextColorsTraits : public T {
     441                 :            :     const X &_nodeTextColors;
     442                 :            :     NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
     443                 :            :   };
     444                 :            :   ///Sets the map of the node text colors
     445                 :            : 
     446                 :            :   ///Sets the map of the node text colors.
     447                 :            :   ///\param x must be a node map with \ref Color values.
     448                 :            :   ///
     449                 :            :   ///\sa Palette
     450                 :            :   template<class X> GraphToEps<NodeTextColorsTraits<X> >
     451                 :            :   nodeTextColors(const X &x)
     452                 :            :   {
     453                 :            :     dontPrint=true;
     454                 :            :     _nodeTextColorType=CUST_COL;
     455                 :            :     return GraphToEps<NodeTextColorsTraits<X> >
     456                 :            :       (NodeTextColorsTraits<X>(*this,x));
     457                 :            :   }
     458                 :            :   template<class X> struct ArcColorsTraits : public T {
     459                 :            :     const X &_arcColors;
     460                 :            :     ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
     461                 :            :   };
     462                 :            :   ///Sets the map of the arc colors
     463                 :            : 
     464                 :            :   ///Sets the map of the arc colors.
     465                 :            :   ///\param x must be an arc map with \ref Color values.
     466                 :            :   ///
     467                 :            :   ///\sa Palette
     468                 :            :   template<class X> GraphToEps<ArcColorsTraits<X> >
     469                 :            :   arcColors(const X &x)
     470                 :            :   {
     471                 :            :     dontPrint=true;
     472                 :            :     return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
     473                 :            :   }
     474                 :            :   ///Sets a global scale factor for node sizes
     475                 :            : 
     476                 :            :   ///Sets a global scale factor for node sizes.
     477                 :            :   ///
     478                 :            :   /// If nodeSizes() is not given, this function simply sets the node
     479                 :            :   /// sizes to \c d.  If nodeSizes() is given, but
     480                 :            :   /// autoNodeScale() is not, then the node size given by
     481                 :            :   /// nodeSizes() will be multiplied by the value \c d.
     482                 :            :   /// If both nodeSizes() and autoNodeScale() are used, then the
     483                 :            :   /// node sizes will be scaled in such a way that the greatest size will be
     484                 :            :   /// equal to \c d.
     485                 :            :   /// \sa nodeSizes()
     486                 :            :   /// \sa autoNodeScale()
     487                 :            :   GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
     488                 :            :   ///Turns on/off the automatic node size scaling.
     489                 :            : 
     490                 :            :   ///Turns on/off the automatic node size scaling.
     491                 :            :   ///
     492                 :            :   ///\sa nodeScale()
     493                 :            :   ///
     494                 :            :   GraphToEps<T> &autoNodeScale(bool b=true) {
     495                 :            :     _autoNodeScale=b;return *this;
     496                 :            :   }
     497                 :            : 
     498                 :            :   ///Turns on/off the absolutematic node size scaling.
     499                 :            : 
     500                 :            :   ///Turns on/off the absolutematic node size scaling.
     501                 :            :   ///
     502                 :            :   ///\sa nodeScale()
     503                 :            :   ///
     504                 :            :   GraphToEps<T> &absoluteNodeSizes(bool b=true) {
     505                 :            :     _absoluteNodeSizes=b;return *this;
     506                 :            :   }
     507                 :            : 
     508                 :            :   ///Negates the Y coordinates.
     509                 :            :   GraphToEps<T> &negateY(bool b=true) {
     510                 :            :     _negY=b;return *this;
     511                 :            :   }
     512                 :            : 
     513                 :            :   ///Turn on/off pre-scaling
     514                 :            : 
     515                 :            :   ///By default, graphToEps() rescales the whole image in order to avoid
     516                 :            :   ///very big or very small bounding boxes.
     517                 :            :   ///
     518                 :            :   ///This (p)rescaling can be turned off with this function.
     519                 :            :   ///
     520                 :            :   GraphToEps<T> &preScale(bool b=true) {
     521                 :            :     _preScale=b;return *this;
     522                 :            :   }
     523                 :            : 
     524                 :            :   ///Sets a global scale factor for arc widths
     525                 :            : 
     526                 :            :   /// Sets a global scale factor for arc widths.
     527                 :            :   ///
     528                 :            :   /// If arcWidths() is not given, this function simply sets the arc
     529                 :            :   /// widths to \c d.  If arcWidths() is given, but
     530                 :            :   /// autoArcWidthScale() is not, then the arc withs given by
     531                 :            :   /// arcWidths() will be multiplied by the value \c d.
     532                 :            :   /// If both arcWidths() and autoArcWidthScale() are used, then the
     533                 :            :   /// arc withs will be scaled in such a way that the greatest width will be
     534                 :            :   /// equal to \c d.
     535                 :            :   GraphToEps<T> &arcWidthScale(double d=.003) {_arcWidthScale=d;return *this;}
     536                 :            :   ///Turns on/off the automatic arc width scaling.
     537                 :            : 
     538                 :            :   ///Turns on/off the automatic arc width scaling.
     539                 :            :   ///
     540                 :            :   ///\sa arcWidthScale()
     541                 :            :   ///
     542                 :            :   GraphToEps<T> &autoArcWidthScale(bool b=true) {
     543                 :            :     _autoArcWidthScale=b;return *this;
     544                 :            :   }
     545                 :            :   ///Turns on/off the absolutematic arc width scaling.
     546                 :            : 
     547                 :            :   ///Turns on/off the absolutematic arc width scaling.
     548                 :            :   ///
     549                 :            :   ///\sa arcWidthScale()
     550                 :            :   ///
     551                 :            :   GraphToEps<T> &absoluteArcWidths(bool b=true) {
     552                 :            :     _absoluteArcWidths=b;return *this;
     553                 :            :   }
     554                 :            :   ///Sets a global scale factor for the whole picture
     555                 :            :   GraphToEps<T> &scale(double d) {_scale=d;return *this;}
     556                 :            :   ///Sets the width of the border around the picture
     557                 :            :   GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
     558                 :            :   ///Sets the width of the border around the picture
     559                 :            :   GraphToEps<T> &border(double x, double y) {
     560                 :            :     _xBorder=x;_yBorder=y;return *this;
     561                 :            :   }
     562                 :            :   ///Sets whether to draw arrows
     563                 :         36 :   GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
     564                 :            :   ///Sets the length of the arrowheads
     565                 :            :   GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
     566                 :            :   ///Sets the width of the arrowheads
     567                 :            :   GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
     568                 :            : 
     569                 :            :   ///Scales the drawing to fit to A4 page
     570                 :            :   GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
     571                 :            : 
     572                 :            :   ///Enables parallel arcs
     573                 :            :   GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
     574                 :            : 
     575                 :            :   ///Sets the distance between parallel arcs
     576                 :            :   GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
     577                 :            : 
     578                 :            :   ///Hides the arcs
     579                 :            :   GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
     580                 :            :   ///Hides the nodes
     581                 :            :   GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
     582                 :            : 
     583                 :            :   ///Sets the size of the node texts
     584                 :         36 :   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
     585                 :            : 
     586                 :            :   ///Sets the color of the node texts to be different from the node color
     587                 :            : 
     588                 :            :   ///Sets the color of the node texts to be as different from the node color
     589                 :            :   ///as it is possible.
     590                 :            :   GraphToEps<T> &distantColorNodeTexts()
     591                 :            :   {_nodeTextColorType=DIST_COL;return *this;}
     592                 :            :   ///Sets the color of the node texts to be black or white and always visible.
     593                 :            : 
     594                 :            :   ///Sets the color of the node texts to be black or white according to
     595                 :            :   ///which is more different from the node color.
     596                 :            :   GraphToEps<T> &distantBWNodeTexts()
     597                 :            :   {_nodeTextColorType=DIST_BW;return *this;}
     598                 :            : 
     599                 :            :   ///Gives a preamble block for node Postscript block.
     600                 :            : 
     601                 :            :   ///Gives a preamble block for node Postscript block.
     602                 :            :   ///
     603                 :            :   ///\sa nodePsTexts()
     604                 :            :   GraphToEps<T> & nodePsTextsPreamble(const char *str) {
     605                 :            :     _nodePsTextsPreamble=str ;return *this;
     606                 :            :   }
     607                 :            :   ///Sets whether the graph is undirected
     608                 :            : 
     609                 :            :   ///Sets whether the graph is undirected.
     610                 :            :   ///
     611                 :            :   ///This setting is the default for undirected graphs.
     612                 :            :   ///
     613                 :            :   ///\sa directed()
     614                 :            :    GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
     615                 :            : 
     616                 :            :   ///Sets whether the graph is directed
     617                 :            : 
     618                 :            :   ///Sets whether the graph is directed.
     619                 :            :   ///Use it to show the edges as a pair of directed ones.
     620                 :            :   ///
     621                 :            :   ///This setting is the default for digraphs.
     622                 :            :   ///
     623                 :            :   ///\sa undirected()
     624                 :            :   GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
     625                 :            : 
     626                 :            :   ///Sets the title.
     627                 :            : 
     628                 :            :   ///Sets the title of the generated image,
     629                 :            :   ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
     630                 :            :   ///the EPS file.
     631                 :            :   GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
     632                 :            :   ///Sets the copyright statement.
     633                 :            : 
     634                 :            :   ///Sets the copyright statement of the generated image,
     635                 :            :   ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
     636                 :            :   ///the EPS file.
     637                 :            :   GraphToEps<T> &copyright(const std::string &t) {_copyright=t;return *this;}
     638                 :            : 
     639                 :            : protected:
     640                 :       6600 :   bool isInsideNode(dim2::Point<double> p, double r,int t)
     641                 :            :   {
     642   [ +  -  -  - ]:       6600 :     switch(t) {
     643                 :            :     case CIRCLE:
     644                 :            :     case MALE:
     645                 :            :     case FEMALE:
     646                 :       6600 :       return p.normSquare()<=r*r;
     647                 :            :     case SQUARE:
     648 [ #  # ][ #  # ]:          0 :       return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
         [ #  # ][ #  # ]
     649                 :            :     case DIAMOND:
     650 [ #  # ][ #  # ]:          0 :       return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
         [ #  # ][ #  # ]
     651                 :            :     }
     652                 :          0 :     return false;
     653                 :            :   }
     654                 :            : 
     655                 :            : public:
     656                 :        108 :   ~GraphToEps() { }
     657                 :            : 
     658                 :            :   ///Draws the graph.
     659                 :            : 
     660                 :            :   ///Like other functions using
     661                 :            :   ///\ref named-templ-func-param "named template parameters",
     662                 :            :   ///this function calls the algorithm itself, i.e. in this case
     663                 :            :   ///it draws the graph.
     664                 :         18 :   void run() {
     665                 :         18 :     const double EPSILON=1e-9;
     666         [ -  + ]:         36 :     if(dontPrint) return;
     667                 :            : 
     668                 :            :     _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
     669         [ +  - ]:         18 :       mycoords(_coords,_negY);
     670                 :            : 
     671         [ +  - ]:         18 :     os << "%!PS-Adobe-2.0 EPSF-2.0\n";
     672 [ -  + ][ #  # ]:         18 :     if(_title.size()>0) os << "%%Title: " << _title << '\n';
         [ #  # ][ #  # ]
     673 [ -  + ][ #  # ]:         18 :      if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
         [ #  # ][ #  # ]
     674         [ +  - ]:         18 :     os << "%%Creator: LEMON, graphToEps()\n";
     675                 :            : 
     676                 :            :     {
     677         [ +  - ]:         18 :       os << "%%CreationDate: ";
     678                 :            : #ifndef _WIN32
     679                 :            :       timeval tv;
     680                 :         18 :       gettimeofday(&tv, 0);
     681                 :            : 
     682                 :            :       char cbuf[26];
     683                 :         18 :       ctime_r(&tv.tv_sec,cbuf);
     684         [ +  - ]:         18 :       os << cbuf;
     685                 :            : #else
     686                 :            :       os << bits::getWinFormattedDate();
     687                 :            :       os << std::endl;
     688                 :            : #endif
     689                 :            :     }
     690                 :            : 
     691         [ -  + ]:         18 :     if (_autoArcWidthScale) {
     692                 :          0 :       double max_w=0;
     693 [ #  # ][ #  # ]:          0 :       for(ArcIt e(g);e!=INVALID;++e)
         [ #  # ][ #  # ]
                 [ #  # ]
     694 [ #  # ][ #  # ]:          0 :         max_w=std::max(double(_arcWidths[e]),max_w);
     695         [ #  # ]:          0 :       if(max_w>EPSILON) {
     696                 :          0 :         _arcWidthScale/=max_w;
     697                 :            :       }
     698                 :            :     }
     699                 :            : 
     700         [ -  + ]:         18 :     if (_autoNodeScale) {
     701                 :          0 :       double max_s=0;
     702 [ #  # ][ #  # ]:          0 :       for(NodeIt n(g);n!=INVALID;++n)
         [ #  # ][ #  # ]
                 [ #  # ]
     703 [ #  # ][ #  # ]:          0 :         max_s=std::max(double(_nodeSizes[n]),max_s);
     704         [ #  # ]:          0 :       if(max_s>EPSILON) {
     705                 :          0 :         _nodeScale/=max_s;
     706                 :            :       }
     707                 :            :     }
     708                 :            : 
     709                 :         18 :     double diag_len = 1;
     710 [ -  + ][ #  # ]:         18 :     if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
     711         [ +  - ]:         18 :       dim2::Box<double> bb;
     712 [ +  - ][ +  - ]:        255 :       for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  + ]
     713 [ +  - ][ -  + ]:         18 :       if (bb.empty()) {
     714 [ #  # ][ #  # ]:          0 :         bb = dim2::Box<double>(dim2::Point<double>(0,0));
     715                 :            :       }
     716 [ +  - ][ +  - ]:         18 :       diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
         [ +  - ][ +  - ]
     717         [ -  + ]:         18 :       if(diag_len<EPSILON) diag_len = 1;
     718         [ +  - ]:         18 :       if(!_absoluteNodeSizes) _nodeScale*=diag_len;
     719         [ +  - ]:         18 :       if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
     720                 :            :     }
     721                 :            : 
     722         [ +  - ]:         18 :     dim2::Box<double> bb;
     723 [ +  - ][ +  - ]:        255 :     for(NodeIt n(g);n!=INVALID;++n) {
         [ +  - ][ +  - ]
                 [ +  + ]
     724         [ +  - ]:        237 :       double ns=_nodeSizes[n]*_nodeScale;
     725         [ +  - ]:        237 :       dim2::Point<double> p(ns,ns);
     726         [ +  - ]:        237 :       switch(_nodeShapes[n]) {
           [ +  -  -  - ]
     727                 :            :       case CIRCLE:
     728                 :            :       case SQUARE:
     729                 :            :       case DIAMOND:
     730 [ +  - ][ +  - ]:        237 :         bb.add(p+mycoords[n]);
         [ +  - ][ +  - ]
     731 [ +  - ][ +  - ]:        237 :         bb.add(-p+mycoords[n]);
         [ +  - ][ +  - ]
                 [ +  - ]
     732                 :        237 :         break;
     733                 :            :       case MALE:
     734 [ #  # ][ #  # ]:          0 :         bb.add(-p+mycoords[n]);
         [ #  # ][ #  # ]
                 [ #  # ]
     735 [ #  # ][ #  # ]:          0 :         bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
         [ #  # ][ #  # ]
                 [ #  # ]
     736                 :          0 :         break;
     737                 :            :       case FEMALE:
     738 [ #  # ][ #  # ]:          0 :         bb.add(p+mycoords[n]);
         [ #  # ][ #  # ]
     739 [ #  # ][ #  # ]:          0 :         bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
         [ #  # ][ #  # ]
                 [ #  # ]
     740                 :          0 :         break;
     741                 :            :       }
     742                 :            :     }
     743 [ +  - ][ -  + ]:         18 :     if (bb.empty()) {
     744 [ #  # ][ #  # ]:          0 :       bb = dim2::Box<double>(dim2::Point<double>(0,0));
     745                 :            :     }
     746                 :            : 
     747         [ -  + ]:         18 :     if(_scaleToA4)
     748         [ #  # ]:          0 :       os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
     749                 :            :     else {
     750         [ +  - ]:         18 :       if(_preScale) {
     751                 :            :         //Rescale so that BoundingBox won't be neither to big nor too small.
     752 [ +  - ][ +  - ]:         18 :         while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
         [ +  - ][ -  + ]
                 [ -  + ]
     753 [ +  - ][ +  + ]:         36 :         while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
         [ +  - ][ +  + ]
                 [ +  + ]
     754                 :            :       }
     755                 :            : 
     756 [ +  - ][ +  - ]:         36 :       os << "%%BoundingBox: "
     757 [ +  - ][ +  - ]:         36 :          << int(floor(bb.left()   * _scale - _xBorder)) << ' '
                 [ +  - ]
     758 [ +  - ][ +  - ]:         36 :          << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
                 [ +  - ]
     759 [ +  - ][ +  - ]:         36 :          << int(ceil(bb.right()  * _scale + _xBorder)) << ' '
                 [ +  - ]
     760 [ +  - ][ +  - ]:         36 :          << int(ceil(bb.top()    * _scale + _yBorder)) << '\n';
     761                 :            :     }
     762                 :            : 
     763         [ +  - ]:         18 :     os << "%%EndComments\n";
     764                 :            : 
     765                 :            :     //x1 y1 x2 y2 x3 y3 cr cg cb w
     766 [ +  - ][ +  - ]:         18 :     os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
     767                 :            :        << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
     768 [ +  - ][ +  - ]:         18 :     os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke }"
     769                 :            :        << " bind def\n";
     770                 :            :     //x y r
     771 [ +  - ][ +  - ]:         18 :     os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath }"
     772                 :            :        << " bind def\n";
     773                 :            :     //x y r
     774 [ +  - ][ +  - ]:         36 :     os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
     775         [ +  - ]:         18 :        << "      2 index 1 index sub 2 index 2 index add lineto\n"
     776         [ +  - ]:         18 :        << "      2 index 1 index sub 2 index 2 index sub lineto\n"
     777         [ +  - ]:         18 :        << "      2 index 1 index add 2 index 2 index sub lineto\n"
     778                 :            :        << "      closepath pop pop pop} bind def\n";
     779                 :            :     //x y r
     780 [ +  - ][ +  - ]:         36 :     os << "/di { newpath 2 index 1 index add 2 index moveto\n"
     781         [ +  - ]:         18 :        << "      2 index             2 index 2 index add lineto\n"
     782         [ +  - ]:         18 :        << "      2 index 1 index sub 2 index             lineto\n"
     783         [ +  - ]:         18 :        << "      2 index             2 index 2 index sub lineto\n"
     784                 :            :        << "      closepath pop pop pop} bind def\n";
     785                 :            :     // x y r cr cg cb
     786 [ +  - ][ +  - ]:         36 :     os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
     787 [ +  - ][ +  - ]:         18 :        << "     setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
                 [ +  - ]
     788                 :            :        << "   } bind def\n";
     789 [ +  - ][ +  - ]:         36 :     os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
     790 [ +  - ][ +  - ]:         18 :        << "     setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
                 [ +  - ]
     791                 :            :        << "   } bind def\n";
     792 [ +  - ][ +  - ]:         36 :     os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
     793 [ +  - ][ +  - ]:         18 :        << "     setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
                 [ +  - ]
     794                 :            :        << "   } bind def\n";
     795 [ +  - ][ +  - ]:         36 :     os << "/nfemale { 0 0 0 setrgbcolor 3 index "
     796         [ +  - ]:         18 :        << _nodeBorderQuotient/(1+_nodeBorderQuotient)
     797         [ +  - ]:         18 :        << " 1.5 mul mul setlinewidth\n"
     798         [ +  - ]:         18 :        << "  newpath 5 index 5 index moveto "
     799         [ +  - ]:         18 :        << "5 index 5 index 5 index 3.01 mul sub\n"
     800         [ +  - ]:         18 :        << "  lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub"
     801         [ +  - ]:         18 :        << " moveto\n"
     802         [ +  - ]:         18 :        << "  5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto "
     803         [ +  - ]:         18 :        << "stroke\n"
     804         [ +  - ]:         18 :        << "  5 index 5 index 5 index c fill\n"
     805 [ +  - ][ +  - ]:         18 :        << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
                 [ +  - ]
     806                 :            :        << "  } bind def\n";
     807 [ +  - ][ +  - ]:         36 :     os << "/nmale {\n"
     808         [ +  - ]:         18 :        << "  0 0 0 setrgbcolor 3 index "
     809         [ +  - ]:         18 :        << _nodeBorderQuotient/(1+_nodeBorderQuotient)
     810         [ +  - ]:         18 :        <<" 1.5 mul mul setlinewidth\n"
     811         [ +  - ]:         18 :        << "  newpath 5 index 5 index moveto\n"
     812         [ +  - ]:         18 :        << "  5 index 4 index 1 mul 1.5 mul add\n"
     813         [ +  - ]:         18 :        << "  5 index 5 index 3 sqrt 1.5 mul mul add\n"
     814         [ +  - ]:         18 :        << "  1 index 1 index lineto\n"
     815         [ +  - ]:         18 :        << "  1 index 1 index 7 index sub moveto\n"
     816         [ +  - ]:         18 :        << "  1 index 1 index lineto\n"
     817         [ +  - ]:         18 :        << "  exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub"
     818         [ +  - ]:         18 :        << " lineto\n"
     819         [ +  - ]:         18 :        << "  stroke\n"
     820         [ +  - ]:         18 :        << "  5 index 5 index 5 index c fill\n"
     821 [ +  - ][ +  - ]:         18 :        << "  setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
                 [ +  - ]
     822                 :            :        << "  } bind def\n";
     823                 :            : 
     824                 :            : 
     825 [ +  - ][ +  - ]:         18 :     os << "/arrl " << _arrowLength << " def\n";
                 [ +  - ]
     826 [ +  - ][ +  - ]:         18 :     os << "/arrw " << _arrowWidth << " def\n";
                 [ +  - ]
     827                 :            :     // l dx_norm dy_norm
     828         [ +  - ]:         18 :     os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
     829                 :            :     //len w dx_norm dy_norm x1 y1 cr cg cb
     830 [ +  - ][ +  - ]:         36 :     os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx "
     831         [ +  - ]:         18 :        << "exch def\n"
     832         [ +  - ]:         18 :        << "       /w exch def /len exch def\n"
     833                 :            :       //<< "0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
     834         [ +  - ]:         18 :        << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
     835         [ +  - ]:         18 :        << "       len w sub arrl sub dx dy lrl\n"
     836         [ +  - ]:         18 :        << "       arrw dy dx neg lrl\n"
     837         [ +  - ]:         18 :        << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
     838         [ +  - ]:         18 :        << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
     839         [ +  - ]:         18 :        << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
     840         [ +  - ]:         18 :        << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
     841         [ +  - ]:         18 :        << "       arrw dy dx neg lrl\n"
     842         [ +  - ]:         18 :        << "       len w sub arrl sub neg dx dy lrl\n"
     843                 :            :        << "       closepath fill } bind def\n";
     844 [ +  - ][ +  - ]:         18 :     os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
     845                 :            :        << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
     846                 :            : 
     847         [ +  - ]:         18 :     os << "\ngsave\n";
     848         [ -  + ]:         18 :     if(_scaleToA4)
     849 [ #  # ][ #  # ]:          0 :       if(bb.height()>bb.width()) {
                 [ #  # ]
     850         [ #  # ]:          0 :         double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
     851 [ #  # ][ #  # ]:          0 :                   (A4WIDTH-2*A4BORDER)/bb.width());
     852 [ #  # ][ #  # ]:          0 :         os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
         [ #  # ][ #  # ]
     853 [ #  # ][ #  # ]:          0 :            << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
     854         [ #  # ]:          0 :            << " translate\n"
     855 [ #  # ][ #  # ]:          0 :            << sc << " dup scale\n"
     856 [ #  # ][ #  # ]:          0 :            << -bb.left() << ' ' << -bb.bottom() << " translate\n";
         [ #  # ][ #  # ]
                 [ #  # ]
     857                 :            :       }
     858                 :            :       else {
     859         [ #  # ]:          0 :         double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
     860 [ #  # ][ #  # ]:          0 :                   (A4WIDTH-2*A4BORDER)/bb.height());
     861 [ #  # ][ #  # ]:          0 :         os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
         [ #  # ][ #  # ]
     862 [ #  # ][ #  # ]:          0 :            << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
     863         [ #  # ]:          0 :            << " translate\n"
     864 [ #  # ][ #  # ]:          0 :            << sc << " dup scale\n90 rotate\n"
     865 [ #  # ][ #  # ]:          0 :            << -bb.left() << ' ' << -bb.top() << " translate\n";
         [ #  # ][ #  # ]
                 [ #  # ]
     866                 :            :         }
     867 [ +  - ][ +  - ]:         18 :     else if(_scale!=1.0) os << _scale << " dup scale\n";
                 [ +  - ]
     868                 :            : 
     869         [ +  - ]:         18 :     if(_showArcs) {
     870         [ +  - ]:         18 :       os << "%Arcs:\ngsave\n";
     871         [ -  + ]:         18 :       if(_enableParallel) {
     872         [ #  # ]:          0 :         std::vector<Arc> el;
     873 [ #  # ][ #  # ]:          0 :         for(ArcIt e(g);e!=INVALID;++e)
         [ #  # ][ #  # ]
                 [ #  # ]
     874 [ #  # ][ #  # ]:          0 :           if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
           [ #  #  #  #  
                   #  # ]
     875 [ #  # ][ #  # ]:          0 :              &&g.source(e)!=g.target(e))
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     876         [ #  # ]:          0 :             el.push_back(e);
     877 [ #  # ][ #  # ]:          0 :         std::sort(el.begin(),el.end(),arcLess(g));
     878                 :            : 
     879                 :          0 :         typename std::vector<Arc>::iterator j;
     880 [ #  # ][ #  # ]:          0 :         for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
     881 [ #  # ][ #  # ]:          0 :           for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     882                 :            : 
     883                 :          0 :           double sw=0;
     884 [ #  # ][ #  # ]:          0 :           for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
                 [ #  # ]
     885 [ #  # ][ #  # ]:          0 :             sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
     886                 :          0 :           sw-=_parArcDist;
     887                 :          0 :           sw/=-2.0;
     888                 :            :           dim2::Point<double>
     889 [ #  # ][ #  # ]:          0 :             dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     890         [ #  # ]:          0 :           double l=std::sqrt(dvec.normSquare());
     891 [ #  # ][ #  # ]:          0 :           dim2::Point<double> d(dvec/std::max(l,EPSILON));
     892         [ #  # ]:          0 :           dim2::Point<double> m;
     893                 :            : //           m=dim2::Point<double>(mycoords[g.target(*i)]+
     894                 :            : //                                 mycoords[g.source(*i)])/2.0;
     895                 :            : 
     896                 :            : //            m=dim2::Point<double>(mycoords[g.source(*i)])+
     897                 :            : //             dvec*(double(_nodeSizes[g.source(*i)])/
     898                 :            : //                (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
     899                 :            : 
     900 [ #  # ][ #  # ]:          0 :           m=dim2::Point<double>(mycoords[g.source(*i)])+
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     901 [ #  # ][ #  # ]:          0 :             d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     902                 :            : 
     903 [ #  # ][ #  # ]:          0 :           for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
                 [ #  # ]
     904 [ #  # ][ #  # ]:          0 :             sw+=_arcWidths[*e]*_arcWidthScale/2.0;
     905 [ #  # ][ #  # ]:          0 :             dim2::Point<double> mm=m+rot90(d)*sw/.75;
         [ #  # ][ #  # ]
     906         [ #  # ]:          0 :             if(_drawArrows) {
     907                 :            :               int node_shape;
     908 [ #  # ][ #  # ]:          0 :               dim2::Point<double> s=mycoords[g.source(*e)];
         [ #  # ][ #  # ]
     909 [ #  # ][ #  # ]:          0 :               dim2::Point<double> t=mycoords[g.target(*e)];
         [ #  # ][ #  # ]
     910 [ #  # ][ #  # ]:          0 :               double rn=_nodeSizes[g.target(*e)]*_nodeScale;
                 [ #  # ]
     911 [ #  # ][ #  # ]:          0 :               node_shape=_nodeShapes[g.target(*e)];
                 [ #  # ]
     912         [ #  # ]:          0 :               dim2::Bezier3 bez(s,mm,mm,t);
     913                 :          0 :               double t1=0,t2=1;
     914         [ #  # ]:          0 :               for(int ii=0;ii<INTERPOL_PREC;++ii)
     915 [ #  # ][ #  # ]:          0 :                 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
         [ #  # ][ #  # ]
     916                 :          0 :                 else t1=(t1+t2)/2;
     917         [ #  # ]:          0 :               dim2::Point<double> apoint=bez((t1+t2)/2);
     918 [ #  # ][ #  # ]:          0 :               rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
     919                 :          0 :               rn*=rn;
     920                 :          0 :               t2=(t1+t2)/2;t1=0;
     921         [ #  # ]:          0 :               for(int ii=0;ii<INTERPOL_PREC;++ii)
     922 [ #  # ][ #  # ]:          0 :                 if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
         [ #  # ][ #  # ]
     923                 :          0 :                 else t2=(t1+t2)/2;
     924         [ #  # ]:          0 :               dim2::Point<double> linend=bez((t1+t2)/2);
     925         [ #  # ]:          0 :               bez=bez.before((t1+t2)/2);
     926                 :            : //               rn=_nodeSizes[g.source(*e)]*_nodeScale;
     927                 :            : //               node_shape=_nodeShapes[g.source(*e)];
     928                 :            : //               t1=0;t2=1;
     929                 :            : //               for(int i=0;i<INTERPOL_PREC;++i)
     930                 :            : //                 if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape))
     931                 :            : //                   t1=(t1+t2)/2;
     932                 :            : //                 else t2=(t1+t2)/2;
     933                 :            : //               bez=bez.after((t1+t2)/2);
     934 [ #  # ][ #  # ]:          0 :               os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
         [ #  # ][ #  # ]
                 [ #  # ]
     935 [ #  # ][ #  # ]:          0 :                  << _arcColors[*e].red() << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     936 [ #  # ][ #  # ]:          0 :                  << _arcColors[*e].green() << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     937 [ #  # ][ #  # ]:          0 :                  << _arcColors[*e].blue() << " setrgbcolor newpath\n"
         [ #  # ][ #  # ]
                 [ #  # ]
     938 [ #  # ][ #  # ]:          0 :                  << bez.p1.x << ' ' <<  bez.p1.y << " moveto\n"
         [ #  # ][ #  # ]
     939 [ #  # ][ #  # ]:          0 :                  << bez.p2.x << ' ' << bez.p2.y << ' '
         [ #  # ][ #  # ]
     940 [ #  # ][ #  # ]:          0 :                  << bez.p3.x << ' ' << bez.p3.y << ' '
         [ #  # ][ #  # ]
     941 [ #  # ][ #  # ]:          0 :                  << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
                 [ #  # ]
     942 [ #  # ][ #  # ]:          0 :               dim2::Point<double> dd(rot90(linend-apoint));
     943 [ #  # ][ #  # ]:          0 :               dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
                 [ #  # ]
     944         [ #  # ]:          0 :                 std::sqrt(dd.normSquare());
     945 [ #  # ][ #  # ]:          0 :               os << "newpath " << psOut(apoint) << " moveto "
         [ #  # ][ #  # ]
                 [ #  # ]
     946 [ #  # ][ #  # ]:          0 :                  << psOut(linend+dd) << " lineto "
         [ #  # ][ #  # ]
     947 [ #  # ][ #  # ]:          0 :                  << psOut(linend-dd) << " lineto closepath fill\n";
                 [ #  # ]
     948                 :            :             }
     949                 :            :             else {
     950 [ #  # ][ #  # ]:          0 :               os << mycoords[g.source(*e)].x << ' '
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     951 [ #  # ][ #  # ]:          0 :                  << mycoords[g.source(*e)].y << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     952 [ #  # ][ #  # ]:          0 :                  << mm.x << ' ' << mm.y << ' '
         [ #  # ][ #  # ]
     953 [ #  # ][ #  # ]:          0 :                  << mycoords[g.target(*e)].x << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     954 [ #  # ][ #  # ]:          0 :                  << mycoords[g.target(*e)].y << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     955 [ #  # ][ #  # ]:          0 :                  << _arcColors[*e].red() << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     956 [ #  # ][ #  # ]:          0 :                  << _arcColors[*e].green() << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     957 [ #  # ][ #  # ]:          0 :                  << _arcColors[*e].blue() << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     958 [ #  # ][ #  # ]:          0 :                  << _arcWidths[*e]*_arcWidthScale << " lb\n";
                 [ #  # ]
     959                 :            :             }
     960 [ #  # ][ #  # ]:          0 :             sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
     961                 :            :           }
     962                 :          0 :         }
     963                 :            :       }
     964 [ +  - ][ +  - ]:        348 :       else for(ArcIt e(g);e!=INVALID;++e)
         [ +  - ][ +  - ]
                 [ +  + ]
     965 [ -  + ][ #  # ]:        990 :         if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
         [ #  # ][ #  # ]
         [ #  # ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
           [ +  -  #  #  
                   #  # ]
     966 [ +  - ][ +  - ]:        660 :            &&g.source(e)!=g.target(e)) {
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
     967         [ +  - ]:        330 :           if(_drawArrows) {
     968 [ +  - ][ +  - ]:        330 :             dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     969 [ +  - ][ +  - ]:        330 :             double rn=_nodeSizes[g.target(e)]*_nodeScale;
     970 [ +  - ][ +  - ]:        330 :             int node_shape=_nodeShapes[g.target(e)];
     971                 :        330 :             double t1=0,t2=1;
     972         [ +  + ]:       6930 :             for(int i=0;i<INTERPOL_PREC;++i)
     973 [ +  - ][ +  - ]:       6600 :               if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
                 [ +  + ]
     974                 :       3977 :               else t2=(t1+t2)/2;
     975         [ +  - ]:        330 :             double l=std::sqrt(d.normSquare());
     976         [ +  - ]:        330 :             d/=l;
     977                 :            : 
     978 [ +  - ][ +  - ]:        660 :             os << l*(1-(t1+t2)/2) << ' '
                 [ +  - ]
     979 [ +  - ][ +  - ]:        660 :                << _arcWidths[e]*_arcWidthScale << ' '
                 [ +  - ]
     980 [ +  - ][ +  - ]:        330 :                << d.x << ' ' << d.y << ' '
         [ +  - ][ +  - ]
     981 [ +  - ][ +  - ]:        660 :                << mycoords[g.source(e)].x << ' '
         [ +  - ][ +  - ]
     982 [ +  - ][ +  - ]:        660 :                << mycoords[g.source(e)].y << ' '
         [ +  - ][ +  - ]
     983 [ +  - ][ +  - ]:        660 :                << _arcColors[e].red() << ' '
         [ +  - ][ +  - ]
     984 [ +  - ][ +  - ]:        660 :                << _arcColors[e].green() << ' '
         [ +  - ][ +  - ]
     985 [ +  - ][ +  - ]:        990 :                << _arcColors[e].blue() << " arr\n";
                 [ +  - ]
     986                 :            :           }
     987 [ #  # ][ #  # ]:          0 :           else os << mycoords[g.source(e)].x << ' '
         [ #  # ][ #  # ]
                 [ #  # ]
     988 [ #  # ][ #  # ]:          0 :                   << mycoords[g.source(e)].y << ' '
         [ #  # ][ #  # ]
     989 [ #  # ][ #  # ]:          0 :                   << mycoords[g.target(e)].x << ' '
         [ #  # ][ #  # ]
     990 [ #  # ][ #  # ]:          0 :                   << mycoords[g.target(e)].y << ' '
         [ #  # ][ #  # ]
     991 [ #  # ][ #  # ]:          0 :                   << _arcColors[e].red() << ' '
         [ #  # ][ #  # ]
     992 [ #  # ][ #  # ]:          0 :                   << _arcColors[e].green() << ' '
         [ #  # ][ #  # ]
     993 [ #  # ][ #  # ]:        330 :                   << _arcColors[e].blue() << ' '
         [ #  # ][ #  # ]
     994 [ #  # ][ #  # ]:          0 :                   << _arcWidths[e]*_arcWidthScale << " l\n";
     995                 :            :         }
     996         [ +  - ]:         18 :       os << "grestore\n";
     997                 :            :     }
     998         [ +  - ]:         18 :     if(_showNodes) {
     999         [ +  - ]:         18 :       os << "%Nodes:\ngsave\n";
    1000 [ +  - ][ +  - ]:        255 :       for(NodeIt n(g);n!=INVALID;++n) {
         [ +  - ][ +  - ]
                 [ +  + ]
    1001 [ +  - ][ +  - ]:        474 :         os << mycoords[n].x << ' ' << mycoords[n].y << ' '
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1002 [ +  - ][ +  - ]:        474 :            << _nodeSizes[n]*_nodeScale << ' '
                 [ +  - ]
    1003 [ +  - ][ +  - ]:        474 :            << _nodeColors[n].red() << ' '
         [ +  - ][ +  - ]
    1004 [ +  - ][ +  - ]:        474 :            << _nodeColors[n].green() << ' '
         [ +  - ][ +  - ]
    1005 [ +  - ][ +  - ]:        474 :            << _nodeColors[n].blue() << ' ';
                 [ +  - ]
    1006 [ +  - ][ +  -  :        237 :         switch(_nodeShapes[n]) {
             -  -  -  - ]
    1007                 :            :         case CIRCLE:
    1008         [ +  - ]:        237 :           os<< "nc";break;
    1009                 :            :         case SQUARE:
    1010         [ #  # ]:          0 :           os<< "nsq";break;
    1011                 :            :         case DIAMOND:
    1012         [ #  # ]:          0 :           os<< "ndi";break;
    1013                 :            :         case MALE:
    1014         [ #  # ]:          0 :           os<< "nmale";break;
    1015                 :            :         case FEMALE:
    1016         [ #  # ]:          0 :           os<< "nfemale";break;
    1017                 :            :         }
    1018         [ +  - ]:        237 :         os<<'\n';
    1019                 :            :       }
    1020         [ +  - ]:         18 :       os << "grestore\n";
    1021                 :            :     }
    1022         [ +  - ]:         18 :     if(_showNodeText) {
    1023         [ +  - ]:         18 :       os << "%Node texts:\ngsave\n";
    1024 [ +  - ][ +  - ]:         18 :       os << "/fosi " << _nodeTextSize << " def\n";
                 [ +  - ]
    1025         [ +  - ]:         18 :       os << "(Helvetica) findfont fosi scalefont setfont\n";
    1026 [ +  - ][ +  - ]:        255 :       for(NodeIt n(g);n!=INVALID;++n) {
         [ +  - ][ +  - ]
                 [ +  + ]
    1027   [ -  -  -  + ]:        237 :         switch(_nodeTextColorType) {
    1028                 :            :         case DIST_COL:
    1029 [ #  # ][ #  # ]:          0 :           os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    1030                 :          0 :           break;
    1031                 :            :         case DIST_BW:
    1032 [ #  # ][ #  # ]:          0 :           os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    1033                 :          0 :           break;
    1034                 :            :         case CUST_COL:
    1035 [ #  # ][ #  # ]:          0 :           os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
         [ #  # ][ #  # ]
                 [ #  # ]
    1036                 :          0 :           break;
    1037                 :            :         default:
    1038         [ +  - ]:        237 :           os << "0 0 0 setrgbcolor\n";
    1039                 :            :         }
    1040 [ +  - ][ +  - ]:        474 :         os << mycoords[n].x << ' ' << mycoords[n].y
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1041 [ +  - ][ +  - ]:        474 :            << " (" << _nodeTexts[n] << ") cshow\n";
                 [ +  - ]
    1042                 :            :       }
    1043         [ +  - ]:         18 :       os << "grestore\n";
    1044                 :            :     }
    1045         [ -  + ]:         18 :     if(_showNodePsText) {
    1046         [ #  # ]:          0 :       os << "%Node PS blocks:\ngsave\n";
    1047 [ #  # ][ #  # ]:          0 :       for(NodeIt n(g);n!=INVALID;++n)
         [ #  # ][ #  # ]
                 [ #  # ]
    1048 [ #  # ][ #  # ]:          0 :         os << mycoords[n].x << ' ' << mycoords[n].y
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1049 [ #  # ][ #  # ]:          0 :            << " moveto\n" << _nodePsTexts[n] << "\n";
                 [ #  # ]
    1050         [ #  # ]:          0 :       os << "grestore\n";
    1051                 :            :     }
    1052                 :            : 
    1053         [ +  - ]:         18 :     os << "grestore\nshowpage\n";
    1054                 :            : 
    1055                 :            :     //CleanUp:
    1056 [ +  - ][ +  - ]:         18 :     if(_pleaseRemoveOsStream) {delete &os;}
    1057                 :            :   }
    1058                 :            : 
    1059                 :            :   ///\name Aliases
    1060                 :            :   ///These are just some aliases to other parameter setting functions.
    1061                 :            : 
    1062                 :            :   ///@{
    1063                 :            : 
    1064                 :            :   ///An alias for arcWidths()
    1065                 :            :   template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x)
    1066                 :            :   {
    1067                 :            :     return arcWidths(x);
    1068                 :            :   }
    1069                 :            : 
    1070                 :            :   ///An alias for arcColors()
    1071                 :            :   template<class X> GraphToEps<ArcColorsTraits<X> >
    1072                 :            :   edgeColors(const X &x)
    1073                 :            :   {
    1074                 :            :     return arcColors(x);
    1075                 :            :   }
    1076                 :            : 
    1077                 :            :   ///An alias for arcWidthScale()
    1078                 :            :   GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
    1079                 :            : 
    1080                 :            :   ///An alias for autoArcWidthScale()
    1081                 :            :   GraphToEps<T> &autoEdgeWidthScale(bool b=true)
    1082                 :            :   {
    1083                 :            :     return autoArcWidthScale(b);
    1084                 :            :   }
    1085                 :            : 
    1086                 :            :   ///An alias for absoluteArcWidths()
    1087                 :            :   GraphToEps<T> &absoluteEdgeWidths(bool b=true)
    1088                 :            :   {
    1089                 :            :     return absoluteArcWidths(b);
    1090                 :            :   }
    1091                 :            : 
    1092                 :            :   ///An alias for parArcDist()
    1093                 :            :   GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
    1094                 :            : 
    1095                 :            :   ///An alias for hideArcs()
    1096                 :            :   GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
    1097                 :            : 
    1098                 :            :   ///@}
    1099                 :            : };
    1100                 :            : 
    1101                 :            : template<class T>
    1102                 :            : const int GraphToEps<T>::INTERPOL_PREC = 20;
    1103                 :            : template<class T>
    1104                 :            : const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
    1105                 :            : template<class T>
    1106                 :            : const double GraphToEps<T>::A4WIDTH  = 595.275590551181;
    1107                 :            : template<class T>
    1108                 :            : const double GraphToEps<T>::A4BORDER = 15;
    1109                 :            : 
    1110                 :            : 
    1111                 :            : ///Generates an EPS file from a graph
    1112                 :            : 
    1113                 :            : ///\ingroup eps_io
    1114                 :            : ///Generates an EPS file from a graph.
    1115                 :            : ///\param g Reference to the graph to be printed.
    1116                 :            : ///\param os Reference to the output stream.
    1117                 :            : ///By default, it is <tt>std::cout</tt>.
    1118                 :            : ///
    1119                 :            : ///This function also has a lot of
    1120                 :            : ///\ref named-templ-func-param "named parameters",
    1121                 :            : ///they are declared as the members of class \ref GraphToEps. The following
    1122                 :            : ///example shows how to use these parameters.
    1123                 :            : ///\code
    1124                 :            : /// graphToEps(g,os).scale(10).coords(coords)
    1125                 :            : ///              .nodeScale(2).nodeSizes(sizes)
    1126                 :            : ///              .arcWidthScale(.4).run();
    1127                 :            : ///\endcode
    1128                 :            : ///
    1129                 :            : ///For more detailed examples, see the \ref graph_to_eps_demo.cc demo file.
    1130                 :            : ///
    1131                 :            : ///\warning Don't forget to put the \ref GraphToEps::run() "run()"
    1132                 :            : ///to the end of the parameter list.
    1133                 :            : ///\sa GraphToEps
    1134                 :            : ///\sa graphToEps(GR &g, const char *file_name)
    1135                 :            : template<class GR>
    1136                 :            : GraphToEps<DefaultGraphToEpsTraits<GR> >
    1137                 :            : graphToEps(GR &g, std::ostream& os=std::cout)
    1138                 :            : {
    1139                 :            :   return
    1140                 :            :     GraphToEps<DefaultGraphToEpsTraits<GR> >(DefaultGraphToEpsTraits<GR>(g,os));
    1141                 :            : }
    1142                 :            : 
    1143                 :            : ///Generates an EPS file from a graph
    1144                 :            : 
    1145                 :            : ///\ingroup eps_io
    1146                 :            : ///This function does the same as
    1147                 :            : ///\ref graphToEps(GR &g,std::ostream& os)
    1148                 :            : ///but it writes its output into the file \c file_name
    1149                 :            : ///instead of a stream.
    1150                 :            : ///\sa graphToEps(GR &g, std::ostream& os)
    1151                 :            : template<class GR>
    1152                 :            : GraphToEps<DefaultGraphToEpsTraits<GR> >
    1153                 :            : graphToEps(GR &g,const char *file_name)
    1154                 :            : {
    1155                 :            :   std::ostream* os = new std::ofstream(file_name);
    1156                 :            :   if (!(*os)) {
    1157                 :            :     delete os;
    1158                 :            :     throw IoError("Cannot write file", file_name);
    1159                 :            :   }
    1160                 :            :   return GraphToEps<DefaultGraphToEpsTraits<GR> >
    1161                 :            :     (DefaultGraphToEpsTraits<GR>(g,*os,true));
    1162                 :            : }
    1163                 :            : 
    1164                 :            : ///Generates an EPS file from a graph
    1165                 :            : 
    1166                 :            : ///\ingroup eps_io
    1167                 :            : ///This function does the same as
    1168                 :            : ///\ref graphToEps(GR &g,std::ostream& os)
    1169                 :            : ///but it writes its output into the file \c file_name
    1170                 :            : ///instead of a stream.
    1171                 :            : ///\sa graphToEps(GR &g, std::ostream& os)
    1172                 :            : template<class GR>
    1173                 :            : GraphToEps<DefaultGraphToEpsTraits<GR> >
    1174                 :         18 : graphToEps(GR &g,const std::string& file_name)
    1175                 :            : {
    1176         [ +  - ]:         18 :   std::ostream* os = new std::ofstream(file_name.c_str());
    1177         [ -  + ]:         18 :   if (!(*os)) {
    1178         [ #  # ]:          0 :     delete os;
    1179                 :          0 :     throw IoError("Cannot write file", file_name);
    1180                 :            :   }
    1181                 :            :   return GraphToEps<DefaultGraphToEpsTraits<GR> >
    1182         [ +  - ]:         18 :     (DefaultGraphToEpsTraits<GR>(g,*os,true));
    1183                 :            : }
    1184                 :            : 
    1185                 :            : } //END OF NAMESPACE LEMON
    1186                 :            : 
    1187                 :            : #endif // LEMON_GRAPH_TO_EPS_H

Generated by: LCOV version 1.11