[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