pre-filter turn restrictions for validity

This commit is contained in:
Moritz Kobitzsch 2017-07-19 14:21:11 +02:00
parent 2e9a7d9c1a
commit b1809d1667
4 changed files with 116 additions and 7 deletions

View File

@ -0,0 +1,23 @@
#ifndef OSRM_EXTRACTOR_RESTRICTION_FILTER_HPP_
#define OSRM_EXTRACTOR_RESTRICTION_FILTER_HPP_
#include "extractor/restriction.hpp"
#include "util/node_based_graph.hpp"
#include <vector>
namespace osrm
{
namespace extractor
{
// To avoid handling invalid restrictions / creating unnecessary duplicate nodes for via-ways, we do
// a pre-flight check for restrictions and remove all invalid restrictions from the data. Use as
// `restrictions = removeInvalidRestrictions(std::move(restrictions))`
std::vector<TurnRestriction> removeInvalidRestrictions(std::vector<TurnRestriction>,
const util::NodeBasedDynamicGraph &);
} // namespace extractor
} // namespace osrm
#endif // OSRM_EXTRACTOR_RESTRICTION_FILTER_HPP_

View File

@ -7,6 +7,7 @@
#include "extractor/extractor_callbacks.hpp"
#include "extractor/files.hpp"
#include "extractor/raster_source.hpp"
#include "extractor/restriction_filter.hpp"
#include "extractor/restriction_parser.hpp"
#include "extractor/scripting_environment.hpp"
@ -465,6 +466,8 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
*node_based_graph,
compressed_edge_container);
turn_restrictions = removeInvalidRestrictions(std::move(turn_restrictions), *node_based_graph);
util::NameTable name_table(config.GetPath(".osrm.names").string());
auto restriction_map = std::make_shared<RestrictionMap>(turn_restrictions);

View File

@ -405,13 +405,8 @@ IntersectionGenerator::GetOnlyAllowedTurnIfExistent(const NodeID coming_from_nod
const auto only_restriction_to_node =
restriction_map.CheckForEmanatingIsOnlyTurn(coming_from_node, node_at_intersection);
if (only_restriction_to_node != SPECIAL_NODEID)
{
// if the mentioned node does not exist anymore, we don't return it. This checks for broken
// turn restrictions
for (const auto onto_edge : node_based_graph.GetAdjacentEdgeRange(node_at_intersection))
if (only_restriction_to_node == node_based_graph.GetTarget(onto_edge))
return only_restriction_to_node;
}
return only_restriction_to_node;
// Ignore broken only restrictions.
return boost::none;
}

View File

@ -0,0 +1,88 @@
#include "extractor/restriction_filter.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
std::vector<TurnRestriction>
removeInvalidRestrictions(std::vector<TurnRestriction> restrictions,
const util::NodeBasedDynamicGraph &node_based_graph)
{
// definition of what we presume to be a valid via-node restriction
const auto is_valid_node = [&node_based_graph](const auto &node_restriction) {
// a valid restriction needs to be connected to both its from and to locations
bool found_from = false, found_to = false;
for (auto eid : node_based_graph.GetAdjacentEdgeRange(node_restriction.via))
{
const auto target = node_based_graph.GetTarget(eid);
if (target == node_restriction.from)
found_from = true;
if (target == node_restriction.to)
found_to = true;
}
if (!found_from || !found_to)
return false;
return true;
};
// definition of what we presume to be a valid via-way restriction
const auto is_valid_way = [&node_based_graph, is_valid_node](const auto &way_restriction) {
const auto eid = node_based_graph.FindEdge(way_restriction.in_restriction.via,
way_restriction.out_restriction.via);
// ability filter, we currently cannot handle restrictions that do not match up in geometry:
// restrictions cannot be interrupted by traffic signals or other similar entities that
// cause node penalties
if ((way_restriction.in_restriction.via != way_restriction.out_restriction.from) ||
(way_restriction.out_restriction.via != way_restriction.in_restriction.to))
return false;
// the edge needs to exit (we cannot handle intermediate stuff, so far)
if (eid == SPECIAL_EDGEID)
return false;
const auto &data = node_based_graph.GetEdgeData(eid);
// edge needs to be traversable for a valid restrction
if (data.reversed)
return false;
// is the in restriction referencing the correct nodes
if (!is_valid_node(way_restriction.in_restriction))
return false;
// is the out restriction referencing the correct nodes
if (!is_valid_node(way_restriction.out_restriction))
return false;
return true;
};
const auto is_invalid = [is_valid_way, is_valid_node](const auto &restriction) {
if (restriction.Type() == RestrictionType::NODE_RESTRICTION)
{
return !is_valid_node(restriction.AsNodeRestriction());
}
else
{
BOOST_ASSERT(restriction.Type() == RestrictionType::WAY_RESTRICTION);
return !is_valid_way(restriction.AsWayRestriction());
}
};
restrictions.erase(std::remove_if(restrictions.begin(), restrictions.end(), is_invalid),
restrictions.end());
return restrictions;
}
} // namespace extractor
} // namespace osrm