diff --git a/CMakeLists.txt b/CMakeLists.txt index 4930018d5..76ec81072 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ file(GLOB ExtractorGlob Extractor/*.cpp) set(ExtractorSources extractor.cpp ${ExtractorGlob}) add_executable(osrm-extract ${ExtractorSources}) -file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp) +file(GLOB PrepareGlob Contractor/*.cpp DataStructures/HilbertValue.cpp DataStructures/RestrictionMap.cpp) set(PrepareSources prepare.cpp ${PrepareGlob}) add_executable(osrm-prepare ${PrepareSources}) diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index 7629660f9..e99ddb564 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -38,46 +38,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include EdgeBasedGraphFactory::EdgeBasedGraphFactory( - int number_of_nodes, - std::vector & input_edge_list, + const boost::shared_ptr& node_based_graph, + std::unique_ptr restriction_map, std::vector & barrier_node_list, std::vector & traffic_light_node_list, - std::vector & input_restrictions_list, std::vector & m_node_info_list, SpeedProfileProperties & speed_profile ) : speed_profile(speed_profile), - m_turn_restrictions_count(0), + m_node_based_graph(node_based_graph), m_number_of_edge_based_nodes(std::numeric_limits::max()), + m_restriction_map(std::move(restriction_map)), m_node_info_list(m_node_info_list), max_id(0) { - BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) { - std::pair restriction_source = - std::make_pair(restriction.fromNode, restriction.viaNode); - unsigned index; - RestrictionMap::iterator restriction_iter; - restriction_iter = m_restriction_map.find(restriction_source); - if(restriction_iter == m_restriction_map.end()) { - index = m_restriction_bucket_list.size(); - m_restriction_bucket_list.resize(index+1); - m_restriction_map.emplace(restriction_source, index); - } else { - index = restriction_iter->second; - //Map already contains an is_only_*-restriction - if(m_restriction_bucket_list.at(index).begin()->second) { - continue; - } else if(restriction.flags.isOnly) { - //We are going to insert an is_only_*-restriction. There can be only one. - m_turn_restrictions_count -= m_restriction_bucket_list.at(index).size(); - m_restriction_bucket_list.at(index).clear(); - } - } - ++m_turn_restrictions_count; - m_restriction_bucket_list.at(index).push_back( - std::make_pair( restriction.toNode, restriction.flags.isOnly) - ); - } + // why not use the copy constructor? m_barrier_nodes.insert( barrier_node_list.begin(), barrier_node_list.end() @@ -88,121 +63,8 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( traffic_light_node_list.end() ); - std::sort( input_edge_list.begin(), input_edge_list.end() ); - - //TODO: remove duplicate edges - - DeallocatingVector edges_list; - NodeBasedEdge edge; - BOOST_FOREACH(const ImportEdge & import_edge, input_edge_list) { - - if( !import_edge.isForward() ) { - edge.source = import_edge.target(); - edge.target = import_edge.source(); - edge.data.backward = import_edge.isForward(); - edge.data.forward = import_edge.isBackward(); - } else { - edge.source = import_edge.source(); - edge.target = import_edge.target(); - edge.data.forward = import_edge.isForward(); - edge.data.backward = import_edge.isBackward(); - } - - if( edge.source == edge.target ) { - continue; - } - - edge.data.distance = (std::max)((int)import_edge.weight(), 1 ); - BOOST_ASSERT( edge.data.distance > 0 ); - edge.data.shortcut = false; - edge.data.roundabout = import_edge.isRoundabout(); - edge.data.ignore_in_grid = import_edge.ignoreInGrid(); - edge.data.nameID = import_edge.name(); - edge.data.type = import_edge.type(); - edge.data.isAccessRestricted = import_edge.isAccessRestricted(); - edge.data.contraFlow = import_edge.isContraFlow(); - edges_list.push_back( edge ); - - if( !import_edge.IsSplit() ) { - using std::swap; //enable ADL - swap( edge.source, edge.target ); - edge.data.SwapDirectionFlags(); - edges_list.push_back( edge ); - } - } - - std::vector().swap(input_edge_list); - std::sort( edges_list.begin(), edges_list.end() ); - - m_node_based_graph = boost::make_shared( - number_of_nodes, - edges_list - ); - DeallocatingVector().swap(edges_list); - BOOST_ASSERT(0 == edges_list.size() ); } -void EdgeBasedGraphFactory::FixupArrivingTurnRestriction( - const NodeID u, - const NodeID v, - const NodeID w -) { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - BOOST_ASSERT( w != std::numeric_limits::max() ); - - std::vector predecessors; - for( - EdgeID current_edge_id = m_node_based_graph->BeginEdges(u); - current_edge_id < m_node_based_graph->EndEdges(u); - ++current_edge_id - ) { - const EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge_id); - const NodeID target = m_node_based_graph->GetTarget(current_edge_id); - if( edge_data.backward && ( v != target) ) { - predecessors.push_back(target); - } - } - BOOST_FOREACH( const NodeID x, predecessors ) { - const std::pair restr_start = std::make_pair(x,u); - RestrictionMap::const_iterator restriction_iterator; - restriction_iterator = m_restriction_map.find( restr_start ); - if( restriction_iterator != m_restriction_map.end() ) { - const unsigned index = restriction_iterator->second; - BOOST_FOREACH( - RestrictionTarget & restriction_target, - m_restriction_bucket_list.at(index) - ) { - if( v == restriction_target.first ) { - restriction_target.first = w; - } - } - } - } -} - -void EdgeBasedGraphFactory::FixupStartingTurnRestriction( - const NodeID u, - const NodeID v, - const NodeID w -) { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - BOOST_ASSERT( w != std::numeric_limits::max() ); - - const std::pair old_start = std::make_pair(v,w); - RestrictionMap::const_iterator restriction_iterator; - restriction_iterator = m_restriction_map.find( old_start ); - if( restriction_iterator != m_restriction_map.end() ) { - const unsigned index = restriction_iterator->second; - // remove old restriction start (v,w) - m_restriction_map.erase( restriction_iterator ); - - // insert new restriction start (u,w) (point to index) - const std::pair new_start = std::make_pair(u,w); - m_restriction_map.insert( std::make_pair(new_start, index) ); - } -} void EdgeBasedGraphFactory::GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& output_edge_list @@ -227,57 +89,6 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector & node nodes.swap(m_edge_based_node_list); } -NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn( - const NodeID u, - const NodeID v -) const { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - const std::pair restriction_source = std::make_pair(u, v); - RestrictionMap::const_iterator restriction_iter; - restriction_iter = m_restriction_map.find(restriction_source); - if (restriction_iter != m_restriction_map.end()) { - const unsigned index = restriction_iter->second; - BOOST_FOREACH( - const RestrictionSource & restriction_target, - m_restriction_bucket_list.at(index) - ) { - if(restriction_target.second) { - return restriction_target.first; - } - } - } - return std::numeric_limits::max(); -} - -bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( - const NodeID u, - const NodeID v, - const NodeID w -) const { - BOOST_ASSERT( u != std::numeric_limits::max() ); - BOOST_ASSERT( v != std::numeric_limits::max() ); - BOOST_ASSERT( w != std::numeric_limits::max() ); - - const std::pair restriction_source = std::make_pair(u, v); - RestrictionMap::const_iterator restriction_iter; - restriction_iter = m_restriction_map.find(restriction_source); - if (restriction_iter != m_restriction_map.end()) { - const unsigned index = restriction_iter->second; - BOOST_FOREACH( - const RestrictionTarget & restriction_target, - m_restriction_bucket_list.at(index) - ) { - if( - ( w == restriction_target.first ) && // target found - ( !restriction_target.second ) // and not an only_-restr. - ) { - return true; - } - } - } - return false; -} void EdgeBasedGraphFactory::InsertEdgeBasedNode( NodeIterator u, @@ -375,7 +186,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( BOOST_ASSERT( current_edge_target_coordinate_id != current_edge_start_coordinate_id); // build edges - m_edge_based_node_list.push_back( + m_edge_based_node_list.emplace_back( EdgeBasedNode( forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, @@ -430,8 +241,7 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( reverse_data.edgeBasedNodeID != SPECIAL_NODEID ); - //TODO C++11: emplace_back with - m_edge_based_node_list.push_back( + m_edge_based_node_list.emplace_back( EdgeBasedNode( forward_data.edgeBasedNodeID, reverse_data.edgeBasedNodeID, @@ -560,11 +370,11 @@ void EdgeBasedGraphFactory::Run( m_node_based_graph->DeleteEdge(v, reverse_e2); // update any involved turn restrictions - FixupStartingTurnRestriction( u, v, w ); - FixupArrivingTurnRestriction( u, v, w ); + m_restriction_map->FixupStartingTurnRestriction( u, v, w ); + m_restriction_map->FixupArrivingTurnRestriction( u, v, w ); - FixupStartingTurnRestriction( w, v, u ); - FixupArrivingTurnRestriction( w, v, u ); + m_restriction_map->FixupStartingTurnRestriction( w, v, u ); + m_restriction_map->FixupArrivingTurnRestriction( w, v, u ); // store compressed geometry in container m_geometry_compressor.CompressEdge( @@ -731,7 +541,7 @@ void EdgeBasedGraphFactory::Run( ++node_based_edge_counter; const NodeIterator v = m_node_based_graph->GetTarget(e1); - const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); + const NodeID to_node_of_only_restriction = m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v); const bool is_barrier_node = ( m_barrier_nodes.find(v) != m_barrier_nodes.end() ); for( @@ -772,7 +582,7 @@ void EdgeBasedGraphFactory::Run( //only add an edge if turn is not a U-turn except when it is //at the end of a dead-end street - if (CheckIfTurnIsRestricted(u, v, w) && (to_node_of_only_restriction == SPECIAL_NODEID) && (w != to_node_of_only_restriction)) + if (m_restriction_map->CheckIfTurnIsRestricted(u, v, w) && (to_node_of_only_restriction == SPECIAL_NODEID) && (w != to_node_of_only_restriction)) { ++restricted_turns_counter; continue; @@ -853,7 +663,7 @@ void EdgeBasedGraphFactory::Run( SimpleLogger().Write() << "Edge-expanded graph ..."; SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges"; SimpleLogger().Write() << " skips " << restricted_turns_counter << " turns, " - "defined by " << m_turn_restrictions_count << " restrictions"; + "defined by " << m_restriction_map->size() << " restrictions"; SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns"; SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers"; } @@ -987,7 +797,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( ++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 = CheckForEmanatingIsOnlyTurn(u, v); + const NodeID to_node_of_only_restriction = m_restriction_map->CheckForEmanatingIsOnlyTurn(u, v); for( EdgeIterator e2 = m_node_based_graph->BeginEdges(v); @@ -1006,7 +816,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( 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 (!CheckIfTurnIsRestricted(u, v, w) ) { + if (!m_restriction_map->CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited if(std::numeric_limits::max() == component_index_list[w]) { //insert next (node, parent) only if w has diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 2a777dd3a..033c81c4b 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -35,13 +35,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../DataStructures/DynamicGraph.h" #include "../DataStructures/EdgeBasedNode.h" #include "../DataStructures/HashTable.h" -#include "../DataStructures/ImportEdge.h" #include "../DataStructures/OriginalEdgeData.h" #include "../DataStructures/Percent.h" #include "../DataStructures/QueryEdge.h" #include "../DataStructures/QueryNode.h" #include "../DataStructures/TurnInstructions.h" #include "../DataStructures/Restriction.h" +#include "../DataStructures/NodeBasedGraph.h" +#include "../DataStructures/RestrictionMap.h" #include "../Util/LuaUtil.h" #include "../Util/SimpleLogger.h" @@ -62,11 +63,10 @@ public: struct SpeedProfileProperties; explicit EdgeBasedGraphFactory( - int number_of_nodes, - std::vector & input_edge_list, + const boost::shared_ptr& node_based_graph, + std::unique_ptr restricion_map, std::vector & barrier_node_list, std::vector & traffic_light_node_list, - std::vector & input_restrictions_list, std::vector & m_node_info_list, SpeedProfileProperties & speed_profile ); @@ -109,54 +109,13 @@ public: } speed_profile; private: - struct NodeBasedEdgeData { - NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), nameID(std::numeric_limits::max()), - type(std::numeric_limits::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false), - roundabout(false), ignore_in_grid(false), contraFlow(false) - { } - - int distance; - unsigned edgeBasedNodeID; - unsigned nameID; - short type; - bool isAccessRestricted:1; - bool shortcut:1; - bool forward:1; - bool backward:1; - bool roundabout:1; - bool ignore_in_grid:1; - bool contraFlow:1; - - void SwapDirectionFlags() { - bool temp_flag = forward; - forward = backward; - backward = temp_flag; - } - - bool IsEqualTo( const NodeBasedEdgeData & other ) const { - return (forward == other.forward) && - (backward == other.backward) && - (nameID == other.nameID) && - (ignore_in_grid == other.ignore_in_grid) && - (contraFlow == other.contraFlow); - } - }; - - unsigned m_turn_restrictions_count; - unsigned m_number_of_edge_based_nodes; - - typedef DynamicGraph NodeBasedDynamicGraph; - typedef NodeBasedDynamicGraph::InputEdge NodeBasedEdge; typedef NodeBasedDynamicGraph::NodeIterator NodeIterator; typedef NodeBasedDynamicGraph::EdgeIterator EdgeIterator; typedef NodeBasedDynamicGraph::EdgeData EdgeData; - typedef std::pair RestrictionSource; - typedef std::pair RestrictionTarget; - typedef std::vector EmanatingRestrictionsVector; - typedef boost::unordered_map RestrictionMap; + + unsigned m_number_of_edge_based_nodes; std::vector m_node_info_list; - std::vector m_restriction_bucket_list; std::vector m_edge_based_node_list; DeallocatingVector m_edge_based_edge_list; @@ -164,7 +123,8 @@ private: boost::unordered_set m_barrier_nodes; boost::unordered_set m_traffic_lights; - RestrictionMap m_restriction_map; + std::unique_ptr m_restriction_map; + GeometryCompressor m_geometry_compressor; NodeID CheckForEmanatingIsOnlyTurn( diff --git a/DataStructures/NodeBasedGraph.h b/DataStructures/NodeBasedGraph.h new file mode 100644 index 000000000..f79e0363d --- /dev/null +++ b/DataStructures/NodeBasedGraph.h @@ -0,0 +1,109 @@ +#ifndef __NODE_BASED_GRAPH_H__ +#define __NODE_BASED_GRAPH_H__ + +#include "DynamicGraph.h" +#include "ImportEdge.h" + +#include +#include + +struct NodeBasedEdgeData { + NodeBasedEdgeData() : distance(INVALID_EDGE_WEIGHT), edgeBasedNodeID(SPECIAL_NODEID), nameID(std::numeric_limits::max()), + type(std::numeric_limits::max()), isAccessRestricted(false), shortcut(false), forward(false), backward(false), + roundabout(false), ignore_in_grid(false), contraFlow(false) + { } + + int distance; + unsigned edgeBasedNodeID; + unsigned nameID; + short type; + bool isAccessRestricted:1; + bool shortcut:1; + bool forward:1; + bool backward:1; + bool roundabout:1; + bool ignore_in_grid:1; + bool contraFlow:1; + + void SwapDirectionFlags() { + bool temp_flag = forward; + forward = backward; + backward = temp_flag; + } + + bool IsEqualTo( const NodeBasedEdgeData & other ) const { + return (forward == other.forward) && + (backward == other.backward) && + (nameID == other.nameID) && + (ignore_in_grid == other.ignore_in_grid) && + (contraFlow == other.contraFlow); + } +}; + +typedef DynamicGraph NodeBasedDynamicGraph; + +// Factory method to create NodeBasedDynamicGraph from ImportEdges +inline boost::shared_ptr NodeBasedDynamicGraphFromImportEdges( + int number_of_nodes, + std::vector& input_edge_list +) { + typedef NodeBasedDynamicGraph::InputEdge DynInputEdge; + + std::sort( input_edge_list.begin(), input_edge_list.end() ); + + //TODO: remove duplicate edges + DeallocatingVector edges_list; + DynInputEdge edge; + for(const ImportEdge& import_edge : input_edge_list) { + + if( !import_edge.isForward() ) { + edge.source = import_edge.target(); + edge.target = import_edge.source(); + edge.data.backward = import_edge.isForward(); + edge.data.forward = import_edge.isBackward(); + } else { + edge.source = import_edge.source(); + edge.target = import_edge.target(); + edge.data.forward = import_edge.isForward(); + edge.data.backward = import_edge.isBackward(); + } + + if( edge.source == edge.target ) { + continue; + } + + edge.data.distance = (std::max)((int)import_edge.weight(), 1 ); + BOOST_ASSERT( edge.data.distance > 0 ); + edge.data.shortcut = false; + edge.data.roundabout = import_edge.isRoundabout(); + edge.data.ignore_in_grid = import_edge.ignoreInGrid(); + edge.data.nameID = import_edge.name(); + edge.data.type = import_edge.type(); + edge.data.isAccessRestricted = import_edge.isAccessRestricted(); + edge.data.contraFlow = import_edge.isContraFlow(); + edges_list.push_back( edge ); + + if( !import_edge.IsSplit() ) { + using std::swap; //enable ADL + swap( edge.source, edge.target ); + edge.data.SwapDirectionFlags(); + edges_list.push_back( edge ); + } + } + + std::sort( edges_list.begin(), edges_list.end() ); + auto graph = boost::make_shared( + number_of_nodes, + edges_list + ); + + //FIXME probably unneeded since this is the end of scope + DeallocatingVector().swap(edges_list); + BOOST_ASSERT(0 == edges_list.size() ); + + return graph; +} + + +#endif + diff --git a/DataStructures/RestrictionMap.cpp b/DataStructures/RestrictionMap.cpp new file mode 100644 index 000000000..166c3bb23 --- /dev/null +++ b/DataStructures/RestrictionMap.cpp @@ -0,0 +1,165 @@ +#include "RestrictionMap.h" +#include "NodeBasedGraph.h" + +RestrictionMap::RestrictionMap(const boost::shared_ptr& graph, const std::vector & input_restrictions_list) +: m_count(0) +, m_graph(graph) +{ + // decompose restirction consisting of a start, via and end note into a start-edge + // and all end-nodes + for (auto& restriction : input_restrictions_list) { + std::pair restriction_source = + std::make_pair(restriction.fromNode, restriction.viaNode); + unsigned index; + auto restriction_iter = m_restriction_map.find(restriction_source); + if(restriction_iter == m_restriction_map.end()) { + index = m_restriction_bucket_list.size(); + m_restriction_bucket_list.resize(index+1); + m_restriction_map.emplace(restriction_source, index); + } else { + index = restriction_iter->second; + //Map already contains an is_only_*-restriction + if(m_restriction_bucket_list.at(index).begin()->second) { + continue; + } else if(restriction.flags.isOnly) { + //We are going to insert an is_only_*-restriction. There can be only one. + m_count -= m_restriction_bucket_list.at(index).size(); + m_restriction_bucket_list.at(index).clear(); + } + } + ++m_count; + m_restriction_bucket_list.at(index).push_back( + std::make_pair( restriction.toNode, restriction.flags.isOnly) + ); + } +} + +/** + * Replace end v with w in each turn restriction containing u as via node + * + * Note: We need access to node based graph. + */ +void RestrictionMap::FixupArrivingTurnRestriction( + const NodeID u, + const NodeID v, + const NodeID w +) { + BOOST_ASSERT( u != std::numeric_limits::max() ); + BOOST_ASSERT( v != std::numeric_limits::max() ); + BOOST_ASSERT( w != std::numeric_limits::max() ); + + // find all possible start edges + // it is more efficent to get a (small) list of potential start edges + // than iterating over all buckets + std::vector predecessors; + for( + EdgeID current_edge_id = m_graph->BeginEdges(u); + current_edge_id < m_graph->EndEdges(u); + ++current_edge_id + ) { + const EdgeData & edge_data = m_graph->GetEdgeData(current_edge_id); + const NodeID target = m_graph->GetTarget(current_edge_id); + if( edge_data.backward && ( v != target) ) { + predecessors.push_back(target); + } + } + + for(const NodeID x : predecessors) { + const std::pair restr_start = std::make_pair(x,u); + auto restriction_iterator = m_restriction_map.find( restr_start ); + if( restriction_iterator == m_restriction_map.end() ) + continue; + + const unsigned index = restriction_iterator->second; + auto& bucket = m_restriction_bucket_list.at(index); + for(RestrictionTarget& restriction_target : bucket) { + if( v == restriction_target.first ) { + restriction_target.first = w; + } + } + } +} + +/** + * Replaces the start edge (v, w) with (u, w), only start node changes. + */ +void RestrictionMap::FixupStartingTurnRestriction( + const NodeID u, + const NodeID v, + const NodeID w +) { + BOOST_ASSERT( u != std::numeric_limits::max() ); + BOOST_ASSERT( v != std::numeric_limits::max() ); + BOOST_ASSERT( w != std::numeric_limits::max() ); + + const std::pair old_start = std::make_pair(v,w); + + auto restriction_iterator = m_restriction_map.find( old_start ); + if( restriction_iterator != m_restriction_map.end() ) { + const unsigned index = restriction_iterator->second; + // remove old restriction start (v,w) + m_restriction_map.erase( restriction_iterator ); + + // insert new restriction start (u,w) (point to index) + const std::pair new_start = std::make_pair(u,w); + m_restriction_map.insert( std::make_pair(new_start, index) ); + } +} + +/* + * Check if the edge (u, v) is contained in any turn restriction. + * If so returns id of first target node. + */ +NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn( + const NodeID u, + const NodeID v +) const { + BOOST_ASSERT( u != std::numeric_limits::max() ); + BOOST_ASSERT( v != std::numeric_limits::max() ); + + const std::pair restriction_source = std::make_pair(u, v); + auto restriction_iter = m_restriction_map.find(restriction_source); + + if (restriction_iter != m_restriction_map.end()) { + const unsigned index = restriction_iter->second; + auto& bucket = m_restriction_bucket_list.at(index); + for(const RestrictionSource& restriction_target : bucket) { + if(restriction_target.second) { + return restriction_target.first; + } + } + } + + return std::numeric_limits::max(); +} + +/** + * Checks if the turn described by start u, via v and targed w is covert by any turn restriction. + */ +bool RestrictionMap::CheckIfTurnIsRestricted( + const NodeID u, + const NodeID v, + const NodeID w +) const { + BOOST_ASSERT( u != std::numeric_limits::max() ); + BOOST_ASSERT( v != std::numeric_limits::max() ); + BOOST_ASSERT( w != std::numeric_limits::max() ); + + const std::pair restriction_source = std::make_pair(u, v); + auto restriction_iter = m_restriction_map.find(restriction_source); + + if (restriction_iter != m_restriction_map.end()) { + const unsigned index = restriction_iter->second; + auto& bucket = m_restriction_bucket_list.at(index); + for(const RestrictionTarget & restriction_target : bucket) { + if( + ( w == restriction_target.first ) && // target found + ( !restriction_target.second ) // and not an only_-restr. + ) { + return true; + } + } + } + + return false; +} diff --git a/DataStructures/RestrictionMap.h b/DataStructures/RestrictionMap.h new file mode 100644 index 000000000..59311e708 --- /dev/null +++ b/DataStructures/RestrictionMap.h @@ -0,0 +1,69 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef __RESTRICTION_MAP_H__ +#define __RESTRICTION_MAP_H__ + +#include "../typedefs.h" +#include "DynamicGraph.h" +#include "Restriction.h" +#include "NodeBasedGraph.h" + +#include + +/*! + * Makee it efficent to look up if an edge is the start + via node of a TurnRestriction. + * Is needed by EdgeBasedGraphFactory. + */ +class RestrictionMap +{ +public: + RestrictionMap(const boost::shared_ptr& graph, + const std::vector & input_restrictions_list); + + void FixupArrivingTurnRestriction(const NodeID u, const NodeID v, const NodeID w); + void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w); + NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const; + bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const; + + unsigned size() { return m_count; } + +private: + typedef std::pair RestrictionSource; + typedef std::pair RestrictionTarget; + typedef std::vector EmanatingRestrictionsVector; + typedef NodeBasedDynamicGraph::EdgeData EdgeData; + + unsigned m_count; + boost::shared_ptr m_graph; + //! index -> list of (target, isOnly) + std::vector m_restriction_bucket_list; + //! maps (start, via) -> bucket index + boost::unordered_map m_restriction_map; +}; + +#endif diff --git a/prepare.cpp b/prepare.cpp index 48dd3b5ed..05d7c1980 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DataStructures/QueryEdge.h" #include "DataStructures/StaticGraph.h" #include "DataStructures/StaticRTree.h" +#include "DataStructures/RestrictionMap.h" #include "Util/GitDescription.h" #include "Util/GraphLoader.h" #include "Util/LuaUtil.h" @@ -274,12 +275,13 @@ int main(int argc, char *argv[]) */ SimpleLogger().Write() << "Generating edge-expanded graph representation"; - EdgeBasedGraphFactory *edge_based_graph_factor = - new EdgeBasedGraphFactory(number_of_node_based_nodes, - edge_list, + boost::shared_ptr node_based_graph = NodeBasedDynamicGraphFromImportEdges(number_of_node_based_nodes, edge_list); + std::unique_ptr restriction_map = std::unique_ptr(new RestrictionMap(node_based_graph, restriction_list)); + EdgeBasedGraphFactory * edge_based_graph_factor = + new EdgeBasedGraphFactory(node_based_graph, + std::move(restriction_map), barrier_node_list, traffic_light_list, - restriction_list, internal_to_external_node_map, speed_profile); edge_list.clear(); @@ -302,6 +304,9 @@ int main(int argc, char *argv[]) edge_based_graph_factor->GetEdgeBasedNodes(node_based_edge_list); delete edge_based_graph_factor; + // TODO actually use scoping: Split this up in subfunctions + node_based_graph.reset(); + std::chrono::duration end_of_expansion_time = std::chrono::steady_clock::now() - startup_time;