From 3065de63dd55218fcf93d74d2fc188fcdfaae14c Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Wed, 13 May 2015 01:26:54 +0200 Subject: [PATCH] Move renumbering and edge deduplication in extractor --- contractor/edge_based_graph_factory.cpp | 10 +- contractor/processing_chain.cpp | 22 +-- contractor/processing_chain.hpp | 4 +- data_structures/import_edge.cpp | 7 + data_structures/import_edge.hpp | 3 +- data_structures/node_based_graph.hpp | 3 +- extractor/extraction_containers.cpp | 191 +++++++++++++++++++++--- extractor/extraction_containers.hpp | 2 + extractor/internal_extractor_edge.hpp | 14 ++ tools/components.cpp | 17 +-- util/graph_loader.hpp | 156 ++----------------- 11 files changed, 235 insertions(+), 194 deletions(-) diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index c760f0f43..6f414ecd9 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -343,8 +343,14 @@ void EdgeBasedGraphFactory::CompressGeometry() continue; } - if ( // TODO: rename to IsCompatibleTo - fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2)) + // this case can happen if two ways with different names overlap + if (fwd_edge_data1.nameID != rev_edge_data1.nameID || + fwd_edge_data2.nameID != rev_edge_data2.nameID) + { + continue; + } + + if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2)) { BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID == m_node_based_graph->GetEdgeData(reverse_e1).nameID); diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index b51fab76c..b354a62b3 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -303,44 +303,38 @@ void Prepare::SetupScriptingEnvironment( /** \brief Build load restrictions from .restriction file */ -void Prepare::LoadRestrictionMap(const std::unordered_map &external_to_internal_node_map, - RestrictionMap &restriction_map) +std::shared_ptr Prepare::LoadRestrictionMap() { boost::filesystem::ifstream input_stream(config.restrictions_path, std::ios::in | std::ios::binary); std::vector restriction_list; - loadRestrictionsFromFile(input_stream, external_to_internal_node_map, restriction_list); + loadRestrictionsFromFile(input_stream, restriction_list); SimpleLogger().Write() << " - " << restriction_list.size() << " restrictions."; - restriction_map = RestrictionMap(restriction_list); + return std::make_shared(restriction_list); } /** - \brief Build load node based graph from .osrm file and restrictions from .restrictions file + \brief Load node based graph from .osrm file */ std::shared_ptr Prepare::LoadNodeBasedGraph(std::vector &barrier_node_list, std::vector &traffic_light_list, - RestrictionMap &restriction_map, std::vector& internal_to_external_node_map) { std::vector edge_list; - std::unordered_map external_to_internal_node_map; boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary); NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream, barrier_node_list, traffic_light_list, - internal_to_external_node_map, - external_to_internal_node_map); + internal_to_external_node_map); SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, " << traffic_light_list.size() << " traffic lights"; - loadEdgesFromFile(input_stream, external_to_internal_node_map, edge_list); - - LoadRestrictionMap(external_to_internal_node_map, restriction_map); + loadEdgesFromFile(input_stream, edge_list); if (edge_list.empty()) { @@ -369,9 +363,9 @@ Prepare::BuildEdgeExpandedGraph(std::vector &internal_to_external_nod auto barrier_node_list = osrm::make_unique>(); auto traffic_light_list = osrm::make_unique>(); - auto restriction_map = std::make_shared(); - auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, *restriction_map, internal_to_external_node_map); + auto restriction_map = LoadRestrictionMap(); + auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, internal_to_external_node_map); const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes(); diff --git a/contractor/processing_chain.hpp b/contractor/processing_chain.hpp index 2e4b2cd1f..12f74f3fb 100644 --- a/contractor/processing_chain.hpp +++ b/contractor/processing_chain.hpp @@ -61,8 +61,7 @@ class Prepare protected: void SetupScriptingEnvironment(lua_State *myLuaState, EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile); - void LoadRestrictionMap(const std::unordered_map &external_to_internal_node_map, - RestrictionMap &restriction_map); + std::shared_ptr LoadRestrictionMap(); unsigned CalculateEdgeChecksum(std::unique_ptr> node_based_edge_list); void ContractGraph(const std::size_t number_of_edge_based_nodes, DeallocatingVector& edge_based_edge_list, @@ -72,7 +71,6 @@ class Prepare std::unique_ptr> contracted_edge_list); std::shared_ptr LoadNodeBasedGraph(std::vector &barrier_node_list, std::vector &traffic_light_list, - RestrictionMap &restriction_map, std::vector& internal_to_external_node_map); std::pair BuildEdgeExpandedGraph(std::vector &internal_to_external_node_map, diff --git a/data_structures/import_edge.cpp b/data_structures/import_edge.cpp index f41b066b1..3f2146ca3 100644 --- a/data_structures/import_edge.cpp +++ b/data_structures/import_edge.cpp @@ -47,6 +47,13 @@ bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const return source < other.source; } +NodeBasedEdge::NodeBasedEdge() + : source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false), + backward(false), roundabout(false), in_tiny_cc(false), + access_restricted(false), is_split(false), travel_mode(false) +{ +} + NodeBasedEdge::NodeBasedEdge(NodeID source, NodeID target, NodeID name_id, diff --git a/data_structures/import_edge.hpp b/data_structures/import_edge.hpp index 27af59846..e48985073 100644 --- a/data_structures/import_edge.hpp +++ b/data_structures/import_edge.hpp @@ -35,6 +35,7 @@ struct NodeBasedEdge { bool operator<(const NodeBasedEdge &e) const; + NodeBasedEdge(); explicit NodeBasedEdge(NodeID source, NodeID target, NodeID name_id, @@ -58,8 +59,6 @@ struct NodeBasedEdge bool access_restricted : 1; bool is_split : 1; TravelMode travel_mode : 4; - - NodeBasedEdge() = delete; }; struct EdgeBasedEdge diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp index f35367924..d33bef459 100644 --- a/data_structures/node_based_graph.hpp +++ b/data_structures/node_based_graph.hpp @@ -64,7 +64,7 @@ struct NodeBasedEdgeData backward = temp_flag; } - bool IsEqualTo(const NodeBasedEdgeData &other) const + bool IsCompatibleTo(const NodeBasedEdgeData &other) const { return (forward == other.forward) && (backward == other.backward) && (nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) && @@ -85,6 +85,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vectorresult.source == node_iterator->node_id); + + // assign new node id + auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id); + BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end()); + edge_iterator->result.source = id_iter->second; + edge_iterator->source_coordinate.lat = node_iterator->lat; edge_iterator->source_coordinate.lon = node_iterator->lon; ++edge_iterator; @@ -211,6 +224,10 @@ void ExtractionContainers::PrepareEdges() { if (edge_iterator->result.target < node_iterator->node_id) { + // mark edge as invalid + edge_iterator->result.source = SPECIAL_NODEID; + edge_iterator->result.target = SPECIAL_NODEID; + // FIXME we are skipping edges here: That means the data is broken! ++edge_iterator; continue; @@ -246,12 +263,113 @@ void ExtractionContainers::PrepareEdges() return -1.0; }(edge_iterator->weight_data); - edge_iterator->result.weight = std::max(1, (int)std::floor(weight + .5)); + auto& edge = edge_iterator->result; + edge.weight = std::max(1, (int)std::floor(weight + .5)); + + // assign new node id + auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id); + BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end()); + edge.target = id_iter->second; + + // if source id > target id -> swap + if (edge.source > edge.target) + { + std::swap(edge.source, edge.target); + + // std::swap does not work with bit-fields + bool temp = edge.forward; + edge.forward = edge.backward; + edge.backward = temp; + } + } + else + { + // mark edge as invalid + edge_iterator->result.source = SPECIAL_NODEID; + edge_iterator->result.target = SPECIAL_NODEID; + + // FIXME we should print a warning here. } ++edge_iterator; } TIMER_STOP(compute_weights); std::cout << "ok, after " << TIMER_SEC(compute_weights) << "s" << std::endl; + + // Sort edges by start. + std::cout << "[extractor] Sorting edges by renumbered start ... " << std::flush; + TIMER_START(sort_edges_by_renumbered_start); + stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartThenTargetID(), stxxl_memory); + TIMER_STOP(sort_edges_by_renumbered_start); + std::cout << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s" << std::endl; + + BOOST_ASSERT(all_edges_list.size() > 0); + for (unsigned i = 1; i < all_edges_list.size();) + { + // only invalid edges left + if (all_edges_list[i].result.source == SPECIAL_NODEID) + { + break; + } + + unsigned start_idx = i; + NodeID source = all_edges_list[i].result.source; + NodeID target = all_edges_list[i].result.target; + + int min_forward_weight = std::numeric_limits::max(); + int min_backward_weight = std::numeric_limits::max(); + unsigned min_forward_idx = std::numeric_limits::max(); + unsigned min_backward_idx = std::numeric_limits::max(); + + while (all_edges_list[i].result.source == source && + all_edges_list[i].result.target == target) + { + if (all_edges_list[i].result.forward && all_edges_list[i].result.weight < min_forward_weight) + { + min_forward_idx = i; + } + if (all_edges_list[i].result.backward && all_edges_list[i].result.weight < min_backward_weight) + { + min_backward_idx = i; + } + + // this also increments the outer loop counter! + i++; + } + + BOOST_ASSERT(min_forward_idx == std::numeric_limits::max() || min_forward_idx < i); + BOOST_ASSERT(min_backward_idx == std::numeric_limits::max() || min_backward_idx < i); + + // reset direction for both edges + if (min_forward_idx != std::numeric_limits::max()) + { + all_edges_list[min_forward_idx].result.forward = false; + all_edges_list[min_forward_idx].result.backward = false; + } + if (min_backward_idx != std::numeric_limits::max()) + { + all_edges_list[min_backward_idx].result.forward = false; + all_edges_list[min_backward_idx].result.backward = false; + } + + // set directions that were chosen as min + // note that this needs to come after the ifs above, since + // the minimal forward and backward edge can be the same + if (min_forward_idx != std::numeric_limits::max()) + all_edges_list[min_forward_idx].result.forward = true; + if (min_backward_idx != std::numeric_limits::max()) + all_edges_list[min_backward_idx].result.backward = true; + + // invalidate all unused edges + for (unsigned j = start_idx; j < i; j++) + { + if (j == min_forward_idx || j == min_backward_idx) + { + continue; + } + all_edges_list[j].result.source = SPECIAL_NODEID; + all_edges_list[j].result.target = SPECIAL_NODEID; + } + } } void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const @@ -266,11 +384,13 @@ void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const for (const auto& edge : all_edges_list) { - if (edge.result.weight > 0) + if (edge.result.source == SPECIAL_NODEID || edge.result.target == SPECIAL_NODEID) { - file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge)); - number_of_used_edges++; + continue; } + + file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge)); + number_of_used_edges++; } TIMER_STOP(write_edges); std::cout << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl; @@ -339,6 +459,7 @@ void ExtractionContainers::WriteRestrictions(const std::string& path) const for (const auto &restriction_container : restrictions_list) { if (SPECIAL_NODEID != restriction_container.restriction.from.node && + SPECIAL_NODEID != restriction_container.restriction.via.node && SPECIAL_NODEID != restriction_container.restriction.to.node) { restrictions_out_stream.write((char *)&(restriction_container.restriction), @@ -362,7 +483,7 @@ void ExtractionContainers::PrepareRestrictions() std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl; std::cout << "[extractor] Sorting " << restrictions_list.size() - << " restrictions. by from... " << std::flush; + << " restriction. by from... " << std::flush; TIMER_START(sort_restrictions); stxxl::sort(restrictions_list.begin(), restrictions_list.end(), CmpRestrictionContainerByFrom(), stxxl_memory); @@ -385,23 +506,42 @@ void ExtractionContainers::PrepareRestrictions() if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way) { + SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.from.way; + restrictions_iterator->restriction.from.node = SPECIAL_NODEID; ++restrictions_iterator; continue; } BOOST_ASSERT(way_start_and_end_iterator->way_id == restrictions_iterator->restriction.from.way); + // we do not remap the via id yet, since we will need it for the to node as well const NodeID via_node_id = restrictions_iterator->restriction.via.node; + // check if via is actually valid, if not invalidate + auto via_id_iter = external_to_internal_node_id_map.find(via_node_id); + if(via_id_iter == external_to_internal_node_id_map.end()) + { + SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid node: " << restrictions_iterator->restriction.via.node; + restrictions_iterator->restriction.via.node = SPECIAL_NODEID; + ++restrictions_iterator; + continue; + } + if (way_start_and_end_iterator->first_segment_source_id == via_node_id) { - restrictions_iterator->restriction.from.node = - way_start_and_end_iterator->first_segment_target_id; + // assign new from node id + auto id_iter = external_to_internal_node_id_map.find( + way_start_and_end_iterator->first_segment_target_id); + BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end()); + restrictions_iterator->restriction.from.node = id_iter->second; } else if (way_start_and_end_iterator->last_segment_target_id == via_node_id) { - restrictions_iterator->restriction.from.node = - way_start_and_end_iterator->last_segment_source_id; + // assign new from node id + auto id_iter = external_to_internal_node_id_map.find( + way_start_and_end_iterator->last_segment_source_id); + BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end()); + restrictions_iterator->restriction.from.node = id_iter->second; } ++restrictions_iterator; } @@ -428,8 +568,16 @@ void ExtractionContainers::PrepareRestrictions() ++way_start_and_end_iterator; continue; } + if (restrictions_iterator->restriction.from.node == SPECIAL_NODEID || + restrictions_iterator->restriction.via.node == SPECIAL_NODEID) + { + ++restrictions_iterator; + continue; + } if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way) { + SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.to.way; + restrictions_iterator->restriction.to.way = SPECIAL_NODEID; ++restrictions_iterator; continue; } @@ -437,15 +585,24 @@ void ExtractionContainers::PrepareRestrictions() restrictions_iterator->restriction.to.way); const NodeID via_node_id = restrictions_iterator->restriction.via.node; + // assign new via node id + auto via_id_iter = external_to_internal_node_id_map.find(via_node_id); + BOOST_ASSERT(via_id_iter != external_to_internal_node_id_map.end()); + restrictions_iterator->restriction.via.node = via_id_iter->second; + if (way_start_and_end_iterator->first_segment_source_id == via_node_id) { - restrictions_iterator->restriction.to.node = - way_start_and_end_iterator->first_segment_target_id; + auto to_id_iter = external_to_internal_node_id_map.find( + way_start_and_end_iterator->first_segment_target_id); + BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end()); + restrictions_iterator->restriction.to.node = to_id_iter->second; } else if (way_start_and_end_iterator->last_segment_target_id == via_node_id) { - restrictions_iterator->restriction.to.node = - way_start_and_end_iterator->last_segment_source_id; + auto to_id_iter = external_to_internal_node_id_map.find( + way_start_and_end_iterator->last_segment_source_id); + BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end()); + restrictions_iterator->restriction.to.node = to_id_iter->second; } ++restrictions_iterator; } diff --git a/extractor/extraction_containers.hpp b/extractor/extraction_containers.hpp index 56109def8..444f04f02 100644 --- a/extractor/extraction_containers.hpp +++ b/extractor/extraction_containers.hpp @@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../util/fingerprint.hpp" #include +#include /** * Uses external memory containers from stxxl to store all the data that @@ -73,6 +74,7 @@ class ExtractionContainers STXXLStringVector name_list; STXXLRestrictionsVector restrictions_list; STXXLWayIDStartEndVector way_start_end_id_list; + std::unordered_map external_to_internal_node_id_map; const FingerPrint fingerprint; ExtractionContainers(); diff --git a/extractor/internal_extractor_edge.hpp b/extractor/internal_extractor_edge.hpp index ea76c560b..15f3c0d66 100644 --- a/extractor/internal_extractor_edge.hpp +++ b/extractor/internal_extractor_edge.hpp @@ -105,6 +105,20 @@ struct InternalExtractorEdge } }; +struct CmpEdgeByStartThenTargetID +{ + using value_type = InternalExtractorEdge; + bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const + { + return (lhs.result.source < rhs.result.source) || + ((lhs.result.source == rhs.result.source) && + (lhs.result.target < rhs.result.target)); + } + + value_type max_value() { return InternalExtractorEdge::max_value(); } + value_type min_value() { return InternalExtractorEdge::min_value(); } +}; + struct CmpEdgeByStartID { using value_type = InternalExtractorEdge; diff --git a/tools/components.cpp b/tools/components.cpp index d0fcd79ab..660d9225e 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -76,22 +76,19 @@ void DeleteFileIfExists(const std::string &file_name) } } -void LoadRestrictions(const char* path, - std::unique_ptr> ext_to_int_id_map, - std::vector& restriction_list) +void LoadRestrictions(const char* path, std::vector& restriction_list) { std::ifstream input_stream(path, std::ios::binary); if (!input_stream.is_open()) { throw osrm::exception("Cannot open restriction file"); } - loadRestrictionsFromFile(input_stream, *ext_to_int_id_map, restriction_list); + loadRestrictionsFromFile(input_stream, restriction_list); } std::size_t LoadGraph(const char* path, std::vector& coordinate_list, std::vector& barrier_node_list, - std::unordered_map& ext_to_int_id_map, std::vector& graph_edge_list) { std::ifstream input_stream(path, std::ifstream::in | std::ifstream::binary); @@ -106,10 +103,9 @@ std::size_t LoadGraph(const char* path, auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list, traffic_light_node_list, - coordinate_list, - ext_to_int_id_map); + coordinate_list); - loadEdgesFromFile(input_stream, ext_to_int_id_map, edge_list); + loadEdgesFromFile(input_stream, edge_list); traffic_light_node_list.clear(); traffic_light_node_list.shrink_to_fit(); @@ -142,7 +138,6 @@ int main(int argc, char *argv[]) std::vector coordinate_list; std::vector restriction_list; std::vector barrier_node_list; - auto ext_to_int_id_map = osrm::make_unique>(); LogPolicy::GetInstance().Unmute(); try @@ -158,8 +153,8 @@ int main(int argc, char *argv[]) SimpleLogger().Write() << "Using restrictions from file: " << argv[2]; std::vector graph_edge_list; - auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, *ext_to_int_id_map, graph_edge_list); - LoadRestrictions(argv[2], std::move(ext_to_int_id_map), restriction_list); + auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, graph_edge_list); + LoadRestrictions(argv[2], restriction_list); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); const auto graph = std::make_shared(number_of_nodes, graph_edge_list); diff --git a/util/graph_loader.hpp b/util/graph_loader.hpp index 0736775b9..8d7cdd0fb 100644 --- a/util/graph_loader.hpp +++ b/util/graph_loader.hpp @@ -58,7 +58,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * we need to renumber it to the new internal id. */ unsigned loadRestrictionsFromFile(std::istream& input_stream, - const std::unordered_map& ext_to_int_id_map, std::vector& restriction_list) { const FingerPrint fingerprint_orig; @@ -79,38 +78,6 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream, number_of_usable_restrictions * sizeof(TurnRestriction)); } - // renumber ids referenced in restrictions - for (TurnRestriction ¤t_restriction : restriction_list) - { - auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node); - if (internal_id_iter == ext_to_int_id_map.end()) - { - SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node - << " of restriction"; - continue; - } - current_restriction.from.node = internal_id_iter->second; - - internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node); - if (internal_id_iter == ext_to_int_id_map.end()) - { - SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node - << " of restriction"; - continue; - } - - current_restriction.via.node = internal_id_iter->second; - - internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node); - if (internal_id_iter == ext_to_int_id_map.end()) - { - SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node - << " of restriction"; - continue; - } - current_restriction.to.node = internal_id_iter->second; - } - return number_of_usable_restrictions; } @@ -119,14 +86,12 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream, * Reads the beginning of an .osrm file and produces: * - list of barrier nodes * - list of traffic lights - * - index to original node id map - * - original node id to index map + * - nodes indexed by their internal (non-osm) id */ NodeID loadNodesFromFile(std::istream &input_stream, std::vector &barrier_node_list, std::vector &traffic_light_node_list, - std::vector &int_to_ext_node_id_map, - std::unordered_map &ext_to_int_id_map) + std::vector &node_array) { const FingerPrint fingerprint_orig; FingerPrint fingerprint_loaded; @@ -146,9 +111,7 @@ NodeID loadNodesFromFile(std::istream &input_stream, for (NodeID i = 0; i < n; ++i) { input_stream.read(reinterpret_cast(¤t_node), sizeof(ExternalMemoryNode)); - int_to_ext_node_id_map.emplace_back(current_node.lat, current_node.lon, - current_node.node_id); - ext_to_int_id_map.emplace(current_node.node_id, i); + node_array.emplace_back(current_node.lat, current_node.lon, current_node.node_id); if (current_node.barrier) { barrier_node_list.emplace_back(i); @@ -167,122 +130,27 @@ NodeID loadNodesFromFile(std::istream &input_stream, } /** - * Reads a .osrm file and produces the edges. Edges reference nodes in the old - * OSM based format, we need to renumber it here. + * Reads a .osrm file and produces the edges. */ NodeID loadEdgesFromFile(std::istream &input_stream, - const std::unordered_map &ext_to_int_id_map, std::vector &edge_list) { EdgeID m; input_stream.read(reinterpret_cast(&m), sizeof(unsigned)); - edge_list.reserve(m); + edge_list.resize(m); SimpleLogger().Write() << " and " << m << " edges "; - NodeBasedEdge edge(0, 0, 0, 0, false, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); - for (EdgeID i = 0; i < m; ++i) + input_stream.read((char *) edge_list.data(), m * sizeof(NodeBasedEdge)); + +#ifndef NDEBUG + for (const auto& edge : edge_list) { - input_stream.read(reinterpret_cast(&edge), sizeof(NodeBasedEdge)); BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight"); - BOOST_ASSERT_MSG(edge.forward || edge.backward, "loaded null weight"); - BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded null weight"); - - // translate the external NodeIDs to internal IDs - auto internal_id_iter = ext_to_int_id_map.find(edge.source); - if (ext_to_int_id_map.find(edge.source) == ext_to_int_id_map.end()) - { -#ifndef NDEBUG - SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << edge.source; -#endif - continue; - } - edge.source = internal_id_iter->second; - internal_id_iter = ext_to_int_id_map.find(edge.target); - if (ext_to_int_id_map.find(edge.target) == ext_to_int_id_map.end()) - { -#ifndef NDEBUG - SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << edge.target; -#endif - continue; - } - edge.target = internal_id_iter->second; - BOOST_ASSERT_MSG(edge.source != SPECIAL_NODEID && edge.target != SPECIAL_NODEID, - "nonexisting source or target"); - - if (edge.source > edge.target) - { - std::swap(edge.source, edge.target); - - // std::swap does not work with bit-fields - bool temp = edge.forward; - edge.forward = edge.backward; - edge.backward = temp; - } - - edge_list.push_back(edge); + BOOST_ASSERT_MSG(edge.forward || edge.backward, "loaded invalid direction"); + BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible"); } +#endif - tbb::parallel_sort(edge_list.begin(), edge_list.end()); - - // Removes multi-edges between nodes - for (unsigned i = 1; i < edge_list.size(); ++i) - { - if ((edge_list[i - 1].target == edge_list[i].target) && - (edge_list[i - 1].source == edge_list[i].source)) - { - const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) && - (edge_list[i - 1].backward == edge_list[i].backward); - const bool edge_flags_are_superset1 = - (edge_list[i - 1].forward && edge_list[i - 1].backward) && - (edge_list[i].forward != edge_list[i].backward); - const bool edge_flags_are_superset_2 = - (edge_list[i].forward && edge_list[i].backward) && - (edge_list[i - 1].forward != edge_list[i - 1].backward); - - if (edge_flags_equivalent) - { - edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight); - edge_list[i - 1].source = SPECIAL_NODEID; - } - else if (edge_flags_are_superset1) - { - if (edge_list[i - 1].weight <= edge_list[i].weight) - { - // edge i-1 is smaller and goes in both directions. Throw away the other edge - edge_list[i].source = SPECIAL_NODEID; - } - else - { - // edge i-1 is open in both directions, but edge i is smaller in one direction. - // Close edge i-1 in this direction - edge_list[i - 1].forward = !edge_list[i].forward; - edge_list[i - 1].backward = !edge_list[i].backward; - } - } - else if (edge_flags_are_superset_2) - { - if (edge_list[i - 1].weight <= edge_list[i].weight) - { - // edge i-1 is smaller for one direction. edge i is open in both. close edge i - // in the other direction - edge_list[i].forward = !edge_list[i - 1].forward; - edge_list[i].backward = !edge_list[i - 1].backward; - } - else - { - // edge i is smaller and goes in both direction. Throw away edge i-1 - edge_list[i - 1].source = SPECIAL_NODEID; - } - } - } - } - const auto new_end_iter = - std::remove_if(edge_list.begin(), edge_list.end(), [](const NodeBasedEdge &edge) - { - return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID; - }); - edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates. - edge_list.shrink_to_fit(); SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges"; return m;