alpar@1046
|
1 |
#include<lemon/xy.h>
|
alpar@1046
|
2 |
#include<lemon/maps.h>
|
alpar@1046
|
3 |
#include<lemon/list_graph.h>
|
alpar@1046
|
4 |
|
alpar@1046
|
5 |
///\file
|
alpar@1046
|
6 |
///Simple graph drawer
|
alpar@1046
|
7 |
|
alpar@1046
|
8 |
namespace lemon {
|
alpar@1046
|
9 |
|
alpar@1046
|
10 |
///\e
|
alpar@1046
|
11 |
class Color
|
alpar@1046
|
12 |
{
|
alpar@1046
|
13 |
double _r,_g,_b;
|
alpar@1046
|
14 |
public:
|
alpar@1046
|
15 |
///\e
|
alpar@1046
|
16 |
Color() {}
|
alpar@1046
|
17 |
///\e
|
alpar@1046
|
18 |
Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
|
alpar@1046
|
19 |
///\e
|
alpar@1046
|
20 |
double getR() {return _r;}
|
alpar@1046
|
21 |
///\e
|
alpar@1046
|
22 |
double getG() {return _g;}
|
alpar@1046
|
23 |
///\e
|
alpar@1046
|
24 |
double getB() {return _b;}
|
alpar@1046
|
25 |
///\e
|
alpar@1046
|
26 |
void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
|
alpar@1046
|
27 |
};
|
alpar@1046
|
28 |
|
alpar@1046
|
29 |
///\e
|
alpar@1046
|
30 |
template<class G>
|
alpar@1046
|
31 |
struct DefaultGraphToEpsTraits
|
alpar@1046
|
32 |
{
|
alpar@1046
|
33 |
typedef G Graph;
|
alpar@1046
|
34 |
typedef typename Graph::Node Node;
|
alpar@1046
|
35 |
typedef typename Graph::NodeIt NodeIt;
|
alpar@1046
|
36 |
typedef typename Graph::Edge Edge;
|
alpar@1046
|
37 |
typedef typename Graph::EdgeIt EdgeIt;
|
alpar@1046
|
38 |
typedef typename Graph::InEdgeIt InEdgeIt;
|
alpar@1046
|
39 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
alpar@1046
|
40 |
|
alpar@1046
|
41 |
|
alpar@1046
|
42 |
const Graph &g;
|
alpar@1046
|
43 |
ConstMap<typename Graph::Node,xy<double> > coords;
|
alpar@1046
|
44 |
ConstMap<typename Graph::Node,double > nodeSizes;
|
alpar@1046
|
45 |
|
alpar@1046
|
46 |
ConstMap<typename Graph::Node,Color > nodeColors;
|
alpar@1046
|
47 |
ConstMap<typename Graph::Edge,Color > edgeColors;
|
alpar@1046
|
48 |
double nodeSizeScalar;
|
alpar@1046
|
49 |
double xBorder, yBorder;
|
alpar@1046
|
50 |
|
alpar@1046
|
51 |
DefaultGraphToEpsTraits(G &_g) :
|
alpar@1046
|
52 |
g(_g), coords(xy<double>(1,1)), nodeSizes(1.0),
|
alpar@1046
|
53 |
nodeColors(Color(1,1,1)), edgeColors(Color(0,0,0)),
|
alpar@1046
|
54 |
nodeSizeScalar(1.0), xBorder(10), yBorder(10) {}
|
alpar@1046
|
55 |
};
|
alpar@1046
|
56 |
|
alpar@1046
|
57 |
///\e
|
alpar@1046
|
58 |
template<class T> class GraphToEps : public T
|
alpar@1046
|
59 |
{
|
alpar@1046
|
60 |
typedef typename T::Graph Graph;
|
alpar@1046
|
61 |
typedef typename Graph::Node Node;
|
alpar@1046
|
62 |
typedef typename Graph::NodeIt NodeIt;
|
alpar@1046
|
63 |
typedef typename Graph::Edge Edge;
|
alpar@1046
|
64 |
typedef typename Graph::EdgeIt EdgeIt;
|
alpar@1046
|
65 |
typedef typename Graph::InEdgeIt InEdgeIt;
|
alpar@1046
|
66 |
typedef typename Graph::OutEdgeIt OutEdgeIt;
|
alpar@1046
|
67 |
|
alpar@1046
|
68 |
bool dontPrint;
|
alpar@1046
|
69 |
|
alpar@1046
|
70 |
public:
|
alpar@1046
|
71 |
GraphToEps(const T &t) : T(t), dontPrint(false) {};
|
alpar@1046
|
72 |
|
alpar@1046
|
73 |
template<class X> struct SetCoordsTraits : public T {
|
alpar@1046
|
74 |
const X &coords;
|
alpar@1046
|
75 |
SetCoordsTraits(const T &t,const X &x) : T(t), coords(x) {}
|
alpar@1046
|
76 |
};
|
alpar@1046
|
77 |
///\e
|
alpar@1046
|
78 |
template<class X> GraphToEps<SetCoordsTraits<X> > setCoords(const X &x) {
|
alpar@1046
|
79 |
dontPrint=true;
|
alpar@1046
|
80 |
return GraphToEps<SetCoordsTraits<X> >(SetCoordsTraits<X>(*this,x));
|
alpar@1046
|
81 |
}
|
alpar@1046
|
82 |
template<class X> struct SetNodeSizesTraits : public T {
|
alpar@1046
|
83 |
const X &nodeSizes;
|
alpar@1046
|
84 |
SetNodeSizesTraits(const T &t,const X &x) : T(t), nodeSizes(x) {}
|
alpar@1046
|
85 |
};
|
alpar@1046
|
86 |
///\e
|
alpar@1046
|
87 |
template<class X> GraphToEps<SetNodeSizesTraits<X> > setNodeSizes(const X &x)
|
alpar@1046
|
88 |
{
|
alpar@1046
|
89 |
dontPrint=true;
|
alpar@1046
|
90 |
return GraphToEps<SetNodeSizesTraits<X> >(SetNodeSizesTraits<X>(*this,x));
|
alpar@1046
|
91 |
}
|
alpar@1046
|
92 |
template<class X> struct SetNodeColorsTraits : public T {
|
alpar@1046
|
93 |
const X &nodeColors;
|
alpar@1046
|
94 |
SetNodeColorsTraits(const T &t,const X &x) : T(t), nodeColors(x) {}
|
alpar@1046
|
95 |
};
|
alpar@1046
|
96 |
///\e
|
alpar@1046
|
97 |
template<class X> GraphToEps<SetNodeColorsTraits<X> >
|
alpar@1046
|
98 |
setNodeColors(const X &x)
|
alpar@1046
|
99 |
{
|
alpar@1046
|
100 |
dontPrint=true;
|
alpar@1046
|
101 |
return GraphToEps<SetNodeColorsTraits<X> >(SetNodeColorsTraits<X>(*this,x));
|
alpar@1046
|
102 |
}
|
alpar@1046
|
103 |
template<class X> struct SetEdgeColorsTraits : public T {
|
alpar@1046
|
104 |
const X &edgeColors;
|
alpar@1046
|
105 |
SetEdgeColorsTraits(const T &t,const X &x) : T(t), edgeColors(x) {}
|
alpar@1046
|
106 |
};
|
alpar@1046
|
107 |
///\e
|
alpar@1046
|
108 |
template<class X> GraphToEps<SetEdgeColorsTraits<X> >
|
alpar@1046
|
109 |
setEdgeColors(const X &x)
|
alpar@1046
|
110 |
{
|
alpar@1046
|
111 |
dontPrint=true;
|
alpar@1046
|
112 |
return GraphToEps<SetEdgeColorsTraits<X> >(SetEdgeColorsTraits<X>(*this,x));
|
alpar@1046
|
113 |
}
|
alpar@1046
|
114 |
///\e
|
alpar@1046
|
115 |
GraphToEps<T> &scaleNodeSize(double d) {nodeSizeScalar=d;return *this;}
|
alpar@1046
|
116 |
|
alpar@1046
|
117 |
~GraphToEps()
|
alpar@1046
|
118 |
{
|
alpar@1046
|
119 |
if(dontPrint) return;
|
alpar@1046
|
120 |
|
alpar@1046
|
121 |
cout << "%!PS-Adobe-2.0 EPSF-2.0\n";
|
alpar@1046
|
122 |
//\todo: Chech whether the graph is empty.
|
alpar@1046
|
123 |
BoundingBox<double> bb;
|
alpar@1046
|
124 |
for(NodeIt n(g);
|
alpar@1046
|
125 |
n!=INVALID;
|
alpar@1046
|
126 |
++n) {
|
alpar@1046
|
127 |
xy<double> p(nodeSizes[n]*nodeSizeScalar,nodeSizes[n]*nodeSizeScalar);
|
alpar@1046
|
128 |
bb+=coords[n]+p;
|
alpar@1046
|
129 |
bb+=coords[n]-p;
|
alpar@1046
|
130 |
}
|
alpar@1046
|
131 |
cout << "%%BoundingBox: "
|
alpar@1046
|
132 |
<< bb.left()-xBorder << ' ' << bb.bottom()-yBorder << ' '
|
alpar@1046
|
133 |
<< bb.right()+xBorder << ' ' << bb.top()+yBorder << '\n';
|
alpar@1046
|
134 |
//x1 y1 x2 y2 cr cg cb
|
alpar@1046
|
135 |
cout << "/l { setrgbcolor newpath moveto lineto stroke } bind def\n";
|
alpar@1046
|
136 |
cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
|
alpar@1046
|
137 |
// x y r cr cg cb
|
alpar@1046
|
138 |
cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
|
alpar@1046
|
139 |
<< " 0 0 0 setrgbcolor dup 10 div setlinewidth c stroke\n"
|
alpar@1046
|
140 |
<< " } bind def\n";
|
alpar@1046
|
141 |
|
alpar@1046
|
142 |
cout << "%Edges:\ngsave\n";
|
alpar@1046
|
143 |
for(NodeIt n(g);n!=INVALID;++n)
|
alpar@1046
|
144 |
for(OutEdgeIt e(g,n);e!=INVALID;++e)
|
alpar@1046
|
145 |
cout << coords[g.source(e)].x << ' ' << coords[g.source(e)].y << ' '
|
alpar@1046
|
146 |
<< coords[g.target(e)].x << ' ' << coords[g.target(e)].y << ' '
|
alpar@1046
|
147 |
<< edgeColors[e].getR() << ' '
|
alpar@1046
|
148 |
<< edgeColors[e].getG() << ' '
|
alpar@1046
|
149 |
<< edgeColors[e].getB() << " l\n";
|
alpar@1046
|
150 |
cout << "grestore\n%Nodes:\ngsave\n";
|
alpar@1046
|
151 |
for(NodeIt n(g);n!=INVALID;++n)
|
alpar@1046
|
152 |
cout << coords[n].x << ' ' << coords[n].y << ' '
|
alpar@1046
|
153 |
<< nodeSizes[n]*nodeSizeScalar << ' '
|
alpar@1046
|
154 |
<< nodeColors[n].getR() << ' '
|
alpar@1046
|
155 |
<< nodeColors[n].getG() << ' '
|
alpar@1046
|
156 |
<< nodeColors[n].getB() << " n\n";
|
alpar@1046
|
157 |
cout << "grestore\n";
|
alpar@1046
|
158 |
}
|
alpar@1046
|
159 |
};
|
alpar@1046
|
160 |
|
alpar@1046
|
161 |
|
alpar@1046
|
162 |
template<class G>
|
alpar@1046
|
163 |
GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g)
|
alpar@1046
|
164 |
{
|
alpar@1046
|
165 |
return GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g));
|
alpar@1046
|
166 |
}
|
alpar@1046
|
167 |
|
alpar@1046
|
168 |
}
|
alpar@1046
|
169 |
|
alpar@1046
|
170 |
using namespace lemon;
|
alpar@1046
|
171 |
|
alpar@1046
|
172 |
class ColorSet : public MapBase<int,Color>
|
alpar@1046
|
173 |
{
|
alpar@1046
|
174 |
public:
|
alpar@1046
|
175 |
Color operator[](int i) const
|
alpar@1046
|
176 |
{
|
alpar@1046
|
177 |
switch(i%8){
|
alpar@1046
|
178 |
case 0: return Color(0,0,0);
|
alpar@1046
|
179 |
case 1: return Color(1,0,0);
|
alpar@1046
|
180 |
case 2: return Color(0,1,0);
|
alpar@1046
|
181 |
case 3: return Color(0,0,1);
|
alpar@1046
|
182 |
case 4: return Color(1,1,0);
|
alpar@1046
|
183 |
case 5: return Color(1,0,1);
|
alpar@1046
|
184 |
case 6: return Color(0,1,1);
|
alpar@1046
|
185 |
case 7: return Color(1,1,1);
|
alpar@1046
|
186 |
}
|
alpar@1046
|
187 |
return Color(0,0,0);
|
alpar@1046
|
188 |
}
|
alpar@1046
|
189 |
} colorSet;
|
alpar@1046
|
190 |
|
alpar@1046
|
191 |
int main()
|
alpar@1046
|
192 |
{
|
alpar@1046
|
193 |
ListGraph g;
|
alpar@1046
|
194 |
typedef ListGraph::Node Node;
|
alpar@1046
|
195 |
typedef ListGraph::NodeIt NodeIt;
|
alpar@1046
|
196 |
typedef ListGraph::Edge Edge;
|
alpar@1046
|
197 |
typedef xy<double> Xy;
|
alpar@1046
|
198 |
|
alpar@1046
|
199 |
Node n1=g.addNode();
|
alpar@1046
|
200 |
Node n2=g.addNode();
|
alpar@1046
|
201 |
Node n3=g.addNode();
|
alpar@1046
|
202 |
Node n4=g.addNode();
|
alpar@1046
|
203 |
Node n5=g.addNode();
|
alpar@1046
|
204 |
|
alpar@1046
|
205 |
ListGraph::NodeMap<Xy> coords(g);
|
alpar@1046
|
206 |
ListGraph::NodeMap<double> sizes(g);
|
alpar@1046
|
207 |
ListGraph::NodeMap<int> colors(g);
|
alpar@1046
|
208 |
ListGraph::EdgeMap<int> ecolors(g,0);
|
alpar@1046
|
209 |
|
alpar@1046
|
210 |
coords[n1]=Xy(50,50); sizes[n1]=1; colors[n1]=1;
|
alpar@1046
|
211 |
coords[n2]=Xy(50,70); sizes[n2]=2; colors[n2]=2;
|
alpar@1046
|
212 |
coords[n3]=Xy(70,70); sizes[n3]=1; colors[n3]=3;
|
alpar@1046
|
213 |
coords[n4]=Xy(70,50); sizes[n4]=2; colors[n4]=4;
|
alpar@1046
|
214 |
coords[n5]=Xy(85,60); sizes[n5]=3; colors[n5]=5;
|
alpar@1046
|
215 |
|
alpar@1046
|
216 |
Edge e;
|
alpar@1046
|
217 |
|
alpar@1046
|
218 |
e=g.addEdge(n1,n2);
|
alpar@1046
|
219 |
e=g.addEdge(n2,n3);
|
alpar@1046
|
220 |
e=g.addEdge(n3,n5);
|
alpar@1046
|
221 |
e=g.addEdge(n5,n4);
|
alpar@1046
|
222 |
e=g.addEdge(n4,n1);
|
alpar@1046
|
223 |
e=g.addEdge(n2,n4); ecolors[e]=1;
|
alpar@1046
|
224 |
e=g.addEdge(n3,n4); ecolors[e]=2;
|
alpar@1046
|
225 |
|
alpar@1046
|
226 |
graphToEps(g).setCoords(coords).
|
alpar@1046
|
227 |
scaleNodeSize(2).setNodeSizes(sizes).
|
alpar@1046
|
228 |
setNodeColors(composeMap(colorSet,colors)).
|
alpar@1046
|
229 |
setEdgeColors(composeMap(colorSet,ecolors));
|
alpar@1046
|
230 |
}
|