# HG changeset patch # User alpar # Date 1155568557 0 # Node ID 0d7c0f96a5eef5aeebb7504f2be76f9901103916 # Parent 416a7030b7e377746634e05ae477b3173758269f - bezier.h went to lemon/bits/ - new graphToEps() option: absolute/relative node size/link width scaling. diff -r 416a7030b7e3 -r 0d7c0f96a5ee demo/graph_to_eps_demo.cc --- a/demo/graph_to_eps_demo.cc Fri Aug 11 14:55:33 2006 +0000 +++ b/demo/graph_to_eps_demo.cc Mon Aug 14 15:15:57 2006 +0000 @@ -42,6 +42,7 @@ int main() { Palette palette; + Palette paletteW(true); ListGraph g; typedef ListGraph::Node Node; @@ -80,12 +81,21 @@ IdMap id(g); + cout << "Create 'graph_to_eps_demo_out_pure.eps'" << endl; + graphToEps(g,"graph_to_eps_demo_out_pure.eps"). + //scale(10). + coords(coords). + title("Sample .eps figure"). + copyright("(C) 2006 LEMON Project"). + run(); + cout << "Create 'graph_to_eps_demo_out.eps'" << endl; graphToEps(g,"graph_to_eps_demo_out.eps"). //scale(10). coords(coords). title("Sample .eps figure"). copyright("(C) 2006 LEMON Project"). + absoluteNodeSizes().absoluteEdgeWidths(). nodeScale(2).nodeSizes(sizes). nodeShapes(shapes). nodeColors(composeMap(palette,colors)). @@ -100,6 +110,7 @@ //scale(10). title("Sample .eps figure (with arrowheads)"). copyright("(C) 2006 LEMON Project"). + absoluteNodeSizes().absoluteEdgeWidths(). nodeColors(composeMap(palette,colors)). coords(coords). nodeScale(2).nodeSizes(sizes). @@ -126,6 +137,7 @@ //scale(10). title("Sample .eps figure (parallel edges)"). copyright("(C) 2006 LEMON Project"). + absoluteNodeSizes().absoluteEdgeWidths(). nodeShapes(shapes). coords(coords). nodeScale(2).nodeSizes(sizes). @@ -141,6 +153,7 @@ //scale(10). title("Sample .eps figure (parallel edges and arrowheads)"). copyright("(C) 2006 LEMON Project"). + absoluteNodeSizes().absoluteEdgeWidths(). nodeScale(2).nodeSizes(sizes). coords(coords). nodeShapes(shapes). @@ -156,6 +169,7 @@ graphToEps(g,"graph_to_eps_demo_out_a4.eps").scaleToA4(). title("Sample .eps figure (fits to A4)"). copyright("(C) 2006 LEMON Project"). + absoluteNodeSizes().absoluteEdgeWidths(). nodeScale(2).nodeSizes(sizes). coords(coords). nodeShapes(shapes). @@ -172,7 +186,7 @@ ListGraph::NodeMap hcoords(h); int cols=int(sqrt(double(palette.size()))); - for(int i=0;i - -namespace lemon { - -class BezierBase { -public: - typedef xy xy; -protected: - static xy conv(xy x,xy y,double t) {return (1-t)*x+t*y;} -}; - -class Bezier1 : public BezierBase -{ -public: - xy p1,p2; - - Bezier1() {} - Bezier1(xy _p1, xy _p2) :p1(_p1), p2(_p2) {} - - xy operator()(double t) const - { - // return conv(conv(p1,p2,t),conv(p2,p3,t),t); - return conv(p1,p2,t); - } - Bezier1 before(double t) const - { - return Bezier1(p1,conv(p1,p2,t)); - } - - Bezier1 after(double t) const - { - return Bezier1(conv(p1,p2,t),p2); - } - - Bezier1 revert() const { return Bezier1(p2,p1);} - Bezier1 operator()(double a,double b) const { return before(b).after(a/b); } - xy grad() const { return p2-p1; } - xy norm() const { return rot90(p2-p1); } - xy grad(double) const { return grad(); } - xy norm(double t) const { return rot90(grad(t)); } -}; - -class Bezier2 : public BezierBase -{ -public: - xy p1,p2,p3; - - Bezier2() {} - Bezier2(xy _p1, xy _p2, xy _p3) :p1(_p1), p2(_p2), p3(_p3) {} - Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {} - xy operator()(double t) const - { - // return conv(conv(p1,p2,t),conv(p2,p3,t),t); - return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3; - } - Bezier2 before(double t) const - { - xy q(conv(p1,p2,t)); - xy r(conv(p2,p3,t)); - return Bezier2(p1,q,conv(q,r,t)); - } - - Bezier2 after(double t) const - { - xy q(conv(p1,p2,t)); - xy r(conv(p2,p3,t)); - return Bezier2(conv(q,r,t),r,p3); - } - Bezier2 revert() const { return Bezier2(p3,p2,p1);} - Bezier2 operator()(double a,double b) const { return before(b).after(a/b); } - Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); } - Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); } - xy grad(double t) const { return grad()(t); } - xy norm(double t) const { return rot90(grad(t)); } -}; - -class Bezier3 : public BezierBase -{ -public: - xy p1,p2,p3,p4; - - Bezier3() {} - Bezier3(xy _p1, xy _p2, xy _p3, xy _p4) :p1(_p1), p2(_p2), p3(_p3), p4(_p4) {} - Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), - p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {} - Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)), - p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {} - - xy operator()(double t) const - { - // return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t); - return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+ - (3*t*t*(1-t))*p3+(t*t*t)*p4; - } - Bezier3 before(double t) const - { - xy p(conv(p1,p2,t)); - xy q(conv(p2,p3,t)); - xy r(conv(p3,p4,t)); - xy a(conv(p,q,t)); - xy b(conv(q,r,t)); - xy c(conv(a,b,t)); - return Bezier3(p1,p,a,c); - } - - Bezier3 after(double t) const - { - xy p(conv(p1,p2,t)); - xy q(conv(p2,p3,t)); - xy r(conv(p3,p4,t)); - xy a(conv(p,q,t)); - xy b(conv(q,r,t)); - xy c(conv(a,b,t)); - return Bezier3(c,b,r,p4); - } - Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);} - Bezier3 operator()(double a,double b) const { return before(b).after(a/b); } - Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); } - Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1), - 3.0*rot90(p3-p2), - 3.0*rot90(p4-p3)); } - xy grad(double t) const { return grad()(t); } - xy norm(double t) const { return rot90(grad(t)); } - - template - R recSplit(F &_f,const S &_s,D _d) const - { - const xy a=(p1+p2)/2; - const xy b=(p2+p3)/2; - const xy c=(p3+p4)/2; - const xy d=(a+b)/2; - const xy e=(b+c)/2; - const xy f=(d+e)/2; - R f1=_f(Bezier3(p1,a,d,e),_d); - R f2=_f(Bezier3(e,d,c,p4),_d); - return _s(f1,f2); - } - -}; - -} //END OF NAMESPACE LEMON - -#endif // LEMON_BEZIER_H diff -r 416a7030b7e3 -r 0d7c0f96a5ee lemon/bits/bezier.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/bits/bezier.h Mon Aug 14 15:15:57 2006 +0000 @@ -0,0 +1,172 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2006 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#ifndef LEMON_BEZIER_H +#define LEMON_BEZIER_H + +///\ingroup misc +///\file +///\brief Classes to compute with Bezier curves. +/// +///Up to now this file is used internally by \ref graph_to_eps.h +/// +///\author Alpar Juttner + +#include + +namespace lemon { + +class BezierBase { +public: + typedef xy xy; +protected: + static xy conv(xy x,xy y,double t) {return (1-t)*x+t*y;} +}; + +class Bezier1 : public BezierBase +{ +public: + xy p1,p2; + + Bezier1() {} + Bezier1(xy _p1, xy _p2) :p1(_p1), p2(_p2) {} + + xy operator()(double t) const + { + // return conv(conv(p1,p2,t),conv(p2,p3,t),t); + return conv(p1,p2,t); + } + Bezier1 before(double t) const + { + return Bezier1(p1,conv(p1,p2,t)); + } + + Bezier1 after(double t) const + { + return Bezier1(conv(p1,p2,t),p2); + } + + Bezier1 revert() const { return Bezier1(p2,p1);} + Bezier1 operator()(double a,double b) const { return before(b).after(a/b); } + xy grad() const { return p2-p1; } + xy norm() const { return rot90(p2-p1); } + xy grad(double) const { return grad(); } + xy norm(double t) const { return rot90(grad(t)); } +}; + +class Bezier2 : public BezierBase +{ +public: + xy p1,p2,p3; + + Bezier2() {} + Bezier2(xy _p1, xy _p2, xy _p3) :p1(_p1), p2(_p2), p3(_p3) {} + Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {} + xy operator()(double t) const + { + // return conv(conv(p1,p2,t),conv(p2,p3,t),t); + return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3; + } + Bezier2 before(double t) const + { + xy q(conv(p1,p2,t)); + xy r(conv(p2,p3,t)); + return Bezier2(p1,q,conv(q,r,t)); + } + + Bezier2 after(double t) const + { + xy q(conv(p1,p2,t)); + xy r(conv(p2,p3,t)); + return Bezier2(conv(q,r,t),r,p3); + } + Bezier2 revert() const { return Bezier2(p3,p2,p1);} + Bezier2 operator()(double a,double b) const { return before(b).after(a/b); } + Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); } + Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); } + xy grad(double t) const { return grad()(t); } + xy norm(double t) const { return rot90(grad(t)); } +}; + +class Bezier3 : public BezierBase +{ +public: + xy p1,p2,p3,p4; + + Bezier3() {} + Bezier3(xy _p1, xy _p2, xy _p3, xy _p4) :p1(_p1), p2(_p2), p3(_p3), p4(_p4) {} + Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), + p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {} + Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)), + p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {} + + xy operator()(double t) const + { + // return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t); + return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+ + (3*t*t*(1-t))*p3+(t*t*t)*p4; + } + Bezier3 before(double t) const + { + xy p(conv(p1,p2,t)); + xy q(conv(p2,p3,t)); + xy r(conv(p3,p4,t)); + xy a(conv(p,q,t)); + xy b(conv(q,r,t)); + xy c(conv(a,b,t)); + return Bezier3(p1,p,a,c); + } + + Bezier3 after(double t) const + { + xy p(conv(p1,p2,t)); + xy q(conv(p2,p3,t)); + xy r(conv(p3,p4,t)); + xy a(conv(p,q,t)); + xy b(conv(q,r,t)); + xy c(conv(a,b,t)); + return Bezier3(c,b,r,p4); + } + Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);} + Bezier3 operator()(double a,double b) const { return before(b).after(a/b); } + Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); } + Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1), + 3.0*rot90(p3-p2), + 3.0*rot90(p4-p3)); } + xy grad(double t) const { return grad()(t); } + xy norm(double t) const { return rot90(grad(t)); } + + template + R recSplit(F &_f,const S &_s,D _d) const + { + const xy a=(p1+p2)/2; + const xy b=(p2+p3)/2; + const xy c=(p3+p4)/2; + const xy d=(a+b)/2; + const xy e=(b+c)/2; + const xy f=(d+e)/2; + R f1=_f(Bezier3(p1,a,d,e),_d); + R f2=_f(Bezier3(e,d,c,p4),_d); + return _s(f1,f2); + } + +}; + +} //END OF NAMESPACE LEMON + +#endif // LEMON_BEZIER_H diff -r 416a7030b7e3 -r 0d7c0f96a5ee lemon/graph_to_eps.h --- a/lemon/graph_to_eps.h Fri Aug 11 14:55:33 2006 +0000 +++ b/lemon/graph_to_eps.h Mon Aug 14 15:15:57 2006 +0000 @@ -38,7 +38,7 @@ #include #include #include -#include +#include ///\ingroup eps_io @@ -130,6 +130,9 @@ bool _autoNodeScale; bool _autoEdgeWidthScale; + bool _absoluteNodeSizes; + bool _absoluteEdgeWidths; + bool _negY; ///Constructor @@ -143,9 +146,9 @@ DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, bool _pros=false) : g(_g), os(_os), - _coords(xy(1,1)), _nodeSizes(1.0), _nodeShapes(0), + _coords(xy(1,1)), _nodeSizes(.01), _nodeShapes(0), _nodeColors(WHITE), _edgeColors(BLACK), - _edgeWidths(1), _edgeWidthScale(0.3), + _edgeWidths(1.0), _edgeWidthScale(0.003), _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), _nodeBorderQuotient(.1), _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), @@ -158,6 +161,8 @@ _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK), _autoNodeScale(false), _autoEdgeWidthScale(false), + _absoluteNodeSizes(false), + _absoluteEdgeWidths(false), _negY(false) {} }; @@ -229,6 +234,10 @@ using T::_autoNodeScale; using T::_autoEdgeWidthScale; + using T::_absoluteNodeSizes; + using T::_absoluteEdgeWidths; + + using T::_negY; // dradnats ++C eht yb deriuqer si ti eveileb t'naC @@ -478,6 +487,8 @@ /// If both nodeSizes() and autoNodeScale() are used, then the /// node sizes will be scaled in such a way that the greatest size will be /// equal to \c d. + /// \sa nodeSizes() + /// \sa autoNodeScale() GraphToEps &nodeScale(double d) {_nodeScale=d;return *this;} ///Turns on/off the automatic node width scaling. @@ -489,6 +500,16 @@ _autoNodeScale=b;return *this; } + ///Turns on/off the absolutematic node width scaling. + + ///Turns on/off the absolutematic node width scaling. + /// + ///\sa nodeScale() + /// + GraphToEps &absoluteNodeSizes(bool b=true) { + _absoluteNodeSizes=b;return *this; + } + ///Negates the Y coordinates. ///Negates the Y coordinates. @@ -520,6 +541,15 @@ GraphToEps &autoEdgeWidthScale(bool b=true) { _autoEdgeWidthScale=b;return *this; } + ///Turns on/off the absolutematic edge width scaling. + + ///Turns on/off the absolutematic edge width scaling. + /// + ///\sa edgeWidthScale() + /// + GraphToEps &absoluteEdgeWidths(bool b=true) { + _absoluteEdgeWidths=b;return *this; + } ///Sets a global scale factor for the whole picture ///Sets a global scale factor for the whole picture @@ -664,6 +694,8 @@ ///this function calles the algorithm itself, i.e. in this case ///it draws the graph. void run() { + ///\todo better 'epsilon' would be nice here. + const double EPSILON=1e-9; if(dontPrint) return; _NegY mycoords(_coords,_negY); @@ -687,7 +719,7 @@ for(EdgeIt e(g);e!=INVALID;++e) max_w=std::max(double(_edgeWidths[e]),max_w); ///\todo better 'epsilon' would be nice here. - if(max_w>1e-9) { + if(max_w>EPSILON) { _edgeWidthScale/=max_w; } } @@ -697,14 +729,25 @@ for(NodeIt n(g);n!=INVALID;++n) max_s=std::max(double(_nodeSizes[n]),max_s); ///\todo better 'epsilon' would be nice here. - if(max_s>1e-9) { + if(max_s>EPSILON) { _nodeScale/=max_s; } } - + double diag_len = 1; + if(!(_absoluteNodeSizes&&_absoluteEdgeWidths)) { + BoundingBox bb; + for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]); + if (bb.empty()) { + bb = BoundingBox(xy(0,0)); + } + diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare()); + if(diag_len bb; - ///\bug: Chech whether the graph is empty. for(NodeIt n(g);n!=INVALID;++n) { double ns=_nodeSizes[n]*_nodeScale; xy p(ns,ns); @@ -864,7 +907,7 @@ xy dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]); double l=std::sqrt(dvec.normSquare()); ///\todo better 'epsilon' would be nice here. - xy d(dvec/std::max(l,1e-9)); + xy d(dvec/std::max(l,EPSILON)); xy m; // m=xy(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0;