From c04e295835eb8c5a6bb3a9c5535a0028c95318df Mon Sep 17 00:00:00 2001 From: Guo Date: Sat, 4 May 2019 07:12:59 +0900 Subject: [PATCH] 1.Strictly follow OSRM Clang Style Format as defined in .clang-format 2.Implementing multi heading route --- .gitignore | 1 + docs/http.md | 2 +- include/engine/routing_algorithms.hpp | 26 +- .../routing_algorithms/multi_heading_path.hpp | 27 +++ src/engine/plugins/viaroute.cpp | 25 +- .../routing_algorithms/multi_heading_path.cpp | 224 ++++++++++++++++++ 6 files changed, 290 insertions(+), 15 deletions(-) create mode 100644 include/engine/routing_algorithms/multi_heading_path.hpp create mode 100644 src/engine/routing_algorithms/multi_heading_path.cpp diff --git a/.gitignore b/.gitignore index 69b0c2afc..576d1f900 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ Thumbs.db /test/data/corech /test/data/mld /cmake/postinst +/cmake-build-debug/ # Eclipse related files # ######################### diff --git a/docs/http.md b/docs/http.md index 5cbd76673..ba6858ec7 100644 --- a/docs/http.md +++ b/docs/http.md @@ -290,7 +290,7 @@ curl 'http://router.project-osrm.org/table/v1/driving/13.388860,52.517037;13.397 - `durations` array of arrays that stores the matrix in row-major order. `durations[i][j]` gives the travel time from the i-th waypoint to the j-th waypoint. Values are given in seconds. Can be `null` if no route between `i` and `j` can be found. - `distances` array of arrays that stores the matrix in row-major order. `distances[i][j]` gives the travel distance from - the i-th waypoint to the j-th waypoint. Values are given in meters. Can be `null` if no route between `i` and `j` can be found. Note that computing the `distances` table is currently only implemented for CH. If `annotations=distance` or `annotations=duration,distance` is requested when running a MLD router, a `NotImplemented` error will be returned. + the i-th waypoint to the j-th waypoint. Values are given in meters. Can be `null` if no route between `i` and `j` can be found. - `sources` array of `Waypoint` objects describing all sources in order - `destinations` array of `Waypoint` objects describing all destinations in order - `fallback_speed_cells` (optional) array of arrays containing `i,j` pairs indicating which cells contain estimated values based on `fallback_speed`. Will be absent if `fallback_speed` is not used. diff --git a/include/engine/routing_algorithms.hpp b/include/engine/routing_algorithms.hpp index 5d4a8a956..0d9f3a533 100644 --- a/include/engine/routing_algorithms.hpp +++ b/include/engine/routing_algorithms.hpp @@ -8,6 +8,7 @@ #include "engine/routing_algorithms/direct_shortest_path.hpp" #include "engine/routing_algorithms/many_to_many.hpp" #include "engine/routing_algorithms/map_matching.hpp" +#include "engine/routing_algorithms/multi_heading_path.hpp" #include "engine/routing_algorithms/shortest_path.hpp" #include "engine/routing_algorithms/tile_turns.hpp" @@ -23,6 +24,9 @@ class RoutingAlgorithmsInterface AlternativePathSearch(const PhantomNodes &phantom_node_pair, unsigned number_of_alternatives) const = 0; + virtual InternalManyRoutesResult + MultiHeadingDirectShortestPathsSearch(const PhantomNodes &phantom_node_pair) const = 0; + virtual InternalRouteResult ShortestPathSearch(const std::vector &phantom_node_pair, const boost::optional continue_straight_at_waypoint) const = 0; @@ -50,13 +54,21 @@ class RoutingAlgorithmsInterface virtual const DataFacadeBase &GetFacade() const = 0; virtual bool HasAlternativePathSearch() const = 0; + virtual bool HasShortestPathSearch() const = 0; + virtual bool HasDirectShortestPathSearch() const = 0; + virtual bool HasMapMatching() const = 0; + virtual bool HasManyToManySearch() const = 0; + virtual bool SupportsDistanceAnnotationType() const = 0; + virtual bool HasGetTileTurns() const = 0; + virtual bool HasExcludeFlags() const = 0; + virtual bool IsValid() const = 0; }; @@ -80,6 +92,9 @@ template class RoutingAlgorithms final : public RoutingAlgo const std::vector &phantom_node_pair, const boost::optional continue_straight_at_waypoint) const final override; + InternalManyRoutesResult + MultiHeadingDirectShortestPathsSearch(const PhantomNodes &phantom_nodes) const final override; + InternalRouteResult DirectShortestPathSearch(const PhantomNodes &phantom_nodes) const final override; @@ -158,6 +173,13 @@ RoutingAlgorithms::AlternativePathSearch(const PhantomNodes &phantom_ heaps, *facade, phantom_node_pair, number_of_alternatives); } +template +InternalManyRoutesResult RoutingAlgorithms::MultiHeadingDirectShortestPathsSearch( + const PhantomNodes &phantom_nodes) const +{ + return routing_algorithms::multiHeadingDirectShortestPathsSearch(heaps, *facade, phantom_nodes); +} + template InternalRouteResult RoutingAlgorithms::ShortestPathSearch( const std::vector &phantom_node_pair, @@ -230,7 +252,7 @@ inline std::vector RoutingAlgorithms::G return routing_algorithms::getTileTurns(*facade, edges, sorted_edge_indexes); } -} // ns engine -} // ns osrm +} // namespace engine +} // namespace osrm #endif diff --git a/include/engine/routing_algorithms/multi_heading_path.hpp b/include/engine/routing_algorithms/multi_heading_path.hpp new file mode 100644 index 000000000..e7588db8d --- /dev/null +++ b/include/engine/routing_algorithms/multi_heading_path.hpp @@ -0,0 +1,27 @@ +#ifndef MULTI_HEADING_PATH_HPP +#define MULTI_HEADING_PATH_HPP + +#include "engine/algorithm.hpp" +#include "engine/datafacade.hpp" +#include "engine/internal_route_result.hpp" +#include "engine/search_engine_data.hpp" + +#include "util/typedefs.hpp" + +namespace osrm +{ +namespace engine +{ +namespace routing_algorithms +{ + +template +InternalManyRoutesResult +multiHeadingDirectShortestPathsSearch(SearchEngineData &engine_working_data, + const DataFacade &facade, + const PhantomNodes &phantom_nodes); +} // namespace routing_algorithms +} // namespace engine +} // namespace osrm + +#endif diff --git a/src/engine/plugins/viaroute.cpp b/src/engine/plugins/viaroute.cpp index a4df2de86..33b72f21d 100644 --- a/src/engine/plugins/viaroute.cpp +++ b/src/engine/plugins/viaroute.cpp @@ -53,8 +53,8 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm { return Error("TooBig", "Number of entries " + std::to_string(route_parameters.coordinates.size()) + - " is higher than current maximum (" + - std::to_string(max_locations_viaroute) + ")", + " is higher than current maximum (" + + std::to_string(max_locations_viaroute) + ")", json_result); } @@ -64,7 +64,7 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm { return Error("TooBig", "Requested number of alternatives is higher than current maximum (" + - std::to_string(max_alternatives) + ")", + std::to_string(max_alternatives) + ")", json_result); } @@ -92,7 +92,7 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm { return Error("NoSegment", std::string("Could not find a matching segment for coordinate ") + - std::to_string(phantom_node_pairs.size()), + std::to_string(phantom_node_pairs.size()), json_result); } BOOST_ASSERT(phantom_node_pairs.size() == route_parameters.coordinates.size()); @@ -102,7 +102,7 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm std::vector start_end_nodes; auto build_phantom_pairs = [&start_end_nodes](const PhantomNode &first_node, const PhantomNode &second_node) { - start_end_nodes.push_back(PhantomNodes{first_node, second_node}); + start_end_nodes.push_back(PhantomNodes{first_node, second_node}); }; util::for_each_pair(snapped_phantoms, build_phantom_pairs); @@ -126,7 +126,8 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm } else if (1 == start_end_nodes.size() && algorithms.HasDirectShortestPathSearch()) { - routes = algorithms.DirectShortestPathSearch(start_end_nodes.front()); + std::cout << "calling MultiHeadingDirectShortestPathsSearch in viaroute.cpp" << std::endl; + routes = algorithms.MultiHeadingDirectShortestPathsSearch(start_end_nodes.front()); } else { @@ -149,8 +150,8 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm std::for_each(route_parameters.waypoints.begin(), route_parameters.waypoints.end(), [&](const std::size_t waypoint_index) { - BOOST_ASSERT(waypoint_index < waypoint_legs.size()); - waypoint_legs[waypoint_index] = true; + BOOST_ASSERT(waypoint_index < waypoint_legs.size()); + waypoint_legs[waypoint_index] = true; }); // First and last coordinates should always be waypoints // This gets validated earlier, but double-checking here, jic @@ -170,7 +171,7 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm auto not_in_same_component = std::any_of(snapped_phantoms.begin(), snapped_phantoms.end(), [first_component_id](const PhantomNode &node) { - return node.component.id != first_component_id; + return node.component.id != first_component_id; }); if (not_in_same_component) @@ -185,6 +186,6 @@ Status ViaRoutePlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithm return Status::Ok; } -} -} -} +} // namespace plugins +} // namespace engine +} // namespace osrm diff --git a/src/engine/routing_algorithms/multi_heading_path.cpp b/src/engine/routing_algorithms/multi_heading_path.cpp new file mode 100644 index 000000000..54bfce4b7 --- /dev/null +++ b/src/engine/routing_algorithms/multi_heading_path.cpp @@ -0,0 +1,224 @@ +#include "engine/routing_algorithms/multi_heading_path.hpp" +#include "engine/routing_algorithms/routing_base.hpp" +#include "engine/routing_algorithms/routing_base_ch.hpp" +#include "engine/routing_algorithms/routing_base_mld.hpp" +#include "util/static_assert.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace osrm +{ +namespace engine +{ +namespace routing_algorithms +{ + +template <> +InternalManyRoutesResult +multiHeadingDirectShortestPathsSearch(SearchEngineData &engine_working_data, + const DataFacade &facade, + const PhantomNodes &phantom_nodes) +{ + engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes()); + auto &forward_heap = *engine_working_data.forward_heap_1; + auto &reverse_heap = *engine_working_data.reverse_heap_1; + forward_heap.Clear(); + reverse_heap.Clear(); + + EdgeWeight weight = INVALID_EDGE_WEIGHT; + std::vector packed_leg; + insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes); + + search(engine_working_data, + facade, + forward_heap, + reverse_heap, + weight, + packed_leg, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS, + phantom_nodes); + + std::vector unpacked_nodes; + std::vector unpacked_edges; + + if (!packed_leg.empty()) + { + unpacked_nodes.reserve(packed_leg.size()); + unpacked_edges.reserve(packed_leg.size()); + unpacked_nodes.push_back(packed_leg.front()); + ch::unpackPath(facade, + packed_leg.begin(), + packed_leg.end(), + [&unpacked_nodes, &unpacked_edges](std::pair &edge, + const auto &edge_id) { + BOOST_ASSERT(edge.first == unpacked_nodes.back()); + unpacked_nodes.push_back(edge.second); + unpacked_edges.push_back(edge_id); + }); + } + + std::vector routes; + routes.reserve(6); + + InternalRouteResult route = + extractRoute(facade, weight, phantom_nodes, unpacked_nodes, unpacked_edges); + routes.push_back(route); + BOOST_ASSERT(routes.size() >= 1); + + return InternalManyRoutesResult{std::move(routes)}; +} + +template <> +InternalManyRoutesResult +multiHeadingDirectShortestPathsSearch(SearchEngineData &engine_working_data, + const DataFacade &facade, + const PhantomNodes &phantom_nodes) +{ + engine_working_data.InitializeOrClearFirstThreadLocalStorage(facade.GetNumberOfNodes(), + facade.GetMaxBorderNodeID() + 1); + + std::vector routes; + routes.reserve(6); + + // insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes); + + const auto &source = phantom_nodes.source_phantom; + const auto &target = phantom_nodes.target_phantom; + + auto &forward_heap = *engine_working_data.forward_heap_1; + auto &reverse_heap = *engine_working_data.reverse_heap_1; + if (source.IsValidForwardSource() && target.IsValidForwardTarget()) + { + + forward_heap.Clear(); + reverse_heap.Clear(); + forward_heap.Insert(source.forward_segment_id.id, + -source.GetForwardWeightPlusOffset(), + source.forward_segment_id.id); + reverse_heap.Insert(target.forward_segment_id.id, + target.GetForwardWeightPlusOffset(), + target.forward_segment_id.id); + // TODO: when structured bindings will be allowed change to + // auto [weight, source_node, target_node, unpacked_edges] = ... + EdgeWeight weight = INVALID_EDGE_WEIGHT; + std::vector unpacked_nodes; + std::vector unpacked_edges; + std::tie(weight, unpacked_nodes, unpacked_edges) = mld::search(engine_working_data, + facade, + forward_heap, + reverse_heap, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS, + INVALID_EDGE_WEIGHT, + phantom_nodes); + InternalRouteResult route = + extractRoute(facade, weight, phantom_nodes, unpacked_nodes, unpacked_edges); + + routes.push_back(route); + } + + if (source.IsValidReverseSource() && target.IsValidForwardTarget()) + { + forward_heap.Clear(); + reverse_heap.Clear(); + forward_heap.Insert(source.reverse_segment_id.id, + -source.GetReverseWeightPlusOffset(), + source.reverse_segment_id.id); + reverse_heap.Insert(target.forward_segment_id.id, + target.GetForwardWeightPlusOffset(), + target.forward_segment_id.id); + // TODO: when structured bindings will be allowed change to + // auto [weight, source_node, target_node, unpacked_edges] = ... + EdgeWeight weight = INVALID_EDGE_WEIGHT; + std::vector unpacked_nodes; + std::vector unpacked_edges; + std::tie(weight, unpacked_nodes, unpacked_edges) = mld::search(engine_working_data, + facade, + forward_heap, + reverse_heap, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS, + INVALID_EDGE_WEIGHT, + phantom_nodes); + InternalRouteResult route = + extractRoute(facade, weight, phantom_nodes, unpacked_nodes, unpacked_edges); + + routes.push_back(route); + } + + if (source.IsValidForwardSource() && target.IsValidReverseTarget()) + { + forward_heap.Clear(); + reverse_heap.Clear(); + forward_heap.Insert(source.forward_segment_id.id, + -source.GetForwardWeightPlusOffset(), + source.forward_segment_id.id); + reverse_heap.Insert(target.reverse_segment_id.id, + target.GetReverseWeightPlusOffset(), + target.reverse_segment_id.id); + // TODO: when structured bindings will be allowed change to + // auto [weight, source_node, target_node, unpacked_edges] = ... + EdgeWeight weight = INVALID_EDGE_WEIGHT; + std::vector unpacked_nodes; + std::vector unpacked_edges; + std::tie(weight, unpacked_nodes, unpacked_edges) = mld::search(engine_working_data, + facade, + forward_heap, + reverse_heap, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS, + INVALID_EDGE_WEIGHT, + phantom_nodes); + InternalRouteResult route = + extractRoute(facade, weight, phantom_nodes, unpacked_nodes, unpacked_edges); + + routes.push_back(route); + } + if (source.IsValidReverseSource() && target.IsValidReverseTarget()) + { + forward_heap.Clear(); + reverse_heap.Clear(); + forward_heap.Insert(source.reverse_segment_id.id, + -source.GetReverseWeightPlusOffset(), + source.reverse_segment_id.id); + reverse_heap.Insert(target.reverse_segment_id.id, + target.GetReverseWeightPlusOffset(), + target.reverse_segment_id.id); + // TODO: when structured bindings will be allowed change to + // auto [weight, source_node, target_node, unpacked_edges] = ... + EdgeWeight weight = INVALID_EDGE_WEIGHT; + std::vector unpacked_nodes; + std::vector unpacked_edges; + std::tie(weight, unpacked_nodes, unpacked_edges) = mld::search(engine_working_data, + facade, + forward_heap, + reverse_heap, + DO_NOT_FORCE_LOOPS, + DO_NOT_FORCE_LOOPS, + INVALID_EDGE_WEIGHT, + phantom_nodes); + InternalRouteResult route = + extractRoute(facade, weight, phantom_nodes, unpacked_nodes, unpacked_edges); + + routes.push_back(route); + } + + BOOST_ASSERT(routes.size() >= 1); + + return InternalManyRoutesResult{std::move(routes)}; +} + +} // namespace routing_algorithms +} // namespace engine +} // namespace osrm