[Lemon-commits] [lemon_svn] alpar: r1444 - in hugo/trunk/src/work: . alpar

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


Author: alpar
Date: Tue Jan  4 23:16:46 2005
New Revision: 1444

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

Log:
Several new named parameters and documentation added to graphToEps().

Modified: hugo/trunk/src/work/Doxyfile
==============================================================================
--- hugo/trunk/src/work/Doxyfile	(original)
+++ hugo/trunk/src/work/Doxyfile	Tue Jan  4 23:16:46 2005
@@ -407,6 +407,7 @@
 			 jacint/graph_gen.h \
 			 marci/max_bipartite_matching.h \
 			 marci/bipartite_graph_wrapper.h \
+			 alpar/graph_to_eps.cc \
                          deba \
                          
 

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	Tue Jan  4 23:16:46 2005
@@ -1,32 +1,41 @@
+#include<math.h>
 #include<lemon/xy.h>
 #include<lemon/maps.h>
 #include<lemon/list_graph.h>
 
-///\file
+
+///\file \ingroup misc
 ///Simple graph drawer
 
 namespace lemon {
 
-  ///\e
+///Data structure representing RGB colors.
+
+///Data structure representing RGB colors.
+///\ingroup misc
 class Color
 {
   double _r,_g,_b;
 public:
-  ///\e
+  ///Default constructor
   Color() {}
-  ///\e
+  ///Constructor
   Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
-  ///\e
+  ///Returns the red component
   double getR() {return _r;}
-  ///\e
+  ///Returns the green component
   double getG() {return _g;}
-  ///\e
+  ///Returns the blue component
   double getB() {return _b;}
-  ///\e
+  ///Set the color components
   void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
 };
   
-  ///\e
+///Default traits class of \ref GraphToEps
+
+///Default traits class of \ref GraphToEps
+///
+///\c G is the type of the underlying graph.
 template<class G>
 struct DefaultGraphToEpsTraits
 {
@@ -40,21 +49,42 @@
   
 
   const Graph &g;
-  ConstMap<typename Graph::Node,xy<double> > coords;
-  ConstMap<typename Graph::Node,double > nodeSizes;
+  ConstMap<typename Graph::Node,xy<double> > _coords;
+  ConstMap<typename Graph::Node,double > _nodeSizes;
 
-  ConstMap<typename Graph::Node,Color > nodeColors;
-  ConstMap<typename Graph::Edge,Color > edgeColors;
-  double nodeSizeScalar;
-  double xBorder, yBorder;
-    
-  DefaultGraphToEpsTraits(G &_g) :
-    g(_g), coords(xy<double>(1,1)), nodeSizes(1.0),
-    nodeColors(Color(1,1,1)), edgeColors(Color(0,0,0)),
-    nodeSizeScalar(1.0), xBorder(10), yBorder(10) {}
+  ConstMap<typename Graph::Node,Color > _nodeColors;
+  ConstMap<typename Graph::Edge,Color > _edgeColors;
+
+  ConstMap<typename Graph::Edge,double > _edgeWidths;
+  
+  double _edgeWidthScale;
+  
+  double _nodeScale;
+  double _xBorder, _yBorder;
+  double _scale;
+  double _nodeBorderQuotient;
+  
+  bool _drawArrows;
+  double _arrowLength, _arrowWidth;
+  
+  ///Constructor
+
+  ///Constructor
+  ///\param _g is a reference to the underlying graph
+  DefaultGraphToEpsTraits(const G &_g) :
+    g(_g), _coords(xy<double>(1,1)), _nodeSizes(1.0),
+    _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
+    _edgeWidths(1), _edgeWidthScale(0.3),
+    _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
+    _nodeBorderQuotient(.1),
+    _drawArrows(false), _arrowLength(1), _arrowWidth(0.3) {}
 };
 
-  ///\e
+///Helper class to implement the named parameters of \ref graphToEps()
+
+///Helper class to implement the named parameters of \ref graphToEps()
+///\todo Is 'helper class' a good name for this?
+///
 template<class T> class GraphToEps : public T 
 {
   typedef typename T::Graph Graph;
@@ -70,49 +100,115 @@
 public:
   GraphToEps(const T &t) : T(t), dontPrint(false) {};
   
-  template<class X> struct SetCoordsTraits : public T {
-    const X &coords;
-    SetCoordsTraits(const T &t,const X &x) : T(t), coords(x) {}
+  template<class X> struct CoordsTraits : public T {
+    const X &_coords;
+    CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
   };
-  ///\e
-  template<class X> GraphToEps<SetCoordsTraits<X> > setCoords(const X &x) {
+  ///Sets the map of the node coordinates
+
+  ///Sets the map of the node coordinates.
+  ///\param x must be a node map with xy<double> or xy<int> values. 
+  template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
     dontPrint=true;
-    return GraphToEps<SetCoordsTraits<X> >(SetCoordsTraits<X>(*this,x));
+    return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
   }
-  template<class X> struct SetNodeSizesTraits : public T {
-    const X &nodeSizes;
-    SetNodeSizesTraits(const T &t,const X &x) : T(t), nodeSizes(x) {}
+  template<class X> struct NodeSizesTraits : public T {
+    const X &_nodeSizes;
+    NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
   };
-  ///\e
-  template<class X> GraphToEps<SetNodeSizesTraits<X> > setNodeSizes(const X &x)
+  ///Sets the map of the node sizes
+
+  ///Sets the map of the node sizes
+  ///\param x must be a node map with \c double (or convertible) values. 
+  template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
   {
     dontPrint=true;
-    return GraphToEps<SetNodeSizesTraits<X> >(SetNodeSizesTraits<X>(*this,x));
+    return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
   }
-  template<class X> struct SetNodeColorsTraits : public T {
-    const X &nodeColors;
-    SetNodeColorsTraits(const T &t,const X &x) : T(t), nodeColors(x) {}
+   template<class X> struct EdgeWidthsTraits : public T {
+    const X &_edgeWidths;
+    EdgeWidthsTraits(const T &t,const X &x) : T(t), _edgeWidths(x) {}
   };
-  ///\e
-  template<class X> GraphToEps<SetNodeColorsTraits<X> >
-  setNodeColors(const X &x)
+  ///Sets the map of the edge widths
+
+  ///Sets the map of the edge widths
+  ///\param x must be a edge map with \c double (or convertible) values. 
+  template<class X> GraphToEps<EdgeWidthsTraits<X> > edgeWidths(const X &x)
   {
     dontPrint=true;
-    return GraphToEps<SetNodeColorsTraits<X> >(SetNodeColorsTraits<X>(*this,x));
+    return GraphToEps<EdgeWidthsTraits<X> >(EdgeWidthsTraits<X>(*this,x));
   }
-  template<class X> struct SetEdgeColorsTraits : public T {
-    const X &edgeColors;
-    SetEdgeColorsTraits(const T &t,const X &x) : T(t), edgeColors(x) {}
+
+  template<class X> struct NodeColorsTraits : public T {
+    const X &_nodeColors;
+    NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
   };
-  ///\e
-  template<class X> GraphToEps<SetEdgeColorsTraits<X> >
-  setEdgeColors(const X &x)
+  ///Sets the map of the node colors
+
+  ///Sets the map of the node colors
+  ///\param x must be a node map with \ref Color values. 
+  template<class X> GraphToEps<NodeColorsTraits<X> >
+  nodeColors(const X &x)
+  {
+    dontPrint=true;
+    return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
+  }
+  template<class X> struct EdgeColorsTraits : public T {
+    const X &_edgeColors;
+    EdgeColorsTraits(const T &t,const X &x) : T(t), _edgeColors(x) {}
+  };
+  ///Sets the map of the edge colors
+
+  ///Sets the map of the edge colors
+  ///\param x must be a edge map with \ref Color values. 
+  template<class X> GraphToEps<EdgeColorsTraits<X> >
+  edgeColors(const X &x)
   {
     dontPrint=true;
-    return GraphToEps<SetEdgeColorsTraits<X> >(SetEdgeColorsTraits<X>(*this,x));
+    return GraphToEps<EdgeColorsTraits<X> >(EdgeColorsTraits<X>(*this,x));
   }
-  ///\e
-  GraphToEps<T> &scaleNodeSize(double d) {nodeSizeScalar=d;return *this;}
+  ///Sets a global scale factor for node sizes
+
+  ///Sets a global scale factor for node sizes
+  ///
+  GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
+  ///Sets a global scale factor for edge widths
+
+  ///Sets a global scale factor for edge widths
+  ///
+  GraphToEps<T> &edgeWidthScale(double d) {_edgeWidthScale=d;return *this;}
+  ///Sets a global scale factor for the whole picture
+
+  ///Sets a global scale factor for the whole picture
+  ///
+  GraphToEps<T> &scale(double d) {_scale=d;return *this;}
+  ///Sets the width of the border around the picture
+
+  ///Sets the width of the border around the picture
+  ///
+  GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
+  ///Sets the width of the border around the picture
+
+  ///Sets the width of the border around the picture
+  ///
+  GraphToEps<T> &border(double x, double y) {
+    _xBorder=x;_yBorder=y;return *this;
+  }
+  ///Sets whether to draw arrows
+
+  ///Sets whether to draw arrows
+  ///
+  GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
+  ///Sets the length of the arrowheads
+
+  ///Sets the length of the arrowheads
+  ///
+  GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
+  ///Sets the width of the arrowheads
+
+  ///Sets the width of the arrowheads
+  ///
+  GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
   
   ~GraphToEps() 
   {
@@ -121,44 +217,98 @@
     cout << "%!PS-Adobe-2.0 EPSF-2.0\n";
     //\todo: Chech whether the graph is empty.
     BoundingBox<double> bb;
-    for(NodeIt n(g);
-	n!=INVALID;
-	++n) {
-      xy<double> p(nodeSizes[n]*nodeSizeScalar,nodeSizes[n]*nodeSizeScalar);
-      bb+=coords[n]+p;
-      bb+=coords[n]-p;
+    for(NodeIt n(g);n!=INVALID;++n) {
+      double ns=_nodeSizes[n]*_nodeScale;
+      xy<double> p(ns,ns);
+      bb+=p+_coords[n];
+      bb+=-p+_coords[n];
       }
     cout << "%%BoundingBox: "
-	 << bb.left()-xBorder << ' ' << bb.bottom()-yBorder << ' '
-	 << bb.right()+xBorder << ' ' << bb.top()+yBorder << '\n';
-    //x1 y1 x2 y2 cr cg cb
-    cout << "/l { setrgbcolor newpath moveto lineto stroke } bind def\n";
+	 << bb.left()*  _scale-_xBorder << ' '
+	 << bb.bottom()*_scale-_yBorder << ' '
+	 << bb.right()* _scale+_xBorder << ' '
+	 << bb.top()*   _scale+_yBorder << '\n';
+    //x1 y1 x2 y2 cr cg cb w
+    cout << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
     cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
     // x y r cr cg cb
     cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
-	 << "     0 0 0 setrgbcolor dup 10 div setlinewidth c stroke\n"
+	 << "     0 0 0 setrgbcolor dup "
+	 << _nodeBorderQuotient << " mul setlinewidth "
+	 << 1+_nodeBorderQuotient/2 << " div c stroke\n"
 	 << "   } bind def\n";
-    
+    cout << "/arrl " << _arrowLength << " def\n";
+    cout << "/arrw " << _arrowWidth << " def\n";
+    // l dx_norm dy_norm
+    cout << "/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
+    cout << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx 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";
+    cout << "\ngsave\n";
+    if(_scale!=1.0) cout << _scale << " dup scale\n";
     cout << "%Edges:\ngsave\n";
     for(NodeIt n(g);n!=INVALID;++n)
       for(OutEdgeIt e(g,n);e!=INVALID;++e)
-	cout << coords[g.source(e)].x << ' ' << coords[g.source(e)].y << ' '
-	     << coords[g.target(e)].x << ' ' << coords[g.target(e)].y << ' '
-	     << edgeColors[e].getR() << ' '
-	     << edgeColors[e].getG() << ' '
-	     << edgeColors[e].getB() << " l\n";
+	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)]);
+	  cout << 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 cout << _coords[g.source(e)].x << ' '
+		  << _coords[g.source(e)].y << ' '
+		  << _coords[g.target(e)].x << ' '
+		  << _coords[g.target(e)].y << ' '
+		  << _edgeColors[e].getR() << ' '
+		  << _edgeColors[e].getG() << ' '
+		  << _edgeColors[e].getB() << ' '
+		  << _edgeWidths[e]*_edgeWidthScale << " l\n";
     cout << "grestore\n%Nodes:\ngsave\n";
     for(NodeIt n(g);n!=INVALID;++n)
-      cout << coords[n].x << ' ' << coords[n].y << ' '
-	   << nodeSizes[n]*nodeSizeScalar << ' '
-	   << nodeColors[n].getR() << ' '
-	   << nodeColors[n].getG() << ' '
-	   << nodeColors[n].getB() << " n\n"; 
-    cout << "grestore\n";
+      cout << _coords[n].x << ' ' << _coords[n].y << ' '
+	   << _nodeSizes[n]*_nodeScale << ' '
+	   << _nodeColors[n].getR() << ' '
+	   << _nodeColors[n].getG() << ' '
+	   << _nodeColors[n].getB() << " n\n"; 
+    cout << "grestore\ngrestore\n";
   } 
 };
 
 
+///Generates an EPS file from a graph
+
+///\ingroup misc
+///Generates an EPS file from a graph.
+///
+///This function 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
 template<class G>
 GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g)
 {
@@ -194,7 +344,7 @@
   typedef ListGraph::Node Node;
   typedef ListGraph::NodeIt NodeIt;
   typedef ListGraph::Edge Edge;
-  typedef xy<double> Xy;
+  typedef xy<int> Xy;
   
   Node n1=g.addNode();
   Node n2=g.addNode();
@@ -206,6 +356,7 @@
   ListGraph::NodeMap<double> sizes(g);
   ListGraph::NodeMap<int> colors(g);
   ListGraph::EdgeMap<int> ecolors(g);
+  ListGraph::EdgeMap<int> widths(g);
   
   coords[n1]=Xy(50,50);  sizes[n1]=1; colors[n1]=1;
   coords[n2]=Xy(50,70);  sizes[n2]=2; colors[n2]=2;
@@ -215,16 +366,19 @@
   
   Edge e;
 
-  e=g.addEdge(n1,n2); ecolors[e]=0;
-  e=g.addEdge(n2,n3); ecolors[e]=0;
-  e=g.addEdge(n3,n5); ecolors[e]=0;
-  e=g.addEdge(n5,n4); ecolors[e]=0;
-  e=g.addEdge(n4,n1); ecolors[e]=0;
-  e=g.addEdge(n2,n4); ecolors[e]=1;
-  e=g.addEdge(n3,n4); ecolors[e]=2;
-  
-  graphToEps(g).setCoords(coords).
-    scaleNodeSize(2).setNodeSizes(sizes).
-    setNodeColors(composeMap(colorSet,colors)).
-    setEdgeColors(composeMap(colorSet,ecolors));
+  e=g.addEdge(n1,n2); ecolors[e]=0; widths[e]=1;
+  e=g.addEdge(n2,n3); ecolors[e]=0; widths[e]=1;
+  e=g.addEdge(n3,n5); ecolors[e]=0; widths[e]=3;
+  e=g.addEdge(n5,n4); ecolors[e]=0; widths[e]=1;
+  e=g.addEdge(n4,n1); ecolors[e]=0; widths[e]=1;
+  e=g.addEdge(n2,n4); ecolors[e]=1; widths[e]=2;
+  e=g.addEdge(n3,n4); ecolors[e]=2; widths[e]=1;
+  
+  graphToEps(g).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)
+    ;
 }



More information about the Lemon-commits mailing list