restructure for review remarks

This commit is contained in:
Moritz Kobitzsch 2017-07-27 11:42:13 +02:00
parent 645b1ffd75
commit 8135f08958
14 changed files with 221 additions and 237 deletions

View File

@ -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:

View File

@ -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 |

View File

@ -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<EdgeBasedEdge> 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<util::Coordinate> &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<NBGToEBG> 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);

View File

@ -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<InputConditionalTurnRestriction> restrictions_list;
// turn restrictions split into conditional and unconditional turn restrictions

View File

@ -5,7 +5,7 @@
#include "util/opening_hours.hpp"
#include "util/typedefs.hpp"
#include <boost/variant.hpp>
#include "mapbox/variant.hpp"
#include <limits>
namespace osrm
@ -55,21 +55,21 @@ enum RestrictionType
struct InputTurnRestriction
{
// keep in the same order as the turn restrictions below
boost::variant<InputNodeRestriction, InputWayRestriction> node_or_way;
mapbox::util::variant<InputNodeRestriction, InputWayRestriction> node_or_way;
bool is_only;
OSMWayID From() const
{
return node_or_way.which() == RestrictionType::NODE_RESTRICTION
? boost::get<InputNodeRestriction>(node_or_way).from
: boost::get<InputWayRestriction>(node_or_way).from;
? mapbox::util::get<InputNodeRestriction>(node_or_way).from
: mapbox::util::get<InputWayRestriction>(node_or_way).from;
}
OSMWayID To() const
{
return node_or_way.which() == RestrictionType::NODE_RESTRICTION
? boost::get<InputNodeRestriction>(node_or_way).to
: boost::get<InputWayRestriction>(node_or_way).to;
? mapbox::util::get<InputNodeRestriction>(node_or_way).to
: mapbox::util::get<InputWayRestriction>(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<InputWayRestriction>(node_or_way);
return mapbox::util::get<InputWayRestriction>(node_or_way);
}
const InputWayRestriction &AsWayRestriction() const
{
BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION);
return boost::get<InputWayRestriction>(node_or_way);
return mapbox::util::get<InputWayRestriction>(node_or_way);
}
InputNodeRestriction &AsNodeRestriction()
{
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
return boost::get<InputNodeRestriction>(node_or_way);
return mapbox::util::get<InputNodeRestriction>(node_or_way);
}
const InputNodeRestriction &AsNodeRestriction() const
{
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
return boost::get<InputNodeRestriction>(node_or_way);
return mapbox::util::get<InputNodeRestriction>(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<NodeRestriction, WayRestriction> node_or_way;
mapbox::util::variant<NodeRestriction, WayRestriction> 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<WayRestriction>(node_or_way);
return mapbox::util::get<WayRestriction>(node_or_way);
}
const WayRestriction &AsWayRestriction() const
{
BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION);
return boost::get<WayRestriction>(node_or_way);
return mapbox::util::get<WayRestriction>(node_or_way);
}
NodeRestriction &AsNodeRestriction()
{
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
return boost::get<NodeRestriction>(node_or_way);
return mapbox::util::get<NodeRestriction>(node_or_way);
}
const NodeRestriction &AsNodeRestriction() const
{
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
return boost::get<NodeRestriction>(node_or_way);
return mapbox::util::get<NodeRestriction>(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

View File

@ -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<NodeID, NodeRestriction *> heads;
boost::unordered_multimap<NodeID, NodeRestriction *> tails;
boost::unordered_multimap<NodeID, NodeRestriction *> starts;
boost::unordered_multimap<NodeID, NodeRestriction *> ends;
};
} // namespace extractor

View File

@ -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<WayRestriction>(restriction.node_or_way));
write(writer, mapbox::util::get<WayRestriction>(restriction.node_or_way));
}
else
{
BOOST_ASSERT(restriction.Type() == RestrictionType::NODE_RESTRICTION);
write(writer, boost::get<NodeRestriction>(restriction.node_or_way));
write(writer, mapbox::util::get<NodeRestriction>(restriction.node_or_way));
}
}
inline void write(storage::io::FileWriter &writer, const ConditionalTurnRestriction &restriction)
{
write(writer, static_cast<TurnRestriction>(restriction));
write(writer, static_cast<const TurnRestriction &>(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<TurnRestriction &>(restriction) = std::move(base);
read(reader, static_cast<TurnRestriction &>(restriction));
const auto num_conditions = reader.ReadElementCount64();
restriction.condition.resize(num_conditions);
for (uint64_t i = 0; i < num_conditions; i++)

View File

@ -23,30 +23,30 @@ class WayRestrictionMap
public:
struct ViaWay
{
std::size_t id;
NodeID from;
NodeID to;
};
WayRestrictionMap(const std::vector<TurnRestriction> &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<ViaWay> DuplicatedNodeRepresentatives() const;
// Access all duplicated NodeIDs for a set of nodes indicating a via way
util::range<std::size_t> DuplicatedNodeIDs(const NodeID from, const NodeID to) const;
util::range<DuplicatedNodeID> 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<std::size_t> duplicated_node_groups;
std::vector<DuplicatedNodeID> duplicated_node_groups;
boost::unordered_multimap<std::pair<NodeID, NodeID>, std::size_t> restriction_starts;
boost::unordered_multimap<std::pair<NodeID, NodeID>, std::size_t> restriction_ends;
boost::unordered_multimap<std::pair<NodeID, NodeID>, RestrictionID> restriction_starts;
boost::unordered_multimap<std::pair<NodeID, NodeID>, RestrictionID> restriction_ends;
std::vector<TurnRestriction> restriction_data;
};

View File

@ -45,12 +45,18 @@ struct osm_node_id
struct osm_way_id
{
};
struct duplicated_node
{
};
}
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
static_assert(std::is_pod<OSMWayID>(), "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<OSMNodeID::value_type>::max()};
static const OSMWayID SPECIAL_OSM_WAYID =

View File

@ -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<EdgeWithData> 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<EdgeWithData> 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<NodeID>::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<std::shared_ptr<PipelineBuffer>, void> output_stage(
tbb::filter::serial_in_order, [&](const std::shared_ptr<PipelineBuffer> 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<NodeID>::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";
}

View File

@ -660,41 +660,44 @@ void ExtractionContainers::PrepareRestrictions()
// contain the start/end nodes of each way that is part of an restriction
std::unordered_map<OSMWayID, FirstAndLastSegmentOfWay> 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));
}
};

View File

@ -12,13 +12,13 @@ namespace extractor
RestrictionCompressor::RestrictionCompressor(std::vector<TurnRestriction> &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<TurnRestriction> &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 startptrs and move them from via to from.
auto all_starts_range = starts.equal_range(via);
std::vector<NodeRestriction *> start_ptrs;
std::transform(all_starts_range.first,
all_starts_range.second,
std::back_inserter(start_ptrs),
[](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<NodeRestriction *> 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) {
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<NodeRestriction *> 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<NodeRestriction *> 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)); };
// update end ptrs in mapping
ends.erase(via);
std::for_each(tail_ptrs.begin(), tail_ptrs.end(), update_tail);
// 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

View File

@ -78,8 +78,9 @@ removeInvalidRestrictions(std::vector<TurnRestriction> 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;
}

View File

@ -1,4 +1,5 @@
#include "extractor/way_restriction_map.hpp"
#include "util/for_each_pair.hpp"
#include <iterator>
#include <tuple>
@ -45,12 +46,10 @@ WayRestrictionMap::WayRestrictionMap(const std::vector<TurnRestriction> &turn_re
};
std::for_each(turn_restrictions.begin(), turn_restrictions.end(), extract_restrictions);
const auto as_duplicated_node =
[](auto const &restriction) -> std::tuple<NodeID, NodeID, NodeID> {
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<TurnRestriction> &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<TurnRestriction> &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<std::size_t> WayRestrictionMap::DuplicatedNodeIDs(const NodeID from,
const NodeID to) const
util::range<DuplicatedNodeID> 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<std::size_t> WayRestrictionMap::DuplicatedNodeIDs(const NodeID from,
return std::distance(restriction_data.begin(), itr);
};
return util::irange<std::size_t>(
return util::irange<DuplicatedNodeID>(
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::ViaWay> WayRestrictionMap::DuplicatedNodeRepresentatives() const
{
std::vector<ViaWay> result;
@ -167,7 +158,7 @@ std::vector<WayRestrictionMap::ViaWay> 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;
}