diff --git a/Contractor/EdgeBasedGraphFactory.cpp b/Contractor/EdgeBasedGraphFactory.cpp index fef577840..0ac515c60 100644 --- a/Contractor/EdgeBasedGraphFactory.cpp +++ b/Contractor/EdgeBasedGraphFactory.cpp @@ -33,13 +33,7 @@ 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 EdgeBasedGraphFactory::EdgeBasedGraphFactory( int number_of_nodes, @@ -107,6 +101,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( 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; @@ -115,22 +110,85 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( 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(); - edges_list.push_back( edge ); - } + + std::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 != UINT_MAX ); + BOOST_ASSERT( v != UINT_MAX ); + BOOST_ASSERT( w != UINT_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 != UINT_MAX ); + BOOST_ASSERT( v != UINT_MAX ); + BOOST_ASSERT( w != UINT_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( @@ -157,7 +215,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 != UINT_MAX ); + BOOST_ASSERT( v != UINT_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()) { @@ -179,8 +239,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 != UINT_MAX ); + BOOST_ASSERT( v != UINT_MAX ); + BOOST_ASSERT( w != UINT_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 +252,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,10 +264,14 @@ bool EdgeBasedGraphFactory::CheckIfTurnIsRestricted( } void EdgeBasedGraphFactory::InsertEdgeBasedNode( - EdgeIterator e1, - NodeIterator u, - NodeIterator v, - bool belongsToTinyComponent) { + EdgeIterator e1, + NodeIterator u, + NodeIterator v, + bool belongsToTinyComponent +) { + BOOST_ASSERT( u != UINT_MAX ); + BOOST_ASSERT( v != UINT_MAX ); + BOOST_ASSERT( e1 != UINT_MAX ); EdgeData & data = m_node_based_graph->GetEdgeData(e1); EdgeBasedNode currentNode; currentNode.nameID = data.nameID; @@ -209,6 +279,9 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode( currentNode.lon1 = m_node_info_list[u].lon; currentNode.lat2 = m_node_info_list[v].lat; currentNode.lon2 = m_node_info_list[v].lon; + if( m_geometry_compressor.HasEntryForID(e1) ) { + //reconstruct geometry and put in each individual edge with its offset + } currentNode.belongsToTinyComponent = belongsToTinyComponent; currentNode.id = data.edgeBasedNodeID; currentNode.ignoreInGrid = data.ignoreInGrid; @@ -229,27 +302,163 @@ 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 + SimpleLogger().Write(logDEBUG) << "Input graph has " << original_number_of_nodes << " nodes and " << original_number_of_edges << " edges"; + Percent p(original_number_of_nodes); + unsigned removed_node_count = 0; + for( NodeID v = 0; v < original_number_of_nodes; ++v ) { + p.printStatus(v); - //TODO: do some compression statistics + // 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( UINT_MAX != forward_e2 ); + const EdgeIterator reverse_e2 = m_node_based_graph->BeginEdges(v) + 1 - reverse_edge_order; + BOOST_ASSERT( UINT_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( UINT_MAX != w ); + BOOST_ASSERT( v != w ); + const NodeIterator u = m_node_based_graph->GetTarget(reverse_e2); + BOOST_ASSERT( UINT_MAX != u ); + BOOST_ASSERT( u != v ); + + const EdgeIterator forward_e1 = m_node_based_graph->FindEdge(u, v); + BOOST_ASSERT( UINT_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( UINT_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 ( + fwd_edge_data1.IsEqualTo(fwd_edge_data2) && + rev_edge_data1.IsEqualTo(rev_edge_data2) + ) { + // extend e1's to targets of e2's + m_node_based_graph->SetTarget(forward_e1, w); + m_node_based_graph->SetTarget(reverse_e1, u); + + // 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; + + // 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 ); + + //TODO: store compressed geometry in container + m_geometry_compressor.CompressEdge( forward_e1, forward_e2, v ); + m_geometry_compressor.CompressEdge( reverse_e1, reverse_e2, v ); + + ++removed_node_count; + } + } + 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; + + //Extract routing graph + DeallocatingVector edges_list; + NodeBasedEdge new_edge; + for(NodeID source = 0; source < m_node_based_graph->GetNumberOfNodes(); ++source) { + for( + EdgeID current_edge_id = m_node_based_graph->BeginEdges(source); + current_edge_id < m_node_based_graph->EndEdges(source); + ++current_edge_id + ) { + const NodeID target = m_node_based_graph->GetTarget(current_edge_id); + const EdgeData & edge_data = m_node_based_graph->GetEdgeData(current_edge_id); + if( source > target ) { + continue; + } + if( edge_data.forward) { + new_edge.source = source; + new_edge.target = target; + new_edge.data = edge_data; + new_edge.data.edgeBasedNodeID = edges_list.size(); + edges_list.push_back(new_edge); + } + + const EdgeID reverse_edge_id = m_node_based_graph->FindEdge(target, source); + BOOST_ASSERT( reverse_edge_id != m_node_based_graph->EndEdges(target)); + + const EdgeData & reverse_edge_data = m_node_based_graph->GetEdgeData(reverse_edge_id); + if( reverse_edge_data.forward ) { + new_edge.source = target; + new_edge.target = source; + new_edge.data = reverse_edge_data; + new_edge.data.edgeBasedNodeID = edges_list.size(); + edges_list.push_back(new_edge); + } + } + } + m_node_based_graph.reset(); + + std::sort( edges_list.begin(), edges_list.end() ); + + //Instantiate routing graph + m_node_based_graph = boost::make_shared( + original_number_of_nodes, + edges_list + ); + + DeallocatingVector().swap(edges_list); + BOOST_ASSERT(0 == edges_list.size() ); 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 ); @@ -269,8 +478,8 @@ void EdgeBasedGraphFactory::Run( 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; @@ -322,6 +531,9 @@ 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; p.reinit(m_node_based_graph->GetNumberOfNodes()); for( NodeIterator u = 0, end = m_node_based_graph->GetNumberOfNodes(); @@ -351,18 +563,18 @@ void EdgeBasedGraphFactory::Run( 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; } } @@ -374,13 +586,13 @@ void EdgeBasedGraphFactory::Run( (to_node_of_only_restriction == UINT_MAX) && (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() @@ -406,11 +618,17 @@ void EdgeBasedGraphFactory::Run( } distance += turn_penalty; + const bool edge_is_compressed = m_geometry_compressor.HasEntryForID(e1); + if(edge_is_compressed) { + m_geometry_compressor.AddNodeIDToCompressedEdge(e1, v); + } + original_edge_data_vector.push_back( OriginalEdgeData( - v, + edge_is_compressed ? m_geometry_compressor.GetPositionForID(e1) : v, edge_data2.nameID, - turnInstruction + turnInstruction, + edge_is_compressed ) ); ++original_edges_counter; @@ -442,6 +660,8 @@ void EdgeBasedGraphFactory::Run( edge_data_file.write( (char*)&original_edges_counter, sizeof(unsigned) ); edge_data_file.close(); + m_geometry_compressor.SerializeInternalVector( geometry_filename ); + SimpleLogger().Write() << "Generated " << m_edge_based_node_list.size() << " edge based nodes"; SimpleLogger().Write() << @@ -451,8 +671,12 @@ void EdgeBasedGraphFactory::Run( SimpleLogger().Write() << " contains " << m_edge_based_edge_list.size() << " edges"; SimpleLogger().Write() << - " skips " << skipped_turns_counter << " turns, " + " 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( diff --git a/Contractor/EdgeBasedGraphFactory.h b/Contractor/EdgeBasedGraphFactory.h index 4621d752c..d6f75dbd2 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 ); @@ -102,6 +96,18 @@ public: unsigned GetNumberOfNodes() 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 { int distance; @@ -115,6 +121,20 @@ private: bool roundabout:1; bool ignoreInGrid: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) && + (ignoreInGrid == other.ignoreInGrid) && + (contraFlow == other.contraFlow); + } }; unsigned m_turn_restrictions_count; @@ -139,6 +159,7 @@ private: boost::unordered_set m_traffic_lights; RestrictionMap m_restriction_map; + GeometryCompressor m_geometry_compressor; NodeID CheckForEmanatingIsOnlyTurn( const NodeID u, @@ -167,6 +188,18 @@ 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 + ); }; #endif /* EDGEBASEDGRAPHFACTORY_H_ */ diff --git a/Contractor/GeometryCompressor.cpp b/Contractor/GeometryCompressor.cpp index 5f97a751c..9e9837bf6 100644 --- a/Contractor/GeometryCompressor.cpp +++ b/Contractor/GeometryCompressor.cpp @@ -26,6 +26,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "GeometryCompressor.h" +#include "../Util/SimpleLogger.h" + +#include +#include + +#include int current_free_list_maximum = 0; int UniqueNumber () { return ++current_free_list_maximum; } @@ -37,58 +43,155 @@ GeometryCompressor::GeometryCompressor() { 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) { + 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() ) { - IncreaseFreeList(); +unsigned GeometryCompressor::GetPositionForID(const EdgeID edge_id) { + 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() ); + return map_iterator->second; +} + +void GeometryCompressor::AddNodeIDToCompressedEdge( + const EdgeID edge_id, + const NodeID node_id +) { + unsigned index = GetPositionForID(edge_id); + BOOST_ASSERT( index < m_compressed_geometries.size() ); + m_compressed_geometries[index].push_back( node_id ); +} + +void GeometryCompressor::SerializeInternalVector( + const std::string & path +) const { + std::ofstream geometry_out_stream( path.c_str(), std::ios::binary ); + const unsigned compressed_edge_count = m_compressed_geometries.size()+1; + BOOST_ASSERT( UINT_MAX != compressed_edge_count ); + geometry_out_stream.write( + (char*)&compressed_edge_count, + sizeof(unsigned) + ); + + // write indices array + unsigned prefix_sum_of_list_indices = 0; + for(unsigned i = 0; i < m_compressed_geometries.size(); ++i ) { + const std::vector & current_vector = m_compressed_geometries[i]; + const unsigned unpacked_size = current_vector.size(); + BOOST_ASSERT( UINT_MAX != unpacked_size ); + geometry_out_stream.write( + (char*)&prefix_sum_of_list_indices, + sizeof(unsigned) + ); + prefix_sum_of_list_indices += unpacked_size; + } + // write sentinel element + geometry_out_stream.write( + (char*)&prefix_sum_of_list_indices, + sizeof(unsigned) + ); + + // write compressed geometries + for(unsigned i = 0; i < m_compressed_geometries.size(); ++i ) { + const std::vector & current_vector = m_compressed_geometries[i]; + const unsigned unpacked_size = current_vector.size(); + BOOST_ASSERT( UINT_MAX != unpacked_size ); + for(unsigned j = 0; j < unpacked_size; ++j) { + geometry_out_stream.write( + (char*)&(current_vector[j]), + sizeof(unsigned) + ); } - geometry_bucket_index = m_free_list.back(); - m_free_list.pop_back(); - } else { - geometry_bucket_index = map_iterator->second; } - BOOST_ASSERT( std::numeric_limits::max() != geometry_bucket_index ); - BOOST_ASSERT( geometry_bucket_index < m_compressed_geometries.size() ); + // all done, let's close the resource + geometry_out_stream.close(); +} - //append contracted_node_id to m_compressed_geometries[node_id] - m_compressed_geometries[geometry_bucket_index].push_back(contracted_node_id); +void GeometryCompressor::CompressEdge( + const EdgeID surviving_edge_id, + const EdgeID removed_edge_id, + const NodeID via_node_id +) { + BOOST_ASSERT( UINT_MAX != surviving_edge_id ); + BOOST_ASSERT( UINT_MAX != removed_edge_id ); + BOOST_ASSERT( UINT_MAX != via_node_id ); - //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() ); + // append list of removed edge_id plus via node to surviving edge id: + // & compressed_id_list = m_compressed_geometries[surving_list_id]; + compressed_id_list.push_back(via_node_id); + BOOST_ASSERT( 0 < compressed_id_list.size() ); + + // Find any existing list for removed_edge_id + typename boost::unordered_map::const_iterator map_iterator; + map_iterator = m_edge_id_to_list_index_map.find(removed_edge_id); + if( m_edge_id_to_list_index_map.end() != map_iterator ) { + const unsigned index = map_iterator->second; + BOOST_ASSERT( index < m_compressed_geometries.size() ); + // found an existing list, append it to the list of surviving_edge_id + compressed_id_list.insert( + compressed_id_list.end(), + m_compressed_geometries[index].begin(), + m_compressed_geometries[index].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); + + //remove the list of removed_edge_id + m_edge_id_to_list_index_map.erase(map_iterator); + BOOST_ASSERT( m_edge_id_to_list_index_map.end() == m_edge_id_to_list_index_map.find(removed_edge_id) ); + m_compressed_geometries[index].clear(); + BOOST_ASSERT( 0 == m_compressed_geometries[index].size() ); + m_free_list.push_back(index); + BOOST_ASSERT( index == m_free_list.back() ); } } void GeometryCompressor::PrintStatistics() const { - unsigned compressed_node_count = 0; - const unsigned surviving_node_count = m_compressed_geometries.size(); + unsigned removed_edge_count = 0; + const unsigned surviving_edge_count = m_compressed_geometries.size()-m_free_list.size(); + BOOST_ASSERT( m_compressed_geometries.size() + m_free_list.size() > 0 ); + + unsigned long longest_chain_length = 0; BOOST_FOREACH(const std::vector & current_vector, m_compressed_geometries) { - compressed_node_count += current_vector.size(); + removed_edge_count += current_vector.size(); + longest_chain_length = std::max(longest_chain_length, current_vector.size()); } + BOOST_ASSERT(0 == surviving_edge_count % 2); SimpleLogger().Write() << - "surv: " << surviving_node_count << - ", comp: " << compressed_node_count << - ", comp ratio: " << ((float)surviving_node_count/std::max(compressed_node_count, 1u) ); + "surviving edges: " << surviving_edge_count << + ", compressed edges: " << removed_edge_count << + ", longest chain length: " << longest_chain_length << + ", comp ratio: " << ((float)surviving_edge_count/std::max(removed_edge_count, 1u) ) << + ", avg: chain length: " << (float)removed_edge_count/std::max(1u, surviving_edge_count); + + SimpleLogger().Write() << + "No bytes: " << 4*surviving_edge_count + removed_edge_count*4; } diff --git a/Contractor/GeometryCompressor.h b/Contractor/GeometryCompressor.h index 8d2bf66a6..1fda18cdb 100644 --- a/Contractor/GeometryCompressor.h +++ b/Contractor/GeometryCompressor.h @@ -25,14 +25,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../Util/SimpleLogger.h" #include "../typedefs.h" -#include -#include #include -#include #include #include @@ -42,17 +38,24 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. class GeometryCompressor { public: GeometryCompressor(); - void AppendNodeIDsToGeomtry( NodeID node_id, NodeID contracted_node_id ); + void CompressEdge( + const EdgeID first_edge_id, + const EdgeID second_edge_id, + const NodeID via_node_id + ); void PrintStatistics() const; + bool HasEntryForID(const EdgeID edge_id); + void AddNodeIDToCompressedEdge(const EdgeID edge_id, const NodeID node_id); + unsigned GetPositionForID(const EdgeID edge_id); + void SerializeInternalVector(const std::string & path) const; 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 diff --git a/DataStructures/OriginalEdgeData.h b/DataStructures/OriginalEdgeData.h index 894cf8add..5ebf98087 100644 --- a/DataStructures/OriginalEdgeData.h +++ b/DataStructures/OriginalEdgeData.h @@ -37,22 +37,26 @@ 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( UINT_MAX ), + name_id( UINT_MAX ), + turn_instruction( UCHAR_MAX ), + compressed_geometry( false ) { } NodeID via_node; unsigned name_id; TurnInstruction turn_instruction; + bool compressed_geometry; }; #endif //ORIGINAL_EDGE_DATA_H diff --git a/Server/DataStructures/InternalDataFacade.h b/Server/DataStructures/InternalDataFacade.h index b8a552cf3..249c37bda 100644 --- a/Server/DataStructures/InternalDataFacade.h +++ b/Server/DataStructures/InternalDataFacade.h @@ -113,8 +113,8 @@ 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, @@ -163,6 +163,12 @@ private: edges_input_stream.close(); } + void LoadGeometries( + const boost::filesystem::path & geometries_file + ) { + + } + void LoadRTree( const boost::filesystem::path & ram_index_path, const boost::filesystem::path & file_index_path @@ -249,12 +255,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"; diff --git a/Server/DataStructures/SharedDataFacade.h b/Server/DataStructures/SharedDataFacade.h index 0778eb06d..213b696a2 100644 --- a/Server/DataStructures/SharedDataFacade.h +++ b/Server/DataStructures/SharedDataFacade.h @@ -241,6 +241,7 @@ public: LoadGraph(); LoadNodeAndEdgeInformation(); + //TODO: LoadGeometries(); LoadRTree(ram_index_path); LoadTimestamp(); LoadViaNodeList(); diff --git a/Util/GraphLoader.h b/Util/GraphLoader.h index 9a0a46832..3785da6b2 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 diff --git a/Util/ProgramOptions.h b/Util/ProgramOptions.h index 2c311698f..1b7fbc292 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") + ( + "geometries", + boost::program_options::value(&paths["geometries"]), + ".geometries file") ( "ramindex", boost::program_options::value(&paths["ramindex"]), diff --git a/prepare.cpp b/prepare.cpp index 145309e97..43130f0b7 100644 --- a/prepare.cpp +++ b/prepare.cpp @@ -183,11 +183,12 @@ int main (int argc, char *argv[]) { std::ifstream in; in.open (input_path.c_str(), std::ifstream::in | std::ifstream::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 ***/ @@ -254,7 +255,7 @@ 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); @@ -270,7 +271,7 @@ int main (int argc, char *argv[]) { */ SimpleLogger().Write() << "writing node map ..."; - std::ofstream mapOutFile(nodeOut.c_str(), std::ios::binary); + std::ofstream mapOutFile(nodeOut, std::ios::binary); const unsigned size_of_mapping = internalToExternalNodeMapping.size(); mapOutFile.write((char *)&size_of_mapping, sizeof(unsigned)); mapOutFile.write( @@ -330,7 +331,7 @@ int main (int argc, char *argv[]) { numberOfEdges << " edges"; - std::ofstream hsgr_output_stream(graphOut.c_str(), std::ios::binary); + std::ofstream hsgr_output_stream(graphOut, std::ios::binary); hsgr_output_stream.write((char*)&uuid_orig, sizeof(UUID) ); BOOST_FOREACH(const QueryEdge & edge, contractedEdgeList) { BOOST_ASSERT( UINT_MAX != edge.source );