Port graph_to_eps() and Color from svn -r3482.
1.1 --- a/.hgignore Tue Apr 01 16:25:51 2008 +0100
1.2 +++ b/.hgignore Thu Apr 03 11:10:49 2008 +0100
1.3 @@ -24,6 +24,7 @@
1.4 .dirstamp
1.5 .libs/*
1.6 .deps/*
1.7 +demo/*.eps
1.8
1.9 syntax: regexp
1.10 (.*/)?\#[^/]*\#$
2.1 --- a/demo/Makefile.am Tue Apr 01 16:25:51 2008 +0100
2.2 +++ b/demo/Makefile.am Thu Apr 03 11:10:49 2008 +0100
2.3 @@ -4,9 +4,12 @@
2.4 if WANT_DEMO
2.5
2.6 noinst_PROGRAMS += \
2.7 - demo/arg_parser_demo
2.8 + demo/arg_parser_demo \
2.9 + demo/graph_to_eps_demo
2.10
2.11 endif WANT_DEMO
2.12
2.13 demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc
2.14
2.15 +demo_graph_to_eps_demo_SOURCES = demo/graph_to_eps_demo.cc
2.16 +
3.1 --- a/demo/arg_parser_demo.cc Tue Apr 01 16:25:51 2008 +0100
3.2 +++ b/demo/arg_parser_demo.cc Thu Apr 03 11:10:49 2008 +0100
3.3 @@ -37,6 +37,7 @@
3.4 bool g1,g2,g3;
3.5 ap.refOption("n", "An integer input.", i, true)
3.6 .refOption("val", "A double input.", d)
3.7 + .doubleOption("val2", "A double input.", d)
3.8 .synonym("vals","val")
3.9 .refOption("name", "A string input.", s)
3.10 .refOption("f", "A switch.", b)
3.11 @@ -45,7 +46,7 @@
3.12 .refOption("grb","Choice B",g2)
3.13 .refOption("grc","Choice C",g3)
3.14 .optionGroup("gr","gra")
3.15 - .optionGroup("gr","grb")
3.16 + .optionGroup("gr","grbkk")
3.17 .optionGroup("gr","grc")
3.18 .mandatoryGroup("gr")
3.19 .onlyOneGroup("gr")
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/demo/graph_to_eps_demo.cc Thu Apr 03 11:10:49 2008 +0100
4.3 @@ -0,0 +1,208 @@
4.4 +/* -*- C++ -*-
4.5 + *
4.6 + * This file is a part of LEMON, a generic C++ optimization library
4.7 + *
4.8 + * Copyright (C) 2003-2008
4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
4.11 + *
4.12 + * Permission to use, modify and distribute this software is granted
4.13 + * provided that this copyright notice appears in all copies. For
4.14 + * precise terms see the accompanying LICENSE file.
4.15 + *
4.16 + * This software is provided "AS IS" with no warranty of any kind,
4.17 + * express or implied, and with no claim as to its suitability for any
4.18 + * purpose.
4.19 + *
4.20 + */
4.21 +
4.22 +/// \ingroup demos
4.23 +/// \file
4.24 +/// \brief Demo of the graph grawing function \ref graphToEps()
4.25 +///
4.26 +/// This demo program shows examples how to use the function \ref
4.27 +/// graphToEps(). It takes no input but simply creates six
4.28 +/// <tt>.eps</tt> files demonstrating the capability of \ref
4.29 +/// graphToEps(), and showing how to draw directed/graphs,
4.30 +/// how to handle parallel egdes, how to change the properties (like
4.31 +/// color, shape, size, title etc.) of nodes and arcs individually
4.32 +/// using appropriate \ref maps-page "graph maps".
4.33 +///
4.34 +/// \include graph_to_eps_demo.cc
4.35 +
4.36 +#include <lemon/math.h>
4.37 +
4.38 +#include<lemon/graph_to_eps.h>
4.39 +#include<lemon/list_graph.h>
4.40 +#include<lemon/graph_utils.h>
4.41 +
4.42 +using namespace std;
4.43 +using namespace lemon;
4.44 +
4.45 +int main()
4.46 +{
4.47 + Palette palette;
4.48 + Palette paletteW(-1,true);
4.49 +
4.50 + ListDigraph g;
4.51 + typedef ListDigraph::Node Node;
4.52 + typedef ListDigraph::NodeIt NodeIt;
4.53 + typedef ListDigraph::Arc Arc;
4.54 + typedef dim2::Point<int> Point;
4.55 +
4.56 + Node n1=g.addNode();
4.57 + Node n2=g.addNode();
4.58 + Node n3=g.addNode();
4.59 + Node n4=g.addNode();
4.60 + Node n5=g.addNode();
4.61 +
4.62 + ListDigraph::NodeMap<Point> coords(g);
4.63 + ListDigraph::NodeMap<double> sizes(g);
4.64 + ListDigraph::NodeMap<int> colors(g);
4.65 + ListDigraph::NodeMap<int> shapes(g);
4.66 + ListDigraph::ArcMap<int> ecolors(g);
4.67 + ListDigraph::ArcMap<int> widths(g);
4.68 +
4.69 + coords[n1]=Point(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0;
4.70 + coords[n2]=Point(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2;
4.71 + coords[n3]=Point(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0;
4.72 + coords[n4]=Point(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1;
4.73 + coords[n5]=Point(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2;
4.74 +
4.75 + Arc e;
4.76 +
4.77 + e=g.addArc(n1,n2); ecolors[e]=0; widths[e]=1;
4.78 + e=g.addArc(n2,n3); ecolors[e]=0; widths[e]=1;
4.79 + e=g.addArc(n3,n5); ecolors[e]=0; widths[e]=3;
4.80 + e=g.addArc(n5,n4); ecolors[e]=0; widths[e]=1;
4.81 + e=g.addArc(n4,n1); ecolors[e]=0; widths[e]=1;
4.82 + e=g.addArc(n2,n4); ecolors[e]=1; widths[e]=2;
4.83 + e=g.addArc(n3,n4); ecolors[e]=2; widths[e]=1;
4.84 +
4.85 + IdMap<ListDigraph,Node> id(g);
4.86 +
4.87 + cout << "Create 'graph_to_eps_demo_out_pure.eps'" << endl;
4.88 + graphToEps(g,"graph_to_eps_demo_out_pure.eps").
4.89 + //scale(10).
4.90 + coords(coords).
4.91 + title("Sample .eps figure").
4.92 + copyright("(C) 2003-2007 LEMON Project").
4.93 + run();
4.94 +
4.95 + cout << "Create 'graph_to_eps_demo_out.eps'" << endl;
4.96 + graphToEps(g,"graph_to_eps_demo_out.eps").
4.97 + //scale(10).
4.98 + coords(coords).
4.99 + title("Sample .eps figure").
4.100 + copyright("(C) 2003-2007 LEMON Project").
4.101 + absoluteNodeSizes().absoluteArcWidths().
4.102 + nodeScale(2).nodeSizes(sizes).
4.103 + nodeShapes(shapes).
4.104 + nodeColors(composeMap(palette,colors)).
4.105 + arcColors(composeMap(palette,ecolors)).
4.106 + arcWidthScale(.4).arcWidths(widths).
4.107 + nodeTexts(id).nodeTextSize(3).
4.108 + run();
4.109 +
4.110 +
4.111 + cout << "Create 'graph_to_eps_demo_out_arr.eps'" << endl;
4.112 + graphToEps(g,"graph_to_eps_demo_out_arr.eps").
4.113 + //scale(10).
4.114 + title("Sample .eps figure (with arrowheads)").
4.115 + copyright("(C) 2003-2007 LEMON Project").
4.116 + absoluteNodeSizes().absoluteArcWidths().
4.117 + nodeColors(composeMap(palette,colors)).
4.118 + coords(coords).
4.119 + nodeScale(2).nodeSizes(sizes).
4.120 + nodeShapes(shapes).
4.121 + arcColors(composeMap(palette,ecolors)).
4.122 + arcWidthScale(.4).arcWidths(widths).
4.123 + nodeTexts(id).nodeTextSize(3).
4.124 + drawArrows().arrowWidth(1).arrowLength(1).
4.125 + run();
4.126 +
4.127 + e=g.addArc(n1,n4); ecolors[e]=2; widths[e]=1;
4.128 + e=g.addArc(n4,n1); ecolors[e]=1; widths[e]=2;
4.129 +
4.130 + e=g.addArc(n1,n2); ecolors[e]=1; widths[e]=1;
4.131 + e=g.addArc(n1,n2); ecolors[e]=2; widths[e]=1;
4.132 + e=g.addArc(n1,n2); ecolors[e]=3; widths[e]=1;
4.133 + e=g.addArc(n1,n2); ecolors[e]=4; widths[e]=1;
4.134 + e=g.addArc(n1,n2); ecolors[e]=5; widths[e]=1;
4.135 + e=g.addArc(n1,n2); ecolors[e]=6; widths[e]=1;
4.136 + e=g.addArc(n1,n2); ecolors[e]=7; widths[e]=1;
4.137 +
4.138 + cout << "Create 'graph_to_eps_demo_out_par.eps'" << endl;
4.139 + graphToEps(g,"graph_to_eps_demo_out_par.eps").
4.140 + //scale(10).
4.141 + title("Sample .eps figure (parallel arcs)").
4.142 + copyright("(C) 2003-2007 LEMON Project").
4.143 + absoluteNodeSizes().absoluteArcWidths().
4.144 + nodeShapes(shapes).
4.145 + coords(coords).
4.146 + nodeScale(2).nodeSizes(sizes).
4.147 + nodeColors(composeMap(palette,colors)).
4.148 + arcColors(composeMap(palette,ecolors)).
4.149 + arcWidthScale(.4).arcWidths(widths).
4.150 + nodeTexts(id).nodeTextSize(3).
4.151 + enableParallel().parArcDist(1.5).
4.152 + run();
4.153 +
4.154 + cout << "Create 'graph_to_eps_demo_out_par_arr.eps'" << endl;
4.155 + graphToEps(g,"graph_to_eps_demo_out_par_arr.eps").
4.156 + //scale(10).
4.157 + title("Sample .eps figure (parallel arcs and arrowheads)").
4.158 + copyright("(C) 2003-2007 LEMON Project").
4.159 + absoluteNodeSizes().absoluteArcWidths().
4.160 + nodeScale(2).nodeSizes(sizes).
4.161 + coords(coords).
4.162 + nodeShapes(shapes).
4.163 + nodeColors(composeMap(palette,colors)).
4.164 + arcColors(composeMap(palette,ecolors)).
4.165 + arcWidthScale(.3).arcWidths(widths).
4.166 + nodeTexts(id).nodeTextSize(3).
4.167 + enableParallel().parArcDist(1).
4.168 + drawArrows().arrowWidth(1).arrowLength(1).
4.169 + run();
4.170 +
4.171 + cout << "Create 'graph_to_eps_demo_out_a4.eps'" << endl;
4.172 + graphToEps(g,"graph_to_eps_demo_out_a4.eps").scaleToA4().
4.173 + title("Sample .eps figure (fits to A4)").
4.174 + copyright("(C) 2003-2007 LEMON Project").
4.175 + absoluteNodeSizes().absoluteArcWidths().
4.176 + nodeScale(2).nodeSizes(sizes).
4.177 + coords(coords).
4.178 + nodeShapes(shapes).
4.179 + nodeColors(composeMap(palette,colors)).
4.180 + arcColors(composeMap(palette,ecolors)).
4.181 + arcWidthScale(.3).arcWidths(widths).
4.182 + nodeTexts(id).nodeTextSize(3).
4.183 + enableParallel().parArcDist(1).
4.184 + drawArrows().arrowWidth(1).arrowLength(1).
4.185 + run();
4.186 +
4.187 + ListDigraph h;
4.188 + ListDigraph::NodeMap<int> hcolors(h);
4.189 + ListDigraph::NodeMap<Point> hcoords(h);
4.190 +
4.191 + int cols=int(sqrt(double(palette.size())));
4.192 + for(int i=0;i<int(paletteW.size());i++) {
4.193 + Node n=h.addNode();
4.194 + hcoords[n]=Point(i%cols,i/cols);
4.195 + hcolors[n]=i;
4.196 + }
4.197 +
4.198 + cout << "Create 'graph_to_eps_demo_out_colors.eps'" << endl;
4.199 + graphToEps(h,"graph_to_eps_demo_out_colors.eps").
4.200 + //scale(60).
4.201 + title("Sample .eps figure (Palette demo)").
4.202 + copyright("(C) 2003-2007 LEMON Project").
4.203 + coords(hcoords).
4.204 + absoluteNodeSizes().absoluteArcWidths().
4.205 + nodeScale(45).
4.206 + distantColorNodeTexts().
4.207 + // distantBWNodeTexts().
4.208 + nodeTexts(hcolors).nodeTextSize(.6).
4.209 + nodeColors(composeMap(paletteW,hcolors)).
4.210 + run();
4.211 +}
5.1 --- a/lemon/Makefile.am Tue Apr 01 16:25:51 2008 +0100
5.2 +++ b/lemon/Makefile.am Thu Apr 03 11:10:49 2008 +0100
5.3 @@ -9,6 +9,7 @@
5.4 lemon_libemon_la_SOURCES = \
5.5 lemon/arg_parser.cc \
5.6 lemon/base.cc \
5.7 + lemon/color.cc \
5.8 lemon/random.cc
5.9
5.10
5.11 @@ -20,10 +21,12 @@
5.12 lemon/assert.h \
5.13 lemon/bfs.h \
5.14 lemon/bin_heap.h \
5.15 + lemon/color.h \
5.16 lemon/dfs.h \
5.17 lemon/dijkstra.h \
5.18 lemon/dim2.h \
5.19 lemon/error.h \
5.20 + lemon/graph_to_eps.h \
5.21 lemon/graph_utils.h \
5.22 lemon/kruskal.h \
5.23 lemon/list_graph.h \
5.24 @@ -39,6 +42,7 @@
5.25 lemon/bits/alteration_notifier.h \
5.26 lemon/bits/array_map.h \
5.27 lemon/bits/base_extender.h \
5.28 + lemon/bits/bezier.h \
5.29 lemon/bits/default_map.h \
5.30 lemon/bits/graph_extender.h \
5.31 lemon/bits/invalid.h \
6.1 --- a/lemon/arg_parser.cc Tue Apr 01 16:25:51 2008 +0100
6.2 +++ b/lemon/arg_parser.cc Thu Apr 03 11:10:49 2008 +0100
6.3 @@ -194,6 +194,7 @@
6.4 {
6.5 Opts::iterator i = _opts.find(opt);
6.6 LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'");
6.7 + if(i==_opts.end()) std::cout << "JAJJJJJJJJ\n";
6.8 LEMON_ASSERT(!(i->second.ingroup),
6.9 "Option already in option group: '"+opt+"'");
6.10 GroupData &g=_groups[group];
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/lemon/bits/bezier.h Thu Apr 03 11:10:49 2008 +0100
7.3 @@ -0,0 +1,176 @@
7.4 +/* -*- C++ -*-
7.5 + *
7.6 + * This file is a part of LEMON, a generic C++ optimization library
7.7 + *
7.8 + * Copyright (C) 2003-2008
7.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
7.11 + *
7.12 + * Permission to use, modify and distribute this software is granted
7.13 + * provided that this copyright notice appears in all copies. For
7.14 + * precise terms see the accompanying LICENSE file.
7.15 + *
7.16 + * This software is provided "AS IS" with no warranty of any kind,
7.17 + * express or implied, and with no claim as to its suitability for any
7.18 + * purpose.
7.19 + *
7.20 + */
7.21 +
7.22 +#ifndef LEMON_BEZIER_H
7.23 +#define LEMON_BEZIER_H
7.24 +
7.25 +///\ingroup misc
7.26 +///\file
7.27 +///\brief Classes to compute with Bezier curves.
7.28 +///
7.29 +///Up to now this file is used internally by \ref graph_to_eps.h
7.30 +///
7.31 +///\author Alpar Juttner
7.32 +
7.33 +#include<lemon/dim2.h>
7.34 +
7.35 +namespace lemon {
7.36 + namespace dim2 {
7.37 +
7.38 +class BezierBase {
7.39 +public:
7.40 + typedef Point<double> Point;
7.41 +protected:
7.42 + static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
7.43 +};
7.44 +
7.45 +class Bezier1 : public BezierBase
7.46 +{
7.47 +public:
7.48 + Point p1,p2;
7.49 +
7.50 + Bezier1() {}
7.51 + Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
7.52 +
7.53 + Point operator()(double t) const
7.54 + {
7.55 + // return conv(conv(p1,p2,t),conv(p2,p3,t),t);
7.56 + return conv(p1,p2,t);
7.57 + }
7.58 + Bezier1 before(double t) const
7.59 + {
7.60 + return Bezier1(p1,conv(p1,p2,t));
7.61 + }
7.62 +
7.63 + Bezier1 after(double t) const
7.64 + {
7.65 + return Bezier1(conv(p1,p2,t),p2);
7.66 + }
7.67 +
7.68 + Bezier1 revert() const { return Bezier1(p2,p1);}
7.69 + Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
7.70 + Point grad() const { return p2-p1; }
7.71 + Point norm() const { return rot90(p2-p1); }
7.72 + Point grad(double) const { return grad(); }
7.73 + Point norm(double t) const { return rot90(grad(t)); }
7.74 +};
7.75 +
7.76 +class Bezier2 : public BezierBase
7.77 +{
7.78 +public:
7.79 + Point p1,p2,p3;
7.80 +
7.81 + Bezier2() {}
7.82 + Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
7.83 + Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
7.84 + Point operator()(double t) const
7.85 + {
7.86 + // return conv(conv(p1,p2,t),conv(p2,p3,t),t);
7.87 + return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3;
7.88 + }
7.89 + Bezier2 before(double t) const
7.90 + {
7.91 + Point q(conv(p1,p2,t));
7.92 + Point r(conv(p2,p3,t));
7.93 + return Bezier2(p1,q,conv(q,r,t));
7.94 + }
7.95 +
7.96 + Bezier2 after(double t) const
7.97 + {
7.98 + Point q(conv(p1,p2,t));
7.99 + Point r(conv(p2,p3,t));
7.100 + return Bezier2(conv(q,r,t),r,p3);
7.101 + }
7.102 + Bezier2 revert() const { return Bezier2(p3,p2,p1);}
7.103 + Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
7.104 + Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
7.105 + Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
7.106 + Point grad(double t) const { return grad()(t); }
7.107 + Point norm(double t) const { return rot90(grad(t)); }
7.108 +};
7.109 +
7.110 +class Bezier3 : public BezierBase
7.111 +{
7.112 +public:
7.113 + Point p1,p2,p3,p4;
7.114 +
7.115 + Bezier3() {}
7.116 + Bezier3(Point _p1, Point _p2, Point _p3, Point _p4)
7.117 + : p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
7.118 + Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)),
7.119 + p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
7.120 + Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)),
7.121 + p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
7.122 +
7.123 + Point operator()(double t) const
7.124 + {
7.125 + // return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t);
7.126 + return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+
7.127 + (3*t*t*(1-t))*p3+(t*t*t)*p4;
7.128 + }
7.129 + Bezier3 before(double t) const
7.130 + {
7.131 + Point p(conv(p1,p2,t));
7.132 + Point q(conv(p2,p3,t));
7.133 + Point r(conv(p3,p4,t));
7.134 + Point a(conv(p,q,t));
7.135 + Point b(conv(q,r,t));
7.136 + Point c(conv(a,b,t));
7.137 + return Bezier3(p1,p,a,c);
7.138 + }
7.139 +
7.140 + Bezier3 after(double t) const
7.141 + {
7.142 + Point p(conv(p1,p2,t));
7.143 + Point q(conv(p2,p3,t));
7.144 + Point r(conv(p3,p4,t));
7.145 + Point a(conv(p,q,t));
7.146 + Point b(conv(q,r,t));
7.147 + Point c(conv(a,b,t));
7.148 + return Bezier3(c,b,r,p4);
7.149 + }
7.150 + Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
7.151 + Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
7.152 + Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
7.153 + Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
7.154 + 3.0*rot90(p3-p2),
7.155 + 3.0*rot90(p4-p3)); }
7.156 + Point grad(double t) const { return grad()(t); }
7.157 + Point norm(double t) const { return rot90(grad(t)); }
7.158 +
7.159 + template<class R,class F,class S,class D>
7.160 + R recSplit(F &_f,const S &_s,D _d) const
7.161 + {
7.162 + const Point a=(p1+p2)/2;
7.163 + const Point b=(p2+p3)/2;
7.164 + const Point c=(p3+p4)/2;
7.165 + const Point d=(a+b)/2;
7.166 + const Point e=(b+c)/2;
7.167 + const Point f=(d+e)/2;
7.168 + R f1=_f(Bezier3(p1,a,d,e),_d);
7.169 + R f2=_f(Bezier3(e,d,c,p4),_d);
7.170 + return _s(f1,f2);
7.171 + }
7.172 +
7.173 +};
7.174 +
7.175 +
7.176 +} //END OF NAMESPACE dim2
7.177 +} //END OF NAMESPACE lemon
7.178 +
7.179 +#endif // LEMON_BEZIER_H
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/lemon/color.cc Thu Apr 03 11:10:49 2008 +0100
8.3 @@ -0,0 +1,44 @@
8.4 +/* -*- C++ -*-
8.5 + *
8.6 + * This file is a part of LEMON, a generic C++ optimization library
8.7 + *
8.8 + * Copyright (C) 2003-2008
8.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
8.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
8.11 + *
8.12 + * Permission to use, modify and distribute this software is granted
8.13 + * provided that this copyright notice appears in all copies. For
8.14 + * precise terms see the accompanying LICENSE file.
8.15 + *
8.16 + * This software is provided "AS IS" with no warranty of any kind,
8.17 + * express or implied, and with no claim as to its suitability for any
8.18 + * purpose.
8.19 + *
8.20 + */
8.21 +
8.22 +///\file
8.23 +///\brief Color constants
8.24 +
8.25 +#include<lemon/color.h>
8.26 +
8.27 +namespace lemon {
8.28 +
8.29 + const Color WHITE(1,1,1);
8.30 +
8.31 + const Color BLACK(0,0,0);
8.32 + const Color RED(1,0,0);
8.33 + const Color GREEN(0,1,0);
8.34 + const Color BLUE(0,0,1);
8.35 + const Color YELLOW(1,1,0);
8.36 + const Color MAGENTA(1,0,1);
8.37 + const Color CYAN(0,1,1);
8.38 +
8.39 + const Color GREY(0,0,0);
8.40 + const Color DARK_RED(.5,0,0);
8.41 + const Color DARK_GREEN(0,.5,0);
8.42 + const Color DARK_BLUE(0,0,.5);
8.43 + const Color DARK_YELLOW(.5,.5,0);
8.44 + const Color DARK_MAGENTA(.5,0,.5);
8.45 + const Color DARK_CYAN(0,.5,.5);
8.46 +
8.47 +} //namespace lemon
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/lemon/color.h Thu Apr 03 11:10:49 2008 +0100
9.3 @@ -0,0 +1,207 @@
9.4 +/* -*- C++ -*-
9.5 + *
9.6 + * This file is a part of LEMON, a generic C++ optimization library
9.7 + *
9.8 + * Copyright (C) 2003-2008
9.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
9.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
9.11 + *
9.12 + * Permission to use, modify and distribute this software is granted
9.13 + * provided that this copyright notice appears in all copies. For
9.14 + * precise terms see the accompanying LICENSE file.
9.15 + *
9.16 + * This software is provided "AS IS" with no warranty of any kind,
9.17 + * express or implied, and with no claim as to its suitability for any
9.18 + * purpose.
9.19 + *
9.20 + */
9.21 +
9.22 +#ifndef LEMON_COLOR_H
9.23 +#define LEMON_COLOR_H
9.24 +
9.25 +#include<vector>
9.26 +#include<lemon/math.h>
9.27 +#include<lemon/maps.h>
9.28 +
9.29 +
9.30 +///\ingroup misc
9.31 +///\file
9.32 +///\brief Tools to manage RGB colors.
9.33 +///
9.34 +///\author Alpar Juttner
9.35 +
9.36 +namespace lemon {
9.37 +
9.38 +
9.39 + /// \addtogroup misc
9.40 + /// @{
9.41 +
9.42 + ///Data structure representing RGB colors.
9.43 +
9.44 + ///Data structure representing RGB colors.
9.45 + class Color
9.46 + {
9.47 + double _r,_g,_b;
9.48 + public:
9.49 + ///Default constructor
9.50 + Color() {}
9.51 + ///Constructor
9.52 + Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
9.53 + ///Set the red component
9.54 + double & red() {return _r;}
9.55 + ///Return the red component
9.56 + const double & red() const {return _r;}
9.57 + ///Set the green component
9.58 + double & green() {return _g;}
9.59 + ///Return the green component
9.60 + const double & green() const {return _g;}
9.61 + ///Set the blue component
9.62 + double & blue() {return _b;}
9.63 + ///Return the blue component
9.64 + const double & blue() const {return _b;}
9.65 + ///Set the color components
9.66 + void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
9.67 + };
9.68 +
9.69 + /// White color constant
9.70 + extern const Color WHITE;
9.71 + /// Black color constant
9.72 + extern const Color BLACK;
9.73 + /// Red color constant
9.74 + extern const Color RED;
9.75 + /// Green color constant
9.76 + extern const Color GREEN;
9.77 + /// Blue color constant
9.78 + extern const Color BLUE;
9.79 + /// Yellow color constant
9.80 + extern const Color YELLOW;
9.81 + /// Magenta color constant
9.82 + extern const Color MAGENTA;
9.83 + /// Cyan color constant
9.84 + extern const Color CYAN;
9.85 + /// Grey color constant
9.86 + extern const Color GREY;
9.87 + /// Dark red color constant
9.88 + extern const Color DARK_RED;
9.89 + /// Dark green color constant
9.90 + extern const Color DARK_GREEN;
9.91 + /// Drak blue color constant
9.92 + extern const Color DARK_BLUE;
9.93 + /// Dark yellow color constant
9.94 + extern const Color DARK_YELLOW;
9.95 + /// Dark magenta color constant
9.96 + extern const Color DARK_MAGENTA;
9.97 + /// Dark cyan color constant
9.98 + extern const Color DARK_CYAN;
9.99 +
9.100 + ///Map <tt>int</tt>s to different \ref Color "Color"s
9.101 +
9.102 + ///This map assigns one of the predefined \ref Color "Color"s to
9.103 + ///each <tt>int</tt>. It is possible to change the colors as well as
9.104 + ///their number. The integer range is cyclically mapped to the
9.105 + ///provided set of colors.
9.106 + ///
9.107 + ///This is a true \ref concepts::ReferenceMap "reference map", so
9.108 + ///you can also change the actual colors.
9.109 +
9.110 + class Palette : public MapBase<int,Color>
9.111 + {
9.112 + std::vector<Color> colors;
9.113 + public:
9.114 + ///Constructor
9.115 +
9.116 + ///Constructor
9.117 + ///\param num the number of the allocated colors. If it is \c -1,
9.118 + ///the default color configuration is set up (26 color plus the
9.119 + ///white). If \c num is less then 26/27 then the default color
9.120 + ///list is cut. Otherwise the color list is filled repeatedly with
9.121 + ///the default color list. (The colors can be changed later on.)
9.122 + ///\param have_white indicates whether white is amongst the
9.123 + ///provided color (\c true) or not (\c false). If it is true,
9.124 + ///white will be assigned to \c 0.
9.125 + Palette(int num=-1,bool have_white=false)
9.126 + {
9.127 + if (num==0) return;
9.128 + do {
9.129 + if(have_white) colors.push_back(Color(1,1,1));
9.130 +
9.131 + colors.push_back(Color(0,0,0));
9.132 + colors.push_back(Color(1,0,0));
9.133 + colors.push_back(Color(0,1,0));
9.134 + colors.push_back(Color(0,0,1));
9.135 + colors.push_back(Color(1,1,0));
9.136 + colors.push_back(Color(1,0,1));
9.137 + colors.push_back(Color(0,1,1));
9.138 +
9.139 + colors.push_back(Color(.5,0,0));
9.140 + colors.push_back(Color(0,.5,0));
9.141 + colors.push_back(Color(0,0,.5));
9.142 + colors.push_back(Color(.5,.5,0));
9.143 + colors.push_back(Color(.5,0,.5));
9.144 + colors.push_back(Color(0,.5,.5));
9.145 +
9.146 + colors.push_back(Color(.5,.5,.5));
9.147 + colors.push_back(Color(1,.5,.5));
9.148 + colors.push_back(Color(.5,1,.5));
9.149 + colors.push_back(Color(.5,.5,1));
9.150 + colors.push_back(Color(1,1,.5));
9.151 + colors.push_back(Color(1,.5,1));
9.152 + colors.push_back(Color(.5,1,1));
9.153 +
9.154 + colors.push_back(Color(1,.5,0));
9.155 + colors.push_back(Color(.5,1,0));
9.156 + colors.push_back(Color(1,0,.5));
9.157 + colors.push_back(Color(0,1,.5));
9.158 + colors.push_back(Color(0,.5,1));
9.159 + colors.push_back(Color(.5,0,1));
9.160 + } while(int(colors.size())<num);
9.161 + // colors.push_back(Color(1,1,1));
9.162 + if(num>=0) colors.resize(num);
9.163 + }
9.164 + ///\e
9.165 + Color &operator[](int i)
9.166 + {
9.167 + return colors[i%colors.size()];
9.168 + }
9.169 + ///\e
9.170 + const Color &operator[](int i) const
9.171 + {
9.172 + return colors[i%colors.size()];
9.173 + }
9.174 + ///\e
9.175 + void set(int i,const Color &c)
9.176 + {
9.177 + colors[i%colors.size()]=c;
9.178 + }
9.179 + ///\e
9.180 + void add(const Color &c)
9.181 + {
9.182 + colors.push_back(c);
9.183 + }
9.184 +
9.185 + ///Sets the number of the exiting colors.
9.186 + void resize(int s) { colors.resize(s);}
9.187 + ///Returns the number of the existing colors.
9.188 + int size() const { return int(colors.size());}
9.189 + };
9.190 +
9.191 + ///Returns a visible distinct \ref Color
9.192 +
9.193 + ///Returns a \ref Color which is as different from the given parameter
9.194 + ///as it is possible.
9.195 + inline Color distantColor(const Color &c)
9.196 + {
9.197 + return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0);
9.198 + }
9.199 + ///Returns black for light colors and white for the dark ones.
9.200 +
9.201 + ///Returns black for light colors and white for the dark ones.
9.202 + inline Color distantBW(const Color &c){
9.203 + return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK;
9.204 + }
9.205 +
9.206 + /// @}
9.207 +
9.208 +} //END OF NAMESPACE LEMON
9.209 +
9.210 +#endif // LEMON_COLOR_H
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/lemon/graph_to_eps.h Thu Apr 03 11:10:49 2008 +0100
10.3 @@ -0,0 +1,1170 @@
10.4 +/* -*- C++ -*-
10.5 + *
10.6 + * This file is a part of LEMON, a generic C++ optimization library
10.7 + *
10.8 + * Copyright (C) 2003-2008
10.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
10.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
10.11 + *
10.12 + * Permission to use, modify and distribute this software is granted
10.13 + * provided that this copyright notice appears in all copies. For
10.14 + * precise terms see the accompanying LICENSE file.
10.15 + *
10.16 + * This software is provided "AS IS" with no warranty of any kind,
10.17 + * express or implied, and with no claim as to its suitability for any
10.18 + * purpose.
10.19 + *
10.20 + */
10.21 +
10.22 +#ifndef LEMON_GRAPH_TO_EPS_H
10.23 +#define LEMON_GRAPH_TO_EPS_H
10.24 +
10.25 +#include <sys/time.h>
10.26 +
10.27 +#ifdef WIN32
10.28 +#include <lemon/bits/mingw32_time.h>
10.29 +#endif
10.30 +
10.31 +#include<iostream>
10.32 +#include<fstream>
10.33 +#include<sstream>
10.34 +#include<algorithm>
10.35 +#include<vector>
10.36 +
10.37 +#include<ctime>
10.38 +
10.39 +#include<lemon/math.h>
10.40 +#include<lemon/bits/invalid.h>
10.41 +#include<lemon/dim2.h>
10.42 +#include<lemon/maps.h>
10.43 +#include<lemon/color.h>
10.44 +#include<lemon/bits/bezier.h>
10.45 +
10.46 +
10.47 +///\ingroup eps_io
10.48 +///\file
10.49 +///\brief Simple graph drawer
10.50 +///
10.51 +///\author Alpar Juttner
10.52 +
10.53 +namespace lemon {
10.54 +
10.55 +template<class MT>
10.56 +class _NegY {
10.57 +public:
10.58 + typedef typename MT::Key Key;
10.59 + typedef typename MT::Value Value;
10.60 + const MT ↦
10.61 + int yscale;
10.62 + _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
10.63 + Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
10.64 +};
10.65 +
10.66 +///Default traits class of \ref GraphToEps
10.67 +
10.68 +///Default traits class of \ref GraphToEps
10.69 +///
10.70 +///\c G is the type of the underlying graph.
10.71 +template<class G>
10.72 +struct DefaultGraphToEpsTraits
10.73 +{
10.74 + typedef G Graph;
10.75 + typedef typename Graph::Node Node;
10.76 + typedef typename Graph::NodeIt NodeIt;
10.77 + typedef typename Graph::Arc Arc;
10.78 + typedef typename Graph::ArcIt ArcIt;
10.79 + typedef typename Graph::InArcIt InArcIt;
10.80 + typedef typename Graph::OutArcIt OutArcIt;
10.81 +
10.82 +
10.83 + const Graph &g;
10.84 +
10.85 + std::ostream& os;
10.86 +
10.87 + typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
10.88 + CoordsMapType _coords;
10.89 + ConstMap<typename Graph::Node,double > _nodeSizes;
10.90 + ConstMap<typename Graph::Node,int > _nodeShapes;
10.91 +
10.92 + ConstMap<typename Graph::Node,Color > _nodeColors;
10.93 + ConstMap<typename Graph::Arc,Color > _arcColors;
10.94 +
10.95 + ConstMap<typename Graph::Arc,double > _arcWidths;
10.96 +
10.97 + double _arcWidthScale;
10.98 +
10.99 + double _nodeScale;
10.100 + double _xBorder, _yBorder;
10.101 + double _scale;
10.102 + double _nodeBorderQuotient;
10.103 +
10.104 + bool _drawArrows;
10.105 + double _arrowLength, _arrowWidth;
10.106 +
10.107 + bool _showNodes, _showArcs;
10.108 +
10.109 + bool _enableParallel;
10.110 + double _parArcDist;
10.111 +
10.112 + bool _showNodeText;
10.113 + ConstMap<typename Graph::Node,bool > _nodeTexts;
10.114 + double _nodeTextSize;
10.115 +
10.116 + bool _showNodePsText;
10.117 + ConstMap<typename Graph::Node,bool > _nodePsTexts;
10.118 + char *_nodePsTextsPreamble;
10.119 +
10.120 + bool _undirected;
10.121 +
10.122 + bool _pleaseRemoveOsStream;
10.123 +
10.124 + bool _scaleToA4;
10.125 +
10.126 + std::string _title;
10.127 + std::string _copyright;
10.128 +
10.129 + enum NodeTextColorType
10.130 + { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
10.131 + ConstMap<typename Graph::Node,Color > _nodeTextColors;
10.132 +
10.133 + bool _autoNodeScale;
10.134 + bool _autoArcWidthScale;
10.135 +
10.136 + bool _absoluteNodeSizes;
10.137 + bool _absoluteArcWidths;
10.138 +
10.139 + bool _negY;
10.140 +
10.141 + bool _preScale;
10.142 + ///Constructor
10.143 +
10.144 + ///Constructor
10.145 + ///\param _g is a reference to the graph to be printed
10.146 + ///\param _os is a reference to the output stream.
10.147 + ///\param _os is a reference to the output stream.
10.148 + ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
10.149 + ///will be explicitly deallocated by the destructor.
10.150 + ///By default it is <tt>std::cout</tt>
10.151 + DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
10.152 + bool _pros=false) :
10.153 + g(_g), os(_os),
10.154 + _coords(dim2::Point<double>(1,1)), _nodeSizes(.01), _nodeShapes(0),
10.155 + _nodeColors(WHITE), _arcColors(BLACK),
10.156 + _arcWidths(1.0), _arcWidthScale(0.003),
10.157 + _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
10.158 + _nodeBorderQuotient(.1),
10.159 + _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
10.160 + _showNodes(true), _showArcs(true),
10.161 + _enableParallel(false), _parArcDist(1),
10.162 + _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
10.163 + _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
10.164 + _undirected(false),
10.165 + _pleaseRemoveOsStream(_pros), _scaleToA4(false),
10.166 + _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
10.167 + _autoNodeScale(false),
10.168 + _autoArcWidthScale(false),
10.169 + _absoluteNodeSizes(false),
10.170 + _absoluteArcWidths(false),
10.171 + _negY(false),
10.172 + _preScale(true)
10.173 + {}
10.174 +};
10.175 +
10.176 +///Helper class to implement the named parameters of \ref graphToEps()
10.177 +
10.178 +///Helper class to implement the named parameters of \ref graphToEps()
10.179 +///\todo Is 'helper class' a good name for this?
10.180 +///
10.181 +///\todo Follow PostScript's DSC.
10.182 +/// Use own dictionary.
10.183 +///\todo Useful new features.
10.184 +/// - Linestyles: dotted, dashed etc.
10.185 +/// - A second color and percent value for the lines.
10.186 +template<class T> class GraphToEps : public T
10.187 +{
10.188 + // Can't believe it is required by the C++ standard
10.189 + using T::g;
10.190 + using T::os;
10.191 +
10.192 + using T::_coords;
10.193 + using T::_nodeSizes;
10.194 + using T::_nodeShapes;
10.195 + using T::_nodeColors;
10.196 + using T::_arcColors;
10.197 + using T::_arcWidths;
10.198 +
10.199 + using T::_arcWidthScale;
10.200 + using T::_nodeScale;
10.201 + using T::_xBorder;
10.202 + using T::_yBorder;
10.203 + using T::_scale;
10.204 + using T::_nodeBorderQuotient;
10.205 +
10.206 + using T::_drawArrows;
10.207 + using T::_arrowLength;
10.208 + using T::_arrowWidth;
10.209 +
10.210 + using T::_showNodes;
10.211 + using T::_showArcs;
10.212 +
10.213 + using T::_enableParallel;
10.214 + using T::_parArcDist;
10.215 +
10.216 + using T::_showNodeText;
10.217 + using T::_nodeTexts;
10.218 + using T::_nodeTextSize;
10.219 +
10.220 + using T::_showNodePsText;
10.221 + using T::_nodePsTexts;
10.222 + using T::_nodePsTextsPreamble;
10.223 +
10.224 + using T::_undirected;
10.225 +
10.226 + using T::_pleaseRemoveOsStream;
10.227 +
10.228 + using T::_scaleToA4;
10.229 +
10.230 + using T::_title;
10.231 + using T::_copyright;
10.232 +
10.233 + using T::NodeTextColorType;
10.234 + using T::CUST_COL;
10.235 + using T::DIST_COL;
10.236 + using T::DIST_BW;
10.237 + using T::_nodeTextColorType;
10.238 + using T::_nodeTextColors;
10.239 +
10.240 + using T::_autoNodeScale;
10.241 + using T::_autoArcWidthScale;
10.242 +
10.243 + using T::_absoluteNodeSizes;
10.244 + using T::_absoluteArcWidths;
10.245 +
10.246 +
10.247 + using T::_negY;
10.248 + using T::_preScale;
10.249 +
10.250 + // dradnats ++C eht yb deriuqer si ti eveileb t'naC
10.251 +
10.252 + typedef typename T::Graph Graph;
10.253 + typedef typename Graph::Node Node;
10.254 + typedef typename Graph::NodeIt NodeIt;
10.255 + typedef typename Graph::Arc Arc;
10.256 + typedef typename Graph::ArcIt ArcIt;
10.257 + typedef typename Graph::InArcIt InArcIt;
10.258 + typedef typename Graph::OutArcIt OutArcIt;
10.259 +
10.260 + static const int INTERPOL_PREC;
10.261 + static const double A4HEIGHT;
10.262 + static const double A4WIDTH;
10.263 + static const double A4BORDER;
10.264 +
10.265 + bool dontPrint;
10.266 +
10.267 +public:
10.268 + ///Node shapes
10.269 +
10.270 + ///Node shapes
10.271 + ///
10.272 + enum NodeShapes {
10.273 + /// = 0
10.274 + ///\image html nodeshape_0.png
10.275 + ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
10.276 + CIRCLE=0,
10.277 + /// = 1
10.278 + ///\image html nodeshape_1.png
10.279 + ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
10.280 + ///
10.281 + SQUARE=1,
10.282 + /// = 2
10.283 + ///\image html nodeshape_2.png
10.284 + ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
10.285 + ///
10.286 + DIAMOND=2,
10.287 + /// = 3
10.288 + ///\image html nodeshape_3.png
10.289 + ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
10.290 + ///
10.291 + MALE=3,
10.292 + /// = 4
10.293 + ///\image html nodeshape_4.png
10.294 + ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
10.295 + ///
10.296 + FEMALE=4
10.297 + };
10.298 +
10.299 +private:
10.300 + class arcLess {
10.301 + const Graph &g;
10.302 + public:
10.303 + arcLess(const Graph &_g) : g(_g) {}
10.304 + bool operator()(Arc a,Arc b) const
10.305 + {
10.306 + Node ai=std::min(g.source(a),g.target(a));
10.307 + Node aa=std::max(g.source(a),g.target(a));
10.308 + Node bi=std::min(g.source(b),g.target(b));
10.309 + Node ba=std::max(g.source(b),g.target(b));
10.310 + return ai<bi ||
10.311 + (ai==bi && (aa < ba ||
10.312 + (aa==ba && ai==g.source(a) && bi==g.target(b))));
10.313 + }
10.314 + };
10.315 + bool isParallel(Arc e,Arc f) const
10.316 + {
10.317 + return (g.source(e)==g.source(f)&&
10.318 + g.target(e)==g.target(f)) ||
10.319 + (g.source(e)==g.target(f)&&
10.320 + g.target(e)==g.source(f));
10.321 + }
10.322 + template<class TT>
10.323 + static std::string psOut(const dim2::Point<TT> &p)
10.324 + {
10.325 + std::ostringstream os;
10.326 + os << p.x << ' ' << p.y;
10.327 + return os.str();
10.328 + }
10.329 + static std::string psOut(const Color &c)
10.330 + {
10.331 + std::ostringstream os;
10.332 + os << c.red() << ' ' << c.green() << ' ' << c.blue();
10.333 + return os.str();
10.334 + }
10.335 +
10.336 +public:
10.337 + GraphToEps(const T &t) : T(t), dontPrint(false) {};
10.338 +
10.339 + template<class X> struct CoordsTraits : public T {
10.340 + typedef X CoordsMapType;
10.341 + const X &_coords;
10.342 + CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
10.343 + };
10.344 + ///Sets the map of the node coordinates
10.345 +
10.346 + ///Sets the map of the node coordinates.
10.347 + ///\param x must be a node map with dim2::Point<double> or
10.348 + ///\ref dim2::Point "dim2::Point<int>" values.
10.349 + template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
10.350 + dontPrint=true;
10.351 + return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
10.352 + }
10.353 + template<class X> struct NodeSizesTraits : public T {
10.354 + const X &_nodeSizes;
10.355 + NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
10.356 + };
10.357 + ///Sets the map of the node sizes
10.358 +
10.359 + ///Sets the map of the node sizes
10.360 + ///\param x must be a node map with \c double (or convertible) values.
10.361 + template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
10.362 + {
10.363 + dontPrint=true;
10.364 + return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
10.365 + }
10.366 + template<class X> struct NodeShapesTraits : public T {
10.367 + const X &_nodeShapes;
10.368 + NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
10.369 + };
10.370 + ///Sets the map of the node shapes
10.371 +
10.372 + ///Sets the map of the node shapes.
10.373 + ///The availabe shape values
10.374 + ///can be found in \ref NodeShapes "enum NodeShapes".
10.375 + ///\param x must be a node map with \c int (or convertible) values.
10.376 + ///\sa NodeShapes
10.377 + template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
10.378 + {
10.379 + dontPrint=true;
10.380 + return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
10.381 + }
10.382 + template<class X> struct NodeTextsTraits : public T {
10.383 + const X &_nodeTexts;
10.384 + NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
10.385 + };
10.386 + ///Sets the text printed on the nodes
10.387 +
10.388 + ///Sets the text printed on the nodes
10.389 + ///\param x must be a node map with type that can be pushed to a standard
10.390 + ///ostream.
10.391 + template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
10.392 + {
10.393 + dontPrint=true;
10.394 + _showNodeText=true;
10.395 + return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
10.396 + }
10.397 + template<class X> struct NodePsTextsTraits : public T {
10.398 + const X &_nodePsTexts;
10.399 + NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
10.400 + };
10.401 + ///Inserts a PostScript block to the nodes
10.402 +
10.403 + ///With this command it is possible to insert a verbatim PostScript
10.404 + ///block to the nodes.
10.405 + ///The PS current point will be moved to the centre of the node before
10.406 + ///the PostScript block inserted.
10.407 + ///
10.408 + ///Before and after the block a newline character is inserted so you
10.409 + ///don't have to bother with the separators.
10.410 + ///
10.411 + ///\param x must be a node map with type that can be pushed to a standard
10.412 + ///ostream.
10.413 + ///
10.414 + ///\sa nodePsTextsPreamble()
10.415 + ///\todo Offer the choise not to move to the centre but pass the coordinates
10.416 + ///to the Postscript block inserted.
10.417 + template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
10.418 + {
10.419 + dontPrint=true;
10.420 + _showNodePsText=true;
10.421 + return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
10.422 + }
10.423 + template<class X> struct ArcWidthsTraits : public T {
10.424 + const X &_arcWidths;
10.425 + ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
10.426 + };
10.427 + ///Sets the map of the arc widths
10.428 +
10.429 + ///Sets the map of the arc widths
10.430 + ///\param x must be a arc map with \c double (or convertible) values.
10.431 + template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
10.432 + {
10.433 + dontPrint=true;
10.434 + return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
10.435 + }
10.436 +
10.437 + template<class X> struct NodeColorsTraits : public T {
10.438 + const X &_nodeColors;
10.439 + NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
10.440 + };
10.441 + ///Sets the map of the node colors
10.442 +
10.443 + ///Sets the map of the node colors
10.444 + ///\param x must be a node map with \ref Color values.
10.445 + ///
10.446 + ///\sa Palette
10.447 + template<class X> GraphToEps<NodeColorsTraits<X> >
10.448 + nodeColors(const X &x)
10.449 + {
10.450 + dontPrint=true;
10.451 + return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
10.452 + }
10.453 + template<class X> struct NodeTextColorsTraits : public T {
10.454 + const X &_nodeTextColors;
10.455 + NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
10.456 + };
10.457 + ///Sets the map of the node text colors
10.458 +
10.459 + ///Sets the map of the node text colors
10.460 + ///\param x must be a node map with \ref Color values.
10.461 + ///
10.462 + ///\sa Palette
10.463 + template<class X> GraphToEps<NodeTextColorsTraits<X> >
10.464 + nodeTextColors(const X &x)
10.465 + {
10.466 + dontPrint=true;
10.467 + _nodeTextColorType=CUST_COL;
10.468 + return GraphToEps<NodeTextColorsTraits<X> >
10.469 + (NodeTextColorsTraits<X>(*this,x));
10.470 + }
10.471 + template<class X> struct ArcColorsTraits : public T {
10.472 + const X &_arcColors;
10.473 + ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
10.474 + };
10.475 + ///Sets the map of the arc colors
10.476 +
10.477 + ///Sets the map of the arc colors
10.478 + ///\param x must be a arc map with \ref Color values.
10.479 + ///
10.480 + ///\sa Palette
10.481 + template<class X> GraphToEps<ArcColorsTraits<X> >
10.482 + arcColors(const X &x)
10.483 + {
10.484 + dontPrint=true;
10.485 + return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
10.486 + }
10.487 + ///Sets a global scale factor for node sizes
10.488 +
10.489 + ///Sets a global scale factor for node sizes.
10.490 + ///
10.491 + /// If nodeSizes() is not given, this function simply sets the node
10.492 + /// sizes to \c d. If nodeSizes() is given, but
10.493 + /// autoNodeScale() is not, then the node size given by
10.494 + /// nodeSizes() will be multiplied by the value \c d.
10.495 + /// If both nodeSizes() and autoNodeScale() are used, then the
10.496 + /// node sizes will be scaled in such a way that the greatest size will be
10.497 + /// equal to \c d.
10.498 + /// \sa nodeSizes()
10.499 + /// \sa autoNodeScale()
10.500 + GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;}
10.501 + ///Turns on/off the automatic node width scaling.
10.502 +
10.503 + ///Turns on/off the automatic node width scaling.
10.504 + ///
10.505 + ///\sa nodeScale()
10.506 + ///
10.507 + GraphToEps<T> &autoNodeScale(bool b=true) {
10.508 + _autoNodeScale=b;return *this;
10.509 + }
10.510 +
10.511 + ///Turns on/off the absolutematic node width scaling.
10.512 +
10.513 + ///Turns on/off the absolutematic node width scaling.
10.514 + ///
10.515 + ///\sa nodeScale()
10.516 + ///
10.517 + GraphToEps<T> &absoluteNodeSizes(bool b=true) {
10.518 + _absoluteNodeSizes=b;return *this;
10.519 + }
10.520 +
10.521 + ///Negates the Y coordinates.
10.522 +
10.523 + ///Negates the Y coordinates.
10.524 + ///
10.525 + ///\todo More docs.
10.526 + ///
10.527 + GraphToEps<T> &negateY(bool b=true) {
10.528 + _negY=b;return *this;
10.529 + }
10.530 +
10.531 + ///Turn on/off prescaling
10.532 +
10.533 + ///By default graphToEps() rescales the whole image in order to avoid
10.534 + ///very big or very small bounding boxes.
10.535 + ///
10.536 + ///This (p)rescaling can be turned off with this function.
10.537 + ///
10.538 + GraphToEps<T> &preScale(bool b=true) {
10.539 + _preScale=b;return *this;
10.540 + }
10.541 +
10.542 + ///Sets a global scale factor for arc widths
10.543 +
10.544 + /// Sets a global scale factor for arc widths.
10.545 + ///
10.546 + /// If arcWidths() is not given, this function simply sets the arc
10.547 + /// widths to \c d. If arcWidths() is given, but
10.548 + /// autoArcWidthScale() is not, then the arc withs given by
10.549 + /// arcWidths() will be multiplied by the value \c d.
10.550 + /// If both arcWidths() and autoArcWidthScale() are used, then the
10.551 + /// arc withs will be scaled in such a way that the greatest width will be
10.552 + /// equal to \c d.
10.553 + GraphToEps<T> &arcWidthScale(double d) {_arcWidthScale=d;return *this;}
10.554 + ///Turns on/off the automatic arc width scaling.
10.555 +
10.556 + ///Turns on/off the automatic arc width scaling.
10.557 + ///
10.558 + ///\sa arcWidthScale()
10.559 + ///
10.560 + GraphToEps<T> &autoArcWidthScale(bool b=true) {
10.561 + _autoArcWidthScale=b;return *this;
10.562 + }
10.563 + ///Turns on/off the absolutematic arc width scaling.
10.564 +
10.565 + ///Turns on/off the absolutematic arc width scaling.
10.566 + ///
10.567 + ///\sa arcWidthScale()
10.568 + ///
10.569 + GraphToEps<T> &absoluteArcWidths(bool b=true) {
10.570 + _absoluteArcWidths=b;return *this;
10.571 + }
10.572 + ///Sets a global scale factor for the whole picture
10.573 +
10.574 + ///Sets a global scale factor for the whole picture
10.575 + ///
10.576 +
10.577 + GraphToEps<T> &scale(double d) {_scale=d;return *this;}
10.578 + ///Sets the width of the border around the picture
10.579 +
10.580 + ///Sets the width of the border around the picture
10.581 + ///
10.582 + GraphToEps<T> &border(double b) {_xBorder=_yBorder=b;return *this;}
10.583 + ///Sets the width of the border around the picture
10.584 +
10.585 + ///Sets the width of the border around the picture
10.586 + ///
10.587 + GraphToEps<T> &border(double x, double y) {
10.588 + _xBorder=x;_yBorder=y;return *this;
10.589 + }
10.590 + ///Sets whether to draw arrows
10.591 +
10.592 + ///Sets whether to draw arrows
10.593 + ///
10.594 + GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
10.595 + ///Sets the length of the arrowheads
10.596 +
10.597 + ///Sets the length of the arrowheads
10.598 + ///
10.599 + GraphToEps<T> &arrowLength(double d) {_arrowLength*=d;return *this;}
10.600 + ///Sets the width of the arrowheads
10.601 +
10.602 + ///Sets the width of the arrowheads
10.603 + ///
10.604 + GraphToEps<T> &arrowWidth(double d) {_arrowWidth*=d;return *this;}
10.605 +
10.606 + ///Scales the drawing to fit to A4 page
10.607 +
10.608 + ///Scales the drawing to fit to A4 page
10.609 + ///
10.610 + GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
10.611 +
10.612 + ///Enables parallel arcs
10.613 +
10.614 + ///Enables parallel arcs
10.615 + GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
10.616 +
10.617 + ///Sets the distance
10.618 +
10.619 + ///Sets the distance
10.620 + ///
10.621 + GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
10.622 +
10.623 + ///Hides the arcs
10.624 +
10.625 + ///Hides the arcs
10.626 + ///
10.627 + GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
10.628 + ///Hides the nodes
10.629 +
10.630 + ///Hides the nodes
10.631 + ///
10.632 + GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
10.633 +
10.634 + ///Sets the size of the node texts
10.635 +
10.636 + ///Sets the size of the node texts
10.637 + ///
10.638 + GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
10.639 +
10.640 + ///Sets the color of the node texts to be different from the node color
10.641 +
10.642 + ///Sets the color of the node texts to be as different from the node color
10.643 + ///as it is possible
10.644 + ///
10.645 + GraphToEps<T> &distantColorNodeTexts()
10.646 + {_nodeTextColorType=DIST_COL;return *this;}
10.647 + ///Sets the color of the node texts to be black or white and always visible.
10.648 +
10.649 + ///Sets the color of the node texts to be black or white according to
10.650 + ///which is more
10.651 + ///different from the node color
10.652 + ///
10.653 + GraphToEps<T> &distantBWNodeTexts()
10.654 + {_nodeTextColorType=DIST_BW;return *this;}
10.655 +
10.656 + ///Gives a preamble block for node Postscript block.
10.657 +
10.658 + ///Gives a preamble block for node Postscript block.
10.659 + ///
10.660 + ///\sa nodePsTexts()
10.661 + GraphToEps<T> & nodePsTextsPreamble(const char *str) {
10.662 + _nodePsTextsPreamble=str ;return *this;
10.663 + }
10.664 + ///Sets whether the the graph is undirected
10.665 +
10.666 + ///Sets whether the the graph is undirected
10.667 + ///
10.668 + GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
10.669 +
10.670 + ///Sets whether the the graph is directed
10.671 +
10.672 + ///Sets whether the the graph is directed.
10.673 + ///Use it to show the edges as a pair of directed ones.
10.674 + GraphToEps<T> &bidir(bool b=true) {_undirected=!b;return *this;}
10.675 +
10.676 + ///Sets the title.
10.677 +
10.678 + ///Sets the title of the generated image,
10.679 + ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
10.680 + ///the EPS file.
10.681 + GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
10.682 + ///Sets the copyright statement.
10.683 +
10.684 + ///Sets the copyright statement of the generated image,
10.685 + ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
10.686 + ///the EPS file.
10.687 + ///\todo Multiline copyright notice could be supported.
10.688 + GraphToEps<T> ©right(const std::string &t) {_copyright=t;return *this;}
10.689 +
10.690 +protected:
10.691 + bool isInsideNode(dim2::Point<double> p, double r,int t)
10.692 + {
10.693 + switch(t) {
10.694 + case CIRCLE:
10.695 + case MALE:
10.696 + case FEMALE:
10.697 + return p.normSquare()<=r*r;
10.698 + case SQUARE:
10.699 + return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
10.700 + case DIAMOND:
10.701 + return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
10.702 + }
10.703 + return false;
10.704 + }
10.705 +
10.706 +public:
10.707 + ~GraphToEps() { }
10.708 +
10.709 + ///Draws the graph.
10.710 +
10.711 + ///Like other functions using
10.712 + ///\ref named-templ-func-param "named template parameters",
10.713 + ///this function calles the algorithm itself, i.e. in this case
10.714 + ///it draws the graph.
10.715 + void run() {
10.716 + ///\todo better 'epsilon' would be nice here.
10.717 + const double EPSILON=1e-9;
10.718 + if(dontPrint) return;
10.719 +
10.720 + _NegY<typename T::CoordsMapType> mycoords(_coords,_negY);
10.721 +
10.722 + os << "%!PS-Adobe-2.0 EPSF-2.0\n";
10.723 + if(_title.size()>0) os << "%%Title: " << _title << '\n';
10.724 + if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
10.725 +// << "%%Copyright: XXXX\n"
10.726 + os << "%%Creator: LEMON, graphToEps()\n";
10.727 +
10.728 + {
10.729 + char cbuf[50];
10.730 + timeval tv;
10.731 + gettimeofday(&tv, 0);
10.732 + ctime_r(&tv.tv_sec,cbuf);
10.733 + os << "%%CreationDate: " << cbuf;
10.734 + }
10.735 +
10.736 + if (_autoArcWidthScale) {
10.737 + double max_w=0;
10.738 + for(ArcIt e(g);e!=INVALID;++e)
10.739 + max_w=std::max(double(_arcWidths[e]),max_w);
10.740 + ///\todo better 'epsilon' would be nice here.
10.741 + if(max_w>EPSILON) {
10.742 + _arcWidthScale/=max_w;
10.743 + }
10.744 + }
10.745 +
10.746 + if (_autoNodeScale) {
10.747 + double max_s=0;
10.748 + for(NodeIt n(g);n!=INVALID;++n)
10.749 + max_s=std::max(double(_nodeSizes[n]),max_s);
10.750 + ///\todo better 'epsilon' would be nice here.
10.751 + if(max_s>EPSILON) {
10.752 + _nodeScale/=max_s;
10.753 + }
10.754 + }
10.755 +
10.756 + double diag_len = 1;
10.757 + if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
10.758 + dim2::BoundingBox<double> bb;
10.759 + for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
10.760 + if (bb.empty()) {
10.761 + bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
10.762 + }
10.763 + diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
10.764 + if(diag_len<EPSILON) diag_len = 1;
10.765 + if(!_absoluteNodeSizes) _nodeScale*=diag_len;
10.766 + if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
10.767 + }
10.768 +
10.769 + dim2::BoundingBox<double> bb;
10.770 + for(NodeIt n(g);n!=INVALID;++n) {
10.771 + double ns=_nodeSizes[n]*_nodeScale;
10.772 + dim2::Point<double> p(ns,ns);
10.773 + switch(_nodeShapes[n]) {
10.774 + case CIRCLE:
10.775 + case SQUARE:
10.776 + case DIAMOND:
10.777 + bb.add(p+mycoords[n]);
10.778 + bb.add(-p+mycoords[n]);
10.779 + break;
10.780 + case MALE:
10.781 + bb.add(-p+mycoords[n]);
10.782 + bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
10.783 + break;
10.784 + case FEMALE:
10.785 + bb.add(p+mycoords[n]);
10.786 + bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
10.787 + break;
10.788 + }
10.789 + }
10.790 + if (bb.empty()) {
10.791 + bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
10.792 + }
10.793 +
10.794 + if(_scaleToA4)
10.795 + os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
10.796 + else {
10.797 + if(_preScale) {
10.798 + //Rescale so that BoundingBox won't be neither to big nor too small.
10.799 + while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
10.800 + while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
10.801 + }
10.802 +
10.803 + os << "%%BoundingBox: "
10.804 + << int(floor(bb.left() * _scale - _xBorder)) << ' '
10.805 + << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
10.806 + << int(ceil(bb.right() * _scale + _xBorder)) << ' '
10.807 + << int(ceil(bb.top() * _scale + _yBorder)) << '\n';
10.808 + }
10.809 +
10.810 + os << "%%EndComments\n";
10.811 +
10.812 + //x1 y1 x2 y2 x3 y3 cr cg cb w
10.813 + os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
10.814 + << " 4 2 roll 1 index 1 index curveto stroke } bind def\n";
10.815 + os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
10.816 + //x y r
10.817 + os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
10.818 + //x y r
10.819 + os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
10.820 + << " 2 index 1 index sub 2 index 2 index add lineto\n"
10.821 + << " 2 index 1 index sub 2 index 2 index sub lineto\n"
10.822 + << " 2 index 1 index add 2 index 2 index sub lineto\n"
10.823 + << " closepath pop pop pop} bind def\n";
10.824 + //x y r
10.825 + os << "/di { newpath 2 index 1 index add 2 index moveto\n"
10.826 + << " 2 index 2 index 2 index add lineto\n"
10.827 + << " 2 index 1 index sub 2 index lineto\n"
10.828 + << " 2 index 2 index 2 index sub lineto\n"
10.829 + << " closepath pop pop pop} bind def\n";
10.830 + // x y r cr cg cb
10.831 + os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
10.832 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
10.833 + << " } bind def\n";
10.834 + os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
10.835 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
10.836 + << " } bind def\n";
10.837 + os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
10.838 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
10.839 + << " } bind def\n";
10.840 + os << "/nfemale { 0 0 0 setrgbcolor 3 index "
10.841 + << _nodeBorderQuotient/(1+_nodeBorderQuotient)
10.842 + << " 1.5 mul mul setlinewidth\n"
10.843 + << " newpath 5 index 5 index moveto "
10.844 + << "5 index 5 index 5 index 3.01 mul sub\n"
10.845 + << " lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto\n"
10.846 + << " 5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke\n"
10.847 + << " 5 index 5 index 5 index c fill\n"
10.848 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
10.849 + << " } bind def\n";
10.850 + os << "/nmale {\n"
10.851 + << " 0 0 0 setrgbcolor 3 index "
10.852 + << _nodeBorderQuotient/(1+_nodeBorderQuotient)
10.853 + <<" 1.5 mul mul setlinewidth\n"
10.854 + << " newpath 5 index 5 index moveto\n"
10.855 + << " 5 index 4 index 1 mul 1.5 mul add\n"
10.856 + << " 5 index 5 index 3 sqrt 1.5 mul mul add\n"
10.857 + << " 1 index 1 index lineto\n"
10.858 + << " 1 index 1 index 7 index sub moveto\n"
10.859 + << " 1 index 1 index lineto\n"
10.860 + << " exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto\n"
10.861 + << " stroke\n"
10.862 + << " 5 index 5 index 5 index c fill\n"
10.863 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
10.864 + << " } bind def\n";
10.865 +
10.866 +
10.867 + os << "/arrl " << _arrowLength << " def\n";
10.868 + os << "/arrw " << _arrowWidth << " def\n";
10.869 + // l dx_norm dy_norm
10.870 + os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
10.871 + //len w dx_norm dy_norm x1 y1 cr cg cb
10.872 + os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
10.873 + << " /w exch def /len exch def\n"
10.874 + // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
10.875 + << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
10.876 + << " len w sub arrl sub dx dy lrl\n"
10.877 + << " arrw dy dx neg lrl\n"
10.878 + << " dx arrl w add mul dy w 2 div arrw add mul sub\n"
10.879 + << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
10.880 + << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
10.881 + << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
10.882 + << " arrw dy dx neg lrl\n"
10.883 + << " len w sub arrl sub neg dx dy lrl\n"
10.884 + << " closepath fill } bind def\n";
10.885 + os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
10.886 + << " neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
10.887 +
10.888 + os << "\ngsave\n";
10.889 + if(_scaleToA4)
10.890 + if(bb.height()>bb.width()) {
10.891 + double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
10.892 + (A4WIDTH-2*A4BORDER)/bb.width());
10.893 + os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
10.894 + << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
10.895 + << " translate\n"
10.896 + << sc << " dup scale\n"
10.897 + << -bb.left() << ' ' << -bb.bottom() << " translate\n";
10.898 + }
10.899 + else {
10.900 + //\todo Verify centering
10.901 + double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
10.902 + (A4WIDTH-2*A4BORDER)/bb.height());
10.903 + os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
10.904 + << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
10.905 + << " translate\n"
10.906 + << sc << " dup scale\n90 rotate\n"
10.907 + << -bb.left() << ' ' << -bb.top() << " translate\n";
10.908 + }
10.909 + else if(_scale!=1.0) os << _scale << " dup scale\n";
10.910 +
10.911 + if(_showArcs) {
10.912 + os << "%Arcs:\ngsave\n";
10.913 + if(_enableParallel) {
10.914 + std::vector<Arc> el;
10.915 + for(ArcIt e(g);e!=INVALID;++e)
10.916 + if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
10.917 + &&g.source(e)!=g.target(e))
10.918 + el.push_back(e);
10.919 + std::sort(el.begin(),el.end(),arcLess(g));
10.920 +
10.921 + typename std::vector<Arc>::iterator j;
10.922 + for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
10.923 + for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
10.924 +
10.925 + double sw=0;
10.926 + for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
10.927 + sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
10.928 + sw-=_parArcDist;
10.929 + sw/=-2.0;
10.930 + dim2::Point<double>
10.931 + dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
10.932 + double l=std::sqrt(dvec.normSquare());
10.933 + ///\todo better 'epsilon' would be nice here.
10.934 + dim2::Point<double> d(dvec/std::max(l,EPSILON));
10.935 + dim2::Point<double> m;
10.936 +// m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
10.937 +
10.938 +// m=dim2::Point<double>(mycoords[g.source(*i)])+
10.939 +// dvec*(double(_nodeSizes[g.source(*i)])/
10.940 +// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
10.941 +
10.942 + m=dim2::Point<double>(mycoords[g.source(*i)])+
10.943 + d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
10.944 +
10.945 + for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
10.946 + sw+=_arcWidths[*e]*_arcWidthScale/2.0;
10.947 + dim2::Point<double> mm=m+rot90(d)*sw/.75;
10.948 + if(_drawArrows) {
10.949 + int node_shape;
10.950 + dim2::Point<double> s=mycoords[g.source(*e)];
10.951 + dim2::Point<double> t=mycoords[g.target(*e)];
10.952 + double rn=_nodeSizes[g.target(*e)]*_nodeScale;
10.953 + node_shape=_nodeShapes[g.target(*e)];
10.954 + dim2::Bezier3 bez(s,mm,mm,t);
10.955 + double t1=0,t2=1;
10.956 + for(int ii=0;ii<INTERPOL_PREC;++ii)
10.957 + if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
10.958 + else t1=(t1+t2)/2;
10.959 + dim2::Point<double> apoint=bez((t1+t2)/2);
10.960 + rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
10.961 + rn*=rn;
10.962 + t2=(t1+t2)/2;t1=0;
10.963 + for(int ii=0;ii<INTERPOL_PREC;++ii)
10.964 + if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
10.965 + else t2=(t1+t2)/2;
10.966 + dim2::Point<double> linend=bez((t1+t2)/2);
10.967 + bez=bez.before((t1+t2)/2);
10.968 +// rn=_nodeSizes[g.source(*e)]*_nodeScale;
10.969 +// node_shape=_nodeShapes[g.source(*e)];
10.970 +// t1=0;t2=1;
10.971 +// for(int i=0;i<INTERPOL_PREC;++i)
10.972 +// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
10.973 +// else t2=(t1+t2)/2;
10.974 +// bez=bez.after((t1+t2)/2);
10.975 + os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
10.976 + << _arcColors[*e].red() << ' '
10.977 + << _arcColors[*e].green() << ' '
10.978 + << _arcColors[*e].blue() << " setrgbcolor newpath\n"
10.979 + << bez.p1.x << ' ' << bez.p1.y << " moveto\n"
10.980 + << bez.p2.x << ' ' << bez.p2.y << ' '
10.981 + << bez.p3.x << ' ' << bez.p3.y << ' '
10.982 + << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
10.983 + dim2::Point<double> dd(rot90(linend-apoint));
10.984 + dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
10.985 + std::sqrt(dd.normSquare());
10.986 + os << "newpath " << psOut(apoint) << " moveto "
10.987 + << psOut(linend+dd) << " lineto "
10.988 + << psOut(linend-dd) << " lineto closepath fill\n";
10.989 + }
10.990 + else {
10.991 + os << mycoords[g.source(*e)].x << ' '
10.992 + << mycoords[g.source(*e)].y << ' '
10.993 + << mm.x << ' ' << mm.y << ' '
10.994 + << mycoords[g.target(*e)].x << ' '
10.995 + << mycoords[g.target(*e)].y << ' '
10.996 + << _arcColors[*e].red() << ' '
10.997 + << _arcColors[*e].green() << ' '
10.998 + << _arcColors[*e].blue() << ' '
10.999 + << _arcWidths[*e]*_arcWidthScale << " lb\n";
10.1000 + }
10.1001 + sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
10.1002 + }
10.1003 + }
10.1004 + }
10.1005 + else for(ArcIt e(g);e!=INVALID;++e)
10.1006 + if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
10.1007 + &&g.source(e)!=g.target(e))
10.1008 + if(_drawArrows) {
10.1009 + dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
10.1010 + double rn=_nodeSizes[g.target(e)]*_nodeScale;
10.1011 + int node_shape=_nodeShapes[g.target(e)];
10.1012 + double t1=0,t2=1;
10.1013 + for(int i=0;i<INTERPOL_PREC;++i)
10.1014 + if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
10.1015 + else t2=(t1+t2)/2;
10.1016 + double l=std::sqrt(d.normSquare());
10.1017 + d/=l;
10.1018 +
10.1019 + os << l*(1-(t1+t2)/2) << ' '
10.1020 + << _arcWidths[e]*_arcWidthScale << ' '
10.1021 + << d.x << ' ' << d.y << ' '
10.1022 + << mycoords[g.source(e)].x << ' '
10.1023 + << mycoords[g.source(e)].y << ' '
10.1024 + << _arcColors[e].red() << ' '
10.1025 + << _arcColors[e].green() << ' '
10.1026 + << _arcColors[e].blue() << " arr\n";
10.1027 + }
10.1028 + else os << mycoords[g.source(e)].x << ' '
10.1029 + << mycoords[g.source(e)].y << ' '
10.1030 + << mycoords[g.target(e)].x << ' '
10.1031 + << mycoords[g.target(e)].y << ' '
10.1032 + << _arcColors[e].red() << ' '
10.1033 + << _arcColors[e].green() << ' '
10.1034 + << _arcColors[e].blue() << ' '
10.1035 + << _arcWidths[e]*_arcWidthScale << " l\n";
10.1036 + os << "grestore\n";
10.1037 + }
10.1038 + if(_showNodes) {
10.1039 + os << "%Nodes:\ngsave\n";
10.1040 + for(NodeIt n(g);n!=INVALID;++n) {
10.1041 + os << mycoords[n].x << ' ' << mycoords[n].y << ' '
10.1042 + << _nodeSizes[n]*_nodeScale << ' '
10.1043 + << _nodeColors[n].red() << ' '
10.1044 + << _nodeColors[n].green() << ' '
10.1045 + << _nodeColors[n].blue() << ' ';
10.1046 + switch(_nodeShapes[n]) {
10.1047 + case CIRCLE:
10.1048 + os<< "nc";break;
10.1049 + case SQUARE:
10.1050 + os<< "nsq";break;
10.1051 + case DIAMOND:
10.1052 + os<< "ndi";break;
10.1053 + case MALE:
10.1054 + os<< "nmale";break;
10.1055 + case FEMALE:
10.1056 + os<< "nfemale";break;
10.1057 + }
10.1058 + os<<'\n';
10.1059 + }
10.1060 + os << "grestore\n";
10.1061 + }
10.1062 + if(_showNodeText) {
10.1063 + os << "%Node texts:\ngsave\n";
10.1064 + os << "/fosi " << _nodeTextSize << " def\n";
10.1065 + os << "(Helvetica) findfont fosi scalefont setfont\n";
10.1066 + for(NodeIt n(g);n!=INVALID;++n) {
10.1067 + switch(_nodeTextColorType) {
10.1068 + case DIST_COL:
10.1069 + os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
10.1070 + break;
10.1071 + case DIST_BW:
10.1072 + os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
10.1073 + break;
10.1074 + case CUST_COL:
10.1075 + os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
10.1076 + break;
10.1077 + default:
10.1078 + os << "0 0 0 setrgbcolor\n";
10.1079 + }
10.1080 + os << mycoords[n].x << ' ' << mycoords[n].y
10.1081 + << " (" << _nodeTexts[n] << ") cshow\n";
10.1082 + }
10.1083 + os << "grestore\n";
10.1084 + }
10.1085 + if(_showNodePsText) {
10.1086 + os << "%Node PS blocks:\ngsave\n";
10.1087 + for(NodeIt n(g);n!=INVALID;++n)
10.1088 + os << mycoords[n].x << ' ' << mycoords[n].y
10.1089 + << " moveto\n" << _nodePsTexts[n] << "\n";
10.1090 + os << "grestore\n";
10.1091 + }
10.1092 +
10.1093 + os << "grestore\nshowpage\n";
10.1094 +
10.1095 + //CleanUp:
10.1096 + if(_pleaseRemoveOsStream) {delete &os;}
10.1097 + }
10.1098 +};
10.1099 +
10.1100 +template<class T>
10.1101 +const int GraphToEps<T>::INTERPOL_PREC = 20;
10.1102 +template<class T>
10.1103 +const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
10.1104 +template<class T>
10.1105 +const double GraphToEps<T>::A4WIDTH = 595.275590551181;
10.1106 +template<class T>
10.1107 +const double GraphToEps<T>::A4BORDER = 15;
10.1108 +
10.1109 +
10.1110 +///Generates an EPS file from a graph
10.1111 +
10.1112 +///\ingroup eps_io
10.1113 +///Generates an EPS file from a graph.
10.1114 +///\param g is a reference to the graph to be printed
10.1115 +///\param os is a reference to the output stream.
10.1116 +///By default it is <tt>std::cout</tt>
10.1117 +///
10.1118 +///This function also has a lot of
10.1119 +///\ref named-templ-func-param "named parameters",
10.1120 +///they are declared as the members of class \ref GraphToEps. The following
10.1121 +///example shows how to use these parameters.
10.1122 +///\code
10.1123 +/// graphToEps(g,os).scale(10).coords(coords)
10.1124 +/// .nodeScale(2).nodeSizes(sizes)
10.1125 +/// .arcWidthScale(.4).run();
10.1126 +///\endcode
10.1127 +///\warning Don't forget to put the \ref GraphToEps::run() "run()"
10.1128 +///to the end of the parameter list.
10.1129 +///\sa GraphToEps
10.1130 +///\sa graphToEps(G &g, const char *file_name)
10.1131 +template<class G>
10.1132 +GraphToEps<DefaultGraphToEpsTraits<G> >
10.1133 +graphToEps(G &g, std::ostream& os=std::cout)
10.1134 +{
10.1135 + return
10.1136 + GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
10.1137 +}
10.1138 +
10.1139 +///Generates an EPS file from a graph
10.1140 +
10.1141 +///\ingroup eps_io
10.1142 +///This function does the same as
10.1143 +///\ref graphToEps(G &g,std::ostream& os)
10.1144 +///but it writes its output into the file \c file_name
10.1145 +///instead of a stream.
10.1146 +///\sa graphToEps(G &g, std::ostream& os)
10.1147 +template<class G>
10.1148 +GraphToEps<DefaultGraphToEpsTraits<G> >
10.1149 +graphToEps(G &g,const char *file_name)
10.1150 +{
10.1151 + return GraphToEps<DefaultGraphToEpsTraits<G> >
10.1152 + (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
10.1153 +}
10.1154 +
10.1155 +///Generates an EPS file from a graph
10.1156 +
10.1157 +///\ingroup eps_io
10.1158 +///This function does the same as
10.1159 +///\ref graphToEps(G &g,std::ostream& os)
10.1160 +///but it writes its output into the file \c file_name
10.1161 +///instead of a stream.
10.1162 +///\sa graphToEps(G &g, std::ostream& os)
10.1163 +template<class G>
10.1164 +GraphToEps<DefaultGraphToEpsTraits<G> >
10.1165 +graphToEps(G &g,const std::string& file_name)
10.1166 +{
10.1167 + return GraphToEps<DefaultGraphToEpsTraits<G> >
10.1168 + (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true));
10.1169 +}
10.1170 +
10.1171 +} //END OF NAMESPACE LEMON
10.1172 +
10.1173 +#endif // LEMON_GRAPH_TO_EPS_H