Main MRPT website > C++ reference
MRPT logo
CDirectedGraph.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_DIRECTEDGRAPH_H
00029 #define  MRPT_DIRECTEDGRAPH_H
00030 
00031 #include <mrpt/utils/utils_defs.h>
00032 //#include <mrpt/math/utils.h>
00033 
00034 /*---------------------------------------------------------------
00035         Class
00036   ---------------------------------------------------------------*/
00037 namespace mrpt
00038 {
00039         namespace graphs
00040         {
00041                 using mrpt::utils::TNodeID;
00042                 using mrpt::utils::TPairNodeIDs;
00043 
00044                 /** \addtogroup mrpt_graphs_grp
00045                     @{ */
00046 
00047                 namespace detail
00048                 {
00049                         /** An empty structure */
00050                         struct edge_annotations_empty {  };
00051                 }
00052 
00053                 /** A directed graph with the argument of the template specifying the type of the annotations in the edges.
00054                   *  This class only keeps a list of edges (in the member \a edges), so there is no information stored for each node but its existence referred by a node_ID.
00055                   *
00056                   *  Note that edges are stored as a std::multimap<> to allow <b>multiple edges</b> between the same pair of nodes.
00057                   *
00058                   * \sa mrpt::math::CDijkstra, mrpt::graphs::CNetworkOfPoses, mrpt::graphs::CDirectedTree
00059                  * \ingroup mrpt_graphs_grp
00060                   */
00061                 template<class TYPE_EDGES, class EDGE_ANNOTATIONS = detail::edge_annotations_empty>
00062                 class CDirectedGraph
00063                 {
00064                 public:
00065                         /** The type of each global pose in \a nodes: an extension of the \a TYPE_EDGES pose with any optional user-defined data */
00066                         struct edge_t : public TYPE_EDGES, public EDGE_ANNOTATIONS
00067                         {
00068                                 // Replicate possible constructors:
00069                                 inline edge_t () : TYPE_EDGES() { }
00070                                 template <typename ARG1> inline edge_t (const ARG1 &a1) : TYPE_EDGES(a1) { }
00071                                 template <typename ARG1,typename ARG2> inline edge_t (const ARG1 &a1,const ARG2 &a2) : TYPE_EDGES(a1,a2) { }
00072                         };
00073 
00074 
00075                         typedef typename mrpt::aligned_containers<TPairNodeIDs,edge_t>::multimap_t      edges_map_t;  //!< The type of the member \a edges
00076                         typedef typename edges_map_t::iterator         iterator;
00077                         typedef typename edges_map_t::const_iterator   const_iterator;
00078 
00079                         /** The public member with the directed edges in the graph */
00080                         edges_map_t   edges;
00081 
00082 
00083                         inline CDirectedGraph(const edges_map_t &obj) : edges(obj) { }  //!< Copy constructor from a multimap<pair< >, >
00084                         inline CDirectedGraph() : edges() {}  //!< Default constructor
00085 
00086                         inline iterator begin() { return edges.begin(); }
00087                         inline iterator end() { return edges.end(); }
00088                         inline const_iterator begin() const { return edges.begin(); }
00089                         inline const_iterator end() const { return edges.end(); }
00090 
00091 
00092                         /** @name Edges/nodes utility methods
00093                                 @{ */
00094 
00095                         inline size_t edgeCount() const { return edges.size(); }  //!< The number of edges in the graph
00096                         inline void clearEdges() { edges.clear(); } //!< Erase all edges
00097 
00098 
00099                         /** Insert an edge (from -> to) with the given edge value. \sa insertEdgeAtEnd */
00100                         inline void insertEdge(TNodeID from_nodeID, TNodeID to_nodeID,const edge_t &edge_value )
00101                         {
00102                                 EIGEN_ALIGN16 typename edges_map_t::value_type entry(
00103                                         std::make_pair(from_nodeID,to_nodeID),
00104                                         edge_value);
00105                                 edges.insert(entry);
00106                         }
00107 
00108                         /** Insert an edge (from -> to) with the given edge value (more efficient version to be called if you know that the end will go at the end of the sorted std::multimap). \sa insertEdge */
00109                         inline void insertEdgeAtEnd(TNodeID from_nodeID, TNodeID to_nodeID,const edge_t &edge_value )
00110                         {
00111                                 EIGEN_ALIGN16 typename edges_map_t::value_type entry(
00112                                         std::make_pair(from_nodeID,to_nodeID),
00113                                         edge_value);
00114                                 edges.insert(edges.end(), entry);
00115                         }
00116 
00117                         /** Test is the given directed edge exists. */
00118                         inline bool edgeExists(TNodeID from_nodeID, TNodeID to_nodeID) const
00119                         { return edges.find(std::make_pair(from_nodeID,to_nodeID))!=edges.end(); }
00120 
00121                         /** Return a reference to the content of a given edge.
00122                           *  If several edges exist between the given nodes, the first one is returned.
00123                           * \exception std::exception if the given edge does not exist
00124                           * \sa getEdges
00125                           */
00126                         edge_t & getEdge(TNodeID from_nodeID, TNodeID to_nodeID)
00127                         {
00128                                 iterator it = edges.find(std::make_pair(from_nodeID,to_nodeID));
00129                                 if (it==edges.end())
00130                                         THROW_EXCEPTION( format("Edge %u->%u does not exist",(unsigned)from_nodeID,(unsigned)to_nodeID) )
00131                                 else return it->second;
00132                         }
00133 
00134                         /** Return a reference to the content of a given edge.
00135                           *  If several edges exist between the given nodes, the first one is returned.
00136                           * \exception std::exception if the given edge does not exist
00137                           * \sa getEdges
00138                           */
00139                         const edge_t & getEdge(TNodeID from_nodeID, TNodeID to_nodeID) const
00140                         {
00141                                 const_iterator it = edges.find(std::make_pair(from_nodeID,to_nodeID));
00142                                 if (it==edges.end())
00143                                         THROW_EXCEPTION( format("Edge %u->%u does not exist",(unsigned)from_nodeID,(unsigned)to_nodeID) )
00144                                 else return it->second;
00145                         }
00146 
00147                         /** Return a pair<first,last> of iterators to the range of edges between two given nodes. \sa getEdge  */
00148                         std::pair<iterator,iterator> getEdges(TNodeID from_nodeID, TNodeID to_nodeID) {
00149                                 return edges.equal_range( std::make_pair(from_nodeID,to_nodeID) );
00150                         }
00151                         /** Return a pair<first,last> of const iterators to the range of edges between two given nodes.  \sa getEdge */
00152                         std::pair<const_iterator,const_iterator> getEdges(TNodeID from_nodeID, TNodeID to_nodeID) const {
00153                                 return edges.equal_range( std::make_pair(from_nodeID,to_nodeID) );
00154                         }
00155 
00156                         /** Erase all edges between the given nodes (it has no effect if no edge existed)
00157                           */
00158                         inline void eraseEdge(TNodeID from_nodeID, TNodeID to_nodeID) {
00159                                 edges.erase(std::make_pair(from_nodeID,to_nodeID));
00160                         }
00161 
00162                         /** Return a list of all the node_ID's of the graph, generated from all the nodes that appear in the list of edges
00163                           */
00164                         void getAllNodes( std::set<TNodeID> &lstNode_IDs) const
00165                         {
00166                                 lstNode_IDs.clear();
00167                                 for (typename edges_map_t::const_iterator it=edges.begin();it!=edges.end();++it)
00168                                 {
00169                                         lstNode_IDs.insert(it->first.first);
00170                                         lstNode_IDs.insert(it->first.second);
00171                                 }
00172                         }
00173 
00174                         /** Less efficient way to get all nodes that returns a copy of the set object \sa getAllNodes( std::set<TNodeID> &lstNode_IDs) */
00175                         inline std::set<TNodeID> getAllNodes() const { std::set<TNodeID> lst; getAllNodes(lst); return lst; }
00176 
00177                         /** Count how many different node IDs appear in the graph edges.
00178                           */
00179                         size_t countDifferentNodesInEdges() const
00180                         {
00181                                 std::set<TNodeID> aux;
00182                                 for (typename edges_map_t::const_iterator it=edges.begin();it!=edges.end();++it)
00183                                 {
00184                                         aux.insert(it->first.first);
00185                                         aux.insert(it->first.second);
00186                                 }
00187                                 return aux.size();
00188                         }
00189 
00190                         /** Return the list of all neighbors of "nodeID", by creating a list of their node IDs. \sa getAdjacencyMatrix */
00191                         void getNeighborsOf(const TNodeID nodeID, std::set<TNodeID> &neighborIDs) const
00192                         {
00193                                 neighborIDs.clear();
00194                                 for (typename edges_map_t::const_iterator it=edges.begin();it!=edges.end();++it)
00195                                 {
00196                                         if (it->first.first==nodeID)
00197                                                 neighborIDs.insert(it->first.second);
00198                                         else if (it->first.second==nodeID)
00199                                                 neighborIDs.insert(it->first.first);
00200                                 }
00201                         }
00202 
00203                         /** Return a map from node IDs to all its neighbors (that is, connected nodes, regardless of the edge direction)
00204                           *  This is a much more efficient method than calling getNeighborsOf() for each node in the graph.
00205                           *  Possible values for the template argument MAP_NODEID_SET_NODEIDS are:
00206                           *    - std::map<TNodeID, std::set<TNodeID> >
00207                           *    - mrpt::utils::map_as_vector<TNodeID, std::set<TNodeID> >
00208                           * \sa getNeighborsOf
00209                           */
00210                         template <class MAP_NODEID_SET_NODEIDS>
00211                         void getAdjacencyMatrix( MAP_NODEID_SET_NODEIDS  &outAdjacency ) const
00212                         {
00213                                 outAdjacency.clear();
00214                                 for (typename edges_map_t::const_iterator it=edges.begin();it!=edges.end();++it)
00215                                 {
00216                                         outAdjacency[it->first.first].insert(it->first.second);
00217                                         outAdjacency[it->first.second].insert(it->first.first);
00218                                 }
00219                         }
00220 
00221                         /** Just like \a getAdjacencyMatrix but return only the adjacency for those node_ids in the set \a onlyForTheseNodes
00222                           *  (both endings nodes of an edge must be within the set for it to be returned) */
00223                         template <class MAP_NODEID_SET_NODEIDS,class SET_NODEIDS>
00224                         void getAdjacencyMatrix( MAP_NODEID_SET_NODEIDS  &outAdjacency, const SET_NODEIDS &onlyForTheseNodes ) const
00225                         {
00226                                 outAdjacency.clear();
00227                                 const typename SET_NODEIDS::const_iterator setEnd = onlyForTheseNodes.end();
00228                                 for (typename edges_map_t::const_iterator it=edges.begin();it!=edges.end();++it)
00229                                 {
00230                                         if (onlyForTheseNodes.find(it->first.first)==setEnd || onlyForTheseNodes.find(it->first.second)==setEnd)
00231                                                 continue;
00232                                         outAdjacency[it->first.first].insert(it->first.second);
00233                                         outAdjacency[it->first.second].insert(it->first.first);
00234                                 }
00235                         }
00236 
00237                         /** @} */  // end of edge/nodes utilities
00238 
00239                 }; // end class CDirectedGraph
00240 
00241                 /** @} */
00242         } // End of namespace
00243 } // End of namespace
00244 #endif



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