diff --git a/CMakeLists.txt b/CMakeLists.txt index e033134a6..155201183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) message(STATUS "Configuring OSRM in debug mode") if(NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") message(STATUS "adding profiling flags") - set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") set(CMAKE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage -fno-inline") endif() endif() @@ -92,7 +92,7 @@ endif() # Configuring compilers if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # using Clang - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunreachable-code -Wno-unknown-pragmas -Wno-unneeded-internal-declaration -pedantic -fPIC") message(STATUS "OpenMP parallelization not available using clang++") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # using GCC diff --git a/Contractor/Contractor.h b/Contractor/Contractor.h index 357f05b6d..55d54c83b 100644 --- a/Contractor/Contractor.h +++ b/Contractor/Contractor.h @@ -126,7 +126,6 @@ public: newEdge.source = diter->source(); newEdge.target = diter->target(); newEdge.data = ContractorEdgeData( (std::max)((int)diter->weight(), 1 ), 1, diter->id(), false, diter->isForward(), diter->isBackward()); - BOOST_ASSERT_MSG( newEdge.data.distance > 0, "edge distance < 1" ); #ifndef NDEBUG if ( newEdge.data.distance > 24 * 60 * 60 * 10 ) { @@ -737,6 +736,7 @@ private: if ( std::abs(priority - targetPriority) < std::numeric_limits::epsilon() && bias(node, target) ) { return false; } + // TODO: C++11 copy_if with lambda neighbours.push_back( target ); } diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index fef577840..f312fd68e 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -33,13 +33,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -//TODO: CompressionWorker -//TODO: EdgeBasedEdgeGenerator - -// template -// inline static void TraverseGraph(NodeBasedDynamicGraph & graph, Work & work) { - -// } +#include +#include +#include EdgeBasedGraphFactory::EdgeBasedGraphFactory( int number_of_nodes, @@ -47,13 +43,15 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( std::vector & barrier_node_list, std::vector & traffic_light_node_list, std::vector & input_restrictions_list, - std::vector & node_info_list, - SpeedProfileProperties speed_profile + std::vector & m_node_info_list, + SpeedProfileProperties & speed_profile ) : speed_profile(speed_profile), m_turn_restrictions_count(0), - m_node_info_list(node_info_list) + m_number_of_edge_based_nodes(std::numeric_limits::max()), + m_node_info_list(m_node_info_list), + max_id(0) { - BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) { + BOOST_FOREACH(const TurnRestriction & restriction, input_restrictions_list) { std::pair restriction_source = std::make_pair(restriction.fromNode, restriction.viaNode); unsigned index; @@ -80,7 +78,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( ); } - m_barrier_nodes.insert( + m_barrier_nodes.insert( barrier_node_list.begin(), barrier_node_list.end() ); @@ -90,10 +88,15 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( traffic_light_node_list.end() ); - DeallocatingVector< NodeBasedEdge > edges_list; + 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()) { + + if( !import_edge.isForward() ) { edge.source = import_edge.target(); edge.target = import_edge.source(); edge.data.backward = import_edge.isForward(); @@ -104,33 +107,101 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( edge.data.forward = import_edge.isForward(); edge.data.backward = import_edge.isBackward(); } - if(edge.source == edge.target) { - continue; + + 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.ignoreInGrid = import_edge.ignoreInGrid(); + 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.edgeBasedNodeID = edges_list.size(); edge.data.contraFlow = import_edge.isContraFlow(); edges_list.push_back( edge ); - if( edge.data.backward ) { - std::swap( edge.source, edge.target ); - edge.data.forward = import_edge.isBackward(); - edge.data.backward = import_edge.isForward(); - edge.data.edgeBasedNodeID = edges_list.size(); + + 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 + 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( @@ -146,8 +217,11 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges( void EdgeBasedGraphFactory::GetEdgeBasedNodes( std::vector & nodes) { #ifndef NDEBUG BOOST_FOREACH(const EdgeBasedNode & node, m_edge_based_node_list){ - BOOST_ASSERT(node.lat1 != INT_MAX); BOOST_ASSERT(node.lon1 != INT_MAX); - BOOST_ASSERT(node.lat2 != INT_MAX); BOOST_ASSERT(node.lon2 != INT_MAX); + + BOOST_ASSERT( m_node_info_list.at(node.u).lat != INT_MAX ); + BOOST_ASSERT( m_node_info_list.at(node.u).lon != INT_MAX ); + BOOST_ASSERT( m_node_info_list.at(node.v).lon != INT_MAX ); + BOOST_ASSERT( m_node_info_list.at(node.v).lat != INT_MAX ); } #endif nodes.swap(m_edge_based_node_list); @@ -157,7 +231,9 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn( const NodeID u, const NodeID v ) const { - const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); + 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()) { @@ -171,7 +247,7 @@ NodeID EdgeBasedGraphFactory::CheckForEmanatingIsOnlyTurn( } } } - return UINT_MAX; + return std::numeric_limits::max(); } bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( @@ -179,8 +255,11 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( const NodeID v, const NodeID w ) const { - //only add an edge if turn is not a U-turn except it is the end of dead-end street. - const std::pair < NodeID, NodeID > restriction_source = std::make_pair(u, v); + 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()) { @@ -189,7 +268,10 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( const RestrictionTarget & restriction_target, m_restriction_bucket_list.at(index) ) { - if(w == restriction_target.first) { + if( + ( w == restriction_target.first ) && // target found + ( !restriction_target.second ) // and not an only_-restr. + ) { return true; } } @@ -198,22 +280,175 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( } void EdgeBasedGraphFactory::InsertEdgeBasedNode( - EdgeIterator e1, - NodeIterator u, - NodeIterator v, - bool belongsToTinyComponent) { - EdgeData & data = m_node_based_graph->GetEdgeData(e1); - EdgeBasedNode currentNode; - currentNode.nameID = data.nameID; - currentNode.lat1 = m_node_info_list[u].lat; - currentNode.lon1 = m_node_info_list[u].lon; - currentNode.lat2 = m_node_info_list[v].lat; - currentNode.lon2 = m_node_info_list[v].lon; - currentNode.belongsToTinyComponent = belongsToTinyComponent; - currentNode.id = data.edgeBasedNodeID; - currentNode.ignoreInGrid = data.ignoreInGrid; - currentNode.weight = data.distance; - m_edge_based_node_list.push_back(currentNode); + NodeIterator u, + NodeIterator v, + EdgeIterator e1, + bool belongs_to_tiny_cc +) { + // merge edges together into one EdgeBasedNode + BOOST_ASSERT( u != SPECIAL_NODEID ); + BOOST_ASSERT( v != SPECIAL_NODEID ); + BOOST_ASSERT( e1 != SPECIAL_EDGEID ); + +#ifndef NDEBUG + // find forward edge id and + const EdgeID e1b = m_node_based_graph->FindEdge(u, v); + BOOST_ASSERT( e1 == e1b ); +#endif + + BOOST_ASSERT( e1 != SPECIAL_EDGEID ); + const EdgeData & forward_data = m_node_based_graph->GetEdgeData(e1); + + // find reverse edge id and + const EdgeID e2 = m_node_based_graph->FindEdge(v, u); + +#ifndef NDEBUG + if ( e2 == m_node_based_graph->EndEdges(v) ) { + SimpleLogger().Write(logWARNING) << "Did not find edge (" << v << "," << u << ")"; + } +#endif + BOOST_ASSERT( e2 != SPECIAL_EDGEID ); + BOOST_ASSERT( e2 < m_node_based_graph->EndEdges(v) ); + const EdgeData & reverse_data = m_node_based_graph->GetEdgeData(e2); + + if( + forward_data.edgeBasedNodeID == SPECIAL_NODEID && + reverse_data.edgeBasedNodeID == SPECIAL_NODEID + ) { + return; + } + + BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e1) == m_geometry_compressor.HasEntryForID(e2) ); + if( m_geometry_compressor.HasEntryForID(e1) ) { + + BOOST_ASSERT( m_geometry_compressor.HasEntryForID(e2) ); + + // reconstruct geometry and put in each individual edge with its offset + const std::vector & forward_geometry = m_geometry_compressor.GetBucketReference(e1); + const std::vector & reverse_geometry = m_geometry_compressor.GetBucketReference(e2); + BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() ); + BOOST_ASSERT( 0 != forward_geometry.size() ); + + // reconstruct bidirectional edge with individual weights and put each into the NN index + + std::vector forward_dist_prefix_sum(forward_geometry.size(), 0); + std::vector reverse_dist_prefix_sum(reverse_geometry.size(), 0); + + // quick'n'dirty prefix sum as std::partial_sum needs addtional casts + // TODO: move to lambda function with C++11 + int temp_sum = 0; + + for (unsigned i = 0; i < forward_geometry.size(); ++i) + { + forward_dist_prefix_sum[i] = temp_sum; + temp_sum += forward_geometry[i].second; + + BOOST_ASSERT( forward_data.distance >= temp_sum ); + } + + temp_sum = 0; + for( unsigned i = 0; i < reverse_geometry.size(); ++i ) { + temp_sum += reverse_geometry[reverse_geometry.size()-1-i].second; + reverse_dist_prefix_sum[i] = reverse_data.distance - temp_sum; + BOOST_ASSERT( reverse_data.distance >= temp_sum ); + } + + BOOST_ASSERT( forward_geometry.size() == reverse_geometry.size() ); + + const unsigned geometry_size = forward_geometry.size(); + BOOST_ASSERT( geometry_size > 1 ); + NodeID current_edge_start_coordinate_id = u; + + if (forward_data.edgeBasedNodeID != SPECIAL_NODEID) + { + max_id = std::max(forward_data.edgeBasedNodeID, max_id); + } + if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID) + { + max_id = std::max(reverse_data.edgeBasedNodeID, max_id); + } + + // traverse arrays from start and end respectively + for( unsigned i = 0; i < geometry_size; ++i ) { + BOOST_ASSERT( current_edge_start_coordinate_id == reverse_geometry[geometry_size-1-i].first ); + const NodeID current_edge_target_coordinate_id = forward_geometry[i].first; + BOOST_ASSERT( current_edge_target_coordinate_id != current_edge_start_coordinate_id); + + // build edges + m_edge_based_node_list.push_back( + EdgeBasedNode( + forward_data.edgeBasedNodeID, + reverse_data.edgeBasedNodeID, + current_edge_start_coordinate_id, + current_edge_target_coordinate_id, + forward_data.nameID, + forward_geometry[i].second, + reverse_geometry[i].second, + forward_dist_prefix_sum[i], + reverse_dist_prefix_sum[i], + m_geometry_compressor.GetPositionForID(e1), + i, + belongs_to_tiny_cc + ) + ); + current_edge_start_coordinate_id = current_edge_target_coordinate_id; + + BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() ); + + BOOST_ASSERT( + u != m_edge_based_node_list.back().u || + v != m_edge_based_node_list.back().v + ); + + BOOST_ASSERT( + u != m_edge_based_node_list.back().v || + v != m_edge_based_node_list.back().u + ); + } + + BOOST_ASSERT( current_edge_start_coordinate_id == v ); + BOOST_ASSERT( m_edge_based_node_list.back().IsCompressed() ); + + } else { + BOOST_ASSERT( !m_geometry_compressor.HasEntryForID(e2) ); + + if( forward_data.edgeBasedNodeID != std::numeric_limits::max() ) { + BOOST_ASSERT( forward_data.forward ); + } + if( reverse_data.edgeBasedNodeID != std::numeric_limits::max() ) { + BOOST_ASSERT( reverse_data.forward ); + } + if( forward_data.edgeBasedNodeID == std::numeric_limits::max() ) { + BOOST_ASSERT( !forward_data.forward ); + } + if( reverse_data.edgeBasedNodeID == std::numeric_limits::max() ) { + BOOST_ASSERT( !reverse_data.forward ); + } + + BOOST_ASSERT( + forward_data.edgeBasedNodeID != SPECIAL_NODEID || + reverse_data.edgeBasedNodeID != SPECIAL_NODEID + ); + + //TODO C++11: emplace_back with + m_edge_based_node_list.push_back( + EdgeBasedNode( + forward_data.edgeBasedNodeID, + reverse_data.edgeBasedNodeID, + u, + v, + forward_data.nameID, + forward_data.distance, + reverse_data.distance, + 0, + 0, + SPECIAL_EDGEID, + 0, + belongs_to_tiny_cc + ) + ); + BOOST_ASSERT( !m_edge_based_node_list.back().IsCompressed() ); + } } @@ -229,27 +464,173 @@ void EdgeBasedGraphFactory::FlushVectorToStream( } void EdgeBasedGraphFactory::Run( - const char * original_edge_data_filename, + const std::string & original_edge_data_filename, + const std::string & geometry_filename, lua_State *lua_state ) { - SimpleLogger().Write() << "Compressing geometry of input graph"; - //TODO: iterate over all turns + SimpleLogger().Write() << "Removing graph geometry while preserving topology"; - //TODO: compress geometries + const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes(); + const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges(); - //TODO: update turn restrictions if concerned by compression + Percent p(original_number_of_nodes); + unsigned removed_node_count = 0; - //TODO: do some compression statistics + for( NodeID v = 0; v < original_number_of_nodes; ++v ) { + p.printStatus(v); + // only contract degree 2 vertices + if( 2 != m_node_based_graph->GetOutDegree(v) ) { + continue; + } + + // don't contract barrier node + if( m_barrier_nodes.end() != m_barrier_nodes.find(v) ) { + continue; + } + + const bool reverse_edge_order = !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward); + const EdgeIterator forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order; + BOOST_ASSERT( std::numeric_limits::max() != forward_e2 ); + const EdgeIterator reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order; + BOOST_ASSERT( std::numeric_limits::max() != reverse_e2 ); + + const EdgeData & fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2); + const EdgeData & rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2); + + const NodeIterator w = m_node_based_graph->GetTarget(forward_e2); + BOOST_ASSERT( std::numeric_limits::max() != w ); + BOOST_ASSERT( v != w ); + const NodeIterator u = m_node_based_graph->GetTarget(reverse_e2); + BOOST_ASSERT( std::numeric_limits::max() != u ); + BOOST_ASSERT( u != v ); + + const EdgeIterator forward_e1 = m_node_based_graph->FindEdge(u, v); + BOOST_ASSERT( m_node_based_graph->EndEdges(u) != forward_e1 ); + BOOST_ASSERT( std::numeric_limits::max() != forward_e1 ); + BOOST_ASSERT( v == m_node_based_graph->GetTarget(forward_e1)); + const EdgeIterator reverse_e1 = m_node_based_graph->FindEdge(w, v); + BOOST_ASSERT( std::numeric_limits::max() != reverse_e1 ); + BOOST_ASSERT( v == m_node_based_graph->GetTarget(reverse_e1)); + + const EdgeData & fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1); + const EdgeData & rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1); + + if( + ( m_node_based_graph->FindEdge(u, w) != m_node_based_graph->EndEdges(u) ) || + ( m_node_based_graph->FindEdge(w, u) != m_node_based_graph->EndEdges(w) ) + ) { + continue; + } + + if ( //TODO: rename to IsCompatibleTo + fwd_edge_data1.IsEqualTo(fwd_edge_data2) && + rev_edge_data1.IsEqualTo(rev_edge_data2) + ) { + //Get distances before graph is modified + const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance; + const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance; + + BOOST_ASSERT( 0 != forward_weight1 ); + BOOST_ASSERT( 0 != forward_weight2 ); + + const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance; + const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance; + + BOOST_ASSERT( 0 != reverse_weight1 ); + BOOST_ASSERT( 0 != forward_weight2 ); + + const bool add_traffic_signal_penalty = (m_traffic_lights.find(v) != m_traffic_lights.end()); + + // add weight of e2's to e1 + m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance; + m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance; + if (add_traffic_signal_penalty) + { + m_node_based_graph->GetEdgeData(forward_e1).distance += speed_profile.trafficSignalPenalty; + m_node_based_graph->GetEdgeData(reverse_e1).distance += speed_profile.trafficSignalPenalty; + } + + // extend e1's to targets of e2's + m_node_based_graph->SetTarget(forward_e1, w); + m_node_based_graph->SetTarget(reverse_e1, u); + + // remove e2's (if bidir, otherwise only one) + m_node_based_graph->DeleteEdge(v, forward_e2); + m_node_based_graph->DeleteEdge(v, reverse_e2); + + // update any involved turn restrictions + FixupStartingTurnRestriction( u, v, w ); + FixupArrivingTurnRestriction( u, v, w ); + + FixupStartingTurnRestriction( w, v, u ); + FixupArrivingTurnRestriction( w, v, u ); + + // store compressed geometry in container + m_geometry_compressor.CompressEdge( + forward_e1, + forward_e2, + v, + w, + forward_weight1 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0), + forward_weight2 + ); + m_geometry_compressor.CompressEdge( + reverse_e1, + reverse_e2, + v, + u, + reverse_weight1 , + reverse_weight2 + (add_traffic_signal_penalty ? speed_profile.trafficSignalPenalty :0) + ); + ++removed_node_count; + + BOOST_ASSERT + ( + m_node_based_graph->GetEdgeData(forward_e1).nameID == + m_node_based_graph->GetEdgeData(reverse_e1).nameID + ); + } + } + SimpleLogger().Write() << "removed " << removed_node_count << " nodes"; + m_geometry_compressor.PrintStatistics(); + + unsigned new_node_count = 0; + unsigned new_edge_count = 0; + for( unsigned i = 0; i < m_node_based_graph->GetNumberOfNodes(); ++i ) { + if( m_node_based_graph->GetOutDegree(i) > 0 ) { + ++new_node_count; + new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i)); + } + } + SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count; + SimpleLogger().Write() << "Node compression ratio: " << new_node_count/(double)original_number_of_nodes; + SimpleLogger().Write() << "Edge compression ratio: " << new_edge_count/(double)original_number_of_edges; + + // renumber edge based node IDs + unsigned numbered_edges_count = 0; + for(NodeID current_node = 0; current_node < m_node_based_graph->GetNumberOfNodes(); ++current_node) { + for(EdgeIterator current_edge = m_node_based_graph->BeginEdges(current_node); current_edge < m_node_based_graph->EndEdges(current_node); ++current_edge) { + EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge); + if( !edge_data.forward ) { + continue; + } + + BOOST_ASSERT( numbered_edges_count < m_node_based_graph->GetNumberOfEdges() ); + edge_data.edgeBasedNodeID = numbered_edges_count; + ++numbered_edges_count; + + BOOST_ASSERT( std::numeric_limits::max() != edge_data.edgeBasedNodeID); + } + } SimpleLogger().Write() << "Identifying components of the road network"; - unsigned skipped_turns_counter = 0; unsigned node_based_edge_counter = 0; unsigned original_edges_counter = 0; std::ofstream edge_data_file( - original_edge_data_filename, + original_edge_data_filename.c_str(), std::ios::binary ); @@ -261,49 +642,62 @@ void EdgeBasedGraphFactory::Run( //Run a BFS on the undirected graph and identify small components std::vector component_index_list; - std::vector component_index_size; - BFSCompentExplorer( component_index_list, component_index_size); + std::vector component_index_size; + BFSCompentExplorer( component_index_list, component_index_size ); SimpleLogger().Write() << "identified: " << component_index_size.size() << " many components"; - SimpleLogger().Write() << - "generating edge-expanded nodes"; + SimpleLogger().Write() << "generating edge-expanded nodes"; - Percent p(m_node_based_graph->GetNumberOfNodes()); - //loop over all edges and generate new set of nodes. + p.reinit(m_node_based_graph->GetNumberOfNodes()); + + //loop over all edges and generate new set of nodes for( NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); u < end; ++u ) { + BOOST_ASSERT( u != std::numeric_limits::max() ); + BOOST_ASSERT( u < m_node_based_graph->GetNumberOfNodes() ); p.printIncrement(); for( - EdgeIterator e1 = m_node_based_graph->BeginEdges(u), + EdgeID e1 = m_node_based_graph->BeginEdges(u), last_edge = m_node_based_graph->EndEdges(u); e1 < last_edge; ++e1 ) { - NodeIterator v = m_node_based_graph->GetTarget(e1); + const EdgeData & edge_data = m_node_based_graph->GetEdgeData(e1); + if( edge_data.edgeBasedNodeID == SPECIAL_NODEID ) { + // continue; + } + BOOST_ASSERT( e1 != SPECIAL_EDGEID ); + const NodeID v = m_node_based_graph->GetTarget(e1); + + BOOST_ASSERT( SPECIAL_NODEID != v ); + // pick only every other edge + if( u > v ) { + continue; + } + + BOOST_ASSERT( u < v ); + BOOST_ASSERT( edge_data.type != SHRT_MAX ); - if(m_node_based_graph->GetEdgeData(e1).type != SHRT_MAX) { - BOOST_ASSERT_MSG(e1 != UINT_MAX, "edge id invalid"); - BOOST_ASSERT_MSG(u != UINT_MAX, "souce node invalid"); - BOOST_ASSERT_MSG(v != UINT_MAX, "target node invalid"); //Note: edges that end on barrier nodes or on a turn restriction //may actually be in two distinct components. We choose the smallest - const unsigned size_of_component = std::min( - component_index_size[component_index_list[u]], - component_index_size[component_index_list[v]] - ); + const unsigned size_of_component = std::min( + component_index_size[component_index_list[u]], + component_index_size[component_index_list[v]] + ); - InsertEdgeBasedNode( e1, u, v, size_of_component < 1000 ); - } + const bool component_is_tiny = ( size_of_component < 1000 ); + InsertEdgeBasedNode( u, v, e1, component_is_tiny ); } } - SimpleLogger().Write() - << "Generated " << m_edge_based_node_list.size() << " nodes in " << - "edge-expanded graph"; + m_number_of_edge_based_nodes = numbered_edges_count; + + SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << + " nodes in edge-expanded graph"; SimpleLogger().Write() << "generating edge-expanded edges"; std::vector().swap(component_index_size); @@ -322,6 +716,10 @@ void EdgeBasedGraphFactory::Run( //Loop over all turns and generate new set of edges. //Three nested loop look super-linear, but we are dealing with a (kind of) //linear number of turns only. + unsigned restricted_turns_counter = 0; + unsigned skipped_uturns_counter = 0; + unsigned skipped_barrier_turns_counter = 0; + unsigned compressed = 0; p.reinit(m_node_based_graph->GetNumberOfNodes()); for( NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); @@ -334,6 +732,10 @@ void EdgeBasedGraphFactory::Run( e1 < last_edge_u; ++e1 ) { + if( !m_node_based_graph->GetEdgeData(e1).forward ) { + continue; + } + ++node_based_edge_counter; const NodeIterator v = m_node_based_graph->GetTarget(e1); const NodeID to_node_of_only_restriction = CheckForEmanatingIsOnlyTurn(u, v); @@ -345,24 +747,28 @@ void EdgeBasedGraphFactory::Run( e2 < last_edge_v; ++e2 ) { + if( !m_node_based_graph->GetEdgeData(e2).forward ) { + continue; + } const NodeIterator w = m_node_based_graph->GetTarget(e2); + if( - to_node_of_only_restriction != UINT_MAX && + to_node_of_only_restriction != SPECIAL_NODEID && w != to_node_of_only_restriction ) { //We are at an only_-restriction but not at the right turn. - ++skipped_turns_counter; + ++restricted_turns_counter; continue; } if( is_barrier_node) { if(u != w) { - ++skipped_turns_counter; + ++skipped_barrier_turns_counter; continue; } } else { if ( (u == w) && (m_node_based_graph->GetOutDegree(v) > 1) ) { - ++skipped_turns_counter; + ++skipped_uturns_counter; continue; } } @@ -371,28 +777,20 @@ void EdgeBasedGraphFactory::Run( //at the end of a dead-end street if ( CheckIfTurnIsRestricted(u, v, w) && - (to_node_of_only_restriction == UINT_MAX) && + (to_node_of_only_restriction == SPECIAL_NODEID) && (w != to_node_of_only_restriction) ) { - ++skipped_turns_counter; + ++restricted_turns_counter; continue; } //only add an edge if turn is not prohibited - const EdgeData edge_data1 = m_node_based_graph->GetEdgeData(e1); - const EdgeData edge_data2 = m_node_based_graph->GetEdgeData(e2); + const EdgeData & edge_data1 = m_node_based_graph->GetEdgeData(e1); + const EdgeData & edge_data2 = m_node_based_graph->GetEdgeData(e2); - BOOST_ASSERT( - edge_data1.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() - ); - BOOST_ASSERT( - edge_data2.edgeBasedNodeID < m_node_based_graph->GetNumberOfEdges() - ); - BOOST_ASSERT( - edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID - ); - BOOST_ASSERT( edge_data1.forward ); - BOOST_ASSERT( edge_data2.forward ); + BOOST_ASSERT(edge_data1.edgeBasedNodeID != edge_data2.edgeBasedNodeID); + BOOST_ASSERT(edge_data1.forward); + BOOST_ASSERT(edge_data2.forward); // the following is the core of the loop. unsigned distance = edge_data1.distance; @@ -400,19 +798,27 @@ void EdgeBasedGraphFactory::Run( distance += speed_profile.trafficSignalPenalty; } const int turn_penalty = GetTurnPenalty(u, v, w, lua_state); - TurnInstruction turnInstruction = AnalyzeTurn(u, v, w); - if(turnInstruction == TurnInstructions.UTurn){ + TurnInstruction turn_instruction = AnalyzeTurn(u, v, w); + if(turn_instruction == TurnInstructionsClass::UTurn){ distance += speed_profile.uTurnPenalty; } distance += turn_penalty; + const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1); + + if(edge_is_compressed) { + ++compressed; + } + original_edge_data_vector.push_back( OriginalEdgeData( - v, - edge_data2.nameID, - turnInstruction + (edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v), + edge_data1.nameID, + turn_instruction, + edge_is_compressed ) ); + ++original_edges_counter; if(original_edge_data_vector.size() > 100000) { @@ -422,6 +828,9 @@ void EdgeBasedGraphFactory::Run( ); } + BOOST_ASSERT( SPECIAL_NODEID != edge_data1.edgeBasedNodeID ); + BOOST_ASSERT( SPECIAL_NODEID != edge_data2.edgeBasedNodeID ); + m_edge_based_edge_list.push_back( EdgeBasedEdge( edge_data1.edgeBasedNodeID, @@ -442,17 +851,16 @@ void EdgeBasedGraphFactory::Run( edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); edge_data_file.close(); - SimpleLogger().Write() << - "Generated " << m_edge_based_node_list.size() << " edge based nodes"; - SimpleLogger().Write() << - "Node-based graph contains " << node_based_edge_counter << " edges"; - SimpleLogger().Write() << - "Edge-expanded graph ..."; - SimpleLogger().Write() << - " contains " << m_edge_based_edge_list.size() << " edges"; - SimpleLogger().Write() << - " skips " << skipped_turns_counter << " turns, " - "defined by " << m_turn_restrictions_count << " restrictions"; + m_geometry_compressor.SerializeInternalVector( geometry_filename ); + + SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes"; + SimpleLogger().Write() << "Node-based graph contains " << node_based_edge_counter << " edges"; + 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"; + SimpleLogger().Write() << " skips " << skipped_uturns_counter << " U turns"; + SimpleLogger().Write() << " skips " << skipped_barrier_turns_counter << " turns over barriers"; } int EdgeBasedGraphFactory::GetTurnPenalty( @@ -488,7 +896,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( const NodeID w ) const { if(u == w) { - return TurnInstructions.UTurn; + return TurnInstructionsClass::UTurn; } const EdgeIterator edge1 = m_node_based_graph->FindEdge(u, v); @@ -498,10 +906,10 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( const EdgeData & data2 = m_node_based_graph->GetEdgeData(edge2); if(!data1.contraFlow && data2.contraFlow) { - return TurnInstructions.EnterAgainstAllowedDirection; + return TurnInstructionsClass::EnterAgainstAllowedDirection; } if(data1.contraFlow && !data2.contraFlow) { - return TurnInstructions.LeaveAgainstAllowedDirection; + return TurnInstructionsClass::LeaveAgainstAllowedDirection; } //roundabouts need to be handled explicitely @@ -509,19 +917,19 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( //Is a turn possible? If yes, we stay on the roundabout! if( 1 == m_node_based_graph->GetOutDegree(v) ) { //No turn possible. - return TurnInstructions.NoTurn; + return TurnInstructionsClass::NoTurn; } - return TurnInstructions.StayOnRoundAbout; + return TurnInstructionsClass::StayOnRoundAbout; } //Does turn start or end on roundabout? if(data1.roundabout || data2.roundabout) { //We are entering the roundabout if( (!data1.roundabout) && data2.roundabout) { - return TurnInstructions.EnterRoundAbout; + return TurnInstructionsClass::EnterRoundAbout; } //We are leaving the roundabout if(data1.roundabout && (!data2.roundabout) ) { - return TurnInstructions.LeaveRoundAbout; + return TurnInstructionsClass::LeaveRoundAbout; } } @@ -531,9 +939,9 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( //TODO: Here we should also do a small graph exploration to check for // more complex situations if( 0 != data1.nameID ) { - return TurnInstructions.NoTurn; + return TurnInstructionsClass::NoTurn; } else if (m_node_based_graph->GetOutDegree(v) <= 2) { - return TurnInstructions.NoTurn; + return TurnInstructionsClass::NoTurn; } } @@ -542,11 +950,11 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn( m_node_info_list[v], m_node_info_list[w] ); - return TurnInstructions.GetTurnDirectionOfInstruction(angle); + return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle); } -unsigned EdgeBasedGraphFactory::GetNumberOfNodes() const { - return m_node_based_graph->GetNumberOfEdges(); +unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const { + return m_number_of_edge_based_nodes; } void EdgeBasedGraphFactory::BFSCompentExplorer( @@ -563,12 +971,12 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( component_index_list.resize( m_node_based_graph->GetNumberOfNodes(), - UINT_MAX + std::numeric_limits::max() ); //put unexplorered node with parent pointer into queue for( NodeID node = 0, end = m_node_based_graph->GetNumberOfNodes(); node < end; ++node) { - if(UINT_MAX == component_index_list[node]) { + if(std::numeric_limits::max() == component_index_list[node]) { bfs_queue.push(std::make_pair(node, node)); //mark node as read component_index_list[node] = current_component; @@ -594,7 +1002,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( NodeIterator w = m_node_based_graph->GetTarget(e2); if( - to_node_of_only_restriction != UINT_MAX && + 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 @@ -605,7 +1013,7 @@ void EdgeBasedGraphFactory::BFSCompentExplorer( //when it is at the end of a dead-end street. if (!CheckIfTurnIsRestricted(u, v, w) ) { //only add an edge if turn is not prohibited - if(UINT_MAX == component_index_list[w]) { + if(std::numeric_limits::max() == component_index_list[w]) { //insert next (node, parent) only if w has //not yet been explored //mark node as read diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 4621d752c..c949f1622 100644 --- a/Contractor/EdgeBasedGraphFactory.h +++ b/Contractor/EdgeBasedGraphFactory.h @@ -53,23 +53,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -#include +#include #include #include class EdgeBasedGraphFactory : boost::noncopyable { public: - struct SpeedProfileProperties{ - SpeedProfileProperties() : - trafficSignalPenalty(0), - uTurnPenalty(0), - has_turn_penalty_function(false) - { } - - int trafficSignalPenalty; - int uTurnPenalty; - bool has_turn_penalty_function; - } speed_profile; + struct SpeedProfileProperties; explicit EdgeBasedGraphFactory( int number_of_nodes, @@ -78,10 +68,14 @@ public: std::vector & traffic_light_node_list, std::vector & input_restrictions_list, std::vector & m_node_info_list, - SpeedProfileProperties speed_profile + SpeedProfileProperties & speed_profile ); - void Run(const char * originalEdgeDataFilename, lua_State *myLuaState); + void Run( + const std::string & original_edge_data_filename, + const std::string & geometry_filename, + lua_State *myLuaState + ); void GetEdgeBasedEdges( DeallocatingVector< EdgeBasedEdge >& edges ); @@ -100,10 +94,27 @@ public: lua_State *myLuaState ) const; - unsigned GetNumberOfNodes() const; + unsigned GetNumberOfEdgeBasedNodes() const; + + struct SpeedProfileProperties{ + SpeedProfileProperties() : + trafficSignalPenalty(0), + uTurnPenalty(0), + has_turn_penalty_function(false) + { } + + int trafficSignalPenalty; + int uTurnPenalty; + bool has_turn_penalty_function; + } speed_profile; private: struct NodeBasedEdgeData { + NodeBasedEdgeData() { + //TODO: proper c'tor + edgeBasedNodeID = UINT_MAX; + } + int distance; unsigned edgeBasedNodeID; unsigned nameID; @@ -113,11 +124,26 @@ private: bool forward:1; bool backward:1; bool roundabout:1; - bool ignoreInGrid: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; @@ -139,6 +165,7 @@ private: boost::unordered_set m_traffic_lights; RestrictionMap m_restriction_map; + GeometryCompressor m_geometry_compressor; NodeID CheckForEmanatingIsOnlyTurn( const NodeID u, @@ -152,9 +179,9 @@ private: ) const; void InsertEdgeBasedNode( - NodeBasedDynamicGraph::EdgeIterator e1, NodeBasedDynamicGraph::NodeIterator u, NodeBasedDynamicGraph::NodeIterator v, + NodeBasedDynamicGraph::EdgeIterator e1, bool belongsToTinyComponent ); @@ -167,6 +194,20 @@ private: std::ofstream & edge_data_file, std::vector & original_edge_data_vector ) const; + + void FixupArrivingTurnRestriction( + const NodeID u, + const NodeID v, + const NodeID w + ); + + void FixupStartingTurnRestriction( + const NodeID u, + const NodeID v, + const NodeID w + ); + + unsigned max_id; }; #endif /* EDGEBASEDGRAPHFACTORY_H_ */ diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp index 5f97a751c..e0d5752d0 100644 --- a/Contractor/GeometryCompressor.cpp +++ b/Contractor/GeometryCompressor.cpp @@ -26,69 +26,199 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "GeometryCompressor.h" +#include "../Util/SimpleLogger.h" + +#include +#include +#include +#include + +#include int current_free_list_maximum = 0; -int UniqueNumber () { return ++current_free_list_maximum; } +int UniqueNumber() { return ++current_free_list_maximum; } -GeometryCompressor::GeometryCompressor() { - m_free_list.resize(100); +GeometryCompressor::GeometryCompressor() +{ + m_free_list.reserve(100); IncreaseFreeList(); } -void GeometryCompressor::IncreaseFreeList() { +void GeometryCompressor::IncreaseFreeList() +{ m_compressed_geometries.resize(m_compressed_geometries.size() + 100); - std::generate_n (m_free_list.rend(), 100, UniqueNumber); + for (unsigned i = 100; i > 0; --i) + { + m_free_list.push_back(current_free_list_maximum); + ++current_free_list_maximum; + } } -void GeometryCompressor::AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ) { - //check if node_id already has a list - boost::unordered_map::const_iterator map_iterator; - map_iterator = m_node_id_to_index_map.find( node_id ); +bool GeometryCompressor::HasEntryForID(const EdgeID edge_id) const +{ + return (m_edge_id_to_list_index_map.find(edge_id) != m_edge_id_to_list_index_map.end()); +} - unsigned geometry_bucket_index = std::numeric_limits::max(); - if( m_node_id_to_index_map.end() == map_iterator ) { - //if not, create one - if( m_free_list.empty() ) { +unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) const +{ + boost::unordered_map::const_iterator map_iterator; + map_iterator = m_edge_id_to_list_index_map.find(edge_id); + BOOST_ASSERT(map_iterator != m_edge_id_to_list_index_map.end()); + BOOST_ASSERT(map_iterator->second < m_compressed_geometries.size()); + return map_iterator->second; +} + +void GeometryCompressor::SerializeInternalVector(const std::string &path) const +{ + + boost::filesystem::fstream geometry_out_stream(path, std::ios::binary|std::ios::out); + const unsigned number_of_compressed_geometries = m_compressed_geometries.size() + 1; + BOOST_ASSERT(UINT_MAX != number_of_compressed_geometries); + geometry_out_stream.write((char *)&number_of_compressed_geometries, sizeof(unsigned)); + + // write indices array + unsigned prefix_sum_of_list_indices = 0; + for (unsigned i = 0; i < m_compressed_geometries.size(); ++i) + { + geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned)); + + const std::vector ¤t_vector = m_compressed_geometries.at(i); + const unsigned unpacked_size = current_vector.size(); + BOOST_ASSERT(UINT_MAX != unpacked_size); + prefix_sum_of_list_indices += unpacked_size; + } + // sentinel element + geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned)); + + // number of geometry entries to follow, it is the (inclusive) prefix sum + geometry_out_stream.write((char *)&prefix_sum_of_list_indices, sizeof(unsigned)); + + unsigned control_sum = 0; + // write compressed geometries + for (unsigned i = 0; i < m_compressed_geometries.size(); ++i) + { + const std::vector ¤t_vector = m_compressed_geometries[i]; + const unsigned unpacked_size = current_vector.size(); + control_sum += unpacked_size; + BOOST_ASSERT(UINT_MAX != unpacked_size); + BOOST_FOREACH (const CompressedNode current_node, current_vector) + { + geometry_out_stream.write((char *)&(current_node.first), sizeof(NodeID)); + } + } + BOOST_ASSERT(control_sum == prefix_sum_of_list_indices); + // all done, let's close the resource + geometry_out_stream.close(); +} + +void GeometryCompressor::CompressEdge(const EdgeID edge_id_1, + const EdgeID edge_id_2, + const NodeID via_node_id, + const NodeID target_node_id, + const EdgeWeight weight1, + const EdgeWeight weight2) +{ + // remove super-trivial geometries + BOOST_ASSERT(SPECIAL_EDGEID != edge_id_1); + BOOST_ASSERT(SPECIAL_EDGEID != edge_id_2); + BOOST_ASSERT(SPECIAL_NODEID != via_node_id); + BOOST_ASSERT(SPECIAL_NODEID != target_node_id); + BOOST_ASSERT(std::numeric_limits::max() != weight1); + BOOST_ASSERT(std::numeric_limits::max() != weight2); + + // append list of removed edge_id plus via node to surviving edge id: + // second; } - BOOST_ASSERT( std::numeric_limits::max() != geometry_bucket_index ); - BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() ); + const unsigned edge_bucket_id1 = m_edge_id_to_list_index_map[edge_id_1]; + BOOST_ASSERT(edge_bucket_id1 == GetPositionForID(edge_id_1)); + BOOST_ASSERT(edge_bucket_id1 < m_compressed_geometries.size()); - //append contracted_node_id to m_compressed_geometries[node_id] - m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id); + std::vector &edge_bucket_list1 = m_compressed_geometries[edge_bucket_id1]; - //append m_compressed_geometries[contracted_node_id] to m_compressed_geometries[node_id] - map_iterator = m_node_id_to_index_map.find(contracted_node_id); - if ( m_node_id_to_index_map.end() != map_iterator) { - const unsigned bucket_index_to_remove = map_iterator->second; - BOOST_ASSERT( bucket_index_to_remove < m_compressed_geometries.size() ); + if (edge_bucket_list1.empty()) + { + edge_bucket_list1.push_back(std::make_pair(via_node_id, weight1)); + } - m_compressed_geometries[geometry_bucket_index].insert( - m_compressed_geometries[geometry_bucket_index].end(), - m_compressed_geometries[bucket_index_to_remove].begin(), - m_compressed_geometries[bucket_index_to_remove].end() - ); - //remove m_compressed_geometries[contracted_node_id], add to free list - m_compressed_geometries[bucket_index_to_remove].clear(); - m_free_list.push_back(bucket_index_to_remove); + BOOST_ASSERT(0 < edge_bucket_list1.size()); + BOOST_ASSERT(!edge_bucket_list1.empty()); + + if (HasEntryForID(edge_id_2)) + { + // second edge is not atomic anymore + const unsigned list_to_remove_index = GetPositionForID(edge_id_2); + BOOST_ASSERT(list_to_remove_index < m_compressed_geometries.size()); + + std::vector &edge_bucket_list2 = + m_compressed_geometries[list_to_remove_index]; + + // found an existing list, append it to the list of edge_id_1 + edge_bucket_list1.insert( + edge_bucket_list1.end(), edge_bucket_list2.begin(), edge_bucket_list2.end()); + + // remove the list of edge_id_2 + m_edge_id_to_list_index_map.erase(edge_id_2); + BOOST_ASSERT(m_edge_id_to_list_index_map.end() == + m_edge_id_to_list_index_map.find(edge_id_2)); + edge_bucket_list2.clear(); + BOOST_ASSERT(0 == edge_bucket_list2.size()); + m_free_list.push_back(list_to_remove_index); + BOOST_ASSERT(list_to_remove_index == m_free_list.back()); + } + else + { + // we are certain that the second edge is atomic. + edge_bucket_list1.push_back(std::make_pair(target_node_id, weight2)); } } -void GeometryCompressor::PrintStatistics() const { - unsigned compressed_node_count = 0; - const unsigned surviving_node_count = m_compressed_geometries.size(); +void GeometryCompressor::PrintStatistics() const +{ + const uint64_t compressed_edges = m_compressed_geometries.size(); + BOOST_ASSERT(0 == compressed_edges % 2); + BOOST_ASSERT(m_compressed_geometries.size() + m_free_list.size() > 0); - BOOST_FOREACH(const std::vector & current_vector, m_compressed_geometries) { - compressed_node_count += current_vector.size(); + uint64_t number_of_compressed_geometries = 0; + uint64_t longest_chain_length = 0; + BOOST_FOREACH (const std::vector ¤t_vector, m_compressed_geometries) + { + number_of_compressed_geometries += current_vector.size(); + longest_chain_length = std::max(longest_chain_length, (uint64_t)current_vector.size()); } - SimpleLogger().Write() << - "surv: " << surviving_node_count << - ", comp: " << compressed_node_count << - ", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) ); + + SimpleLogger().Write() << "Geometry successfully removed:" + "\n compressed edges: " << compressed_edges + << "\n compressed geometries: " << number_of_compressed_geometries + << "\n longest chain length: " << longest_chain_length + << "\n cmpr ratio: " + << ((float)compressed_edges / + std::max(number_of_compressed_geometries, (uint64_t)1)) + << "\n avg chain length: " + << (float)number_of_compressed_geometries / + std::max((uint64_t)1, compressed_edges); +} + +const std::vector & +GeometryCompressor::GetBucketReference(const EdgeID edge_id) const +{ + const unsigned index = m_edge_id_to_list_index_map.at(edge_id); + return m_compressed_geometries.at(index); } diff --git a/Contractor/GeometryCompressor.h b/Contractor/GeometryCompressor.h index 8d2bf66a6..39c92d45d 100644 --- a/Contractor/GeometryCompressor.h +++ b/Contractor/GeometryCompressor.h @@ -25,34 +25,40 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../Util/SimpleLogger.h" #include "../typedefs.h" -#include -#include #include -#include -#include #include #ifndef GEOMETRY_COMPRESSOR_H #define GEOMETRY_COMPRESSOR_H -class GeometryCompressor { -public: +class GeometryCompressor +{ + public: + typedef std::pair CompressedNode; + GeometryCompressor(); - void AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ); + void CompressEdge(const EdgeID surviving_edge_id, + const EdgeID removed_edge_id, + const NodeID via_node_id, + const NodeID target_node, + const EdgeWeight weight1, + const EdgeWeight weight2); + + bool HasEntryForID(const EdgeID edge_id) const; void PrintStatistics() const; + void SerializeInternalVector(const std::string &path) const; + unsigned GetPositionForID(const EdgeID edge_id) const; + const std::vector & + GetBucketReference(const EdgeID edge_id) const; -private: - + private: void IncreaseFreeList(); - - std::vector > m_compressed_geometries; + std::vector > m_compressed_geometries; std::vector m_free_list; - boost::unordered_map m_node_id_to_index_map; + boost::unordered_map m_edge_id_to_list_index_map; }; - -#endif //GEOMETRY_COMPRESSOR_H +#endif // GEOMETRY_COMPRESSOR_H diff --git a/DataStructures/BinaryHeap.h b/DataStructures/BinaryHeap.h index 9edd600e3..cc91272f1 100644 --- a/DataStructures/BinaryHeap.h +++ b/DataStructures/BinaryHeap.h @@ -96,6 +96,11 @@ public: return nodes[node]; } + Key const & operator[]( const NodeID node ) const { + UnorderedMapConstIterator iter = nodes.find(node); + return iter->second; + } + void Clear() { nodes.clear(); } @@ -158,6 +163,11 @@ public: return insertedNodes[index].data; } + Data const & GetData( NodeID node ) const { + const Key index = nodeIndex[node]; + return insertedNodes[index].data; + } + Weight& GetKey( NodeID node ) { const Key index = nodeIndex[node]; return insertedNodes[index].weight; diff --git a/DataStructures/Coordinate.cpp b/DataStructures/Coordinate.cpp index 58598b206..3fb2cfc04 100644 --- a/DataStructures/Coordinate.cpp +++ b/DataStructures/Coordinate.cpp @@ -26,28 +26,45 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include "../Util/SimpleLogger.h" #include "../Util/StringUtil.h" #include -#include -#include + +#ifndef NDEBUG +#include +#endif +#include +#include FixedPointCoordinate::FixedPointCoordinate() - : lat(INT_MIN), - lon(INT_MIN) + : lat(std::numeric_limits::min()), + lon(std::numeric_limits::min()) { } FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon) -{ } +{ +#ifndef NDEBUG + if(0 != (std::abs(lat) >> 30)) { + std::bitset<32> y(lat); + SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y; + } + if(0 != (std::abs(lon) >> 30)) { + std::bitset<32> x(lon); + SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x; + } +#endif +} void FixedPointCoordinate::Reset() { - lat = INT_MIN; - lon = INT_MIN; + lat = std::numeric_limits::min(); + lon = std::numeric_limits::min(); } bool FixedPointCoordinate::isSet() const { - return (INT_MIN != lat) && (INT_MIN != lon); + return (std::numeric_limits::min() != lat) && + (std::numeric_limits::min() != lon); } bool FixedPointCoordinate::isValid() const { if( @@ -70,10 +87,10 @@ double FixedPointCoordinate::ApproximateDistance( const int lat2, const int lon2 ) { - BOOST_ASSERT(lat1 != INT_MIN); - BOOST_ASSERT(lon1 != INT_MIN); - BOOST_ASSERT(lat2 != INT_MIN); - BOOST_ASSERT(lon2 != INT_MIN); + BOOST_ASSERT(lat1 != std::numeric_limits::min()); + BOOST_ASSERT(lon1 != std::numeric_limits::min()); + BOOST_ASSERT(lat2 != std::numeric_limits::min()); + BOOST_ASSERT(lon2 != std::numeric_limits::min()); double RAD = 0.017453292519943295769236907684886; double lt1 = lat1/COORDINATE_PRECISION; double ln1 = lon1/COORDINATE_PRECISION; @@ -108,10 +125,10 @@ double FixedPointCoordinate::ApproximateEuclideanDistance( const FixedPointCoordinate &c1, const FixedPointCoordinate &c2 ) { - BOOST_ASSERT(c1.lat != INT_MIN); - BOOST_ASSERT(c1.lon != INT_MIN); - BOOST_ASSERT(c2.lat != INT_MIN); - BOOST_ASSERT(c2.lon != INT_MIN); + BOOST_ASSERT(c1.lat != std::numeric_limits::min()); + BOOST_ASSERT(c1.lon != std::numeric_limits::min()); + BOOST_ASSERT(c2.lat != std::numeric_limits::min()); + BOOST_ASSERT(c2.lon != std::numeric_limits::min()); const double RAD = 0.017453292519943295769236907684886; const double lat1 = (c1.lat/COORDINATE_PRECISION)*RAD; const double lon1 = (c1.lon/COORDINATE_PRECISION)*RAD; @@ -160,3 +177,7 @@ void FixedPointCoordinate::convertInternalReversedCoordinateToString( convertInternalLatLonToString(coord.lon, tmp); output += tmp; } + +void FixedPointCoordinate::Output(std::ostream & out) const {//, FixedPointCoordinate & c) { + out << "(" << lat/COORDINATE_PRECISION << "," << lon/COORDINATE_PRECISION << ")"; +} diff --git a/DataStructures/EdgeBasedNode.h b/DataStructures/EdgeBasedNode.h index 895baa8dd..d76a4958b 100644 --- a/DataStructures/EdgeBasedNode.h +++ b/DataStructures/EdgeBasedNode.h @@ -1,176 +1,160 @@ #ifndef EDGE_BASED_NODE_H #define EDGE_BASED_NODE_H -#include - -#include - #include "../Util/MercatorUtil.h" +#include "../Util/SimpleLogger.h" #include "../typedefs.h" #include -// An EdgeBasedNode represents a node in the edge-expanded graph. +#include + +#include + struct EdgeBasedNode { EdgeBasedNode() : - id(INT_MAX), - lat1(INT_MAX), - lat2(INT_MAX), - lon1(INT_MAX), - lon2(INT_MAX >> 1), - belongsToTinyComponent(false), - nameID(UINT_MAX), - weight(UINT_MAX >> 1), - ignoreInGrid(false) + forward_edge_based_node_id(SPECIAL_NODEID), + reverse_edge_based_node_id(SPECIAL_NODEID), + u(SPECIAL_NODEID), + v(SPECIAL_NODEID), + name_id(0), + forward_weight(INVALID_EDGE_WEIGHT >> 1), + reverse_weight(INVALID_EDGE_WEIGHT >> 1), + forward_offset(0), + reverse_offset(0), + packed_geometry_id(SPECIAL_EDGEID), + fwd_segment_position( std::numeric_limits::max() ), + belongsToTinyComponent(false) { } - // Computes: - // - the distance from the given query location to nearest point on this edge (and returns it) - // - the location on this edge which is nearest to the query location - // - the ratio ps:pq, where p and q are the end points of this edge, and s is the perpendicular foot of - // the query location on the line defined by p and q. - double ComputePerpendicularDistance( - const FixedPointCoordinate& query_location, + explicit EdgeBasedNode( + NodeID forward_edge_based_node_id, + NodeID reverse_edge_based_node_id, + NodeID u, + NodeID v, + unsigned name_id, + int forward_weight, + int reverse_weight, + int forward_offset, + int reverse_offset, + unsigned packed_geometry_id, + unsigned short fwd_segment_position, + bool belongs_to_tiny_component + ) : + forward_edge_based_node_id(forward_edge_based_node_id), + reverse_edge_based_node_id(reverse_edge_based_node_id), + u(u), + v(v), + name_id(name_id), + forward_weight(forward_weight), + reverse_weight(reverse_weight), + forward_offset(forward_offset), + reverse_offset(reverse_offset), + packed_geometry_id(packed_geometry_id), + fwd_segment_position(fwd_segment_position), + belongsToTinyComponent(belongs_to_tiny_component) + { + BOOST_ASSERT( + ( forward_edge_based_node_id != SPECIAL_NODEID ) || + ( reverse_edge_based_node_id != SPECIAL_NODEID ) + ); + } + + inline static double ComputePerpendicularDistance( + const FixedPointCoordinate & coord_a, + const FixedPointCoordinate & coord_b, + const FixedPointCoordinate & query_location, FixedPointCoordinate & nearest_location, - double & ratio, - double precision = COORDINATE_PRECISION - ) const { + double & r + ) { BOOST_ASSERT( query_location.isValid() ); - const double epsilon = 1.0/precision; + const double x = lat2y(query_location.lat/COORDINATE_PRECISION); + const double y = query_location.lon/COORDINATE_PRECISION; + const double a = lat2y(coord_a.lat/COORDINATE_PRECISION); + const double b = coord_a.lon/COORDINATE_PRECISION; + const double c = lat2y(coord_b.lat/COORDINATE_PRECISION); + const double d = coord_b.lon/COORDINATE_PRECISION; + double p,q/*,mX*/,nY; + if( std::abs(a-c) > std::numeric_limits::epsilon() ){ + const double m = (d-b)/(c-a); // slope + // Projection of (x,y) on line joining (a,b) and (c,d) + p = ((x + (m*y)) + (m*m*a - m*b))/(1. + m*m); + q = b + m*(p - a); + } else { + p = c; + q = y; + } + nY = (d*p - c*q)/(a*d - b*c); - if( ignoreInGrid ) { - return std::numeric_limits::max(); + //discretize the result to coordinate precision. it's a hack! + if( std::abs(nY) < (1./COORDINATE_PRECISION) ) { + nY = 0.; } - // p, q : the end points of the underlying edge - const Point p(lat2y(lat1/COORDINATE_PRECISION), lon1/COORDINATE_PRECISION); - const Point q(lat2y(lat2/COORDINATE_PRECISION), lon2/COORDINATE_PRECISION); - - // r : query location - const Point r(lat2y(query_location.lat/COORDINATE_PRECISION), - query_location.lon/COORDINATE_PRECISION); - - const Point foot = ComputePerpendicularFoot(p, q, r, epsilon); - ratio = ComputeRatio(p, q, foot, epsilon); - - BOOST_ASSERT( !std::isnan(ratio) ); - - nearest_location = ComputeNearestPointOnSegment(foot, ratio); - + r = (p - nY*a)/c;// These values are actually n/m+n and m/m+n , we need + // not calculate the explicit values of m an n as we + // are just interested in the ratio + if( std::isnan(r) ) { + r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.; + } else if( std::abs(r) <= std::numeric_limits::epsilon() ) { + r = 0.; + } else if( std::abs(r-1.) <= std::numeric_limits::epsilon() ) { + r = 1.; + } + BOOST_ASSERT( !std::isnan(r) ); + if( r <= 0. ){ + nearest_location.lat = coord_a.lat; + nearest_location.lon = coord_a.lon; + } else if( r >= 1. ){ + nearest_location.lat = coord_b.lat; + nearest_location.lon = coord_b.lon; + } else { + // point lies in between + nearest_location.lat = y2lat(p)*COORDINATE_PRECISION; + nearest_location.lon = q*COORDINATE_PRECISION; + } BOOST_ASSERT( nearest_location.isValid() ); // TODO: Replace with euclidean approximation when k-NN search is done // const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance( - const double approximated_distance = FixedPointCoordinate::ApproximateDistance(query_location, nearest_location); - - BOOST_ASSERT( 0.0 <= approximated_distance ); + const double approximated_distance = FixedPointCoordinate::ApproximateDistance( + query_location, + nearest_location + ); + BOOST_ASSERT( 0. <= approximated_distance ); return approximated_distance; } - bool operator<(const EdgeBasedNode & other) const { - return other.id < id; + static inline FixedPointCoordinate Centroid( + const FixedPointCoordinate & a, + const FixedPointCoordinate & b + ) { + FixedPointCoordinate centroid; + //The coordinates of the midpoint are given by: + //x = (x1 + x2) /2 and y = (y1 + y2) /2. + centroid.lon = (std::min(a.lon, b.lon) + std::max(a.lon, b.lon))/2; + centroid.lat = (std::min(a.lat, b.lat) + std::max(a.lat, b.lat))/2; + return centroid; } - bool operator==(const EdgeBasedNode & other) const { - return id == other.id; - } - - // Returns the midpoint of the underlying edge. - inline FixedPointCoordinate Centroid() const { - return FixedPointCoordinate((lat1+lat2)/2, (lon1+lon2)/2); - } - - NodeID id; - - // The coordinates of the end-points of the underlying edge. - int lat1; - int lat2; - int lon1; - int lon2:31; - - bool belongsToTinyComponent:1; - NodeID nameID; - - // The weight of the underlying edge. - unsigned weight:31; - - bool ignoreInGrid:1; - -private: - - typedef std::pair Point; - - // Compute the perpendicular foot of point r on the line defined by p and q. - Point ComputePerpendicularFoot(const Point &p, const Point &q, const Point &r, double epsilon) const { - - // the projection of r onto the line pq - double foot_x, foot_y; - - const bool is_parallel_to_y_axis = std::abs(q.first - p.first) < epsilon; - - if( is_parallel_to_y_axis ) { - foot_x = q.first; - foot_y = r.second; - } else { - // the slope of the line through (a|b) and (c|d) - const double m = (q.second - p.second) / (q.first - p.first); - - // Projection of (x|y) onto the line joining (a|b) and (c|d). - foot_x = ((r.first + (m*r.second)) + (m*m*p.first - m*p.second))/(1.0 + m*m); - foot_y = p.second + m*(foot_x - p.first); - } - - return Point(foot_x, foot_y); - } - - // Compute the ratio of the line segment pr to line segment pq. - double ComputeRatio(const Point & p, const Point & q, const Point & r, double epsilon) const { - - const bool is_parallel_to_x_axis = std::abs(q.second-p.second) < epsilon; - const bool is_parallel_to_y_axis = std::abs(q.first -p.first ) < epsilon; - - double ratio; - - if( !is_parallel_to_y_axis ) { - ratio = (r.first - p.first)/(q.first - p.first); - } else if( !is_parallel_to_x_axis ) { - ratio = (r.second - p.second)/(q.second - p.second); - } else { - // (a|b) and (c|d) are essentially the same point - // by convention, we set the ratio to 0 in this case - //ratio = ((lat2 == query_location.lat) && (lon2 == query_location.lon)) ? 1. : 0.; - ratio = 0.0; - } - - // Round to integer if the ratio is close to 0 or 1. - if( std::abs(ratio) <= epsilon ) { - ratio = 0.0; - } else if( std::abs(ratio-1.0) <= epsilon ) { - ratio = 1.0; - } - - return ratio; - } - - // Computes the point on the segment pq which is nearest to a point r = p + lambda * (q-p). - // p and q are the end points of the underlying edge. - FixedPointCoordinate ComputeNearestPointOnSegment(const Point & r, double lambda) const { - - if( lambda <= 0.0 ) { - return FixedPointCoordinate(lat1, lon1); - } else if( lambda >= 1.0 ) { - return FixedPointCoordinate(lat2, lon2); - } - - // r lies between p and q - return FixedPointCoordinate( - y2lat(r.first)*COORDINATE_PRECISION, - r.second*COORDINATE_PRECISION - ); + bool IsCompressed() { + return packed_geometry_id != SPECIAL_EDGEID; } + NodeID forward_edge_based_node_id; // needed for edge-expanded graph + NodeID reverse_edge_based_node_id; // needed for edge-expanded graph + NodeID u; // indices into the coordinates array + NodeID v; // indices into the coordinates array + unsigned name_id; // id of the edge name + int forward_weight; // weight of the edge + int reverse_weight; // weight in the other direction (may be different) + int forward_offset; // prefix sum of the weight up the edge TODO: short must suffice + int reverse_offset; // prefix sum of the weight from the edge TODO: short must suffice + unsigned packed_geometry_id; // if set, then the edge represents a packed geometry + unsigned short fwd_segment_position; // segment id in a compressed geometry + bool belongsToTinyComponent; }; #endif //EDGE_BASED_NODE_H diff --git a/DataStructures/HashTable.h b/DataStructures/HashTable.h index b4984e4b5..871ba4933 100644 --- a/DataStructures/HashTable.h +++ b/DataStructures/HashTable.h @@ -54,7 +54,7 @@ public: return boost::cref(iter->second); } - inline bool Holds( KeyT const & key) const { + inline const bool Holds( KeyT const & key) const { if( super::find(key) == super::end() ) { return false; } diff --git a/DataStructures/ImportEdge.h b/DataStructures/ImportEdge.h index 33e52cc12..1006d2bb3 100644 --- a/DataStructures/ImportEdge.h +++ b/DataStructures/ImportEdge.h @@ -61,7 +61,8 @@ public: bool ra, bool ig, bool ar, - bool cf + bool cf, + bool is_split ) : _source(s), _target(t), _name(n), @@ -72,7 +73,8 @@ public: _roundabout(ra), _ignoreInGrid(ig), _accessRestricted(ar), - _contraFlow(cf) + _contraFlow(cf), + is_split(is_split) { if(ty < 0) { throw OSRMException("negative edge type"); @@ -93,6 +95,7 @@ public: bool ignoreInGrid() const { return _ignoreInGrid; } bool isAccessRestricted() const { return _accessRestricted; } bool isContraFlow() const { return _contraFlow; } + bool IsSplit() const { return is_split; } //TODO: names need to be fixed. NodeID _source; @@ -106,6 +109,7 @@ public: bool _ignoreInGrid:1; bool _accessRestricted:1; bool _contraFlow:1; + bool is_split:1; private: NodeBasedEdge() { } @@ -162,7 +166,7 @@ public: m_weight(w), m_forward(f), m_backward(b) - {} + { } NodeID target() const { return m_target; } NodeID source() const { return m_source; } diff --git a/DataStructures/ImportNode.h b/DataStructures/ImportNode.h index f249a6433..f409a3be6 100644 --- a/DataStructures/ImportNode.h +++ b/DataStructures/ImportNode.h @@ -44,11 +44,17 @@ struct ExternalMemoryNode : NodeInfo { bollard(bollard), trafficLight(traffic_light) { } - ExternalMemoryNode() : bollard(false), trafficLight(false) {} + + ExternalMemoryNode() + : + bollard(false), + trafficLight(false) + { } static ExternalMemoryNode min_value() { return ExternalMemoryNode(0,0,0, false, false); } + static ExternalMemoryNode max_value() { return ExternalMemoryNode( std::numeric_limits::max(), @@ -58,9 +64,11 @@ struct ExternalMemoryNode : NodeInfo { false ); } + NodeID key() const { return id; } + bool bollard; bool trafficLight; }; diff --git a/DataStructures/InputReaderFactory.h b/DataStructures/InputReaderFactory.h index 26418c1f2..3ca09fe03 100644 --- a/DataStructures/InputReaderFactory.h +++ b/DataStructures/InputReaderFactory.h @@ -29,6 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INPUTREADERFACTORY_H #define INPUTREADERFACTORY_H +#include + #include #include @@ -51,21 +53,21 @@ int readFromBz2Stream( void* pointer, char* buffer, int len ) { return read; } else if(BZ_STREAM_END == context->error) { BZ2_bzReadGetUnused(&context->error, context->bz2, &unusedTmpVoid, &context->nUnused); - if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadGetUnused" <error, "Could not BZ2_bzReadGetUnused"); unusedTmp = (char*)unusedTmpVoid; for(int i=0;inUnused;i++) { context->unused[i] = unusedTmp[i]; } BZ2_bzReadClose(&context->error, context->bz2); - if(BZ_OK != context->error) {std::cerr << "Could not BZ2_bzReadClose" <error, "Could not BZ2_bzReadClose"); context->error = BZ_STREAM_END; // set to the stream end for next call to this function if(0 == context->nUnused && feof(context->file)) { return read; } else { context->bz2 = BZ2_bzReadOpen(&context->error, context->file, 0, 0, context->unused, context->nUnused); - if(NULL == context->bz2){std::cerr << "Could not open file" <bz2, "Could not open file"); } - } else { std::cerr << "Could not read bz2 file" << std::endl; exit(-1); } + } else { BOOST_ASSERT_MSG(false, "Could not read bz2 file"); } } return read; } diff --git a/DataStructures/OriginalEdgeData.h b/DataStructures/OriginalEdgeData.h index 894cf8add..48653cbb6 100644 --- a/DataStructures/OriginalEdgeData.h +++ b/DataStructures/OriginalEdgeData.h @@ -31,28 +31,32 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "TurnInstructions.h" #include "../typedefs.h" -#include +#include struct OriginalEdgeData{ explicit OriginalEdgeData( NodeID via_node, unsigned name_id, - TurnInstruction turn_instruction + TurnInstruction turn_instruction, + bool compressed_geometry ) : - via_node(via_node), - name_id(name_id), - turn_instruction(turn_instruction) + via_node( via_node ), + name_id( name_id ), + turn_instruction( turn_instruction ), + compressed_geometry( compressed_geometry ) { } OriginalEdgeData() : - via_node(UINT_MAX), - name_id(UINT_MAX), - turn_instruction(UCHAR_MAX) + via_node( std::numeric_limits::max() ), + name_id( std::numeric_limits::max() ), + turn_instruction( std::numeric_limits::max() ), + compressed_geometry( false ) { } NodeID via_node; unsigned name_id; TurnInstruction turn_instruction; + bool compressed_geometry; }; #endif //ORIGINAL_EDGE_DATA_H diff --git a/DataStructures/PhantomNodes.h b/DataStructures/PhantomNodes.h index 3a3fbbd93..c7b8517c4 100644 --- a/DataStructures/PhantomNodes.h +++ b/DataStructures/PhantomNodes.h @@ -29,75 +29,145 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define PHANTOMNODES_H_ #include - +#include "../Util/SimpleLogger.h" #include "../typedefs.h" -struct PhantomNode { +struct PhantomNode +{ PhantomNode() : - edgeBasedNode(UINT_MAX), - nodeBasedEdgeNameID(UINT_MAX), - weight1(INT_MAX), - weight2(INT_MAX), - ratio(0.) + forward_node_id(SPECIAL_NODEID), + reverse_node_id(SPECIAL_NODEID), + name_id(std::numeric_limits::max()), + forward_weight(INVALID_EDGE_WEIGHT), + reverse_weight(INVALID_EDGE_WEIGHT), + forward_offset(0), + reverse_offset(0), + packed_geometry_id(SPECIAL_EDGEID), + fwd_segment_position(0) { } - NodeID edgeBasedNode; - unsigned nodeBasedEdgeNameID; - int weight1; - int weight2; - double ratio; + NodeID forward_node_id; + NodeID reverse_node_id; + unsigned name_id; + int forward_weight; + int reverse_weight; + int forward_offset; + int reverse_offset; + unsigned packed_geometry_id; FixedPointCoordinate location; - void Reset() { - edgeBasedNode = UINT_MAX; - nodeBasedEdgeNameID = UINT_MAX; - weight1 = INT_MAX; - weight2 = INT_MAX; - ratio = 0.; - location.Reset(); - } - bool isBidirected() const { - return weight2 != INT_MAX; - } - bool isValid(const unsigned numberOfNodes) const { - return location.isValid() && (edgeBasedNode < numberOfNodes) && (weight1 != INT_MAX) && (ratio >= 0.) && (ratio <= 1.) && (nodeBasedEdgeNameID != UINT_MAX); + unsigned short fwd_segment_position; + + int GetForwardWeightPlusOffset() const + { + if (SPECIAL_NODEID == forward_node_id) + { + return 0; + } + const int result = (forward_offset + forward_weight); + return result; } - bool operator==(const PhantomNode & other) const { + int GetReverseWeightPlusOffset() const + { + if (SPECIAL_NODEID == reverse_node_id) + { + return 0; + } + const int result = (reverse_offset + reverse_weight); + return result; + } + + void Reset() + { + forward_node_id = SPECIAL_NODEID; + name_id = SPECIAL_NODEID; + forward_weight = INVALID_EDGE_WEIGHT; + reverse_weight = INVALID_EDGE_WEIGHT; + forward_offset = 0; + reverse_offset = 0; + location.Reset(); + } + + bool isBidirected() const + { + return (forward_node_id != SPECIAL_NODEID) && + (reverse_node_id != SPECIAL_NODEID); + } + + bool IsCompressed() const + { + return (forward_offset != 0) || (reverse_offset != 0); + } + + bool isValid(const unsigned numberOfNodes) const + { + return + location.isValid() && + ( + (forward_node_id < numberOfNodes) || + (reverse_node_id < numberOfNodes) + ) && + ( + (forward_weight != INVALID_EDGE_WEIGHT) || + (reverse_weight != INVALID_EDGE_WEIGHT) + ) && + (name_id != std::numeric_limits::max() + ); + } + + bool operator==(const PhantomNode & other) const + { return location == other.location; } }; -struct PhantomNodes { - PhantomNode startPhantom; - PhantomNode targetPhantom; - void Reset() { - startPhantom.Reset(); - targetPhantom.Reset(); +struct PhantomNodes +{ + PhantomNode source_phantom; + PhantomNode target_phantom; + + void Reset() + { + source_phantom.Reset(); + target_phantom.Reset(); } - bool PhantomsAreOnSameNodeBasedEdge() const { - return (startPhantom.edgeBasedNode == targetPhantom.edgeBasedNode); + bool PhantomsAreOnSameNodeBasedEdge() const + { + return (source_phantom.forward_node_id == target_phantom.forward_node_id); } - bool AtLeastOnePhantomNodeIsUINTMAX() const { - return !(startPhantom.edgeBasedNode == UINT_MAX || targetPhantom.edgeBasedNode == UINT_MAX); + bool AtLeastOnePhantomNodeIsInvalid() const + { + return ((source_phantom.forward_node_id == SPECIAL_NODEID) && (source_phantom.reverse_node_id == SPECIAL_NODEID)) || + ((target_phantom.forward_node_id == SPECIAL_NODEID) && (target_phantom.reverse_node_id == SPECIAL_NODEID)); } - bool PhantomNodesHaveEqualLocation() const { - return startPhantom == targetPhantom; + bool PhantomNodesHaveEqualLocation() const + { + return source_phantom == target_phantom; } }; -inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn){ - out << "Node1: " << pn.startPhantom.edgeBasedNode << std::endl; - out << "Node2: " << pn.targetPhantom.edgeBasedNode << std::endl; - out << "startCoord: " << pn.startPhantom.location << std::endl; - out << "targetCoord: " << pn.targetPhantom.location << std::endl; +inline std::ostream& operator<<(std::ostream &out, const PhantomNodes & pn) +{ + out << "source_coord: " << pn.source_phantom.location << "\n"; + out << "target_coord: " << pn.target_phantom.location << std::endl; return out; } -inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn){ - out << "node: " << pn.edgeBasedNode << ", name: " << pn.nodeBasedEdgeNameID << ", w1: " << pn.weight1 << ", w2: " << pn.weight2 << ", ratio: " << pn.ratio << ", loc: " << pn.location; +inline std::ostream& operator<<(std::ostream &out, const PhantomNode & pn) +{ + out << "node1: " << pn.forward_node_id << ", " << + "node2: " << pn.reverse_node_id << ", " << + "name: " << pn.name_id << ", " << + "fwd-w: " << pn.forward_weight << ", " << + "rev-w: " << pn.reverse_weight << ", " << + "fwd-o: " << pn.forward_offset << ", " << + "rev-o: " << pn.reverse_offset << ", " << + "geom: " << pn.packed_geometry_id << ", " << + "pos: " << pn.fwd_segment_position << ", " << + "loc: " << pn.location; return out; } diff --git a/DataStructures/QueryEdge.h b/DataStructures/QueryEdge.h index 41c9e066f..0e71ab701 100644 --- a/DataStructures/QueryEdge.h +++ b/DataStructures/QueryEdge.h @@ -30,8 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" -#include - struct QueryEdge { NodeID source; NodeID target; diff --git a/DataStructures/QueryNode.h b/DataStructures/QueryNode.h index ae0dc4bac..916aa50e2 100644 --- a/DataStructures/QueryNode.h +++ b/DataStructures/QueryNode.h @@ -34,17 +34,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include -#include - #include struct NodeInfo { typedef NodeID key_type; //type of NodeID typedef int value_type; //type of lat,lons - NodeInfo(int _lat, int _lon, NodeID _id) : lat(_lat), lon(_lon), id(_id) {} - NodeInfo() : lat(INT_MAX), lon(INT_MAX), id(UINT_MAX) {} + NodeInfo(int lat, int lon, NodeID id) : lat(lat), lon(lon), id(id) { } + NodeInfo() + : + lat(std::numeric_limits::max()), + lon(std::numeric_limits::max()), + id(std::numeric_limits::max()) + { } + int lat; int lon; NodeID id; @@ -69,17 +72,15 @@ struct NodeInfo { switch(n) { case 1: return lat; - break; + // break; case 0: return lon; - break; + // break; default: - BOOST_ASSERT_MSG(false, "should not happen"); - return UINT_MAX; break; } BOOST_ASSERT_MSG(false, "should not happen"); - return UINT_MAX; + return std::numeric_limits::max(); } }; diff --git a/DataStructures/RawRouteData.h b/DataStructures/RawRouteData.h index 509c4ca97..cedbc2d76 100644 --- a/DataStructures/RawRouteData.h +++ b/DataStructures/RawRouteData.h @@ -70,10 +70,19 @@ struct RawRouteData { unsigned checkSum; int lengthOfShortestPath; int lengthOfAlternativePath; + bool source_traversed_in_reverse; + bool target_traversed_in_reverse; + bool alt_source_traversed_in_reverse; + bool alt_target_traversed_in_reverse; + RawRouteData() : checkSum(UINT_MAX), lengthOfShortestPath(INT_MAX), - lengthOfAlternativePath(INT_MAX) + lengthOfAlternativePath(INT_MAX), + source_traversed_in_reverse(false), + target_traversed_in_reverse(false), + alt_source_traversed_in_reverse(false), + alt_target_traversed_in_reverse(false) { } }; diff --git a/DataStructures/Restriction.h b/DataStructures/Restriction.h index 429cc8acd..153c5afc9 100644 --- a/DataStructures/Restriction.h +++ b/DataStructures/Restriction.h @@ -29,7 +29,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define RESTRICTION_H_ #include "../typedefs.h" -#include + +#include struct TurnRestriction { NodeID viaNode; @@ -60,8 +61,8 @@ struct TurnRestriction { explicit TurnRestriction(NodeID viaNode) : viaNode(viaNode), - fromNode(UINT_MAX), - toNode(UINT_MAX) { + fromNode(std::numeric_limits::max()), + toNode(std::numeric_limits::max()) { } explicit TurnRestriction(const bool isOnly = false) : @@ -93,9 +94,9 @@ struct InputRestrictionContainer { explicit InputRestrictionContainer( bool isOnly = false ) : - fromWay(UINT_MAX), - toWay(UINT_MAX), - viaNode(UINT_MAX) + fromWay(std::numeric_limits::max()), + toWay(std::numeric_limits::max()), + viaNode(std::numeric_limits::max()) { restriction.flags.isOnly = isOnly; } @@ -105,10 +106,10 @@ struct InputRestrictionContainer { } static InputRestrictionContainer max_value() { return InputRestrictionContainer( - UINT_MAX, - UINT_MAX, - UINT_MAX, - UINT_MAX + std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max() ); } }; diff --git a/DataStructures/SharedMemoryVectorWrapper.h b/DataStructures/SharedMemoryVectorWrapper.h index 8ceff2489..b0e85dfbc 100644 --- a/DataStructures/SharedMemoryVectorWrapper.h +++ b/DataStructures/SharedMemoryVectorWrapper.h @@ -115,6 +115,8 @@ public: std::size_t size() const { return m_size; } + bool empty() const { return 0 == size(); } + DataT & operator[](const unsigned index) { BOOST_ASSERT_MSG(index < m_size, "invalid size"); return m_ptr[index]; @@ -126,6 +128,63 @@ public: } }; +template<> +class SharedMemoryWrapper { +private: + unsigned * m_ptr; + std::size_t m_size; + +public: + SharedMemoryWrapper() : + m_ptr(NULL), + m_size(0) + { } + + SharedMemoryWrapper(unsigned * ptr, std::size_t size) : + m_ptr(ptr), + m_size(size) + { } + + void swap( SharedMemoryWrapper & other ) { + BOOST_ASSERT_MSG(m_size != 0 || other.size() != 0, "size invalid"); + std::swap( m_size, other.m_size); + std::swap( m_ptr , other.m_ptr ); + } + + // void SetData(const DataT * ptr, const std::size_t size) { + // BOOST_ASSERT_MSG( 0 == m_size, "vector not empty"); + // BOOST_ASSERT_MSG( 0 < size , "new vector empty"); + // m_ptr.reset(ptr); + // m_size = size; + // } + + bool at(const std::size_t index) const { + // BOOST_ASSERT_MSG(index < m_size, "invalid size"); + const unsigned bucket = index / 32; + const unsigned offset = index % 32; + return m_ptr[bucket] & (1 << offset); + } + + // ShMemIterator begin() const { + // return ShMemIterator(m_ptr); + // } + + // ShMemIterator end() const { + // return ShMemIterator(m_ptr+m_size); + // } + + std::size_t size() const { return m_size; } + + bool empty() const { return 0 == size(); } + + bool operator[](const unsigned index) { + BOOST_ASSERT_MSG(index < m_size, "invalid size"); + const unsigned bucket = index / 32; + const unsigned offset = index % 32; + return m_ptr[bucket] & (1 << offset); + } +}; + template struct ShM { typedef typename boost::conditional< @@ -135,5 +194,4 @@ struct ShM { >::type vector; }; - #endif //SHARED_MEMORY_VECTOR_WRAPPER_H diff --git a/DataStructures/StaticGraph.h b/DataStructures/StaticGraph.h index b572d7f2e..e3445c583 100644 --- a/DataStructures/StaticGraph.h +++ b/DataStructures/StaticGraph.h @@ -112,16 +112,18 @@ public: if(eid2 == UINT_MAX) { SimpleLogger().Write(logWARNING) << "cannot find first segment of edge (" << - u << "," << data.id << "," << v << ")"; + u << "," << data.id << "," << v << "), eid: " << eid; data.shortcut = false; + BOOST_ASSERT(false); } eid2 = FindEdgeInEitherDirection(data.id, v); if(eid2 == UINT_MAX) { SimpleLogger().Write(logWARNING) << "cannot find second segment of edge (" << - u << "," << data.id << "," << v << ")"; + u << "," << data.id << "," << v << "), eid2: " << eid2; data.shortcut = false; + BOOST_ASSERT(false); } } } @@ -155,17 +157,17 @@ public: } EdgeIterator BeginEdges( const NodeIterator n ) const { - return EdgeIterator( _nodes[n].firstEdge ); + return EdgeIterator( _nodes.at(n).firstEdge ); } EdgeIterator EndEdges( const NodeIterator n ) const { - return EdgeIterator( _nodes[n+1].firstEdge ); + return EdgeIterator( _nodes.at(n+1).firstEdge ); } //searches for a specific edge EdgeIterator FindEdge( const NodeIterator from, const NodeIterator to ) const { EdgeIterator smallestEdge = SPECIAL_EDGEID; - EdgeWeight smallestWeight = UINT_MAX; + EdgeWeight smallestWeight = INVALID_EDGE_WEIGHT; for ( EdgeIterator edge = BeginEdges( from ); edge < EndEdges(from); edge++ ) { const NodeID target = GetTarget(edge); const EdgeWeight weight = GetEdgeData(edge).distance; diff --git a/DataStructures/StaticRTree.h b/DataStructures/StaticRTree.h index 059a9b0ef..a2b936c84 100644 --- a/DataStructures/StaticRTree.h +++ b/DataStructures/StaticRTree.h @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "DeallocatingVector.h" #include "HilbertValue.h" #include "PhantomNodes.h" +#include "QueryNode.h" #include "SharedMemoryFactory.h" #include "SharedMemoryVectorWrapper.h" @@ -51,6 +52,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -68,7 +70,7 @@ const static uint32_t RTREE_LEAF_NODE_SIZE = 1170; static boost::thread_specific_ptr thread_local_rtree_stream; -template +template, bool UseSharedMemory = false> class StaticRTree : boost::noncopyable { public: struct RectangleInt2D { @@ -82,22 +84,35 @@ public: int32_t min_lat, max_lat; inline void InitializeMBRectangle( - const DataT * objects, - const uint32_t element_count + DataT const * objects, + const uint32_t element_count, + const std::vector & coordinate_list ) { for(uint32_t i = 0; i < element_count; ++i) { min_lon = std::min( - min_lon, std::min(objects[i].lon1, objects[i].lon2) + min_lon, std::min( + coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon + ) ); max_lon = std::max( - max_lon, std::max(objects[i].lon1, objects[i].lon2) + max_lon, std::max( + coordinate_list.at(objects[i].u).lon, + coordinate_list.at(objects[i].v).lon + ) ); min_lat = std::min( - min_lat, std::min(objects[i].lat1, objects[i].lat2) + min_lat, std::min( + coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lon + ) ); max_lat = std::max( - max_lat, std::max(objects[i].lat1, objects[i].lat2) + max_lat, std::max( + coordinate_list.at(objects[i].u).lat, + coordinate_list.at(objects[i].v).lon + ) ); } } @@ -221,9 +236,9 @@ public: } inline bool Contains(const FixedPointCoordinate & location) const { - bool lats_contained = + const bool lats_contained = (location.lat > min_lat) && (location.lat < max_lat); - bool lons_contained = + const bool lons_contained = (location.lon > min_lon) && (location.lon < max_lon); return lats_contained && lons_contained; } @@ -289,21 +304,23 @@ private: typename ShM::vector m_search_tree; uint64_t m_element_count; - const std::string m_leaf_node_filename; + boost::shared_ptr m_coordinate_list; + public: //Construct a packed Hilbert-R-Tree with Kamel-Faloutsos algorithm [1] explicit StaticRTree( std::vector & input_data_vector, const std::string tree_node_filename, - const std::string leaf_node_filename + const std::string leaf_node_filename, + const std::vector & coordinate_list ) : m_element_count(input_data_vector.size()), m_leaf_node_filename(leaf_node_filename) { SimpleLogger().Write() << "constructing r-tree of " << m_element_count << - " elements"; + " edge elements build on-top of " << coordinate_list.size() << " coordinates"; double time1 = get_timestamp(); std::vector input_wrapper_vector(m_element_count); @@ -315,8 +332,17 @@ public: for(uint64_t element_counter = 0; element_counter < m_element_count; ++element_counter) { input_wrapper_vector[element_counter].m_array_index = element_counter; //Get Hilbert-Value for centroid in mercartor projection - DataT & current_element = input_data_vector[element_counter]; - FixedPointCoordinate current_centroid = current_element.Centroid(); + DataT const & current_element = input_data_vector[element_counter]; + FixedPointCoordinate current_centroid = DataT::Centroid( + FixedPointCoordinate( + coordinate_list.at(current_element.u).lat, + coordinate_list.at(current_element.u).lon + ), + FixedPointCoordinate( + coordinate_list.at(current_element.v).lat, + coordinate_list.at(current_element.v).lon + ) + ); current_centroid.lat = COORDINATE_PRECISION*lat2y(current_centroid.lat/COORDINATE_PRECISION); uint64_t current_hilbert_value = get_hilbert_number(current_centroid); @@ -347,7 +373,11 @@ public: } //generate tree node that resemble the objects in leaf and store it for next level - current_node.minimum_bounding_rectangle.InitializeMBRectangle(current_leaf.objects, current_leaf.object_count); + current_node.minimum_bounding_rectangle.InitializeMBRectangle( + current_leaf.objects, + current_leaf.object_count, + coordinate_list + ); current_node.child_is_on_disk = true; current_node.children[0] = tree_nodes_in_level.size(); tree_nodes_in_level.push_back(current_node); @@ -426,9 +456,11 @@ public: //Read-only operation for queries explicit StaticRTree( const boost::filesystem::path & node_file, - const boost::filesystem::path & leaf_file - ) : m_leaf_node_filename(leaf_file.string()) { + const boost::filesystem::path & leaf_file, + const boost::shared_ptr coordinate_list + ) : m_leaf_node_filename( leaf_file.string() ) { //open tree node file and load into RAM. + m_coordinate_list = coordinate_list; if ( !boost::filesystem::exists( node_file ) ) { throw OSRMException("ram index file does not exist"); @@ -463,9 +495,11 @@ public: explicit StaticRTree( TreeNode * tree_node_ptr, const uint32_t number_of_nodes, - const boost::filesystem::path & leaf_file + const boost::filesystem::path & leaf_file, + boost::shared_ptr coordinate_list ) : m_search_tree(tree_node_ptr, number_of_nodes), - m_leaf_node_filename(leaf_file.string()) + m_leaf_node_filename(leaf_file.string()), + m_coordinate_list(coordinate_list) { //open leaf node file and store thread specific pointer if ( !boost::filesystem::exists( leaf_file ) ) { @@ -487,152 +521,7 @@ public: //SimpleLogger().Write() << m_element_count << " elements in leafs"; } //Read-only operation for queries -/* - inline void FindKNearestPhantomNodesForCoordinate( - const FixedPointCoordinate & location, - const unsigned zoom_level, - const unsigned candidate_count, - std::vector > & result_vector - ) const { - bool ignore_tiny_components = (zoom_level <= 14); - DataT nearest_edge; - - uint32_t io_count = 0; - uint32_t explored_tree_nodes_count = 0; - SimpleLogger().Write() << "searching for coordinate " << input_coordinate; - double min_dist = std::numeric_limits::max(); - double min_max_dist = std::numeric_limits::max(); - bool found_a_nearest_edge = false; - - FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate; - - //initialize queue with root element - std::priority_queue traversal_queue; - traversal_queue.push(QueryCandidate(0, m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate))); - BOOST_ASSERT_MSG(std::numberic_limits::epsilon() > (0. - traversal_queue.top().min_dist), "Root element in NN Search has min dist != 0."); - - while(!traversal_queue.empty()) { - const QueryCandidate current_query_node = traversal_queue.top(); traversal_queue.pop(); - - ++explored_tree_nodes_count; - bool prune_downward = (current_query_node.min_dist >= min_max_dist); - bool prune_upward = (current_query_node.min_dist >= min_dist); - if( !prune_downward && !prune_upward ) { //downward pruning - TreeNode & current_tree_node = m_search_tree[current_query_node.node_id]; - if (current_tree_node.child_is_on_disk) { - LeafNode current_leaf_node; - LoadLeafFromDisk(current_tree_node.children[0], current_leaf_node); - ++io_count; - for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) { - DataT & current_edge = current_leaf_node.objects[i]; - if(ignore_tiny_components && current_edge.belongsToTinyComponent) { - continue; - } - - double current_ratio = 0.; - double current_perpendicular_distance = current_edge.ComputePerpendicularDistance( - input_coordinate, - nearest, - current_ratio - ); - - if( - current_perpendicular_distance < min_dist - && !DoubleEpsilonCompare( - current_perpendicular_distance, - min_dist - ) - ) { //found a new minimum - min_dist = current_perpendicular_distance; - result_phantom_node.edgeBasedNode = current_edge.id; - result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID; - result_phantom_node.weight1 = current_edge.weight; - result_phantom_node.weight2 = INT_MAX; - result_phantom_node.location = nearest; - current_start_coordinate.lat = current_edge.lat1; - current_start_coordinate.lon = current_edge.lon1; - current_end_coordinate.lat = current_edge.lat2; - current_end_coordinate.lon = current_edge.lon2; - nearest_edge = current_edge; - found_a_nearest_edge = true; - } else if( - DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && - 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) - && EdgesAreEquivalent( - current_start_coordinate, - FixedPointCoordinate( - current_edge.lat1, - current_edge.lon1 - ), - FixedPointCoordinate( - current_edge.lat2, - current_edge.lon2 - ), - current_end_coordinate - ) - ) { - result_phantom_node.edgeBasedNode = std::min(current_edge.id, result_phantom_node.edgeBasedNode); - result_phantom_node.weight2 = current_edge.weight; - } - } - } else { - //traverse children, prune if global mindist is smaller than local one - for (uint32_t i = 0; i < current_tree_node.child_count; ++i) { - const int32_t child_id = current_tree_node.children[i]; - TreeNode & child_tree_node = m_search_tree[child_id]; - RectangleT & child_rectangle = child_tree_node.minimum_bounding_rectangle; - const double current_min_dist = child_rectangle.GetMinDist(input_coordinate); - const double current_min_max_dist = child_rectangle.GetMinMaxDist(input_coordinate); - if( current_min_max_dist < min_max_dist ) { - min_max_dist = current_min_max_dist; - } - if (current_min_dist > min_max_dist) { - continue; - } - if (current_min_dist > min_dist) { //upward pruning - continue; - } - traversal_queue.push(QueryCandidate(child_id, current_min_dist)); - } - } - } - } - - const double distance_to_edge = - ApproximateDistance ( - FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1), - result_phantom_node.location - ); - - const double length_of_edge = - ApproximateDistance( - FixedPointCoordinate(nearest_edge.lat1, nearest_edge.lon1), - FixedPointCoordinate(nearest_edge.lat2, nearest_edge.lon2) - ); - - const double ratio = (found_a_nearest_edge ? - std::min(1., distance_to_edge/ length_of_edge ) : 0 ); - result_phantom_node.weight1 *= ratio; - if(INT_MAX != result_phantom_node.weight2) { - result_phantom_node.weight2 *= (1.-ratio); - } - result_phantom_node.ratio = ratio; - - //Hack to fix rounding errors and wandering via nodes. - if(std::abs(input_coordinate.lon - result_phantom_node.location.lon) == 1) { - result_phantom_node.location.lon = input_coordinate.lon; - } - if(std::abs(input_coordinate.lat - result_phantom_node.location.lat) == 1) { - result_phantom_node.location.lat = input_coordinate.lat; - } - - SimpleLogger().Write() << "mindist: " << min_distphantom_node.isBidirected() ? "yes" : "no"); - return found_a_nearest_edge; - - } - - */ bool LocateClosestEndPointForCoordinate( const FixedPointCoordinate & input_coordinate, FixedPointCoordinate & result_coordinate, @@ -671,7 +560,7 @@ public: current_leaf_node ); for(uint32_t i = 0; i < current_leaf_node.object_count; ++i) { - const DataT & current_edge = current_leaf_node.objects[i]; + DataT const & current_edge = current_leaf_node.objects[i]; if( ignore_tiny_components && current_edge.belongsToTinyComponent @@ -682,29 +571,29 @@ public: double current_minimum_distance = FixedPointCoordinate::ApproximateDistance( input_coordinate.lat, input_coordinate.lon, - current_edge.lat1, - current_edge.lon1 + m_coordinate_list->at(current_edge.u).lat, + m_coordinate_list->at(current_edge.u).lon ); if( current_minimum_distance < min_dist ) { //found a new minimum min_dist = current_minimum_distance; - result_coordinate.lat = current_edge.lat1; - result_coordinate.lon = current_edge.lon1; + result_coordinate.lat = m_coordinate_list->at(current_edge.u).lat; + result_coordinate.lon = m_coordinate_list->at(current_edge.u).lon; found_a_nearest_edge = true; } current_minimum_distance = FixedPointCoordinate::ApproximateDistance( input_coordinate.lat, input_coordinate.lon, - current_edge.lat2, - current_edge.lon2 + m_coordinate_list->at(current_edge.v).lat, + m_coordinate_list->at(current_edge.v).lon ); if( current_minimum_distance < min_dist ) { //found a new minimum min_dist = current_minimum_distance; - result_coordinate.lat = current_edge.lat2; - result_coordinate.lon = current_edge.lon2; + result_coordinate.lat = m_coordinate_list->at(current_edge.v).lat; + result_coordinate.lon = m_coordinate_list->at(current_edge.v).lon; found_a_nearest_edge = true; } } @@ -783,7 +672,9 @@ public: } double current_ratio = 0.; - double current_perpendicular_distance = current_edge.ComputePerpendicularDistance( + const double current_perpendicular_distance = current_edge.ComputePerpendicularDistance( + m_coordinate_list->at(current_edge.u), + m_coordinate_list->at(current_edge.v), input_coordinate, nearest, current_ratio @@ -799,41 +690,24 @@ public: ) ) { //found a new minimum min_dist = current_perpendicular_distance; - result_phantom_node.edgeBasedNode = current_edge.id; - result_phantom_node.nodeBasedEdgeNameID = current_edge.nameID; - result_phantom_node.weight1 = current_edge.weight; - result_phantom_node.weight2 = INT_MAX; + //TODO: use assignment c'tor in PhantomNode + result_phantom_node.forward_node_id = current_edge.forward_edge_based_node_id; + result_phantom_node.reverse_node_id = current_edge.reverse_edge_based_node_id; + result_phantom_node.name_id = current_edge.name_id; + result_phantom_node.forward_weight = current_edge.forward_weight; + result_phantom_node.reverse_weight = current_edge.reverse_weight; + result_phantom_node.forward_offset = current_edge.forward_offset; + result_phantom_node.reverse_offset = current_edge.reverse_offset; + result_phantom_node.packed_geometry_id = current_edge.packed_geometry_id; + result_phantom_node.fwd_segment_position = current_edge.fwd_segment_position; + result_phantom_node.location = nearest; - current_start_coordinate.lat = current_edge.lat1; - current_start_coordinate.lon = current_edge.lon1; - current_end_coordinate.lat = current_edge.lat2; - current_end_coordinate.lon = current_edge.lon2; + current_start_coordinate.lat = m_coordinate_list->at(current_edge.u).lat; + current_start_coordinate.lon = m_coordinate_list->at(current_edge.u).lon; + current_end_coordinate.lat = m_coordinate_list->at(current_edge.v).lat; + current_end_coordinate.lon = m_coordinate_list->at(current_edge.v).lon; nearest_edge = current_edge; found_a_nearest_edge = true; - } else - if( DoubleEpsilonCompare(current_perpendicular_distance, min_dist) && - ( 1 == abs(current_edge.id - result_phantom_node.edgeBasedNode ) ) && - EdgesAreEquivalent( - current_start_coordinate, - FixedPointCoordinate( - current_edge.lat1, - current_edge.lon1 - ), - FixedPointCoordinate( - current_edge.lat2, - current_edge.lon2 - ), - current_end_coordinate - ) - ) { - - BOOST_ASSERT_MSG(current_edge.id != result_phantom_node.edgeBasedNode, "IDs not different"); - result_phantom_node.weight2 = current_edge.weight; - if(current_edge.id < result_phantom_node.edgeBasedNode) { - result_phantom_node.edgeBasedNode = current_edge.id; - std::swap(result_phantom_node.weight1, result_phantom_node.weight2); - std::swap(current_end_coordinate, current_start_coordinate); - } } } } else { @@ -884,11 +758,28 @@ public: ratio = std::min(1., ratio); } - result_phantom_node.weight1 *= ratio; - if(INT_MAX != result_phantom_node.weight2) { - result_phantom_node.weight2 *= (1.-ratio); + // SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_offset: " << result_phantom_node.forward_offset; + // SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_offset: " << result_phantom_node.reverse_offset; + // SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.forward_weight: " << result_phantom_node.forward_weight; + // SimpleLogger().Write(logDEBUG) << "[rtree] result_phantom_node.reverse_weight: " << result_phantom_node.reverse_weight; + + if (SPECIAL_NODEID != result_phantom_node.forward_node_id) + { + result_phantom_node.forward_weight *= ratio; } - result_phantom_node.ratio = ratio; + if (SPECIAL_NODEID != result_phantom_node.reverse_node_id) + { + result_phantom_node.reverse_weight *= (1.-ratio); + } + + // SimpleLogger().Write(logDEBUG) << "[rtree] result location: " << result_phantom_node.location << ", start: " << current_start_coordinate << ", end: " << current_end_coordinate; + // SimpleLogger().Write(logDEBUG) << "[rtree] fwd node: " << result_phantom_node.forward_node_id << ", rev node: " << result_phantom_node.reverse_node_id; + // SimpleLogger().Write(logDEBUG) << "[rtree] fwd weight: " << result_phantom_node.forward_weight << ", rev weight: " << result_phantom_node.reverse_weight; + // SimpleLogger().Write(logDEBUG) << "[rtree] fwd offset: " << result_phantom_node.forward_offset << ", rev offset: " << result_phantom_node.reverse_offset; + // SimpleLogger().Write(logDEBUG) << "[rtree] bidirected: " << (result_phantom_node.isBidirected() ? "y" : "n"); + // SimpleLogger().Write(logDEBUG) << "[rtree] name id: " << result_phantom_node.name_id; + // SimpleLogger().Write(logDEBUG) << "[rtree] geom id: " << result_phantom_node.packed_geometry_id; + // SimpleLogger().Write(logDEBUG) << "[rtree] ratio: " << ratio; return found_a_nearest_edge; } diff --git a/DataStructures/TurnInstructions.h b/DataStructures/TurnInstructions.h index 4a80ccfc2..cb60a32f5 100644 --- a/DataStructures/TurnInstructions.h +++ b/DataStructures/TurnInstructions.h @@ -92,6 +92,4 @@ struct TurnInstructionsClass : boost::noncopyable { }; -static TurnInstructionsClass TurnInstructions; - #endif /* TURNINSTRUCTIONS_H_ */ diff --git a/Descriptors/DescriptionFactory.cpp b/Descriptors/DescriptionFactory.cpp index 90b57d2b3..1db3fca2e 100644 --- a/Descriptors/DescriptionFactory.cpp +++ b/Descriptors/DescriptionFactory.cpp @@ -31,18 +31,18 @@ DescriptionFactory::DescriptionFactory() : entireLength(0) { } DescriptionFactory::~DescriptionFactory() { } -inline double DescriptionFactory::DegreeToRadian(const double degree) const { - return degree * (M_PI/180); +inline double DescriptionFactory::DegreeToRadian(const double degree) const +{ + return degree * (M_PI/180.); } -inline double DescriptionFactory::RadianToDegree(const double radian) const { - return radian * (180/M_PI); +inline double DescriptionFactory::RadianToDegree(const double radian) const +{ + return radian * (180./M_PI); } -double DescriptionFactory::GetBearing( - const FixedPointCoordinate & A, - const FixedPointCoordinate & B -) const { +double DescriptionFactory::GetBearing(const FixedPointCoordinate & A, const FixedPointCoordinate & B) const +{ double delta_long = DegreeToRadian(B.lon/COORDINATE_PRECISION - A.lon/COORDINATE_PRECISION); const double lat1 = DegreeToRadian(A.lat/COORDINATE_PRECISION); @@ -51,55 +51,52 @@ double DescriptionFactory::GetBearing( const double y = sin(delta_long) * cos(lat2); const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long); double result = RadianToDegree(atan2(y, x)); - while(result < 0.) { + while (result < 0.) + { result += 360.; } - while(result >= 360.) { + + while (result >= 360.) + { result -= 360.; } return result; } -void DescriptionFactory::SetStartSegment(const PhantomNode & start) { - start_phantom = start; +void DescriptionFactory::SetStartSegment(const PhantomNode & source, const bool source_traversed_in_reverse) +{ + start_phantom = source; AppendSegment( - start.location, - PathData(0, start.nodeBasedEdgeNameID, 10, start.weight1) + source.location, + PathData(0, source.name_id, 10, source.forward_weight) ); } -void DescriptionFactory::SetEndSegment(const PhantomNode & target) { +void DescriptionFactory::SetEndSegment(const PhantomNode & target, const bool target_traversed_in_reverse) +{ target_phantom = target; pathDescription.push_back( SegmentInformation( target.location, - target.nodeBasedEdgeNameID, + target.name_id, 0, - target.weight1, + target.reverse_weight, 0, true ) ); } -void DescriptionFactory::AppendSegment( - const FixedPointCoordinate & coordinate, - const PathData & data -) { - if( - ( 1 == pathDescription.size()) && - ( pathDescription.back().location == coordinate) - ) { - pathDescription.back().name_id = data.name_id; - } else { +void DescriptionFactory::AppendSegment(const FixedPointCoordinate & coordinate, const PathData & path_point) +{ + if ((1 == pathDescription.size()) && ( pathDescription.back().location == coordinate)) + { + pathDescription.back().name_id = path_point.name_id; + } + else + { pathDescription.push_back( - SegmentInformation( - coordinate, - data.name_id, - data.durationOfSegment, - 0, - data.turnInstruction - ) + SegmentInformation(coordinate, path_point.name_id, path_point.durationOfSegment, 0, path_point.turnInstruction) ); } } @@ -137,7 +134,7 @@ void DescriptionFactory::BuildRouteSummary( const double distance, const unsigned time ) { - summary.startName = start_phantom.nodeBasedEdgeNameID; - summary.destName = target_phantom.nodeBasedEdgeNameID; + summary.startName = start_phantom.name_id; + summary.destName = target_phantom.name_id; summary.BuildDurationAndLengthStrings(distance, time); } diff --git a/Descriptors/DescriptionFactory.h b/Descriptors/DescriptionFactory.h index 53deca7f4..11eb28220 100644 --- a/Descriptors/DescriptionFactory.h +++ b/Descriptors/DescriptionFactory.h @@ -71,7 +71,7 @@ public: ) { //compute distance/duration for route summary intToString(round(distance), lengthString); - int travel_time = time/10; + int travel_time = round(time/10.); intToString(std::max(travel_time, 1), durationString); } } summary; @@ -87,8 +87,8 @@ public: void AppendUnencodedPolylineString(std::vector &output) const; void AppendSegment(const FixedPointCoordinate & coordinate, const PathData & data); void BuildRouteSummary(const double distance, const unsigned time); - void SetStartSegment(const PhantomNode & start_phantom); - void SetEndSegment(const PhantomNode & start_phantom); + void SetStartSegment(const PhantomNode & start_phantom, const bool source_traversed_in_reverse); + void SetEndSegment(const PhantomNode & start_phantom, const bool target_traversed_in_reverse); void AppendEncodedPolylineString( const bool return_encoded, std::vector & output @@ -105,14 +105,13 @@ public: /** starts at index 1 */ pathDescription[0].length = 0; - for(unsigned i = 1; i < pathDescription.size(); ++i) { + for (unsigned i = 1; i < pathDescription.size(); ++i) + { + //move down names by one, q&d hack + pathDescription[i-1].name_id = pathDescription[i].name_id; pathDescription[i].length = FixedPointCoordinate::ApproximateEuclideanDistance(pathDescription[i-1].location, pathDescription[i].location); } - // std::string string0 = facade->GetEscapedNameForNameID(pathDescription[0].name_id); - // std::string string1; - - /*Simplify turn instructions Input : 10. Turn left on B 36 for 20 km @@ -154,23 +153,23 @@ public: // string0 = string1; // } - double lengthOfSegment = 0; - unsigned durationOfSegment = 0; - unsigned indexOfSegmentBegin = 0; + double segment_length = 0.; + unsigned segment_duration = 0; + unsigned segment_start_index = 0; for(unsigned i = 1; i < pathDescription.size(); ++i) { entireLength += pathDescription[i].length; - lengthOfSegment += pathDescription[i].length; - durationOfSegment += pathDescription[i].duration; - pathDescription[indexOfSegmentBegin].length = lengthOfSegment; - pathDescription[indexOfSegmentBegin].duration = durationOfSegment; + segment_length += pathDescription[i].length; + segment_duration += pathDescription[i].duration; + pathDescription[segment_start_index].length = segment_length; + pathDescription[segment_start_index].duration = segment_duration; if(TurnInstructionsClass::NoTurn != pathDescription[i].turn_instruction) { BOOST_ASSERT(pathDescription[i].necessary); - lengthOfSegment = 0; - durationOfSegment = 0; - indexOfSegmentBegin = i; + segment_length = 0; + segment_duration = 0; + segment_start_index = i; } } @@ -179,21 +178,17 @@ public: if(pathDescription.size() > 2){ pathDescription.pop_back(); pathDescription.back().necessary = true; - pathDescription.back().turn_instruction = TurnInstructions.NoTurn; - target_phantom.nodeBasedEdgeNameID = (pathDescription.end()-2)->name_id; + pathDescription.back().turn_instruction = TurnInstructionsClass::NoTurn; + target_phantom.name_id = (pathDescription.end()-2)->name_id; } - } else { - pathDescription[indexOfSegmentBegin].duration *= (1.-target_phantom.ratio); } if(std::numeric_limits::epsilon() > pathDescription[0].length) { if(pathDescription.size() > 2) { pathDescription.erase(pathDescription.begin()); - pathDescription[0].turn_instruction = TurnInstructions.HeadOn; + pathDescription[0].turn_instruction = TurnInstructionsClass::HeadOn; pathDescription[0].necessary = true; - start_phantom.nodeBasedEdgeNameID = pathDescription[0].name_id; + start_phantom.name_id = pathDescription[0].name_id; } - } else { - pathDescription[0].duration *= start_phantom.ratio; } //Generalize poly line diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 105a09abf..7d9a6d680 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -65,12 +65,12 @@ public: (raw_route.unpacked_path_segments[0].size()); if( found_route ) { FixedPointCoordinate::convertInternalLatLonToString( - phantom_node_list.startPhantom.location.lat, + phantom_node_list.source_phantom.location.lat, tmp ); reply.content.push_back(""); @@ -90,12 +90,12 @@ public: } // Add the via point or the end coordinate FixedPointCoordinate::convertInternalLatLonToString( - phantom_node_list.targetPhantom.location.lat, + phantom_node_list.target_phantom.location.lat, tmp ); reply.content.push_back(""); diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index 2d367a9cc..7b0522017 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. template class JSONDescriptor : public BaseDescriptor { private: + // TODO: initalize in c'tor DataFacadeT * facade; DescriptorConfig config; DescriptionFactory description_factory; @@ -59,7 +60,7 @@ private: int start_index; int name_id; int leave_at_exit; - } roundAbout; + } round_about; struct Segment { Segment() : name_id(-1), length(-1), position(-1) {} @@ -90,7 +91,7 @@ public: void SetConfig(const DescriptorConfig & c) { config = c; } int DescribeLeg( - const std::vector & route_leg, + const std::vector route_leg, const PhantomNodes & leg_phantoms ) { int added_element_count = 0; @@ -98,10 +99,10 @@ public: FixedPointCoordinate current_coordinate; BOOST_FOREACH(const PathData & path_data, route_leg) { current_coordinate = facade->GetCoordinateOfNode(path_data.node); - description_factory.AppendSegment(current_coordinate, path_data ); + description_factory.AppendSegment(current_coordinate, path_data); ++added_element_count; } - // description_factory.SetEndSegment( leg_phantoms.targetPhantom ); + // description_factory.SetEndSegment( leg_phantoms.target_phantom ); ++added_element_count; BOOST_ASSERT( (int)(route_leg.size() + 1) == added_element_count ); return added_element_count; @@ -119,7 +120,8 @@ public: "{\"status\":" ); - if(INT_MAX == raw_route.lengthOfShortestPath) { + if (INVALID_EDGE_WEIGHT == raw_route.lengthOfShortestPath) + { //We do not need to do much, if there is no route ;-) reply.content.push_back( "207,\"status_message\": \"Cannot find route between points\"}" @@ -127,12 +129,36 @@ public: return; } - description_factory.SetStartSegment(phantom_nodes.startPhantom); + SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.lengthOfShortestPath; + + //check if first segment is non-zero + std::string road_name; + road_name = facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id); + + // for each unpacked segment add the leg to the description + BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() ); + + for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i) + { + const std::vector & leg_path = raw_route.unpacked_path_segments[i]; + FixedPointCoordinate current_coordinate; + BOOST_FOREACH(const PathData & path_data, leg_path) + { + current_coordinate = facade->GetCoordinateOfNode(path_data.node); + road_name = facade->GetEscapedNameForNameID(path_data.name_id); + } + } + + //check if last segment is non-zero + road_name = facade->GetEscapedNameForNameID(phantom_nodes.target_phantom.name_id); + + description_factory.SetStartSegment(phantom_nodes.source_phantom, raw_route.source_traversed_in_reverse); reply.content.push_back("0," "\"status_message\": \"Found route between points\","); BOOST_ASSERT( raw_route.unpacked_path_segments.size() == raw_route.segmentEndCoordinates.size() ); - for( unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i ) { + for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i) + { const int added_segments = DescribeLeg( raw_route.unpacked_path_segments[i], raw_route.segmentEndCoordinates[i] @@ -142,7 +168,7 @@ public: added_segments + shortest_leg_end_indices.back() ); } - description_factory.SetEndSegment(phantom_nodes.targetPhantom); + description_factory.SetEndSegment(phantom_nodes.target_phantom, raw_route.target_traversed_in_reverse); description_factory.Run(facade, config.zoom_level); reply.content.push_back("\"route_geometry\": "); @@ -194,14 +220,15 @@ public: //only one alternative route is computed at this time, so this is hardcoded - if(raw_route.lengthOfAlternativePath != INT_MAX) { - alternate_descriptionFactory.SetStartSegment(phantom_nodes.startPhantom); + if(raw_route.lengthOfAlternativePath != INVALID_EDGE_WEIGHT) + { + alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom, raw_route.alt_source_traversed_in_reverse); //Get all the coordinates for the computed route BOOST_FOREACH(const PathData & path_data, raw_route.unpacked_alternative) { current = facade->GetCoordinateOfNode(path_data.node); alternate_descriptionFactory.AppendSegment(current, path_data ); } - alternate_descriptionFactory.SetEndSegment(phantom_nodes.targetPhantom); + alternate_descriptionFactory.SetEndSegment(phantom_nodes.target_phantom, raw_route.alt_target_traversed_in_reverse); } alternate_descriptionFactory.Run(facade, config.zoom_level); @@ -286,7 +313,7 @@ public: std::string tmp; FixedPointCoordinate::convertInternalReversedCoordinateToString( - raw_route.segmentEndCoordinates.front().startPhantom.location, + raw_route.segmentEndCoordinates.front().source_phantom.location, tmp ); reply.content.push_back("["); @@ -296,7 +323,7 @@ public: BOOST_FOREACH(const PhantomNodes & nodes, raw_route.segmentEndCoordinates) { tmp.clear(); FixedPointCoordinate::convertInternalReversedCoordinateToString( - nodes.targetPhantom.location, + nodes.target_phantom.location, tmp ); reply.content.push_back(",["); @@ -332,11 +359,11 @@ public: std::string hint; for(unsigned i = 0; i < raw_route.segmentEndCoordinates.size(); ++i) { reply.content.push_back("\""); - EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].startPhantom, hint); + EncodeObjectToBase64(raw_route.segmentEndCoordinates[i].source_phantom, hint); reply.content.push_back(hint); reply.content.push_back("\", "); } - EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().targetPhantom, hint); + EncodeObjectToBase64(raw_route.segmentEndCoordinates.back().target_phantom, hint); reply.content.push_back("\""); reply.content.push_back(hint); reply.content.push_back("\"]"); @@ -419,56 +446,61 @@ public: //Segment information has following format: //["instruction","streetname",length,position,time,"length","earth_direction",azimuth] //Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5] - //See also: http://developers.cloudmade.com/wiki/navengine/JSON_format - unsigned prefixSumOfNecessarySegments = 0; - roundAbout.leave_at_exit = 0; - roundAbout.name_id = 0; - std::string tmpDist, tmpLength, tmpDuration, tmpBearing, tmpInstruction; + unsigned necessary_segments_running_index = 0; + round_about.leave_at_exit = 0; + round_about.name_id = 0; + std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction; + //Fetch data from Factory and generate a string from it. BOOST_FOREACH(const SegmentInformation & segment, description_factory.pathDescription) { - TurnInstruction current_instruction = segment.turn_instruction & TurnInstructions.InverseAccessRestrictionFlag; + TurnInstruction current_instruction = segment.turn_instruction & TurnInstructionsClass::InverseAccessRestrictionFlag; entered_restricted_area_count += (current_instruction != segment.turn_instruction); - if(TurnInstructions.TurnIsNecessary( current_instruction) ) { - if(TurnInstructions.EnterRoundAbout == current_instruction) { - roundAbout.name_id = segment.name_id; - roundAbout.start_index = prefixSumOfNecessarySegments; - } else { - if(0 != prefixSumOfNecessarySegments){ + if (TurnInstructionsClass::TurnIsNecessary( current_instruction) ) + { + if (TurnInstructionsClass::EnterRoundAbout == current_instruction) + { + round_about.name_id = segment.name_id; + round_about.start_index = necessary_segments_running_index; + } + else + { + if (0 != necessary_segments_running_index) + { reply.content.push_back(","); } reply.content.push_back("[\""); - if(TurnInstructions.LeaveRoundAbout == current_instruction) { - intToString(TurnInstructions.EnterRoundAbout, tmpInstruction); - reply.content.push_back(tmpInstruction); + if(TurnInstructionsClass::LeaveRoundAbout == current_instruction) { + intToString(TurnInstructionsClass::EnterRoundAbout, temp_instruction); + reply.content.push_back(temp_instruction); reply.content.push_back("-"); - intToString(roundAbout.leave_at_exit+1, tmpInstruction); - reply.content.push_back(tmpInstruction); - roundAbout.leave_at_exit = 0; + intToString(round_about.leave_at_exit+1, temp_instruction); + reply.content.push_back(temp_instruction); + round_about.leave_at_exit = 0; } else { - intToString(current_instruction, tmpInstruction); - reply.content.push_back(tmpInstruction); + intToString(current_instruction, temp_instruction); + reply.content.push_back(temp_instruction); } reply.content.push_back("\",\""); reply.content.push_back(facade->GetEscapedNameForNameID(segment.name_id)); reply.content.push_back("\","); - intToString(segment.length, tmpDist); - reply.content.push_back(tmpDist); + intToString(segment.length, temp_dist); + reply.content.push_back(temp_dist); reply.content.push_back(","); - intToString(prefixSumOfNecessarySegments, tmpLength); - reply.content.push_back(tmpLength); + intToString(necessary_segments_running_index, temp_length); + reply.content.push_back(temp_length); reply.content.push_back(","); - intToString(segment.duration/10, tmpDuration); - reply.content.push_back(tmpDuration); + intToString(round(segment.duration/10.), temp_duration); + reply.content.push_back(temp_duration); reply.content.push_back(",\""); - intToString(segment.length, tmpLength); - reply.content.push_back(tmpLength); + intToString(segment.length, temp_length); + reply.content.push_back(temp_length); reply.content.push_back("m\",\""); double bearing_value = round(segment.bearing/10.); reply.content.push_back(Azimuth::Get(bearing_value)); reply.content.push_back("\","); - intToString(bearing_value, tmpBearing); - reply.content.push_back(tmpBearing); + intToString(bearing_value, temp_bearing); + reply.content.push_back(temp_bearing); reply.content.push_back("]"); route_segments_list.push_back( @@ -479,22 +511,22 @@ public: ) ); } - } else if(TurnInstructions.StayOnRoundAbout == current_instruction) { - ++roundAbout.leave_at_exit; + } else if(TurnInstructionsClass::StayOnRoundAbout == current_instruction) { + ++round_about.leave_at_exit; } if(segment.necessary) - ++prefixSumOfNecessarySegments; + ++necessary_segments_running_index; } if(INT_MAX != route_length) { reply.content.push_back(",[\""); - intToString(TurnInstructions.ReachedYourDestination, tmpInstruction); - reply.content.push_back(tmpInstruction); + intToString(TurnInstructionsClass::ReachedYourDestination, temp_instruction); + reply.content.push_back(temp_instruction); reply.content.push_back("\",\""); reply.content.push_back("\","); reply.content.push_back("0"); reply.content.push_back(","); - intToString(prefixSumOfNecessarySegments-1, tmpLength); - reply.content.push_back(tmpLength); + intToString(necessary_segments_running_index-1, temp_length); + reply.content.push_back(temp_length); reply.content.push_back(","); reply.content.push_back("0"); reply.content.push_back(",\""); diff --git a/Extractor/ExtractionContainers.cpp b/Extractor/ExtractionContainers.cpp index dc1a7ff60..44c4d6895 100644 --- a/Extractor/ExtractionContainers.cpp +++ b/Extractor/ExtractionContainers.cpp @@ -362,7 +362,6 @@ void ExtractionContainers::PrepareData( break; default: throw OSRMException("edge has broken direction"); - break; } file_out_stream.write( (char*)&integer_weight, sizeof(int) @@ -373,23 +372,27 @@ void ExtractionContainers::PrepareData( sizeof(short) ); file_out_stream.write( - (char*)&edge_iterator->nameID, + (char *) &edge_iterator->nameID, sizeof(unsigned) ); file_out_stream.write( - (char*)&edge_iterator->isRoundabout, + (char *) &edge_iterator->isRoundabout, sizeof(bool) ); file_out_stream.write( - (char*)&edge_iterator->ignoreInGrid, + (char *) &edge_iterator->ignoreInGrid, sizeof(bool) ); file_out_stream.write( - (char*)&edge_iterator->isAccessRestricted, + (char *) &edge_iterator->isAccessRestricted, sizeof(bool) ); file_out_stream.write( - (char*)&edge_iterator->isContraFlow, + (char *) &edge_iterator->isContraFlow, + sizeof(bool) + ); + file_out_stream.write( + (char *) &edge_iterator->is_split, sizeof(bool) ); ++number_of_used_edges; diff --git a/Extractor/ExtractionHelperFunctions.h b/Extractor/ExtractionHelperFunctions.h index c0b74bdb3..d284efdd7 100644 --- a/Extractor/ExtractionHelperFunctions.h +++ b/Extractor/ExtractionHelperFunctions.h @@ -75,13 +75,13 @@ inline unsigned parseDuration(const std::string &s) { return UINT_MAX; } -inline int parseMaxspeed(std::string input) { //call-by-value on purpose. - boost::algorithm::to_lower(input); - int n = stringToInt(input); - if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) { - n = (n*1609)/1000; - } - return n; -} +// inline int parseMaxspeed(std::string input) { //call-by-value on purpose. +// boost::algorithm::to_lower(input); +// int n = stringToInt(input); +// if (input.find("mph") != std::string::npos || input.find("mp/h") != std::string::npos) { +// n = (n*1609)/1000; +// } +// return n; +// } #endif /* EXTRACTIONHELPERFUNCTIONS_H_ */ diff --git a/Extractor/ExtractorCallbacks.cpp b/Extractor/ExtractorCallbacks.cpp index e97275749..9ac9cb1cb 100644 --- a/Extractor/ExtractorCallbacks.cpp +++ b/Extractor/ExtractorCallbacks.cpp @@ -28,34 +28,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ExtractorCallbacks.h" #include "ExtractionContainers.h" -#include "ExtractionHelperFunctions.h" #include "ExtractionWay.h" #include "../DataStructures/Restriction.h" +#include "../DataStructures/ImportNode.h" #include "../Util/SimpleLogger.h" #include -#include - -#include -#include -#include - #include #include ExtractorCallbacks::ExtractorCallbacks() : - stringMap(NULL), + string_map(NULL), externalMemory(NULL) { } ExtractorCallbacks::ExtractorCallbacks( ExtractionContainers * ext, - StringMap * strMap + boost::unordered_map * string_map ) : - stringMap(strMap), + string_map(string_map), externalMemory(ext) { } @@ -95,11 +89,11 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { } //Get the unique identifier for the street name - const StringMap::const_iterator & string_map_iterator = stringMap->find(parsed_way.name); - if(stringMap->end() == string_map_iterator) { + const boost::unordered_map::const_iterator & string_map_iterator = string_map->find(parsed_way.name); + if(string_map->end() == string_map_iterator) { parsed_way.nameID = externalMemory->name_list.size(); externalMemory->name_list.push_back(parsed_way.name); - stringMap->insert(std::make_pair(parsed_way.name, parsed_way.nameID)); + string_map->insert(std::make_pair(parsed_way.name, parsed_way.nameID)); } else { parsed_way.nameID = string_map_iterator->second; } @@ -113,16 +107,19 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->all_edges_list.push_back( - InternalExtractorEdge(parsed_way.path[n], - parsed_way.path[n+1], - parsed_way.type, - (split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction), - parsed_way.speed, - parsed_way.nameID, - parsed_way.roundabout, - parsed_way.ignoreInGrid, - (0 < parsed_way.duration), - parsed_way.isAccessRestricted + InternalExtractorEdge( + parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + (split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction), + parsed_way.speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + (0 < parsed_way.duration), + parsed_way.isAccessRestricted, + false, + split_bidirectional_edge ) ); externalMemory->used_node_id_list.push_back(parsed_way.path[n]); @@ -136,17 +133,19 @@ void ExtractorCallbacks::wayFunction(ExtractionWay &parsed_way) { std::reverse( parsed_way.path.begin(), parsed_way.path.end() ); for(std::vector< NodeID >::size_type n = 0; n < parsed_way.path.size()-1; ++n) { externalMemory->all_edges_list.push_back( - InternalExtractorEdge(parsed_way.path[n], - parsed_way.path[n+1], - parsed_way.type, - ExtractionWay::oneway, - parsed_way.backward_speed, - parsed_way.nameID, - parsed_way.roundabout, - parsed_way.ignoreInGrid, - (0 < parsed_way.duration), - parsed_way.isAccessRestricted, - (ExtractionWay::oneway == parsed_way.direction) + InternalExtractorEdge( + parsed_way.path[n], + parsed_way.path[n+1], + parsed_way.type, + ExtractionWay::oneway, + parsed_way.backward_speed, + parsed_way.nameID, + parsed_way.roundabout, + parsed_way.ignoreInGrid, + (0 < parsed_way.duration), + parsed_way.isAccessRestricted, + (ExtractionWay::oneway == parsed_way.direction), + split_bidirectional_edge ) ); } diff --git a/Extractor/ExtractorCallbacks.h b/Extractor/ExtractorCallbacks.h index 555d19a12..3a27b6ed8 100644 --- a/Extractor/ExtractorCallbacks.h +++ b/Extractor/ExtractorCallbacks.h @@ -28,29 +28,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef EXTRACTORCALLBACKS_H_ #define EXTRACTORCALLBACKS_H_ -#include "ExtractorStructs.h" #include "../typedefs.h" #include #include +struct ExternalMemoryNode; class ExtractionContainers; struct ExtractionWay; struct InputRestrictionContainer; -typedef boost::unordered_map StringMap; - class ExtractorCallbacks{ private: - StringMap * stringMap; + boost::unordered_map * string_map; ExtractionContainers * externalMemory; ExtractorCallbacks(); public: explicit ExtractorCallbacks( ExtractionContainers * ext, - StringMap * strMap + boost::unordered_map * string_map ); ~ExtractorCallbacks(); diff --git a/Extractor/InternalExtractorEdge.h b/Extractor/InternalExtractorEdge.h index 3dca1fa1d..e504d4fd1 100644 --- a/Extractor/InternalExtractorEdge.h +++ b/Extractor/InternalExtractorEdge.h @@ -28,9 +28,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INTERNAL_EXTRACTOR_EDGE_H #define INTERNAL_EXTRACTOR_EDGE_H -#include #include "../typedefs.h" +#include #include @@ -47,70 +47,10 @@ struct InternalExtractorEdge { ignoreInGrid(false), isDurationSet(false), isAccessRestricted(false), - isContraFlow(false) + isContraFlow(false), + is_split(false) { } - explicit InternalExtractorEdge(NodeID start, NodeID target) - : - start(start), - target(target), - type(0), - direction(0), - speed(0), - nameID(0), - isRoundabout(false), - ignoreInGrid(false), - isDurationSet(false), - isAccessRestricted(false), - isContraFlow(false) - { } - - explicit InternalExtractorEdge( - NodeID start, - NodeID target, - short type, - short d, - double speed - ) : - start(start), - target(target), - type(type), - direction(d), - speed(speed), - nameID(0), - isRoundabout(false), - ignoreInGrid(false), - isDurationSet(false), - isAccessRestricted(false), - isContraFlow(false) - { } - - explicit InternalExtractorEdge( - NodeID start, - NodeID target, - short type, - short direction, - double speed, - unsigned nameID, - bool isRoundabout, - bool ignoreInGrid, - bool isDurationSet, - bool isAccressRestricted - ) : - start(start), - target(target), - type(type), - direction(direction), - speed(speed), - nameID(nameID), - isRoundabout(isRoundabout), - ignoreInGrid(ignoreInGrid), - isDurationSet(isDurationSet), - isAccessRestricted(isAccressRestricted), - isContraFlow(false) - { - BOOST_ASSERT(0 <= type); - } explicit InternalExtractorEdge( NodeID start, @@ -123,7 +63,8 @@ struct InternalExtractorEdge { bool ignoreInGrid, bool isDurationSet, bool isAccressRestricted, - bool isContraFlow + bool isContraFlow, + bool is_split ) : start(start), target(target), @@ -135,19 +76,43 @@ struct InternalExtractorEdge { ignoreInGrid(ignoreInGrid), isDurationSet(isDurationSet), isAccessRestricted(isAccressRestricted), - isContraFlow(isContraFlow) + isContraFlow(isContraFlow), + is_split(is_split) { BOOST_ASSERT(0 <= type); } // necessary static util functions for stxxl's sorting static InternalExtractorEdge min_value() { - return InternalExtractorEdge(0,0); + return InternalExtractorEdge( + 0, + 0, + 0, + 0, + 0, + 0, + false, + false, + false, + false, + false, + false + ); } static InternalExtractorEdge max_value() { return InternalExtractorEdge( std::numeric_limits::max(), - std::numeric_limits::max() + std::numeric_limits::max(), + 0, + 0, + 0, + 0, + false, + false, + false, + false, + false, + false ); } @@ -162,6 +127,7 @@ struct InternalExtractorEdge { bool isDurationSet; bool isAccessRestricted; bool isContraFlow; + bool is_split; FixedPointCoordinate startCoord; FixedPointCoordinate targetCoord; diff --git a/Extractor/PBFParser.cpp b/Extractor/PBFParser.cpp index f229ae103..003552885 100644 --- a/Extractor/PBFParser.cpp +++ b/Extractor/PBFParser.cpp @@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ScriptingEnvironment.h" #include "../DataStructures/HashTable.h" +#include "../DataStructures/ImportNode.h" #include "../DataStructures/Restriction.h" #include "../Util/MachineInfo.h" #include "../Util/OpenMPWrapper.h" diff --git a/Extractor/PBFParser.h b/Extractor/PBFParser.h index 91c89157b..e67a845b8 100644 --- a/Extractor/PBFParser.h +++ b/Extractor/PBFParser.h @@ -76,13 +76,13 @@ public: private: inline void ReadData(); inline void ParseData(); - inline void parseDenseNode (_ThreadData * threadData); - inline void parseNode (_ThreadData * threadData); - inline void parseRelation (_ThreadData * threadData); - inline void parseWay (_ThreadData * threadData); + inline void parseDenseNode (_ThreadData * threadData); + inline void parseNode (_ThreadData * threadData); + inline void parseRelation (_ThreadData * threadData); + inline void parseWay (_ThreadData * threadData); - inline void loadGroup (_ThreadData * threadData); - inline void loadBlock (_ThreadData * threadData); + inline void loadGroup (_ThreadData * threadData); + inline void loadBlock (_ThreadData * threadData); inline bool readPBFBlobHeader(std::fstream & stream, _ThreadData * threadData); inline bool unpackZLIB (std::fstream & stream, _ThreadData * threadData); inline bool unpackLZMA (std::fstream & stream, _ThreadData * threadData); diff --git a/Extractor/ScriptingEnvironment.cpp b/Extractor/ScriptingEnvironment.cpp index d904b649a..998e2f198 100644 --- a/Extractor/ScriptingEnvironment.cpp +++ b/Extractor/ScriptingEnvironment.cpp @@ -58,7 +58,7 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { // Add our function to the state's global scope luabind::module(myLuaState) [ luabind::def("print", LUA_print), - luabind::def("parseMaxspeed", parseMaxspeed), + // luabind::def("parseMaxspeed", parseMaxspeed), luabind::def("durationIsValid", durationIsValid), luabind::def("parseDuration", parseDuration) ]; diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 26c31ebd2..2fdcb6a6e 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "XMLParser.h" #include "ExtractionWay.h" +#include "ExtractorCallbacks.h" + #include "../DataStructures/HashTable.h" #include "../DataStructures/ImportNode.h" #include "../DataStructures/InputReaderFactory.h" diff --git a/Extractor/XMLParser.h b/Extractor/XMLParser.h index 9e307fcc1..7c88d48a7 100644 --- a/Extractor/XMLParser.h +++ b/Extractor/XMLParser.h @@ -33,13 +33,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include - class XMLParser : public BaseParser { public: XMLParser( const char* filename, - ExtractorCallbacks* ec, - ScriptingEnvironment& se + ExtractorCallbacks * ec, + ScriptingEnvironment & se ); bool ReadHeader(); bool Parse(); diff --git a/Include/osrm/Coordinate.h b/Include/osrm/Coordinate.h index 1f7a27a28..76d158a34 100644 --- a/Include/osrm/Coordinate.h +++ b/Include/osrm/Coordinate.h @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef FIXED_POINT_COORDINATE_H_ #define FIXED_POINT_COORDINATE_H_ -#include +#include //for std::ostream static const double COORDINATE_PRECISION = 1000000.; @@ -37,7 +37,7 @@ struct FixedPointCoordinate { int lon; FixedPointCoordinate(); - explicit FixedPointCoordinate (int lat, int lon); + explicit FixedPointCoordinate( int lat, int lon); void Reset(); bool isSet() const; bool isValid() const; @@ -74,11 +74,13 @@ struct FixedPointCoordinate { const FixedPointCoordinate & coord, std::string & output ); + + void Output(std::ostream & out) const; }; -inline std::ostream & operator<<(std::ostream & out, const FixedPointCoordinate & c){ - out << "(" << c.lat << "," << c.lon << ")"; - return out; +inline std::ostream& operator<<(std::ostream& o, FixedPointCoordinate const & c){ + c.Output(o); + return o; } #endif /* FIXED_POINT_COORDINATE_H_ */ diff --git a/Library/OSRM.h b/Library/OSRM.h index be137b8c5..599a93524 100644 --- a/Library/OSRM.h +++ b/Library/OSRM.h @@ -28,8 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef OSRM_H #define OSRM_H -#include - #include #include #include diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h index 0543dffe0..2484d0fac 100644 --- a/Plugins/NearestPlugin.h +++ b/Plugins/NearestPlugin.h @@ -50,10 +50,9 @@ public: descriptorTable.emplace("json", 1); } const std::string & GetDescriptor() const { return descriptor_string; } - void HandleRequest( const RouteParameters & routeParameters, - http::Reply& reply + http::Reply & reply ) { //check number of parameters if(!routeParameters.coordinates.size()) { @@ -82,13 +81,13 @@ public: reply.status = http::Reply::ok; reply.content.push_back("{\"status\":"); - if(UINT_MAX != result.edgeBasedNode) { + if(UINT_MAX != result.forward_node_id) { reply.content.push_back("0,"); } else { reply.content.push_back("207,"); } reply.content.push_back("\"mapped_coordinate\":["); - if(UINT_MAX != result.edgeBasedNode) { + if(UINT_MAX != result.forward_node_id) { FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string); reply.content.push_back(temp_string); FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string); @@ -96,8 +95,8 @@ public: reply.content.push_back(temp_string); } reply.content.push_back("],\"name\":\""); - if(UINT_MAX != result.edgeBasedNode) { - facade->GetName(result.nodeBasedEdgeNameID, temp_string); + if(UINT_MAX != result.forward_node_id) { + facade->GetName(result.name_id, temp_string); reply.content.push_back(temp_string); } reply.content.push_back("\"}"); diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 5f25f20bc..007cdae29 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -95,14 +95,11 @@ public: std::vector phantomNodeVector(rawRoute.rawViaNodeCoordinates.size()); for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) { if(checksumOK && i < routeParameters.hints.size() && "" != routeParameters.hints[i]) { -// SimpleLogger().Write() <<"Decoding hint: " << routeParameters.hints[i] << " for location index " << i; DecodeObjectFromBase64(routeParameters.hints[i], phantomNodeVector[i]); if(phantomNodeVector[i].isValid(facade->GetNumberOfNodes())) { -// SimpleLogger().Write() << "Decoded hint " << i << " successfully"; continue; } } -// SimpleLogger().Write() << "Brute force lookup of coordinate " << i; facade->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], @@ -112,8 +109,8 @@ public: PhantomNodes segmentPhantomNodes; for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) { - segmentPhantomNodes.startPhantom = phantomNodeVector[i]; - segmentPhantomNodes.targetPhantom = phantomNodeVector[i+1]; + segmentPhantomNodes.source_phantom = phantomNodeVector[i]; + segmentPhantomNodes.target_phantom = phantomNodeVector[i+1]; rawRoute.segmentEndCoordinates.push_back(segmentPhantomNodes); } @@ -132,9 +129,9 @@ public: ); } - if(INT_MAX == rawRoute.lengthOfShortestPath ) { - SimpleLogger().Write(logDEBUG) << - "Error occurred, single path not found"; + if (INT_MAX == rawRoute.lengthOfShortestPath) + { + SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found"; } reply.status = http::Reply::ok; @@ -172,11 +169,12 @@ public: } PhantomNodes phantomNodes; - phantomNodes.startPhantom = rawRoute.segmentEndCoordinates[0].startPhantom; - phantomNodes.targetPhantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].targetPhantom; + phantomNodes.source_phantom = rawRoute.segmentEndCoordinates[0].source_phantom; + phantomNodes.target_phantom = rawRoute.segmentEndCoordinates[rawRoute.segmentEndCoordinates.size()-1].target_phantom; desc->SetConfig(descriptorConfig); desc->Run(rawRoute, phantomNodes, facade, reply); + if("" != routeParameters.jsonpParameter) { reply.content.push_back(")\n"); } diff --git a/RoutingAlgorithms/AlternativePathRouting.h b/RoutingAlgorithms/AlternativePathRouting.h index 80a410e1e..9d5983c8c 100644 --- a/RoutingAlgorithms/AlternativePathRouting.h +++ b/RoutingAlgorithms/AlternativePathRouting.h @@ -25,20 +25,22 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ALTERNATIVEROUTES_H_ -#define ALTERNATIVEROUTES_H_ +#ifndef ALTERNATIVE_PATH_ROUTING_H +#define ALTERNATIVE_PATH_ROUTING_H #include "BasicRoutingInterface.h" #include "../DataStructures/SearchEngineData.h" +#include "../Util/TimingUtil.h" +#include #include #include -#include + #include -const double VIAPATH_ALPHA = 0.15; -const double VIAPATH_EPSILON = 0.10; //alternative at most 15% longer -const double VIAPATH_GAMMA = 0.75; //alternative shares at most 75% with the shortest. +const double VIAPATH_ALPHA = 0.10; +const double VIAPATH_EPSILON = 0.15; // alternative at most 15% longer +const double VIAPATH_GAMMA = 0.75; // alternative shares at most 75% with the shortest. template class AlternativeRouting : private BasicRoutingInterface { @@ -47,17 +49,18 @@ class AlternativeRouting : private BasicRoutingInterface { typedef SearchEngineData::QueryHeap QueryHeap; typedef std::pair SearchSpaceEdge; - struct RankedCandidateNode { - RankedCandidateNode(const NodeID n, const int l, const int s) : - node(n), - length(l), - sharing(s) + struct RankedCandidateNode + { + RankedCandidateNode(const NodeID node, const int length, const int sharing) + : node(node), length(length), sharing(sharing) { } NodeID node; int length; int sharing; - bool operator<(const RankedCandidateNode& other) const { + + bool operator<(const RankedCandidateNode& other) const + { return (2*length + sharing) < (2*other.length + other.sharing); } }; @@ -74,17 +77,17 @@ public: engine_working_data(engine_working_data) { } - ~AlternativeRouting() {} + virtual ~AlternativeRouting() {} - void operator()( + void operator() ( const PhantomNodes & phantom_node_pair, RawRouteData & raw_route_data ) { - if( (!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) || - phantom_node_pair.PhantomNodesHaveEqualLocation() + if( //phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() || + phantom_node_pair.PhantomNodesHaveEqualLocation() ) { - raw_route_data.lengthOfShortestPath = INT_MAX; - raw_route_data.lengthOfAlternativePath = INT_MAX; + // raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT; + // raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT; return; } @@ -109,41 +112,42 @@ public: QueryHeap & forward_heap2 = *(engine_working_data.forwardHeap2); QueryHeap & reverse_heap2 = *(engine_working_data.backwardHeap2); - int upper_bound_to_shortest_path_distance = INT_MAX; - NodeID middle_node = UINT_MAX; - forward_heap1.Insert( - phantom_node_pair.startPhantom.edgeBasedNode, - -phantom_node_pair.startPhantom.weight1, - phantom_node_pair.startPhantom.edgeBasedNode - ); - if(phantom_node_pair.startPhantom.isBidirected() ) { + int upper_bound_to_shortest_path_distance = INVALID_EDGE_WEIGHT; + NodeID middle_node = SPECIAL_NODEID; + if(phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID ) { + // SimpleLogger().Write(logDEBUG) << "fwd-a insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); forward_heap1.Insert( - phantom_node_pair.startPhantom.edgeBasedNode+1, - -phantom_node_pair.startPhantom.weight2, - phantom_node_pair.startPhantom.edgeBasedNode+1 + phantom_node_pair.source_phantom.forward_node_id, + -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.forward_node_id + ); + } + if(phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID ) { + // SimpleLogger().Write(logDEBUG) << "fwd-b insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); + forward_heap1.Insert( + phantom_node_pair.source_phantom.reverse_node_id, + -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.source_phantom.reverse_node_id ); } - reverse_heap1.Insert( - phantom_node_pair.targetPhantom.edgeBasedNode, - phantom_node_pair.targetPhantom.weight1, - phantom_node_pair.targetPhantom.edgeBasedNode - ); - if(phantom_node_pair.targetPhantom.isBidirected() ) { + if(phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) { + // SimpleLogger().Write(logDEBUG) << "rev-a insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); + reverse_heap1.Insert( + phantom_node_pair.target_phantom.forward_node_id, + phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.target_phantom.forward_node_id + ); + } + if(phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) { + // SimpleLogger().Write(logDEBUG) << "rev-b insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); reverse_heap1.Insert( - phantom_node_pair.targetPhantom.edgeBasedNode+1, - phantom_node_pair.targetPhantom.weight2, - phantom_node_pair.targetPhantom.edgeBasedNode+1 + phantom_node_pair.target_phantom.reverse_node_id, + phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.target_phantom.reverse_node_id ); } - const int forward_offset = super::ComputeEdgeOffset( - phantom_node_pair.startPhantom - ); - const int reverse_offset = super::ComputeEdgeOffset( - phantom_node_pair.targetPhantom - ); - //search from s and t till new_min/(1+epsilon) > length_of_shortest_path while(0 < (forward_heap1.Size() + reverse_heap1.Size())){ if(0 < forward_heap1.Size()){ @@ -153,8 +157,7 @@ public: &middle_node, &upper_bound_to_shortest_path_distance, via_node_candidate_list, - forward_search_space, - forward_offset + forward_search_space ); } if(0 < reverse_heap1.Size()){ @@ -164,12 +167,12 @@ public: &middle_node, &upper_bound_to_shortest_path_distance, via_node_candidate_list, - reverse_search_space, - reverse_offset + reverse_search_space ); } } - sort_unique_resize(via_node_candidate_list); + + sort_unique_resize( via_node_candidate_list ); std::vector packed_forward_path; std::vector packed_reverse_path; @@ -185,6 +188,8 @@ public: packed_reverse_path ); + //TODO: leave early when no path found: + boost::unordered_map approximated_forward_sharing; boost::unordered_map approximated_reverse_sharing; @@ -193,7 +198,10 @@ public: BOOST_FOREACH(const SearchSpaceEdge & current_edge, forward_search_space) { const NodeID u = current_edge.first; const NodeID v = current_edge.second; - if(packed_forward_path.size() < index_into_forward_path && current_edge == forward_search_space[index_into_forward_path]) { + if( + ( packed_forward_path.size() < index_into_forward_path ) && + ( current_edge == forward_search_space[index_into_forward_path] ) + ) { //current_edge is on shortest path => sharing(u):=queue.GetKey(u); ++index_into_forward_path; approximated_forward_sharing[v] = forward_heap1.GetKey(u); @@ -208,176 +216,327 @@ public: BOOST_FOREACH(const SearchSpaceEdge & current_edge, reverse_search_space) { const NodeID u = current_edge.first; const NodeID v = current_edge.second; - if(packed_reverse_path.size() < index_into_reverse_path && current_edge == reverse_search_space[index_into_reverse_path]) { + if( + ( packed_reverse_path.size() < index_into_reverse_path ) && + ( current_edge == reverse_search_space[index_into_reverse_path] ) + ) { //current_edge is on shortest path => sharing(u):=queue.GetKey(u); ++index_into_reverse_path; approximated_reverse_sharing[v] = reverse_heap1.GetKey(u); } else { //sharing (s) = sharing (t) - boost::unordered_map::const_iterator rev_iterator = approximated_reverse_sharing.find(u); + boost::unordered_map::const_iterator rev_iterator = approximated_reverse_sharing.find(u); const int rev_sharing = (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0; approximated_reverse_sharing[v] = rev_sharing; } } - std::vector nodes_that_passed_preselection; + + // SimpleLogger().Write(logDEBUG) << "fwd_search_space size: " << forward_search_space.size() << ", marked " << approximated_forward_sharing.size() << " nodes"; + // SimpleLogger().Write(logDEBUG) << "rev_search_space size: " << reverse_search_space.size() << ", marked " << approximated_reverse_sharing.size() << " nodes"; + + std::vector preselected_node_list; BOOST_FOREACH(const NodeID node, via_node_candidate_list) { boost::unordered_map::const_iterator fwd_iterator = approximated_forward_sharing.find(node); const int fwd_sharing = (fwd_iterator != approximated_forward_sharing.end()) ? fwd_iterator->second : 0; boost::unordered_map::const_iterator rev_iterator = approximated_reverse_sharing.find(node); const int rev_sharing = (rev_iterator != approximated_reverse_sharing.end()) ? rev_iterator->second : 0; - int approximated_sharing = fwd_sharing + rev_sharing; - int approximated_length = forward_heap1.GetKey(node)+reverse_heap1.GetKey(node); - bool lengthPassed = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)); - bool sharingPassed = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA); - bool stretchPassed = approximated_length - approximated_sharing < (1.+VIAPATH_EPSILON)*(upper_bound_to_shortest_path_distance-approximated_sharing); + const int approximated_sharing = fwd_sharing + rev_sharing; + const int approximated_length = forward_heap1.GetKey(node) + reverse_heap1.GetKey(node); + const bool length_passes = (approximated_length < upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)); + const bool sharing_passes = (approximated_sharing <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA); + const bool stretch_passes = (approximated_length - approximated_sharing) < ((1.+VIAPATH_ALPHA)*(upper_bound_to_shortest_path_distance-approximated_sharing)); - if(lengthPassed && sharingPassed && stretchPassed) { - nodes_that_passed_preselection.push_back(node); + if( length_passes && sharing_passes && stretch_passes ) { + preselected_node_list.push_back(node); } } - std::vector & packedShortestPath = packed_forward_path; - std::reverse(packedShortestPath.begin(), packedShortestPath.end()); - packedShortestPath.push_back(middle_node); - packedShortestPath.insert(packedShortestPath.end(),packed_reverse_path.begin(), packed_reverse_path.end()); - std::vector rankedCandidates; + // SimpleLogger().Write() << preselected_node_list.size() << " passed preselection"; + + std::vector & packed_shortest_path = packed_forward_path; + std::reverse(packed_shortest_path.begin(), packed_shortest_path.end()); + packed_shortest_path.push_back(middle_node); + packed_shortest_path.insert( + packed_shortest_path.end(), + packed_reverse_path.begin(), + packed_reverse_path.end() + ); + std::vector ranked_candidates_list; //prioritizing via nodes for deep inspection - BOOST_FOREACH(const NodeID node, nodes_that_passed_preselection) { - int lengthOfViaPath = 0, sharingOfViaPath = 0; - computeLengthAndSharingOfViaPath(node, &lengthOfViaPath, &sharingOfViaPath, forward_offset+reverse_offset, packedShortestPath); - if(sharingOfViaPath <= upper_bound_to_shortest_path_distance*VIAPATH_GAMMA) { - rankedCandidates.push_back(RankedCandidateNode(node, lengthOfViaPath, sharingOfViaPath)); + BOOST_FOREACH(const NodeID node, preselected_node_list) { + int length_of_via_path = 0, sharing_of_via_path = 0; + ComputeLengthAndSharingOfViaPath(node, &length_of_via_path, &sharing_of_via_path, packed_shortest_path); + const int maximum_allowed_sharing = upper_bound_to_shortest_path_distance*VIAPATH_GAMMA; + if( sharing_of_via_path <= maximum_allowed_sharing && length_of_via_path <= upper_bound_to_shortest_path_distance*(1+VIAPATH_EPSILON)) { + ranked_candidates_list.push_back( + RankedCandidateNode( + node, + length_of_via_path, + sharing_of_via_path + ) + ); } } - std::sort(rankedCandidates.begin(), rankedCandidates.end()); + std::sort( + ranked_candidates_list.begin(), + ranked_candidates_list.end() + ); - NodeID selectedViaNode = UINT_MAX; - int lengthOfViaPath = INT_MAX; - NodeID s_v_middle = UINT_MAX, v_t_middle = UINT_MAX; - BOOST_FOREACH(const RankedCandidateNode & candidate, rankedCandidates){ - if(viaNodeCandidatePasses_T_Test(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, forward_offset+reverse_offset, upper_bound_to_shortest_path_distance, &lengthOfViaPath, &s_v_middle, &v_t_middle)) { + NodeID selected_via_node = SPECIAL_NODEID; + int length_of_via_path = INVALID_EDGE_WEIGHT; + NodeID s_v_middle = SPECIAL_NODEID, v_t_middle = SPECIAL_NODEID; + BOOST_FOREACH(const RankedCandidateNode & candidate, ranked_candidates_list){ + if(ViaNodeCandidatePassesTTest(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, candidate, upper_bound_to_shortest_path_distance, &length_of_via_path, &s_v_middle, &v_t_middle)) { // select first admissable - selectedViaNode = candidate.node; + selected_via_node = candidate.node; break; } } - //Unpack shortest path and alternative, if they exist - if(INT_MAX != upper_bound_to_shortest_path_distance) { + if( INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_distance ) + { + BOOST_ASSERT(!packed_shortest_path.empty()); raw_route_data.unpacked_path_segments.resize(1); - super::UnpackPath(packedShortestPath, raw_route_data.unpacked_path_segments[0]); + raw_route_data.source_traversed_in_reverse = (packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_node_id); + raw_route_data.target_traversed_in_reverse = (packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_node_id); + + super::UnpackPath( + // -- packed input + packed_shortest_path, + // -- start of route + phantom_node_pair, + // -- unpacked output + raw_route_data.unpacked_path_segments.front() + ); raw_route_data.lengthOfShortestPath = upper_bound_to_shortest_path_distance; - } else { - raw_route_data.lengthOfShortestPath = INT_MAX; } - if(selectedViaNode != UINT_MAX) { - retrievePackedViaPath(forward_heap1, reverse_heap1, forward_heap2, reverse_heap2, s_v_middle, v_t_middle, raw_route_data.unpacked_alternative); - raw_route_data.lengthOfAlternativePath = lengthOfViaPath; - } else { - raw_route_data.lengthOfAlternativePath = INT_MAX; + if( SPECIAL_NODEID != selected_via_node ) { + std::vector packed_alternate_path; + // retrieve alternate path + RetrievePackedAlternatePath( + forward_heap1, + reverse_heap1, + forward_heap2, + reverse_heap2, + s_v_middle, + v_t_middle, + packed_alternate_path + ); + + raw_route_data.source_traversed_in_reverse = (packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_node_id); + raw_route_data.target_traversed_in_reverse = (packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_node_id); + + // unpack the alternate path + super::UnpackPath( + packed_alternate_path, + phantom_node_pair, + raw_route_data.unpacked_alternative + ); + + raw_route_data.lengthOfAlternativePath = length_of_via_path; } } private: - //unpack by exploring search spaces from v - inline void retrievePackedViaPath(QueryHeap & _forwardHeap1, QueryHeap & _backwardHeap1, QueryHeap & _forwardHeap2, QueryHeap & _backwardHeap2, - const NodeID s_v_middle, const NodeID v_t_middle, std::vector & unpackedPath) { - //unpack [s,v) - std::vector packed_s_v_path, packed_v_t_path; - super::RetrievePackedPathFromHeap(_forwardHeap1, _backwardHeap2, s_v_middle, packed_s_v_path); - packed_s_v_path.resize(packed_s_v_path.size()-1); - //unpack [v,t] - super::RetrievePackedPathFromHeap(_forwardHeap2, _backwardHeap1, v_t_middle, packed_v_t_path); - packed_s_v_path.insert(packed_s_v_path.end(),packed_v_t_path.begin(), packed_v_t_path.end() ); - super::UnpackPath(packed_s_v_path, unpackedPath); + //unpack alternate by exploring search spaces from v + inline void RetrievePackedAlternatePath( + const QueryHeap & forward_heap1, + const QueryHeap & reverse_heap1, + const QueryHeap & forward_heap2, + const QueryHeap & reverse_heap2, + const NodeID s_v_middle, + const NodeID v_t_middle, + std::vector & packed_path + ) const { + //fetch packed path [s,v) + std::vector packed_v_t_path; + super::RetrievePackedPathFromHeap( + forward_heap1, + reverse_heap2, + s_v_middle, + packed_path + ); + packed_path.pop_back(); //remove middle node. It's in both half-paths + + //fetch patched path [v,t] + super::RetrievePackedPathFromHeap( + forward_heap2, + reverse_heap1, + v_t_middle, + packed_v_t_path + ); + + packed_path.insert( + packed_path.end(), + packed_v_t_path.begin(), + packed_v_t_path.end() + ); } - inline void computeLengthAndSharingOfViaPath(const NodeID via_node, int *real_length_of_via_path, int *sharing_of_via_path, - const int offset, const std::vector & packed_shortest_path) { - //compute and unpack and by exploring search spaces from v and intersecting against queues - //only half-searches have to be done at this stage + //TODO: reorder parameters + // compute and unpack and by exploring search spaces + // from v and intersecting against queues. only half-searches have to be + // done at this stage + inline void ComputeLengthAndSharingOfViaPath( + const NodeID via_node, + int *real_length_of_via_path, + int *sharing_of_via_path, + const std::vector & packed_shortest_path + ) { engine_working_data.InitializeOrClearSecondThreadLocalStorage( super::facade->GetNumberOfNodes() ); - QueryHeap & existingForwardHeap = *engine_working_data.forwardHeap; - QueryHeap & existingBackwardHeap = *engine_working_data.backwardHeap; - QueryHeap & newForwardHeap = *engine_working_data.forwardHeap2; - QueryHeap & newBackwardHeap = *engine_working_data.backwardHeap2; + QueryHeap & existing_forward_heap = *engine_working_data.forwardHeap; + QueryHeap & existing_reverse_heap = *engine_working_data.backwardHeap; + QueryHeap & new_forward_heap = *engine_working_data.forwardHeap2; + QueryHeap & new_reverse_heap = *engine_working_data.backwardHeap2; - std::vector < NodeID > packed_s_v_path; - std::vector < NodeID > packed_v_t_path; + std::vector packed_s_v_path; + std::vector packed_v_t_path; - std::vector partiallyUnpackedShortestPath; - std::vector partiallyUnpackedViaPath; + std::vector partially_unpacked_shortest_path; + std::vector partially_unpacked_via_path; - NodeID s_v_middle = UINT_MAX; - int upperBoundFor_s_vPath = INT_MAX;//compute path by reusing forward search from s - newBackwardHeap.Insert(via_node, 0, via_node); - while (0 < newBackwardHeap.Size()) { - super::RoutingStep(newBackwardHeap, existingForwardHeap, &s_v_middle, &upperBoundFor_s_vPath, 2 * offset, false); + NodeID s_v_middle = SPECIAL_NODEID; + int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT; + new_reverse_heap.Insert(via_node, 0, via_node); + //compute path by reusing forward search from s + while( !new_reverse_heap.Empty() ) { + super::RoutingStep( + new_reverse_heap, + existing_forward_heap, + &s_v_middle, + &upper_bound_s_v_path_length, + false + ); } //compute path by reusing backward search from node t - NodeID v_t_middle = UINT_MAX; - int upperBoundFor_v_tPath = INT_MAX; - newForwardHeap.Insert(via_node, 0, via_node); - while (0 < newForwardHeap.Size() ) { - super::RoutingStep(newForwardHeap, existingBackwardHeap, &v_t_middle, &upperBoundFor_v_tPath, 2 * offset, true); + NodeID v_t_middle = SPECIAL_NODEID; + int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT; + new_forward_heap.Insert(via_node, 0, via_node); + while(!new_forward_heap.Empty() ) { + super::RoutingStep( + new_forward_heap, + existing_reverse_heap, + &v_t_middle, + &upper_bound_of_v_t_path_length, + true + ); } - *real_length_of_via_path = upperBoundFor_s_vPath + upperBoundFor_v_tPath; + *real_length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; - if(UINT_MAX == s_v_middle || UINT_MAX == v_t_middle) + if( SPECIAL_NODEID == s_v_middle || SPECIAL_NODEID == v_t_middle ) { return; + } //retrieve packed paths - super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, s_v_middle, packed_s_v_path); - super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap( + existing_forward_heap, + new_reverse_heap, + s_v_middle, + packed_s_v_path + ); + super::RetrievePackedPathFromHeap( + new_forward_heap, + existing_reverse_heap, + v_t_middle, + packed_v_t_path + ); //partial unpacking, compute sharing //First partially unpack s-->v until paths deviate, note length of common path. - for (unsigned i = 0, lengthOfPackedPath = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; (i < lengthOfPackedPath); ++i) { - if (packed_s_v_path[i] == packed_shortest_path[i] && packed_s_v_path[i + 1] == packed_shortest_path[i + 1]) { + const unsigned s_v_min_path_size = std::min( packed_s_v_path.size(), packed_shortest_path.size()) - 1; + for( + unsigned i = 0; + i < s_v_min_path_size; + ++i + ) { + if( packed_s_v_path[i] == packed_shortest_path[i] && + packed_s_v_path[i+1] == packed_shortest_path[i+1] + ) { EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_s_v_path[i], packed_s_v_path[i + 1]); *sharing_of_via_path += facade->GetEdgeData(edgeID).distance; } else { - if (packed_s_v_path[i] == packed_shortest_path[i]) { - super::UnpackEdge(packed_s_v_path[i], packed_s_v_path[i+1], partiallyUnpackedViaPath); - super::UnpackEdge(packed_shortest_path[i], packed_shortest_path[i+1], partiallyUnpackedShortestPath); + if( packed_s_v_path[i] == packed_shortest_path[i] ) { + super::UnpackEdge( + packed_s_v_path[i], + packed_s_v_path[i+1], + partially_unpacked_via_path + ); + super::UnpackEdge( + packed_shortest_path[i], + packed_shortest_path[i+1], + partially_unpacked_shortest_path + ); break; } } } //traverse partially unpacked edge and note common prefix - for (int i = 0, lengthOfPackedPath = std::min( partiallyUnpackedViaPath.size(), partiallyUnpackedShortestPath.size()) - 1; (i < lengthOfPackedPath) && (partiallyUnpackedViaPath[i] == partiallyUnpackedShortestPath[i] && partiallyUnpackedViaPath[i+1] == partiallyUnpackedShortestPath[i+1]); ++i) { - EdgeID edgeID = facade->FindEdgeInEitherDirection(partiallyUnpackedViaPath[i], partiallyUnpackedViaPath[i+1]); + for( + int i = 0, packed_path_length = std::min( partially_unpacked_via_path.size(), partially_unpacked_shortest_path.size()) - 1; + (i < packed_path_length) && (partially_unpacked_via_path[i] == partially_unpacked_shortest_path[i] && partially_unpacked_via_path[i+1] == partially_unpacked_shortest_path[i+1]); + ++i + ) { + EdgeID edgeID = facade->FindEdgeInEitherDirection( + partially_unpacked_via_path[i], + partially_unpacked_via_path[i+1] + ); *sharing_of_via_path += facade->GetEdgeData(edgeID).distance; } //Second, partially unpack v-->t in reverse order until paths deviate and note lengths - int viaPathIndex = packed_v_t_path.size() - 1; - int shortestPathIndex = packed_shortest_path.size() - 1; - for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex ) { - if (packed_v_t_path[viaPathIndex - 1] == packed_shortest_path[shortestPathIndex - 1] && packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) { - EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[viaPathIndex - 1], packed_v_t_path[viaPathIndex]); + int via_path_index = packed_v_t_path.size()-1; + int shortest_path_index = packed_shortest_path.size()-1; + for(; + via_path_index > 0 && shortest_path_index > 0; + --via_path_index,--shortest_path_index + ) { + if( + packed_v_t_path[via_path_index-1] == packed_shortest_path[shortest_path_index-1] && + packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index] + ) { + EdgeID edgeID = facade->FindEdgeInEitherDirection( + packed_v_t_path[via_path_index-1], + packed_v_t_path[via_path_index] + ); *sharing_of_via_path += facade->GetEdgeData(edgeID).distance; } else { - if (packed_v_t_path[viaPathIndex] == packed_shortest_path[shortestPathIndex]) { - super::UnpackEdge(packed_v_t_path[viaPathIndex-1], packed_v_t_path[viaPathIndex], partiallyUnpackedViaPath); - super::UnpackEdge(packed_shortest_path[shortestPathIndex-1] , packed_shortest_path[shortestPathIndex], partiallyUnpackedShortestPath); + if( packed_v_t_path[via_path_index] == packed_shortest_path[shortest_path_index] ) { + super::UnpackEdge( + packed_v_t_path[via_path_index-1], + packed_v_t_path[via_path_index], + partially_unpacked_via_path + ); + super::UnpackEdge( + packed_shortest_path[shortest_path_index-1], + packed_shortest_path[shortest_path_index], + partially_unpacked_shortest_path + ); break; } } } - viaPathIndex = partiallyUnpackedViaPath.size() - 1; - shortestPathIndex = partiallyUnpackedShortestPath.size() - 1; - for (; viaPathIndex > 0 && shortestPathIndex > 0; --viaPathIndex,--shortestPathIndex) { - if (partiallyUnpackedViaPath[viaPathIndex - 1] == partiallyUnpackedShortestPath[shortestPathIndex - 1] && partiallyUnpackedViaPath[viaPathIndex] == partiallyUnpackedShortestPath[shortestPathIndex]) { - EdgeID edgeID = facade->FindEdgeInEitherDirection( partiallyUnpackedViaPath[viaPathIndex - 1], partiallyUnpackedViaPath[viaPathIndex]); + via_path_index = partially_unpacked_via_path.size()-1; + shortest_path_index = partially_unpacked_shortest_path.size()-1; + for(; + via_path_index > 0 && shortest_path_index > 0; + --via_path_index,--shortest_path_index + ) { + if( + partially_unpacked_via_path[via_path_index-1] == partially_unpacked_shortest_path[shortest_path_index-1] && + partially_unpacked_via_path[via_path_index] == partially_unpacked_shortest_path[shortest_path_index] + ) { + EdgeID edgeID = facade->FindEdgeInEitherDirection( + partially_unpacked_via_path[via_path_index-1], + partially_unpacked_via_path[via_path_index] + ); *sharing_of_via_path += facade->GetEdgeData(edgeID).distance; } else { break; @@ -386,241 +545,330 @@ private: //finished partial unpacking spree! Amount of sharing is stored to appropriate pointer variable } - inline int approximateAmountOfSharing(const NodeID middleNodeIDOfAlternativePath, QueryHeap & _forwardHeap, QueryHeap & _backwardHeap, const std::vector & packedShortestPath) { - std::vector packedAlternativePath; - super::RetrievePackedPathFromHeap(_forwardHeap, _backwardHeap, middleNodeIDOfAlternativePath, packedAlternativePath); + // inline int approximateAmountOfSharing( + // const NodeID alternate_path_middle_node_id, + // QueryHeap & forward_heap, + // QueryHeap & reverse_heap, + // const std::vector & packed_shortest_path + // ) const { + // std::vector packed_alternate_path; + // super::RetrievePackedPathFromHeap( + // forward_heap, + // reverse_heap, + // alternate_path_middle_node_id, + // packed_alternate_path + // ); - if(packedShortestPath.size() < 2 || packedAlternativePath.size() < 2) - return 0; + // if(packed_shortest_path.size() < 2 || packed_alternate_path.size() < 2) { + // return 0; + // } - int sharing = 0; - int aindex = 0; - //compute forward sharing - while( (packedAlternativePath[aindex] == packedShortestPath[aindex]) && (packedAlternativePath[aindex+1] == packedShortestPath[aindex+1]) ) { - // SimpleLogger().Write() << "retrieving edge (" << packedAlternativePath[aindex] << "," << packedAlternativePath[aindex+1] << ")"; - EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex+1]); - sharing += facade->GetEdgeData(edgeID).distance; - ++aindex; - } + // int sharing = 0; + // int aindex = 0; + // //compute forward sharing + // while( (packed_alternate_path[aindex] == packed_shortest_path[aindex]) && (packed_alternate_path[aindex+1] == packed_shortest_path[aindex+1]) ) { + // // SimpleLogger().Write() << "retrieving edge (" << packed_alternate_path[aindex] << "," << packed_alternate_path[aindex+1] << ")"; + // EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex], packed_alternate_path[aindex+1]); + // sharing += facade->GetEdgeData(edgeID).distance; + // ++aindex; + // } - aindex = packedAlternativePath.size()-1; - int bindex = packedShortestPath.size()-1; - //compute backward sharing - while( aindex > 0 && bindex > 0 && (packedAlternativePath[aindex] == packedShortestPath[bindex]) && (packedAlternativePath[aindex-1] == packedShortestPath[bindex-1]) ) { - EdgeID edgeID = facade->FindEdgeInEitherDirection(packedAlternativePath[aindex], packedAlternativePath[aindex-1]); - sharing += facade->GetEdgeData(edgeID).distance; - --aindex; --bindex; - } - return sharing; - } + // aindex = packed_alternate_path.size()-1; + // int bindex = packed_shortest_path.size()-1; + // //compute backward sharing + // while( aindex > 0 && bindex > 0 && (packed_alternate_path[aindex] == packed_shortest_path[bindex]) && (packed_alternate_path[aindex-1] == packed_shortest_path[bindex-1]) ) { + // EdgeID edgeID = facade->FindEdgeInEitherDirection(packed_alternate_path[aindex], packed_alternate_path[aindex-1]); + // sharing += facade->GetEdgeData(edgeID).distance; + // --aindex; --bindex; + // } + // return sharing; + // } - template + //todo: reorder parameters + template inline void AlternativeRoutingStep( - QueryHeap & _forward_heap, - QueryHeap & _reverse_heap, - NodeID *middle_node, - int *upper_bound_to_shortest_path_distance, - std::vector& searchSpaceIntersection, - std::vector & search_space, - const int edgeBasedOffset - ) const { - const NodeID node = _forward_heap.DeleteMin(); - const int distance = _forward_heap.GetKey(node); - int scaledDistance = (distance-edgeBasedOffset)/(1.+VIAPATH_EPSILON); - if(scaledDistance > *upper_bound_to_shortest_path_distance){ - _forward_heap.DeleteAll(); + QueryHeap & forward_heap, + QueryHeap & reverse_heap, + NodeID * middle_node, + int * upper_bound_to_shortest_path_distance, + std::vector & search_space_intersection, + std::vector & search_space + ) const { + const NodeID node = forward_heap.DeleteMin(); + const int distance = forward_heap.GetKey(node); + const int scaled_distance = distance/(1.+VIAPATH_EPSILON); + // SimpleLogger().Write(logDEBUG) << "node: " << node << ", distance: " << distance << ", ub: " << *upper_bound_to_shortest_path_distance << ", scaled_distance: " << scaled_distance; + if( + (INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_distance) && + (scaled_distance > *upper_bound_to_shortest_path_distance) + ) { + // SimpleLogger().Write(logDEBUG) << "removing nodes from heap"; + forward_heap.DeleteAll(); return; } - search_space.push_back(std::make_pair(_forward_heap.GetData( node ).parent, node)); + search_space.push_back( + std::make_pair(forward_heap.GetData( node ).parent, node) + ); - if(_reverse_heap.WasInserted(node) ){ - searchSpaceIntersection.push_back(node); + if (reverse_heap.WasInserted(node)) { + search_space_intersection.push_back(node); - const int newDistance = _reverse_heap.GetKey(node) + distance; - if(newDistance < *upper_bound_to_shortest_path_distance ){ - if(newDistance>=0 ) { + const int new_distance = reverse_heap.GetKey(node) + distance; + if (new_distance < *upper_bound_to_shortest_path_distance) + { + if (new_distance >= 0) + { *middle_node = node; - *upper_bound_to_shortest_path_distance = newDistance; + *upper_bound_to_shortest_path_distance = new_distance; } } } - for ( EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); edge++ ) { + for( + EdgeID edge = facade->BeginEdges(node); + edge < facade->EndEdges(node); + ++edge + ) { const EdgeData & data = facade->GetEdgeData(edge); - bool forwardDirectionFlag = (forwardDirection ? data.forward : data.backward ); - if(forwardDirectionFlag) { + const bool edge_is_forward_directed = (is_forward_directed ? data.forward : data.backward ); + if( edge_is_forward_directed ) { const NodeID to = facade->GetTarget(edge); - const int edgeWeight = data.distance; + const int edge_weight = data.distance; - assert( edgeWeight > 0 ); - const int toDistance = distance + edgeWeight; + BOOST_ASSERT( edge_weight > 0 ); + const int to_distance = distance + edge_weight; //New Node discovered -> Add to Heap + Node Info Storage - if ( !_forward_heap.WasInserted( to ) ) { - _forward_heap.Insert( to, toDistance, node ); + if( !forward_heap.WasInserted( to ) ) { + forward_heap.Insert( to, to_distance, node ); } //Found a shorter Path -> Update distance - else if ( toDistance < _forward_heap.GetKey( to ) ) { - _forward_heap.GetData( to ).parent = node; - _forward_heap.DecreaseKey( to, toDistance ); - //new parent + else if( to_distance < forward_heap.GetKey( to ) ) { + // new parent + forward_heap.GetData( to ).parent = node; + // decreased distance + forward_heap.DecreaseKey( to, to_distance ); } } } } //conduct T-Test - inline bool viaNodeCandidatePasses_T_Test( QueryHeap& existingForwardHeap, QueryHeap& existingBackwardHeap, QueryHeap& newForwardHeap, QueryHeap& newBackwardHeap, const RankedCandidateNode& candidate, const int offset, const int lengthOfShortestPath, int * lengthOfViaPath, NodeID * s_v_middle, NodeID * v_t_middle) { - newForwardHeap.Clear(); - newBackwardHeap.Clear(); - std::vector < NodeID > packed_s_v_path; - std::vector < NodeID > packed_v_t_path; + inline bool ViaNodeCandidatePassesTTest( + QueryHeap& existing_forward_heap, + QueryHeap& existing_reverse_heap, + QueryHeap& new_forward_heap, + QueryHeap& new_reverse_heap, + const RankedCandidateNode& candidate, + const int lengthOfShortestPath, + int * length_of_via_path, + NodeID * s_v_middle, + NodeID * v_t_middle + ) const { + new_forward_heap.Clear(); + new_reverse_heap.Clear(); + std::vector packed_s_v_path; + std::vector packed_v_t_path; - *s_v_middle = UINT_MAX; - int upperBoundFor_s_vPath = INT_MAX; + *s_v_middle = SPECIAL_NODEID; + int upper_bound_s_v_path_length = INVALID_EDGE_WEIGHT; //compute path by reusing forward search from s - newBackwardHeap.Insert(candidate.node, 0, candidate.node); - while (newBackwardHeap.Size() > 0) { - super::RoutingStep(newBackwardHeap, existingForwardHeap, s_v_middle, &upperBoundFor_s_vPath, 2*offset, false); + new_reverse_heap.Insert(candidate.node, 0, candidate.node); + while (new_reverse_heap.Size() > 0) { + super::RoutingStep(new_reverse_heap, existing_forward_heap, s_v_middle, &upper_bound_s_v_path_length, false); } - if(INT_MAX == upperBoundFor_s_vPath) + if( INVALID_EDGE_WEIGHT == upper_bound_s_v_path_length ) { return false; + } //compute path by reusing backward search from t - *v_t_middle = UINT_MAX; - int upperBoundFor_v_tPath = INT_MAX; - newForwardHeap.Insert(candidate.node, 0, candidate.node); - while (newForwardHeap.Size() > 0) { - super::RoutingStep(newForwardHeap, existingBackwardHeap, v_t_middle, &upperBoundFor_v_tPath, 2*offset, true); + *v_t_middle = SPECIAL_NODEID; + int upper_bound_of_v_t_path_length = INVALID_EDGE_WEIGHT; + new_forward_heap.Insert(candidate.node, 0, candidate.node); + while (new_forward_heap.Size() > 0) { + super::RoutingStep(new_forward_heap, existing_reverse_heap, v_t_middle, &upper_bound_of_v_t_path_length, true); } - if(INT_MAX == upperBoundFor_v_tPath) + if( INVALID_EDGE_WEIGHT == upper_bound_of_v_t_path_length ){ return false; + } - *lengthOfViaPath = upperBoundFor_s_vPath + upperBoundFor_v_tPath; + *length_of_via_path = upper_bound_s_v_path_length + upper_bound_of_v_t_path_length; //retrieve packed paths - super::RetrievePackedPathFromHeap(existingForwardHeap, newBackwardHeap, *s_v_middle, packed_s_v_path); - super::RetrievePackedPathFromHeap(newForwardHeap, existingBackwardHeap, *v_t_middle, packed_v_t_path); + super::RetrievePackedPathFromHeap( + existing_forward_heap, + new_reverse_heap, + *s_v_middle, + packed_s_v_path + ); + + super::RetrievePackedPathFromHeap( + new_forward_heap, + existing_reverse_heap, + *v_t_middle, + packed_v_t_path + ); NodeID s_P = *s_v_middle, t_P = *v_t_middle; - if(UINT_MAX == s_P) { + if( SPECIAL_NODEID == s_P ) { return false; } - if(UINT_MAX == t_P) { + if( SPECIAL_NODEID == t_P ) { return false; } const int T_threshold = VIAPATH_EPSILON * lengthOfShortestPath; - int unpackedUntilDistance = 0; + int unpacked_until_distance = 0; - std::stack unpackStack; + std::stack unpack_stack; //Traverse path s-->v - for (unsigned i = packed_s_v_path.size() - 1; (i > 0) && unpackStack.empty(); --i) { - EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]); - int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance; - if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { - unpackStack.push(std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i])); + for( + unsigned i = packed_s_v_path.size() - 1; + (i > 0) && unpack_stack.empty(); + --i + ) { + const EdgeID current_edge_id = facade->FindEdgeInEitherDirection( packed_s_v_path[i - 1], packed_s_v_path[i]); + const int length_of_current_edge = facade->GetEdgeData(current_edge_id).distance; + if( (length_of_current_edge + unpacked_until_distance) >= T_threshold ) { + unpack_stack.push( + std::make_pair(packed_s_v_path[i - 1], packed_s_v_path[i]) + ); } else { - unpackedUntilDistance += lengthOfCurrentEdge; + unpacked_until_distance += length_of_current_edge; s_P = packed_s_v_path[i - 1]; } } - while (!unpackStack.empty()) { - const SearchSpaceEdge viaPathEdge = unpackStack.top(); - unpackStack.pop(); - EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); - if(UINT_MAX == edgeIDInViaPath) + while( !unpack_stack.empty() ) { + const SearchSpaceEdge via_path_edge = unpack_stack.top(); + unpack_stack.pop(); + EdgeID edge_in_via_path_id = facade->FindEdgeInEitherDirection( + via_path_edge.first, + via_path_edge.second + ); + + if( SPECIAL_EDGEID == edge_in_via_path_id ) { return false; - EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath); - bool IsViaEdgeShortCut = currentEdgeData.shortcut; - if (IsViaEdgeShortCut) { - const NodeID middleOfViaPath = currentEdgeData.id; - EdgeID edgeIDOfSecondSegment = facade->FindEdgeInEitherDirection(middleOfViaPath, viaPathEdge.second); - int lengthOfSecondSegment = facade->GetEdgeData(edgeIDOfSecondSegment).distance; + } + + const EdgeData & current_edge_data = facade->GetEdgeData(edge_in_via_path_id); + const bool current_edge_is_shortcut = current_edge_data.shortcut; + if( current_edge_is_shortcut ) { + const NodeID via_path_middle_node_id = current_edge_data.id; + const EdgeID second_segment_edge_id = facade->FindEdgeInEitherDirection(via_path_middle_node_id, via_path_edge.second); + const int second_segment_length = facade->GetEdgeData(second_segment_edge_id).distance; //attention: !unpacking in reverse! //Check if second segment is the one to go over treshold? if yes add second segment to stack, else push first segment to stack and add distance of second one. - if (unpackedUntilDistance + lengthOfSecondSegment >= T_threshold) { - unpackStack.push(std::make_pair(middleOfViaPath, viaPathEdge.second)); + if (unpacked_until_distance + second_segment_length >= T_threshold) { + unpack_stack.push( + std::make_pair( + via_path_middle_node_id, + via_path_edge.second + ) + ); } else { - unpackedUntilDistance += lengthOfSecondSegment; - unpackStack.push(std::make_pair(viaPathEdge.first, middleOfViaPath)); + unpacked_until_distance += second_segment_length; + unpack_stack.push( + std::make_pair( + via_path_edge.first, + via_path_middle_node_id + ) + ); } } else { // edge is not a shortcut, set the start node for T-Test to end of edge. - unpackedUntilDistance += currentEdgeData.distance; - s_P = viaPathEdge.first; + unpacked_until_distance += current_edge_data.distance; + s_P = via_path_edge.first; } } - int lengthOfPathT_TestPath = unpackedUntilDistance; - unpackedUntilDistance = 0; + int t_test_path_length = unpacked_until_distance; + unpacked_until_distance = 0; //Traverse path s-->v - for (unsigned i = 0, lengthOfPackedPath = packed_v_t_path.size() - 1; (i < lengthOfPackedPath) && unpackStack.empty(); ++i) { + for( + unsigned i = 0, packed_path_length = packed_v_t_path.size() - 1; + (i < packed_path_length) && unpack_stack.empty(); + ++i + ) { EdgeID edgeID = facade->FindEdgeInEitherDirection( packed_v_t_path[i], packed_v_t_path[i + 1]); - int lengthOfCurrentEdge = facade->GetEdgeData(edgeID).distance; - if (lengthOfCurrentEdge + unpackedUntilDistance >= T_threshold) { - unpackStack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1])); + int length_of_current_edge = facade->GetEdgeData(edgeID).distance; + if (length_of_current_edge + unpacked_until_distance >= T_threshold) { + unpack_stack.push( std::make_pair(packed_v_t_path[i], packed_v_t_path[i + 1])); } else { - unpackedUntilDistance += lengthOfCurrentEdge; + unpacked_until_distance += length_of_current_edge; t_P = packed_v_t_path[i + 1]; } } - while (!unpackStack.empty()) { - const SearchSpaceEdge viaPathEdge = unpackStack.top(); - unpackStack.pop(); - EdgeID edgeIDInViaPath = facade->FindEdgeInEitherDirection(viaPathEdge.first, viaPathEdge.second); - if(UINT_MAX == edgeIDInViaPath) + while (!unpack_stack.empty()) { + const SearchSpaceEdge via_path_edge = unpack_stack.top(); + unpack_stack.pop(); + EdgeID edge_in_via_path_id = facade->FindEdgeInEitherDirection(via_path_edge.first, via_path_edge.second); + if(SPECIAL_EDGEID == edge_in_via_path_id) { return false; - EdgeData currentEdgeData = facade->GetEdgeData(edgeIDInViaPath); - const bool IsViaEdgeShortCut = currentEdgeData.shortcut; + } + + const EdgeData & current_edge_data = facade->GetEdgeData(edge_in_via_path_id); + const bool IsViaEdgeShortCut = current_edge_data.shortcut; if (IsViaEdgeShortCut) { - const NodeID middleOfViaPath = currentEdgeData.id; - EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(viaPathEdge.first, middleOfViaPath); + const NodeID middleOfViaPath = current_edge_data.id; + EdgeID edgeIDOfFirstSegment = facade->FindEdgeInEitherDirection(via_path_edge.first, middleOfViaPath); int lengthOfFirstSegment = facade->GetEdgeData( edgeIDOfFirstSegment).distance; //Check if first segment is the one to go over treshold? if yes first segment to stack, else push second segment to stack and add distance of first one. - if (unpackedUntilDistance + lengthOfFirstSegment >= T_threshold) { - unpackStack.push( std::make_pair(viaPathEdge.first, middleOfViaPath)); + if (unpacked_until_distance + lengthOfFirstSegment >= T_threshold) { + unpack_stack.push( std::make_pair(via_path_edge.first, middleOfViaPath)); } else { - unpackedUntilDistance += lengthOfFirstSegment; - unpackStack.push( std::make_pair(middleOfViaPath, viaPathEdge.second)); + unpacked_until_distance += lengthOfFirstSegment; + unpack_stack.push( std::make_pair(middleOfViaPath, via_path_edge.second)); } } else { // edge is not a shortcut, set the start node for T-Test to end of edge. - unpackedUntilDistance += currentEdgeData.distance; - t_P = viaPathEdge.second; + unpacked_until_distance += current_edge_data.distance; + t_P = via_path_edge.second; } } - lengthOfPathT_TestPath += unpackedUntilDistance; + t_test_path_length += unpacked_until_distance; //Run actual T-Test query and compare if distances equal. engine_working_data.InitializeOrClearThirdThreadLocalStorage( super::facade->GetNumberOfNodes() ); - QueryHeap& forward_heap3 = *engine_working_data.forwardHeap3; - QueryHeap& backward_heap3 = *engine_working_data.backwardHeap3; - int _upperBound = INT_MAX; - NodeID middle = UINT_MAX; + QueryHeap & forward_heap3 = *engine_working_data.forwardHeap3; + QueryHeap & reverse_heap3 = *engine_working_data.backwardHeap3; + int upper_bound = INVALID_EDGE_WEIGHT; + NodeID middle = SPECIAL_NODEID; + forward_heap3.Insert(s_P, 0, s_P); - backward_heap3.Insert(t_P, 0, t_P); + reverse_heap3.Insert(t_P, 0, t_P); //exploration from s and t until deletemin/(1+epsilon) > _lengthOfShortestPath - while (forward_heap3.Size() + backward_heap3.Size() > 0) { - if (forward_heap3.Size() > 0) { - super::RoutingStep(forward_heap3, backward_heap3, &middle, &_upperBound, offset, true); + while( (forward_heap3.Size() + reverse_heap3.Size() ) > 0) { + if( !forward_heap3.Empty() ) { + super::RoutingStep( + forward_heap3, + reverse_heap3, + &middle, + &upper_bound, + true + ); } - if (backward_heap3.Size() > 0) { - super::RoutingStep(backward_heap3, forward_heap3, &middle, &_upperBound, offset, false); + if( !reverse_heap3.Empty() ) { + super::RoutingStep( + reverse_heap3, + forward_heap3, + &middle, + &upper_bound, + false + ); } } - return (_upperBound <= lengthOfPathT_TestPath); + return (upper_bound <= t_test_path_length); } }; -#endif /* ALTERNATIVEROUTES_H_ */ +#endif /* ALTERNATIVE_PATH_ROUTING_H */ diff --git a/RoutingAlgorithms/BasicRoutingInterface.h b/RoutingAlgorithms/BasicRoutingInterface.h index 00bb2e167..e26b504cb 100644 --- a/RoutingAlgorithms/BasicRoutingInterface.h +++ b/RoutingAlgorithms/BasicRoutingInterface.h @@ -30,14 +30,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../DataStructures/RawRouteData.h" #include "../DataStructures/SearchEngineData.h" +#include "../DataStructures/TurnInstructions.h" #include "../Util/ContainerUtils.h" #include "../Util/SimpleLogger.h" #include +#include #include -#include - #include SearchEngineData::SearchEngineHeapPtr SearchEngineData::forwardHeap; @@ -62,57 +62,58 @@ public: SearchEngineData::QueryHeap & reverse_heap, NodeID * middle_node_id, int * upper_bound, - const int edge_expansion_offset, const bool forward_direction - ) const { + ) const + { const NodeID node = forward_heap.DeleteMin(); const int distance = forward_heap.GetKey(node); - //SimpleLogger().Write() << "Settled (" << forward_heap.GetData( node ).parent << "," << node << ")=" << distance; - if(reverse_heap.WasInserted(node) ){ + if (reverse_heap.WasInserted(node)) + { const int new_distance = reverse_heap.GetKey(node) + distance; - if(new_distance < *upper_bound ){ - if( new_distance >= 0 ) { + if(new_distance < *upper_bound ) + { + if (new_distance >= 0) + { *middle_node_id = node; *upper_bound = new_distance; } } } - if( (distance-edge_expansion_offset) > *upper_bound ){ + if (distance > *upper_bound) + { forward_heap.DeleteAll(); return; } //Stalling - for( - EdgeID edge = facade->BeginEdges( node ); - edge < facade->EndEdges(node); - ++edge - ) { + for (EdgeID edge = facade->BeginEdges( node ); edge < facade->EndEdges(node); ++edge) + { const EdgeData & data = facade->GetEdgeData(edge); - const bool reverse_flag = (!forward_direction) ? data.forward : data.backward; - if( reverse_flag ) { + const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward); + if (reverse_flag) + { const NodeID to = facade->GetTarget(edge); const int edge_weight = data.distance; - BOOST_ASSERT_MSG( edge_weight > 0, "edge_weight invalid" ); + BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid"); - if(forward_heap.WasInserted( to )) { - if(forward_heap.GetKey( to ) + edge_weight < distance) { + if (forward_heap.WasInserted(to)) + { + if(forward_heap.GetKey( to ) + edge_weight < distance) + { return; } } } } - for( - EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); - edge < end_edge; - ++edge - ) { + for (EdgeID edge = facade->BeginEdges(node), end_edge = facade->EndEdges(node); edge < end_edge; ++edge) + { const EdgeData & data = facade->GetEdgeData(edge); - bool forward_directionFlag = (forward_direction ? data.forward : data.backward ); - if( forward_directionFlag ) { + bool forward_directionFlag = (forward_direction ? data.forward : data.backward); + if (forward_directionFlag) + { const NodeID to = facade->GetTarget(edge); const int edge_weight = data.distance; @@ -126,18 +127,19 @@ public: } //Found a shorter Path -> Update distance else if ( to_distance < forward_heap.GetKey( to ) ) { + //new parent forward_heap.GetData( to ).parent = node; forward_heap.DecreaseKey( to, to_distance ); - //new parent } } } } - inline void UnpackPath( - const std::vector & packed_path, - std::vector & unpacked_path - ) const { + inline void UnpackPath(const std::vector & packed_path, const PhantomNodes & phantom_node_pair, std::vector & unpacked_path) const + { + const bool start_traversed_in_reverse = (packed_path.front() != phantom_node_pair.source_phantom.forward_node_id); + const bool target_traversed_in_reverse = (packed_path.back() != phantom_node_pair.target_phantom.forward_node_id); + const unsigned packed_path_size = packed_path.size(); std::stack > recursion_stack; @@ -149,87 +151,170 @@ public: } std::pair edge; - while(!recursion_stack.empty()) { + while (!recursion_stack.empty()) + { edge = recursion_stack.top(); recursion_stack.pop(); + // facade->FindEdge does not suffice here in case of shortcuts. + // The above explanation unclear? Think! EdgeID smaller_edge_id = SPECIAL_EDGEID; int edge_weight = INT_MAX; - for( - EdgeID edge_id = facade->BeginEdges(edge.first); - edge_id < facade->EndEdges(edge.first); - ++edge_id - ){ + for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id) + { const int weight = facade->GetEdgeData(edge_id).distance; - if( - (facade->GetTarget(edge_id) == edge.second) && + if ((facade->GetTarget(edge_id) == edge.second) && (weight < edge_weight) && - facade->GetEdgeData(edge_id).forward - ){ + facade->GetEdgeData(edge_id).forward) + { smaller_edge_id = edge_id; edge_weight = weight; } } - - if( SPECIAL_EDGEID == smaller_edge_id ){ - for( - EdgeID edge_id = facade->BeginEdges(edge.second); - edge_id < facade->EndEdges(edge.second); - ++edge_id - ){ + if (SPECIAL_EDGEID == smaller_edge_id) + { + for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id) + { const int weight = facade->GetEdgeData(edge_id).distance; - if( - (facade->GetTarget(edge_id) == edge.first) && - (weight < edge_weight) && - facade->GetEdgeData(edge_id).backward - ){ + if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward) + { smaller_edge_id = edge_id; edge_weight = weight; } } } - BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge id invalid"); + BOOST_ASSERT_MSG(edge_weight != INVALID_EDGE_WEIGHT, "edge id invalid"); - const EdgeData& ed = facade->GetEdgeData(smaller_edge_id); - if( ed.shortcut ) {//unpack + const EdgeData & ed = facade->GetEdgeData(smaller_edge_id); + if (ed.shortcut) + {//unpack const NodeID middle_node_id = ed.id; //again, we need to this in reversed order recursion_stack.push(std::make_pair(middle_node_id, edge.second)); recursion_stack.push(std::make_pair(edge.first, middle_node_id)); - } else { - BOOST_ASSERT_MSG(!ed.shortcut, "edge must be a shortcut"); + } + else + { + BOOST_ASSERT_MSG(!ed.shortcut, "original edge flagged as shortcut"); + unsigned name_index = facade->GetNameIndexFromEdgeID(ed.id); + const TurnInstruction turn_instruction = facade->GetTurnInstructionForEdgeID(ed.id); + + if (!facade->EdgeIsCompressed(ed.id)) + { + BOOST_ASSERT( !facade->EdgeIsCompressed(ed.id) ); + unpacked_path.push_back( + PathData( + facade->GetGeometryIndexForEdgeID(ed.id), + name_index, + turn_instruction, + ed.distance + ) + ); + } + else + { + std::vector id_vector; + facade->GetUncompressedGeometry(facade->GetGeometryIndexForEdgeID(ed.id), id_vector); + + const int start_index = ( unpacked_path.empty() ? ( ( start_traversed_in_reverse ) ? id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position - 1 : phantom_node_pair.source_phantom.fwd_segment_position ) : 0 ); + const int end_index = id_vector.size(); + + BOOST_ASSERT(start_index >= 0); + BOOST_ASSERT(start_index <= end_index); + for (int i = start_index; i < end_index; ++i) + { + unpacked_path.push_back( + PathData( + id_vector[i], + name_index, + TurnInstructionsClass::NoTurn, + 0 + ) + ); + } + unpacked_path.back().turnInstruction = turn_instruction; + unpacked_path.back().durationOfSegment = ed.distance; + } + } + } + if (SPECIAL_EDGEID != phantom_node_pair.target_phantom.packed_geometry_id) + { + std::vector id_vector; + facade->GetUncompressedGeometry(phantom_node_pair.target_phantom.packed_geometry_id, id_vector); + if (target_traversed_in_reverse) + { + std::reverse(id_vector.begin(), id_vector.end() ); + } + const bool is_local_path = (phantom_node_pair.source_phantom.packed_geometry_id == phantom_node_pair.target_phantom.packed_geometry_id) && unpacked_path.empty(); + + int start_index = 0; + int end_index = phantom_node_pair.target_phantom.fwd_segment_position; + if (target_traversed_in_reverse) + { + end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position; + } + if (is_local_path) + { + start_index = phantom_node_pair.source_phantom.fwd_segment_position; + end_index = phantom_node_pair.target_phantom.fwd_segment_position; + if (target_traversed_in_reverse) + { + start_index = id_vector.size() - phantom_node_pair.source_phantom.fwd_segment_position; + end_index = id_vector.size() - phantom_node_pair.target_phantom.fwd_segment_position; + } + } + + BOOST_ASSERT(start_index >= 0); + for (int i = start_index; i != end_index; (start_index < end_index ? ++i :--i)) + { + BOOST_ASSERT( i >= -1 ); unpacked_path.push_back( PathData( - ed.id, - facade->GetNameIndexFromEdgeID(ed.id), - facade->GetTurnInstructionForEdgeID(ed.id), - ed.distance + id_vector[i], + phantom_node_pair.target_phantom.name_id, + TurnInstructionsClass::NoTurn, + 0 ) ); } } + + // there is no equivalent to a node-based node in an edge-expanded graph. + // two equivalent routes may start (or end) at different node-based edges + // as they are added with the offset how much "distance" on the edge + // has already been traversed. Depending on offset one needs to remove + // the last node. + if (unpacked_path.size() > 1) + { + const unsigned last_index = unpacked_path.size()-1; + const unsigned second_to_last_index = last_index -1; + + //looks like a trivially true check but tests for underflow + BOOST_ASSERT(last_index > second_to_last_index); + + if (unpacked_path[last_index].node == unpacked_path[second_to_last_index].node) + { + unpacked_path.pop_back(); + } + BOOST_ASSERT(!unpacked_path.empty()); + } } - inline void UnpackEdge( - const NodeID s, - const NodeID t, - std::vector & unpacked_path - ) const { + inline void UnpackEdge(const NodeID s, const NodeID t, std::vector & unpacked_path) const + { std::stack > recursion_stack; recursion_stack.push(std::make_pair(s,t)); std::pair edge; - while(!recursion_stack.empty()) { + while (!recursion_stack.empty()) + { edge = recursion_stack.top(); recursion_stack.pop(); EdgeID smaller_edge_id = SPECIAL_EDGEID; int edge_weight = INT_MAX; - for( - EdgeID edge_id = facade->BeginEdges(edge.first); - edge_id < facade->EndEdges(edge.first); - ++edge_id - ){ + for (EdgeID edge_id = facade->BeginEdges(edge.first); edge_id < facade->EndEdges(edge.first); ++edge_id) + { const int weight = facade->GetEdgeData(edge_id).distance; if( (facade->GetTarget(edge_id) == edge.second) && @@ -241,18 +326,13 @@ public: } } - if( SPECIAL_EDGEID == smaller_edge_id ){ - for( - EdgeID edge_id = facade->BeginEdges(edge.second); - edge_id < facade->EndEdges(edge.second); - ++edge_id - ){ + if (SPECIAL_EDGEID == smaller_edge_id) + { + for (EdgeID edge_id = facade->BeginEdges(edge.second); edge_id < facade->EndEdges(edge.second); ++edge_id) + { const int weight = facade->GetEdgeData(edge_id).distance; - if( - (facade->GetTarget(edge_id) == edge.first) && - (weight < edge_weight) && - facade->GetEdgeData(edge_id).backward - ){ + if ((facade->GetTarget(edge_id) == edge.first) && (weight < edge_weight) && facade->GetEdgeData(edge_id).backward) + { smaller_edge_id = edge_id; edge_weight = weight; } @@ -261,16 +341,15 @@ public: BOOST_ASSERT_MSG(edge_weight != INT_MAX, "edge weight invalid"); const EdgeData& ed = facade->GetEdgeData(smaller_edge_id); - if(ed.shortcut) {//unpack + if (ed.shortcut) + {//unpack const NodeID middle_node_id = ed.id; //again, we need to this in reversed order - recursion_stack.push( - std::make_pair(middle_node_id, edge.second) - ); - recursion_stack.push( - std::make_pair(edge.first, middle_node_id) - ); - } else { + recursion_stack.push(std::make_pair(middle_node_id, edge.second)); + recursion_stack.push(std::make_pair(edge.first, middle_node_id)); + } + else + { BOOST_ASSERT_MSG(!ed.shortcut, "edge must be shortcut"); unpacked_path.push_back(edge.first ); } @@ -279,43 +358,41 @@ public: } inline void RetrievePackedPathFromHeap( - SearchEngineData::QueryHeap & forward_heap, - SearchEngineData::QueryHeap & reverse_heap, + const SearchEngineData::QueryHeap & forward_heap, + const SearchEngineData::QueryHeap & reverse_heap, const NodeID middle_node_id, std::vector & packed_path - ) const { + ) const + { NodeID current_node_id = middle_node_id; - while(current_node_id != forward_heap.GetData(current_node_id).parent) { + while(current_node_id != forward_heap.GetData(current_node_id).parent) + { current_node_id = forward_heap.GetData(current_node_id).parent; packed_path.push_back(current_node_id); } - std::reverse(packed_path.begin(), packed_path.end()); packed_path.push_back(middle_node_id); current_node_id = middle_node_id; - while (current_node_id != reverse_heap.GetData(current_node_id).parent){ + while (current_node_id != reverse_heap.GetData(current_node_id).parent) + { current_node_id = reverse_heap.GetData(current_node_id).parent; packed_path.push_back(current_node_id); } } -//TODO: reorder parameters inline void RetrievePackedPathFromSingleHeap( - SearchEngineData::QueryHeap & search_heap, + const SearchEngineData::QueryHeap & search_heap, const NodeID middle_node_id, std::vector& packed_path - ) const { + ) const + { NodeID current_node_id = middle_node_id; - while(current_node_id != search_heap.GetData(current_node_id).parent) { + while(current_node_id != search_heap.GetData(current_node_id).parent) + { current_node_id = search_heap.GetData(current_node_id).parent; packed_path.push_back(current_node_id); } } - - int ComputeEdgeOffset(const PhantomNode & phantom) const { - return phantom.weight1 + (phantom.isBidirected() ? phantom.weight2 : 0); - } - }; #endif /* BASICROUTINGINTERFACE_H_ */ diff --git a/RoutingAlgorithms/ShortestPathRouting.h b/RoutingAlgorithms/ShortestPathRouting.h index 982b7b13d..45dffc411 100644 --- a/RoutingAlgorithms/ShortestPathRouting.h +++ b/RoutingAlgorithms/ShortestPathRouting.h @@ -48,21 +48,22 @@ public: ) : super(facade), engine_working_data(engine_working_data) - {} + { } - ~ShortestPathRouting() {} + ~ShortestPathRouting() { } void operator()( const std::vector & phantom_nodes_vector, RawRouteData & raw_route_data - ) const { + ) const + { BOOST_FOREACH( const PhantomNodes & phantom_node_pair, phantom_nodes_vector ){ - if(!phantom_node_pair.AtLeastOnePhantomNodeIsUINTMAX()) { - raw_route_data.lengthOfShortestPath = INT_MAX; - raw_route_data.lengthOfAlternativePath = INT_MAX; + if( phantom_node_pair.AtLeastOnePhantomNodeIsInvalid() ) { + // raw_route_data.lengthOfShortestPath = INT_MAX; + // raw_route_data.lengthOfAlternativePath = INT_MAX; return; } } @@ -104,71 +105,84 @@ public: middle2 = UINT_MAX; //insert new starting nodes into forward heap, adjusted by previous distances. - if(search_from_1st_node) { + if( + search_from_1st_node && + phantom_node_pair.source_phantom.forward_node_id != SPECIAL_NODEID + ) { + // SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.forward_node_id << ", w: " << -phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(); forward_heap1.Insert( - phantom_node_pair.startPhantom.edgeBasedNode, - distance1-phantom_node_pair.startPhantom.weight1, - phantom_node_pair.startPhantom.edgeBasedNode + phantom_node_pair.source_phantom.forward_node_id, + distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.forward_node_id ); forward_heap2.Insert( - phantom_node_pair.startPhantom.edgeBasedNode, - distance1-phantom_node_pair.startPhantom.weight1, - phantom_node_pair.startPhantom.edgeBasedNode + phantom_node_pair.source_phantom.forward_node_id, + distance1-phantom_node_pair.source_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.source_phantom.forward_node_id ); } - if(phantom_node_pair.startPhantom.isBidirected() && search_from_2nd_node) { + if( + search_from_2nd_node && + phantom_node_pair.source_phantom.reverse_node_id != SPECIAL_NODEID + ) { + // SimpleLogger().Write(logDEBUG) << "fwd1 insert: " << phantom_node_pair.source_phantom.reverse_node_id << ", w: " << -phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(); forward_heap1.Insert( - phantom_node_pair.startPhantom.edgeBasedNode+1, - distance2-phantom_node_pair.startPhantom.weight2, - phantom_node_pair.startPhantom.edgeBasedNode+1 + phantom_node_pair.source_phantom.reverse_node_id, + distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.source_phantom.reverse_node_id ); forward_heap2.Insert( - phantom_node_pair.startPhantom.edgeBasedNode+1, - distance2-phantom_node_pair.startPhantom.weight2, - phantom_node_pair.startPhantom.edgeBasedNode+1 + phantom_node_pair.source_phantom.reverse_node_id, + distance2-phantom_node_pair.source_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.source_phantom.reverse_node_id ); } //insert new backward nodes into backward heap, unadjusted. - reverse_heap1.Insert( - phantom_node_pair.targetPhantom.edgeBasedNode, - phantom_node_pair.targetPhantom.weight1, - phantom_node_pair.targetPhantom.edgeBasedNode - ); - if(phantom_node_pair.targetPhantom.isBidirected() ) { - reverse_heap2.Insert( - phantom_node_pair.targetPhantom.edgeBasedNode+1, - phantom_node_pair.targetPhantom.weight2, - phantom_node_pair.targetPhantom.edgeBasedNode+1 + if( phantom_node_pair.target_phantom.forward_node_id != SPECIAL_NODEID ) { + // SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.forward_node_id << ", w: " << phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(); + reverse_heap1.Insert( + phantom_node_pair.target_phantom.forward_node_id, + phantom_node_pair.target_phantom.GetForwardWeightPlusOffset(), + phantom_node_pair.target_phantom.forward_node_id ); } - const int forward_offset = super::ComputeEdgeOffset( - phantom_node_pair.startPhantom - ); - const int reverse_offset = super::ComputeEdgeOffset( - phantom_node_pair.targetPhantom - ); + if( phantom_node_pair.target_phantom.reverse_node_id != SPECIAL_NODEID ) { + // SimpleLogger().Write(logDEBUG) << "rev insert: " << phantom_node_pair.target_phantom.reverse_node_id << ", w: " << phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(); + reverse_heap2.Insert( + phantom_node_pair.target_phantom.reverse_node_id, + phantom_node_pair.target_phantom.GetReverseWeightPlusOffset(), + phantom_node_pair.target_phantom.reverse_node_id + ); + } + + // const int forward_offset = phantom_node_pair.ComputeForwardQueueOffset(); + // const int forward_offset = super::ComputeForwardOffset( + // phantom_node_pair.source_phantom + // ); + // const int reverse_offset = -phantom_node_pair.ComputeReverseQueueOffset(); + // const int reverse_offset = super::ComputeReverseOffset( + // phantom_node_pair.target_phantom + // ); //run two-Target Dijkstra routing step. while(0 < (forward_heap1.Size() + reverse_heap1.Size() )){ - if( !forward_heap1.Empty()){ + if( 0 < forward_heap1.Size() ){ super::RoutingStep( forward_heap1, reverse_heap1, &middle1, &local_upper_bound1, - forward_offset, true ); } - if( !reverse_heap1.Empty() ){ + if( 0 < reverse_heap1.Size() ){ super::RoutingStep( reverse_heap1, forward_heap1, &middle1, &local_upper_bound1, - reverse_offset, false ); } @@ -176,23 +190,21 @@ public: if( !reverse_heap2.Empty() ) { while(0 < (forward_heap2.Size() + reverse_heap2.Size() )){ - if( !forward_heap2.Empty() ){ + if( 0 < forward_heap2.Size() ){ super::RoutingStep( forward_heap2, reverse_heap2, &middle2, &local_upper_bound2, - forward_offset, true ); } - if( !reverse_heap2.Empty() ){ + if( 0 < reverse_heap2.Size() ){ super::RoutingStep( reverse_heap2, forward_heap2, &middle2, &local_upper_bound2, - reverse_offset, false ); } @@ -201,17 +213,17 @@ public: //No path found for both target nodes? if( - (INT_MAX == local_upper_bound1) && - (INT_MAX == local_upper_bound2) + (INVALID_EDGE_WEIGHT == local_upper_bound1) && + (INVALID_EDGE_WEIGHT == local_upper_bound2) ) { - raw_route_data.lengthOfShortestPath = INT_MAX; - raw_route_data.lengthOfAlternativePath = INT_MAX; + raw_route_data.lengthOfShortestPath = INVALID_EDGE_WEIGHT; + raw_route_data.lengthOfAlternativePath = INVALID_EDGE_WEIGHT; return; } - if(UINT_MAX == middle1) { + if( SPECIAL_NODEID == middle1 ) { search_from_1st_node = false; } - if(UINT_MAX == middle2) { + if( SPECIAL_NODEID == middle2 ) { search_from_2nd_node = false; } @@ -228,7 +240,7 @@ public: BOOST_ASSERT( (unsigned)current_leg < packed_legs1.size() ); BOOST_ASSERT( (unsigned)current_leg < packed_legs2.size() ); - if(INT_MAX != local_upper_bound1) { + if( INVALID_EDGE_WEIGHT != local_upper_bound1 ) { super::RetrievePackedPathFromHeap( forward_heap1, reverse_heap1, @@ -237,7 +249,7 @@ public: ); } - if(INT_MAX != local_upper_bound2) { + if( INVALID_EDGE_WEIGHT != local_upper_bound2 ) { super::RetrievePackedPathFromHeap( forward_heap2, reverse_heap2, @@ -264,8 +276,6 @@ public: local_upper_bound2 = local_upper_bound1; } - // SimpleLogger().Write() << "fetched packed paths"; - BOOST_ASSERT_MSG( !temporary_packed_leg1.empty() || !temporary_packed_leg2.empty(), @@ -335,11 +345,11 @@ public: if( (packed_legs1[current_leg].back() == packed_legs2[current_leg].back()) && - phantom_node_pair.targetPhantom.isBidirected() + phantom_node_pair.target_phantom.isBidirected() ) { const NodeID last_node_id = packed_legs2[current_leg].back(); - search_from_1st_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode+1); - search_from_2nd_node &= !(last_node_id == phantom_node_pair.targetPhantom.edgeBasedNode); + search_from_1st_node &= !(last_node_id == phantom_node_pair.target_phantom.reverse_node_id); + search_from_2nd_node &= !(last_node_id == phantom_node_pair.target_phantom.forward_node_id); BOOST_ASSERT( search_from_1st_node != search_from_2nd_node ); } @@ -348,14 +358,42 @@ public: ++current_leg; } - if( distance1 > distance2 ) { + if (distance1 > distance2) + { std::swap( packed_legs1, packed_legs2 ); } raw_route_data.unpacked_path_segments.resize( packed_legs1.size() ); - for(unsigned i = 0; i < packed_legs1.size(); ++i){ - BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size() ); + // const int start_offset = ( packed_legs1[0].front() == phantom_nodes_vector.front().source_phantom.forward_node_id ? 1 : -1 )*phantom_nodes_vector.front().source_phantom.fwd_segment_position; + + raw_route_data.source_traversed_in_reverse = (packed_legs1.front().front() != phantom_nodes_vector.front().source_phantom.forward_node_id); + raw_route_data.target_traversed_in_reverse = (packed_legs1.back().back() != phantom_nodes_vector.back().target_phantom.forward_node_id); + + for (unsigned i = 0; i < packed_legs1.size(); ++i) + { + BOOST_ASSERT(!phantom_nodes_vector.empty()); + // const bool at_beginning = (packed_legs1[i] == packed_legs1.front()); + // const bool at_end = (packed_legs1[i] == packed_legs1.back()); + BOOST_ASSERT(packed_legs1.size() == raw_route_data.unpacked_path_segments.size()); + + PhantomNodes unpack_phantom_node_pair = phantom_nodes_vector[i]; + // if (!at_beginning) + // { + // unpack_phantom_node_pair.source_phantom.packed_geometry_id = SPECIAL_EDGEID; + // unpack_phantom_node_pair.source_phantom.fwd_segment_position = 0; + // } + + // if (!at_end) + // { + // unpack_phantom_node_pair.target_phantom.packed_geometry_id = SPECIAL_EDGEID; + // unpack_phantom_node_pair.target_phantom.fwd_segment_position = 0; + // } + super::UnpackPath( + // -- packed input packed_legs1[i], + // -- start and end of (sub-)route + unpack_phantom_node_pair, + // -- unpacked output raw_route_data.unpacked_path_segments[i] ); } diff --git a/Server/DataStructures/BaseDataFacade.h b/Server/DataStructures/BaseDataFacade.h index 6c4726a9c..7b7a73762 100644 --- a/Server/DataStructures/BaseDataFacade.h +++ b/Server/DataStructures/BaseDataFacade.h @@ -86,6 +86,15 @@ public: const unsigned id ) const = 0; + virtual bool EdgeIsCompressed( const unsigned id ) const = 0; + + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0; + + virtual void GetUncompressedGeometry( + const unsigned id, + std::vector & result_nodes + ) const = 0; + virtual TurnInstruction GetTurnInstructionForEdgeID( const unsigned id ) const = 0; diff --git a/Server/DataStructures/InternalDataFacade.h b/Server/DataStructures/InternalDataFacade.h index b8a552cf3..e82ae356d 100644 --- a/Server/DataStructures/InternalDataFacade.h +++ b/Server/DataStructures/InternalDataFacade.h @@ -45,6 +45,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include +#include + template class InternalDataFacade : public BaseDataFacade { @@ -61,14 +64,23 @@ private: QueryGraph * m_query_graph; std::string m_timestamp; - ShM::vector m_coordinate_list; + boost::shared_ptr::vector> m_coordinate_list; ShM::vector m_via_node_list; ShM::vector m_name_ID_list; ShM::vector m_turn_instruction_list; ShM::vector m_names_char_list; ShM::vector m_name_begin_indices; + ShM::vector m_egde_is_compressed; + ShM::vector m_geometry_indices; + ShM::vector m_geometry_list; - StaticRTree * m_static_rtree; + boost::shared_ptr< + StaticRTree< + RTreeLeaf, + ShM::vector, + false + > + > m_static_rtree; void LoadTimestamp(const boost::filesystem::path & timestamp_path) { @@ -103,7 +115,7 @@ private: ); BOOST_ASSERT_MSG(0 != node_list.size(), "node list empty"); - BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty"); + // BOOST_ASSERT_MSG(0 != edge_list.size(), "edge list empty"); SimpleLogger().Write() << "loaded " << node_list.size() << " nodes and " << edge_list.size() << " edges"; m_query_graph = new QueryGraph(node_list, edge_list); @@ -113,42 +125,44 @@ private: } void LoadNodeAndEdgeInformation( - const boost::filesystem::path nodes_file, - const boost::filesystem::path edges_file + const boost::filesystem::path & nodes_file, + const boost::filesystem::path & edges_file ) { boost::filesystem::ifstream nodes_input_stream( nodes_file, std::ios::binary ); - SimpleLogger().Write(logDEBUG) << "Loading node data"; NodeInfo current_node; unsigned number_of_coordinates = 0; nodes_input_stream.read( (char *)&number_of_coordinates, sizeof(unsigned) ); - m_coordinate_list.resize(number_of_coordinates); + m_coordinate_list = boost::make_shared >(number_of_coordinates); for(unsigned i = 0; i < number_of_coordinates; ++i) { nodes_input_stream.read((char *)¤t_node, sizeof(NodeInfo)); - m_coordinate_list[i] = FixedPointCoordinate( + m_coordinate_list->at(i) = FixedPointCoordinate( current_node.lat, current_node.lon ); + BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lat) >> 30) == 0 ); + BOOST_ASSERT( ( std::abs(m_coordinate_list->at(i).lon) >> 30) == 0 ); } - std::vector(m_coordinate_list).swap(m_coordinate_list); nodes_input_stream.close(); - SimpleLogger().Write(logDEBUG) << "Loading edge data"; boost::filesystem::ifstream edges_input_stream( edges_file, std::ios::binary ); unsigned number_of_edges = 0; edges_input_stream.read((char*)&number_of_edges, sizeof(unsigned)); - m_via_node_list.resize(number_of_edges); - m_name_ID_list.resize(number_of_edges); + m_via_node_list.resize (number_of_edges); + m_name_ID_list.resize (number_of_edges); m_turn_instruction_list.resize(number_of_edges); + m_egde_is_compressed.resize (number_of_edges); + + unsigned compressed = 0; OriginalEdgeData current_edge_data; for(unsigned i = 0; i < number_of_edges; ++i) { @@ -159,17 +173,63 @@ private: m_via_node_list[i] = current_edge_data.via_node; m_name_ID_list[i] = current_edge_data.name_id; m_turn_instruction_list[i] = current_edge_data.turn_instruction; + m_egde_is_compressed[i] = current_edge_data.compressed_geometry; + if(m_egde_is_compressed[i]) { + ++compressed; + } } + edges_input_stream.close(); } + void LoadGeometries(const boost::filesystem::path & geometry_file) + { + std::ifstream geometry_stream( + geometry_file.c_str(), + std::ios::binary + ); + unsigned number_of_indices = 0; + unsigned number_of_compressed_geometries = 0; + + geometry_stream.read( + (char *)&number_of_indices, + sizeof(unsigned) + ); + + m_geometry_indices.resize(number_of_indices); + geometry_stream.read( + (char *)&(m_geometry_indices[0]), + number_of_indices*sizeof(unsigned) + ); + + geometry_stream.read( + (char *)&number_of_compressed_geometries, + sizeof(unsigned) + ); + + BOOST_ASSERT( m_geometry_indices.back() == number_of_compressed_geometries ); + m_geometry_list.resize( number_of_compressed_geometries ); + + geometry_stream.read( + (char *)&(m_geometry_list[0]), + number_of_compressed_geometries*sizeof(unsigned) + ); + geometry_stream.close(); + } + void LoadRTree( const boost::filesystem::path & ram_index_path, const boost::filesystem::path & file_index_path ) { - m_static_rtree = new StaticRTree( + BOOST_ASSERT_MSG( + !m_coordinate_list->empty(), + "coordinates must be loaded before r-tree" + ); + + m_static_rtree = boost::make_shared >( ram_index_path, - file_index_path + file_index_path, + m_coordinate_list ); } @@ -204,7 +264,7 @@ private: public: ~InternalDataFacade() { delete m_query_graph; - delete m_static_rtree; + m_static_rtree.reset(); } explicit InternalDataFacade( const ServerPaths & server_paths ) { @@ -218,6 +278,9 @@ public: if( server_paths.find("fileindex") == server_paths.end() ) { throw OSRMException("no leaf index file given in ini file"); } + if( server_paths.find("geometries") == server_paths.end() ) { + throw OSRMException("no geometries file given in ini file"); + } if( server_paths.find("nodesdata") == server_paths.end() ) { throw OSRMException("no nodes file given in ini file"); } @@ -249,12 +312,17 @@ public: paths_iterator = server_paths.find("namesdata"); BOOST_ASSERT(server_paths.end() != paths_iterator); const boost::filesystem::path & names_data_path = paths_iterator->second; + paths_iterator = server_paths.find("geometries"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + const boost::filesystem::path & geometries_path = paths_iterator->second; //load data SimpleLogger().Write() << "loading graph data"; LoadGraph(hsgr_path); SimpleLogger().Write() << "loading egde information"; LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path); + SimpleLogger().Write() << "loading geometries"; + LoadGeometries( geometries_path ); SimpleLogger().Write() << "loading r-tree"; LoadRTree(ram_index_path, file_index_path); SimpleLogger().Write() << "loading timestamp"; @@ -319,10 +387,13 @@ public: FixedPointCoordinate GetCoordinateOfNode( const unsigned id ) const { - const NodeID node = m_via_node_list.at(id); - return m_coordinate_list.at(node); + return m_coordinate_list->at(id); }; + bool EdgeIsCompressed( const unsigned id ) const { + return m_egde_is_compressed.at(id); + } + TurnInstruction GetTurnInstructionForEdgeID( const unsigned id ) const { @@ -346,11 +417,12 @@ public: PhantomNode & resulting_phantom_node, const unsigned zoom_level ) const { - return m_static_rtree->FindPhantomNodeForCoordinate( - input_coordinate, - resulting_phantom_node, - zoom_level - ); + const bool found = m_static_rtree->FindPhantomNodeForCoordinate( + input_coordinate, + resulting_phantom_node, + zoom_level + ); + return found; } unsigned GetCheckSum() const { return m_check_sum; } @@ -368,8 +440,8 @@ public: name_id < m_name_begin_indices.size(), "name id too high" ); - unsigned begin_index = m_name_begin_indices[name_id]; - unsigned end_index = m_name_begin_indices[name_id+1]; + const unsigned begin_index = m_name_begin_indices[name_id]; + const unsigned end_index = m_name_begin_indices[name_id+1]; BOOST_ASSERT_MSG( begin_index < m_names_char_list.size(), "begin index of name too high" @@ -389,6 +461,22 @@ public: ); } + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const { + return m_via_node_list.at(id); + } + + virtual void GetUncompressedGeometry( + const unsigned id, std::vector & result_nodes + ) const { + const unsigned begin = m_geometry_indices.at(id); + const unsigned end = m_geometry_indices.at(id+1); + + result_nodes.clear(); + result_nodes.insert(result_nodes.begin(), + m_geometry_list.begin() + begin, + m_geometry_list.begin() + end); + } + std::string GetTimestamp() const { return m_timestamp; } diff --git a/Server/DataStructures/SharedDataFacade.h b/Server/DataStructures/SharedDataFacade.h index 0778eb06d..21f2cb99a 100644 --- a/Server/DataStructures/SharedDataFacade.h +++ b/Server/DataStructures/SharedDataFacade.h @@ -30,9 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //implements all data storage when shared memory _IS_ used -#include -#include - #include "BaseDataFacade.h" #include "SharedDataType.h" @@ -42,6 +39,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../../Util/ProgramOptions.h" #include "../../Util/SimpleLogger.h" +#include +#include + #include template @@ -55,7 +55,7 @@ private: typedef typename StaticGraph::_StrEdge GraphEdge; typedef typename QueryGraph::InputEdge InputEdge; typedef typename super::RTreeLeaf RTreeLeaf; - typedef typename StaticRTree::TreeNode RTreeNode; + typedef typename StaticRTree::vector, true>::TreeNode RTreeNode; SharedDataLayout * data_layout; char * shared_memory; @@ -72,15 +72,25 @@ private: boost::shared_ptr m_large_memory; std::string m_timestamp; - ShM::vector m_coordinate_list; + boost::shared_ptr< + ShM::vector + > m_coordinate_list; ShM::vector m_via_node_list; ShM::vector m_name_ID_list; ShM::vector m_turn_instruction_list; ShM::vector m_names_char_list; ShM::vector m_name_begin_indices; - boost::shared_ptr > m_static_rtree; + ShM::vector m_egde_is_compressed; + ShM::vector m_geometry_indices; + ShM::vector m_geometry_list; - // SharedDataFacade() { } + boost::shared_ptr< + StaticRTree< + RTreeLeaf, + ShM::vector, + true + > + > m_static_rtree; void LoadTimestamp() { char * timestamp_ptr = shared_memory + data_layout->GetTimeStampOffset(); @@ -95,13 +105,19 @@ private: void LoadRTree( const boost::filesystem::path & file_index_path ) { + BOOST_ASSERT_MSG( + !m_coordinate_list->empty(), + "coordinates must be loaded before r-tree" + ); + RTreeNode * tree_ptr = (RTreeNode *)( shared_memory + data_layout->GetRSearchTreeOffset() ); - m_static_rtree = boost::make_shared >( + m_static_rtree = boost::make_shared::vector, true> >( tree_ptr, data_layout->r_search_tree_size, - file_index_path + file_index_path, + m_coordinate_list ); } @@ -112,7 +128,7 @@ private: ); GraphEdge * graph_edges_ptr = (GraphEdge *)( - shared_memory + data_layout->GetGraphEdgeListOffsett() + shared_memory + data_layout->GetGraphEdgeListOffset() ); typename ShM::vector node_list( @@ -126,7 +142,6 @@ private: m_query_graph.reset( new QueryGraph(node_list, edge_list) ); - } void LoadNodeAndEdgeInformation() { @@ -134,11 +149,10 @@ private: FixedPointCoordinate * coordinate_list_ptr = (FixedPointCoordinate *)( shared_memory + data_layout->GetCoordinateListOffset() ); - typename ShM::vector coordinate_list( + m_coordinate_list = boost::make_shared::vector> ( coordinate_list_ptr, data_layout->coordinate_list_size ); - m_coordinate_list.swap( coordinate_list ); TurnInstruction * turn_instruction_list_ptr = (TurnInstruction *)( shared_memory + data_layout->GetTurnInstructionListOffset() @@ -190,6 +204,36 @@ private: m_names_char_list.swap(names_char_list); } + void LoadGeometries() + { + unsigned * geometries_compressed_ptr = (unsigned *)( + shared_memory + data_layout->GetGeometriesIndicatorOffset() + ); + typename ShM::vector egde_is_compressed( + geometries_compressed_ptr, + data_layout->geometries_indicators + ); + m_egde_is_compressed.swap(egde_is_compressed); + + unsigned * geometries_index_ptr = (unsigned *)( + shared_memory + data_layout->GetGeometriesIndexListOffset() + ); + typename ShM::vector geometry_begin_indices( + geometries_index_ptr, + data_layout->geometries_index_list_size + ); + m_geometry_indices.swap(geometry_begin_indices); + + unsigned * geometries_list_ptr = (unsigned *)( + shared_memory + data_layout->GetGeometryListOffset() + ); + typename ShM::vector geometry_list( + geometries_list_ptr, + data_layout->geometries_list_size + ); + m_geometry_list.swap(geometry_list); + } + public: SharedDataFacade( ) { data_timestamp_ptr = (SharedDataTimestamp *)SharedMemoryFactory::Get( @@ -241,6 +285,7 @@ public: LoadGraph(); LoadNodeAndEdgeInformation(); + LoadGeometries(); LoadRTree(ram_index_path); LoadTimestamp(); LoadViaNodeList(); @@ -250,7 +295,6 @@ public: } } - //search graph access unsigned GetNumberOfNodes() const { return m_query_graph->GetNumberOfNodes(); @@ -307,10 +351,29 @@ public: FixedPointCoordinate GetCoordinateOfNode( const unsigned id ) const { - const NodeID node = m_via_node_list.at(id); - return m_coordinate_list.at(node); + return m_coordinate_list->at(id); }; + virtual bool EdgeIsCompressed( const unsigned id ) const { + return m_egde_is_compressed.at(id); + } + + virtual void GetUncompressedGeometry( + const unsigned id, std::vector & result_nodes + ) const { + const unsigned begin = m_geometry_indices.at(id); + const unsigned end = m_geometry_indices.at(id+1); + + result_nodes.clear(); + result_nodes.insert(result_nodes.begin(), + m_geometry_list.begin() + begin, + m_geometry_list.begin() + end); + } + + virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const { + return m_via_node_list.at(id); + } + TurnInstruction GetTurnInstructionForEdgeID( const unsigned id ) const { @@ -334,11 +397,12 @@ public: PhantomNode & resulting_phantom_node, const unsigned zoom_level ) const { - return m_static_rtree->FindPhantomNodeForCoordinate( - input_coordinate, - resulting_phantom_node, - zoom_level - ); + const bool found = m_static_rtree->FindPhantomNodeForCoordinate( + input_coordinate, + resulting_phantom_node, + zoom_level + ); + return found; } unsigned GetCheckSum() const { return m_check_sum; } diff --git a/Server/DataStructures/SharedDataType.h b/Server/DataStructures/SharedDataType.h index 902eea986..5efb19f3b 100644 --- a/Server/DataStructures/SharedDataType.h +++ b/Server/DataStructures/SharedDataType.h @@ -43,7 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include typedef BaseDataFacade::RTreeLeaf RTreeLeaf; -typedef StaticRTree::TreeNode RTreeNode; +typedef StaticRTree::vector, true>::TreeNode RTreeNode; typedef StaticGraph QueryGraph; struct SharedDataLayout { @@ -56,6 +56,9 @@ struct SharedDataLayout { uint64_t coordinate_list_size; uint64_t turn_instruction_list_size; uint64_t r_search_tree_size; + uint64_t geometries_index_list_size; + uint64_t geometries_list_size; + uint64_t geometries_indicators; unsigned checksum; unsigned timestamp_length; @@ -72,8 +75,12 @@ struct SharedDataLayout { coordinate_list_size(0), turn_instruction_list_size(0), r_search_tree_size(0), + geometries_index_list_size(0), + geometries_list_size(0), + geometries_indicators(0), checksum(0), timestamp_length(0) + { ram_index_file_name[0] = '\0'; } @@ -90,23 +97,29 @@ struct SharedDataLayout { SimpleLogger().Write(logDEBUG) << "coordinate_list_size: " << coordinate_list_size; SimpleLogger().Write(logDEBUG) << "turn_instruction_list_size: " << turn_instruction_list_size; SimpleLogger().Write(logDEBUG) << "r_search_tree_size: " << r_search_tree_size; + SimpleLogger().Write(logDEBUG) << "geometries_indicators: " << geometries_indicators << "/" << ((geometries_indicators/8) + 1); + SimpleLogger().Write(logDEBUG) << "geometries_index_list_size: " << geometries_index_list_size; + SimpleLogger().Write(logDEBUG) << "geometries_list_size: " << geometries_list_size; SimpleLogger().Write(logDEBUG) << "sizeof(checksum): " << sizeof(checksum); SimpleLogger().Write(logDEBUG) << "ram index file name: " << ram_index_file_name; } uint64_t GetSizeOfLayout() const { uint64_t result = - (name_index_list_size * sizeof(unsigned) ) + - (name_char_list_size * sizeof(char) ) + - (name_id_list_size * sizeof(unsigned) ) + - (via_node_list_size * sizeof(NodeID) ) + - (graph_node_list_size * sizeof(QueryGraph::_StrNode)) + - (graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) + - (timestamp_length * sizeof(char) ) + - (coordinate_list_size * sizeof(FixedPointCoordinate)) + - (turn_instruction_list_size * sizeof(TurnInstructions) ) + - (r_search_tree_size * sizeof(RTreeNode) ) + - sizeof(checksum) + + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + + (name_id_list_size * sizeof(unsigned) ) + + (via_node_list_size * sizeof(NodeID) ) + + (graph_node_list_size * sizeof(QueryGraph::_StrNode) ) + + (graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) + + (timestamp_length * sizeof(char) ) + + (coordinate_list_size * sizeof(FixedPointCoordinate) ) + + (turn_instruction_list_size * sizeof(TurnInstructionsClass)) + + (r_search_tree_size * sizeof(RTreeNode) ) + + (geometries_indicators/32 + 1) * sizeof(unsigned) + + (geometries_index_list_size * sizeof(unsigned) ) + + (geometries_list_size * sizeof(unsigned) ) + + sizeof(checksum) + 1024*sizeof(char); return result; } @@ -140,10 +153,10 @@ struct SharedDataLayout { (via_node_list_size * sizeof(NodeID) ); return result; } - uint64_t GetGraphEdgeListOffsett() const { + uint64_t GetGraphEdgeListOffset() const { uint64_t result = - (name_index_list_size * sizeof(unsigned) ) + - (name_char_list_size * sizeof(char) ) + + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + (name_id_list_size * sizeof(unsigned) ) + (via_node_list_size * sizeof(NodeID) ) + (graph_node_list_size * sizeof(QueryGraph::_StrNode)) ; @@ -184,29 +197,79 @@ struct SharedDataLayout { } uint64_t GetRSearchTreeOffset() const { uint64_t result = - (name_index_list_size * sizeof(unsigned) ) + - (name_char_list_size * sizeof(char) ) + - (name_id_list_size * sizeof(unsigned) ) + - (via_node_list_size * sizeof(NodeID) ) + - (graph_node_list_size * sizeof(QueryGraph::_StrNode)) + - (graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) + - (timestamp_length * sizeof(char) ) + - (coordinate_list_size * sizeof(FixedPointCoordinate)) + - (turn_instruction_list_size * sizeof(TurnInstructions) ); + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + + (name_id_list_size * sizeof(unsigned) ) + + (via_node_list_size * sizeof(NodeID) ) + + (graph_node_list_size * sizeof(QueryGraph::_StrNode) ) + + (graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) + + (timestamp_length * sizeof(char) ) + + (coordinate_list_size * sizeof(FixedPointCoordinate) ) + + (turn_instruction_list_size * sizeof(TurnInstructionsClass)); + return result; + } + uint64_t GetGeometriesIndicatorOffset() const { + uint64_t result = + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + + (name_id_list_size * sizeof(unsigned) ) + + (via_node_list_size * sizeof(NodeID) ) + + (graph_node_list_size * sizeof(QueryGraph::_StrNode) ) + + (graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) + + (timestamp_length * sizeof(char) ) + + (coordinate_list_size * sizeof(FixedPointCoordinate) ) + + (turn_instruction_list_size * sizeof(TurnInstructionsClass)) + + (r_search_tree_size * sizeof(RTreeNode) ); + return result; + } + + uint64_t GetGeometriesIndexListOffset() const + { uint64_t result = + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + + (name_id_list_size * sizeof(unsigned) ) + + (via_node_list_size * sizeof(NodeID) ) + + (graph_node_list_size * sizeof(QueryGraph::_StrNode) ) + + (graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) + + (timestamp_length * sizeof(char) ) + + (coordinate_list_size * sizeof(FixedPointCoordinate) ) + + (turn_instruction_list_size * sizeof(TurnInstructionsClass)) + + (r_search_tree_size * sizeof(RTreeNode) ) + + (geometries_indicators/32 + 1) * sizeof(unsigned); + return result; + } + + uint64_t GetGeometryListOffset() const { + uint64_t result = + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + + (name_id_list_size * sizeof(unsigned) ) + + (via_node_list_size * sizeof(NodeID) ) + + (graph_node_list_size * sizeof(QueryGraph::_StrNode) ) + + (graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) + + (timestamp_length * sizeof(char) ) + + (coordinate_list_size * sizeof(FixedPointCoordinate) ) + + (turn_instruction_list_size * sizeof(TurnInstructionsClass)) + + (r_search_tree_size * sizeof(RTreeNode) ) + + (geometries_indicators/32 + 1) * sizeof(unsigned) + + (geometries_index_list_size * sizeof(unsigned) ); return result; } uint64_t GetChecksumOffset() const { uint64_t result = - (name_index_list_size * sizeof(unsigned) ) + - (name_char_list_size * sizeof(char) ) + - (name_id_list_size * sizeof(unsigned) ) + - (via_node_list_size * sizeof(NodeID) ) + - (graph_node_list_size * sizeof(QueryGraph::_StrNode)) + - (graph_edge_list_size * sizeof(QueryGraph::_StrEdge)) + - (timestamp_length * sizeof(char) ) + - (coordinate_list_size * sizeof(FixedPointCoordinate)) + - (turn_instruction_list_size * sizeof(TurnInstructions) ) + - (r_search_tree_size * sizeof(RTreeNode) ); + (name_index_list_size * sizeof(unsigned) ) + + (name_char_list_size * sizeof(char) ) + + (name_id_list_size * sizeof(unsigned) ) + + (via_node_list_size * sizeof(NodeID) ) + + (graph_node_list_size * sizeof(QueryGraph::_StrNode) ) + + (graph_edge_list_size * sizeof(QueryGraph::_StrEdge) ) + + (timestamp_length * sizeof(char) ) + + (coordinate_list_size * sizeof(FixedPointCoordinate) ) + + (turn_instruction_list_size * sizeof(TurnInstructionsClass)) + + (r_search_tree_size * sizeof(RTreeNode) ) + + (geometries_indicators/32 + 1) * sizeof(unsigned) + + (geometries_index_list_size * sizeof(unsigned) ) + + (geometries_list_size * sizeof(unsigned) ); return result; } }; diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 9dceb6852..664bdf35a 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -25,14 +25,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "RequestHandler.h" #include "APIGrammar.h" +#include "RequestHandler.h" +#include "Http/Request.h" #include "../Library/OSRM.h" #include "../Util/SimpleLogger.h" #include "../Util/StringUtil.h" #include "../typedefs.h" +#include #include #include diff --git a/Server/RequestHandler.h b/Server/RequestHandler.h index 320c0b5b7..ae7591aea 100644 --- a/Server/RequestHandler.h +++ b/Server/RequestHandler.h @@ -28,10 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef REQUEST_HANDLER_H #define REQUEST_HANDLER_H -#include "Http/Request.h" - -#include - #include #include @@ -41,6 +37,11 @@ struct APIGrammar; struct RouteParameters; class OSRM; +namespace http { + class Reply; + struct Request; +} + class RequestHandler : private boost::noncopyable { public: diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index 9a0a46832..dc8d73139 100644 --- a/Util/GraphLoader.h +++ b/Util/GraphLoader.h @@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include +#include #include #include #include @@ -135,7 +136,7 @@ NodeID readBinaryOSRMGraphFromStream( short type; NodeID nameID; int length; - bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow; + bool isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split; for (EdgeID i=0; i 0, "loaded null length edge" ); BOOST_ASSERT_MSG(weight > 0, "loaded null weight"); @@ -189,7 +191,7 @@ NodeID readBinaryOSRMGraphFromStream( std::swap(forward, backward); } - EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow ); + EdgeT inputEdge(source, target, nameID, weight, forward, backward, type, isRoundabout, ignoreInGrid, isAccessRestricted, isContraFlow, is_split ); edge_list.push_back(inputEdge); } std::sort(edge_list.begin(), edge_list.end()); @@ -444,7 +446,10 @@ unsigned readHSGRFromStream( hsgr_input_stream.read( (char*) &number_of_nodes, sizeof(unsigned) ); BOOST_ASSERT_MSG( 0 != number_of_nodes, "number of nodes is zero"); hsgr_input_stream.read( (char*) &number_of_edges, sizeof(unsigned) ); - BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero"); + + SimpleLogger().Write() << "number_of_nodes: " << number_of_nodes << ", number_of_edges: " << number_of_edges; + + // BOOST_ASSERT_MSG( 0 != number_of_edges, "number of edges is zero"); node_list.resize(number_of_nodes + 1); hsgr_input_stream.read( (char*) &(node_list[0]), @@ -457,6 +462,7 @@ unsigned readHSGRFromStream( number_of_edges*sizeof(EdgeT) ); hsgr_input_stream.close(); + return number_of_nodes; } diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 2c311698f..c1e453016 100644 --- a/Util/ProgramOptions.h +++ b/Util/ProgramOptions.h @@ -110,6 +110,10 @@ inline unsigned GenerateServerProgramOptions( "edgesdata", boost::program_options::value(&paths["edgesdata"]), ".edges file") + ( + "geometry", + boost::program_options::value(&paths["geometries"]), + ".geometry file") ( "ramindex", boost::program_options::value(&paths["ramindex"]), @@ -252,6 +256,17 @@ inline unsigned GenerateServerProgramOptions( } + path_iterator = paths.find("geometries"); + if( + path_iterator != paths.end() && + !boost::filesystem::is_regular_file(path_iterator->second) + ) { + path_iterator->second = base_string + ".geometry"; + } else { + throw OSRMException(base_string + ".geometry not found"); + } + + path_iterator = paths.find("ramindex"); if( path_iterator != paths.end() && diff --git a/Util/SimpleLogger.h b/Util/SimpleLogger.h index 144ca73b7..ecba27b68 100644 --- a/Util/SimpleLogger.h +++ b/Util/SimpleLogger.h @@ -32,6 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include + #include #include @@ -70,16 +72,20 @@ private: bool m_is_mute; }; -class SimpleLogger { +class SimpleLogger +{ public: SimpleLogger() : level(logINFO) { } - std::ostringstream& Write(LogLevel l = logINFO) { - try { + std::ostringstream& Write(LogLevel l = logINFO) + { + try + { boost::mutex::scoped_lock lock(logger_mutex); level = l; os << "["; - switch(level) { + switch(level) + { case logINFO: os << "info"; break; @@ -96,22 +102,26 @@ public: break; } os << "] "; - } catch (...) { } + } + catch (...) { } return os; } virtual ~SimpleLogger() { - if(!LogPolicy::GetInstance().IsMute()) { - switch(level) { + if(!LogPolicy::GetInstance().IsMute()) + { + const bool is_terminal = isatty(fileno(stdout)); + switch(level) + { case logINFO: - std::cout << os.str() << std::endl; + std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl; break; case logWARNING: - std::cerr << RED << os.str() << COL_RESET << std::endl; + std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "") << std::endl; break; case logDEBUG: #ifndef NDEBUG - std::cout << YELLOW << os.str() << COL_RESET << std::endl; + std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "") << std::endl; #endif break; default: diff --git a/datastore.cpp b/datastore.cpp index 8d3dccd8d..691606a76 100644 --- a/datastore.cpp +++ b/datastore.cpp @@ -44,9 +44,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #endif -#include #include +#include +#include +#include #include #include @@ -137,6 +139,10 @@ int main( const int argc, const char * argv[] ) { BOOST_ASSERT(!paths_iterator->second.empty()); const boost::filesystem::path & names_data_path = paths_iterator->second; + paths_iterator = server_paths.find("geometries"); + BOOST_ASSERT(server_paths.end() != paths_iterator); + BOOST_ASSERT(!paths_iterator->second.empty()); + const boost::filesystem::path & geometries_data_path = paths_iterator->second; // get the shared memory segment to use bool use_first_segment = SharedMemory::RegionExists( LAYOUT_2 ); @@ -163,7 +169,6 @@ int main( const int argc, const char * argv[] ) { shared_layout_ptr->ram_index_file_name[end_of_string_index] = '\0'; // collect number of elements to store in shared memory object - SimpleLogger().Write(logDEBUG) << "Collecting files sizes"; SimpleLogger().Write() << "load names from: " << names_data_path; // number of entries in name index boost::filesystem::ifstream name_stream( @@ -192,6 +197,7 @@ int main( const int argc, const char * argv[] ) { shared_layout_ptr->via_node_list_size = number_of_original_edges; shared_layout_ptr->name_id_list_size = number_of_original_edges; shared_layout_ptr->turn_instruction_list_size = number_of_original_edges; + shared_layout_ptr->geometries_indicators = number_of_original_edges; boost::filesystem::ifstream hsgr_input_stream( hsgr_path, @@ -276,8 +282,21 @@ int main( const int argc, const char * argv[] ) { shared_layout_ptr->coordinate_list_size = coordinate_list_size; - // allocate shared memory block + // load geometries sizes + std::ifstream geometry_input_stream( + geometries_data_path.c_str(), + std::ios::binary + ); + unsigned number_of_geometries_indices = 0; + unsigned number_of_compressed_geometries = 0; + geometry_input_stream.read((char *)&number_of_geometries_indices, sizeof(unsigned)); + shared_layout_ptr->geometries_index_list_size = number_of_geometries_indices; + boost::iostreams::seek(geometry_input_stream, number_of_geometries_indices*sizeof(unsigned), BOOST_IOS::cur); + geometry_input_stream.read( (char *)&number_of_compressed_geometries, sizeof(unsigned)); + shared_layout_ptr->geometries_list_size = number_of_compressed_geometries; + + // allocate shared memory block SimpleLogger().Write() << "allocating shared memory of " << shared_layout_ptr->GetSizeOfLayout() << " bytes"; SharedMemory * shared_memory = SharedMemoryFactory::Get( DATA, @@ -287,11 +306,9 @@ int main( const int argc, const char * argv[] ) { // read actual data into shared memory object // // Loading street names - // SimpleLogger().Write() << "Loading names index and chars from: " << names_data_path.string(); unsigned * name_index_ptr = (unsigned*)( shared_memory_ptr + shared_layout_ptr->GetNameIndexOffset() ); - // SimpleLogger().Write(logDEBUG) << "Bytes: " << shared_layout_ptr->name_index_list_size*sizeof(unsigned); name_stream.read( (char*)name_index_ptr, @@ -318,9 +335,12 @@ int main( const int argc, const char * argv[] ) { shared_memory_ptr + shared_layout_ptr->GetTurnInstructionListOffset() ); + unsigned * geometries_indicator_ptr = (unsigned *)( + shared_memory_ptr + shared_layout_ptr->GetGeometriesIndicatorOffset() + ); + OriginalEdgeData current_edge_data; for(unsigned i = 0; i < number_of_original_edges; ++i) { - // SimpleLogger().Write() << i << "/" << number_of_edges; edges_input_stream.read( (char*)&(current_edge_data), sizeof(OriginalEdgeData) @@ -328,9 +348,43 @@ int main( const int argc, const char * argv[] ) { via_node_ptr[i] = current_edge_data.via_node; name_id_ptr[i] = current_edge_data.name_id; turn_instructions_ptr[i] = current_edge_data.turn_instruction; + + const unsigned bucket = i / 32; + const unsigned offset = i % 32; + unsigned value = ((0 == offset) ? 0 : geometries_indicator_ptr[bucket]); + if (current_edge_data.compressed_geometry) + { + geometries_indicator_ptr[bucket] = (value | (1 << offset)); + } } edges_input_stream.close(); + // load compressed geometry + unsigned temporary_value; + unsigned * geometries_index_ptr = (unsigned *)( + shared_memory_ptr + shared_layout_ptr->GetGeometriesIndexListOffset() + ); + geometry_input_stream.seekg(0, geometry_input_stream.beg); + geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned)); + BOOST_ASSERT(temporary_value == shared_layout_ptr->geometries_index_list_size); + + geometry_input_stream.read( + (char *)geometries_index_ptr, + shared_layout_ptr->geometries_index_list_size*sizeof(unsigned) + ); + + unsigned * geometries_list_ptr = (unsigned *)( + shared_memory_ptr + shared_layout_ptr->GetGeometryListOffset() + ); + + geometry_input_stream.read((char *)&temporary_value, sizeof(unsigned)); + BOOST_ASSERT(temporary_value == shared_layout_ptr->geometries_list_size); + + geometry_input_stream.read( + (char *)geometries_list_ptr, + shared_layout_ptr->geometries_list_size*sizeof(unsigned) + ); + // Loading list of coordinates FixedPointCoordinate * coordinates_ptr = (FixedPointCoordinate *)( shared_memory_ptr + shared_layout_ptr->GetCoordinateListOffset() @@ -372,7 +426,7 @@ int main( const int argc, const char * argv[] ) { // load the edges of the search graph QueryGraph::_StrEdge * graph_edge_list_ptr = (QueryGraph::_StrEdge *)( - shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffsett() + shared_memory_ptr + shared_layout_ptr->GetGraphEdgeListOffset() ); hsgr_input_stream.read( (char*) graph_edge_list_ptr, @@ -423,6 +477,8 @@ int main( const int argc, const char * argv[] ) { } } SimpleLogger().Write() << "all data loaded"; + + shared_layout_ptr->PrintInformation(); } catch(const std::exception & e) { SimpleLogger().Write(logWARNING) << "caught exception: " << e.what(); } diff --git a/extractor.cpp b/extractor.cpp index 70ff15ced..041635ee8 100644 --- a/extractor.cpp +++ b/extractor.cpp @@ -43,6 +43,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include + #include #include #include @@ -180,7 +182,7 @@ int main (int argc, char *argv[]) { } } - StringMap stringMap; + boost::unordered_map stringMap; ExtractionContainers externalMemory; stringMap[""] = 0; diff --git a/features/car/maxspeed.feature b/features/car/maxspeed.feature index df37e3fb5..d32e3205f 100644 --- a/features/car/maxspeed.feature +++ b/features/car/maxspeed.feature @@ -16,9 +16,9 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed. | bc | trunk | 60 | When I route I should get - | from | to | route | speed | - | a | b | ab | 85 km/h | - | b | c | bc | 40 km/h | + | from | to | route | speed | + | a | b | ab | 85 km/h | + | b | c | bc | 40 km/h +- 1 | Scenario: Car - Do not ignore maxspeed when higher than way speed Given the node map @@ -30,22 +30,22 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed. | bc | residential | 90 | When I route I should get - | from | to | route | speed | - | a | b | ab | 25 km/h | - | b | c | bc | 60 km/h | + | from | to | route | speed | + | a | b | ab | 25 km/h | + | b | c | bc | 60 km/h +- 1 | Scenario: Car - Forward/backward maxspeed Given a grid size of 100 meters Then routability should be - | highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | - | primary | | | | 65 km/h | 65 km/h | - | primary | 60 | | | 40 km/h | 40 km/h | - | primary | | 60 | | 40 km/h | 65 km/h | - | primary | | | 60 | 65 km/h | 40 km/h | - | primary | 15 | 60 | | 40 km/h | 10 km/h | - | primary | 15 | | 60 | 10 km/h | 40 km/h | - | primary | 15 | 30 | 60 | 20 km/h | 40 km/h | + | highway | maxspeed | maxspeed:forward | maxspeed:backward | forw | backw | + | primary | | | | 65 km/h | 65 km/h | + | primary | 60 | | | 40 km/h | 40 km/h | + | primary | | 60 | | 40 km/h | 65 km/h | + | primary | | | 60 | 65 km/h | 40 km/h | + | primary | 15 | 60 | | 40 km/h | 10 km/h +- 1 | + | primary | 15 | | 60 | 10 km/h +- 1| 40 km/h | + | primary | 15 | 30 | 60 | 20 km/h | 40 km/h | Scenario: Car - Maxspeed should not allow routing on unroutable ways Then routability should be @@ -62,4 +62,4 @@ When a max speed is set, osrm will use 2/3 of that as the actual speed. | runway | | | | | | | | runway | | | 100 | | | | | runway | | | | 100 | | | - | runway | | | | | 100 | | \ No newline at end of file + | runway | | | | | 100 | | diff --git a/features/car/speed.feature b/features/car/speed.feature index 261f9aa62..4df30ed4d 100644 --- a/features/car/speed.feature +++ b/features/car/speed.feature @@ -1,24 +1,24 @@ -@routing @car @speed +@routing @car @speed Feature: Car - speeds Background: Given the profile "car" And a grid size of 1000 meters - + Scenario: Car - speed of various way types Then routability should be - | highway | oneway | bothw | - | motorway | no | 90 km/h | - | motorway_link | no | 75 km/h | - | trunk | no | 85 km/h | - | trunk_link | no | 70 km/h | - | primary | no | 65 km/h | - | primary_link | no | 60 km/h | - | secondary | no | 55 km/h | - | secondary_link | no | 50 km/h | - | tertiary | no | 40 km/h | - | tertiary_link | no | 30 km/h | - | unclassified | no | 25 km/h | - | residential | no | 25 km/h | - | living_street | no | 10 km/h | - | service | no | 15 km/h | + | highway | oneway | bothw | + | motorway | no | 90 km/h | + | motorway_link | no | 75 km/h | + | trunk | no | 85 km/h +- 1 | + | trunk_link | no | 70 km/h +- 1 | + | primary | no | 65 km/h +- 1 | + | primary_link | no | 60 km/h | + | secondary | no | 55 km/h +- 1 | + | secondary_link | no | 50 km/h | + | tertiary | no | 40 km/h | + | tertiary_link | no | 30 km/h | + | unclassified | no | 25 km/h | + | residential | no | 25 km/h | + | living_street | no | 10 km/h | + | service | no | 15 km/h | diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature index 3feb95746..9603c40dd 100644 --- a/features/options/routed/help.feature +++ b/features/options/routed/help.feature @@ -25,7 +25,7 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--sharedmemory" - And stdout should contain 21 lines + And stdout should contain 22 lines And it should exit with code 0 Scenario: osrm-routed - Help, short @@ -49,7 +49,7 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--sharedmemory" - And stdout should contain 21 lines + And stdout should contain 22 lines And it should exit with code 0 Scenario: osrm-routed - Help, long @@ -73,5 +73,5 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--sharedmemory" - And stdout should contain 21 lines - And it should exit with code 0 \ No newline at end of file + And stdout should contain 22 lines + And it should exit with code 0 diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index d8a8a3945..cea5481ba 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -11,7 +11,7 @@ def test_routability_row i r[:status] = route_status r[:response] if r[:status].empty? == false r[:route] = way_list r[:json]['route_instructions'] - + if r[:route]=="w#{i}" r[:time] = r[:json]['route_summary']['total_time'] r[:distance] = r[:json]['route_summary']['total_distance'] @@ -24,7 +24,7 @@ def test_routability_row i end result[direction] = r end - + # check if forw and backw returned the same values result['bothw'] = {} [:status,:time,:distance,:speed].each do |key| @@ -62,12 +62,12 @@ Then /^routability should be$/ do |table| else raise "*** Unknown expectation format: #{want}" end - + if FuzzyMatch.match output_row[direction], want output_row[direction] = row[direction] end end - + if output_row != row log_fail row,output_row,result end diff --git a/features/testbot/opposite.feature b/features/testbot/opposite.feature index cd350e73b..c19755cdc 100644 --- a/features/testbot/opposite.feature +++ b/features/testbot/opposite.feature @@ -13,6 +13,6 @@ Feature: Separate settings for forward/backward direction | abcd | river | When I route I should get - | from | to | route | distance | speed | - | a | d | abcd | 300 +- 1m | 36 km/h | - | d | a | abcd | 300 +- 1m | 16 km/h | + | from | to | route | distance | speed | + | a | d | abcd | 300 +- 1m | 36 km/h | + | d | a | abcd | 300 +- 1m | 16 km/h +- 1 | diff --git a/features/testbot/speed.feature b/features/testbot/speed.feature index c9a983136..2eb3724f5 100644 --- a/features/testbot/speed.feature +++ b/features/testbot/speed.feature @@ -26,6 +26,6 @@ Feature: Testbot - speeds | ab | river | When I route I should get - | from | to | route | speed | time | distance | - | a | b | ab | 36 km/h | 10s | 100m | - | b | a | ab | 16 km/h | 22s | 100m | + | from | to | route | speed | time | distance | + | a | b | ab | 36 km/h | 10s | 100m | + | b | a | ab | 16 km/h +- 1 | 23s | 100m | diff --git a/prepare.cpp b/prepare.cpp index 145309e97..3b1ca3155 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -45,13 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "typedefs.h" #include +#include +#include #include -#include -#include -#include -#include #include #include @@ -158,7 +156,7 @@ int main (int argc, char *argv[]) { omp_set_num_threads( std::min( omp_get_num_procs(), requested_num_threads) ); LogPolicy::GetInstance().Unmute(); - std::ifstream restrictionsInstream( restrictions_path.c_str(), std::ios::binary); + boost::filesystem::ifstream restrictionsInstream(restrictions_path, std::ios::binary); TurnRestriction restriction; UUID uuid_loaded, uuid_orig; unsigned usableRestrictionsCounter(0); @@ -180,14 +178,15 @@ int main (int argc, char *argv[]) { ); restrictionsInstream.close(); - std::ifstream in; - in.open (input_path.c_str(), std::ifstream::in | std::ifstream::binary); + boost::filesystem::ifstream in; + in.open(input_path, std::ios::in|std::ios::binary); - std::string nodeOut(input_path.string() + ".nodes"); - std::string edgeOut(input_path.string() + ".edges"); - std::string graphOut(input_path.string() + ".hsgr"); - std::string rtree_nodes_path(input_path.string() + ".ramIndex"); - std::string rtree_leafs_path(input_path.string() + ".fileIndex"); + const std::string nodeOut = input_path.string() + ".nodes"; + const std::string edgeOut = input_path.string() + ".edges"; + const std::string geometry_filename = input_path.string() + ".geometry"; + const std::string graphOut = input_path.string() + ".hsgr"; + const std::string rtree_nodes_path = input_path.string() + ".ramIndex"; + const std::string rtree_leafs_path = input_path.string() + ".fileIndex"; /*** Setup Scripting Environment ***/ @@ -221,6 +220,7 @@ int main (int argc, char *argv[]) { return 1; } speedProfile.trafficSignalPenalty = 10*lua_tointeger(myLuaState, -1); + SimpleLogger().Write(logDEBUG) << "traffic_signal_penalty: " << speedProfile.trafficSignalPenalty; if(0 != luaL_dostring( myLuaState, "return u_turn_penalty\n")) { std::cerr << @@ -254,23 +254,45 @@ int main (int argc, char *argv[]) { SimpleLogger().Write() << "Generating edge-expanded graph representation"; EdgeBasedGraphFactory * edgeBasedGraphFactory = new EdgeBasedGraphFactory (nodeBasedNodeNumber, edgeList, bollardNodes, trafficLightNodes, inputRestrictions, internalToExternalNodeMapping, speedProfile); std::vector().swap(edgeList); - edgeBasedGraphFactory->Run(edgeOut.c_str(), myLuaState); + edgeBasedGraphFactory->Run(edgeOut,geometry_filename, myLuaState); std::vector().swap(inputRestrictions); std::vector().swap(bollardNodes); std::vector().swap(trafficLightNodes); - NodeID edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfNodes(); + unsigned edgeBasedNodeNumber = edgeBasedGraphFactory->GetNumberOfEdgeBasedNodes(); + BOOST_ASSERT( + edgeBasedNodeNumber != std::numeric_limits::max() + ); DeallocatingVector edgeBasedEdgeList; edgeBasedGraphFactory->GetEdgeBasedEdges(edgeBasedEdgeList); std::vector nodeBasedEdgeList; edgeBasedGraphFactory->GetEdgeBasedNodes(nodeBasedEdgeList); delete edgeBasedGraphFactory; + double expansionHasFinishedTime = get_timestamp() - startupTime; + + + // Building grid-like nearest-neighbor data structure + SimpleLogger().Write() << "building r-tree ..."; + StaticRTree * rtree = + new StaticRTree( + nodeBasedEdgeList, + rtree_nodes_path.c_str(), + rtree_leafs_path.c_str(), + internalToExternalNodeMapping + ); + delete rtree; + IteratorbasedCRC32 > crc32; + unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() ); + nodeBasedEdgeList.clear(); + std::vector(nodeBasedEdgeList).swap(nodeBasedEdgeList); + SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList; + /*** * Writing info on original (node-based) nodes */ SimpleLogger().Write() << "writing node map ..."; - std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary); + boost::filesystem::ofstream mapOutFile(nodeOut, std::ios::binary); const unsigned size_of_mapping = internalToExternalNodeMapping.size(); mapOutFile.write((char *)&size_of_mapping, sizeof(unsigned)); mapOutFile.write( @@ -280,26 +302,6 @@ int main (int argc, char *argv[]) { mapOutFile.close(); std::vector().swap(internalToExternalNodeMapping); - double expansionHasFinishedTime = get_timestamp() - startupTime; - - /*** - * Building grid-like nearest-neighbor data structure - */ - - SimpleLogger().Write() << "building r-tree ..."; - StaticRTree * rtree = - new StaticRTree( - nodeBasedEdgeList, - rtree_nodes_path.c_str(), - rtree_leafs_path.c_str() - ); - delete rtree; - IteratorbasedCRC32 > crc32; - unsigned crc32OfNodeBasedEdgeList = crc32(nodeBasedEdgeList.begin(), nodeBasedEdgeList.end() ); - nodeBasedEdgeList.clear(); - std::vector(nodeBasedEdgeList).swap(nodeBasedEdgeList); - SimpleLogger().Write() << "CRC32: " << crc32OfNodeBasedEdgeList; - /*** * Contracting the edge-expanded graph */ @@ -323,86 +325,99 @@ int main (int argc, char *argv[]) { */ std::sort(contractedEdgeList.begin(), contractedEdgeList.end()); - unsigned numberOfNodes = 0; - unsigned numberOfEdges = contractedEdgeList.size(); + unsigned max_used_node_id = 0; + unsigned contracted_edge_count = contractedEdgeList.size(); SimpleLogger().Write() << "Serializing compacted graph of " << - numberOfEdges << + contracted_edge_count << " edges"; - std::ofstream hsgr_output_stream(graphOut.c_str(), std::ios::binary); + boost::filesystem::ofstream hsgr_output_stream(graphOut, std::ios::binary); hsgr_output_stream.write((char*)&uuid_orig, sizeof(UUID) ); - BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { + BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) + { BOOST_ASSERT( UINT_MAX != edge.source ); BOOST_ASSERT( UINT_MAX != edge.target ); - if(edge.source > numberOfNodes) { - numberOfNodes = edge.source; - } - if(edge.target > numberOfNodes) { - numberOfNodes = edge.target; - } + + max_used_node_id = std::max(max_used_node_id, edge.source); + max_used_node_id = std::max(max_used_node_id, edge.target); + + SimpleLogger().Write(logDEBUG) << "generated edge (" << edge.source << ", " << edge.target << ")=" << edge.data.distance; + } - numberOfNodes+=1; + SimpleLogger().Write(logDEBUG) << "input graph has " << edgeBasedNodeNumber << " nodes"; + SimpleLogger().Write(logDEBUG) << "contracted graph has " << max_used_node_id << " nodes"; + max_used_node_id+=1; - std::vector< StaticGraph::_StrNode > _nodes; - _nodes.resize( numberOfNodes + 1 ); + std::vector< StaticGraph::_StrNode > node_array; + node_array.resize( edgeBasedNodeNumber + 1); + SimpleLogger().Write() << "Building node array"; StaticGraph::EdgeIterator edge = 0; StaticGraph::EdgeIterator position = 0; - for ( StaticGraph::NodeIterator node = 0; node < numberOfNodes; ++node ) { - StaticGraph::EdgeIterator lastEdge = edge; - while ( edge < numberOfEdges && contractedEdgeList[edge].source == node ) + StaticGraph::EdgeIterator lastEdge = edge; + + for ( StaticGraph::NodeIterator node = 0; node < max_used_node_id; ++node) + { + lastEdge = edge; + while ((edge < contracted_edge_count) && (contractedEdgeList[edge].source == node)) + { ++edge; - _nodes[node].firstEdge = position; //=edge + } + node_array[node].firstEdge = position; //=edge position += edge - lastEdge; //remove } - _nodes.back().firstEdge = numberOfEdges; //sentinel element - ++numberOfNodes; - - BOOST_ASSERT_MSG( - _nodes.size() == numberOfNodes, - "no. of nodes dont match" - ); + for (unsigned sentinel_counter = max_used_node_id; + sentinel_counter != node_array.size(); + ++sentinel_counter + ) + { + //sentinel element, guarded against underflow + node_array[sentinel_counter].firstEdge = contracted_edge_count; + } + unsigned node_array_size = node_array.size(); //serialize crc32, aka checksum hsgr_output_stream.write((char*) &crc32OfNodeBasedEdgeList, sizeof(unsigned)); - //serialize number f nodes - hsgr_output_stream.write((char*) &numberOfNodes, sizeof(unsigned)); + //serialize number of nodes + hsgr_output_stream.write((char*) &node_array_size, sizeof(unsigned)); //serialize number of edges - hsgr_output_stream.write((char*) &position, sizeof(unsigned)); + hsgr_output_stream.write((char*) &contracted_edge_count, sizeof(unsigned)); //serialize all nodes - hsgr_output_stream.write((char*) &_nodes[0], sizeof(StaticGraph::_StrNode)*(numberOfNodes)); + hsgr_output_stream.write((char*) &node_array[0], sizeof(StaticGraph::_StrNode)*node_array_size); //serialize all edges - --numberOfNodes; + SimpleLogger().Write() << "Building edge array"; edge = 0; int usedEdgeCounter = 0; - SimpleLogger().Write() << "Building Node Array"; - StaticGraph::_StrEdge currentEdge; - for ( StaticGraph::NodeIterator node = 0; node < numberOfNodes; ++node ) { - for ( StaticGraph::EdgeIterator i = _nodes[node].firstEdge, e = _nodes[node+1].firstEdge; i != e; ++i ) { - assert(node != contractedEdgeList[edge].target); - currentEdge.target = contractedEdgeList[edge].target; - currentEdge.data = contractedEdgeList[edge].data; - if(currentEdge.data.distance <= 0) { - SimpleLogger().Write(logWARNING) << - "Edge: " << i << - ",source: " << contractedEdgeList[edge].source << - ", target: " << contractedEdgeList[edge].target << - ", dist: " << currentEdge.data.distance; - SimpleLogger().Write(logWARNING) << - "Failed at edges of node " << node << - " of " << numberOfNodes; - return 1; - } - //Serialize edges - hsgr_output_stream.write((char*) ¤tEdge, sizeof(StaticGraph::_StrEdge)); - ++edge; - ++usedEdgeCounter; + StaticGraph::_StrEdge currentEdge; + for (unsigned edge = 0; edge < contractedEdgeList.size(); ++edge) + { + // no eigen loops + BOOST_ASSERT(contractedEdgeList[edge].source != contractedEdgeList[edge].target); + currentEdge.target = contractedEdgeList[edge].target; + currentEdge.data = contractedEdgeList[edge].data; + + // every target needs to be valid + BOOST_ASSERT(currentEdge.target < max_used_node_id); + if(currentEdge.data.distance <= 0) { + SimpleLogger().Write(logWARNING) << + "Edge: " << edge << + ",source: " << contractedEdgeList[edge].source << + ", target: " << contractedEdgeList[edge].target << + ", dist: " << currentEdge.data.distance; + + SimpleLogger().Write(logWARNING) << + "Failed at adjacency list of node " << contractedEdgeList[edge].source << "/" << node_array.size()-1; + return 1; } + hsgr_output_stream.write((char*) ¤tEdge, sizeof(StaticGraph::_StrEdge)); + ++usedEdgeCounter; } + hsgr_output_stream.close(); + SimpleLogger().Write() << "Preprocessing : " << (get_timestamp() - startupTime) << " seconds"; SimpleLogger().Write() << "Expansion : " << @@ -413,19 +428,16 @@ int main (int argc, char *argv[]) { (edgeBasedNodeNumber/contraction_duration) << " nodes/sec and " << usedEdgeCounter/contraction_duration << " edges/sec"; - hsgr_output_stream.close(); - //cleanedEdgeList.clear(); - _nodes.clear(); + node_array.clear(); SimpleLogger().Write() << "finished preprocessing"; - } catch(boost::program_options::too_many_positional_options_error& e) { + } catch(boost::program_options::too_many_positional_options_error&) { SimpleLogger().Write(logWARNING) << "Only one file can be specified"; return 1; } catch(boost::program_options::error& e) { SimpleLogger().Write(logWARNING) << e.what(); return 1; } catch ( const std::exception &e ) { - SimpleLogger().Write(logWARNING) << - "Exception occured: " << e.what() << std::endl; + SimpleLogger().Write(logWARNING) << "Exception occured: " << e.what() << std::endl; return 1; } return 0; diff --git a/profiles/bicycle.lua b/profiles/bicycle.lua index 08f78b8ce..3efa3d025 100644 --- a/profiles/bicycle.lua +++ b/profiles/bicycle.lua @@ -96,6 +96,22 @@ turn_penalty = 60 turn_bias = 1.4 -- End of globals + +local function parse_maxspeed(source) + if not source then + return 0 + end + local n = tonumber(source:match("%d*")) + if not n then + n = 0 + end + if string.match(source, "mph") or string.match(source, "mp/h") then + n = (n*1609)/1000; + end + return n +end + + function get_exceptions(vector) for i,v in ipairs(restriction_exception_tags) do vector:Add(v) @@ -107,27 +123,27 @@ function node_function (node) local access = Access.find_access_tag(node, access_tags_hierachy) local traffic_signal = node.tags:Find("highway") - -- flag node if it carries a traffic light - if traffic_signal == "traffic_signals" then - node.traffic_light = true - end + -- flag node if it carries a traffic light + if traffic_signal == "traffic_signals" then + node.traffic_light = true + end - -- parse access and barrier tags - if access and access ~= "" then - if access_tag_blacklist[access] then - node.bollard = true - else - node.bollard = false - end - elseif barrier and barrier ~= "" then - if barrier_whitelist[barrier] then - node.bollard = false - else - node.bollard = true - end - end + -- parse access and barrier tags + if access and access ~= "" then + if access_tag_blacklist[access] then + node.bollard = true + else + node.bollard = false + end + elseif barrier and barrier ~= "" then + if barrier_whitelist[barrier] then + node.bollard = false + else + node.bollard = true + end + end - return 1 + -- return 1 end function way_function (way) @@ -159,14 +175,13 @@ function way_function (way) return 0 end - -- other tags local name = way.tags:Find("name") local ref = way.tags:Find("ref") local junction = way.tags:Find("junction") - local maxspeed = parseMaxspeed(way.tags:Find ( "maxspeed") ) - local maxspeed_forward = parseMaxspeed(way.tags:Find( "maxspeed:forward")) - local maxspeed_backward = parseMaxspeed(way.tags:Find( "maxspeed:backward")) + local maxspeed = parse_maxspeed(way.tags:Find ( "maxspeed") ) + local maxspeed_forward = parse_maxspeed(way.tags:Find( "maxspeed:forward")) + local maxspeed_backward = parse_maxspeed(way.tags:Find( "maxspeed:backward")) local barrier = way.tags:Find("barrier") local oneway = way.tags:Find("oneway") local onewayClass = way.tags:Find("oneway:bicycle") @@ -305,7 +320,6 @@ function way_function (way) end end - -- cycleways if cycleway and cycleway_tags[cycleway] then way.speed = bicycle_speeds["cycleway"] diff --git a/profiles/car.lua b/profiles/car.lua index 05b8e7298..d57a6544e 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -32,7 +32,7 @@ speed_profile = { ["default"] = 10 } -local take_minimum_of_speeds = false +local take_minimum_of_speeds = false local obey_oneway = true local obey_bollards = true local use_turn_restrictions = true @@ -77,6 +77,14 @@ local function parse_maxspeed(source) return n end +-- function turn_function (angle) +-- -- print ("called at angle " .. angle ) +-- local index = math.abs(math.floor(angle/10+0.5))+1 -- +1 'coz LUA starts as idx 1 +-- local penalty = turn_cost_table[index] +-- -- print ("index: " .. index .. ", bias: " .. penalty ) +-- return penalty +-- end + function node_function (node) local access = find_access_tag(node, access_tags_hierachy) @@ -260,4 +268,4 @@ function node_vector_function(vector) for v in vector.nodes do node_function(v) end -end \ No newline at end of file +end diff --git a/routed.cpp b/routed.cpp index bd5f46373..855ec04c4 100644 --- a/routed.cpp +++ b/routed.cpp @@ -108,6 +108,7 @@ int main (int argc, const char * argv[]) SimpleLogger().Write() << "HSGR file:\t" << server_paths["hsgrdata"]; SimpleLogger().Write(logDEBUG) << "Nodes file:\t" << server_paths["nodesdata"]; SimpleLogger().Write(logDEBUG) << "Edges file:\t" << server_paths["edgesdata"]; + SimpleLogger().Write(logDEBUG) << "Geometry file:\t" << server_paths["geometries"]; SimpleLogger().Write(logDEBUG) << "RAM file:\t" << server_paths["ramindex"]; SimpleLogger().Write(logDEBUG) << "Index file:\t" << server_paths["fileindex"]; SimpleLogger().Write(logDEBUG) << "Names file:\t" << server_paths["namesdata"]; diff --git a/typedefs.h b/typedefs.h index a3a6362fe..b4fac11e7 100644 --- a/typedefs.h +++ b/typedefs.h @@ -28,9 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TYPEDEFS_H_ #define TYPEDEFS_H_ -// To fix long and long long woes -#include -#include +#include // Necessary workaround for Windows as VS doesn't implement C99 #ifdef _MSC_VER @@ -46,9 +44,10 @@ digitT round(digitT x) { typedef unsigned int NodeID; typedef unsigned int EdgeID; -typedef unsigned int EdgeWeight; +typedef int EdgeWeight; -static const NodeID SPECIAL_NODEID = boost::integer_traits::const_max; -static const EdgeID SPECIAL_EDGEID = boost::integer_traits::const_max; +static const NodeID SPECIAL_NODEID = std::numeric_limits::max(); +static const EdgeID SPECIAL_EDGEID = std::numeric_limits::max(); +static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits::max(); #endif /* TYPEDEFS_H_ */