Support snapping to multiple ways at an input location (#5953)
This PR improves routing results by adding support for snapping to multiple ways at input locations. This means all edges at the snapped location can act as source/target candidates for routing search, ensuring we always find the best route, and not the one dependent on the edge selected.
This commit is contained in:
@@ -44,16 +44,16 @@ BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip)
|
||||
const PhantomNode phantom;
|
||||
const osrm::test::MockDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> facade{};
|
||||
|
||||
const Hint hint{phantom, facade.GetCheckSum()};
|
||||
const SegmentHint seg_hint{phantom, facade.GetCheckSum()};
|
||||
|
||||
const auto base64 = hint.ToBase64();
|
||||
const auto base64 = seg_hint.ToBase64();
|
||||
|
||||
BOOST_CHECK(0 == std::count(begin(base64), end(base64), '+'));
|
||||
BOOST_CHECK(0 == std::count(begin(base64), end(base64), '/'));
|
||||
|
||||
const auto decoded = Hint::FromBase64(base64);
|
||||
const auto decoded = SegmentHint::FromBase64(base64);
|
||||
|
||||
BOOST_CHECK_EQUAL(hint, decoded);
|
||||
BOOST_CHECK_EQUAL(seg_hint, decoded);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip_bytewise)
|
||||
@@ -65,12 +65,12 @@ BOOST_AUTO_TEST_CASE(hint_encoding_decoding_roundtrip_bytewise)
|
||||
const PhantomNode phantom;
|
||||
const osrm::test::MockDataFacade<osrm::engine::routing_algorithms::ch::Algorithm> facade{};
|
||||
|
||||
const Hint hint{phantom, facade.GetCheckSum()};
|
||||
const SegmentHint seg_hint{phantom, facade.GetCheckSum()};
|
||||
|
||||
const auto decoded = Hint::FromBase64(hint.ToBase64());
|
||||
const auto decoded = SegmentHint::FromBase64(seg_hint.ToBase64());
|
||||
|
||||
BOOST_CHECK(std::equal(reinterpret_cast<const unsigned char *>(&hint),
|
||||
reinterpret_cast<const unsigned char *>(&hint) + sizeof(Hint),
|
||||
BOOST_CHECK(std::equal(reinterpret_cast<const unsigned char *>(&seg_hint),
|
||||
reinterpret_cast<const unsigned char *>(&seg_hint) + sizeof(Hint),
|
||||
reinterpret_cast<const unsigned char *>(&decoded)));
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result)
|
||||
PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none};
|
||||
InternalRouteResult one_leg_result;
|
||||
one_leg_result.unpacked_path_segments = {{pathy, kathy}};
|
||||
one_leg_result.segment_end_coordinates = {PhantomNodes{source, target}};
|
||||
one_leg_result.leg_endpoints = {PhantomEndpoints{source, target}};
|
||||
one_leg_result.source_traversed_in_reverse = {true};
|
||||
one_leg_result.target_traversed_in_reverse = {true};
|
||||
one_leg_result.shortest_path_weight = 50;
|
||||
@@ -50,18 +50,17 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg)
|
||||
node_3.forward_segment_id = {12, true};
|
||||
InternalRouteResult two_leg_result;
|
||||
two_leg_result.unpacked_path_segments = {{pathy, kathy}, {kathy, cathy}};
|
||||
two_leg_result.segment_end_coordinates = {PhantomNodes{node_1, node_2},
|
||||
PhantomNodes{node_2, node_3}};
|
||||
two_leg_result.leg_endpoints = {PhantomEndpoints{node_1, node_2},
|
||||
PhantomEndpoints{node_2, node_3}};
|
||||
two_leg_result.source_traversed_in_reverse = {true, false};
|
||||
two_leg_result.target_traversed_in_reverse = {true, false};
|
||||
two_leg_result.shortest_path_weight = 80;
|
||||
|
||||
auto collapsed = CollapseInternalRouteResult(two_leg_result, {true, false, true, true});
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments.size(), 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates.size(), 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[0].target_phantom.forward_segment_id.id,
|
||||
12);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[0].source_phantom.forward_segment_id.id, 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints.size(), 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[0].target_phantom.forward_segment_id.id, 12);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[0].source_phantom.forward_segment_id.id, 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0].size(), 4);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0][0].turn_via_node, 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0][1].turn_via_node, 1);
|
||||
@@ -88,20 +87,20 @@ BOOST_AUTO_TEST_CASE(three_legs_to_two_legs)
|
||||
three_leg_result.unpacked_path_segments = {std::vector<PathData>{pathy, kathy},
|
||||
std::vector<PathData>{kathy, qathy, cathy},
|
||||
std::vector<PathData>{cathy, mathy}};
|
||||
three_leg_result.segment_end_coordinates = {
|
||||
PhantomNodes{node_1, node_2}, PhantomNodes{node_2, node_3}, PhantomNodes{node_3, node_4}};
|
||||
three_leg_result.leg_endpoints = {PhantomEndpoints{node_1, node_2},
|
||||
PhantomEndpoints{node_2, node_3},
|
||||
PhantomEndpoints{node_3, node_4}};
|
||||
three_leg_result.source_traversed_in_reverse = {true, false, true},
|
||||
three_leg_result.target_traversed_in_reverse = {true, false, true},
|
||||
three_leg_result.shortest_path_weight = 140;
|
||||
|
||||
auto collapsed = CollapseInternalRouteResult(three_leg_result, {true, true, false, true});
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments.size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates.size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[0].source_phantom.forward_segment_id.id, 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[0].target_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[1].source_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[1].target_phantom.forward_segment_id.id,
|
||||
18);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints.size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[0].source_phantom.forward_segment_id.id, 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[0].target_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[1].source_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[1].target_phantom.forward_segment_id.id, 18);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0].size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[1].size(), 5);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0][0].turn_via_node, 2);
|
||||
@@ -126,20 +125,19 @@ BOOST_AUTO_TEST_CASE(two_legs_to_two_legs)
|
||||
node_3.forward_segment_id = {12, true};
|
||||
InternalRouteResult two_leg_result;
|
||||
two_leg_result.unpacked_path_segments = {{pathy, kathy}, {kathy, cathy}};
|
||||
two_leg_result.segment_end_coordinates = {PhantomNodes{node_1, node_2},
|
||||
PhantomNodes{node_2, node_3}};
|
||||
two_leg_result.leg_endpoints = {PhantomEndpoints{node_1, node_2},
|
||||
PhantomEndpoints{node_2, node_3}};
|
||||
two_leg_result.source_traversed_in_reverse = {true, false};
|
||||
two_leg_result.target_traversed_in_reverse = {true, false};
|
||||
two_leg_result.shortest_path_weight = 80;
|
||||
|
||||
auto collapsed = CollapseInternalRouteResult(two_leg_result, {true, true, true});
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments.size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates.size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[0].source_phantom.forward_segment_id.id, 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[0].target_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[1].source_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.segment_end_coordinates[1].target_phantom.forward_segment_id.id,
|
||||
12);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints.size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[0].source_phantom.forward_segment_id.id, 1);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[0].target_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[1].source_phantom.forward_segment_id.id, 6);
|
||||
BOOST_CHECK_EQUAL(collapsed.leg_endpoints[1].target_phantom.forward_segment_id.id, 12);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0].size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[1].size(), 2);
|
||||
BOOST_CHECK_EQUAL(collapsed.unpacked_path_segments[0][0].turn_via_node, 2);
|
||||
|
||||
@@ -224,101 +224,35 @@ class ContiguousInternalMemoryDataFacade<routing_algorithms::offline::Algorithm>
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
std::vector<engine::PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
|
||||
const float /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/,
|
||||
const double /*max_distance*/,
|
||||
const boost::optional<engine::Bearing> /*bearing*/,
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodesInRange(const util::Coordinate /*input_coordinate*/,
|
||||
const float /*max_distance*/,
|
||||
const Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
std::vector<engine::PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
|
||||
const unsigned /*max_results*/,
|
||||
const double /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/) const override
|
||||
const size_t /*max_results*/,
|
||||
const boost::optional<double> /*max_distance*/,
|
||||
const boost::optional<engine::Bearing> /*bearing*/,
|
||||
const engine::Approach /*approach*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
|
||||
const unsigned /*max_results*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/) const override
|
||||
engine::PhantomCandidateAlternatives NearestCandidatesWithAlternativeFromBigComponent(
|
||||
const util::Coordinate /*input_coordinate*/,
|
||||
const boost::optional<double> /*max_distance*/,
|
||||
const boost::optional<engine::Bearing> /*bearing*/,
|
||||
const engine::Approach /*approach*/,
|
||||
const bool /*use_all_edges*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
|
||||
const unsigned /*max_results*/,
|
||||
const Approach /*approach*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<PhantomNodeWithDistance>
|
||||
NearestPhantomNodes(const util::Coordinate /*input_coordinate*/,
|
||||
const unsigned /*max_results*/,
|
||||
const double /*max_distance*/,
|
||||
const Approach /*approach*/) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const double /*max_distance*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<PhantomNode, PhantomNode>
|
||||
NearestPhantomNodeWithAlternativeFromBigComponent(const util::Coordinate /*input_coordinate*/,
|
||||
const int /*bearing*/,
|
||||
const int /*bearing_range*/,
|
||||
const Approach /*approach*/,
|
||||
const bool /* use_all_edges */) const override
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
util::guidance::LaneTupleIdPair GetLaneData(const EdgeID /*id*/) const override
|
||||
{
|
||||
@@ -394,15 +328,16 @@ namespace routing_algorithms
|
||||
namespace offline
|
||||
{
|
||||
|
||||
template <typename PhantomT>
|
||||
inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
|
||||
EdgeWeight &weight,
|
||||
std::vector<NodeID> &packed_leg,
|
||||
const bool force_loop_forward,
|
||||
const bool force_loop_reverse,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
const std::vector<NodeID> &forward_loop_nodes,
|
||||
const std::vector<NodeID> &reverse_loop_nodes,
|
||||
const PhantomT &endpoints,
|
||||
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
mld::search(engine_working_data,
|
||||
@@ -411,9 +346,9 @@ inline void search(SearchEngineData<Algorithm> &engine_working_data,
|
||||
reverse_heap,
|
||||
weight,
|
||||
packed_leg,
|
||||
force_loop_forward,
|
||||
force_loop_reverse,
|
||||
phantom_nodes,
|
||||
forward_loop_nodes,
|
||||
reverse_loop_nodes,
|
||||
endpoints,
|
||||
weight_upper_bound);
|
||||
}
|
||||
|
||||
@@ -421,10 +356,10 @@ template <typename RandomIter, typename FacadeT>
|
||||
void unpackPath(const FacadeT &facade,
|
||||
RandomIter packed_path_begin,
|
||||
RandomIter packed_path_end,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
const PhantomEndpoints &endpoints,
|
||||
std::vector<PathData> &unpacked_path)
|
||||
{
|
||||
mld::unpackPath(facade, packed_path_begin, packed_path_end, phantom_nodes, unpacked_path);
|
||||
mld::unpackPath(facade, packed_path_begin, packed_path_end, endpoints, unpacked_path);
|
||||
}
|
||||
|
||||
} // namespace offline
|
||||
@@ -442,11 +377,12 @@ BOOST_AUTO_TEST_CASE(shortest_path)
|
||||
osrm::engine::SearchEngineData<Algorithm> heaps;
|
||||
osrm::engine::datafacade::ContiguousInternalMemoryDataFacade<Algorithm> facade;
|
||||
|
||||
std::vector<osrm::engine::PhantomNodes> phantom_nodes;
|
||||
phantom_nodes.push_back({osrm::engine::PhantomNode{}, osrm::engine::PhantomNode{}});
|
||||
std::vector<osrm::engine::PhantomNodeCandidates> waypoints;
|
||||
waypoints.push_back({osrm::engine::PhantomNode{}});
|
||||
waypoints.push_back({osrm::engine::PhantomNode{}});
|
||||
|
||||
auto route =
|
||||
osrm::engine::routing_algorithms::shortestPathSearch(heaps, facade, phantom_nodes, false);
|
||||
osrm::engine::routing_algorithms::shortestPathSearch(heaps, facade, waypoints, false);
|
||||
|
||||
BOOST_CHECK_EQUAL(route.shortest_path_weight, INVALID_EDGE_WEIGHT);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user