Lifts restriction to only provide zero or one alternative routes
This commit is contained in:
parent
e12c7756d9
commit
e064a9334b
@ -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
|
void MakeResponse(const InternalRouteResult &raw_route, util::json::Object &response) const
|
||||||
{
|
{
|
||||||
auto number_of_routes = raw_route.has_alternative() ? 2UL : 1UL;
|
return MakeResponse(raw_route, response);
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -47,24 +47,29 @@ struct PathData
|
|||||||
struct InternalRouteResult
|
struct InternalRouteResult
|
||||||
{
|
{
|
||||||
std::vector<std::vector<PathData>> unpacked_path_segments;
|
std::vector<std::vector<PathData>> unpacked_path_segments;
|
||||||
std::vector<PathData> unpacked_alternative;
|
|
||||||
std::vector<PhantomNodes> segment_end_coordinates;
|
std::vector<PhantomNodes> segment_end_coordinates;
|
||||||
std::vector<bool> source_traversed_in_reverse;
|
std::vector<bool> source_traversed_in_reverse;
|
||||||
std::vector<bool> target_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 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 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
|
bool is_via_leg(const std::size_t leg) const
|
||||||
{
|
{
|
||||||
return (leg != unpacked_path_segments.size() - 1);
|
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;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace engine
|
|||||||
class RoutingAlgorithmsInterface
|
class RoutingAlgorithmsInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual InternalRouteResult
|
virtual InternalManyRoutesResult
|
||||||
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const = 0;
|
||||||
|
|
||||||
virtual InternalRouteResult
|
virtual InternalRouteResult
|
||||||
@ -65,7 +65,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
|
|
||||||
virtual ~RoutingAlgorithms() = default;
|
virtual ~RoutingAlgorithms() = default;
|
||||||
|
|
||||||
InternalRouteResult
|
InternalManyRoutesResult
|
||||||
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
|
AlternativePathSearch(const PhantomNodes &phantom_node_pair) const final override;
|
||||||
|
|
||||||
InternalRouteResult ShortestPathSearch(
|
InternalRouteResult ShortestPathSearch(
|
||||||
@ -129,7 +129,7 @@ template <typename Algorithm> class RoutingAlgorithms final : public RoutingAlgo
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Algorithm>
|
template <typename Algorithm>
|
||||||
InternalRouteResult
|
InternalManyRoutesResult
|
||||||
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
RoutingAlgorithms<Algorithm>::AlternativePathSearch(const PhantomNodes &phantom_node_pair) const
|
||||||
{
|
{
|
||||||
return routing_algorithms::ch::alternativePathSearch(heaps, facade, phantom_node_pair);
|
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
|
// CoreCH overrides
|
||||||
template <>
|
template <>
|
||||||
InternalRouteResult inline RoutingAlgorithms<
|
InternalManyRoutesResult inline RoutingAlgorithms<
|
||||||
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
routing_algorithms::corech::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||||
{
|
{
|
||||||
throw util::exception("AlternativePathSearch is disabled due to performance reasons");
|
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
|
// MLD overrides for not implemented
|
||||||
template <>
|
template <>
|
||||||
InternalRouteResult inline RoutingAlgorithms<
|
InternalManyRoutesResult inline RoutingAlgorithms<
|
||||||
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
routing_algorithms::mld::Algorithm>::AlternativePathSearch(const PhantomNodes &) const
|
||||||
{
|
{
|
||||||
throw util::exception("AlternativePathSearch is not implemented");
|
throw util::exception("AlternativePathSearch is not implemented");
|
||||||
|
@ -17,7 +17,7 @@ namespace routing_algorithms
|
|||||||
{
|
{
|
||||||
namespace ch
|
namespace ch
|
||||||
{
|
{
|
||||||
InternalRouteResult
|
InternalManyRoutesResult
|
||||||
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
|
alternativePathSearch(SearchEngineData<Algorithm> &search_engine_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const PhantomNodes &phantom_node_pair);
|
const PhantomNodes &phantom_node_pair);
|
||||||
|
@ -84,28 +84,34 @@ ViaRoutePlugin::HandleRequest(const datafacade::ContiguousInternalMemoryDataFaca
|
|||||||
};
|
};
|
||||||
util::for_each_pair(snapped_phantoms, build_phantom_pairs);
|
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() &&
|
if (1 == start_end_nodes.size() && algorithms.HasAlternativePathSearch() &&
|
||||||
route_parameters.alternatives)
|
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())
|
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
|
else
|
||||||
{
|
{
|
||||||
raw_route =
|
routes = algorithms.ShortestPathSearch(start_end_nodes, route_parameters.continue_straight);
|
||||||
algorithms.ShortestPathSearch(start_end_nodes, route_parameters.continue_straight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can only know this after the fact, different SCC ids still
|
// we can only know this after the fact, different SCC ids still
|
||||||
// allow for connection in one direction.
|
// 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(routes, json_result);
|
||||||
route_api.MakeResponse(raw_route, json_result);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -563,13 +563,17 @@ bool viaNodeCandidatePassesTTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalRouteResult
|
InternalManyRoutesResult
|
||||||
alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const PhantomNodes &phantom_node_pair)
|
const PhantomNodes &phantom_node_pair)
|
||||||
{
|
{
|
||||||
InternalRouteResult raw_route_data;
|
InternalRouteResult primary_route;
|
||||||
raw_route_data.segment_end_coordinates = {phantom_node_pair};
|
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> alternative_path;
|
||||||
std::vector<NodeID> via_node_candidate_list;
|
std::vector<NodeID> via_node_candidate_list;
|
||||||
std::vector<SearchSpaceEdge> forward_search_space;
|
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)
|
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));
|
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)
|
if (INVALID_EDGE_WEIGHT != upper_bound_to_shortest_path_weight)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!packed_shortest_path.empty());
|
BOOST_ASSERT(!packed_shortest_path.empty());
|
||||||
raw_route_data.unpacked_path_segments.resize(1);
|
primary_route.unpacked_path_segments.resize(1);
|
||||||
raw_route_data.source_traversed_in_reverse.push_back(
|
primary_route.source_traversed_in_reverse.push_back(
|
||||||
(packed_shortest_path.front() !=
|
(packed_shortest_path.front() !=
|
||||||
phantom_node_pair.source_phantom.forward_segment_id.id));
|
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));
|
packed_shortest_path.back() != phantom_node_pair.target_phantom.forward_segment_id.id));
|
||||||
|
|
||||||
ch::unpackPath(facade,
|
ch::unpackPath(facade,
|
||||||
@ -809,8 +813,8 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
// -- start of route
|
// -- start of route
|
||||||
phantom_node_pair,
|
phantom_node_pair,
|
||||||
// -- unpacked output
|
// -- unpacked output
|
||||||
raw_route_data.unpacked_path_segments.front());
|
primary_route.unpacked_path_segments.front());
|
||||||
raw_route_data.shortest_path_weight = upper_bound_to_shortest_path_weight;
|
primary_route.shortest_path_weight = upper_bound_to_shortest_path_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SPECIAL_NODEID != selected_via_node)
|
if (SPECIAL_NODEID != selected_via_node)
|
||||||
@ -825,10 +829,11 @@ alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
v_t_middle,
|
v_t_middle,
|
||||||
packed_alternate_path);
|
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() !=
|
(packed_alternate_path.front() !=
|
||||||
phantom_node_pair.source_phantom.forward_segment_id.id));
|
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() !=
|
(packed_alternate_path.back() !=
|
||||||
phantom_node_pair.target_phantom.forward_segment_id.id));
|
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.begin(),
|
||||||
packed_alternate_path.end(),
|
packed_alternate_path.end(),
|
||||||
phantom_node_pair,
|
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
|
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
|
} // namespace ch
|
||||||
|
Loading…
Reference in New Issue
Block a user