00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef NODEPRINT_H
00021 #define NODEPRINT_H
00022
00023 #include <map>
00024 #include "node.h"
00025 #include "nodevisitor.h"
00026 #include "nodeoutputstrategy.h"
00027 #include "nodeiterator.h"
00028
00029 namespace treecomp
00030 {
00031
00032
00033
00034
00035 struct Position
00036 {
00037 double x;
00038 double y;
00039 };
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 template<class _TContent, class _TIter>
00057 class LayoutVisitor
00058 : public NodeVisitor<typename _TIter::const_iterator, const Node<_TContent>,
00059 const NormalNode<_TContent>,const RootNode<_TContent> >
00060 {
00061 public:
00062 typedef LayoutVisitor<_TContent,_TIter> _Self;
00063 typedef NodeVisitor<typename _TIter::const_iterator, const Node<_TContent>,
00064 const NormalNode<_TContent>,const RootNode<_TContent> >
00065 _Base;
00066
00067 virtual _Self* construct() const { return new _Self(); }
00068 virtual _Self* clone() const { return new _Self(*this); }
00069 virtual ~LayoutVisitor() {}
00070
00071 virtual void operator()(_TIter& iter);
00072 virtual void visitNormalNode(const NormalNode<_TContent>* node);
00073 virtual void visitRootNode(const RootNode<_TContent>* node);
00074
00075 virtual std::map<const Node<_TContent>*, Position> getMap() const { return m_map; }
00076
00077 protected:
00078 void addNode(const Node<_TContent>* node, Position pos);
00079 Position calculatePosition(const Node<_TContent>* node);
00080
00081 std::map<const Node<_TContent>*, Position> m_map;
00082 private:
00083 virtual LayoutVisitor& operator=(const LayoutVisitor&) {return *this;}
00084 };
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 template<class _TContent>
00097 class TEXGraphOutputStrategy : public StreamOutputStrategy<_TContent>
00098 {
00099 public:
00100 explicit TEXGraphOutputStrategy<_TContent>(std::ostream* out=&std::cout, double scale=1, double border=5)
00101 : StreamOutputStrategy<_TContent>(out), m_width(0), m_height(0), m_scale(scale), m_border(border) {}
00102 virtual TEXGraphOutputStrategy<_TContent>* construct() const { return new TEXGraphOutputStrategy<_TContent>; }
00103 virtual TEXGraphOutputStrategy<_TContent>* clone() const { return new TEXGraphOutputStrategy<_TContent>(*this); }
00104 virtual ~TEXGraphOutputStrategy() {}
00105
00106 virtual void writeHeader();
00107 virtual void writeFooter();
00108 virtual void writeNormalNode(const NormalNode<_TContent>* node);
00109 virtual void writeRootNode(const RootNode<_TContent>* node);
00110
00111 virtual void setScale(double scale) { m_scale = scale; }
00112 virtual void setPositionMap(std::map<const Node<_TContent>*, Position> pMap) { m_pMap = pMap; }
00113
00114 protected:
00115 virtual void writeEdge(const Node<_TContent>* node);
00116 virtual std::string formatName(std::string name);
00117 virtual int getMapIndex(const Node<_TContent>* node);
00118 std::map<const Node<_TContent>*, Position> m_pMap;
00119 double m_width;
00120 double m_height;
00121 double m_scale;
00122 double m_border;
00123 };
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 template<class _TContent, class _TIter>
00138
00139 void LayoutVisitor<_TContent,_TIter>::operator()(_TIter& iter)
00140 {
00141 init(iter);
00142 m_map.clear();
00143 iterate(this);
00144 }
00145
00146
00147
00148
00149
00150 template<class _TContent, class _TIter>
00151 void LayoutVisitor<_TContent,_TIter>::visitNormalNode(const NormalNode<_TContent>* node)
00152 {
00153 addNode(node, calculatePosition(node));
00154 }
00155
00156
00157
00158
00159
00160 template<class _TContent, class _TIter>
00161 void LayoutVisitor<_TContent,_TIter>::visitRootNode(const RootNode<_TContent>* node)
00162 {
00163 addNode(node, calculatePosition(node));
00164 }
00165
00166
00167
00168
00169
00170 template<class _TContent, class _TIter>
00171 void LayoutVisitor<_TContent,_TIter>::addNode(const Node<_TContent>* node, Position position)
00172 {
00173 m_map.insert( typename std::map<const Node<_TContent>*, Position>::value_type(node, position) );
00174 }
00175
00176
00177
00178
00179
00180 template<class _TContent, class _TIter>
00181 Position LayoutVisitor<_TContent,_TIter>::calculatePosition(const Node<_TContent>* node)
00182 {
00183 Position pos;
00184 const Node<_TContent>* parent = node->getParent();
00185 if (!parent)
00186 {
00187
00188 pos.x = 0.0;
00189 pos.y = 0.0;
00190 }
00191 else
00192 {
00193 Position parentPos = m_map[parent];
00194 pos.y = parentPos.y + 1;
00195 const std::list<Node<_TContent>*>* siblings = parent->getChildren();
00196 if (siblings->front() == node)
00197 pos.x = parentPos.x;
00198 else
00199 {
00200
00201 typename std::list<Node<_TContent>*>::const_iterator nlIter = find(siblings->begin(), siblings->end(), node);
00202 const Node<_TContent>* leftSibling = *(--nlIter);
00203
00204 double maxX = 0;
00205 typename Node<_TContent>::const_all_iterator anIter = leftSibling->beginAll();
00206 for (; anIter != leftSibling->endAll(); ++anIter)
00207 if (m_map[anIter()].x >= maxX)
00208 maxX = m_map[anIter()].x;
00209 pos.x = maxX + 2;
00210
00211 while (parent)
00212 {
00213 m_map[parent].x += 1;
00214 parent = parent->getParent();
00215 }
00216 }
00217 }
00218 return pos;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 template<class _TContent>
00230 void TEXGraphOutputStrategy<_TContent>::writeHeader()
00231 {
00232
00233 m_width = 0;
00234 m_height = 0;
00235 typename std::map<const Node<_TContent>*, Position>::const_iterator pmIter;
00236 for (pmIter = m_pMap.begin(); pmIter != m_pMap.end(); ++pmIter)
00237 {
00238 if ((*pmIter).second.x >= m_width)
00239 m_width = (*pmIter).second.x;
00240 if ((*pmIter).second.y >= m_height)
00241 m_height = (*pmIter).second.y;
00242 }
00243 m_width *= m_scale;
00244 m_height *= m_scale;
00245
00246 *m_out << "%% This is a generated file!\n"
00247 << "%% Requires pstricks and pst-node styles.\n"
00248 << "\\begin{figure}[htb]\n"
00249 << "\\begin{center}\n"
00250 << "\\psset{unit=1mm, arrows=-, nodesep=0pt, fillstyle=solid}\n"
00251 << "\\begin{pspicture}(" << m_width + 2*m_border << ',' << m_height + 2*m_border << ")\n";
00252
00253 }
00254
00255
00256
00257
00258 template<class _TContent>
00259 void TEXGraphOutputStrategy<_TContent>::writeFooter()
00260 {
00261
00262 const Node<_TContent>* root = (*(m_pMap.begin())).first;
00263 while(root->getParent())
00264 root = root->getParent();
00265 std::string treeName = formatName(root->getName());
00266 std::string caption = treeName;
00267 std::string label = treeName;
00268 if (treeName[0] == '\\')
00269 {
00270 caption = "$" + treeName + "$";
00271 label.erase(label.begin());
00272 }
00273 *m_out << "\\end{pspicture}\n";
00274 *m_out << "\\caption{" << caption << "}\n";
00275 *m_out << "\\label{tree: " << label << "}\n";
00276 *m_out << "\\end{center}\n";
00277 *m_out << "\\end{figure}\n";
00278 }
00279
00280
00281
00282
00283 template<class _TContent>
00284 void TEXGraphOutputStrategy<_TContent>::writeNormalNode(const NormalNode<_TContent>* node)
00285 {
00286 if (m_pMap.count(node))
00287 {
00288
00289 *m_out << "\\rput(" << (m_border + m_pMap[node].x * m_scale) << ','
00290 << m_border + m_height - m_pMap[node].y * m_scale
00291 << "){\\Rnode{" << getMapIndex(node) << "}{{\\footnotesize \\psovalbox{\\(" << formatName(node->getName()) << "\\)}}}}\n";
00292
00293 writeEdge(node);
00294 }
00295 else
00296 {
00297 *m_out << "Error: Didn't find node " + node->getName() + " in position map\n";
00298 }
00299 }
00300
00301
00302
00303
00304 template<class _TContent>
00305 void TEXGraphOutputStrategy<_TContent>::writeRootNode(const RootNode<_TContent>* node)
00306 {
00307 if (m_pMap.count(node))
00308 {
00309
00310 *m_out << "\\rput(" << (m_border + m_pMap[node].x * m_scale) << ','
00311 << m_border + m_height - m_pMap[node].y * m_scale
00312 << "){\\Rnode{" << getMapIndex(node) << "}{{\\footnotesize \\psovalbox{\\(\\bf " << formatName(node->getName()) << "\\)}}}}\n";
00313
00314 writeEdge(node);
00315 }
00316 else
00317 {
00318 *m_out << "Error: Didn't find node " + node->getName() + " in position map\n";
00319 }
00320 }
00321
00322
00323
00324
00325 template<class _TContent>
00326 void TEXGraphOutputStrategy<_TContent>::writeEdge(const Node<_TContent>* node)
00327 {
00328 if (node->getParent())
00329 {
00330 int parentIndex = getMapIndex(node->getParent());
00331 int nodeIndex = getMapIndex(node);
00332 if (node->isFixed())
00333 {
00334 *m_out << "\\ncline[doubleline=true]{" << parentIndex << "}{" << nodeIndex << "}\n";
00335 }
00336 else
00337 {
00338 *m_out << "\\ncline[doubleline=false]{" << parentIndex << "}{" << nodeIndex << "}\n";
00339 }
00340 }
00341 }
00342
00343
00344
00345
00346 template<class _TContent>
00347 std::string
00348 TEXGraphOutputStrategy<_TContent>::formatName(std::string name)
00349 {
00350 std::string::size_type start = name.find("\"");
00351 if (start < name.size())
00352 {
00353 std::string::size_type end = name.find("\"", start+1);
00354 name=name.substr(start+1, end-start-1);
00355 }
00356 return name;
00357 }
00358
00359
00360
00361
00362 template<class _TContent>
00363 int TEXGraphOutputStrategy<_TContent>::getMapIndex(const Node<_TContent>* node)
00364 {
00365 int i = 0;
00366 typename std::map<const Node<_TContent>*, Position>::const_iterator pmIter;
00367 for (pmIter = m_pMap.begin(); pmIter != m_pMap.end(); ++pmIter)
00368 {
00369 if (node == (*pmIter).first)
00370 return i;
00371 ++i;
00372 }
00373 return 0;
00374 }
00375
00376
00377 }
00378
00379
00380 #endif //PRINT_H