1.1 --- a/lemon/graph_to_eps.h Sun Jul 13 16:46:56 2008 +0100
1.2 +++ b/lemon/graph_to_eps.h Sun Jul 13 19:51:02 2008 +0100
1.3 @@ -1,6 +1,6 @@
1.4 -/* -*- C++ -*-
1.5 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
1.6 *
1.7 - * This file is a part of LEMON, a generic C++ optimization library
1.8 + * This file is a part of LEMON, a generic C++ optimization library.
1.9 *
1.10 * Copyright (C) 2003-2008
1.11 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.12 @@ -60,7 +60,7 @@
1.13 Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
1.14 };
1.15 }
1.16 -
1.17 +
1.18 ///Default traits class of \ref GraphToEps
1.19
1.20 ///Default traits class of \ref GraphToEps.
1.21 @@ -76,12 +76,12 @@
1.22 typedef typename Graph::ArcIt ArcIt;
1.23 typedef typename Graph::InArcIt InArcIt;
1.24 typedef typename Graph::OutArcIt OutArcIt;
1.25 -
1.26 +
1.27
1.28 const Graph &g;
1.29
1.30 std::ostream& os;
1.31 -
1.32 +
1.33 typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
1.34 CoordsMapType _coords;
1.35 ConstMap<typename Graph::Node,double > _nodeSizes;
1.36 @@ -93,28 +93,28 @@
1.37 ConstMap<typename Graph::Arc,double > _arcWidths;
1.38
1.39 double _arcWidthScale;
1.40 -
1.41 +
1.42 double _nodeScale;
1.43 double _xBorder, _yBorder;
1.44 double _scale;
1.45 double _nodeBorderQuotient;
1.46 -
1.47 +
1.48 bool _drawArrows;
1.49 double _arrowLength, _arrowWidth;
1.50 -
1.51 +
1.52 bool _showNodes, _showArcs;
1.53
1.54 bool _enableParallel;
1.55 double _parArcDist;
1.56
1.57 bool _showNodeText;
1.58 - ConstMap<typename Graph::Node,bool > _nodeTexts;
1.59 + ConstMap<typename Graph::Node,bool > _nodeTexts;
1.60 double _nodeTextSize;
1.61
1.62 bool _showNodePsText;
1.63 - ConstMap<typename Graph::Node,bool > _nodePsTexts;
1.64 + ConstMap<typename Graph::Node,bool > _nodePsTexts;
1.65 char *_nodePsTextsPreamble;
1.66 -
1.67 +
1.68 bool _undirected;
1.69
1.70 bool _pleaseRemoveOsStream;
1.71 @@ -124,7 +124,7 @@
1.72 std::string _title;
1.73 std::string _copyright;
1.74
1.75 - enum NodeTextColorType
1.76 + enum NodeTextColorType
1.77 { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
1.78 ConstMap<typename Graph::Node,Color > _nodeTextColors;
1.79
1.80 @@ -146,7 +146,7 @@
1.81 ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
1.82 ///will be explicitly deallocated by the destructor.
1.83 DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
1.84 - bool _pros=false) :
1.85 + bool _pros=false) :
1.86 g(_g), os(_os),
1.87 _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
1.88 _nodeColors(WHITE), _arcColors(BLACK),
1.89 @@ -175,7 +175,7 @@
1.90 ///Auxiliary class to implement the named parameters of \ref graphToEps().
1.91 ///
1.92 ///For detailed examples see the \ref graph_to_eps_demo.cc demo file.
1.93 -template<class T> class GraphToEps : public T
1.94 +template<class T> class GraphToEps : public T
1.95 {
1.96 // Can't believe it is required by the C++ standard
1.97 using T::g;
1.98 @@ -194,11 +194,11 @@
1.99 using T::_yBorder;
1.100 using T::_scale;
1.101 using T::_nodeBorderQuotient;
1.102 -
1.103 +
1.104 using T::_drawArrows;
1.105 using T::_arrowLength;
1.106 using T::_arrowWidth;
1.107 -
1.108 +
1.109 using T::_showNodes;
1.110 using T::_showArcs;
1.111
1.112 @@ -206,13 +206,13 @@
1.113 using T::_parArcDist;
1.114
1.115 using T::_showNodeText;
1.116 - using T::_nodeTexts;
1.117 + using T::_nodeTexts;
1.118 using T::_nodeTextSize;
1.119
1.120 using T::_showNodePsText;
1.121 - using T::_nodePsTexts;
1.122 + using T::_nodePsTexts;
1.123 using T::_nodePsTextsPreamble;
1.124 -
1.125 +
1.126 using T::_undirected;
1.127
1.128 using T::_pleaseRemoveOsStream;
1.129 @@ -261,16 +261,16 @@
1.130
1.131 ///Node shapes.
1.132 ///
1.133 - enum NodeShapes {
1.134 + enum NodeShapes {
1.135 /// = 0
1.136 ///\image html nodeshape_0.png
1.137 ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
1.138 - CIRCLE=0,
1.139 + CIRCLE=0,
1.140 /// = 1
1.141 ///\image html nodeshape_1.png
1.142 ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
1.143 ///
1.144 - SQUARE=1,
1.145 + SQUARE=1,
1.146 /// = 2
1.147 ///\image html nodeshape_2.png
1.148 ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
1.149 @@ -293,41 +293,41 @@
1.150 const Graph &g;
1.151 public:
1.152 arcLess(const Graph &_g) : g(_g) {}
1.153 - bool operator()(Arc a,Arc b) const
1.154 + bool operator()(Arc a,Arc b) const
1.155 {
1.156 Node ai=std::min(g.source(a),g.target(a));
1.157 Node aa=std::max(g.source(a),g.target(a));
1.158 Node bi=std::min(g.source(b),g.target(b));
1.159 Node ba=std::max(g.source(b),g.target(b));
1.160 return ai<bi ||
1.161 - (ai==bi && (aa < ba ||
1.162 - (aa==ba && ai==g.source(a) && bi==g.target(b))));
1.163 + (ai==bi && (aa < ba ||
1.164 + (aa==ba && ai==g.source(a) && bi==g.target(b))));
1.165 }
1.166 };
1.167 bool isParallel(Arc e,Arc f) const
1.168 {
1.169 return (g.source(e)==g.source(f)&&
1.170 - g.target(e)==g.target(f)) ||
1.171 + g.target(e)==g.target(f)) ||
1.172 (g.source(e)==g.target(f)&&
1.173 g.target(e)==g.source(f));
1.174 }
1.175 template<class TT>
1.176 - static std::string psOut(const dim2::Point<TT> &p)
1.177 + static std::string psOut(const dim2::Point<TT> &p)
1.178 {
1.179 - std::ostringstream os;
1.180 + std::ostringstream os;
1.181 os << p.x << ' ' << p.y;
1.182 return os.str();
1.183 }
1.184 - static std::string psOut(const Color &c)
1.185 + static std::string psOut(const Color &c)
1.186 {
1.187 - std::ostringstream os;
1.188 + std::ostringstream os;
1.189 os << c.red() << ' ' << c.green() << ' ' << c.blue();
1.190 return os.str();
1.191 }
1.192 -
1.193 +
1.194 public:
1.195 GraphToEps(const T &t) : T(t), dontPrint(false) {};
1.196 -
1.197 +
1.198 template<class X> struct CoordsTraits : public T {
1.199 typedef X CoordsMapType;
1.200 const X &_coords;
1.201 @@ -337,7 +337,7 @@
1.202
1.203 ///Sets the map of the node coordinates.
1.204 ///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or
1.205 - ///\ref dim2::Point "dim2::Point<int>" values.
1.206 + ///\ref dim2::Point "dim2::Point<int>" values.
1.207 template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
1.208 dontPrint=true;
1.209 return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
1.210 @@ -349,7 +349,7 @@
1.211 ///Sets the map of the node sizes
1.212
1.213 ///Sets the map of the node sizes.
1.214 - ///\param x must be a node map with \c double (or convertible) values.
1.215 + ///\param x must be a node map with \c double (or convertible) values.
1.216 template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
1.217 {
1.218 dontPrint=true;
1.219 @@ -364,7 +364,7 @@
1.220 ///Sets the map of the node shapes.
1.221 ///The available shape values
1.222 ///can be found in \ref NodeShapes "enum NodeShapes".
1.223 - ///\param x must be a node map with \c int (or convertible) values.
1.224 + ///\param x must be a node map with \c int (or convertible) values.
1.225 ///\sa NodeShapes
1.226 template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
1.227 {
1.228 @@ -379,7 +379,7 @@
1.229
1.230 ///Sets the text printed on the nodes.
1.231 ///\param x must be a node map with type that can be pushed to a standard
1.232 - ///\c ostream.
1.233 + ///\c ostream.
1.234 template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
1.235 {
1.236 dontPrint=true;
1.237 @@ -417,7 +417,7 @@
1.238 ///Sets the map of the arc widths
1.239
1.240 ///Sets the map of the arc widths.
1.241 - ///\param x must be an arc map with \c double (or convertible) values.
1.242 + ///\param x must be an arc map with \c double (or convertible) values.
1.243 template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
1.244 {
1.245 dontPrint=true;
1.246 @@ -447,7 +447,7 @@
1.247 ///Sets the map of the node text colors
1.248
1.249 ///Sets the map of the node text colors.
1.250 - ///\param x must be a node map with \ref Color values.
1.251 + ///\param x must be a node map with \ref Color values.
1.252 ///
1.253 ///\sa Palette
1.254 template<class X> GraphToEps<NodeTextColorsTraits<X> >
1.255 @@ -465,7 +465,7 @@
1.256 ///Sets the map of the arc colors
1.257
1.258 ///Sets the map of the arc colors.
1.259 - ///\param x must be an arc map with \ref Color values.
1.260 + ///\param x must be an arc map with \ref Color values.
1.261 ///
1.262 ///\sa Palette
1.263 template<class X> GraphToEps<ArcColorsTraits<X> >
1.264 @@ -477,7 +477,7 @@
1.265 ///Sets a global scale factor for node sizes
1.266
1.267 ///Sets a global scale factor for node sizes.
1.268 - ///
1.269 + ///
1.270 /// If nodeSizes() is not given, this function simply sets the node
1.271 /// sizes to \c d. If nodeSizes() is given, but
1.272 /// autoNodeScale() is not, then the node size given by
1.273 @@ -568,21 +568,21 @@
1.274 GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
1.275 ///Sets the width of the arrowheads
1.276 GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
1.277 -
1.278 +
1.279 ///Scales the drawing to fit to A4 page
1.280 GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
1.281 -
1.282 +
1.283 ///Enables parallel arcs
1.284 GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
1.285 -
1.286 +
1.287 ///Sets the distance between parallel arcs
1.288 GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
1.289 -
1.290 +
1.291 ///Hides the arcs
1.292 GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
1.293 ///Hides the nodes
1.294 GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
1.295 -
1.296 +
1.297 ///Sets the size of the node texts
1.298 GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
1.299
1.300 @@ -600,7 +600,7 @@
1.301 {_nodeTextColorType=DIST_BW;return *this;}
1.302
1.303 ///Gives a preamble block for node Postscript block.
1.304 -
1.305 +
1.306 ///Gives a preamble block for node Postscript block.
1.307 ///
1.308 ///\sa nodePsTexts()
1.309 @@ -625,7 +625,7 @@
1.310 ///
1.311 ///\sa undirected()
1.312 GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
1.313 -
1.314 +
1.315 ///Sets the title.
1.316
1.317 ///Sets the title of the generated image,
1.318 @@ -640,7 +640,7 @@
1.319 GraphToEps<T> ©right(const std::string &t) {_copyright=t;return *this;}
1.320
1.321 protected:
1.322 - bool isInsideNode(dim2::Point<double> p, double r,int t)
1.323 + bool isInsideNode(dim2::Point<double> p, double r,int t)
1.324 {
1.325 switch(t) {
1.326 case CIRCLE:
1.327 @@ -657,7 +657,7 @@
1.328
1.329 public:
1.330 ~GraphToEps() { }
1.331 -
1.332 +
1.333 ///Draws the graph.
1.334
1.335 ///Like other functions using
1.336 @@ -668,7 +668,7 @@
1.337 //\todo better 'epsilon' would be nice here.
1.338 const double EPSILON=1e-9;
1.339 if(dontPrint) return;
1.340 -
1.341 +
1.342 _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
1.343 mycoords(_coords,_negY);
1.344
1.345 @@ -677,8 +677,8 @@
1.346 if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
1.347 os << "%%Creator: LEMON, graphToEps()\n";
1.348
1.349 - {
1.350 -#ifndef WIN32
1.351 + {
1.352 +#ifndef WIN32
1.353 timeval tv;
1.354 gettimeofday(&tv, 0);
1.355
1.356 @@ -688,37 +688,37 @@
1.357 #else
1.358 SYSTEMTIME time;
1.359 char buf1[11], buf2[9], buf3[5];
1.360 -
1.361 +
1.362 GetSystemTime(&time);
1.363 - if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
1.364 - "ddd MMM dd", buf1, 11) &&
1.365 - GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
1.366 - "HH':'mm':'ss", buf2, 9) &&
1.367 - GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
1.368 - "yyyy", buf3, 5)) {
1.369 - os << "%%CreationDate: " << buf1 << ' '
1.370 - << buf2 << ' ' << buf3 << std::endl;
1.371 - }
1.372 + if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
1.373 + "ddd MMM dd", buf1, 11) &&
1.374 + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
1.375 + "HH':'mm':'ss", buf2, 9) &&
1.376 + GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
1.377 + "yyyy", buf3, 5)) {
1.378 + os << "%%CreationDate: " << buf1 << ' '
1.379 + << buf2 << ' ' << buf3 << std::endl;
1.380 + }
1.381 #endif
1.382 }
1.383
1.384 if (_autoArcWidthScale) {
1.385 double max_w=0;
1.386 for(ArcIt e(g);e!=INVALID;++e)
1.387 - max_w=std::max(double(_arcWidths[e]),max_w);
1.388 + max_w=std::max(double(_arcWidths[e]),max_w);
1.389 //\todo better 'epsilon' would be nice here.
1.390 if(max_w>EPSILON) {
1.391 - _arcWidthScale/=max_w;
1.392 + _arcWidthScale/=max_w;
1.393 }
1.394 }
1.395
1.396 if (_autoNodeScale) {
1.397 double max_s=0;
1.398 for(NodeIt n(g);n!=INVALID;++n)
1.399 - max_s=std::max(double(_nodeSizes[n]),max_s);
1.400 + max_s=std::max(double(_nodeSizes[n]),max_s);
1.401 //\todo better 'epsilon' would be nice here.
1.402 if(max_s>EPSILON) {
1.403 - _nodeScale/=max_s;
1.404 + _nodeScale/=max_s;
1.405 }
1.406 }
1.407
1.408 @@ -727,14 +727,14 @@
1.409 dim2::BoundingBox<double> bb;
1.410 for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
1.411 if (bb.empty()) {
1.412 - bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
1.413 + bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
1.414 }
1.415 diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
1.416 if(diag_len<EPSILON) diag_len = 1;
1.417 if(!_absoluteNodeSizes) _nodeScale*=diag_len;
1.418 if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
1.419 }
1.420 -
1.421 +
1.422 dim2::BoundingBox<double> bb;
1.423 for(NodeIt n(g);n!=INVALID;++n) {
1.424 double ns=_nodeSizes[n]*_nodeScale;
1.425 @@ -743,41 +743,41 @@
1.426 case CIRCLE:
1.427 case SQUARE:
1.428 case DIAMOND:
1.429 - bb.add(p+mycoords[n]);
1.430 - bb.add(-p+mycoords[n]);
1.431 - break;
1.432 + bb.add(p+mycoords[n]);
1.433 + bb.add(-p+mycoords[n]);
1.434 + break;
1.435 case MALE:
1.436 - bb.add(-p+mycoords[n]);
1.437 - bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
1.438 - break;
1.439 + bb.add(-p+mycoords[n]);
1.440 + bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
1.441 + break;
1.442 case FEMALE:
1.443 - bb.add(p+mycoords[n]);
1.444 - bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
1.445 - break;
1.446 + bb.add(p+mycoords[n]);
1.447 + bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
1.448 + break;
1.449 }
1.450 }
1.451 if (bb.empty()) {
1.452 bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
1.453 }
1.454 -
1.455 +
1.456 if(_scaleToA4)
1.457 os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
1.458 else {
1.459 if(_preScale) {
1.460 - //Rescale so that BoundingBox won't be neither to big nor too small.
1.461 - while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
1.462 - while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
1.463 + //Rescale so that BoundingBox won't be neither to big nor too small.
1.464 + while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
1.465 + while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
1.466 }
1.467 -
1.468 +
1.469 os << "%%BoundingBox: "
1.470 - << int(floor(bb.left() * _scale - _xBorder)) << ' '
1.471 - << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
1.472 - << int(ceil(bb.right() * _scale + _xBorder)) << ' '
1.473 - << int(ceil(bb.top() * _scale + _yBorder)) << '\n';
1.474 + << int(floor(bb.left() * _scale - _xBorder)) << ' '
1.475 + << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
1.476 + << int(ceil(bb.right() * _scale + _xBorder)) << ' '
1.477 + << int(ceil(bb.top() * _scale + _yBorder)) << '\n';
1.478 }
1.479 -
1.480 +
1.481 os << "%%EndComments\n";
1.482 -
1.483 +
1.484 //x1 y1 x2 y2 x3 y3 cr cg cb w
1.485 os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
1.486 << " 4 2 roll 1 index 1 index curveto stroke } bind def\n";
1.487 @@ -831,7 +831,7 @@
1.488 << " 5 index 5 index 5 index c fill\n"
1.489 << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
1.490 << " } bind def\n";
1.491 -
1.492 +
1.493
1.494 os << "/arrl " << _arrowLength << " def\n";
1.495 os << "/arrw " << _arrowWidth << " def\n";
1.496 @@ -840,7 +840,7 @@
1.497 //len w dx_norm dy_norm x1 y1 cr cg cb
1.498 os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
1.499 << " /w exch def /len exch def\n"
1.500 - // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
1.501 + // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
1.502 << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
1.503 << " len w sub arrl sub dx dy lrl\n"
1.504 << " arrw dy dx neg lrl\n"
1.505 @@ -857,175 +857,175 @@
1.506 os << "\ngsave\n";
1.507 if(_scaleToA4)
1.508 if(bb.height()>bb.width()) {
1.509 - double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
1.510 - (A4WIDTH-2*A4BORDER)/bb.width());
1.511 - os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
1.512 - << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
1.513 - << " translate\n"
1.514 - << sc << " dup scale\n"
1.515 - << -bb.left() << ' ' << -bb.bottom() << " translate\n";
1.516 + double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
1.517 + (A4WIDTH-2*A4BORDER)/bb.width());
1.518 + os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
1.519 + << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
1.520 + << " translate\n"
1.521 + << sc << " dup scale\n"
1.522 + << -bb.left() << ' ' << -bb.bottom() << " translate\n";
1.523 }
1.524 else {
1.525 - //\todo Verify centering
1.526 - double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
1.527 - (A4WIDTH-2*A4BORDER)/bb.height());
1.528 - os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
1.529 - << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
1.530 - << " translate\n"
1.531 - << sc << " dup scale\n90 rotate\n"
1.532 - << -bb.left() << ' ' << -bb.top() << " translate\n";
1.533 - }
1.534 + //\todo Verify centering
1.535 + double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
1.536 + (A4WIDTH-2*A4BORDER)/bb.height());
1.537 + os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
1.538 + << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
1.539 + << " translate\n"
1.540 + << sc << " dup scale\n90 rotate\n"
1.541 + << -bb.left() << ' ' << -bb.top() << " translate\n";
1.542 + }
1.543 else if(_scale!=1.0) os << _scale << " dup scale\n";
1.544 -
1.545 +
1.546 if(_showArcs) {
1.547 - os << "%Arcs:\ngsave\n";
1.548 + os << "%Arcs:\ngsave\n";
1.549 if(_enableParallel) {
1.550 - std::vector<Arc> el;
1.551 - for(ArcIt e(g);e!=INVALID;++e)
1.552 - if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
1.553 - &&g.source(e)!=g.target(e))
1.554 - el.push_back(e);
1.555 - std::sort(el.begin(),el.end(),arcLess(g));
1.556 -
1.557 - typename std::vector<Arc>::iterator j;
1.558 - for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
1.559 - for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
1.560 + std::vector<Arc> el;
1.561 + for(ArcIt e(g);e!=INVALID;++e)
1.562 + if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
1.563 + &&g.source(e)!=g.target(e))
1.564 + el.push_back(e);
1.565 + std::sort(el.begin(),el.end(),arcLess(g));
1.566
1.567 - double sw=0;
1.568 - for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
1.569 - sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
1.570 - sw-=_parArcDist;
1.571 - sw/=-2.0;
1.572 - dim2::Point<double>
1.573 - dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
1.574 - double l=std::sqrt(dvec.normSquare());
1.575 - //\todo better 'epsilon' would be nice here.
1.576 - dim2::Point<double> d(dvec/std::max(l,EPSILON));
1.577 - dim2::Point<double> m;
1.578 -// m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
1.579 + typename std::vector<Arc>::iterator j;
1.580 + for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
1.581 + for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
1.582
1.583 -// m=dim2::Point<double>(mycoords[g.source(*i)])+
1.584 -// dvec*(double(_nodeSizes[g.source(*i)])/
1.585 -// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
1.586 + double sw=0;
1.587 + for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
1.588 + sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
1.589 + sw-=_parArcDist;
1.590 + sw/=-2.0;
1.591 + dim2::Point<double>
1.592 + dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
1.593 + double l=std::sqrt(dvec.normSquare());
1.594 + //\todo better 'epsilon' would be nice here.
1.595 + dim2::Point<double> d(dvec/std::max(l,EPSILON));
1.596 + dim2::Point<double> m;
1.597 +// m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
1.598
1.599 - m=dim2::Point<double>(mycoords[g.source(*i)])+
1.600 - d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
1.601 +// m=dim2::Point<double>(mycoords[g.source(*i)])+
1.602 +// dvec*(double(_nodeSizes[g.source(*i)])/
1.603 +// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
1.604
1.605 - for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
1.606 - sw+=_arcWidths[*e]*_arcWidthScale/2.0;
1.607 - dim2::Point<double> mm=m+rot90(d)*sw/.75;
1.608 - if(_drawArrows) {
1.609 - int node_shape;
1.610 - dim2::Point<double> s=mycoords[g.source(*e)];
1.611 - dim2::Point<double> t=mycoords[g.target(*e)];
1.612 - double rn=_nodeSizes[g.target(*e)]*_nodeScale;
1.613 - node_shape=_nodeShapes[g.target(*e)];
1.614 - dim2::Bezier3 bez(s,mm,mm,t);
1.615 - double t1=0,t2=1;
1.616 - for(int ii=0;ii<INTERPOL_PREC;++ii)
1.617 - if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
1.618 - else t1=(t1+t2)/2;
1.619 - dim2::Point<double> apoint=bez((t1+t2)/2);
1.620 - rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
1.621 - rn*=rn;
1.622 - t2=(t1+t2)/2;t1=0;
1.623 - for(int ii=0;ii<INTERPOL_PREC;++ii)
1.624 - if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
1.625 - else t2=(t1+t2)/2;
1.626 - dim2::Point<double> linend=bez((t1+t2)/2);
1.627 - bez=bez.before((t1+t2)/2);
1.628 -// rn=_nodeSizes[g.source(*e)]*_nodeScale;
1.629 -// node_shape=_nodeShapes[g.source(*e)];
1.630 -// t1=0;t2=1;
1.631 -// for(int i=0;i<INTERPOL_PREC;++i)
1.632 -// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
1.633 -// else t2=(t1+t2)/2;
1.634 -// bez=bez.after((t1+t2)/2);
1.635 - os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
1.636 - << _arcColors[*e].red() << ' '
1.637 - << _arcColors[*e].green() << ' '
1.638 - << _arcColors[*e].blue() << " setrgbcolor newpath\n"
1.639 - << bez.p1.x << ' ' << bez.p1.y << " moveto\n"
1.640 - << bez.p2.x << ' ' << bez.p2.y << ' '
1.641 - << bez.p3.x << ' ' << bez.p3.y << ' '
1.642 - << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
1.643 - dim2::Point<double> dd(rot90(linend-apoint));
1.644 - dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
1.645 - std::sqrt(dd.normSquare());
1.646 - os << "newpath " << psOut(apoint) << " moveto "
1.647 - << psOut(linend+dd) << " lineto "
1.648 - << psOut(linend-dd) << " lineto closepath fill\n";
1.649 - }
1.650 - else {
1.651 - os << mycoords[g.source(*e)].x << ' '
1.652 - << mycoords[g.source(*e)].y << ' '
1.653 - << mm.x << ' ' << mm.y << ' '
1.654 - << mycoords[g.target(*e)].x << ' '
1.655 - << mycoords[g.target(*e)].y << ' '
1.656 - << _arcColors[*e].red() << ' '
1.657 - << _arcColors[*e].green() << ' '
1.658 - << _arcColors[*e].blue() << ' '
1.659 - << _arcWidths[*e]*_arcWidthScale << " lb\n";
1.660 - }
1.661 - sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
1.662 - }
1.663 - }
1.664 + m=dim2::Point<double>(mycoords[g.source(*i)])+
1.665 + d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
1.666 +
1.667 + for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
1.668 + sw+=_arcWidths[*e]*_arcWidthScale/2.0;
1.669 + dim2::Point<double> mm=m+rot90(d)*sw/.75;
1.670 + if(_drawArrows) {
1.671 + int node_shape;
1.672 + dim2::Point<double> s=mycoords[g.source(*e)];
1.673 + dim2::Point<double> t=mycoords[g.target(*e)];
1.674 + double rn=_nodeSizes[g.target(*e)]*_nodeScale;
1.675 + node_shape=_nodeShapes[g.target(*e)];
1.676 + dim2::Bezier3 bez(s,mm,mm,t);
1.677 + double t1=0,t2=1;
1.678 + for(int ii=0;ii<INTERPOL_PREC;++ii)
1.679 + if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
1.680 + else t1=(t1+t2)/2;
1.681 + dim2::Point<double> apoint=bez((t1+t2)/2);
1.682 + rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
1.683 + rn*=rn;
1.684 + t2=(t1+t2)/2;t1=0;
1.685 + for(int ii=0;ii<INTERPOL_PREC;++ii)
1.686 + if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
1.687 + else t2=(t1+t2)/2;
1.688 + dim2::Point<double> linend=bez((t1+t2)/2);
1.689 + bez=bez.before((t1+t2)/2);
1.690 +// rn=_nodeSizes[g.source(*e)]*_nodeScale;
1.691 +// node_shape=_nodeShapes[g.source(*e)];
1.692 +// t1=0;t2=1;
1.693 +// for(int i=0;i<INTERPOL_PREC;++i)
1.694 +// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
1.695 +// else t2=(t1+t2)/2;
1.696 +// bez=bez.after((t1+t2)/2);
1.697 + os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
1.698 + << _arcColors[*e].red() << ' '
1.699 + << _arcColors[*e].green() << ' '
1.700 + << _arcColors[*e].blue() << " setrgbcolor newpath\n"
1.701 + << bez.p1.x << ' ' << bez.p1.y << " moveto\n"
1.702 + << bez.p2.x << ' ' << bez.p2.y << ' '
1.703 + << bez.p3.x << ' ' << bez.p3.y << ' '
1.704 + << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
1.705 + dim2::Point<double> dd(rot90(linend-apoint));
1.706 + dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
1.707 + std::sqrt(dd.normSquare());
1.708 + os << "newpath " << psOut(apoint) << " moveto "
1.709 + << psOut(linend+dd) << " lineto "
1.710 + << psOut(linend-dd) << " lineto closepath fill\n";
1.711 + }
1.712 + else {
1.713 + os << mycoords[g.source(*e)].x << ' '
1.714 + << mycoords[g.source(*e)].y << ' '
1.715 + << mm.x << ' ' << mm.y << ' '
1.716 + << mycoords[g.target(*e)].x << ' '
1.717 + << mycoords[g.target(*e)].y << ' '
1.718 + << _arcColors[*e].red() << ' '
1.719 + << _arcColors[*e].green() << ' '
1.720 + << _arcColors[*e].blue() << ' '
1.721 + << _arcWidths[*e]*_arcWidthScale << " lb\n";
1.722 + }
1.723 + sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
1.724 + }
1.725 + }
1.726 }
1.727 else for(ArcIt e(g);e!=INVALID;++e)
1.728 - if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
1.729 - &&g.source(e)!=g.target(e)) {
1.730 - if(_drawArrows) {
1.731 - dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
1.732 - double rn=_nodeSizes[g.target(e)]*_nodeScale;
1.733 - int node_shape=_nodeShapes[g.target(e)];
1.734 - double t1=0,t2=1;
1.735 - for(int i=0;i<INTERPOL_PREC;++i)
1.736 - if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
1.737 - else t2=(t1+t2)/2;
1.738 - double l=std::sqrt(d.normSquare());
1.739 - d/=l;
1.740 -
1.741 - os << l*(1-(t1+t2)/2) << ' '
1.742 - << _arcWidths[e]*_arcWidthScale << ' '
1.743 - << d.x << ' ' << d.y << ' '
1.744 - << mycoords[g.source(e)].x << ' '
1.745 - << mycoords[g.source(e)].y << ' '
1.746 - << _arcColors[e].red() << ' '
1.747 - << _arcColors[e].green() << ' '
1.748 - << _arcColors[e].blue() << " arr\n";
1.749 - }
1.750 - else os << mycoords[g.source(e)].x << ' '
1.751 - << mycoords[g.source(e)].y << ' '
1.752 - << mycoords[g.target(e)].x << ' '
1.753 - << mycoords[g.target(e)].y << ' '
1.754 - << _arcColors[e].red() << ' '
1.755 - << _arcColors[e].green() << ' '
1.756 - << _arcColors[e].blue() << ' '
1.757 - << _arcWidths[e]*_arcWidthScale << " l\n";
1.758 - }
1.759 + if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
1.760 + &&g.source(e)!=g.target(e)) {
1.761 + if(_drawArrows) {
1.762 + dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
1.763 + double rn=_nodeSizes[g.target(e)]*_nodeScale;
1.764 + int node_shape=_nodeShapes[g.target(e)];
1.765 + double t1=0,t2=1;
1.766 + for(int i=0;i<INTERPOL_PREC;++i)
1.767 + if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
1.768 + else t2=(t1+t2)/2;
1.769 + double l=std::sqrt(d.normSquare());
1.770 + d/=l;
1.771 +
1.772 + os << l*(1-(t1+t2)/2) << ' '
1.773 + << _arcWidths[e]*_arcWidthScale << ' '
1.774 + << d.x << ' ' << d.y << ' '
1.775 + << mycoords[g.source(e)].x << ' '
1.776 + << mycoords[g.source(e)].y << ' '
1.777 + << _arcColors[e].red() << ' '
1.778 + << _arcColors[e].green() << ' '
1.779 + << _arcColors[e].blue() << " arr\n";
1.780 + }
1.781 + else os << mycoords[g.source(e)].x << ' '
1.782 + << mycoords[g.source(e)].y << ' '
1.783 + << mycoords[g.target(e)].x << ' '
1.784 + << mycoords[g.target(e)].y << ' '
1.785 + << _arcColors[e].red() << ' '
1.786 + << _arcColors[e].green() << ' '
1.787 + << _arcColors[e].blue() << ' '
1.788 + << _arcWidths[e]*_arcWidthScale << " l\n";
1.789 + }
1.790 os << "grestore\n";
1.791 }
1.792 if(_showNodes) {
1.793 os << "%Nodes:\ngsave\n";
1.794 for(NodeIt n(g);n!=INVALID;++n) {
1.795 - os << mycoords[n].x << ' ' << mycoords[n].y << ' '
1.796 - << _nodeSizes[n]*_nodeScale << ' '
1.797 - << _nodeColors[n].red() << ' '
1.798 - << _nodeColors[n].green() << ' '
1.799 - << _nodeColors[n].blue() << ' ';
1.800 - switch(_nodeShapes[n]) {
1.801 - case CIRCLE:
1.802 - os<< "nc";break;
1.803 - case SQUARE:
1.804 - os<< "nsq";break;
1.805 - case DIAMOND:
1.806 - os<< "ndi";break;
1.807 - case MALE:
1.808 - os<< "nmale";break;
1.809 - case FEMALE:
1.810 - os<< "nfemale";break;
1.811 - }
1.812 - os<<'\n';
1.813 + os << mycoords[n].x << ' ' << mycoords[n].y << ' '
1.814 + << _nodeSizes[n]*_nodeScale << ' '
1.815 + << _nodeColors[n].red() << ' '
1.816 + << _nodeColors[n].green() << ' '
1.817 + << _nodeColors[n].blue() << ' ';
1.818 + switch(_nodeShapes[n]) {
1.819 + case CIRCLE:
1.820 + os<< "nc";break;
1.821 + case SQUARE:
1.822 + os<< "nsq";break;
1.823 + case DIAMOND:
1.824 + os<< "ndi";break;
1.825 + case MALE:
1.826 + os<< "nmale";break;
1.827 + case FEMALE:
1.828 + os<< "nfemale";break;
1.829 + }
1.830 + os<<'\n';
1.831 }
1.832 os << "grestore\n";
1.833 }
1.834 @@ -1034,32 +1034,32 @@
1.835 os << "/fosi " << _nodeTextSize << " def\n";
1.836 os << "(Helvetica) findfont fosi scalefont setfont\n";
1.837 for(NodeIt n(g);n!=INVALID;++n) {
1.838 - switch(_nodeTextColorType) {
1.839 - case DIST_COL:
1.840 - os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
1.841 - break;
1.842 - case DIST_BW:
1.843 - os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
1.844 - break;
1.845 - case CUST_COL:
1.846 - os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
1.847 - break;
1.848 - default:
1.849 - os << "0 0 0 setrgbcolor\n";
1.850 - }
1.851 - os << mycoords[n].x << ' ' << mycoords[n].y
1.852 - << " (" << _nodeTexts[n] << ") cshow\n";
1.853 + switch(_nodeTextColorType) {
1.854 + case DIST_COL:
1.855 + os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
1.856 + break;
1.857 + case DIST_BW:
1.858 + os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
1.859 + break;
1.860 + case CUST_COL:
1.861 + os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
1.862 + break;
1.863 + default:
1.864 + os << "0 0 0 setrgbcolor\n";
1.865 + }
1.866 + os << mycoords[n].x << ' ' << mycoords[n].y
1.867 + << " (" << _nodeTexts[n] << ") cshow\n";
1.868 }
1.869 os << "grestore\n";
1.870 }
1.871 if(_showNodePsText) {
1.872 os << "%Node PS blocks:\ngsave\n";
1.873 for(NodeIt n(g);n!=INVALID;++n)
1.874 - os << mycoords[n].x << ' ' << mycoords[n].y
1.875 - << " moveto\n" << _nodePsTexts[n] << "\n";
1.876 + os << mycoords[n].x << ' ' << mycoords[n].y
1.877 + << " moveto\n" << _nodePsTexts[n] << "\n";
1.878 os << "grestore\n";
1.879 }
1.880 -
1.881 +
1.882 os << "grestore\nshowpage\n";
1.883
1.884 //CleanUp:
1.885 @@ -1092,16 +1092,16 @@
1.886 {
1.887 return autoArcWidthScale(b);
1.888 }
1.889 -
1.890 +
1.891 ///An alias for absoluteArcWidths()
1.892 GraphToEps<T> &absoluteEdgeWidths(bool b=true)
1.893 {
1.894 return absoluteArcWidths(b);
1.895 }
1.896 -
1.897 +
1.898 ///An alias for parArcDist()
1.899 GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
1.900 -
1.901 +
1.902 ///An alias for hideArcs()
1.903 GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
1.904
1.905 @@ -1143,13 +1143,13 @@
1.906 ///\sa GraphToEps
1.907 ///\sa graphToEps(G &g, const char *file_name)
1.908 template<class G>
1.909 -GraphToEps<DefaultGraphToEpsTraits<G> >
1.910 +GraphToEps<DefaultGraphToEpsTraits<G> >
1.911 graphToEps(G &g, std::ostream& os=std::cout)
1.912 {
1.913 - return
1.914 + return
1.915 GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
1.916 }
1.917 -
1.918 +
1.919 ///Generates an EPS file from a graph
1.920
1.921 ///\ingroup eps_io
1.922 @@ -1159,7 +1159,7 @@
1.923 ///instead of a stream.
1.924 ///\sa graphToEps(G &g, std::ostream& os)
1.925 template<class G>
1.926 -GraphToEps<DefaultGraphToEpsTraits<G> >
1.927 +GraphToEps<DefaultGraphToEpsTraits<G> >
1.928 graphToEps(G &g,const char *file_name)
1.929 {
1.930 return GraphToEps<DefaultGraphToEpsTraits<G> >
1.931 @@ -1175,7 +1175,7 @@
1.932 ///instead of a stream.
1.933 ///\sa graphToEps(G &g, std::ostream& os)
1.934 template<class G>
1.935 -GraphToEps<DefaultGraphToEpsTraits<G> >
1.936 +GraphToEps<DefaultGraphToEpsTraits<G> >
1.937 graphToEps(G &g,const std::string& file_name)
1.938 {
1.939 return GraphToEps<DefaultGraphToEpsTraits<G> >