lemon/graph_to_eps.h
changeset 2198 416b0c06b5c8
parent 2174 f9e43b5cc617
child 2207 75a29ac69c19
equal deleted inserted replaced
26:2959234366bb 27:639c436359ef
    36 
    36 
    37 #include<lemon/bits/invalid.h>
    37 #include<lemon/bits/invalid.h>
    38 #include<lemon/xy.h>
    38 #include<lemon/xy.h>
    39 #include<lemon/maps.h>
    39 #include<lemon/maps.h>
    40 #include<lemon/color.h>
    40 #include<lemon/color.h>
    41 #include<lemon/bezier.h>
    41 #include<lemon/bits/bezier.h>
    42 
    42 
    43 
    43 
    44 ///\ingroup eps_io
    44 ///\ingroup eps_io
    45 ///\file
    45 ///\file
    46 ///\brief Simple graph drawer
    46 ///\brief Simple graph drawer
   128   ConstMap<typename Graph::Node,Color > _nodeTextColors;
   128   ConstMap<typename Graph::Node,Color > _nodeTextColors;
   129 
   129 
   130   bool _autoNodeScale;
   130   bool _autoNodeScale;
   131   bool _autoEdgeWidthScale;
   131   bool _autoEdgeWidthScale;
   132 
   132 
       
   133   bool _absoluteNodeSizes;
       
   134   bool _absoluteEdgeWidths;
       
   135 
   133   bool _negY;
   136   bool _negY;
   134   ///Constructor
   137   ///Constructor
   135 
   138 
   136   ///Constructor
   139   ///Constructor
   137   ///\param _g is a reference to the graph to be printed
   140   ///\param _g is a reference to the graph to be printed
   141   ///will be explicitly deallocated by the destructor.
   144   ///will be explicitly deallocated by the destructor.
   142   ///By default it is <tt>std::cout</tt>
   145   ///By default it is <tt>std::cout</tt>
   143   DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
   146   DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
   144 			  bool _pros=false) :
   147 			  bool _pros=false) :
   145     g(_g), os(_os),
   148     g(_g), os(_os),
   146     _coords(xy<double>(1,1)), _nodeSizes(1.0), _nodeShapes(0),
   149     _coords(xy<double>(1,1)), _nodeSizes(.01), _nodeShapes(0),
   147     _nodeColors(WHITE), _edgeColors(BLACK),
   150     _nodeColors(WHITE), _edgeColors(BLACK),
   148     _edgeWidths(1), _edgeWidthScale(0.3),
   151     _edgeWidths(1.0), _edgeWidthScale(0.003),
   149     _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
   152     _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
   150     _nodeBorderQuotient(.1),
   153     _nodeBorderQuotient(.1),
   151     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   154     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   152     _showNodes(true), _showEdges(true),
   155     _showNodes(true), _showEdges(true),
   153     _enableParallel(false), _parEdgeDist(1),
   156     _enableParallel(false), _parEdgeDist(1),
   156     _undirected(false),
   159     _undirected(false),
   157     _pleaseRemoveOsStream(_pros), _scaleToA4(false),
   160     _pleaseRemoveOsStream(_pros), _scaleToA4(false),
   158     _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
   161     _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
   159     _autoNodeScale(false),
   162     _autoNodeScale(false),
   160     _autoEdgeWidthScale(false),
   163     _autoEdgeWidthScale(false),
       
   164     _absoluteNodeSizes(false),
       
   165     _absoluteEdgeWidths(false),
   161     _negY(false)
   166     _negY(false)
   162   {}
   167   {}
   163 };
   168 };
   164 
   169 
   165 ///Helper class to implement the named parameters of \ref graphToEps()
   170 ///Helper class to implement the named parameters of \ref graphToEps()
   226   using T::_nodeTextColorType;
   231   using T::_nodeTextColorType;
   227   using T::_nodeTextColors;
   232   using T::_nodeTextColors;
   228 
   233 
   229   using T::_autoNodeScale;
   234   using T::_autoNodeScale;
   230   using T::_autoEdgeWidthScale;
   235   using T::_autoEdgeWidthScale;
       
   236 
       
   237   using T::_absoluteNodeSizes;
       
   238   using T::_absoluteEdgeWidths;
       
   239 
   231 
   240 
   232   using T::_negY;
   241   using T::_negY;
   233 
   242 
   234   // dradnats ++C eht yb deriuqer si ti eveileb t'naC
   243   // dradnats ++C eht yb deriuqer si ti eveileb t'naC
   235 
   244 
   476   /// autoNodeScale() is not, then the node size given by
   485   /// autoNodeScale() is not, then the node size given by
   477   /// nodeSizes() will be multiplied by the value \c d.
   486   /// nodeSizes() will be multiplied by the value \c d.
   478   /// If both nodeSizes() and autoNodeScale() are used, then the
   487   /// If both nodeSizes() and autoNodeScale() are used, then the
   479   /// node sizes will be scaled in such a way that the greatest size will be
   488   /// node sizes will be scaled in such a way that the greatest size will be
   480   /// equal to \c d.
   489   /// equal to \c d.
       
   490   /// \sa nodeSizes()
       
   491   /// \sa autoNodeScale()
   481   GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
   492   GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
   482   ///Turns on/off the automatic node width scaling.
   493   ///Turns on/off the automatic node width scaling.
   483 
   494 
   484   ///Turns on/off the automatic node width scaling.
   495   ///Turns on/off the automatic node width scaling.
   485   ///
   496   ///
   486   ///\sa nodeScale()
   497   ///\sa nodeScale()
   487   ///
   498   ///
   488   GraphToEps<T> &autoNodeScale(bool b=true) {
   499   GraphToEps<T> &autoNodeScale(bool b=true) {
   489     _autoNodeScale=b;return *this;
   500     _autoNodeScale=b;return *this;
       
   501   }
       
   502 
       
   503   ///Turns on/off the absolutematic node width scaling.
       
   504 
       
   505   ///Turns on/off the absolutematic node width scaling.
       
   506   ///
       
   507   ///\sa nodeScale()
       
   508   ///
       
   509   GraphToEps<T> &absoluteNodeSizes(bool b=true) {
       
   510     _absoluteNodeSizes=b;return *this;
   490   }
   511   }
   491 
   512 
   492   ///Negates the Y coordinates.
   513   ///Negates the Y coordinates.
   493 
   514 
   494   ///Negates the Y coordinates.
   515   ///Negates the Y coordinates.
   517   ///
   538   ///
   518   ///\sa edgeWidthScale()
   539   ///\sa edgeWidthScale()
   519   ///
   540   ///
   520   GraphToEps<T> &autoEdgeWidthScale(bool b=true) {
   541   GraphToEps<T> &autoEdgeWidthScale(bool b=true) {
   521     _autoEdgeWidthScale=b;return *this;
   542     _autoEdgeWidthScale=b;return *this;
       
   543   }
       
   544   ///Turns on/off the absolutematic edge width scaling.
       
   545 
       
   546   ///Turns on/off the absolutematic edge width scaling.
       
   547   ///
       
   548   ///\sa edgeWidthScale()
       
   549   ///
       
   550   GraphToEps<T> &absoluteEdgeWidths(bool b=true) {
       
   551     _absoluteEdgeWidths=b;return *this;
   522   }
   552   }
   523   ///Sets a global scale factor for the whole picture
   553   ///Sets a global scale factor for the whole picture
   524 
   554 
   525   ///Sets a global scale factor for the whole picture
   555   ///Sets a global scale factor for the whole picture
   526   ///
   556   ///
   662   ///Like other functions using
   692   ///Like other functions using
   663   ///\ref named-templ-func-param "named template parameters",
   693   ///\ref named-templ-func-param "named template parameters",
   664   ///this function calles the algorithm itself, i.e. in this case
   694   ///this function calles the algorithm itself, i.e. in this case
   665   ///it draws the graph.
   695   ///it draws the graph.
   666   void run() {
   696   void run() {
       
   697     ///\todo better 'epsilon' would be nice here.
       
   698     const double EPSILON=1e-9;
   667     if(dontPrint) return;
   699     if(dontPrint) return;
   668     
   700     
   669     _NegY<typename T::CoordsMapType> mycoords(_coords,_negY);
   701     _NegY<typename T::CoordsMapType> mycoords(_coords,_negY);
   670 
   702 
   671     os << "%!PS-Adobe-2.0 EPSF-2.0\n";
   703     os << "%!PS-Adobe-2.0 EPSF-2.0\n";
   685     if (_autoEdgeWidthScale) {
   717     if (_autoEdgeWidthScale) {
   686       double max_w=0;
   718       double max_w=0;
   687       for(EdgeIt e(g);e!=INVALID;++e)
   719       for(EdgeIt e(g);e!=INVALID;++e)
   688 	max_w=std::max(double(_edgeWidths[e]),max_w);
   720 	max_w=std::max(double(_edgeWidths[e]),max_w);
   689       ///\todo better 'epsilon' would be nice here.
   721       ///\todo better 'epsilon' would be nice here.
   690       if(max_w>1e-9) {
   722       if(max_w>EPSILON) {
   691 	_edgeWidthScale/=max_w;
   723 	_edgeWidthScale/=max_w;
   692       }
   724       }
   693     }
   725     }
   694 
   726 
   695     if (_autoNodeScale) {
   727     if (_autoNodeScale) {
   696       double max_s=0;
   728       double max_s=0;
   697       for(NodeIt n(g);n!=INVALID;++n)
   729       for(NodeIt n(g);n!=INVALID;++n)
   698 	max_s=std::max(double(_nodeSizes[n]),max_s);
   730 	max_s=std::max(double(_nodeSizes[n]),max_s);
   699       ///\todo better 'epsilon' would be nice here.
   731       ///\todo better 'epsilon' would be nice here.
   700       if(max_s>1e-9) {
   732       if(max_s>EPSILON) {
   701 	_nodeScale/=max_s;
   733 	_nodeScale/=max_s;
   702       }
   734       }
   703     }
   735     }
   704 
   736 
   705 
   737     double diag_len = 1;
       
   738     if(!(_absoluteNodeSizes&&_absoluteEdgeWidths)) {
       
   739       BoundingBox<double> bb;
       
   740       for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
       
   741       if (bb.empty()) {
       
   742 	bb = BoundingBox<double>(xy<double>(0,0));
       
   743       }
       
   744       diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
       
   745       if(diag_len<EPSILON) diag_len = 1;
       
   746       if(!_absoluteNodeSizes) _nodeScale*=diag_len;
       
   747       if(!_absoluteEdgeWidths) _edgeWidthScale*=diag_len;
       
   748     }
       
   749     
   706     BoundingBox<double> bb;
   750     BoundingBox<double> bb;
   707     ///\bug: Chech whether the graph is empty.
       
   708     for(NodeIt n(g);n!=INVALID;++n) {
   751     for(NodeIt n(g);n!=INVALID;++n) {
   709       double ns=_nodeSizes[n]*_nodeScale;
   752       double ns=_nodeSizes[n]*_nodeScale;
   710       xy<double> p(ns,ns);
   753       xy<double> p(ns,ns);
   711       switch(_nodeShapes[n]) {
   754       switch(_nodeShapes[n]) {
   712       case CIRCLE:
   755       case CIRCLE:
   862 	  sw-=_parEdgeDist;
   905 	  sw-=_parEdgeDist;
   863 	  sw/=-2.0;
   906 	  sw/=-2.0;
   864 	  xy<double> dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
   907 	  xy<double> dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
   865 	  double l=std::sqrt(dvec.normSquare()); 
   908 	  double l=std::sqrt(dvec.normSquare()); 
   866 	  ///\todo better 'epsilon' would be nice here.
   909 	  ///\todo better 'epsilon' would be nice here.
   867 	  xy<double> d(dvec/std::max(l,1e-9));
   910 	  xy<double> d(dvec/std::max(l,EPSILON));
   868  	  xy<double> m;
   911  	  xy<double> m;
   869 // 	  m=xy<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
   912 // 	  m=xy<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
   870 
   913 
   871 //  	  m=xy<double>(mycoords[g.source(*i)])+
   914 //  	  m=xy<double>(mycoords[g.source(*i)])+
   872 // 	    dvec*(double(_nodeSizes[g.source(*i)])/
   915 // 	    dvec*(double(_nodeSizes[g.source(*i)])/