68 double _arrowLength, _arrowWidth; |
73 double _arrowLength, _arrowWidth; |
69 |
74 |
70 ///Constructor |
75 ///Constructor |
71 |
76 |
72 ///Constructor |
77 ///Constructor |
73 ///\param _g is a reference to the underlying graph |
78 ///\param _g is a reference to the graph to be printed |
74 DefaultGraphToEpsTraits(const G &_g) : |
79 ///\param _os is a reference to the output stream. |
75 g(_g), _coords(xy<double>(1,1)), _nodeSizes(1.0), |
80 ///By default it is <tt>std::cout</tt> |
|
81 DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout) : |
|
82 g(_g), os(_os), |
|
83 _coords(xy<double>(1,1)), _nodeSizes(1.0), |
76 _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), |
84 _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)), |
77 _edgeWidths(1), _edgeWidthScale(0.3), |
85 _edgeWidths(1), _edgeWidthScale(0.3), |
78 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
86 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
79 _nodeBorderQuotient(.1), |
87 _nodeBorderQuotient(.1), |
80 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3) {} |
88 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3) {} |
212 |
220 |
213 ~GraphToEps() |
221 ~GraphToEps() |
214 { |
222 { |
215 if(dontPrint) return; |
223 if(dontPrint) return; |
216 |
224 |
217 cout << "%!PS-Adobe-2.0 EPSF-2.0\n"; |
225 os << "%!PS-Adobe-2.0 EPSF-2.0\n"; |
218 //\todo: Chech whether the graph is empty. |
226 //\todo: Chech whether the graph is empty. |
219 BoundingBox<double> bb; |
227 BoundingBox<double> bb; |
220 for(NodeIt n(g);n!=INVALID;++n) { |
228 for(NodeIt n(g);n!=INVALID;++n) { |
221 double ns=_nodeSizes[n]*_nodeScale; |
229 double ns=_nodeSizes[n]*_nodeScale; |
222 xy<double> p(ns,ns); |
230 xy<double> p(ns,ns); |
223 bb+=p+_coords[n]; |
231 bb+=p+_coords[n]; |
224 bb+=-p+_coords[n]; |
232 bb+=-p+_coords[n]; |
225 } |
233 } |
226 cout << "%%BoundingBox: " |
234 os << "%%BoundingBox: " |
227 << bb.left()* _scale-_xBorder << ' ' |
235 << bb.left()* _scale-_xBorder << ' ' |
228 << bb.bottom()*_scale-_yBorder << ' ' |
236 << bb.bottom()*_scale-_yBorder << ' ' |
229 << bb.right()* _scale+_xBorder << ' ' |
237 << bb.right()* _scale+_xBorder << ' ' |
230 << bb.top()* _scale+_yBorder << '\n'; |
238 << bb.top()* _scale+_yBorder << '\n'; |
231 //x1 y1 x2 y2 cr cg cb w |
239 //x1 y1 x2 y2 cr cg cb w |
232 cout << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; |
240 os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n"; |
233 cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n"; |
241 os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n"; |
234 // x y r cr cg cb |
242 // x y r cr cg cb |
235 cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" |
243 os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n" |
236 << " 0 0 0 setrgbcolor dup " |
244 << " 0 0 0 setrgbcolor dup " |
237 << _nodeBorderQuotient << " mul setlinewidth " |
245 << _nodeBorderQuotient << " mul setlinewidth " |
238 << 1+_nodeBorderQuotient/2 << " div c stroke\n" |
246 << 1+_nodeBorderQuotient/2 << " div c stroke\n" |
239 << " } bind def\n"; |
247 << " } bind def\n"; |
240 cout << "/arrl " << _arrowLength << " def\n"; |
248 os << "/arrl " << _arrowLength << " def\n"; |
241 cout << "/arrw " << _arrowWidth << " def\n"; |
249 os << "/arrw " << _arrowWidth << " def\n"; |
242 // l dx_norm dy_norm |
250 // l dx_norm dy_norm |
243 cout << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; |
251 os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n"; |
244 //len w dx_norm dy_norm x1 y1 cr cg cb |
252 //len w dx_norm dy_norm x1 y1 cr cg cb |
245 cout << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" |
253 os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n" |
246 << " /w exch def /len exch def\n" |
254 << " /w exch def /len exch def\n" |
247 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" |
255 // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" |
248 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" |
256 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" |
249 << " len w sub arrl sub dx dy lrl\n" |
257 << " len w sub arrl sub dx dy lrl\n" |
250 << " arrw dy dx neg lrl\n" |
258 << " arrw dy dx neg lrl\n" |
253 << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" |
261 << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" |
254 << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" |
262 << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" |
255 << " arrw dy dx neg lrl\n" |
263 << " arrw dy dx neg lrl\n" |
256 << " len w sub arrl sub neg dx dy lrl\n" |
264 << " len w sub arrl sub neg dx dy lrl\n" |
257 << " closepath fill } bind def\n"; |
265 << " closepath fill } bind def\n"; |
258 cout << "\ngsave\n"; |
266 os << "\ngsave\n"; |
259 if(_scale!=1.0) cout << _scale << " dup scale\n"; |
267 if(_scale!=1.0) os << _scale << " dup scale\n"; |
260 cout << "%Edges:\ngsave\n"; |
268 os << "%Edges:\ngsave\n"; |
261 for(NodeIt n(g);n!=INVALID;++n) |
269 for(NodeIt n(g);n!=INVALID;++n) |
262 for(OutEdgeIt e(g,n);e!=INVALID;++e) |
270 for(OutEdgeIt e(g,n);e!=INVALID;++e) |
263 if(_drawArrows) { |
271 if(_drawArrows) { |
264 xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]); |
272 xy<double> d(_coords[g.target(e)]-_coords[g.source(e)]); |
265 double l=sqrt(d.normSquare()); |
273 double l=sqrt(d.normSquare()); |
266 d/=l; |
274 d/=l; |
267 xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ |
275 xy<double> x1(d*_nodeScale*_nodeSizes[g.source(e)]+ |
268 _coords[g.source(e)]); |
276 _coords[g.source(e)]); |
269 cout << l-(_nodeSizes[g.source(e)]+ |
277 os << l-(_nodeSizes[g.source(e)]+ |
270 _nodeSizes[g.target(e)])*_nodeScale << ' ' |
278 _nodeSizes[g.target(e)])*_nodeScale << ' ' |
271 << _edgeWidths[e]*_edgeWidthScale << ' ' |
279 << _edgeWidths[e]*_edgeWidthScale << ' ' |
272 << d.x << ' ' << d.y << ' ' |
280 << d.x << ' ' << d.y << ' ' |
273 << x1.x << ' ' << x1.y << ' ' |
281 << x1.x << ' ' << x1.y << ' ' |
274 << _edgeColors[e].getR() << ' ' |
282 << _edgeColors[e].getR() << ' ' |
275 << _edgeColors[e].getG() << ' ' |
283 << _edgeColors[e].getG() << ' ' |
276 << _edgeColors[e].getB() << " arr\n"; |
284 << _edgeColors[e].getB() << " arr\n"; |
277 } |
285 } |
278 else cout << _coords[g.source(e)].x << ' ' |
286 else os << _coords[g.source(e)].x << ' ' |
279 << _coords[g.source(e)].y << ' ' |
287 << _coords[g.source(e)].y << ' ' |
280 << _coords[g.target(e)].x << ' ' |
288 << _coords[g.target(e)].x << ' ' |
281 << _coords[g.target(e)].y << ' ' |
289 << _coords[g.target(e)].y << ' ' |
282 << _edgeColors[e].getR() << ' ' |
290 << _edgeColors[e].getR() << ' ' |
283 << _edgeColors[e].getG() << ' ' |
291 << _edgeColors[e].getG() << ' ' |
284 << _edgeColors[e].getB() << ' ' |
292 << _edgeColors[e].getB() << ' ' |
285 << _edgeWidths[e]*_edgeWidthScale << " l\n"; |
293 << _edgeWidths[e]*_edgeWidthScale << " l\n"; |
286 cout << "grestore\n%Nodes:\ngsave\n"; |
294 os << "grestore\n%Nodes:\ngsave\n"; |
287 for(NodeIt n(g);n!=INVALID;++n) |
295 for(NodeIt n(g);n!=INVALID;++n) |
288 cout << _coords[n].x << ' ' << _coords[n].y << ' ' |
296 os << _coords[n].x << ' ' << _coords[n].y << ' ' |
289 << _nodeSizes[n]*_nodeScale << ' ' |
297 << _nodeSizes[n]*_nodeScale << ' ' |
290 << _nodeColors[n].getR() << ' ' |
298 << _nodeColors[n].getR() << ' ' |
291 << _nodeColors[n].getG() << ' ' |
299 << _nodeColors[n].getG() << ' ' |
292 << _nodeColors[n].getB() << " n\n"; |
300 << _nodeColors[n].getB() << " n\n"; |
293 cout << "grestore\ngrestore\n"; |
301 os << "grestore\ngrestore\n"; |
294 } |
302 } |
295 }; |
303 }; |
296 |
304 |
297 |
305 |
298 ///Generates an EPS file from a graph |
306 ///Generates an EPS file from a graph |
299 |
307 |
300 ///\ingroup misc |
308 ///\ingroup misc |
301 ///Generates an EPS file from a graph. |
309 ///Generates an EPS file from a graph. |
|
310 ///\param g is a reference to the graph to be printed |
|
311 ///\param os is a reference to the output stream. |
|
312 ///By default it is <tt>std::cout</tt> |
302 /// |
313 /// |
303 ///This function has a lot of \ref named-templ-param "named parameters", |
314 ///This function also has a lot of \ref named-templ-param "named parameters", |
304 ///they are declared as the members of class \ref GraphToEps. The following |
315 ///they are declared as the members of class \ref GraphToEps. The following |
305 ///example shows how to use these parameters. |
316 ///example shows how to use these parameters. |
306 ///\code |
317 ///\code |
307 /// graphToEps(g).scale(10).coords(coords) |
318 /// graphToEps(g).scale(10).coords(coords) |
308 /// .nodeScale(2).nodeSizes(sizes) |
319 /// .nodeScale(2).nodeSizes(sizes) |
309 /// .edgeWidthScale(.4); |
320 /// .edgeWidthScale(.4); |
310 ///\endcode |
321 ///\endcode |
311 ///\sa GraphToEps |
322 ///\sa GraphToEps |
312 template<class G> |
323 template<class G> |
313 GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g) |
324 GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g,std::ostream& os=std::cout) |
314 { |
325 { |
315 return GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g)); |
326 return GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g)); |
316 } |
327 } |
317 |
328 |
318 } |
329 } |