[Lemon-commits] [lemon_svn] alpar: r1458 - hugo/trunk/src/work/alpar

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:45:36 CET 2006


Author: alpar
Date: Sat Jan  8 21:16:56 2005
New Revision: 1458

Modified:
   hugo/trunk/src/work/alpar/graph_to_eps.cc

Log:
- Parallel edge support (without arrowheads)
- Texts on the nodes


Modified: hugo/trunk/src/work/alpar/graph_to_eps.cc
==============================================================================
--- hugo/trunk/src/work/alpar/graph_to_eps.cc	(original)
+++ hugo/trunk/src/work/alpar/graph_to_eps.cc	Sat Jan  8 21:16:56 2005
@@ -1,3 +1,19 @@
+/* -*- C++ -*-
+ * src/lemon/graph_to_eps.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Combinatorial Optimization Research Group, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
 #include <iostream>
 #include <fstream>
 #include <algorithm>
@@ -8,8 +24,9 @@
 #include<lemon/list_graph.h>
 
 
-///\file \ingroup misc
-///Simple graph drawer
+///\ingroup misc
+///\file
+///\brief Simple graph drawer
 
 namespace lemon {
 
@@ -74,7 +91,14 @@
   bool _drawArrows;
   double _arrowLength, _arrowWidth;
   
+  bool _showNodes, _showEdges;
+
   bool _enableParallel;
+  double _parEdgeDist;
+
+  bool _showNodeText;
+  ConstMap<typename Graph::Node,bool > _nodeTexts;  
+  double _nodeTextSize;
 
   bool _pleaseRemoveOsStream;
   ///Constructor
@@ -95,7 +119,10 @@
     _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
     _nodeBorderQuotient(.1),
     _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
-    _enableParallel(false), _pleaseRemoveOsStream(_pros) {}
+    _showNodes(true), _showEdges(true),
+    _enableParallel(false), _parEdgeDist(1),
+    _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
+    _pleaseRemoveOsStream(_pros) {}
 };
 
 ///Helper class to implement the named parameters of \ref graphToEps()
@@ -130,7 +157,16 @@
 		    (aa==ba && ai==g.source(a) && bi==g.target(b))));
     }
   };
-    
+  bool isParallel(Edge e,Edge f) const
+  {
+    return (g.source(e)==g.source(f)&&g.target(e)==g.target(f))||
+      (g.source(e)==g.target(f)&&g.target(e)==g.source(f));
+  }
+  static xy<double> rot(xy<double> v) 
+  {
+    return xy<double>(v.y,-v.x);
+  }
+  
 public:
   GraphToEps(const T &t) : T(t), dontPrint(false) {};
   
@@ -159,6 +195,21 @@
     dontPrint=true;
     return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
   }
+  template<class X> struct NodeTextsTraits : public T {
+    const X &_nodeTexts;
+    NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
+  };
+  ///Sets the text printed on the nodes
+
+  ///Sets the text printed on the nodes
+  ///\param x must be a node map with type that can be pushed to a standard
+  ///ostream. 
+  template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
+  {
+    dontPrint=true;
+    _showNodeText=true;
+    return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
+  }
    template<class X> struct EdgeWidthsTraits : public T {
     const X &_edgeWidths;
     EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
@@ -247,9 +298,33 @@
   ///Enables parallel edges
 
   ///Enables parallel edges
-  ///\todo Unimplemented
+  ///\todo Partially implemented
   GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
   
+  ///Sets the distance 
+  
+  ///Sets the distance 
+  ///
+  GraphToEps<T> &parEdgeDist(double d) {_parEdgeDist*=d;return *this;}
+  
+  ///Hides the edges
+  
+  ///Hides the edges
+  ///
+  GraphToEps<T> &hideEdges(bool b=true) {_showEdges=!b;return *this;}
+  ///Hides the nodes
+  
+  ///Hides the nodes
+  ///
+  GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
+  
+  ///Sets the size of the node texts
+  
+  ///Sets the size of the node texts
+  ///
+  GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
+
+  
   ~GraphToEps() 
   {
     if(dontPrint) return;
@@ -268,53 +343,104 @@
 	 << bb.bottom()*_scale-_yBorder << ' '
 	 << bb.right()* _scale+_xBorder << ' '
 	 << bb.top()*   _scale+_yBorder << '\n';
-    //x1 y1 x2 y2 cr cg cb w
+    //x1 y1 x2 y2 x3 y3 cr cg cb w
+    os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
+       << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
     os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
-    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
+    os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
     // x y r cr cg cb
     os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
-	 << "     0 0 0 setrgbcolor dup "
-	 << _nodeBorderQuotient << " mul setlinewidth "
-	 << 1+_nodeBorderQuotient/2 << " div c stroke\n"
-	 << "   } bind def\n";
+       << "     0 0 0 setrgbcolor dup "
+       << _nodeBorderQuotient << " mul setlinewidth "
+       << 1+_nodeBorderQuotient/2 << " div c stroke\n"
+       << "   } bind def\n";
     os << "/arrl " << _arrowLength << " def\n";
     os << "/arrw " << _arrowWidth << " def\n";
     // l dx_norm dy_norm
     os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
     //len w dx_norm dy_norm x1 y1 cr cg cb
     os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
-	 << "       /w exch def /len exch def\n"
+       << "       /w exch def /len exch def\n"
       //	 << "       0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
-	 << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
-	 << "       len w sub arrl sub dx dy lrl\n"
-	 << "       arrw dy dx neg lrl\n"
-	 << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
-	 << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
-	 << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
-	 << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
-	 << "       arrw dy dx neg lrl\n"
-	 << "       len w sub arrl sub neg dx dy lrl\n"
-	 << "       closepath fill } bind def\n";
+       << "       newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
+       << "       len w sub arrl sub dx dy lrl\n"
+       << "       arrw dy dx neg lrl\n"
+       << "       dx arrl w add mul dy w 2 div arrw add mul sub\n"
+       << "       dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
+       << "       dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
+       << "       dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
+       << "       arrw dy dx neg lrl\n"
+       << "       len w sub arrl sub neg dx dy lrl\n"
+       << "       closepath fill } bind def\n";
+    os << "/cshow { 2 index 2 index moveto\n"
+       << "         dup stringwidth pop neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
+
     os << "\ngsave\n";
     if(_scale!=1.0) os << _scale << " dup scale\n";
     
     os << "%Edges:\ngsave\n";
     
-    vector<Edge> el;
-    if(_enableParallel) {
-      for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e);
-      sort(el.begin(),el.end(),edgeLess(g));
-    }
-    
-    for(NodeIt n(g);n!=INVALID;++n)
-      for(OutEdgeIt e(g,n);e!=INVALID;++e)
-	if(_drawArrows) {
-	  xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
-	  double l=sqrt(d.normSquare());
-	  d/=l;
-	  xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
-			_coords[g.source(e)]);
-	  os << l-(_nodeSizes[g.source(e)]+
+    if(_showEdges)
+      if(_enableParallel) {
+	vector<Edge> el;
+	for(EdgeIt e(g);e!=INVALID;++e) el.push_back(e);
+	sort(el.begin(),el.end(),edgeLess(g));
+	
+	typename vector<Edge>::iterator j;
+	for(typename vector<Edge>::iterator i=el.begin();i!=el.end();i=j) {
+	  for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
+	  
+	  if(_drawArrows) {
+	    // 	  xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
+	    // 	  double l=sqrt(d.normSquare());
+	    // 	  d/=l;
+	    // 	  xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
+	    // 			_coords[g.source(e)]);
+	    // 	  os << l-(_nodeSizes[g.source(e)]+
+	    // 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
+	    // 	       << _edgeWidths[e]*_edgeWidthScale << ' '
+	    // 	       << d.x << ' ' << d.y << ' '
+	    // 	       << x1.x << ' ' << x1.y << ' '
+	    // 	       << _edgeColors[e].getR() << ' '
+	    // 	       << _edgeColors[e].getG() << ' '
+	    // 	       << _edgeColors[e].getB() << " arr\n";
+	  }
+	  else {
+	    double sw=0;
+	    for(typename vector<Edge>::iterator e=i;e!=j;++e)
+	      sw+=_edgeWidths[*e]*_edgeWidthScale+_parEdgeDist;
+	    sw-=_parEdgeDist;
+	    sw/=-2.0;
+	    xy<double> d(_coords[g.target(*i)]-_coords[g.source(*i)]);
+	    double l=sqrt(d.normSquare());
+	    d/=l;
+	    for(typename vector<Edge>::iterator e=i;e!=j;++e) {
+	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
+	      xy<double> m(_coords[g.target(*e)]+_coords[g.source(*e)]);
+	      m=m/2.0+rot(d)*sw/.75;
+	      os << _coords[g.source(*e)].x << ' '
+		 << _coords[g.source(*e)].y << ' '
+		 << m.x << ' ' << m.y << ' '
+		 << _coords[g.target(*e)].x << ' '
+		 << _coords[g.target(*e)].y << ' '
+		 << _edgeColors[*e].getR() << ' '
+		 << _edgeColors[*e].getG() << ' '
+		 << _edgeColors[*e].getB() << ' '
+		 << _edgeWidths[*e]*_edgeWidthScale << " lb\n";
+	      sw+=_edgeWidths[*e]*_edgeWidthScale/2.0+_parEdgeDist;
+	    }
+	  }
+	}
+      }
+      else for(NodeIt n(g);n!=INVALID;++n)
+	for(OutEdgeIt e(g,n);e!=INVALID;++e)
+	  if(_drawArrows) {
+	    xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]);
+	    double l=sqrt(d.normSquare());
+	    d/=l;
+	    xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+
+			  _coords[g.source(e)]);
+	    os << l-(_nodeSizes[g.source(e)]+
 		     _nodeSizes[g.target(e)])*_nodeScale << ' '
 	       << _edgeWidths[e]*_edgeWidthScale << ' '
 	       << d.x << ' ' << d.y << ' '
@@ -322,8 +448,8 @@
 	       << _edgeColors[e].getR() << ' '
 	       << _edgeColors[e].getG() << ' '
 	       << _edgeColors[e].getB() << " arr\n";
-	}
-    	else os << _coords[g.source(e)].x << ' '
+	  }
+	  else os << _coords[g.source(e)].x << ' '
 		  << _coords[g.source(e)].y << ' '
 		  << _coords[g.target(e)].x << ' '
 		  << _coords[g.target(e)].y << ' '
@@ -332,15 +458,24 @@
 		  << _edgeColors[e].getB() << ' '
 		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
     os << "grestore\n%Nodes:\ngsave\n";
-    for(NodeIt n(g);n!=INVALID;++n)
-      os << _coords[n].x << ' ' << _coords[n].y << ' '
+    if(_showNodes)
+      for(NodeIt n(g);n!=INVALID;++n)
+	os << _coords[n].x << ' ' << _coords[n].y << ' '
 	   << _nodeSizes[n]*_nodeScale << ' '
 	   << _nodeColors[n].getR() << ' '
 	   << _nodeColors[n].getG() << ' '
 	   << _nodeColors[n].getB() << " n\n"; 
+    if(_showNodeText) {
+      os << "grestore\n%Node texts:\ngsave\n";
+      os << "/fosi " << _nodeTextSize << " def\n";
+      os << "(Helvetica) findfont fosi scalefont setfont\n";
+      os << "0 0 0 setrgbcolor\n";
+      for(NodeIt n(g);n!=INVALID;++n)
+	os << _coords[n].x << ' ' << _coords[n].y
+	   << " (" << _nodeTexts[n] << ") cshow\n";
+    }
     os << "grestore\ngrestore\n";
 
-
     //CleanUp:
     if(_pleaseRemoveOsStream) {delete &os;}
   } 
@@ -364,9 +499,10 @@
 ///              .edgeWidthScale(.4);
 ///\endcode
 ///\sa GraphToEps
+///\sa graphToEps(G &g, char *file_name)
 template<class G>
 GraphToEps<DefaultGraphToEpsTraits<G> > 
-graphToEps(G &g,std::ostream& os=std::cout)
+graphToEps(G &g, std::ostream& os=std::cout)
 {
   return 
     GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
@@ -374,22 +510,12 @@
  
 ///Generates an EPS file from a graph
 
-///\ingroup misc
-///Generates an EPS file from a graph.
-///\param g is a reference to the graph to be printed
-///\param file_name is the output file_name.
-///
-///This function also has a lot of \ref named-templ-param "named parameters",
-///they are declared as the members of class \ref GraphToEps. The following
-///example shows how to use these parameters.
-///\code
-/// graphToEps(g).scale(10).coords(coords)
-///              .nodeScale(2).nodeSizes(sizes)
-///              .edgeWidthScale(.4);
-///\endcode
-///\sa GraphToEps
-///\todo Avoid duplicated documentation
-///\bug Exception handling is missing? (Or we can just ignore it?)
+//\ingroup misc
+///This function does the same as
+///\ref graphToEps(G &g,std::ostream& os)
+///but it writes its output into the file \c file_name
+///instead of a stream.
+///\sa graphToEps(G &g, std::ostream& os)
 template<class G>
 GraphToEps<DefaultGraphToEpsTraits<G> > 
 graphToEps(G &g,char *file_name)
@@ -398,6 +524,21 @@
     (DefaultGraphToEpsTraits<G>(g,*new ofstream(file_name),true));
 }
 
+//Generates an EPS file from a graph.
+//\param g is a reference to the graph to be printed
+//\param file_name is the output file_name.
+//
+//This function also has a lot of \ref named-templ-param "named parameters",
+//they are declared as the members of class \ref GraphToEps. The following
+//example shows how to use these parameters.
+//\code
+// graphToEps(g).scale(10).coords(coords)
+//              .nodeScale(2).nodeSizes(sizes)
+//              .edgeWidthScale(.4);
+//\endcode
+//\sa GraphToEps
+//\todo Avoid duplicated documentation
+//\bug Exception handling is missing? (Or we can just ignore it?)
 
 }
 
@@ -422,6 +563,16 @@
   }
 } colorSet;
 
+class IdMap :public MapBase<ListGraph::Node,int>
+{
+  const ListGraph &g;
+public:
+  IdMap(const ListGraph &_g) :g(_g) {}
+  Value operator[](Key n) const { return g.id(n); }
+};
+
+
+
 int main()
 {
   ListGraph g;
@@ -458,16 +609,39 @@
   e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
   e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
   
+  IdMap id(g);
+
   graphToEps(g,"proba.eps").scale(10).coords(coords).
     nodeScale(2).nodeSizes(sizes).
     nodeColors(composeMap(colorSet,colors)).
     edgeColors(composeMap(colorSet,ecolors)).
-    edgeWidthScale(.4).edgeWidths(widths);
+    edgeWidthScale(.4).edgeWidths(widths).
+    nodeTexts(id).nodeTextSize(3);
+
   graphToEps(g,"proba_arr.eps").scale(10).coords(coords).
     nodeScale(2).nodeSizes(sizes).
     nodeColors(composeMap(colorSet,colors)).
     edgeColors(composeMap(colorSet,ecolors)).
     edgeWidthScale(.4).edgeWidths(widths).
-    drawArrows().arrowWidth(1).arrowLength(1)
-    ;
+    nodeTexts(id).nodeTextSize(3).
+    drawArrows().arrowWidth(1).arrowLength(1);
+
+  e=g.addEdge(n1,n4); ecolors[e]=2; widths[e]=1;
+  e=g.addEdge(n4,n1); ecolors[e]=1; widths[e]=2;
+
+  e=g.addEdge(n1,n2); ecolors[e]=1; widths[e]=1;
+  e=g.addEdge(n1,n2); ecolors[e]=2; widths[e]=1;
+  e=g.addEdge(n1,n2); ecolors[e]=3; widths[e]=1;
+  e=g.addEdge(n1,n2); ecolors[e]=4; widths[e]=1;
+  e=g.addEdge(n1,n2); ecolors[e]=5; widths[e]=1;
+  e=g.addEdge(n1,n2); ecolors[e]=6; widths[e]=1;
+  e=g.addEdge(n1,n2); ecolors[e]=7; widths[e]=1;
+
+  graphToEps(g,"proba_par.eps").scale(10).coords(coords).
+    nodeScale(2).nodeSizes(sizes).
+    nodeColors(composeMap(colorSet,colors)).
+    edgeColors(composeMap(colorSet,ecolors)).
+    edgeWidthScale(.4).edgeWidths(widths).
+    nodeTexts(id).nodeTextSize(3).
+    enableParallel().parEdgeDist(1.5);
 }



More information about the Lemon-commits mailing list