From b1809d16671d8def20146bae6278659c9d723d6f Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Wed, 19 Jul 2017 14:21:11 +0200 Subject: [PATCH] pre-filter turn restrictions for validity --- include/extractor/restriction_filter.hpp | 23 +++++ src/extractor/extractor.cpp | 3 + .../guidance/intersection_generator.cpp | 9 +- src/extractor/restriction_filter.cpp | 88 +++++++++++++++++++ 4 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 include/extractor/restriction_filter.hpp create mode 100644 src/extractor/restriction_filter.cpp diff --git a/include/extractor/restriction_filter.hpp b/include/extractor/restriction_filter.hpp new file mode 100644 index 000000000..c8c6d7293 --- /dev/null +++ b/include/extractor/restriction_filter.hpp @@ -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 + +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 removeInvalidRestrictions(std::vector, + const util::NodeBasedDynamicGraph &); + +} // namespace extractor +} // namespace osrm + +#endif // OSRM_EXTRACTOR_RESTRICTION_FILTER_HPP_ diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp index e61a2db48..c75e77f6c 100644 --- a/src/extractor/extractor.cpp +++ b/src/extractor/extractor.cpp @@ -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(turn_restrictions); diff --git a/src/extractor/guidance/intersection_generator.cpp b/src/extractor/guidance/intersection_generator.cpp index c63b4eb11..51fde3ec3 100644 --- a/src/extractor/guidance/intersection_generator.cpp +++ b/src/extractor/guidance/intersection_generator.cpp @@ -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; } diff --git a/src/extractor/restriction_filter.cpp b/src/extractor/restriction_filter.cpp new file mode 100644 index 000000000..8a74cefb8 --- /dev/null +++ b/src/extractor/restriction_filter.cpp @@ -0,0 +1,88 @@ +#include "extractor/restriction_filter.hpp" +#include "util/node_based_graph.hpp" +#include "util/typedefs.hpp" + +#include +#include + +namespace osrm +{ +namespace extractor +{ + +std::vector +removeInvalidRestrictions(std::vector 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