osrm-backend/include/extractor/node_restriction_map.hpp
Michael Bell 5266ac1635
Add support for multiple via-way restrictions (#5907)
Currently OSRM only supports turn restrictions with a single via-node or one
via-way. OSM allows for multiple via-ways to represent longer and more
complex restrictions.

This PR extends the use of duplicate nodes for representng via-way turn
restrictions to also support multi via-way restrictions. Effectively, this
increases the edge-based graph size by the number of edges in multi via-way
restrictions. However, given the low number of these restrictions it
has little effect on total graph size.

In addition, we add a new step in the extraction phase that constructs
a restriction graph to support more complex relationships between restrictions,
such as nested restrictions and overlapping restrictions.
2020-12-20 13:59:57 -08:00

81 lines
2.3 KiB
C++

#ifndef OSRM_EXTRACTOR_NODE_RESTRICTION_MAP_HPP_
#define OSRM_EXTRACTOR_NODE_RESTRICTION_MAP_HPP_
#include "extractor/restriction.hpp"
#include "restriction_graph.hpp"
#include "util/typedefs.hpp"
#include <boost/range/adaptor/filtered.hpp>
#include <boost/unordered_map.hpp>
#include <utility>
#include <vector>
namespace osrm
{
namespace extractor
{
// Allows easy check for whether a node restriction is present at a given intersection
template <typename RestrictionFilter> class NodeRestrictionMap
{
public:
NodeRestrictionMap(const RestrictionGraph &restriction_graph)
: restriction_graph(restriction_graph), index_filter(RestrictionFilter{})
{
}
// Find all restrictions applicable to (from,via,*) turns
auto Restrictions(NodeID from, NodeID via) const
{
return getRange(from, via) | boost::adaptors::filtered(index_filter);
};
// Find all restrictions applicable to (from,via,to) turns
auto Restrictions(NodeID from, NodeID via, NodeID to) const
{
const auto turnFilter = [this, to](const auto &restriction) {
return index_filter(restriction) && restriction->IsTurnRestricted(to);
};
return getRange(from, via) | boost::adaptors::filtered(turnFilter);
};
private:
RestrictionGraph::RestrictionRange getRange(NodeID from, NodeID via) const
{
const auto start_node_it = restriction_graph.start_edge_to_node.find({from, via});
if (start_node_it != restriction_graph.start_edge_to_node.end())
{
return restriction_graph.GetRestrictions(start_node_it->second);
}
return {};
}
const RestrictionGraph &restriction_graph;
const RestrictionFilter index_filter;
};
// Restriction filters to use as index defaults
struct ConditionalOnly
{
bool operator()(const TurnRestriction *restriction) const
{
return !restriction->IsUnconditional();
};
};
struct UnconditionalOnly
{
bool operator()(const TurnRestriction *restriction) const
{
return restriction->IsUnconditional();
};
};
using RestrictionMap = NodeRestrictionMap<UnconditionalOnly>;
using ConditionalRestrictionMap = NodeRestrictionMap<ConditionalOnly>;
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_NODE_RESTRICTION_MAP_HPP_