Merge with graph_to_eps.h & Co.
1.1 --- a/.hgignore Thu Apr 17 15:18:45 2008 +0100
1.2 +++ b/.hgignore Thu Apr 17 15:54:30 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 Thu Apr 17 15:18:45 2008 +0100
2.2 +++ b/demo/Makefile.am Thu Apr 17 15:54:30 2008 +0100
2.3 @@ -4,11 +4,13 @@
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 demo/lgf_demo
2.11
2.12 endif WANT_DEMO
2.13
2.14 demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc
2.15 +demo_graph_to_eps_demo_SOURCES = demo/graph_to_eps_demo.cc
2.16 demo_lgf_demo_SOURCES = demo/lgf_demo.cc
2.17
3.1 --- a/demo/arg_parser_demo.cc Thu Apr 17 15:18:45 2008 +0100
3.2 +++ b/demo/arg_parser_demo.cc Thu Apr 17 15:54:30 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 17 15:54:30 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(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 Thu Apr 17 15:18:45 2008 +0100
5.2 +++ b/lemon/Makefile.am Thu Apr 17 15:54:30 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,11 +21,13 @@
5.12 lemon/assert.h \
5.13 lemon/bfs.h \
5.14 lemon/bin_heap.h \
5.15 + lemon/color.h \
5.16 lemon/counter.h \
5.17 lemon/dfs.h \
5.18 lemon/dijkstra.h \
5.19 lemon/dim2.h \
5.20 lemon/error.h \
5.21 + lemon/graph_to_eps.h \
5.22 lemon/graph_utils.h \
5.23 lemon/kruskal.h \
5.24 lemon/lgf_reader.h \
5.25 @@ -42,6 +45,7 @@
5.26 lemon/bits/alteration_notifier.h \
5.27 lemon/bits/array_map.h \
5.28 lemon/bits/base_extender.h \
5.29 + lemon/bits/bezier.h \
5.30 lemon/bits/default_map.h \
5.31 lemon/bits/graph_extender.h \
5.32 lemon/bits/invalid.h \
6.1 --- a/lemon/arg_parser.cc Thu Apr 17 15:18:45 2008 +0100
6.2 +++ b/lemon/arg_parser.cc Thu Apr 17 15:54:30 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 17 15:54:30 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 17 15:54:30 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 17 15:54:30 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 have_white indicates whether white is amongst the
9.118 + ///provided initial colors (\c true) or not (\c false). If it is true,
9.119 + ///white will be assigned to \c 0.
9.120 + ///\param num the number of the allocated colors. If it is \c -1,
9.121 + ///the default color configuration is set up (26 color plus optionaly the
9.122 + ///white). If \c num is less then 26/27 then the default color
9.123 + ///list is cut. Otherwise the color list is filled repeatedly with
9.124 + ///the default color list. (The colors can be changed later on.)
9.125 + Palette(bool have_white=false,int num=-1)
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 + ///Add a new color to the end of the color list.
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 visibly 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 17 15:54:30 2008 +0100
10.3 @@ -0,0 +1,1244 @@
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<iostream>
10.26 +#include<fstream>
10.27 +#include<sstream>
10.28 +#include<algorithm>
10.29 +#include<vector>
10.30 +
10.31 +#ifndef WIN32
10.32 +#include<sys/time.h>
10.33 +#include<ctime>
10.34 +#else
10.35 +#include<windows.h>
10.36 +#endif
10.37 +
10.38 +#include<lemon/math.h>
10.39 +#include<lemon/bits/invalid.h>
10.40 +#include<lemon/dim2.h>
10.41 +#include<lemon/maps.h>
10.42 +#include<lemon/color.h>
10.43 +#include<lemon/bits/bezier.h>
10.44 +
10.45 +
10.46 +///\ingroup eps_io
10.47 +///\file
10.48 +///\brief A well configurable tool for visualizing graphs
10.49 +
10.50 +namespace lemon {
10.51 +
10.52 + namespace _graph_to_eps_bits {
10.53 + template<class MT>
10.54 + class _NegY {
10.55 + public:
10.56 + typedef typename MT::Key Key;
10.57 + typedef typename MT::Value Value;
10.58 + const MT ↦
10.59 + int yscale;
10.60 + _NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
10.61 + Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
10.62 + };
10.63 + }
10.64 +
10.65 +///Default traits class of \ref GraphToEps
10.66 +
10.67 +///Default traits class of \ref GraphToEps
10.68 +///
10.69 +///\c G is the type of the underlying graph.
10.70 +template<class G>
10.71 +struct DefaultGraphToEpsTraits
10.72 +{
10.73 + typedef G Graph;
10.74 + typedef typename Graph::Node Node;
10.75 + typedef typename Graph::NodeIt NodeIt;
10.76 + typedef typename Graph::Arc Arc;
10.77 + typedef typename Graph::ArcIt ArcIt;
10.78 + typedef typename Graph::InArcIt InArcIt;
10.79 + typedef typename Graph::OutArcIt OutArcIt;
10.80 +
10.81 +
10.82 + const Graph &g;
10.83 +
10.84 + std::ostream& os;
10.85 +
10.86 + typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType;
10.87 + CoordsMapType _coords;
10.88 + ConstMap<typename Graph::Node,double > _nodeSizes;
10.89 + ConstMap<typename Graph::Node,int > _nodeShapes;
10.90 +
10.91 + ConstMap<typename Graph::Node,Color > _nodeColors;
10.92 + ConstMap<typename Graph::Arc,Color > _arcColors;
10.93 +
10.94 + ConstMap<typename Graph::Arc,double > _arcWidths;
10.95 +
10.96 + double _arcWidthScale;
10.97 +
10.98 + double _nodeScale;
10.99 + double _xBorder, _yBorder;
10.100 + double _scale;
10.101 + double _nodeBorderQuotient;
10.102 +
10.103 + bool _drawArrows;
10.104 + double _arrowLength, _arrowWidth;
10.105 +
10.106 + bool _showNodes, _showArcs;
10.107 +
10.108 + bool _enableParallel;
10.109 + double _parArcDist;
10.110 +
10.111 + bool _showNodeText;
10.112 + ConstMap<typename Graph::Node,bool > _nodeTexts;
10.113 + double _nodeTextSize;
10.114 +
10.115 + bool _showNodePsText;
10.116 + ConstMap<typename Graph::Node,bool > _nodePsTexts;
10.117 + char *_nodePsTextsPreamble;
10.118 +
10.119 + bool _undirected;
10.120 +
10.121 + bool _pleaseRemoveOsStream;
10.122 +
10.123 + bool _scaleToA4;
10.124 +
10.125 + std::string _title;
10.126 + std::string _copyright;
10.127 +
10.128 + enum NodeTextColorType
10.129 + { DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
10.130 + ConstMap<typename Graph::Node,Color > _nodeTextColors;
10.131 +
10.132 + bool _autoNodeScale;
10.133 + bool _autoArcWidthScale;
10.134 +
10.135 + bool _absoluteNodeSizes;
10.136 + bool _absoluteArcWidths;
10.137 +
10.138 + bool _negY;
10.139 +
10.140 + bool _preScale;
10.141 + ///Constructor
10.142 +
10.143 + ///Constructor
10.144 + ///\param _g is a reference to the graph to be printed
10.145 + ///\param _os is a reference to the output stream.
10.146 + ///\param _os is a reference to the output stream.
10.147 + ///\param _pros If it is \c true, then the \c ostream referenced by \c _os
10.148 + ///will be explicitly deallocated by the destructor.
10.149 + ///By default it is <tt>std::cout</tt>
10.150 + DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
10.151 + bool _pros=false) :
10.152 + g(_g), os(_os),
10.153 + _coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0),
10.154 + _nodeColors(WHITE), _arcColors(BLACK),
10.155 + _arcWidths(1.0), _arcWidthScale(0.003),
10.156 + _nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0),
10.157 + _nodeBorderQuotient(.1),
10.158 + _drawArrows(false), _arrowLength(1), _arrowWidth(0.3),
10.159 + _showNodes(true), _showArcs(true),
10.160 + _enableParallel(false), _parArcDist(1),
10.161 + _showNodeText(false), _nodeTexts(false), _nodeTextSize(1),
10.162 + _showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0),
10.163 + _undirected(lemon::UndirectedTagIndicator<G>::value),
10.164 + _pleaseRemoveOsStream(_pros), _scaleToA4(false),
10.165 + _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK),
10.166 + _autoNodeScale(false),
10.167 + _autoArcWidthScale(false),
10.168 + _absoluteNodeSizes(false),
10.169 + _absoluteArcWidths(false),
10.170 + _negY(false),
10.171 + _preScale(true)
10.172 + {}
10.173 +};
10.174 +
10.175 +///Auxiliary class to implement the named parameters of \ref graphToEps()
10.176 +
10.177 +///Auxiliary class to implement the named parameters of \ref graphToEps()
10.178 +template<class T> class GraphToEps : public T
10.179 +{
10.180 + // Can't believe it is required by the C++ standard
10.181 + using T::g;
10.182 + using T::os;
10.183 +
10.184 + using T::_coords;
10.185 + using T::_nodeSizes;
10.186 + using T::_nodeShapes;
10.187 + using T::_nodeColors;
10.188 + using T::_arcColors;
10.189 + using T::_arcWidths;
10.190 +
10.191 + using T::_arcWidthScale;
10.192 + using T::_nodeScale;
10.193 + using T::_xBorder;
10.194 + using T::_yBorder;
10.195 + using T::_scale;
10.196 + using T::_nodeBorderQuotient;
10.197 +
10.198 + using T::_drawArrows;
10.199 + using T::_arrowLength;
10.200 + using T::_arrowWidth;
10.201 +
10.202 + using T::_showNodes;
10.203 + using T::_showArcs;
10.204 +
10.205 + using T::_enableParallel;
10.206 + using T::_parArcDist;
10.207 +
10.208 + using T::_showNodeText;
10.209 + using T::_nodeTexts;
10.210 + using T::_nodeTextSize;
10.211 +
10.212 + using T::_showNodePsText;
10.213 + using T::_nodePsTexts;
10.214 + using T::_nodePsTextsPreamble;
10.215 +
10.216 + using T::_undirected;
10.217 +
10.218 + using T::_pleaseRemoveOsStream;
10.219 +
10.220 + using T::_scaleToA4;
10.221 +
10.222 + using T::_title;
10.223 + using T::_copyright;
10.224 +
10.225 + using T::NodeTextColorType;
10.226 + using T::CUST_COL;
10.227 + using T::DIST_COL;
10.228 + using T::DIST_BW;
10.229 + using T::_nodeTextColorType;
10.230 + using T::_nodeTextColors;
10.231 +
10.232 + using T::_autoNodeScale;
10.233 + using T::_autoArcWidthScale;
10.234 +
10.235 + using T::_absoluteNodeSizes;
10.236 + using T::_absoluteArcWidths;
10.237 +
10.238 +
10.239 + using T::_negY;
10.240 + using T::_preScale;
10.241 +
10.242 + // dradnats ++C eht yb deriuqer si ti eveileb t'naC
10.243 +
10.244 + typedef typename T::Graph Graph;
10.245 + typedef typename Graph::Node Node;
10.246 + typedef typename Graph::NodeIt NodeIt;
10.247 + typedef typename Graph::Arc Arc;
10.248 + typedef typename Graph::ArcIt ArcIt;
10.249 + typedef typename Graph::InArcIt InArcIt;
10.250 + typedef typename Graph::OutArcIt OutArcIt;
10.251 +
10.252 + static const int INTERPOL_PREC;
10.253 + static const double A4HEIGHT;
10.254 + static const double A4WIDTH;
10.255 + static const double A4BORDER;
10.256 +
10.257 + bool dontPrint;
10.258 +
10.259 +public:
10.260 + ///Node shapes
10.261 +
10.262 + ///Node shapes
10.263 + ///
10.264 + enum NodeShapes {
10.265 + /// = 0
10.266 + ///\image html nodeshape_0.png
10.267 + ///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm
10.268 + CIRCLE=0,
10.269 + /// = 1
10.270 + ///\image html nodeshape_1.png
10.271 + ///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm
10.272 + ///
10.273 + SQUARE=1,
10.274 + /// = 2
10.275 + ///\image html nodeshape_2.png
10.276 + ///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm
10.277 + ///
10.278 + DIAMOND=2,
10.279 + /// = 3
10.280 + ///\image html nodeshape_3.png
10.281 + ///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm
10.282 + ///
10.283 + MALE=3,
10.284 + /// = 4
10.285 + ///\image html nodeshape_4.png
10.286 + ///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm
10.287 + ///
10.288 + FEMALE=4
10.289 + };
10.290 +
10.291 +private:
10.292 + class arcLess {
10.293 + const Graph &g;
10.294 + public:
10.295 + arcLess(const Graph &_g) : g(_g) {}
10.296 + bool operator()(Arc a,Arc b) const
10.297 + {
10.298 + Node ai=std::min(g.source(a),g.target(a));
10.299 + Node aa=std::max(g.source(a),g.target(a));
10.300 + Node bi=std::min(g.source(b),g.target(b));
10.301 + Node ba=std::max(g.source(b),g.target(b));
10.302 + return ai<bi ||
10.303 + (ai==bi && (aa < ba ||
10.304 + (aa==ba && ai==g.source(a) && bi==g.target(b))));
10.305 + }
10.306 + };
10.307 + bool isParallel(Arc e,Arc f) const
10.308 + {
10.309 + return (g.source(e)==g.source(f)&&
10.310 + g.target(e)==g.target(f)) ||
10.311 + (g.source(e)==g.target(f)&&
10.312 + g.target(e)==g.source(f));
10.313 + }
10.314 + template<class TT>
10.315 + static std::string psOut(const dim2::Point<TT> &p)
10.316 + {
10.317 + std::ostringstream os;
10.318 + os << p.x << ' ' << p.y;
10.319 + return os.str();
10.320 + }
10.321 + static std::string psOut(const Color &c)
10.322 + {
10.323 + std::ostringstream os;
10.324 + os << c.red() << ' ' << c.green() << ' ' << c.blue();
10.325 + return os.str();
10.326 + }
10.327 +
10.328 +public:
10.329 + GraphToEps(const T &t) : T(t), dontPrint(false) {};
10.330 +
10.331 + template<class X> struct CoordsTraits : public T {
10.332 + typedef X CoordsMapType;
10.333 + const X &_coords;
10.334 + CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
10.335 + };
10.336 + ///Sets the map of the node coordinates
10.337 +
10.338 + ///Sets the map of the node coordinates.
10.339 + ///\param x must be a node map with dim2::Point<double> or
10.340 + ///\ref dim2::Point "dim2::Point<int>" values.
10.341 + template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
10.342 + dontPrint=true;
10.343 + return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x));
10.344 + }
10.345 + template<class X> struct NodeSizesTraits : public T {
10.346 + const X &_nodeSizes;
10.347 + NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
10.348 + };
10.349 + ///Sets the map of the node sizes
10.350 +
10.351 + ///Sets the map of the node sizes
10.352 + ///\param x must be a node map with \c double (or convertible) values.
10.353 + template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x)
10.354 + {
10.355 + dontPrint=true;
10.356 + return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
10.357 + }
10.358 + template<class X> struct NodeShapesTraits : public T {
10.359 + const X &_nodeShapes;
10.360 + NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
10.361 + };
10.362 + ///Sets the map of the node shapes
10.363 +
10.364 + ///Sets the map of the node shapes.
10.365 + ///The available shape values
10.366 + ///can be found in \ref NodeShapes "enum NodeShapes".
10.367 + ///\param x must be a node map with \c int (or convertible) values.
10.368 + ///\sa NodeShapes
10.369 + template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
10.370 + {
10.371 + dontPrint=true;
10.372 + return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
10.373 + }
10.374 + template<class X> struct NodeTextsTraits : public T {
10.375 + const X &_nodeTexts;
10.376 + NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
10.377 + };
10.378 + ///Sets the text printed on the nodes
10.379 +
10.380 + ///Sets the text printed on the nodes
10.381 + ///\param x must be a node map with type that can be pushed to a standard
10.382 + ///ostream.
10.383 + template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x)
10.384 + {
10.385 + dontPrint=true;
10.386 + _showNodeText=true;
10.387 + return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x));
10.388 + }
10.389 + template<class X> struct NodePsTextsTraits : public T {
10.390 + const X &_nodePsTexts;
10.391 + NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
10.392 + };
10.393 + ///Inserts a PostScript block to the nodes
10.394 +
10.395 + ///With this command it is possible to insert a verbatim PostScript
10.396 + ///block to the nodes.
10.397 + ///The PS current point will be moved to the centre of the node before
10.398 + ///the PostScript block inserted.
10.399 + ///
10.400 + ///Before and after the block a newline character is inserted so you
10.401 + ///don't have to bother with the separators.
10.402 + ///
10.403 + ///\param x must be a node map with type that can be pushed to a standard
10.404 + ///ostream.
10.405 + ///
10.406 + ///\sa nodePsTextsPreamble()
10.407 + template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x)
10.408 + {
10.409 + dontPrint=true;
10.410 + _showNodePsText=true;
10.411 + return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x));
10.412 + }
10.413 + template<class X> struct ArcWidthsTraits : public T {
10.414 + const X &_arcWidths;
10.415 + ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
10.416 + };
10.417 + ///Sets the map of the arc widths
10.418 +
10.419 + ///Sets the map of the arc widths
10.420 + ///\param x must be a arc map with \c double (or convertible) values.
10.421 + template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x)
10.422 + {
10.423 + dontPrint=true;
10.424 + return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x));
10.425 + }
10.426 +
10.427 + template<class X> struct NodeColorsTraits : public T {
10.428 + const X &_nodeColors;
10.429 + NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
10.430 + };
10.431 + ///Sets the map of the node colors
10.432 +
10.433 + ///Sets the map of the node colors
10.434 + ///\param x must be a node map with \ref Color values.
10.435 + ///
10.436 + ///\sa Palette
10.437 + template<class X> GraphToEps<NodeColorsTraits<X> >
10.438 + nodeColors(const X &x)
10.439 + {
10.440 + dontPrint=true;
10.441 + return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x));
10.442 + }
10.443 + template<class X> struct NodeTextColorsTraits : public T {
10.444 + const X &_nodeTextColors;
10.445 + NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
10.446 + };
10.447 + ///Sets the map of the node text colors
10.448 +
10.449 + ///Sets the map of the node text colors
10.450 + ///\param x must be a node map with \ref Color values.
10.451 + ///
10.452 + ///\sa Palette
10.453 + template<class X> GraphToEps<NodeTextColorsTraits<X> >
10.454 + nodeTextColors(const X &x)
10.455 + {
10.456 + dontPrint=true;
10.457 + _nodeTextColorType=CUST_COL;
10.458 + return GraphToEps<NodeTextColorsTraits<X> >
10.459 + (NodeTextColorsTraits<X>(*this,x));
10.460 + }
10.461 + template<class X> struct ArcColorsTraits : public T {
10.462 + const X &_arcColors;
10.463 + ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
10.464 + };
10.465 + ///Sets the map of the arc colors
10.466 +
10.467 + ///Sets the map of the arc colors
10.468 + ///\param x must be a arc map with \ref Color values.
10.469 + ///
10.470 + ///\sa Palette
10.471 + template<class X> GraphToEps<ArcColorsTraits<X> >
10.472 + arcColors(const X &x)
10.473 + {
10.474 + dontPrint=true;
10.475 + return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x));
10.476 + }
10.477 + ///Sets a global scale factor for node sizes
10.478 +
10.479 + ///Sets a global scale factor for node sizes.
10.480 + ///
10.481 + /// If nodeSizes() is not given, this function simply sets the node
10.482 + /// sizes to \c d. If nodeSizes() is given, but
10.483 + /// autoNodeScale() is not, then the node size given by
10.484 + /// nodeSizes() will be multiplied by the value \c d.
10.485 + /// If both nodeSizes() and autoNodeScale() are used, then the
10.486 + /// node sizes will be scaled in such a way that the greatest size will be
10.487 + /// equal to \c d.
10.488 + /// \sa nodeSizes()
10.489 + /// \sa autoNodeScale()
10.490 + GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
10.491 + ///Turns on/off the automatic node width scaling.
10.492 +
10.493 + ///Turns on/off the automatic node width scaling.
10.494 + ///
10.495 + ///\sa nodeScale()
10.496 + ///
10.497 + GraphToEps<T> &autoNodeScale(bool b=true) {
10.498 + _autoNodeScale=b;return *this;
10.499 + }
10.500 +
10.501 + ///Turns on/off the absolutematic node width scaling.
10.502 +
10.503 + ///Turns on/off the absolutematic node width scaling.
10.504 + ///
10.505 + ///\sa nodeScale()
10.506 + ///
10.507 + GraphToEps<T> &absoluteNodeSizes(bool b=true) {
10.508 + _absoluteNodeSizes=b;return *this;
10.509 + }
10.510 +
10.511 + ///Negates the Y coordinates.
10.512 +
10.513 + ///Negates the Y coordinates.
10.514 + ///
10.515 + GraphToEps<T> &negateY(bool b=true) {
10.516 + _negY=b;return *this;
10.517 + }
10.518 +
10.519 + ///Turn on/off pre-scaling
10.520 +
10.521 + ///By default graphToEps() rescales the whole image in order to avoid
10.522 + ///very big or very small bounding boxes.
10.523 + ///
10.524 + ///This (p)rescaling can be turned off with this function.
10.525 + ///
10.526 + GraphToEps<T> &preScale(bool b=true) {
10.527 + _preScale=b;return *this;
10.528 + }
10.529 +
10.530 + ///Sets a global scale factor for arc widths
10.531 +
10.532 + /// Sets a global scale factor for arc widths.
10.533 + ///
10.534 + /// If arcWidths() is not given, this function simply sets the arc
10.535 + /// widths to \c d. If arcWidths() is given, but
10.536 + /// autoArcWidthScale() is not, then the arc withs given by
10.537 + /// arcWidths() will be multiplied by the value \c d.
10.538 + /// If both arcWidths() and autoArcWidthScale() are used, then the
10.539 + /// arc withs will be scaled in such a way that the greatest width will be
10.540 + /// equal to \c d.
10.541 + GraphToEps<T> &arcWidthScale(double d=.003) {_arcWidthScale=d;return *this;}
10.542 + ///Turns on/off the automatic arc width scaling.
10.543 +
10.544 + ///Turns on/off the automatic arc width scaling.
10.545 + ///
10.546 + ///\sa arcWidthScale()
10.547 + ///
10.548 + GraphToEps<T> &autoArcWidthScale(bool b=true) {
10.549 + _autoArcWidthScale=b;return *this;
10.550 + }
10.551 + ///Turns on/off the absolutematic arc width scaling.
10.552 +
10.553 + ///Turns on/off the absolutematic arc width scaling.
10.554 + ///
10.555 + ///\sa arcWidthScale()
10.556 + ///
10.557 + GraphToEps<T> &absoluteArcWidths(bool b=true) {
10.558 + _absoluteArcWidths=b;return *this;
10.559 + }
10.560 + ///Sets a global scale factor for the whole picture
10.561 +
10.562 + ///Sets a global scale factor for the whole picture
10.563 + ///
10.564 +
10.565 + GraphToEps<T> &scale(double d) {_scale=d;return *this;}
10.566 + ///Sets the width of the border around the picture
10.567 +
10.568 + ///Sets the width of the border around the picture
10.569 + ///
10.570 + GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
10.571 + ///Sets the width of the border around the picture
10.572 +
10.573 + ///Sets the width of the border around the picture
10.574 + ///
10.575 + GraphToEps<T> &border(double x, double y) {
10.576 + _xBorder=x;_yBorder=y;return *this;
10.577 + }
10.578 + ///Sets whether to draw arrows
10.579 +
10.580 + ///Sets whether to draw arrows
10.581 + ///
10.582 + GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
10.583 + ///Sets the length of the arrowheads
10.584 +
10.585 + ///Sets the length of the arrowheads
10.586 + ///
10.587 + GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
10.588 + ///Sets the width of the arrowheads
10.589 +
10.590 + ///Sets the width of the arrowheads
10.591 + ///
10.592 + GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
10.593 +
10.594 + ///Scales the drawing to fit to A4 page
10.595 +
10.596 + ///Scales the drawing to fit to A4 page
10.597 + ///
10.598 + GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
10.599 +
10.600 + ///Enables parallel arcs
10.601 +
10.602 + ///Enables parallel arcs
10.603 + GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
10.604 +
10.605 + ///Sets the distance
10.606 +
10.607 + ///Sets the distance
10.608 + ///
10.609 + GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
10.610 +
10.611 + ///Hides the arcs
10.612 +
10.613 + ///Hides the arcs
10.614 + ///
10.615 + GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
10.616 + ///Hides the nodes
10.617 +
10.618 + ///Hides the nodes
10.619 + ///
10.620 + GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
10.621 +
10.622 + ///Sets the size of the node texts
10.623 +
10.624 + ///Sets the size of the node texts
10.625 + ///
10.626 + GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
10.627 +
10.628 + ///Sets the color of the node texts to be different from the node color
10.629 +
10.630 + ///Sets the color of the node texts to be as different from the node color
10.631 + ///as it is possible
10.632 + ///
10.633 + GraphToEps<T> &distantColorNodeTexts()
10.634 + {_nodeTextColorType=DIST_COL;return *this;}
10.635 + ///Sets the color of the node texts to be black or white and always visible.
10.636 +
10.637 + ///Sets the color of the node texts to be black or white according to
10.638 + ///which is more
10.639 + ///different from the node color
10.640 + ///
10.641 + GraphToEps<T> &distantBWNodeTexts()
10.642 + {_nodeTextColorType=DIST_BW;return *this;}
10.643 +
10.644 + ///Gives a preamble block for node Postscript block.
10.645 +
10.646 + ///Gives a preamble block for node Postscript block.
10.647 + ///
10.648 + ///\sa nodePsTexts()
10.649 + GraphToEps<T> & nodePsTextsPreamble(const char *str) {
10.650 + _nodePsTextsPreamble=str ;return *this;
10.651 + }
10.652 + ///Sets whether the the graph is undirected
10.653 +
10.654 + ///Sets whether the the graph is undirected.
10.655 + ///
10.656 + ///This setting is the default for undirected graphs.
10.657 + ///
10.658 + ///\sa directed()
10.659 + GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
10.660 +
10.661 + ///Sets whether the the graph is directed
10.662 +
10.663 + ///Sets whether the the graph is directed.
10.664 + ///Use it to show the edges as a pair of directed ones.
10.665 + ///
10.666 + ///This setting is the default for digraphs.
10.667 + ///
10.668 + ///\sa undirected()
10.669 + GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
10.670 +
10.671 + ///Sets the title.
10.672 +
10.673 + ///Sets the title of the generated image,
10.674 + ///namely it inserts a <tt>%%Title:</tt> DSC field to the header of
10.675 + ///the EPS file.
10.676 + GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
10.677 + ///Sets the copyright statement.
10.678 +
10.679 + ///Sets the copyright statement of the generated image,
10.680 + ///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of
10.681 + ///the EPS file.
10.682 + GraphToEps<T> ©right(const std::string &t) {_copyright=t;return *this;}
10.683 +
10.684 +protected:
10.685 + bool isInsideNode(dim2::Point<double> p, double r,int t)
10.686 + {
10.687 + switch(t) {
10.688 + case CIRCLE:
10.689 + case MALE:
10.690 + case FEMALE:
10.691 + return p.normSquare()<=r*r;
10.692 + case SQUARE:
10.693 + return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
10.694 + case DIAMOND:
10.695 + return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r;
10.696 + }
10.697 + return false;
10.698 + }
10.699 +
10.700 +public:
10.701 + ~GraphToEps() { }
10.702 +
10.703 + ///Draws the graph.
10.704 +
10.705 + ///Like other functions using
10.706 + ///\ref named-templ-func-param "named template parameters",
10.707 + ///this function calls the algorithm itself, i.e. in this case
10.708 + ///it draws the graph.
10.709 + void run() {
10.710 + //\todo better 'epsilon' would be nice here.
10.711 + const double EPSILON=1e-9;
10.712 + if(dontPrint) return;
10.713 +
10.714 + _graph_to_eps_bits::_NegY<typename T::CoordsMapType>
10.715 + mycoords(_coords,_negY);
10.716 +
10.717 + os << "%!PS-Adobe-2.0 EPSF-2.0\n";
10.718 + if(_title.size()>0) os << "%%Title: " << _title << '\n';
10.719 + if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n';
10.720 +// << "%%Copyright: XXXX\n"
10.721 + os << "%%Creator: LEMON, graphToEps()\n";
10.722 +
10.723 + {
10.724 +#ifndef WIN32
10.725 + timeval tv;
10.726 + gettimeofday(&tv, 0);
10.727 +
10.728 + char cbuf[26];
10.729 + ctime_r(&tv.tv_sec,cbuf);
10.730 + os << "%%CreationDate: " << cbuf;
10.731 +#else
10.732 + SYSTEMTIME time;
10.733 + char buf1[11], buf2[9], buf3[5];
10.734 +
10.735 + GetSystemTime(&time);
10.736 + if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
10.737 + "ddd MMM dd", buf1, 11) &&
10.738 + GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time,
10.739 + "HH':'mm':'ss", buf2, 9) &&
10.740 + GetDateFormat(LOCALE_USER_DEFAULT, 0, &time,
10.741 + "yyyy", buf3, 5)) {
10.742 + os << "%%CreationDate: " << buf1 << ' '
10.743 + << buf2 << ' ' << buf3 << std::endl;
10.744 + }
10.745 +#endif
10.746 + }
10.747 +
10.748 + if (_autoArcWidthScale) {
10.749 + double max_w=0;
10.750 + for(ArcIt e(g);e!=INVALID;++e)
10.751 + max_w=std::max(double(_arcWidths[e]),max_w);
10.752 + ///\todo better 'epsilon' would be nice here.
10.753 + if(max_w>EPSILON) {
10.754 + _arcWidthScale/=max_w;
10.755 + }
10.756 + }
10.757 +
10.758 + if (_autoNodeScale) {
10.759 + double max_s=0;
10.760 + for(NodeIt n(g);n!=INVALID;++n)
10.761 + max_s=std::max(double(_nodeSizes[n]),max_s);
10.762 + ///\todo better 'epsilon' would be nice here.
10.763 + if(max_s>EPSILON) {
10.764 + _nodeScale/=max_s;
10.765 + }
10.766 + }
10.767 +
10.768 + double diag_len = 1;
10.769 + if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
10.770 + dim2::BoundingBox<double> bb;
10.771 + for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]);
10.772 + if (bb.empty()) {
10.773 + bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
10.774 + }
10.775 + diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare());
10.776 + if(diag_len<EPSILON) diag_len = 1;
10.777 + if(!_absoluteNodeSizes) _nodeScale*=diag_len;
10.778 + if(!_absoluteArcWidths) _arcWidthScale*=diag_len;
10.779 + }
10.780 +
10.781 + dim2::BoundingBox<double> bb;
10.782 + for(NodeIt n(g);n!=INVALID;++n) {
10.783 + double ns=_nodeSizes[n]*_nodeScale;
10.784 + dim2::Point<double> p(ns,ns);
10.785 + switch(_nodeShapes[n]) {
10.786 + case CIRCLE:
10.787 + case SQUARE:
10.788 + case DIAMOND:
10.789 + bb.add(p+mycoords[n]);
10.790 + bb.add(-p+mycoords[n]);
10.791 + break;
10.792 + case MALE:
10.793 + bb.add(-p+mycoords[n]);
10.794 + bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]);
10.795 + break;
10.796 + case FEMALE:
10.797 + bb.add(p+mycoords[n]);
10.798 + bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]);
10.799 + break;
10.800 + }
10.801 + }
10.802 + if (bb.empty()) {
10.803 + bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0));
10.804 + }
10.805 +
10.806 + if(_scaleToA4)
10.807 + os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n";
10.808 + else {
10.809 + if(_preScale) {
10.810 + //Rescale so that BoundingBox won't be neither to big nor too small.
10.811 + while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10;
10.812 + while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10;
10.813 + }
10.814 +
10.815 + os << "%%BoundingBox: "
10.816 + << int(floor(bb.left() * _scale - _xBorder)) << ' '
10.817 + << int(floor(bb.bottom() * _scale - _yBorder)) << ' '
10.818 + << int(ceil(bb.right() * _scale + _xBorder)) << ' '
10.819 + << int(ceil(bb.top() * _scale + _yBorder)) << '\n';
10.820 + }
10.821 +
10.822 + os << "%%EndComments\n";
10.823 +
10.824 + //x1 y1 x2 y2 x3 y3 cr cg cb w
10.825 + os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
10.826 + << " 4 2 roll 1 index 1 index curveto stroke } bind def\n";
10.827 + os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
10.828 + //x y r
10.829 + os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
10.830 + //x y r
10.831 + os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
10.832 + << " 2 index 1 index sub 2 index 2 index add lineto\n"
10.833 + << " 2 index 1 index sub 2 index 2 index sub lineto\n"
10.834 + << " 2 index 1 index add 2 index 2 index sub lineto\n"
10.835 + << " closepath pop pop pop} bind def\n";
10.836 + //x y r
10.837 + os << "/di { newpath 2 index 1 index add 2 index moveto\n"
10.838 + << " 2 index 2 index 2 index add lineto\n"
10.839 + << " 2 index 1 index sub 2 index lineto\n"
10.840 + << " 2 index 2 index 2 index sub lineto\n"
10.841 + << " closepath pop pop pop} bind def\n";
10.842 + // x y r cr cg cb
10.843 + os << "/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill\n"
10.844 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
10.845 + << " } bind def\n";
10.846 + os << "/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill\n"
10.847 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div sq fill\n"
10.848 + << " } bind def\n";
10.849 + os << "/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill\n"
10.850 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div di fill\n"
10.851 + << " } bind def\n";
10.852 + os << "/nfemale { 0 0 0 setrgbcolor 3 index "
10.853 + << _nodeBorderQuotient/(1+_nodeBorderQuotient)
10.854 + << " 1.5 mul mul setlinewidth\n"
10.855 + << " newpath 5 index 5 index moveto "
10.856 + << "5 index 5 index 5 index 3.01 mul sub\n"
10.857 + << " lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto\n"
10.858 + << " 5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke\n"
10.859 + << " 5 index 5 index 5 index c fill\n"
10.860 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
10.861 + << " } bind def\n";
10.862 + os << "/nmale {\n"
10.863 + << " 0 0 0 setrgbcolor 3 index "
10.864 + << _nodeBorderQuotient/(1+_nodeBorderQuotient)
10.865 + <<" 1.5 mul mul setlinewidth\n"
10.866 + << " newpath 5 index 5 index moveto\n"
10.867 + << " 5 index 4 index 1 mul 1.5 mul add\n"
10.868 + << " 5 index 5 index 3 sqrt 1.5 mul mul add\n"
10.869 + << " 1 index 1 index lineto\n"
10.870 + << " 1 index 1 index 7 index sub moveto\n"
10.871 + << " 1 index 1 index lineto\n"
10.872 + << " exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto\n"
10.873 + << " stroke\n"
10.874 + << " 5 index 5 index 5 index c fill\n"
10.875 + << " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n"
10.876 + << " } bind def\n";
10.877 +
10.878 +
10.879 + os << "/arrl " << _arrowLength << " def\n";
10.880 + os << "/arrw " << _arrowWidth << " def\n";
10.881 + // l dx_norm dy_norm
10.882 + os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
10.883 + //len w dx_norm dy_norm x1 y1 cr cg cb
10.884 + os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
10.885 + << " /w exch def /len exch def\n"
10.886 + // << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke"
10.887 + << " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n"
10.888 + << " len w sub arrl sub dx dy lrl\n"
10.889 + << " arrw dy dx neg lrl\n"
10.890 + << " dx arrl w add mul dy w 2 div arrw add mul sub\n"
10.891 + << " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n"
10.892 + << " dx arrl w add mul neg dy w 2 div arrw add mul sub\n"
10.893 + << " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n"
10.894 + << " arrw dy dx neg lrl\n"
10.895 + << " len w sub arrl sub neg dx dy lrl\n"
10.896 + << " closepath fill } bind def\n";
10.897 + os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
10.898 + << " neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n";
10.899 +
10.900 + os << "\ngsave\n";
10.901 + if(_scaleToA4)
10.902 + if(bb.height()>bb.width()) {
10.903 + double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(),
10.904 + (A4WIDTH-2*A4BORDER)/bb.width());
10.905 + os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' '
10.906 + << ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER
10.907 + << " translate\n"
10.908 + << sc << " dup scale\n"
10.909 + << -bb.left() << ' ' << -bb.bottom() << " translate\n";
10.910 + }
10.911 + else {
10.912 + //\todo Verify centering
10.913 + double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(),
10.914 + (A4WIDTH-2*A4BORDER)/bb.height());
10.915 + os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' '
10.916 + << ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER
10.917 + << " translate\n"
10.918 + << sc << " dup scale\n90 rotate\n"
10.919 + << -bb.left() << ' ' << -bb.top() << " translate\n";
10.920 + }
10.921 + else if(_scale!=1.0) os << _scale << " dup scale\n";
10.922 +
10.923 + if(_showArcs) {
10.924 + os << "%Arcs:\ngsave\n";
10.925 + if(_enableParallel) {
10.926 + std::vector<Arc> el;
10.927 + for(ArcIt e(g);e!=INVALID;++e)
10.928 + if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
10.929 + &&g.source(e)!=g.target(e))
10.930 + el.push_back(e);
10.931 + std::sort(el.begin(),el.end(),arcLess(g));
10.932 +
10.933 + typename std::vector<Arc>::iterator j;
10.934 + for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
10.935 + for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ;
10.936 +
10.937 + double sw=0;
10.938 + for(typename std::vector<Arc>::iterator e=i;e!=j;++e)
10.939 + sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist;
10.940 + sw-=_parArcDist;
10.941 + sw/=-2.0;
10.942 + dim2::Point<double>
10.943 + dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]);
10.944 + double l=std::sqrt(dvec.normSquare());
10.945 + //\todo better 'epsilon' would be nice here.
10.946 + dim2::Point<double> d(dvec/std::max(l,EPSILON));
10.947 + dim2::Point<double> m;
10.948 +// m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;
10.949 +
10.950 +// m=dim2::Point<double>(mycoords[g.source(*i)])+
10.951 +// dvec*(double(_nodeSizes[g.source(*i)])/
10.952 +// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)]));
10.953 +
10.954 + m=dim2::Point<double>(mycoords[g.source(*i)])+
10.955 + d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0;
10.956 +
10.957 + for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
10.958 + sw+=_arcWidths[*e]*_arcWidthScale/2.0;
10.959 + dim2::Point<double> mm=m+rot90(d)*sw/.75;
10.960 + if(_drawArrows) {
10.961 + int node_shape;
10.962 + dim2::Point<double> s=mycoords[g.source(*e)];
10.963 + dim2::Point<double> t=mycoords[g.target(*e)];
10.964 + double rn=_nodeSizes[g.target(*e)]*_nodeScale;
10.965 + node_shape=_nodeShapes[g.target(*e)];
10.966 + dim2::Bezier3 bez(s,mm,mm,t);
10.967 + double t1=0,t2=1;
10.968 + for(int ii=0;ii<INTERPOL_PREC;++ii)
10.969 + if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
10.970 + else t1=(t1+t2)/2;
10.971 + dim2::Point<double> apoint=bez((t1+t2)/2);
10.972 + rn = _arrowLength+_arcWidths[*e]*_arcWidthScale;
10.973 + rn*=rn;
10.974 + t2=(t1+t2)/2;t1=0;
10.975 + for(int ii=0;ii<INTERPOL_PREC;++ii)
10.976 + if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
10.977 + else t2=(t1+t2)/2;
10.978 + dim2::Point<double> linend=bez((t1+t2)/2);
10.979 + bez=bez.before((t1+t2)/2);
10.980 +// rn=_nodeSizes[g.source(*e)]*_nodeScale;
10.981 +// node_shape=_nodeShapes[g.source(*e)];
10.982 +// t1=0;t2=1;
10.983 +// for(int i=0;i<INTERPOL_PREC;++i)
10.984 +// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
10.985 +// else t2=(t1+t2)/2;
10.986 +// bez=bez.after((t1+t2)/2);
10.987 + os << _arcWidths[*e]*_arcWidthScale << " setlinewidth "
10.988 + << _arcColors[*e].red() << ' '
10.989 + << _arcColors[*e].green() << ' '
10.990 + << _arcColors[*e].blue() << " setrgbcolor newpath\n"
10.991 + << bez.p1.x << ' ' << bez.p1.y << " moveto\n"
10.992 + << bez.p2.x << ' ' << bez.p2.y << ' '
10.993 + << bez.p3.x << ' ' << bez.p3.y << ' '
10.994 + << bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n";
10.995 + dim2::Point<double> dd(rot90(linend-apoint));
10.996 + dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/
10.997 + std::sqrt(dd.normSquare());
10.998 + os << "newpath " << psOut(apoint) << " moveto "
10.999 + << psOut(linend+dd) << " lineto "
10.1000 + << psOut(linend-dd) << " lineto closepath fill\n";
10.1001 + }
10.1002 + else {
10.1003 + os << mycoords[g.source(*e)].x << ' '
10.1004 + << mycoords[g.source(*e)].y << ' '
10.1005 + << mm.x << ' ' << mm.y << ' '
10.1006 + << mycoords[g.target(*e)].x << ' '
10.1007 + << mycoords[g.target(*e)].y << ' '
10.1008 + << _arcColors[*e].red() << ' '
10.1009 + << _arcColors[*e].green() << ' '
10.1010 + << _arcColors[*e].blue() << ' '
10.1011 + << _arcWidths[*e]*_arcWidthScale << " lb\n";
10.1012 + }
10.1013 + sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist;
10.1014 + }
10.1015 + }
10.1016 + }
10.1017 + else for(ArcIt e(g);e!=INVALID;++e)
10.1018 + if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0
10.1019 + &&g.source(e)!=g.target(e))
10.1020 + if(_drawArrows) {
10.1021 + dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]);
10.1022 + double rn=_nodeSizes[g.target(e)]*_nodeScale;
10.1023 + int node_shape=_nodeShapes[g.target(e)];
10.1024 + double t1=0,t2=1;
10.1025 + for(int i=0;i<INTERPOL_PREC;++i)
10.1026 + if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2;
10.1027 + else t2=(t1+t2)/2;
10.1028 + double l=std::sqrt(d.normSquare());
10.1029 + d/=l;
10.1030 +
10.1031 + os << l*(1-(t1+t2)/2) << ' '
10.1032 + << _arcWidths[e]*_arcWidthScale << ' '
10.1033 + << d.x << ' ' << d.y << ' '
10.1034 + << mycoords[g.source(e)].x << ' '
10.1035 + << mycoords[g.source(e)].y << ' '
10.1036 + << _arcColors[e].red() << ' '
10.1037 + << _arcColors[e].green() << ' '
10.1038 + << _arcColors[e].blue() << " arr\n";
10.1039 + }
10.1040 + else os << mycoords[g.source(e)].x << ' '
10.1041 + << mycoords[g.source(e)].y << ' '
10.1042 + << mycoords[g.target(e)].x << ' '
10.1043 + << mycoords[g.target(e)].y << ' '
10.1044 + << _arcColors[e].red() << ' '
10.1045 + << _arcColors[e].green() << ' '
10.1046 + << _arcColors[e].blue() << ' '
10.1047 + << _arcWidths[e]*_arcWidthScale << " l\n";
10.1048 + os << "grestore\n";
10.1049 + }
10.1050 + if(_showNodes) {
10.1051 + os << "%Nodes:\ngsave\n";
10.1052 + for(NodeIt n(g);n!=INVALID;++n) {
10.1053 + os << mycoords[n].x << ' ' << mycoords[n].y << ' '
10.1054 + << _nodeSizes[n]*_nodeScale << ' '
10.1055 + << _nodeColors[n].red() << ' '
10.1056 + << _nodeColors[n].green() << ' '
10.1057 + << _nodeColors[n].blue() << ' ';
10.1058 + switch(_nodeShapes[n]) {
10.1059 + case CIRCLE:
10.1060 + os<< "nc";break;
10.1061 + case SQUARE:
10.1062 + os<< "nsq";break;
10.1063 + case DIAMOND:
10.1064 + os<< "ndi";break;
10.1065 + case MALE:
10.1066 + os<< "nmale";break;
10.1067 + case FEMALE:
10.1068 + os<< "nfemale";break;
10.1069 + }
10.1070 + os<<'\n';
10.1071 + }
10.1072 + os << "grestore\n";
10.1073 + }
10.1074 + if(_showNodeText) {
10.1075 + os << "%Node texts:\ngsave\n";
10.1076 + os << "/fosi " << _nodeTextSize << " def\n";
10.1077 + os << "(Helvetica) findfont fosi scalefont setfont\n";
10.1078 + for(NodeIt n(g);n!=INVALID;++n) {
10.1079 + switch(_nodeTextColorType) {
10.1080 + case DIST_COL:
10.1081 + os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n";
10.1082 + break;
10.1083 + case DIST_BW:
10.1084 + os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n";
10.1085 + break;
10.1086 + case CUST_COL:
10.1087 + os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n";
10.1088 + break;
10.1089 + default:
10.1090 + os << "0 0 0 setrgbcolor\n";
10.1091 + }
10.1092 + os << mycoords[n].x << ' ' << mycoords[n].y
10.1093 + << " (" << _nodeTexts[n] << ") cshow\n";
10.1094 + }
10.1095 + os << "grestore\n";
10.1096 + }
10.1097 + if(_showNodePsText) {
10.1098 + os << "%Node PS blocks:\ngsave\n";
10.1099 + for(NodeIt n(g);n!=INVALID;++n)
10.1100 + os << mycoords[n].x << ' ' << mycoords[n].y
10.1101 + << " moveto\n" << _nodePsTexts[n] << "\n";
10.1102 + os << "grestore\n";
10.1103 + }
10.1104 +
10.1105 + os << "grestore\nshowpage\n";
10.1106 +
10.1107 + //CleanUp:
10.1108 + if(_pleaseRemoveOsStream) {delete &os;}
10.1109 + }
10.1110 +
10.1111 + ///\name Aliases
10.1112 + ///These are just some aliases to other parameter setting functions.
10.1113 +
10.1114 + ///@{
10.1115 +
10.1116 + ///An alias for arcWidths()
10.1117 +
10.1118 + ///An alias for arcWidths()
10.1119 + ///
10.1120 + template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x)
10.1121 + {
10.1122 + return arcWidths(x);
10.1123 + }
10.1124 +
10.1125 + ///An alias for arcColors()
10.1126 +
10.1127 + ///An alias for arcColors()
10.1128 + ///
10.1129 + template<class X> GraphToEps<ArcColorsTraits<X> >
10.1130 + edgeColors(const X &x)
10.1131 + {
10.1132 + return arcColors(x);
10.1133 + }
10.1134 +
10.1135 + ///An alias for arcWidthScale()
10.1136 +
10.1137 + ///An alias for arcWidthScale()
10.1138 + ///
10.1139 + GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
10.1140 +
10.1141 + ///An alias for autoArcWidthScale()
10.1142 +
10.1143 + ///An alias for autoArcWidthScale()
10.1144 + ///
10.1145 + GraphToEps<T> &autoEdgeWidthScale(bool b=true)
10.1146 + {
10.1147 + return autoArcWidthScale(b);
10.1148 + }
10.1149 +
10.1150 + ///An alias for absoluteArcWidths()
10.1151 +
10.1152 + ///An alias for absoluteArcWidths()
10.1153 + ///
10.1154 + GraphToEps<T> &absoluteEdgeWidths(bool b=true)
10.1155 + {
10.1156 + return absoluteArcWidths(b);
10.1157 + }
10.1158 +
10.1159 + ///An alias for parArcDist()
10.1160 +
10.1161 + ///An alias for parArcDist()
10.1162 + ///
10.1163 + GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
10.1164 +
10.1165 + ///An alias for hideArcs()
10.1166 +
10.1167 + ///An alias for hideArcs()
10.1168 + ///
10.1169 + GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
10.1170 +
10.1171 + ///@}
10.1172 +};
10.1173 +
10.1174 +template<class T>
10.1175 +const int GraphToEps<T>::INTERPOL_PREC = 20;
10.1176 +template<class T>
10.1177 +const double GraphToEps<T>::A4HEIGHT = 841.8897637795276;
10.1178 +template<class T>
10.1179 +const double GraphToEps<T>::A4WIDTH = 595.275590551181;
10.1180 +template<class T>
10.1181 +const double GraphToEps<T>::A4BORDER = 15;
10.1182 +
10.1183 +
10.1184 +///Generates an EPS file from a graph
10.1185 +
10.1186 +///\ingroup eps_io
10.1187 +///Generates an EPS file from a graph.
10.1188 +///\param g is a reference to the graph to be printed
10.1189 +///\param os is a reference to the output stream.
10.1190 +///By default it is <tt>std::cout</tt>
10.1191 +///
10.1192 +///This function also has a lot of
10.1193 +///\ref named-templ-func-param "named parameters",
10.1194 +///they are declared as the members of class \ref GraphToEps. The following
10.1195 +///example shows how to use these parameters.
10.1196 +///\code
10.1197 +/// graphToEps(g,os).scale(10).coords(coords)
10.1198 +/// .nodeScale(2).nodeSizes(sizes)
10.1199 +/// .arcWidthScale(.4).run();
10.1200 +///\endcode
10.1201 +///\warning Don't forget to put the \ref GraphToEps::run() "run()"
10.1202 +///to the end of the parameter list.
10.1203 +///\sa GraphToEps
10.1204 +///\sa graphToEps(G &g, const char *file_name)
10.1205 +template<class G>
10.1206 +GraphToEps<DefaultGraphToEpsTraits<G> >
10.1207 +graphToEps(G &g, std::ostream& os=std::cout)
10.1208 +{
10.1209 + return
10.1210 + GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os));
10.1211 +}
10.1212 +
10.1213 +///Generates an EPS file from a graph
10.1214 +
10.1215 +///\ingroup eps_io
10.1216 +///This function does the same as
10.1217 +///\ref graphToEps(G &g,std::ostream& os)
10.1218 +///but it writes its output into the file \c file_name
10.1219 +///instead of a stream.
10.1220 +///\sa graphToEps(G &g, std::ostream& os)
10.1221 +template<class G>
10.1222 +GraphToEps<DefaultGraphToEpsTraits<G> >
10.1223 +graphToEps(G &g,const char *file_name)
10.1224 +{
10.1225 + return GraphToEps<DefaultGraphToEpsTraits<G> >
10.1226 + (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
10.1227 +}
10.1228 +
10.1229 +///Generates an EPS file from a graph
10.1230 +
10.1231 +///\ingroup eps_io
10.1232 +///This function does the same as
10.1233 +///\ref graphToEps(G &g,std::ostream& os)
10.1234 +///but it writes its output into the file \c file_name
10.1235 +///instead of a stream.
10.1236 +///\sa graphToEps(G &g, std::ostream& os)
10.1237 +template<class G>
10.1238 +GraphToEps<DefaultGraphToEpsTraits<G> >
10.1239 +graphToEps(G &g,const std::string& file_name)
10.1240 +{
10.1241 + return GraphToEps<DefaultGraphToEpsTraits<G> >
10.1242 + (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true));
10.1243 +}
10.1244 +
10.1245 +} //END OF NAMESPACE LEMON
10.1246 +
10.1247 +#endif // LEMON_GRAPH_TO_EPS_H