36 |
36 |
37 #include<lemon/bits/invalid.h> |
37 #include<lemon/bits/invalid.h> |
38 #include<lemon/xy.h> |
38 #include<lemon/xy.h> |
39 #include<lemon/maps.h> |
39 #include<lemon/maps.h> |
40 #include<lemon/color.h> |
40 #include<lemon/color.h> |
41 #include<lemon/bezier.h> |
41 #include<lemon/bits/bezier.h> |
42 |
42 |
43 |
43 |
44 ///\ingroup eps_io |
44 ///\ingroup eps_io |
45 ///\file |
45 ///\file |
46 ///\brief Simple graph drawer |
46 ///\brief Simple graph drawer |
141 ///will be explicitly deallocated by the destructor. |
144 ///will be explicitly deallocated by the destructor. |
142 ///By default it is <tt>std::cout</tt> |
145 ///By default it is <tt>std::cout</tt> |
143 DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, |
146 DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, |
144 bool _pros=false) : |
147 bool _pros=false) : |
145 g(_g), os(_os), |
148 g(_g), os(_os), |
146 _coords(xy<double>(1,1)), _nodeSizes(1.0), _nodeShapes(0), |
149 _coords(xy<double>(1,1)), _nodeSizes(.01), _nodeShapes(0), |
147 _nodeColors(WHITE), _edgeColors(BLACK), |
150 _nodeColors(WHITE), _edgeColors(BLACK), |
148 _edgeWidths(1), _edgeWidthScale(0.3), |
151 _edgeWidths(1.0), _edgeWidthScale(0.003), |
149 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
152 _nodeScale(1.0), _xBorder(10), _yBorder(10), _scale(1.0), |
150 _nodeBorderQuotient(.1), |
153 _nodeBorderQuotient(.1), |
151 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), |
154 _drawArrows(false), _arrowLength(1), _arrowWidth(0.3), |
152 _showNodes(true), _showEdges(true), |
155 _showNodes(true), _showEdges(true), |
153 _enableParallel(false), _parEdgeDist(1), |
156 _enableParallel(false), _parEdgeDist(1), |
156 _undirected(false), |
159 _undirected(false), |
157 _pleaseRemoveOsStream(_pros), _scaleToA4(false), |
160 _pleaseRemoveOsStream(_pros), _scaleToA4(false), |
158 _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK), |
161 _nodeTextColorType(SAME_COL), _nodeTextColors(BLACK), |
159 _autoNodeScale(false), |
162 _autoNodeScale(false), |
160 _autoEdgeWidthScale(false), |
163 _autoEdgeWidthScale(false), |
|
164 _absoluteNodeSizes(false), |
|
165 _absoluteEdgeWidths(false), |
161 _negY(false) |
166 _negY(false) |
162 {} |
167 {} |
163 }; |
168 }; |
164 |
169 |
165 ///Helper class to implement the named parameters of \ref graphToEps() |
170 ///Helper class to implement the named parameters of \ref graphToEps() |
226 using T::_nodeTextColorType; |
231 using T::_nodeTextColorType; |
227 using T::_nodeTextColors; |
232 using T::_nodeTextColors; |
228 |
233 |
229 using T::_autoNodeScale; |
234 using T::_autoNodeScale; |
230 using T::_autoEdgeWidthScale; |
235 using T::_autoEdgeWidthScale; |
|
236 |
|
237 using T::_absoluteNodeSizes; |
|
238 using T::_absoluteEdgeWidths; |
|
239 |
231 |
240 |
232 using T::_negY; |
241 using T::_negY; |
233 |
242 |
234 // dradnats ++C eht yb deriuqer si ti eveileb t'naC |
243 // dradnats ++C eht yb deriuqer si ti eveileb t'naC |
235 |
244 |
476 /// autoNodeScale() is not, then the node size given by |
485 /// autoNodeScale() is not, then the node size given by |
477 /// nodeSizes() will be multiplied by the value \c d. |
486 /// nodeSizes() will be multiplied by the value \c d. |
478 /// If both nodeSizes() and autoNodeScale() are used, then the |
487 /// If both nodeSizes() and autoNodeScale() are used, then the |
479 /// node sizes will be scaled in such a way that the greatest size will be |
488 /// node sizes will be scaled in such a way that the greatest size will be |
480 /// equal to \c d. |
489 /// equal to \c d. |
|
490 /// \sa nodeSizes() |
|
491 /// \sa autoNodeScale() |
481 GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;} |
492 GraphToEps<T> &nodeScale(double d) {_nodeScale=d;return *this;} |
482 ///Turns on/off the automatic node width scaling. |
493 ///Turns on/off the automatic node width scaling. |
483 |
494 |
484 ///Turns on/off the automatic node width scaling. |
495 ///Turns on/off the automatic node width scaling. |
485 /// |
496 /// |
486 ///\sa nodeScale() |
497 ///\sa nodeScale() |
487 /// |
498 /// |
488 GraphToEps<T> &autoNodeScale(bool b=true) { |
499 GraphToEps<T> &autoNodeScale(bool b=true) { |
489 _autoNodeScale=b;return *this; |
500 _autoNodeScale=b;return *this; |
|
501 } |
|
502 |
|
503 ///Turns on/off the absolutematic node width scaling. |
|
504 |
|
505 ///Turns on/off the absolutematic node width scaling. |
|
506 /// |
|
507 ///\sa nodeScale() |
|
508 /// |
|
509 GraphToEps<T> &absoluteNodeSizes(bool b=true) { |
|
510 _absoluteNodeSizes=b;return *this; |
490 } |
511 } |
491 |
512 |
492 ///Negates the Y coordinates. |
513 ///Negates the Y coordinates. |
493 |
514 |
494 ///Negates the Y coordinates. |
515 ///Negates the Y coordinates. |
517 /// |
538 /// |
518 ///\sa edgeWidthScale() |
539 ///\sa edgeWidthScale() |
519 /// |
540 /// |
520 GraphToEps<T> &autoEdgeWidthScale(bool b=true) { |
541 GraphToEps<T> &autoEdgeWidthScale(bool b=true) { |
521 _autoEdgeWidthScale=b;return *this; |
542 _autoEdgeWidthScale=b;return *this; |
|
543 } |
|
544 ///Turns on/off the absolutematic edge width scaling. |
|
545 |
|
546 ///Turns on/off the absolutematic edge width scaling. |
|
547 /// |
|
548 ///\sa edgeWidthScale() |
|
549 /// |
|
550 GraphToEps<T> &absoluteEdgeWidths(bool b=true) { |
|
551 _absoluteEdgeWidths=b;return *this; |
522 } |
552 } |
523 ///Sets a global scale factor for the whole picture |
553 ///Sets a global scale factor for the whole picture |
524 |
554 |
525 ///Sets a global scale factor for the whole picture |
555 ///Sets a global scale factor for the whole picture |
526 /// |
556 /// |
662 ///Like other functions using |
692 ///Like other functions using |
663 ///\ref named-templ-func-param "named template parameters", |
693 ///\ref named-templ-func-param "named template parameters", |
664 ///this function calles the algorithm itself, i.e. in this case |
694 ///this function calles the algorithm itself, i.e. in this case |
665 ///it draws the graph. |
695 ///it draws the graph. |
666 void run() { |
696 void run() { |
|
697 ///\todo better 'epsilon' would be nice here. |
|
698 const double EPSILON=1e-9; |
667 if(dontPrint) return; |
699 if(dontPrint) return; |
668 |
700 |
669 _NegY<typename T::CoordsMapType> mycoords(_coords,_negY); |
701 _NegY<typename T::CoordsMapType> mycoords(_coords,_negY); |
670 |
702 |
671 os << "%!PS-Adobe-2.0 EPSF-2.0\n"; |
703 os << "%!PS-Adobe-2.0 EPSF-2.0\n"; |
685 if (_autoEdgeWidthScale) { |
717 if (_autoEdgeWidthScale) { |
686 double max_w=0; |
718 double max_w=0; |
687 for(EdgeIt e(g);e!=INVALID;++e) |
719 for(EdgeIt e(g);e!=INVALID;++e) |
688 max_w=std::max(double(_edgeWidths[e]),max_w); |
720 max_w=std::max(double(_edgeWidths[e]),max_w); |
689 ///\todo better 'epsilon' would be nice here. |
721 ///\todo better 'epsilon' would be nice here. |
690 if(max_w>1e-9) { |
722 if(max_w>EPSILON) { |
691 _edgeWidthScale/=max_w; |
723 _edgeWidthScale/=max_w; |
692 } |
724 } |
693 } |
725 } |
694 |
726 |
695 if (_autoNodeScale) { |
727 if (_autoNodeScale) { |
696 double max_s=0; |
728 double max_s=0; |
697 for(NodeIt n(g);n!=INVALID;++n) |
729 for(NodeIt n(g);n!=INVALID;++n) |
698 max_s=std::max(double(_nodeSizes[n]),max_s); |
730 max_s=std::max(double(_nodeSizes[n]),max_s); |
699 ///\todo better 'epsilon' would be nice here. |
731 ///\todo better 'epsilon' would be nice here. |
700 if(max_s>1e-9) { |
732 if(max_s>EPSILON) { |
701 _nodeScale/=max_s; |
733 _nodeScale/=max_s; |
702 } |
734 } |
703 } |
735 } |
704 |
736 |
705 |
737 double diag_len = 1; |
|
738 if(!(_absoluteNodeSizes&&_absoluteEdgeWidths)) { |
|
739 BoundingBox<double> bb; |
|
740 for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]); |
|
741 if (bb.empty()) { |
|
742 bb = BoundingBox<double>(xy<double>(0,0)); |
|
743 } |
|
744 diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare()); |
|
745 if(diag_len<EPSILON) diag_len = 1; |
|
746 if(!_absoluteNodeSizes) _nodeScale*=diag_len; |
|
747 if(!_absoluteEdgeWidths) _edgeWidthScale*=diag_len; |
|
748 } |
|
749 |
706 BoundingBox<double> bb; |
750 BoundingBox<double> bb; |
707 ///\bug: Chech whether the graph is empty. |
|
708 for(NodeIt n(g);n!=INVALID;++n) { |
751 for(NodeIt n(g);n!=INVALID;++n) { |
709 double ns=_nodeSizes[n]*_nodeScale; |
752 double ns=_nodeSizes[n]*_nodeScale; |
710 xy<double> p(ns,ns); |
753 xy<double> p(ns,ns); |
711 switch(_nodeShapes[n]) { |
754 switch(_nodeShapes[n]) { |
712 case CIRCLE: |
755 case CIRCLE: |
862 sw-=_parEdgeDist; |
905 sw-=_parEdgeDist; |
863 sw/=-2.0; |
906 sw/=-2.0; |
864 xy<double> dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]); |
907 xy<double> dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]); |
865 double l=std::sqrt(dvec.normSquare()); |
908 double l=std::sqrt(dvec.normSquare()); |
866 ///\todo better 'epsilon' would be nice here. |
909 ///\todo better 'epsilon' would be nice here. |
867 xy<double> d(dvec/std::max(l,1e-9)); |
910 xy<double> d(dvec/std::max(l,EPSILON)); |
868 xy<double> m; |
911 xy<double> m; |
869 // m=xy<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0; |
912 // m=xy<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0; |
870 |
913 |
871 // m=xy<double>(mycoords[g.source(*i)])+ |
914 // m=xy<double>(mycoords[g.source(*i)])+ |
872 // dvec*(double(_nodeSizes[g.source(*i)])/ |
915 // dvec*(double(_nodeSizes[g.source(*i)])/ |