Main MRPT website > C++ reference
MRPT logo
CDirectedTree.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  MRPT_DIRECTED_TREE_H
00029 #define  MRPT_DIRECTED_TREE_H
00030 
00031 //#include <mrpt/math/utils.h>
00032 #include <mrpt/utils/utils_defs.h>
00033 
00034 /*---------------------------------------------------------------
00035         Class
00036   ---------------------------------------------------------------*/
00037 namespace mrpt
00038 {
00039         namespace graphs
00040         {
00041                 using mrpt::utils::TNodeID;
00042 
00043                 /** A special kind of graph in the form of a tree with directed edges and optional edge annotations of templatized type "TYPE_EDGES".
00044                   *  The tree is represented by means of:
00045                   *             - \a root: The ID of the root node.
00046                   *             - \a edges_to_children: A map from node ID to all the edges to its children.
00047                   *
00048                   *  This class is less general than CDirectedGraph but more efficient to traverse (see \a visitDepthFirst and \a visitBreadthFirst).
00049                   *
00050                   *  If annotations in edges are not required, you can leave TYPE_EDGES to its default type "uint8_t".
00051                   *  \sa CDirectedGraph, CDijkstra, mrpt::graphs::CNetworkOfPoses,
00052                  * \ingroup mrpt_graphs_grp
00053                   */
00054                 template <class TYPE_EDGES = uint8_t>
00055                 class CDirectedTree
00056                 {
00057                 public:
00058                         struct TEdgeInfo
00059                         {
00060                                 TNodeID    id;      //!< The ID of the child node.
00061                                 bool       reverse; //!< True if edge direction is child->parent, false if it's parent->child.
00062                                 TYPE_EDGES data;    //!< User data for this edge.
00063                         };
00064                         typedef std::list<TEdgeInfo>          TListEdges;
00065                         typedef std::map<TNodeID,TListEdges>  TMapNode2ListEdges;
00066 
00067                         /** @name Data
00068                             @{ */
00069                         TNodeID            root;               //!< The root of the tree
00070                         TMapNode2ListEdges edges_to_children;  //!< The edges of each node
00071                         /** @} */
00072 
00073                         /** @name Utilities
00074                             @{ */
00075 
00076                         /** Empty all edge data and set "root" to INVALID_NODEID */
00077                         void clear() { edges_to_children.clear(); root = INVALID_NODEID; }
00078 
00079                         /** Virtual base class for user-defined visitors */
00080                         struct Visitor
00081                         {
00082                                 typedef CDirectedTree<TYPE_EDGES> tree_t;
00083 
00084                                 /** Virtual method to be implemented by the user and which will be called during the visit to a graph with visitDepthFirst or visitBreadthFirst
00085                                   *  Specifically, the method will be called once for each <b>edge</b> in the tree.
00086                                   * \param parent [IN] The ID of the parent node.
00087                                   * \param edge_to_child [IN] The edge information from the parent to "edge_to_child.id"
00088                                   * \param depth_level [IN] The "depth level" of the child node "edge_to_child.id" (root node is at 0, its children are at 1, etc.).
00089                                   */
00090                                 virtual void OnVisitNode( const TNodeID parent, const typename tree_t::TEdgeInfo &edge_to_child, const size_t depth_level ) = 0;
00091                         };
00092 
00093                         /** Depth-first visit of all children nodes of a given root (itself excluded from the visit), invoking a user-provided function for each node/edge. \sa visitBreadthFirst */
00094                         void visitDepthFirst( const TNodeID root, Visitor & user_visitor, const size_t root_depth_level =0 ) const
00095                         {
00096                                 const size_t next_depth_level = root_depth_level+1;
00097                                 typename TMapNode2ListEdges::const_iterator itChildren = edges_to_children.find(root);
00098                                 if (itChildren==edges_to_children.end()) return; // No children
00099                                 const TListEdges &children = itChildren->second;
00100                                 for (typename TListEdges::const_iterator itEdge=children.begin();itEdge!=children.end();++itEdge)
00101                                 {
00102                                         user_visitor.OnVisitNode(root,*itEdge,next_depth_level);
00103                                         visitDepthFirst(itEdge->id,user_visitor, next_depth_level); // Recursive depth-first call.
00104                                 }
00105                         }
00106 
00107                         /** Breadth-first visit of all children nodes of a given root (itself excluded from the visit), invoking a user-provided function for each node/edge. \sa visitDepthFirst */
00108                         void visitBreadthFirst( const TNodeID root, Visitor & user_visitor, const size_t root_depth_level =0  ) const
00109                         {
00110                                 const size_t next_depth_level = root_depth_level+1;
00111                                 typename TMapNode2ListEdges::const_iterator itChildren = edges_to_children.find(root);
00112                                 if (itChildren==edges_to_children.end()) return; // No children
00113                                 const TListEdges &children = itChildren->second;
00114                                 for (typename TListEdges::const_iterator itEdge=children.begin();itEdge!=children.end();++itEdge)
00115                                         user_visitor.OnVisitNode(root,*itEdge,next_depth_level);
00116                                 for (typename TListEdges::const_iterator itEdge=children.begin();itEdge!=children.end();++itEdge)
00117                                         visitDepthFirst(itEdge->id,user_visitor,next_depth_level); // Recursive breath-first call.
00118                         }
00119 
00120                         /** Return a text representation of the tree spanned in a depth-first view, as in this example:
00121                           *  \code
00122                           *    0
00123                           *     -> 1
00124                           *     -> 2
00125                           *         -> 4
00126                           *         -> 5
00127                           *     -> 3
00128                           *  \endcode
00129                           */
00130                         std::string getAsTextDescription() const
00131                         {
00132                                 std::ostringstream s;
00133                                 struct CMyVisitor : public mrpt::graphs::CDirectedTree<TYPE_EDGES>::Visitor
00134                                 {
00135                                         std::ostringstream  &m_s;
00136                                         CMyVisitor(std::ostringstream &s) : m_s(s) { }
00137                                         virtual void OnVisitNode( const TNodeID parent, const typename mrpt::graphs::CDirectedTree<TYPE_EDGES>::Visitor::tree_t::TEdgeInfo &edge_to_child, const size_t depth_level ) {
00138                                                 m_s << std::string(depth_level*5, ' ') << (edge_to_child.reverse ? "<-" : "->" ) //;
00139                                                         << std::setw(3) << edge_to_child.id << std::endl;
00140                                         }
00141                                 };
00142                                 CMyVisitor myVisitor(s);
00143                                 s << std::setw(3) << root << std::endl;
00144                                 visitDepthFirst( root, myVisitor );
00145                                 return s.str();
00146                         }
00147 
00148                 };
00149 
00150                 /** @} */
00151         } // End of namespace
00152 } // End of namespace
00153 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011