src/work/alpar/graph_to_eps.cc
author alpar
Tue, 04 Jan 2005 17:07:05 +0000
changeset 1046 1bb1d4c87331
child 1047 a6094968ed09
permissions -rw-r--r--
An experimental graph-to-eps exporter.
alpar@1046
     1
#include<lemon/xy.h>
alpar@1046
     2
#include<lemon/maps.h>
alpar@1046
     3
#include<lemon/list_graph.h>
alpar@1046
     4
alpar@1046
     5
///\file
alpar@1046
     6
///Simple graph drawer
alpar@1046
     7
alpar@1046
     8
namespace lemon {
alpar@1046
     9
alpar@1046
    10
  ///\e
alpar@1046
    11
class Color
alpar@1046
    12
{
alpar@1046
    13
  double _r,_g,_b;
alpar@1046
    14
public:
alpar@1046
    15
  ///\e
alpar@1046
    16
  Color() {}
alpar@1046
    17
  ///\e
alpar@1046
    18
  Color(double r,double g,double b) :_r(r),_g(g),_b(b) {};
alpar@1046
    19
  ///\e
alpar@1046
    20
  double getR() {return _r;}
alpar@1046
    21
  ///\e
alpar@1046
    22
  double getG() {return _g;}
alpar@1046
    23
  ///\e
alpar@1046
    24
  double getB() {return _b;}
alpar@1046
    25
  ///\e
alpar@1046
    26
  void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
alpar@1046
    27
};
alpar@1046
    28
  
alpar@1046
    29
  ///\e
alpar@1046
    30
template<class G>
alpar@1046
    31
struct DefaultGraphToEpsTraits
alpar@1046
    32
{
alpar@1046
    33
  typedef G Graph;
alpar@1046
    34
  typedef typename Graph::Node Node;
alpar@1046
    35
  typedef typename Graph::NodeIt NodeIt;
alpar@1046
    36
  typedef typename Graph::Edge Edge;
alpar@1046
    37
  typedef typename Graph::EdgeIt EdgeIt;
alpar@1046
    38
  typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1046
    39
  typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1046
    40
  
alpar@1046
    41
alpar@1046
    42
  const Graph &g;
alpar@1046
    43
  ConstMap<typename Graph::Node,xy<double> > coords;
alpar@1046
    44
  ConstMap<typename Graph::Node,double > nodeSizes;
alpar@1046
    45
alpar@1046
    46
  ConstMap<typename Graph::Node,Color > nodeColors;
alpar@1046
    47
  ConstMap<typename Graph::Edge,Color > edgeColors;
alpar@1046
    48
  double nodeSizeScalar;
alpar@1046
    49
  double xBorder, yBorder;
alpar@1046
    50
    
alpar@1046
    51
  DefaultGraphToEpsTraits(G &_g) :
alpar@1046
    52
    g(_g), coords(xy<double>(1,1)), nodeSizes(1.0),
alpar@1046
    53
    nodeColors(Color(1,1,1)), edgeColors(Color(0,0,0)),
alpar@1046
    54
    nodeSizeScalar(1.0), xBorder(10), yBorder(10) {}
alpar@1046
    55
};
alpar@1046
    56
alpar@1046
    57
  ///\e
alpar@1046
    58
template<class T> class GraphToEps : public T 
alpar@1046
    59
{
alpar@1046
    60
  typedef typename T::Graph Graph;
alpar@1046
    61
  typedef typename Graph::Node Node;
alpar@1046
    62
  typedef typename Graph::NodeIt NodeIt;
alpar@1046
    63
  typedef typename Graph::Edge Edge;
alpar@1046
    64
  typedef typename Graph::EdgeIt EdgeIt;
alpar@1046
    65
  typedef typename Graph::InEdgeIt InEdgeIt;
alpar@1046
    66
  typedef typename Graph::OutEdgeIt OutEdgeIt;
alpar@1046
    67
alpar@1046
    68
  bool dontPrint;
alpar@1046
    69
alpar@1046
    70
public:
alpar@1046
    71
  GraphToEps(const T &t) : T(t), dontPrint(false) {};
alpar@1046
    72
  
alpar@1046
    73
  template<class X> struct SetCoordsTraits : public T {
alpar@1046
    74
    const X &coords;
alpar@1046
    75
    SetCoordsTraits(const T &t,const X &x) : T(t), coords(x) {}
alpar@1046
    76
  };
alpar@1046
    77
  ///\e
alpar@1046
    78
  template<class X> GraphToEps<SetCoordsTraits<X> > setCoords(const X &x) {
alpar@1046
    79
    dontPrint=true;
alpar@1046
    80
    return GraphToEps<SetCoordsTraits<X> >(SetCoordsTraits<X>(*this,x));
alpar@1046
    81
  }
alpar@1046
    82
  template<class X> struct SetNodeSizesTraits : public T {
alpar@1046
    83
    const X &nodeSizes;
alpar@1046
    84
    SetNodeSizesTraits(const T &t,const X &x) : T(t), nodeSizes(x) {}
alpar@1046
    85
  };
alpar@1046
    86
  ///\e
alpar@1046
    87
  template<class X> GraphToEps<SetNodeSizesTraits<X> > setNodeSizes(const X &x)
alpar@1046
    88
  {
alpar@1046
    89
    dontPrint=true;
alpar@1046
    90
    return GraphToEps<SetNodeSizesTraits<X> >(SetNodeSizesTraits<X>(*this,x));
alpar@1046
    91
  }
alpar@1046
    92
  template<class X> struct SetNodeColorsTraits : public T {
alpar@1046
    93
    const X &nodeColors;
alpar@1046
    94
    SetNodeColorsTraits(const T &t,const X &x) : T(t), nodeColors(x) {}
alpar@1046
    95
  };
alpar@1046
    96
  ///\e
alpar@1046
    97
  template<class X> GraphToEps<SetNodeColorsTraits<X> >
alpar@1046
    98
  setNodeColors(const X &x)
alpar@1046
    99
  {
alpar@1046
   100
    dontPrint=true;
alpar@1046
   101
    return GraphToEps<SetNodeColorsTraits<X> >(SetNodeColorsTraits<X>(*this,x));
alpar@1046
   102
  }
alpar@1046
   103
  template<class X> struct SetEdgeColorsTraits : public T {
alpar@1046
   104
    const X &edgeColors;
alpar@1046
   105
    SetEdgeColorsTraits(const T &t,const X &x) : T(t), edgeColors(x) {}
alpar@1046
   106
  };
alpar@1046
   107
  ///\e
alpar@1046
   108
  template<class X> GraphToEps<SetEdgeColorsTraits<X> >
alpar@1046
   109
  setEdgeColors(const X &x)
alpar@1046
   110
  {
alpar@1046
   111
    dontPrint=true;
alpar@1046
   112
    return GraphToEps<SetEdgeColorsTraits<X> >(SetEdgeColorsTraits<X>(*this,x));
alpar@1046
   113
  }
alpar@1046
   114
  ///\e
alpar@1046
   115
  GraphToEps<T> &scaleNodeSize(double d) {nodeSizeScalar=d;return *this;}
alpar@1046
   116
  
alpar@1046
   117
  ~GraphToEps() 
alpar@1046
   118
  {
alpar@1046
   119
    if(dontPrint) return;
alpar@1046
   120
    
alpar@1046
   121
    cout << "%!PS-Adobe-2.0 EPSF-2.0\n";
alpar@1046
   122
    //\todo: Chech whether the graph is empty.
alpar@1046
   123
    BoundingBox<double> bb;
alpar@1046
   124
    for(NodeIt n(g);
alpar@1046
   125
	n!=INVALID;
alpar@1046
   126
	++n) {
alpar@1046
   127
      xy<double> p(nodeSizes[n]*nodeSizeScalar,nodeSizes[n]*nodeSizeScalar);
alpar@1046
   128
      bb+=coords[n]+p;
alpar@1046
   129
      bb+=coords[n]-p;
alpar@1046
   130
      }
alpar@1046
   131
    cout << "%%BoundingBox: "
alpar@1046
   132
	 << bb.left()-xBorder << ' ' << bb.bottom()-yBorder << ' '
alpar@1046
   133
	 << bb.right()+xBorder << ' ' << bb.top()+yBorder << '\n';
alpar@1046
   134
    //x1 y1 x2 y2 cr cg cb
alpar@1046
   135
    cout << "/l { setrgbcolor newpath moveto lineto stroke } bind def\n";
alpar@1046
   136
    cout << "/c { newpath dup 3 index add 2 index moveto 0 360 arc } bind def\n";
alpar@1046
   137
    // x y r cr cg cb
alpar@1046
   138
    cout << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
alpar@1046
   139
	 << "     0 0 0 setrgbcolor dup 10 div setlinewidth c stroke\n"
alpar@1046
   140
	 << "   } bind def\n";
alpar@1046
   141
    
alpar@1046
   142
    cout << "%Edges:\ngsave\n";
alpar@1046
   143
    for(NodeIt n(g);n!=INVALID;++n)
alpar@1046
   144
      for(OutEdgeIt e(g,n);e!=INVALID;++e)
alpar@1046
   145
	cout << coords[g.source(e)].x << ' ' << coords[g.source(e)].y << ' '
alpar@1046
   146
	     << coords[g.target(e)].x << ' ' << coords[g.target(e)].y << ' '
alpar@1046
   147
	     << edgeColors[e].getR() << ' '
alpar@1046
   148
	     << edgeColors[e].getG() << ' '
alpar@1046
   149
	     << edgeColors[e].getB() << " l\n";
alpar@1046
   150
    cout << "grestore\n%Nodes:\ngsave\n";
alpar@1046
   151
    for(NodeIt n(g);n!=INVALID;++n)
alpar@1046
   152
      cout << coords[n].x << ' ' << coords[n].y << ' '
alpar@1046
   153
	   << nodeSizes[n]*nodeSizeScalar << ' '
alpar@1046
   154
	   << nodeColors[n].getR() << ' '
alpar@1046
   155
	   << nodeColors[n].getG() << ' '
alpar@1046
   156
	   << nodeColors[n].getB() << " n\n"; 
alpar@1046
   157
    cout << "grestore\n";
alpar@1046
   158
  } 
alpar@1046
   159
};
alpar@1046
   160
alpar@1046
   161
alpar@1046
   162
template<class G>
alpar@1046
   163
GraphToEps<DefaultGraphToEpsTraits<G> > graphToEps(G &g)
alpar@1046
   164
{
alpar@1046
   165
  return GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g));
alpar@1046
   166
}
alpar@1046
   167
 
alpar@1046
   168
}
alpar@1046
   169
alpar@1046
   170
using namespace lemon;
alpar@1046
   171
alpar@1046
   172
class ColorSet : public MapBase<int,Color>
alpar@1046
   173
{
alpar@1046
   174
public:
alpar@1046
   175
  Color operator[](int i) const
alpar@1046
   176
  {
alpar@1046
   177
    switch(i%8){
alpar@1046
   178
    case 0: return Color(0,0,0);
alpar@1046
   179
    case 1: return Color(1,0,0);
alpar@1046
   180
    case 2: return Color(0,1,0);
alpar@1046
   181
    case 3: return Color(0,0,1);
alpar@1046
   182
    case 4: return Color(1,1,0);
alpar@1046
   183
    case 5: return Color(1,0,1);
alpar@1046
   184
    case 6: return Color(0,1,1);
alpar@1046
   185
    case 7: return Color(1,1,1);
alpar@1046
   186
    }
alpar@1046
   187
    return Color(0,0,0);
alpar@1046
   188
  }
alpar@1046
   189
} colorSet;
alpar@1046
   190
alpar@1046
   191
int main()
alpar@1046
   192
{
alpar@1046
   193
  ListGraph g;
alpar@1046
   194
  typedef ListGraph::Node Node;
alpar@1046
   195
  typedef ListGraph::NodeIt NodeIt;
alpar@1046
   196
  typedef ListGraph::Edge Edge;
alpar@1046
   197
  typedef xy<double> Xy;
alpar@1046
   198
  
alpar@1046
   199
  Node n1=g.addNode();
alpar@1046
   200
  Node n2=g.addNode();
alpar@1046
   201
  Node n3=g.addNode();
alpar@1046
   202
  Node n4=g.addNode();
alpar@1046
   203
  Node n5=g.addNode();
alpar@1046
   204
alpar@1046
   205
  ListGraph::NodeMap<Xy> coords(g);
alpar@1046
   206
  ListGraph::NodeMap<double> sizes(g);
alpar@1046
   207
  ListGraph::NodeMap<int> colors(g);
alpar@1046
   208
  ListGraph::EdgeMap<int> ecolors(g,0);
alpar@1046
   209
  
alpar@1046
   210
  coords[n1]=Xy(50,50);  sizes[n1]=1; colors[n1]=1;
alpar@1046
   211
  coords[n2]=Xy(50,70);  sizes[n2]=2; colors[n2]=2;
alpar@1046
   212
  coords[n3]=Xy(70,70);  sizes[n3]=1; colors[n3]=3;
alpar@1046
   213
  coords[n4]=Xy(70,50);  sizes[n4]=2; colors[n4]=4;
alpar@1046
   214
  coords[n5]=Xy(85,60);  sizes[n5]=3; colors[n5]=5;
alpar@1046
   215
  
alpar@1046
   216
  Edge e;
alpar@1046
   217
alpar@1046
   218
  e=g.addEdge(n1,n2);
alpar@1046
   219
  e=g.addEdge(n2,n3);
alpar@1046
   220
  e=g.addEdge(n3,n5);
alpar@1046
   221
  e=g.addEdge(n5,n4);
alpar@1046
   222
  e=g.addEdge(n4,n1);
alpar@1046
   223
  e=g.addEdge(n2,n4); ecolors[e]=1;
alpar@1046
   224
  e=g.addEdge(n3,n4); ecolors[e]=2;
alpar@1046
   225
  
alpar@1046
   226
  graphToEps(g).setCoords(coords).
alpar@1046
   227
    scaleNodeSize(2).setNodeSizes(sizes).
alpar@1046
   228
    setNodeColors(composeMap(colorSet,colors)).
alpar@1046
   229
    setEdgeColors(composeMap(colorSet,ecolors));
alpar@1046
   230
}