Lifts restriction to only provide zero or one alternative routes

This commit is contained in:
Daniel J. Hofmann 2017-05-11 18:44:48 +02:00
parent e12c7756d9
commit e064a9334b
6 changed files with 76 additions and 54 deletions

View File

@ -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<std::vector<PathData>> 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:

View File

@ -47,24 +47,29 @@ struct PathData
struct InternalRouteResult
{
std::vector<std::vector<PathData>> unpacked_path_segments;
std::vector<PathData> unpacked_alternative;
std::vector<PhantomNodes> segment_end_coordinates;
std::vector<bool> source_traversed_in_reverse;
std::vector<bool> target_traversed_in_reverse;
std::vector<bool> alt_source_traversed_in_reverse;
std::vector<bool> 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<InternalRouteResult> routes_) : routes{std::move(routes_)}
{
}
std::vector<InternalRouteResult> routes;
};
}
}

View File

@ -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 <typename Algorithm> 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 <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
};
template <typename Algorithm>
InternalRouteResult
InternalManyRoutesResult
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
{
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
@ -188,7 +188,7 @@ inline std::vector<routing_algorithms::TurnData> RoutingAlgorithms<Algorithm>::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<routing_algorithms::corech::Algorithm>::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");

View File

@ -17,7 +17,7 @@ namespace routing_algorithms
{
namespace ch
{
InternalRouteResult
InternalManyRoutesResult
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
const PhantomNodes &phantom_node_pair);

View File

@ -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
{

View File

@ -563,13 +563,17 @@ bool viaNodeCandidatePassesTTest(
}
}
InternalRouteResult
InternalManyRoutesResult
alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &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<NodeID> alternative_path;
std::vector<NodeID> via_node_candidate_list;
std::vector<SearchSpaceEdge> forward_search_space;
@ -626,7 +630,7 @@ alternativePathSearch(SearchEngineData<Algorithm> &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<Algorithm> &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<Algorithm> &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<Algorithm> &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<Algorithm> &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