#ifndef __BFS_COMPONENT_EXPLORER_H__ #define __BFS_COMPONENT_EXPLORER_H__ #include #include #include "../typedefs.h" #include "DynamicGraph.h" #include "RestrictionMap.h" /** * Explores the components of the given graph while respecting turn restrictions * and barriers. */ template class BFSComponentExplorer { public: typedef typename GraphT::NodeIterator NodeIterator; typedef typename GraphT::EdgeIterator EdgeIterator; BFSComponentExplorer(const GraphT& dynamicGraph, const RestrictionMap& restrictions, const boost::unordered_set& barrier_nodes) : m_graph(dynamicGraph) , m_restriction_map(restrictions) , m_barrier_nodes(barrier_nodes) { BOOST_ASSERT(m_graph.GetNumberOfNodes() > 0); } /*! * Returns the size of the component that the node belongs to. */ inline unsigned int getComponentSize(NodeID node) { BOOST_ASSERT(node < m_component_index_list.size()); return m_component_index_size[m_component_index_list[node]]; } inline unsigned int getNumberOfComponents() { return m_component_index_size.size(); } /*! * Computes the component sizes. */ void run() { std::queue > bfs_queue; unsigned current_component = 0; BOOST_ASSERT( m_component_index_list.empty() ); BOOST_ASSERT( m_component_index_size.empty() ); unsigned num_nodes = m_graph.GetNumberOfNodes(); m_component_index_list.resize( num_nodes, std::numeric_limits::max() ); BOOST_ASSERT (num_nodes > 0); //put unexplorered node with parent pointer into queue for( NodeID node = 0; node < num_nodes; ++node) { if(std::numeric_limits::max() == m_component_index_list[node]) { unsigned size = exploreComponent(bfs_queue, node, current_component); //push size into vector m_component_index_size.push_back(size); ++current_component; } } } private: /*! * Explores the current component that starts at node using BFS. */ inline unsigned exploreComponent( std::queue > &bfs_queue, NodeID node, unsigned current_component ) { bfs_queue.push(std::make_pair(node, node)); //mark node as read m_component_index_list[node] = current_component; unsigned current_component_size = 1; while(!bfs_queue.empty()) { //fetch element from BFS queue std::pair current_queue_item = bfs_queue.front(); bfs_queue.pop(); const NodeID v = current_queue_item.first; //current node const NodeID u = current_queue_item.second; //parent //increment size counter of current component ++current_component_size; const bool is_barrier_node = (m_barrier_nodes.find(v) != m_barrier_nodes.end()); if(!is_barrier_node) { const NodeID to_node_of_only_restriction = m_restriction_map.CheckForEmanatingIsOnlyTurn(u, v); for( EdgeIterator e2 = m_graph.BeginEdges(v); e2 < m_graph.EndEdges(v); ++e2 ) { NodeIterator w = m_graph.GetTarget(e2); if( to_node_of_only_restriction != std::numeric_limits::max() && w != to_node_of_only_restriction ) { // At an only_-restriction but not at the right turn continue; } if( u != w ) { //only add an edge if turn is not a U-turn except //when it is at the end of a dead-end street. if (!m_restriction_map.CheckIfTurnIsRestricted(u, v, w)) { //only add an edge if turn is not prohibited if(std::numeric_limits::max() == m_component_index_list[w]) { //insert next (node, parent) only if w has //not yet been explored //mark node as read m_component_index_list[w] = current_component; bfs_queue.push(std::make_pair(w,v)); } } } } } } return current_component_size; } std::vector m_component_index_list; std::vector m_component_index_size; const GraphT& m_graph; const RestrictionMap& m_restriction_map; const boost::unordered_set& m_barrier_nodes; }; #endif