From 8ffe915395624bb22d2531fd901a55439a8e4aab Mon Sep 17 00:00:00 2001 From: karenzshea Date: Wed, 7 Dec 2016 14:26:34 -0500 Subject: [PATCH] do not emit turns on ferries --- features/bicycle/bridge.feature | 6 +- features/guidance/collapse-ferry.feature | 91 +++++++++++++++++++ features/guidance/ramp.feature | 8 +- .../guidance/suppress_mode_handler.hpp | 44 +++++++++ include/extractor/guidance/turn_analysis.hpp | 2 + include/extractor/travel_mode.hpp | 2 + .../guidance/intersection_handler.cpp | 3 + .../guidance/suppress_mode_handler.cpp | 66 ++++++++++++++ src/extractor/guidance/turn_analysis.cpp | 19 +++- src/extractor/guidance/turn_handler.cpp | 3 +- 10 files changed, 234 insertions(+), 10 deletions(-) create mode 100644 features/guidance/collapse-ferry.feature create mode 100644 include/extractor/guidance/suppress_mode_handler.hpp create mode 100644 src/extractor/guidance/suppress_mode_handler.cpp diff --git a/features/bicycle/bridge.feature b/features/bicycle/bridge.feature index 51094c330..424dde94f 100644 --- a/features/bicycle/bridge.feature +++ b/features/bicycle/bridge.feature @@ -44,8 +44,8 @@ Feature: Bicycle - Handle cycling | efg | primary | | | When I route I should get - | from | to | route | modes | speed | + | from | to | route | modes | speed | | a | g | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 5 km/h | | b | f | abc,cde,efg,efg | cycling,cycling,cycling,cycling | 4 km/h | - | c | e | cde,cde | cycling,cycling | 2 km/h | - | e | c | cde,cde | cycling,cycling | 2 km/h | + | c | e | cde,cde | cycling,cycling | 2 km/h | + | e | c | cde,cde | cycling,cycling | 2 km/h | diff --git a/features/guidance/collapse-ferry.feature b/features/guidance/collapse-ferry.feature new file mode 100644 index 000000000..67f1616d5 --- /dev/null +++ b/features/guidance/collapse-ferry.feature @@ -0,0 +1,91 @@ +@routing @guidance @collapsing +Feature: Collapse + + Background: + Given the profile "car" + Given a grid size of 20 meters + + Scenario: Collapse Steps While On Ferry + Given the node map + """ + j----a---c---b----k + ~ ~ ~ + ~ ~ ~ + ~~~ + d + ~ + ~ + ~ + e --- f + """ + + And the ways + | nodes | highway | route | name | + | jacbk | primary | | land | + | ad | | ferry | sea | + | bd | | ferry | sea | + | cd | | ferry | sea | + | de | | ferry | sea | + | ef | primary | | land | + + When I route I should get + | waypoints | route | turns | modes | + | f,j | land,sea,land,land | depart,notification right,end of road left,arrive | driving,ferry,driving,driving | + + Scenario: Switching Ferry in a Harbour + Given the node map + """ + d + | + | + | + e - a ~ ~ ~ ~ b + ~ + ~ + ~ + c + | + f + """ + + And the ways + | nodes | highway | route | name | + | ea | primary | | melee-island | + | ab | | ferry | melee-island-ferry | + | cf | primary | | pennydog-island | + | bd | primary | | landmass | + | bc | primary | ferry | pennydog-island-ferry | + + When I route I should get + | waypoints | route | turns | modes | + | e,f | melee-island,melee-island-ferry,pennydog-island-ferry,pennydog-island,pennydog-island | depart,notification straight,turn right,notification straight,arrive | driving,ferry,ferry,driving,driving | + + Scenario: Fork Ferries + Given the node map + """ + a - b d - e + ~ ~ + ~ ~ + ~ ~ + ~ ~ + c + ~ + ~ + ~ + f + | + g + """ + + And the ways + | nodes | highway | route | name | + | ab | primary | | land-left | + | de | primary | | land-right | + | gf | primary | | land-bottom | + | cb | | ferry | ferry | + | cd | | ferry | ferry | + | fc | | ferry | ferry | + + When I route I should get + | waypoints | route | turns | + | g,e | land-bottom,ferry,land-right,land-right | depart,notification straight,notification right,arrive | diff --git a/features/guidance/ramp.feature b/features/guidance/ramp.feature index f23213061..426668093 100644 --- a/features/guidance/ramp.feature +++ b/features/guidance/ramp.feature @@ -261,7 +261,7 @@ Feature: Ramp Guidance """ d - e - g | - a - b ~ ~ ~ ~ ~ ~ ~ c + a - b ~ ~ ~ ~ ~ ~ ~ c ` f """ @@ -271,8 +271,8 @@ Feature: Ramp Guidance | bc | | ferry | boaty mc boatface | m2 | | cf | | ferry | boaty mc boatface | | | cd | | ferry | boaty mc boatface's cousin | | - | de | motorway_link | | | | + | de | motorway_link | | | | When I route I should get - | waypoints | route | - | a,e | boarding,boaty mc boatface,boaty mc boatface's cousin,, | + | waypoints | route | + | a,e | boarding,boaty mc boatface,, | diff --git a/include/extractor/guidance/suppress_mode_handler.hpp b/include/extractor/guidance/suppress_mode_handler.hpp new file mode 100644 index 000000000..290755322 --- /dev/null +++ b/include/extractor/guidance/suppress_mode_handler.hpp @@ -0,0 +1,44 @@ +#ifndef OSRM_EXTRACTOR_GUIDANCE_SUPPRESS_MODE_HANDLER_HPP_ +#define OSRM_EXTRACTOR_GUIDANCE_SUPPRESS_MODE_HANDLER_HPP_ + +#include "extractor/guidance/constants.hpp" +#include "extractor/guidance/intersection.hpp" +#include "extractor/guidance/intersection_generator.hpp" +#include "extractor/guidance/intersection_handler.hpp" +#include "extractor/travel_mode.hpp" +#include "util/node_based_graph.hpp" + +namespace osrm +{ +namespace extractor +{ +namespace guidance +{ + +class SuppressModeHandler final : public IntersectionHandler +{ + public: + SuppressModeHandler(const IntersectionGenerator &intersection_generator, + const util::NodeBasedDynamicGraph &node_based_graph, + const std::vector &node_info_list, + const util::NameTable &name_table, + const SuffixTable &street_name_suffix_table); + + ~SuppressModeHandler() override final = default; + + bool canProcess(const NodeID /*nid*/, + const EdgeID via_eid, + const Intersection &intersection) const override final; + + Intersection operator()(const NodeID nid, + const EdgeID via_eid, + Intersection intersection) const override final; + + using SuppressModeListT = std::array; +}; + +} // namespace osrm +} // namespace extractor +} // namespace guidance + +#endif /* OSRM_EXTRACTOR_GUIDANCE_SUPPRESS_MODE_HANDLER_HPP_ */ diff --git a/include/extractor/guidance/turn_analysis.hpp b/include/extractor/guidance/turn_analysis.hpp index ac3b7fe13..332373bd2 100644 --- a/include/extractor/guidance/turn_analysis.hpp +++ b/include/extractor/guidance/turn_analysis.hpp @@ -8,6 +8,7 @@ #include "extractor/guidance/motorway_handler.hpp" #include "extractor/guidance/roundabout_handler.hpp" #include "extractor/guidance/sliproad_handler.hpp" +#include "extractor/guidance/suppress_mode_handler.hpp" #include "extractor/guidance/turn_classification.hpp" #include "extractor/guidance/turn_handler.hpp" #include "extractor/query_node.hpp" @@ -86,6 +87,7 @@ class TurnAnalysis const MotorwayHandler motorway_handler; const TurnHandler turn_handler; const SliproadHandler sliproad_handler; + const SuppressModeHandler suppress_mode_handler; // Utility function, setting basic turn types. Prepares for normal turn handling. Intersection diff --git a/include/extractor/travel_mode.hpp b/include/extractor/travel_mode.hpp index fa75c373b..93e273e34 100644 --- a/include/extractor/travel_mode.hpp +++ b/include/extractor/travel_mode.hpp @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TRAVEL_MODE_HPP #define TRAVEL_MODE_HPP +#include + namespace osrm { namespace extractor diff --git a/src/extractor/guidance/intersection_handler.cpp b/src/extractor/guidance/intersection_handler.cpp index 7c61029be..ae23a4a8d 100644 --- a/src/extractor/guidance/intersection_handler.cpp +++ b/src/extractor/guidance/intersection_handler.cpp @@ -1,5 +1,6 @@ #include "extractor/guidance/intersection_handler.hpp" #include "extractor/guidance/constants.hpp" +#include "extractor/travel_mode.hpp" #include "util/coordinate_calculation.hpp" #include "util/guidance/name_announcements.hpp" @@ -326,8 +327,10 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid, { for (std::size_t index = begin; index != end; ++index) if (intersection[index].entry_allowed) + { intersection[index].instruction = {findBasicTurnType(via_eid, intersection[index]), getTurnDirection(intersection[index].angle)}; + } } bool IntersectionHandler::isThroughStreet(const std::size_t index, diff --git a/src/extractor/guidance/suppress_mode_handler.cpp b/src/extractor/guidance/suppress_mode_handler.cpp new file mode 100644 index 000000000..0937a9b1a --- /dev/null +++ b/src/extractor/guidance/suppress_mode_handler.cpp @@ -0,0 +1,66 @@ +#include "extractor/guidance/constants.hpp" +#include "extractor/guidance/suppress_mode_handler.hpp" +#include "extractor/travel_mode.hpp" + +#include +#include + +namespace osrm +{ +namespace extractor +{ +namespace guidance +{ + +SuppressModeHandler::SuppressModeHandler(const IntersectionGenerator &intersection_generator, + const util::NodeBasedDynamicGraph &node_based_graph, + const std::vector &node_info_list, + const util::NameTable &name_table, + const SuffixTable &street_name_suffix_table) + : IntersectionHandler(node_based_graph, + node_info_list, + name_table, + street_name_suffix_table, + intersection_generator) +{ +} + +// travel modes for which navigation should be suppressed +const SuppressModeHandler::SuppressModeListT constexpr SUPPRESS_MODE_LIST = { + {TRAVEL_MODE_TRAIN, TRAVEL_MODE_FERRY}}; + +bool SuppressModeHandler::canProcess(const NodeID /*nid*/, + const EdgeID via_eid, + const Intersection &intersection) const +{ + // if the approach way is not on the suppression blacklist, and not all the exit ways share that mode, + // there are no ways to suppress by this criteria + const auto in_mode = node_based_graph.GetEdgeData(via_eid).travel_mode; + const auto suppress_in_mode = + std::find(begin(SUPPRESS_MODE_LIST), end(SUPPRESS_MODE_LIST), in_mode); + + auto Begin = begin(intersection) + 1; + auto End = end(intersection); + const auto all_share_mode = std::all_of(Begin, End, [this, &in_mode](const ConnectedRoad &way) { + return node_based_graph.GetEdgeData(way.eid).travel_mode == in_mode; + }); + + return (suppress_in_mode != end(SUPPRESS_MODE_LIST)) && all_share_mode; +} + +Intersection SuppressModeHandler:: +operator()(const NodeID nid, const EdgeID via_eid, Intersection intersection) const +{ + const auto suppress_all = SuppressModeHandler::canProcess(nid, via_eid, intersection); + if (suppress_all) + { + std::for_each(begin(intersection) + 1, end(intersection), [&](ConnectedRoad &out_way) { + out_way.instruction = {TurnType::Suppressed, getTurnDirection(out_way.angle)}; + }); + } + + return intersection; +} +} +} +} diff --git a/src/extractor/guidance/turn_analysis.cpp b/src/extractor/guidance/turn_analysis.cpp index e06fa2e27..510a63dfc 100644 --- a/src/extractor/guidance/turn_analysis.cpp +++ b/src/extractor/guidance/turn_analysis.cpp @@ -1,6 +1,6 @@ -#include "extractor/guidance/turn_analysis.hpp" #include "extractor/guidance/constants.hpp" #include "extractor/guidance/road_classification.hpp" +#include "extractor/guidance/turn_analysis.hpp" #include "util/coordinate.hpp" #include "util/coordinate_calculation.hpp" @@ -65,7 +65,12 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph, node_based_graph, node_info_list, name_table, - street_name_suffix_table) + street_name_suffix_table), + suppress_mode_handler(intersection_generator, + node_based_graph, + node_info_list, + name_table, + street_name_suffix_table) { } @@ -106,6 +111,16 @@ Intersection TurnAnalysis::AssignTurnTypes(const NodeID node_prior_to_intersecti {TurnType::Invalid, DirectionModifier::UTurn}, INVALID_LANE_DATAID); }); + // Suppress turns on ways between mode types that do not need guidance + if (suppress_mode_handler.canProcess( + node_prior_to_intersection, entering_via_edge, intersection)) + { + intersection = suppress_mode_handler( + node_prior_to_intersection, entering_via_edge, std::move(intersection)); + + return intersection; + } + if (roundabout_handler.canProcess(node_prior_to_intersection, entering_via_edge, intersection)) { intersection = roundabout_handler( diff --git a/src/extractor/guidance/turn_handler.cpp b/src/extractor/guidance/turn_handler.cpp index e24d22769..e493fcc05 100644 --- a/src/extractor/guidance/turn_handler.cpp +++ b/src/extractor/guidance/turn_handler.cpp @@ -1,5 +1,5 @@ -#include "extractor/guidance/turn_handler.hpp" #include "extractor/guidance/constants.hpp" +#include "extractor/guidance/turn_handler.hpp" #include "util/bearing.hpp" #include "util/guidance/name_announcements.hpp" @@ -151,6 +151,7 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection \ OOOOOOO */ + const auto fork_range = findFork(via_edge, intersection); if (fork_range.first == 1 && fork_range.second == 2 && obvious_index == 0) assignFork(via_edge, intersection[2], intersection[1]);