src/lemon/graph_to_eps.h
changeset 1085 5b7ca75297b5
parent 1073 bedab8bd915f
child 1086 caa13d291528
equal deleted inserted replaced
0:ef0787face42 1:89442d9e6f49
   103 
   103 
   104   bool _showNodeText;
   104   bool _showNodeText;
   105   ConstMap<typename Graph::Node,bool > _nodeTexts;  
   105   ConstMap<typename Graph::Node,bool > _nodeTexts;  
   106   double _nodeTextSize;
   106   double _nodeTextSize;
   107 
   107 
       
   108   bool _showNodePsText;
       
   109   ConstMap<typename Graph::Node,bool > _nodePsTexts;  
       
   110   char *_nodePsTextsPreamble;
       
   111   
   108   bool _undir;
   112   bool _undir;
   109   bool _pleaseRemoveOsStream;
   113   bool _pleaseRemoveOsStream;
   110   ///Constructor
   114   ///Constructor
   111 
   115 
   112   ///Constructor
   116   ///Constructor
   126     _nodeBorderQuotient(.1),
   130     _nodeBorderQuotient(.1),
   127     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   131     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
   128     _showNodes(true), _showEdges(true),
   132     _showNodes(true), _showEdges(true),
   129     _enableParallel(false), _parEdgeDist(1),
   133     _enableParallel(false), _parEdgeDist(1),
   130     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
   134     _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
       
   135     _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
   131     _undir(false),
   136     _undir(false),
   132     _pleaseRemoveOsStream(_pros) {}
   137     _pleaseRemoveOsStream(_pros) {}
   133 };
   138 };
   134 
   139 
   135 ///Helper class to implement the named parameters of \ref graphToEps()
   140 ///Helper class to implement the named parameters of \ref graphToEps()
   222   {
   227   {
   223     dontPrint=true;
   228     dontPrint=true;
   224     _showNodeText=true;
   229     _showNodeText=true;
   225     return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
   230     return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
   226   }
   231   }
   227    template<class X> struct EdgeWidthsTraits : public T {
   232   template<class X> struct NodePsTextsTraits : public T {
       
   233     const X &_nodePsTexts;
       
   234     NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
       
   235   };
       
   236   ///Inserts a PostScript block to the nodes
       
   237 
       
   238   ///With this command it is possible to insert a verbatim PostScript
       
   239   ///block to the nodes.
       
   240   ///The PS current point will be moved to the centre of the node before
       
   241   ///the PostScript block inserted.
       
   242   ///
       
   243   ///Before and after the block a newline character is inserted to you
       
   244   ///don't have to bother with the separators.
       
   245   ///
       
   246   ///\param x must be a node map with type that can be pushed to a standard
       
   247   ///ostream.
       
   248   ///
       
   249   ///\sa nodePsTextsPreamble()
       
   250   ///\todo Offer the choise not to move to the centre but pass the coordinates
       
   251   ///to the Postscript block inserted.
       
   252   template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
       
   253   {
       
   254     dontPrint=true;
       
   255     _showNodePsText=true;
       
   256     return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
       
   257   }
       
   258   template<class X> struct EdgeWidthsTraits : public T {
   228     const X &_edgeWidths;
   259     const X &_edgeWidths;
   229     EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   260     EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   230   };
   261   };
   231   ///Sets the map of the edge widths
   262   ///Sets the map of the edge widths
   232 
   263 
   335   ///Sets the size of the node texts
   366   ///Sets the size of the node texts
   336   
   367   
   337   ///Sets the size of the node texts
   368   ///Sets the size of the node texts
   338   ///
   369   ///
   339   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
   370   GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
       
   371   ///Gives a preamble block for node Postscript block.
       
   372   
       
   373   ///Gives a preamble block for node Postscript block.
       
   374   ///
       
   375   ///\sa nodePsTexts()
       
   376   GraphToEps<T> & nodePsTextsPreamble(const char *str) {
       
   377     _nodePsTextsPreamble=s ;return *this;
       
   378   }
   340   ///Sets whether the the graph is undirected
   379   ///Sets whether the the graph is undirected
   341 
   380 
   342   ///Sets whether the the graph is undirected
   381   ///Sets whether the the graph is undirected
   343   ///
   382   ///
   344   GraphToEps<T> &undir(bool b=true) {_undir=b;return *this;}
   383   GraphToEps<T> &undir(bool b=true) {_undir=b;return *this;}
   399        << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
   438        << "         neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
   400 
   439 
   401     os << "\ngsave\n";
   440     os << "\ngsave\n";
   402     if(_scale!=1.0) os << _scale << " dup scale\n";
   441     if(_scale!=1.0) os << _scale << " dup scale\n";
   403     
   442     
   404     os << "%Edges:\ngsave\n";
   443     if(_showEdges) {
   405     
   444       os << "%Edges:\ngsave\n";      
   406     if(_showEdges)
       
   407       if(_enableParallel) {
   445       if(_enableParallel) {
   408 	std::vector<Edge> el;
   446 	std::vector<Edge> el;
   409 	for(EdgeIt e(g);e!=INVALID;++e)
   447 	for(EdgeIt e(g);e!=INVALID;++e)
   410 	  if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
   448 	  if(!_undir||g.source(e)<g.target(e)) el.push_back(e);
   411 	sort(el.begin(),el.end(),edgeLess(g));
   449 	sort(el.begin(),el.end(),edgeLess(g));
   417 	  double sw=0;
   455 	  double sw=0;
   418 	  for(typename std::vector<Edge>::iterator e=i;e!=j;++e)
   456 	  for(typename std::vector<Edge>::iterator e=i;e!=j;++e)
   419 	    sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
   457 	    sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
   420 	  sw-=_parEdgeDist;
   458 	  sw-=_parEdgeDist;
   421 	  sw/=-2.0;
   459 	  sw/=-2.0;
   422 	  xy<double> d(_coords[g.target(*i)]-_coords[g.source(*i)]);
   460 	  xy<double> dvec(_coords[g.target(*i)]-_coords[g.source(*i)]);
   423 	  double l=sqrt(d.normSquare());
   461 	  double l=sqrt(dvec.normSquare());
   424 	  d/=l;
   462 	  xy<double> d(dvec/l);
   425 	  
   463  	  xy<double> m;
       
   464 // 	  m=xy<double>(_coords[g.target(*i)]+_coords[g.source(*i)])/2.0;
       
   465 
       
   466 //  	  m=xy<double>(_coords[g.source(*i)])+
       
   467 // 	    dvec*(double(_nodeSizes[g.source(*i)])/
       
   468 // 	       (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
       
   469 
       
   470  	  m=xy<double>(_coords[g.source(*i)])+
       
   471 	    d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
       
   472 
   426 	  for(typename std::vector<Edge>::iterator e=i;e!=j;++e) {
   473 	  for(typename std::vector<Edge>::iterator e=i;e!=j;++e) {
   427 	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
   474 	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
   428 	    xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]);
   475 	    xy<double> mm=m+rot(d)*sw/.75;
   429 	    m=m/2.0+rot(d)*sw/.75;
       
   430 	    if(_drawArrows) {
   476 	    if(_drawArrows) {
   431 	      const int INERPOL_PREC=20;
   477 	      const int INERPOL_PREC=20;
   432 	      xy<double> s=_coords[g.source(*e)];
   478 	      xy<double> s=_coords[g.source(*e)];
   433 	      xy<double> t=_coords[g.target(*e)];
   479 	      xy<double> t=_coords[g.target(*e)];
   434 	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
   480 	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
   435 	      rn*=rn;
   481 	      rn*=rn;
   436 	      Bezier3 bez(s,m,m,t);
   482 	      Bezier3 bez(s,mm,mm,t);
   437 	      double t1=0,t2=1;
   483 	      double t1=0,t2=1;
   438 	      for(int i=0;i<INERPOL_PREC;++i)
   484 	      for(int i=0;i<INERPOL_PREC;++i)
   439 		if((bez((t1+t2)/2)-t).normSquare()>rn) t1=(t1+t2)/2;
   485 		if((bez((t1+t2)/2)-t).normSquare()>rn) t1=(t1+t2)/2;
   440 		else t2=(t1+t2)/2;
   486 		else t2=(t1+t2)/2;
   441 	      xy<double> apoint=bez((t1+t2)/2);
   487 	      xy<double> apoint=bez((t1+t2)/2);
   470 		 << psOut(linend-dd) << " lineto closepath fill\n";
   516 		 << psOut(linend-dd) << " lineto closepath fill\n";
   471 	    }
   517 	    }
   472 	    else {
   518 	    else {
   473 	      os << _coords[g.source(*e)].x << ' '
   519 	      os << _coords[g.source(*e)].x << ' '
   474 		 << _coords[g.source(*e)].y << ' '
   520 		 << _coords[g.source(*e)].y << ' '
   475 		 << m.x << ' ' << m.y << ' '
   521 		 << mm.x << ' ' << mm.y << ' '
   476 		 << _coords[g.target(*e)].x << ' '
   522 		 << _coords[g.target(*e)].x << ' '
   477 		 << _coords[g.target(*e)].y << ' '
   523 		 << _coords[g.target(*e)].y << ' '
   478 		 << _edgeColors[*e].getR() << ' '
   524 		 << _edgeColors[*e].getR() << ' '
   479 		 << _edgeColors[*e].getG() << ' '
   525 		 << _edgeColors[*e].getG() << ' '
   480 		 << _edgeColors[*e].getB() << ' '
   526 		 << _edgeColors[*e].getB() << ' '
   507 		  << _coords[g.target(e)].y << ' '
   553 		  << _coords[g.target(e)].y << ' '
   508 		  << _edgeColors[e].getR() << ' '
   554 		  << _edgeColors[e].getR() << ' '
   509 		  << _edgeColors[e].getG() << ' '
   555 		  << _edgeColors[e].getG() << ' '
   510 		  << _edgeColors[e].getB() << ' '
   556 		  << _edgeColors[e].getB() << ' '
   511 		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
   557 		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
   512     os << "grestore\n%Nodes:\ngsave\n";
   558       os << "grestore\n";
   513     if(_showNodes)
   559     }
       
   560     if(_showNodes) {
       
   561       os << "%Nodes:\ngsave\n";
   514       for(NodeIt n(g);n!=INVALID;++n)
   562       for(NodeIt n(g);n!=INVALID;++n)
   515 	os << _coords[n].x << ' ' << _coords[n].y << ' '
   563 	os << _coords[n].x << ' ' << _coords[n].y << ' '
   516 	   << _nodeSizes[n]*_nodeScale << ' '
   564 	   << _nodeSizes[n]*_nodeScale << ' '
   517 	   << _nodeColors[n].getR() << ' '
   565 	   << _nodeColors[n].getR() << ' '
   518 	   << _nodeColors[n].getG() << ' '
   566 	   << _nodeColors[n].getG() << ' '
   519 	   << _nodeColors[n].getB() << " n\n"; 
   567 	   << _nodeColors[n].getB() << " n\n";
       
   568       os << "grestore\n";
       
   569     }
   520     if(_showNodeText) {
   570     if(_showNodeText) {
   521       os << "grestore\n%Node texts:\ngsave\n";
   571       os << "%Node texts:\ngsave\n";
   522       os << "/fosi " << _nodeTextSize << " def\n";
   572       os << "/fosi " << _nodeTextSize << " def\n";
   523       os << "(Helvetica) findfont fosi scalefont setfont\n";
   573       os << "(Helvetica) findfont fosi scalefont setfont\n";
   524       os << "0 0 0 setrgbcolor\n";
   574       os << "0 0 0 setrgbcolor\n";
   525       for(NodeIt n(g);n!=INVALID;++n)
   575       for(NodeIt n(g);n!=INVALID;++n)
   526 	os << _coords[n].x << ' ' << _coords[n].y
   576 	os << _coords[n].x << ' ' << _coords[n].y
   527 	   << " (" << _nodeTexts[n] << ") cshow\n";
   577 	   << " (" << _nodeTexts[n] << ") cshow\n";
       
   578       os << "grestore\n";
   528     }
   579     }
   529     os << "grestore\ngrestore\n";
   580     if(_showNodePsText) {
       
   581       os << "%Node PS blocks:\ngsave\n";
       
   582       for(NodeIt n(g);n!=INVALID;++n)
       
   583 	os << _coords[n].x << ' ' << _coords[n].y
       
   584 	   << " moveto\n" << _nodePsTexts[n] << "\n";
       
   585       os << "grestore\n";
       
   586     }
       
   587     
       
   588     os << "grestore\n";
   530 
   589 
   531     //CleanUp:
   590     //CleanUp:
   532     if(_pleaseRemoveOsStream) {delete &os;}
   591     if(_pleaseRemoveOsStream) {delete &os;}
   533   } 
   592   } 
   534 };
   593 };
   574 {
   633 {
   575   return GraphToEps<DefaultGraphToEpsTraits<G> >
   634   return GraphToEps<DefaultGraphToEpsTraits<G> >
   576     (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
   635     (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
   577 }
   636 }
   578 
   637 
   579 //Generates an EPS file from a graph.
       
   580 //\param g is a reference to the graph to be printed
       
   581 //\param file_name is the output file_name.
       
   582 //
       
   583 //This function also has a lot of \ref named-templ-param "named parameters",
       
   584 //they are declared as the members of class \ref GraphToEps. The following
       
   585 //example shows how to use these parameters.
       
   586 //\code
       
   587 // graphToEps(g).scale(10).coords(coords)
       
   588 //              .nodeScale(2).nodeSizes(sizes)
       
   589 //              .edgeWidthScale(.4);
       
   590 //\endcode
       
   591 //\sa GraphToEps
       
   592 //\todo Avoid duplicated documentation
       
   593 //\bug Exception handling is missing? (Or we can just ignore it?)
       
   594 
       
   595 } //END OF NAMESPACE LEMON
   638 } //END OF NAMESPACE LEMON
   596 
   639 
   597 #endif // LEMON_GRAPH_TO_EPS_H
   640 #endif // LEMON_GRAPH_TO_EPS_H