src/lemon/graph_to_eps.h
changeset 1086 caa13d291528
parent 1085 5b7ca75297b5
child 1087 d496d1d5a5e7
     1.1 --- a/src/lemon/graph_to_eps.h	Sun Jan 16 22:34:51 2005 +0000
     1.2 +++ b/src/lemon/graph_to_eps.h	Tue Jan 18 12:02:27 2005 +0000
     1.3 @@ -80,6 +80,7 @@
     1.4    
     1.5    ConstMap<typename Graph::Node,xy<double> > _coords;
     1.6    ConstMap<typename Graph::Node,double > _nodeSizes;
     1.7 +  ConstMap<typename Graph::Node,int > _nodeShapes;
     1.8  
     1.9    ConstMap<typename Graph::Node,Color > _nodeColors;
    1.10    ConstMap<typename Graph::Edge,Color > _edgeColors;
    1.11 @@ -123,7 +124,7 @@
    1.12    DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout,
    1.13  			  bool _pros=false) :
    1.14      g(_g), os(_os),
    1.15 -    _coords(xy<double>(1,1)), _nodeSizes(1.0),
    1.16 +    _coords(xy<double>(1,1)), _nodeSizes(1.0), _nodeShapes(0),
    1.17      _nodeColors(Color(1,1,1)), _edgeColors(Color(0,0,0)),
    1.18      _edgeWidths(1), _edgeWidthScale(0.3),
    1.19      _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0),
    1.20 @@ -154,6 +155,8 @@
    1.21  
    1.22    bool dontPrint;
    1.23  
    1.24 +  enum NodeShapes { CIRCLE=0, SQUARE=1 };
    1.25 +		   
    1.26    class edgeLess {
    1.27      const Graph &g;
    1.28    public:
    1.29 @@ -214,6 +217,20 @@
    1.30      dontPrint=true;
    1.31      return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x));
    1.32    }
    1.33 +  template<class X> struct NodeShapesTraits : public T {
    1.34 +    const X &_nodeShapes;
    1.35 +    NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
    1.36 +  };
    1.37 +  ///Sets the map of the node shapes
    1.38 +
    1.39 +  ///Sets the map of the node shapes
    1.40 +  ///\param x must be a node map with \c int (or convertible) values. 
    1.41 +  ///\todo Incomplete doc.
    1.42 +  template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x)
    1.43 +  {
    1.44 +    dontPrint=true;
    1.45 +    return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x));
    1.46 +  }
    1.47    template<class X> struct NodeTextsTraits : public T {
    1.48      const X &_nodeTexts;
    1.49      NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
    1.50 @@ -386,7 +403,20 @@
    1.51    ///Sets whether the the graph is directed.
    1.52    ///Use it to show the undirected edges as a pair of directed ones.
    1.53    GraphToEps<T> &bidir(bool b=true) {_undir=!b;return *this;}
    1.54 -  
    1.55 +
    1.56 +protected:
    1.57 +  bool isInsideNode(xy<double> p, double r,int t) 
    1.58 +  {
    1.59 +    switch(t) {
    1.60 +    case CIRCLE:
    1.61 +      return p.normSquare()<=r*r;
    1.62 +    case SQUARE:
    1.63 +      return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r;
    1.64 +    }
    1.65 +    return false;
    1.66 +  }
    1.67 +
    1.68 +public:
    1.69    ~GraphToEps() 
    1.70    {
    1.71      if(dontPrint) return;
    1.72 @@ -409,13 +439,25 @@
    1.73      os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
    1.74         << "      4 2 roll 1 index 1 index curveto stroke } bind def\n";
    1.75      os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
    1.76 +    //x y r
    1.77      os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
    1.78 +    //x y r
    1.79 +    os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
    1.80 +       << "      2 index 1 index sub 2 index 2 index add lineto\n"
    1.81 +       << "      2 index 1 index sub 2 index 2 index sub lineto\n"
    1.82 +       << "      2 index 1 index add 2 index 2 index sub lineto\n"
    1.83 +       << "      closepath pop pop pop} bind def\n";
    1.84      // x y r cr cg cb
    1.85 -    os << "/n { setrgbcolor 2 index 2 index 2 index c fill\n"
    1.86 +    os << "/nc { setrgbcolor 2 index 2 index 2 index c fill\n"
    1.87         << "     0 0 0 setrgbcolor dup "
    1.88         << _nodeBorderQuotient << " mul setlinewidth "
    1.89         << 1+_nodeBorderQuotient/2 << " div c stroke\n"
    1.90         << "   } bind def\n";
    1.91 +    os << "/nsq { setrgbcolor 2 index 2 index 2 index sq fill\n"
    1.92 +       << "     0 0 0 setrgbcolor dup "
    1.93 +       << _nodeBorderQuotient << " mul setlinewidth "
    1.94 +       << 1+_nodeBorderQuotient/2 << " div sq stroke\n"
    1.95 +       << "   } bind def\n";
    1.96      os << "/arrl " << _arrowLength << " def\n";
    1.97      os << "/arrw " << _arrowWidth << " def\n";
    1.98      // l dx_norm dy_norm
    1.99 @@ -474,32 +516,33 @@
   1.100  	    sw+=_edgeWidths[*e]*_edgeWidthScale/2.0;
   1.101  	    xy<double> mm=m+rot(d)*sw/.75;
   1.102  	    if(_drawArrows) {
   1.103 +	      int node_shape;
   1.104  	      const int INERPOL_PREC=20;
   1.105  	      xy<double> s=_coords[g.source(*e)];
   1.106  	      xy<double> t=_coords[g.target(*e)];
   1.107  	      double rn=_nodeSizes[g.target(*e)]*_nodeScale;
   1.108 -	      rn*=rn;
   1.109 +	      node_shape=_nodeShapes[g.target(*e)];
   1.110  	      Bezier3 bez(s,mm,mm,t);
   1.111  	      double t1=0,t2=1;
   1.112  	      for(int i=0;i<INERPOL_PREC;++i)
   1.113 -		if((bez((t1+t2)/2)-t).normSquare()>rn) t1=(t1+t2)/2;
   1.114 -		else t2=(t1+t2)/2;
   1.115 +		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2;
   1.116 +		else t1=(t1+t2)/2;
   1.117  	      xy<double> apoint=bez((t1+t2)/2);
   1.118 -	      rn = _nodeSizes[g.target(*e)]*_nodeScale+_arrowLength+
   1.119 -		_edgeWidths[*e]*_edgeWidthScale;
   1.120 +	      rn = _arrowLength+_edgeWidths[*e]*_edgeWidthScale;
   1.121  	      rn*=rn;
   1.122 -	      t1=0;t2=1;
   1.123 +	      t2=(t1+t2)/2;t1=0;
   1.124  	      for(int i=0;i<INERPOL_PREC;++i)
   1.125 -		if((bez((t1+t2)/2)-t).normSquare()>rn) t1=(t1+t2)/2;
   1.126 +		if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2;
   1.127  		else t2=(t1+t2)/2;
   1.128  	      xy<double> linend=bez((t1+t2)/2);	      
   1.129  	      bez=bez.before((t1+t2)/2);
   1.130 -	      rn=_nodeSizes[g.source(*e)]*_nodeScale; rn*=rn;
   1.131 -	      t1=0;t2=1;
   1.132 -	      for(int i=0;i<INERPOL_PREC;++i)
   1.133 -		if((bez((t1+t2)/2)-s).normSquare()>rn) t2=(t1+t2)/2;
   1.134 -		else t1=(t1+t2)/2;
   1.135 -	      bez=bez.after((t1+t2)/2);
   1.136 +// 	      rn=_nodeSizes[g.source(*e)]*_nodeScale;
   1.137 +// 	      node_shape=_nodeShapes[g.source(*e)];
   1.138 +// 	      t1=0;t2=1;
   1.139 +// 	      for(int i=0;i<INERPOL_PREC;++i)
   1.140 +// 		if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2;
   1.141 +// 		else t2=(t1+t2)/2;
   1.142 +// 	      bez=bez.after((t1+t2)/2);
   1.143  	      os << _edgeWidths[*e]*_edgeWidthScale << " setlinewidth "
   1.144  		 << _edgeColors[*e].getR() << ' '
   1.145  		 << _edgeColors[*e].getG() << ' '
   1.146 @@ -559,12 +602,20 @@
   1.147      }
   1.148      if(_showNodes) {
   1.149        os << "%Nodes:\ngsave\n";
   1.150 -      for(NodeIt n(g);n!=INVALID;++n)
   1.151 +      for(NodeIt n(g);n!=INVALID;++n) {
   1.152  	os << _coords[n].x << ' ' << _coords[n].y << ' '
   1.153  	   << _nodeSizes[n]*_nodeScale << ' '
   1.154  	   << _nodeColors[n].getR() << ' '
   1.155  	   << _nodeColors[n].getG() << ' '
   1.156 -	   << _nodeColors[n].getB() << " n\n";
   1.157 +	   << _nodeColors[n].getB() << ' ';
   1.158 +	switch(_nodeShapes[n]) {
   1.159 +	case CIRCLE:
   1.160 +	  os<< "nc";break;
   1.161 +	case SQUARE:
   1.162 +	  os<< "nsq";break;
   1.163 +	}
   1.164 +	os<<'\n';
   1.165 +      }
   1.166        os << "grestore\n";
   1.167      }
   1.168      if(_showNodeText) {