| ... | ... |
@@ -20,75 +20,77 @@ |
| 20 | 20 |
#define LEMON_GRAPH_TO_EPS_H |
| 21 | 21 |
|
| 22 | 22 |
#include <sys/time.h> |
| 23 | 23 |
|
| 24 | 24 |
#ifdef WIN32 |
| 25 | 25 |
#include <lemon/bits/mingw32_time.h> |
| 26 | 26 |
#endif |
| 27 | 27 |
|
| 28 | 28 |
#include<iostream> |
| 29 | 29 |
#include<fstream> |
| 30 | 30 |
#include<sstream> |
| 31 | 31 |
#include<algorithm> |
| 32 | 32 |
#include<vector> |
| 33 | 33 |
|
| 34 | 34 |
#include<ctime> |
| 35 | 35 |
|
| 36 | 36 |
#include<lemon/math.h> |
| 37 | 37 |
#include<lemon/bits/invalid.h> |
| 38 | 38 |
#include<lemon/dim2.h> |
| 39 | 39 |
#include<lemon/maps.h> |
| 40 | 40 |
#include<lemon/color.h> |
| 41 | 41 |
#include<lemon/bits/bezier.h> |
| 42 | 42 |
|
| 43 | 43 |
|
| 44 | 44 |
///\ingroup eps_io |
| 45 | 45 |
///\file |
| 46 | 46 |
///\brief Simple graph drawer |
| 47 | 47 |
/// |
| 48 | 48 |
///\author Alpar Juttner |
| 49 | 49 |
|
| 50 | 50 |
namespace lemon {
|
| 51 | 51 |
|
| 52 |
template<class MT> |
|
| 53 |
class _NegY {
|
|
| 54 |
public: |
|
| 55 |
typedef typename MT::Key Key; |
|
| 56 |
typedef typename MT::Value Value; |
|
| 57 |
const MT ↦ |
|
| 58 |
int yscale; |
|
| 59 |
_NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
|
|
| 60 |
Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
|
|
| 61 |
}; |
|
| 62 |
|
|
| 52 |
namespace _graph_to_eps_bits {
|
|
| 53 |
template<class MT> |
|
| 54 |
class _NegY {
|
|
| 55 |
public: |
|
| 56 |
typedef typename MT::Key Key; |
|
| 57 |
typedef typename MT::Value Value; |
|
| 58 |
const MT ↦ |
|
| 59 |
int yscale; |
|
| 60 |
_NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
|
|
| 61 |
Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
|
|
| 62 |
}; |
|
| 63 |
} |
|
| 64 |
|
|
| 63 | 65 |
///Default traits class of \ref GraphToEps |
| 64 | 66 |
|
| 65 | 67 |
///Default traits class of \ref GraphToEps |
| 66 | 68 |
/// |
| 67 | 69 |
///\c G is the type of the underlying graph. |
| 68 | 70 |
template<class G> |
| 69 | 71 |
struct DefaultGraphToEpsTraits |
| 70 | 72 |
{
|
| 71 | 73 |
typedef G Graph; |
| 72 | 74 |
typedef typename Graph::Node Node; |
| 73 | 75 |
typedef typename Graph::NodeIt NodeIt; |
| 74 | 76 |
typedef typename Graph::Arc Arc; |
| 75 | 77 |
typedef typename Graph::ArcIt ArcIt; |
| 76 | 78 |
typedef typename Graph::InArcIt InArcIt; |
| 77 | 79 |
typedef typename Graph::OutArcIt OutArcIt; |
| 78 | 80 |
|
| 79 | 81 |
|
| 80 | 82 |
const Graph &g; |
| 81 | 83 |
|
| 82 | 84 |
std::ostream& os; |
| 83 | 85 |
|
| 84 | 86 |
typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType; |
| 85 | 87 |
CoordsMapType _coords; |
| 86 | 88 |
ConstMap<typename Graph::Node,double > _nodeSizes; |
| 87 | 89 |
ConstMap<typename Graph::Node,int > _nodeShapes; |
| 88 | 90 |
|
| 89 | 91 |
ConstMap<typename Graph::Node,Color > _nodeColors; |
| 90 | 92 |
ConstMap<typename Graph::Arc,Color > _arcColors; |
| 91 | 93 |
|
| 92 | 94 |
ConstMap<typename Graph::Arc,double > _arcWidths; |
| 93 | 95 |
|
| 94 | 96 |
double _arcWidthScale; |
| ... | ... |
@@ -129,65 +131,65 @@ |
| 129 | 131 |
|
| 130 | 132 |
bool _autoNodeScale; |
| 131 | 133 |
bool _autoArcWidthScale; |
| 132 | 134 |
|
| 133 | 135 |
bool _absoluteNodeSizes; |
| 134 | 136 |
bool _absoluteArcWidths; |
| 135 | 137 |
|
| 136 | 138 |
bool _negY; |
| 137 | 139 |
|
| 138 | 140 |
bool _preScale; |
| 139 | 141 |
///Constructor |
| 140 | 142 |
|
| 141 | 143 |
///Constructor |
| 142 | 144 |
///\param _g is a reference to the graph to be printed |
| 143 | 145 |
///\param _os is a reference to the output stream. |
| 144 | 146 |
///\param _os is a reference to the output stream. |
| 145 | 147 |
///\param _pros If it is \c true, then the \c ostream referenced by \c _os |
| 146 | 148 |
///will be explicitly deallocated by the destructor. |
| 147 | 149 |
///By default it is <tt>std::cout</tt> |
| 148 | 150 |
DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, |
| 149 | 151 |
bool _pros=false) : |
| 150 | 152 |
g(_g), os(_os), |
| 151 | 153 |
_coords(dim2::Point<double>(1,1)), _nodeSizes(.01), _nodeShapes(0), |
| 152 | 154 |
_nodeColors(WHITE), _arcColors(BLACK), |
| 153 | 155 |
_arcWidths(1.0), _arcWidthScale(0.003), |
| 154 | 156 |
_nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
| 155 | 157 |
_nodeBorderQuotient(.1), |
| 156 | 158 |
_drawArrows(false), _arrowLength(1), _arrowWidth(0.3), |
| 157 | 159 |
_showNodes(true), _showArcs(true), |
| 158 | 160 |
_enableParallel(false), _parArcDist(1), |
| 159 | 161 |
_showNodeText(false), _nodeTexts(false), _nodeTextSize(1), |
| 160 | 162 |
_showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0), |
| 161 |
_undirected( |
|
| 163 |
_undirected(lemon::UndirectedTagIndicator<G>::value), |
|
| 162 | 164 |
_pleaseRemoveOsStream(_pros), _scaleToA4(false), |
| 163 | 165 |
_nodeTextColorType(SAME_COL), _nodeTextColors(BLACK), |
| 164 | 166 |
_autoNodeScale(false), |
| 165 | 167 |
_autoArcWidthScale(false), |
| 166 | 168 |
_absoluteNodeSizes(false), |
| 167 | 169 |
_absoluteArcWidths(false), |
| 168 | 170 |
_negY(false), |
| 169 | 171 |
_preScale(true) |
| 170 | 172 |
{}
|
| 171 | 173 |
}; |
| 172 | 174 |
|
| 173 | 175 |
///Helper class to implement the named parameters of \ref graphToEps() |
| 174 | 176 |
|
| 175 | 177 |
///Helper class to implement the named parameters of \ref graphToEps() |
| 176 | 178 |
///\todo Is 'helper class' a good name for this? |
| 177 | 179 |
/// |
| 178 | 180 |
///\todo Follow PostScript's DSC. |
| 179 | 181 |
/// Use own dictionary. |
| 180 | 182 |
///\todo Useful new features. |
| 181 | 183 |
/// - Linestyles: dotted, dashed etc. |
| 182 | 184 |
/// - A second color and percent value for the lines. |
| 183 | 185 |
template<class T> class GraphToEps : public T |
| 184 | 186 |
{
|
| 185 | 187 |
// Can't believe it is required by the C++ standard |
| 186 | 188 |
using T::g; |
| 187 | 189 |
using T::os; |
| 188 | 190 |
|
| 189 | 191 |
using T::_coords; |
| 190 | 192 |
using T::_nodeSizes; |
| 191 | 193 |
using T::_nodeShapes; |
| 192 | 194 |
using T::_nodeColors; |
| 193 | 195 |
using T::_arcColors; |
| ... | ... |
@@ -639,111 +641,112 @@ |
| 639 | 641 |
///Sets the color of the node texts to be as different from the node color |
| 640 | 642 |
///as it is possible |
| 641 | 643 |
/// |
| 642 | 644 |
GraphToEps<T> &distantColorNodeTexts() |
| 643 | 645 |
{_nodeTextColorType=DIST_COL;return *this;}
|
| 644 | 646 |
///Sets the color of the node texts to be black or white and always visible. |
| 645 | 647 |
|
| 646 | 648 |
///Sets the color of the node texts to be black or white according to |
| 647 | 649 |
///which is more |
| 648 | 650 |
///different from the node color |
| 649 | 651 |
/// |
| 650 | 652 |
GraphToEps<T> &distantBWNodeTexts() |
| 651 | 653 |
{_nodeTextColorType=DIST_BW;return *this;}
|
| 652 | 654 |
|
| 653 | 655 |
///Gives a preamble block for node Postscript block. |
| 654 | 656 |
|
| 655 | 657 |
///Gives a preamble block for node Postscript block. |
| 656 | 658 |
/// |
| 657 | 659 |
///\sa nodePsTexts() |
| 658 | 660 |
GraphToEps<T> & nodePsTextsPreamble(const char *str) {
|
| 659 | 661 |
_nodePsTextsPreamble=str ;return *this; |
| 660 | 662 |
} |
| 661 | 663 |
///Sets whether the the graph is undirected |
| 662 | 664 |
|
| 663 | 665 |
///Sets whether the the graph is undirected |
| 664 | 666 |
/// |
| 665 | 667 |
GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
|
| 666 | 668 |
|
| 667 | 669 |
///Sets whether the the graph is directed |
| 668 | 670 |
|
| 669 | 671 |
///Sets whether the the graph is directed. |
| 670 | 672 |
///Use it to show the edges as a pair of directed ones. |
| 671 |
GraphToEps<T> & |
|
| 673 |
GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
|
|
| 672 | 674 |
|
| 673 | 675 |
///Sets the title. |
| 674 | 676 |
|
| 675 | 677 |
///Sets the title of the generated image, |
| 676 | 678 |
///namely it inserts a <tt>%%Title:</tt> DSC field to the header of |
| 677 | 679 |
///the EPS file. |
| 678 | 680 |
GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
|
| 679 | 681 |
///Sets the copyright statement. |
| 680 | 682 |
|
| 681 | 683 |
///Sets the copyright statement of the generated image, |
| 682 | 684 |
///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of |
| 683 | 685 |
///the EPS file. |
| 684 | 686 |
///\todo Multiline copyright notice could be supported. |
| 685 | 687 |
GraphToEps<T> ©right(const std::string &t) {_copyright=t;return *this;}
|
| 686 | 688 |
|
| 687 | 689 |
protected: |
| 688 | 690 |
bool isInsideNode(dim2::Point<double> p, double r,int t) |
| 689 | 691 |
{
|
| 690 | 692 |
switch(t) {
|
| 691 | 693 |
case CIRCLE: |
| 692 | 694 |
case MALE: |
| 693 | 695 |
case FEMALE: |
| 694 | 696 |
return p.normSquare()<=r*r; |
| 695 | 697 |
case SQUARE: |
| 696 | 698 |
return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r; |
| 697 | 699 |
case DIAMOND: |
| 698 | 700 |
return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r; |
| 699 | 701 |
} |
| 700 | 702 |
return false; |
| 701 | 703 |
} |
| 702 | 704 |
|
| 703 | 705 |
public: |
| 704 | 706 |
~GraphToEps() { }
|
| 705 | 707 |
|
| 706 | 708 |
///Draws the graph. |
| 707 | 709 |
|
| 708 | 710 |
///Like other functions using |
| 709 | 711 |
///\ref named-templ-func-param "named template parameters", |
| 710 | 712 |
///this function calles the algorithm itself, i.e. in this case |
| 711 | 713 |
///it draws the graph. |
| 712 | 714 |
void run() {
|
| 713 | 715 |
///\todo better 'epsilon' would be nice here. |
| 714 | 716 |
const double EPSILON=1e-9; |
| 715 | 717 |
if(dontPrint) return; |
| 716 | 718 |
|
| 717 |
_NegY<typename T::CoordsMapType> |
|
| 719 |
_graph_to_eps_bits::_NegY<typename T::CoordsMapType> |
|
| 720 |
mycoords(_coords,_negY); |
|
| 718 | 721 |
|
| 719 | 722 |
os << "%!PS-Adobe-2.0 EPSF-2.0\n"; |
| 720 | 723 |
if(_title.size()>0) os << "%%Title: " << _title << '\n'; |
| 721 | 724 |
if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n'; |
| 722 | 725 |
// << "%%Copyright: XXXX\n" |
| 723 | 726 |
os << "%%Creator: LEMON, graphToEps()\n"; |
| 724 | 727 |
|
| 725 | 728 |
{
|
| 726 | 729 |
char cbuf[50]; |
| 727 | 730 |
timeval tv; |
| 728 | 731 |
gettimeofday(&tv, 0); |
| 729 | 732 |
ctime_r(&tv.tv_sec,cbuf); |
| 730 | 733 |
os << "%%CreationDate: " << cbuf; |
| 731 | 734 |
} |
| 732 | 735 |
|
| 733 | 736 |
if (_autoArcWidthScale) {
|
| 734 | 737 |
double max_w=0; |
| 735 | 738 |
for(ArcIt e(g);e!=INVALID;++e) |
| 736 | 739 |
max_w=std::max(double(_arcWidths[e]),max_w); |
| 737 | 740 |
///\todo better 'epsilon' would be nice here. |
| 738 | 741 |
if(max_w>EPSILON) {
|
| 739 | 742 |
_arcWidthScale/=max_w; |
| 740 | 743 |
} |
| 741 | 744 |
} |
| 742 | 745 |
|
| 743 | 746 |
if (_autoNodeScale) {
|
| 744 | 747 |
double max_s=0; |
| 745 | 748 |
for(NodeIt n(g);n!=INVALID;++n) |
| 746 | 749 |
max_s=std::max(double(_nodeSizes[n]),max_s); |
| 747 | 750 |
///\todo better 'epsilon' would be nice here. |
| 748 | 751 |
if(max_s>EPSILON) {
|
| 749 | 752 |
_nodeScale/=max_s; |
0 comments (0 inline)