From 8135f089583e458b4946332c6e348fe282a4a9c4 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Thu, 27 Jul 2017 11:42:13 +0200 Subject: [PATCH] restructure for review remarks --- CHANGELOG.md | 5 +- features/car/restrictions.feature | 2 + .../extractor/edge_based_graph_factory.hpp | 14 +- include/extractor/extraction_containers.hpp | 5 +- include/extractor/restriction.hpp | 54 ++----- include/extractor/restriction_compressor.hpp | 6 +- include/extractor/serialization.hpp | 10 +- include/extractor/way_restriction_map.hpp | 24 +-- include/util/typedefs.hpp | 6 + src/extractor/edge_based_graph_factory.cpp | 144 ++++++++---------- src/extractor/extraction_containers.cpp | 73 ++++----- src/extractor/restriction_compressor.cpp | 65 ++++---- src/extractor/restriction_filter.cpp | 5 +- src/extractor/way_restriction_map.cpp | 47 +++--- 14 files changed, 222 insertions(+), 238 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d452afd8ce..c77ae8031c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,10 @@ - Profiles must return a hash of profile functions. This makes it easier for profiles to include each other. - Guidance: add support for throughabouts - Bugfixes - - Properly save/retrieve datasource annotations for road segments ([#4346](https://github.com/Project-OSRM/osrm-backend/issues/4346)) + - Properly save/retrieve datasource annotations for road segments ([#4346](https://github.com/Project-OSRM/osrm-backend/issues/4346) + - Algorithm) + - BREAKING: the file format requires re-processing due to the changes on via-ways + - Added support for via-way restrictions # 5.9.2 - API: diff --git a/features/car/restrictions.feature b/features/car/restrictions.feature index f21837287f8..b5e90e2859c 100644 --- a/features/car/restrictions.feature +++ b/features/car/restrictions.feature @@ -639,6 +639,8 @@ Feature: Car - Turn restrictions | | \ / i - d - e - - - - - - - - - - - - - - - - - """ + # The long distances here are required to make other turns undesriable in comparison to the restricted turns. + # Otherwise they might just be picked without the actual turns being restricted And the ways | nodes | oneway | diff --git a/include/extractor/edge_based_graph_factory.hpp b/include/extractor/edge_based_graph_factory.hpp index 3edbd20ea60..972eabe9597 100644 --- a/include/extractor/edge_based_graph_factory.hpp +++ b/include/extractor/edge_based_graph_factory.hpp @@ -92,7 +92,7 @@ class EdgeBasedGraphFactory const std::string &turn_duration_penalties_filename, const std::string &turn_penalties_index_filename, const std::string &cnbg_ebg_mapping_path, - const RestrictionMap &restriction_map, + const RestrictionMap &node_restriction_map, const WayRestrictionMap &way_restriction_map); // The following get access functions destroy the content in the factory @@ -137,9 +137,11 @@ class EdgeBasedGraphFactory EdgeBasedNodeDataContainer m_edge_based_node_container; util::DeallocatingVector m_edge_based_edge_list; - // the number of edge-based nodes is mostly made up out of the edges in the node-based graph. + // The number of edge-based nodes is mostly made up out of the edges in the node-based graph. // Any edge in the node-based graph represents a node in the edge-based graph. In addition, we // add a set of artificial edge-based nodes into the mix to model via-way turn restrictions. + // See https://github.com/Project-OSRM/osrm-backend/issues/2681#issuecomment-313080353 for + // reference std::uint64_t m_number_of_edge_based_nodes; const std::vector &m_coordinates; @@ -157,15 +159,21 @@ class EdgeBasedGraphFactory unsigned RenumberEdges(); + // During the generation of the edge-expanded nodes, we need to also generate duplicates that + // represent state during via-way restrictions (see + // https://github.com/Project-OSRM/osrm-backend/issues/2681#issuecomment-313080353). Access to + // the information on what to duplicate and how is provided via the way_restriction_map std::vector GenerateEdgeExpandedNodes(const WayRestrictionMap &way_restriction_map); + // Edge-expanded edges are generate for all valid turns. The validity can be checked via the + // restriction maps void GenerateEdgeExpandedEdges(ScriptingEnvironment &scripting_environment, const std::string &original_edge_data_filename, const std::string &turn_lane_data_filename, const std::string &turn_weight_penalties_filename, const std::string &turn_duration_penalties_filename, const std::string &turn_penalties_index_filename, - const RestrictionMap &restriction_map, + const RestrictionMap &node_restriction_map, const WayRestrictionMap &way_restriction_map); NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v); diff --git a/include/extractor/extraction_containers.hpp b/include/extractor/extraction_containers.hpp index cd30cffa05c..82387a8a6e5 100644 --- a/include/extractor/extraction_containers.hpp +++ b/include/extractor/extraction_containers.hpp @@ -51,7 +51,10 @@ class ExtractionContainers unsigned max_internal_node_id; - // list of restrictions before we transform them into the output types + // list of restrictions before we transform them into the output types. Input containers + // reference OSMNodeIDs. We can only transform them to the correct internal IDs after we've read + // everything. Without a multi-parse approach, we have to remember the output restrictions + // before converting them to the internal formats std::vector restrictions_list; // turn restrictions split into conditional and unconditional turn restrictions diff --git a/include/extractor/restriction.hpp b/include/extractor/restriction.hpp index 9e1764278a7..4f7f59a0e60 100644 --- a/include/extractor/restriction.hpp +++ b/include/extractor/restriction.hpp @@ -5,7 +5,7 @@ #include "util/opening_hours.hpp" #include "util/typedefs.hpp" -#include +#include "mapbox/variant.hpp" #include namespace osrm @@ -55,21 +55,21 @@ enum RestrictionType struct InputTurnRestriction { // keep in the same order as the turn restrictions below - boost::variant node_or_way; + mapbox::util::variant node_or_way; bool is_only; OSMWayID From() const { return node_or_way.which() == RestrictionType::NODE_RESTRICTION - ? boost::get(node_or_way).from - : boost::get(node_or_way).from; + ? mapbox::util::get(node_or_way).from + : mapbox::util::get(node_or_way).from; } OSMWayID To() const { return node_or_way.which() == RestrictionType::NODE_RESTRICTION - ? boost::get(node_or_way).to - : boost::get(node_or_way).to; + ? mapbox::util::get(node_or_way).to + : mapbox::util::get(node_or_way).to; } RestrictionType Type() const @@ -81,25 +81,25 @@ struct InputTurnRestriction InputWayRestriction &AsWayRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } const InputWayRestriction &AsWayRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } InputNodeRestriction &AsNodeRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } const InputNodeRestriction &AsNodeRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } }; struct InputConditionalTurnRestriction : InputTurnRestriction @@ -121,12 +121,6 @@ struct NodeRestriction return from != SPECIAL_NODEID && to != SPECIAL_NODEID && via != SPECIAL_NODEID; }; - std::string ToString() const - { - return "From " + std::to_string(from) + " via " + std::to_string(via) + " to " + - std::to_string(to); - } - bool operator==(const NodeRestriction &other) const { return std::tie(from, via, to) == std::tie(other.from, other.via, other.to); @@ -168,7 +162,7 @@ struct WayRestriction struct TurnRestriction { // keep in the same order as the turn restrictions above - boost::variant node_or_way; + mapbox::util::variant node_or_way; bool is_only; // construction for NodeRestrictions @@ -191,25 +185,25 @@ struct TurnRestriction WayRestriction &AsWayRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } const WayRestriction &AsWayRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } NodeRestriction &AsNodeRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } const NodeRestriction &AsNodeRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); - return boost::get(node_or_way); + return mapbox::util::get(node_or_way); } RestrictionType Type() const @@ -250,24 +244,6 @@ struct TurnRestriction return AsNodeRestriction() == other.AsNodeRestriction(); } } - - std::string ToString() const - { - std::string representation; - if (node_or_way.which() == RestrictionType::WAY_RESTRICTION) - { - auto const &way = AsWayRestriction(); - representation = - "In: " + way.in_restriction.ToString() + " Out: " + way.out_restriction.ToString(); - } - else - { - auto const &node = AsNodeRestriction(); - representation = node.ToString(); - } - representation += " is_only: " + std::to_string(is_only); - return representation; - } }; struct ConditionalTurnRestriction : TurnRestriction diff --git a/include/extractor/restriction_compressor.hpp b/include/extractor/restriction_compressor.hpp index 33e0fe71d3a..f3136760cc3 100644 --- a/include/extractor/restriction_compressor.hpp +++ b/include/extractor/restriction_compressor.hpp @@ -32,12 +32,12 @@ class RestrictionCompressor void Compress(const NodeID from, const NodeID via, const NodeID to); private: - // a turn restriction is given as `from head via node to tail`. Edges ending at `head` being + // a turn restriction is given as `from star via node to end`. Edges ending at `head` being // contracted move the head pointer to their respective head. Edges starting at tail move the // tail values to their respective tails. Way turn restrictions are represented by two // node-restrictions, so we can focus on them alone - boost::unordered_multimap heads; - boost::unordered_multimap tails; + boost::unordered_multimap starts; + boost::unordered_multimap ends; }; } // namespace extractor diff --git a/include/extractor/serialization.hpp b/include/extractor/serialization.hpp index 4885e591438..e1fbce8bdb1 100644 --- a/include/extractor/serialization.hpp +++ b/include/extractor/serialization.hpp @@ -186,18 +186,18 @@ inline void write(storage::io::FileWriter &writer, const TurnRestriction &restri writer.WriteOne(restriction.is_only); if (restriction.Type() == RestrictionType::WAY_RESTRICTION) { - write(writer, boost::get(restriction.node_or_way)); + write(writer, mapbox::util::get(restriction.node_or_way)); } else { BOOST_ASSERT(restriction.Type() == RestrictionType::NODE_RESTRICTION); - write(writer, boost::get(restriction.node_or_way)); + write(writer, mapbox::util::get(restriction.node_or_way)); } } inline void write(storage::io::FileWriter &writer, const ConditionalTurnRestriction &restriction) { - write(writer, static_cast(restriction)); + write(writer, static_cast(restriction)); writer.WriteElementCount64(restriction.condition.size()); for (const auto &c : restriction.condition) { @@ -210,9 +210,7 @@ inline void write(storage::io::FileWriter &writer, const ConditionalTurnRestrict inline void read(storage::io::FileReader &reader, ConditionalTurnRestriction &restriction) { - TurnRestriction base; - read(reader, base); - reinterpret_cast(restriction) = std::move(base); + read(reader, static_cast(restriction)); const auto num_conditions = reader.ReadElementCount64(); restriction.condition.resize(num_conditions); for (uint64_t i = 0; i < num_conditions; i++) diff --git a/include/extractor/way_restriction_map.hpp b/include/extractor/way_restriction_map.hpp index 4e105c8af09..4daf9928440 100644 --- a/include/extractor/way_restriction_map.hpp +++ b/include/extractor/way_restriction_map.hpp @@ -23,30 +23,30 @@ class WayRestrictionMap public: struct ViaWay { - std::size_t id; NodeID from; NodeID to; }; WayRestrictionMap(const std::vector &turn_restrictions); - // check if an edge between two nodes is a restricted turn. The check needs to be performed + // Check if an edge between two nodes is a restricted turn. The check needs to be performed to + // find duplicated nodes during the creation of edge-based-edges bool IsViaWay(const NodeID from, const NodeID to) const; - // number of duplicated nodes + // Every via-way results in a duplicated node that is required in the edge-based-graph. This + // count is essentially the same as the number of valid via-way restrictions (except for + // non-only restrictions that share the same in/via combination) std::size_t NumberOfDuplicatedNodes() const; - // returns a representative for the duplicated way, consisting of the representative ID (first + // Returns a representative for each duplicated node, consisting of the representative ID (first // ID of the nodes restrictions) and the from/to vertices of the via-way // This is used to construct edge based nodes that act as intermediate nodes. std::vector DuplicatedNodeRepresentatives() const; // Access all duplicated NodeIDs for a set of nodes indicating a via way - util::range DuplicatedNodeIDs(const NodeID from, const NodeID to) const; + util::range DuplicatedNodeIDs(const NodeID from, const NodeID to) const; // check whether a turn onto a given node is restricted, when coming from a duplicated node - bool IsRestricted(std::size_t duplicated_node, const NodeID to) const; - - TurnRestriction const &GetRestriction(std::size_t) const; + bool IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const; // changes edge_based_node to the correct duplicated_node_id in case node_based_from, // node_based_via, node_based_to can be identified with a restriction group @@ -57,7 +57,7 @@ class WayRestrictionMap const NodeID number_of_edge_based_nodes) const; private: - std::size_t AsDuplicatedNodeID(const std::size_t restriction_id) const; + DuplicatedNodeID AsDuplicatedNodeID(const RestrictionID restriction_id) const; // access all restrictions that have the same starting way and via way. Any duplicated node // represents the same in-way + via-way combination. This vector contains data about all @@ -75,10 +75,10 @@ class WayRestrictionMap // // EBN: 0 . | 2 | 3 | 4 ... // duplicated node groups: ... | 5 | 7 | ... - std::vector duplicated_node_groups; + std::vector duplicated_node_groups; - boost::unordered_multimap, std::size_t> restriction_starts; - boost::unordered_multimap, std::size_t> restriction_ends; + boost::unordered_multimap, RestrictionID> restriction_starts; + boost::unordered_multimap, RestrictionID> restriction_ends; std::vector restriction_data; }; diff --git a/include/util/typedefs.hpp b/include/util/typedefs.hpp index 1ba65b2c0f6..2bb80855087 100644 --- a/include/util/typedefs.hpp +++ b/include/util/typedefs.hpp @@ -45,12 +45,18 @@ struct osm_node_id struct osm_way_id { }; +struct duplicated_node +{ +}; } using OSMNodeID = osrm::Alias; static_assert(std::is_pod(), "OSMNodeID is not a valid alias"); using OSMWayID = osrm::Alias; static_assert(std::is_pod(), "OSMWayID is not a valid alias"); +using DuplicatedNodeID = std::uint64_t; +using RestrictionID = std::uint64_t; + static const OSMNodeID SPECIAL_OSM_NODEID = OSMNodeID{std::numeric_limits::max()}; static const OSMWayID SPECIAL_OSM_WAYID = diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index e7da76da654..3f4ec96f35f 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -194,7 +194,7 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment, const std::string &turn_duration_penalties_filename, const std::string &turn_penalties_index_filename, const std::string &cnbg_ebg_mapping_path, - const RestrictionMap &restriction_map, + const RestrictionMap &node_restriction_map, const WayRestrictionMap &way_restriction_map) { TIMER_START(renumber); @@ -215,7 +215,7 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment, turn_weight_penalties_filename, turn_duration_penalties_filename, turn_penalties_index_filename, - restriction_map, + node_restriction_map, way_restriction_map); TIMER_STOP(generate_edges); @@ -228,7 +228,7 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment, /// Renumbers all _forward_ edges and sets the edge_id. /// A specific numbering is not important. Any unique ID will do. -/// Returns the number of edge based nodes. +/// Returns the number of edge-based nodes. unsigned EdgeBasedGraphFactory::RenumberEdges() { // heuristic: node-based graph node is a simple intersection with four edges (edge-based nodes) @@ -363,8 +363,10 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re BOOST_ASSERT(m_edge_based_node_segments.size() == m_edge_based_node_is_startpoint.size()); BOOST_ASSERT(m_number_of_edge_based_nodes == m_edge_based_node_weights.size()); - util::Log() << "Generated " << m_number_of_edge_based_nodes << " nodes and " - << m_edge_based_node_segments.size() << " segments in edge-expanded graph"; + util::Log() << "Generated " << m_number_of_edge_based_nodes << " nodes (" + << way_restriction_map.NumberOfDuplicatedNodes() + << " of which are duplicates) and " << m_edge_based_node_segments.size() + << " segments in edge-expanded graph"; return mapping; } @@ -377,7 +379,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( const std::string &turn_weight_penalties_filename, const std::string &turn_duration_penalties_filename, const std::string &turn_penalties_index_filename, - const RestrictionMap &restriction_map, + const RestrictionMap &node_restriction_map, const WayRestrictionMap &way_restriction_map) { @@ -399,7 +401,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( SuffixTable street_name_suffix_table(scripting_environment); guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_coordinates, - restriction_map, + node_restriction_map, m_barrier_nodes, m_compressed_edge_container, name_table, @@ -492,24 +494,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( std::vector delayed_data; }; - // add into delayed data - const auto delayed_inserter = [](const auto &edge_with_data, auto &buffer) { - buffer.delayed_data.push_back(edge_with_data); - }; - - // add into main data - const auto continuous_inserter = [](const auto &edge_with_data, auto &buffer) { - buffer.continuous_data.edges_list.push_back(edge_with_data.edge); - buffer.continuous_data.turn_indexes.push_back(edge_with_data.turn_index); - buffer.continuous_data.turn_weight_penalties.push_back( - edge_with_data.turn_weight_penalty); - buffer.continuous_data.turn_duration_penalties.push_back( - edge_with_data.turn_duration_penalty); - buffer.continuous_data.turn_data_container.push_back(edge_with_data.turn_data); - }; - // Generate edges for either artificial nodes or the main graph - const auto generate_edges = [this, &scripting_environment, weight_multiplier]( + const auto generate_edge = [this, &scripting_environment, weight_multiplier]( // what nodes will be used? In most cases this will be the id stored in the edge_data. // In case of duplicated nodes (e.g. due to via-way restrictions), one/both of these // might refer to a newly added edge based node @@ -522,11 +508,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( const auto node_based_edge_to, const auto &intersection, const auto &turn, - const auto entry_class_id, - // we require a sorted output, additional nodes are collected and added after the - // sorting is done Here we can specify how/where to add the data - auto inserter, - auto &output_buffer) { + const auto entry_class_id) { const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(node_based_edge_from); const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(node_based_edge_to); @@ -593,11 +575,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( lookup::TurnIndexBlock turn_index_block = {from_node, via_node, to_node}; // insert data into the designated buffer - inserter( - EdgeWithData{ - edge_based_edge, turn_index_block, weight_penalty, duration_penalty, turn_data}, - output_buffer); - + return EdgeWithData{ + edge_based_edge, turn_index_block, weight_penalty, duration_penalty, turn_data}; }; // Second part of the pipeline is where the intersection analysis is done for @@ -735,17 +714,28 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( m_node_based_graph->GetTarget(turn.eid), m_number_of_edge_based_nodes); - generate_edges(edge_data1.edge_id, - target_id, - node_along_road_entering, - incoming_edge, - node_at_center_of_intersection, - turn.eid, - intersection, - turn, - entry_class_id, - continuous_inserter, - *buffer); + { // scope to forget edge_with_data after + const auto edge_with_data = + generate_edge(edge_data1.edge_id, + target_id, + node_along_road_entering, + incoming_edge, + node_at_center_of_intersection, + turn.eid, + intersection, + turn, + entry_class_id); + + buffer->continuous_data.edges_list.push_back(edge_with_data.edge); + buffer->continuous_data.turn_indexes.push_back( + edge_with_data.turn_index); + buffer->continuous_data.turn_weight_penalties.push_back( + edge_with_data.turn_weight_penalty); + buffer->continuous_data.turn_duration_penalties.push_back( + edge_with_data.turn_duration_penalty); + buffer->continuous_data.turn_data_container.push_back( + edge_with_data.turn_data); + } // when turning off a a via-way turn restriction, we need to not only // handle the normal edges for the way, but also add turns for every @@ -775,7 +765,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( if (is_restricted) return; - generate_edges( + // add into delayed data + auto edge_with_data = generate_edge( NodeID(from_id), m_node_based_graph->GetEdgeData(turn.eid).edge_id, node_along_road_entering, @@ -784,10 +775,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( turn.eid, intersection, turn, - entry_class_id, - delayed_inserter, - *buffer); + entry_class_id); + buffer->delayed_data.push_back(std::move(edge_with_data)); }; std::for_each(duplicated_nodes.begin(), @@ -812,38 +802,38 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( std::vector delayed_data; - auto const append_data_to_output = [&](IntersectionData const &data) { - // NOTE: potential overflow here if we hit 2^32 routable edges - m_edge_based_edge_list.append(data.edges_list.begin(), data.edges_list.end()); - - BOOST_ASSERT(m_edge_based_edge_list.size() <= std::numeric_limits::max()); - - turn_weight_penalties.insert(turn_weight_penalties.end(), - data.turn_weight_penalties.begin(), - data.turn_weight_penalties.end()); - turn_duration_penalties.insert(turn_duration_penalties.end(), - data.turn_duration_penalties.begin(), - data.turn_duration_penalties.end()); - turn_data_container.append(data.turn_data_container); - turn_indexes_write_buffer.insert(turn_indexes_write_buffer.end(), - data.turn_indexes.begin(), - data.turn_indexes.end()); - - // Buffer writes to reduce syscall count - if (turn_indexes_write_buffer.size() >= TURN_INDEX_WRITE_BUFFER_SIZE) - { - turn_penalties_index_file.WriteFrom(turn_indexes_write_buffer.data(), - turn_indexes_write_buffer.size()); - turn_indexes_write_buffer.clear(); - } - }; - // Last part of the pipeline puts all the calculated data into the serial buffers tbb::filter_t, void> output_stage( tbb::filter::serial_in_order, [&](const std::shared_ptr buffer) { nodes_completed += buffer->nodes_processed; progress.PrintStatus(nodes_completed); - append_data_to_output(buffer->continuous_data); + + // for readability + const auto &data = buffer->continuous_data; + // NOTE: potential overflow here if we hit 2^32 routable edges + m_edge_based_edge_list.append(data.edges_list.begin(), data.edges_list.end()); + + BOOST_ASSERT(m_edge_based_edge_list.size() <= std::numeric_limits::max()); + + turn_weight_penalties.insert(turn_weight_penalties.end(), + data.turn_weight_penalties.begin(), + data.turn_weight_penalties.end()); + turn_duration_penalties.insert(turn_duration_penalties.end(), + data.turn_duration_penalties.begin(), + data.turn_duration_penalties.end()); + turn_data_container.append(data.turn_data_container); + turn_indexes_write_buffer.insert(turn_indexes_write_buffer.end(), + data.turn_indexes.begin(), + data.turn_indexes.end()); + + // Buffer writes to reduce syscall count + if (turn_indexes_write_buffer.size() >= TURN_INDEX_WRITE_BUFFER_SIZE) + { + turn_penalties_index_file.WriteFrom(turn_indexes_write_buffer.data(), + turn_indexes_write_buffer.size()); + turn_indexes_write_buffer.clear(); + } + delayed_data.insert( delayed_data.end(), buffer->delayed_data.begin(), buffer->delayed_data.end()); }); @@ -927,7 +917,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( util::Log() << " contains " << m_edge_based_edge_list.size() << " edges"; util::Log() << " skips " << restricted_turns_counter << " turns, " "defined by " - << restriction_map.size() << " restrictions"; + << node_restriction_map.size() << " restrictions"; util::Log() << " skips " << skipped_uturns_counter << " U turns"; util::Log() << " skips " << skipped_barrier_turns_counter << " turns over barriers"; } diff --git a/src/extractor/extraction_containers.cpp b/src/extractor/extraction_containers.cpp index df805522e00..9f771d226b0 100644 --- a/src/extractor/extraction_containers.cpp +++ b/src/extractor/extraction_containers.cpp @@ -660,41 +660,44 @@ void ExtractionContainers::PrepareRestrictions() // contain the start/end nodes of each way that is part of an restriction std::unordered_map referenced_ways; - // enter invalid IDs into the above maps to indicate that we want to find out about start/end - // nodes of these ways - const auto mark_ids = [&](auto const &turn_restriction) { - FirstAndLastSegmentOfWay dummy_segment{ - MAX_OSM_WAYID, MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID}; - if (turn_restriction.Type() == RestrictionType::WAY_RESTRICTION) - { - const auto &way = turn_restriction.AsWayRestriction(); - referenced_ways[way.from] = dummy_segment; - referenced_ways[way.to] = dummy_segment; - referenced_ways[way.via] = dummy_segment; - } - else - { - BOOST_ASSERT(turn_restriction.Type() == RestrictionType::NODE_RESTRICTION); - const auto &node = turn_restriction.AsNodeRestriction(); - referenced_ways[node.from] = dummy_segment; - referenced_ways[node.to] = dummy_segment; - } - }; - - // update the values for all edges already sporting SPECIAL_NODEID - const auto set_ids = [&](auto const &start_end) { - auto itr = referenced_ways.find(start_end.way_id); - if (itr != referenced_ways.end()) - itr->second = start_end; - }; - // prepare for extracting source/destination nodes for all restrictions { util::UnbufferedLog log; log << "Collecting start/end information on " << restrictions_list.size() << " restrictions..."; TIMER_START(prepare_restrictions); + + const auto mark_ids = [&](auto const &turn_restriction) { + FirstAndLastSegmentOfWay dummy_segment{ + MAX_OSM_WAYID, MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID}; + if (turn_restriction.Type() == RestrictionType::WAY_RESTRICTION) + { + const auto &way = turn_restriction.AsWayRestriction(); + referenced_ways[way.from] = dummy_segment; + referenced_ways[way.to] = dummy_segment; + referenced_ways[way.via] = dummy_segment; + } + else + { + BOOST_ASSERT(turn_restriction.Type() == RestrictionType::NODE_RESTRICTION); + const auto &node = turn_restriction.AsNodeRestriction(); + referenced_ways[node.from] = dummy_segment; + referenced_ways[node.to] = dummy_segment; + } + }; + std::for_each(restrictions_list.begin(), restrictions_list.end(), mark_ids); + + // enter invalid IDs into the above maps to indicate that we want to find out about + // start/end + // nodes of these ways + // update the values for all edges already sporting SPECIAL_NODEID + const auto set_ids = [&](auto const &start_end) { + auto itr = referenced_ways.find(start_end.way_id); + if (itr != referenced_ways.end()) + itr->second = start_end; + }; + std::for_each(way_start_end_id_list.cbegin(), way_start_end_id_list.cend(), set_ids); TIMER_STOP(prepare_restrictions); log << "ok, after " << TIMER_SEC(prepare_restrictions) << "s"; @@ -710,8 +713,6 @@ void ExtractionContainers::PrepareRestrictions() return internal; }; - // Given: - // a -- b - ????????? - c -- d // Given // a -- b - ????????? - c -- d as via segment // and either @@ -720,6 +721,8 @@ void ExtractionContainers::PrepareRestrictions() // (d,e) or (j,a) as entry-segment auto const find_node_restriction = [&](auto const &segment, auto const &via_segment, auto const via_node) { + // In case of way-restrictions, via-node will be set to MAX_OSM_NODEID to signal that + // the node is not present. // connected at the front of the segment if (via_node == MAX_OSM_NODEID || segment.first_segment_source_id == via_node) { @@ -779,8 +782,10 @@ void ExtractionContainers::PrepareRestrictions() return find_node_restriction(from_segment_itr->second, to_segment_itr->second, via_node); }; - // transform an OSMRestriction (based on WayIDs) into an OSRM restriction (base on NodeIDs) - // returns true on successful transformation, false in case of invalid references + // Transform an OSMRestriction (based on WayIDs) into an OSRM restriction (base on NodeIDs). + // Returns true on successful transformation, false in case of invalid references. + // Based on the auto type deduction, this transfor handles both conditional and unconditional + // turn restrictions. const auto transform = [&](const auto &external_type, auto &internal_type) { if (external_type.Type() == RestrictionType::WAY_RESTRICTION) { @@ -837,7 +842,7 @@ void ExtractionContainers::PrepareRestrictions() TurnRestriction restriction; restriction.is_only = external_restriction.is_only; if (transform(external_restriction, restriction)) - unconditional_turn_restrictions.push_back(restriction); + unconditional_turn_restrictions.push_back(std::move(restriction)); } // conditional turn restriction else @@ -846,7 +851,7 @@ void ExtractionContainers::PrepareRestrictions() restriction.is_only = external_restriction.is_only; restriction.condition = std::move(external_restriction.condition); if (transform(external_restriction, restriction)) - conditional_turn_restrictions.push_back(restriction); + conditional_turn_restrictions.push_back(std::move(restriction)); } }; diff --git a/src/extractor/restriction_compressor.cpp b/src/extractor/restriction_compressor.cpp index 25ed7515599..6da820f4187 100644 --- a/src/extractor/restriction_compressor.cpp +++ b/src/extractor/restriction_compressor.cpp @@ -12,13 +12,13 @@ namespace extractor RestrictionCompressor::RestrictionCompressor(std::vector &restrictions) { - // add a node restriction ptr to the heads/tails maps, needs to be a reference! + // add a node restriction ptr to the starts/ends maps, needs to be a reference! auto index = [&](auto &element) { - heads.insert(std::make_pair(element.from, &element)); - tails.insert(std::make_pair(element.to, &element)); + starts.insert(std::make_pair(element.from, &element)); + ends.insert(std::make_pair(element.to, &element)); }; // !needs to be reference, so we can get the correct address - const auto index_heads_and_tails = [&](auto &restriction) { + const auto index_starts_and_ends = [&](auto &restriction) { if (restriction.Type() == RestrictionType::WAY_RESTRICTION) { auto &way_restriction = restriction.AsWayRestriction(); @@ -33,21 +33,21 @@ RestrictionCompressor::RestrictionCompressor(std::vector &restr } }; - // add all restrictions as their respective head-tail pointers - std::for_each(restrictions.begin(), restrictions.end(), index_heads_and_tails); + // add all restrictions as their respective startend pointers + std::for_each(restrictions.begin(), restrictions.end(), index_starts_and_ends); } void RestrictionCompressor::Compress(const NodeID from, const NodeID via, const NodeID to) { - const auto get_value = [](const auto pair) { return pair.second; }; - - // extract all head ptrs and move them from via to from. - auto all_heads_range = heads.equal_range(via); - std::vector head_ptrs; - std::transform( - all_heads_range.first, all_heads_range.second, std::back_inserter(head_ptrs), get_value); - - const auto update_head = [&](auto ptr) { + // extract all startptrs and move them from via to from. + auto all_starts_range = starts.equal_range(via); + std::vector start_ptrs; + std::transform(all_starts_range.first, + all_starts_range.second, + std::back_inserter(start_ptrs), + [](const auto pair) { return pair.second; }); + + const auto update_start = [&](auto ptr) { // ____ | from - p.from | via - p.via | to - p.to | ____ BOOST_ASSERT(ptr->from == via); if (ptr->via == to) @@ -62,21 +62,23 @@ void RestrictionCompressor::Compress(const NodeID from, const NodeID via, const } }; - std::for_each(head_ptrs.begin(), head_ptrs.end(), update_head); - - const auto reinsert_head = [&](auto ptr) { heads.insert(std::make_pair(ptr->from, ptr)); }; + std::for_each(start_ptrs.begin(), start_ptrs.end(), update_start); // update the ptrs in our mapping - heads.erase(via); - std::for_each(head_ptrs.begin(), head_ptrs.end(), reinsert_head); + starts.erase(via); - // extract all tail ptrs and move them from via to to - auto all_tails_range = tails.equal_range(via); - std::vector tail_ptrs; - std::transform( - all_tails_range.first, all_tails_range.second, std::back_inserter(tail_ptrs), get_value); + const auto reinsert_start = [&](auto ptr) { starts.insert(std::make_pair(ptr->from, ptr)); }; + std::for_each(start_ptrs.begin(), start_ptrs.end(), reinsert_start); - const auto update_tail = [&](auto ptr) { + // extract all end ptrs and move them from via to to + auto all_ends_range = ends.equal_range(via); + std::vector end_ptrs; + std::transform(all_ends_range.first, + all_ends_range.second, + std::back_inserter(end_ptrs), + [](const auto pair) { return pair.second; }); + + const auto update_end = [&](auto ptr) { BOOST_ASSERT(ptr->to == via); // p.from | ____ - p.via | from - p.to | via - ____ | to if (ptr->via == from) @@ -90,14 +92,13 @@ void RestrictionCompressor::Compress(const NodeID from, const NodeID via, const ptr->to = from; } }; + std::for_each(end_ptrs.begin(), end_ptrs.end(), update_end); - const auto reinsert_tail = [&](auto ptr) { tails.insert(std::make_pair(ptr->to, ptr)); }; - - std::for_each(tail_ptrs.begin(), tail_ptrs.end(), update_tail); + // update end ptrs in mapping + ends.erase(via); - // update tail ptrs in mapping - tails.erase(via); - std::for_each(tail_ptrs.begin(), tail_ptrs.end(), reinsert_tail); + const auto reinsert_end = [&](auto ptr) { ends.insert(std::make_pair(ptr->to, ptr)); }; + std::for_each(end_ptrs.begin(), end_ptrs.end(), reinsert_end); } } // namespace extractor diff --git a/src/extractor/restriction_filter.cpp b/src/extractor/restriction_filter.cpp index 8a74cefb827..af23d7d10f7 100644 --- a/src/extractor/restriction_filter.cpp +++ b/src/extractor/restriction_filter.cpp @@ -78,8 +78,9 @@ removeInvalidRestrictions(std::vector restrictions, } }; - restrictions.erase(std::remove_if(restrictions.begin(), restrictions.end(), is_invalid), - restrictions.end()); + const auto end_valid_restrictions = + std::remove_if(restrictions.begin(), restrictions.end(), is_invalid); + restrictions.erase(end_valid_restrictions, restrictions.end()); return restrictions; } diff --git a/src/extractor/way_restriction_map.cpp b/src/extractor/way_restriction_map.cpp index ae9dbe380d5..570f926db01 100644 --- a/src/extractor/way_restriction_map.cpp +++ b/src/extractor/way_restriction_map.cpp @@ -1,4 +1,5 @@ #include "extractor/way_restriction_map.hpp" +#include "util/for_each_pair.hpp" #include #include @@ -45,12 +46,10 @@ WayRestrictionMap::WayRestrictionMap(const std::vector &turn_re }; std::for_each(turn_restrictions.begin(), turn_restrictions.end(), extract_restrictions); - const auto as_duplicated_node = - [](auto const &restriction) -> std::tuple { + const auto as_duplicated_node = [](auto const &restriction) { auto &way = restriction.AsWayRestriction(); // group restrictions by the via-way. On same via-ways group by from - return std::make_tuple( - way.in_restriction.via, way.out_restriction.via, way.in_restriction.from); + return std::tie(way.in_restriction.via, way.out_restriction.via, way.in_restriction.from); }; const auto by_duplicated_node = [&](auto const &lhs, auto const &rhs) { @@ -59,16 +58,14 @@ WayRestrictionMap::WayRestrictionMap(const std::vector &turn_re std::sort(restriction_data.begin(), restriction_data.end(), by_duplicated_node); - std::size_t index = 0, duplication_id = 0; // map all way restrictions into access containers - const auto prepare_way_restriction = [this, &index, &duplication_id, as_duplicated_node]( - const auto &restriction) { + for (RestrictionID index = 0; index < restriction_data.size(); ++index) + { + const auto &restriction = restriction_data[index]; const auto &way = restriction.AsWayRestriction(); restriction_starts.insert( std::make_pair(std::make_pair(way.in_restriction.from, way.in_restriction.via), index)); - ++index; }; - std::for_each(restriction_data.begin(), restriction_data.end(), prepare_way_restriction); std::size_t offset = 1; // the first group starts at 0 @@ -81,9 +78,8 @@ WayRestrictionMap::WayRestrictionMap(const std::vector &turn_re if (as_duplicated_node(lhs) != as_duplicated_node(rhs)) duplicated_node_groups.push_back(offset); ++offset; - return false; // continue until the end }; - std::adjacent_find(restriction_data.begin(), restriction_data.end(), add_offset_on_new_groups); + util::for_each_pair(restriction_data.begin(), restriction_data.end(), add_offset_on_new_groups); duplicated_node_groups.push_back(restriction_data.size()); } @@ -110,17 +106,17 @@ bool WayRestrictionMap::IsViaWay(const NodeID from, const NodeID to) const return way.out_restriction.from == from && way.out_restriction.via == to; } -std::size_t WayRestrictionMap::AsDuplicatedNodeID(const std::size_t restriction_id) const +DuplicatedNodeID WayRestrictionMap::AsDuplicatedNodeID(const RestrictionID restriction_id) const { - return std::distance(duplicated_node_groups.begin(), - std::upper_bound(duplicated_node_groups.begin(), - duplicated_node_groups.end(), - restriction_id)) - - 1; + const auto upper_bound_restriction = std::upper_bound( + duplicated_node_groups.begin(), duplicated_node_groups.end(), restriction_id); + const auto distance_to_upper_bound = + std::distance(duplicated_node_groups.begin(), upper_bound_restriction); + return distance_to_upper_bound - 1; } -util::range WayRestrictionMap::DuplicatedNodeIDs(const NodeID from, - const NodeID to) const +util::range WayRestrictionMap::DuplicatedNodeIDs(const NodeID from, + const NodeID to) const { const auto duplicated_node_range_itr = std::equal_range( restriction_data.begin(), restriction_data.end(), std::make_tuple(from, to), FindViaWay()); @@ -129,16 +125,16 @@ util::range WayRestrictionMap::DuplicatedNodeIDs(const NodeID from, return std::distance(restriction_data.begin(), itr); }; - return util::irange( + return util::irange( AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.first)), AsDuplicatedNodeID(as_restriction_id(duplicated_node_range_itr.second))); } -bool WayRestrictionMap::IsRestricted(std::size_t duplicated_node, const NodeID to) const +bool WayRestrictionMap::IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const { // loop over all restrictions associated with the node. Mark as restricted based on // is_only/restricted targets - for (std::size_t restriction_index = duplicated_node_groups[duplicated_node]; + for (RestrictionID restriction_index = duplicated_node_groups[duplicated_node]; restriction_index != duplicated_node_groups[duplicated_node + 1]; ++restriction_index) { @@ -153,11 +149,6 @@ bool WayRestrictionMap::IsRestricted(std::size_t duplicated_node, const NodeID t return false; } -TurnRestriction const &WayRestrictionMap::GetRestriction(const std::size_t id) const -{ - return restriction_data[id]; -} - std::vector WayRestrictionMap::DuplicatedNodeRepresentatives() const { std::vector result; @@ -167,7 +158,7 @@ std::vector WayRestrictionMap::DuplicatedNodeRepresen std::back_inserter(result), [&](auto const representative_id) -> ViaWay { auto &way = restriction_data[representative_id].AsWayRestriction(); - return {representative_id, way.in_restriction.via, way.out_restriction.via}; + return {way.in_restriction.via, way.out_restriction.via}; }); return result; }