From e064a9334bbd022365ad1c5c50f25b8093fb72e7 Mon Sep 17 00:00:00 2001 From: "Daniel J. Hofmann" Date: Thu, 11 May 2017 18:44:48 +0200 Subject: [PATCH] Lifts restriction to only provide zero or one alternative routes --- include/engine/api/route_api.hpp | 44 +++++++++++-------- include/engine/internal_route_result.hpp | 17 ++++--- include/engine/routing_algorithms.hpp | 10 ++--- .../routing_algorithms/alternative_path.hpp | 2 +- src/engine/plugins/viaroute.cpp | 22 ++++++---- .../routing_algorithms/alternative_path.cpp | 35 ++++++++------- 6 files changed, 76 insertions(+), 54 deletions(-) diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 394af1e75..585190fd1 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -41,27 +41,33 @@ class RouteAPI : public BaseAPI { } + void MakeResponse(const InternalManyRoutesResult &raw_routes, + util::json::Object &response) const + { + BOOST_ASSERT(!raw_routes.routes.empty()); + + util::json::Array jsRoutes; + + for (const auto &route : raw_routes.routes) + { + if (!route.is_valid()) + continue; + + jsRoutes.values.push_back(MakeRoute(route.segment_end_coordinates, + route.unpacked_path_segments, + route.source_traversed_in_reverse, + route.target_traversed_in_reverse)); + } + + response.values["waypoints"] = + BaseAPI::MakeWaypoints(raw_routes.routes[0].segment_end_coordinates); + response.values["routes"] = std::move(jsRoutes); + response.values["code"] = "Ok"; + } + void MakeResponse(const InternalRouteResult &raw_route, util::json::Object &response) const { - auto number_of_routes = raw_route.has_alternative() ? 2UL : 1UL; - util::json::Array routes; - routes.values.resize(number_of_routes); - routes.values[0] = MakeRoute(raw_route.segment_end_coordinates, - raw_route.unpacked_path_segments, - raw_route.source_traversed_in_reverse, - raw_route.target_traversed_in_reverse); - if (raw_route.has_alternative()) - { - std::vector> wrapped_leg(1); - wrapped_leg.front() = std::move(raw_route.unpacked_alternative); - routes.values[1] = MakeRoute(raw_route.segment_end_coordinates, - wrapped_leg, - raw_route.alt_source_traversed_in_reverse, - raw_route.alt_target_traversed_in_reverse); - } - response.values["waypoints"] = BaseAPI::MakeWaypoints(raw_route.segment_end_coordinates); - response.values["routes"] = std::move(routes); - response.values["code"] = "Ok"; + return MakeResponse(raw_route, response); } protected: diff --git a/include/engine/internal_route_result.hpp b/include/engine/internal_route_result.hpp index 6e1722b26..d7d986e18 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -47,24 +47,29 @@ struct PathData struct InternalRouteResult { std::vector> unpacked_path_segments; - std::vector unpacked_alternative; std::vector segment_end_coordinates; std::vector source_traversed_in_reverse; std::vector target_traversed_in_reverse; - std::vector alt_source_traversed_in_reverse; - std::vector alt_target_traversed_in_reverse; EdgeWeight shortest_path_weight = INVALID_EDGE_WEIGHT; - EdgeWeight alternative_path_weight = INVALID_EDGE_WEIGHT; bool is_valid() const { return INVALID_EDGE_WEIGHT != shortest_path_weight; } - bool has_alternative() const { return INVALID_EDGE_WEIGHT != alternative_path_weight; } - bool is_via_leg(const std::size_t leg) const { return (leg != unpacked_path_segments.size() - 1); } }; + +struct InternalManyRoutesResult +{ + InternalManyRoutesResult() = default; + InternalManyRoutesResult(InternalRouteResult route) : routes{std::move(route)} {} + InternalManyRoutesResult(std::vector routes_) : routes{std::move(routes_)} + { + } + + std::vector routes; +}; } } diff --git a/include/engine/routing_algorithms.hpp b/include/engine/routing_algorithms.hpp index 7a19e2b41..8619341a5 100644 --- a/include/engine/routing_algorithms.hpp +++ b/include/engine/routing_algorithms.hpp @@ -19,7 +19,7 @@ namespace engine class RoutingAlgorithmsInterface { public: - virtual InternalRouteResult + virtual InternalManyRoutesResult AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0; virtual InternalRouteResult @@ -65,7 +65,7 @@ template class RoutingAlgorithms final : public RoutingAlgo virtual ~RoutingAlgorithms() = default; - InternalRouteResult + InternalManyRoutesResult AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override; InternalRouteResult ShortestPathSearch( @@ -129,7 +129,7 @@ template class RoutingAlgorithms final : public RoutingAlgo }; template -InternalRouteResult +InternalManyRoutesResult RoutingAlgorithms::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const { return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair); @@ -188,7 +188,7 @@ inline std::vector RoutingAlgorithms::G // CoreCH overrides template <> -InternalRouteResult inline RoutingAlgorithms< +InternalManyRoutesResult inline RoutingAlgorithms< routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const { throw util::exception("AlternativePathSearch is disabled due to performance reasons"); @@ -206,7 +206,7 @@ RoutingAlgorithms::ManyToManySearch( // MLD overrides for not implemented template <> -InternalRouteResult inline RoutingAlgorithms< +InternalManyRoutesResult inline RoutingAlgorithms< routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const { throw util::exception("AlternativePathSearch is not implemented"); diff --git a/include/engine/routing_algorithms/alternative_path.hpp b/include/engine/routing_algorithms/alternative_path.hpp index 0bd418275..016c46621 100644 --- a/include/engine/routing_algorithms/alternative_path.hpp +++ b/include/engine/routing_algorithms/alternative_path.hpp @@ -17,7 +17,7 @@ namespace routing_algorithms { namespace ch { -InternalRouteResult +InternalManyRoutesResult alternativePathSearch(SearchEngineData &search_engine_data, const datafacade::ContiguousInternalMemoryDataFacade &facade, const PhantomNodes &phantom_node_pair); diff --git a/src/engine/plugins/viaroute.cpp b/src/engine/plugins/viaroute.cpp index 2be8756eb..98b97c51c 100644 --- a/src/engine/plugins/viaroute.cpp +++ b/src/engine/plugins/viaroute.cpp @@ -84,28 +84,34 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca }; util::for_each_pair(snapped_phantoms, build_phantom_pairs); - InternalRouteResult raw_route; + api::RouteAPI route_api{facade, route_parameters}; + + InternalManyRoutesResult routes; + + // Alternatives do not support vias, only direct s,t queries supported + // See the implementation notes and high-level outline. + // https://github.com/Project-OSRM/osrm-backend/issues/3905 if (1 == start_end_nodes.size() && algorithms.HasAlternativePathSearch() && route_parameters.alternatives) { - raw_route = algorithms.AlternativePathSearch(start_end_nodes.front()); + routes = algorithms.AlternativePathSearch(start_end_nodes.front()); } else if (1 == start_end_nodes.size() && algorithms.HasDirectShortestPathSearch()) { - raw_route = algorithms.DirectShortestPathSearch(start_end_nodes.front()); + routes = algorithms.DirectShortestPathSearch(start_end_nodes.front()); } else { - raw_route = - algorithms.ShortestPathSearch(start_end_nodes, route_parameters.continue_straight); + routes = algorithms.ShortestPathSearch(start_end_nodes, route_parameters.continue_straight); } // we can only know this after the fact, different SCC ids still // allow for connection in one direction. - if (raw_route.is_valid()) + BOOST_ASSERT(!routes.routes.empty()); + + if (routes.routes[0].is_valid()) { - api::RouteAPI route_api{facade, route_parameters}; - route_api.MakeResponse(raw_route, json_result); + route_api.MakeResponse(routes, json_result); } else { diff --git a/src/engine/routing_algorithms/alternative_path.cpp b/src/engine/routing_algorithms/alternative_path.cpp index 9dc1e76af..98e77161f 100644 --- a/src/engine/routing_algorithms/alternative_path.cpp +++ b/src/engine/routing_algorithms/alternative_path.cpp @@ -563,13 +563,17 @@ bool viaNodeCandidatePassesTTest( } } -InternalRouteResult +InternalManyRoutesResult alternativePathSearch(SearchEngineData &engine_working_data, const datafacade::ContiguousInternalMemoryDataFacade &facade, const PhantomNodes &phantom_node_pair) { - InternalRouteResult raw_route_data; - raw_route_data.segment_end_coordinates = {phantom_node_pair}; + InternalRouteResult primary_route; + InternalRouteResult secondary_route; + + primary_route.segment_end_coordinates = {phantom_node_pair}; + secondary_route.segment_end_coordinates = {phantom_node_pair}; + std::vector alternative_path; std::vector via_node_candidate_list; std::vector forward_search_space; @@ -626,7 +630,7 @@ alternativePathSearch(SearchEngineData &engine_working_data, if (INVALID_EDGE_WEIGHT == upper_bound_to_shortest_path_weight) { - return raw_route_data; + return InternalManyRoutesResult{std::move(primary_route)}; } std::sort(begin(via_node_candidate_list), end(via_node_candidate_list)); @@ -795,11 +799,11 @@ alternativePathSearch(SearchEngineData &engine_working_data, if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_weight) { BOOST_ASSERT(!packed_shortest_path.empty()); - raw_route_data.unpacked_path_segments.resize(1); - raw_route_data.source_traversed_in_reverse.push_back( + primary_route.unpacked_path_segments.resize(1); + primary_route.source_traversed_in_reverse.push_back( (packed_shortest_path.front() != phantom_node_pair.source_phantom.forward_segment_id.id)); - raw_route_data.target_traversed_in_reverse.push_back(( + primary_route.target_traversed_in_reverse.push_back(( packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); ch::unpackPath(facade, @@ -809,8 +813,8 @@ alternativePathSearch(SearchEngineData &engine_working_data, // -- start of route phantom_node_pair, // -- unpacked output - raw_route_data.unpacked_path_segments.front()); - raw_route_data.shortest_path_weight = upper_bound_to_shortest_path_weight; + primary_route.unpacked_path_segments.front()); + primary_route.shortest_path_weight = upper_bound_to_shortest_path_weight; } if (SPECIAL_NODEID != selected_via_node) @@ -825,10 +829,11 @@ alternativePathSearch(SearchEngineData &engine_working_data, v_t_middle, packed_alternate_path); - raw_route_data.alt_source_traversed_in_reverse.push_back( + secondary_route.unpacked_path_segments.resize(1); + secondary_route.source_traversed_in_reverse.push_back( (packed_alternate_path.front() != phantom_node_pair.source_phantom.forward_segment_id.id)); - raw_route_data.alt_target_traversed_in_reverse.push_back( + secondary_route.target_traversed_in_reverse.push_back( (packed_alternate_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id)); @@ -837,16 +842,16 @@ alternativePathSearch(SearchEngineData &engine_working_data, packed_alternate_path.begin(), packed_alternate_path.end(), phantom_node_pair, - raw_route_data.unpacked_alternative); + secondary_route.unpacked_path_segments.front()); - raw_route_data.alternative_path_weight = weight_of_via_path; + secondary_route.shortest_path_weight = weight_of_via_path; } else { - BOOST_ASSERT(raw_route_data.alternative_path_weight == INVALID_EDGE_WEIGHT); + BOOST_ASSERT(secondary_route.shortest_path_weight == INVALID_EDGE_WEIGHT); } - return raw_route_data; + return InternalManyRoutesResult{{std::move(primary_route), std::move(secondary_route)}}; } } // namespace ch