diff --git a/CHANGELOG.md b/CHANGELOG.md index b131602a2..a7ab645fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # UNRELEASED - Changes from 5.15.0: + - Bugfixes: + - FIXED: Segfault in map matching when RouteLeg collapsing code is run on a match with multiple submatches - Profile: - FIXED: `highway=service` will now be used for restricted access, `access=private` is still disabled for snapping. - ADDED #4775: Exposes more information to the turn function, now being able to set turn weights with highway and access information of the turn as well as other roads at the intersection [#4775](https://github.com/Project-OSRM/osrm-backend/issues/4775) diff --git a/features/testbot/matching.feature b/features/testbot/matching.feature index 77eea3545..35a7e0b8d 100644 --- a/features/testbot/matching.feature +++ b/features/testbot/matching.feature @@ -603,3 +603,26 @@ Feature: Basic Map Matching When I match I should get | trace | timestamps | code | | ab1d | 0 1 2 3 | NoMatch | + + Scenario: Regression test - avoid collapsing legs of a tidied split trace + Given a grid size of 20 meters + Given the node map + """ + a--b--f + | + | + e--c---d--g + """ + Given the query options + | tidy | true | + + And the ways + | nodes | oneway | + | abf | no | + | be | no | + | ecdg | no | + + When I match I should get + | trace | timestamps | matchings | code | + | abbecd | 10 11 27 1516914902 1516914913 1516914952 | ab,ecd | Ok | + diff --git a/include/engine/api/match_parameters_tidy.hpp b/include/engine/api/match_parameters_tidy.hpp index 7a54b0605..ab4610c4f 100644 --- a/include/engine/api/match_parameters_tidy.hpp +++ b/include/engine/api/match_parameters_tidy.hpp @@ -48,12 +48,14 @@ inline Result keep_all(const MatchParameters ¶ms) result.can_be_removed.resize(params.coordinates.size(), false); result.was_waypoint.resize(params.coordinates.size(), true); + // by default all input coordinates are treated as waypoints if (!params.waypoints.empty()) { for (const auto p : params.waypoints) { result.was_waypoint.set(p, false); } + // logic is a little funny, uses inversion to set the bitfield result.was_waypoint.flip(); } result.tidied_to_original.reserve(params.coordinates.size()); diff --git a/src/engine/plugins/match.cpp b/src/engine/plugins/match.cpp index c35f43eff..2319abc02 100644 --- a/src/engine/plugins/match.cpp +++ b/src/engine/plugins/match.cpp @@ -247,6 +247,7 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, } // Error: Check if user-supplied waypoints can be found in the resulting matches + if (!parameters.waypoints.empty()) { std::set tidied_waypoints(tidied.parameters.waypoints.begin(), tidied.parameters.waypoints.end()); @@ -262,6 +263,9 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, "NoMatch", "Requested waypoint parameter could not be matched.", json_result); } } + // we haven't errored yet, only allow leg collapsing if it was originally requested + BOOST_ASSERT(parameters.waypoints.empty() || sub_matchings.size() == 1); + const auto collapse_legs = !parameters.waypoints.empty(); // each sub_route will correspond to a MatchObject std::vector sub_routes(sub_matchings.size()); @@ -286,7 +290,7 @@ Status MatchPlugin::HandleRequest(const RoutingAlgorithmsInterface &algorithms, sub_routes[index] = algorithms.ShortestPathSearch(sub_routes[index].segment_end_coordinates, {false}); BOOST_ASSERT(sub_routes[index].shortest_path_weight != INVALID_EDGE_WEIGHT); - if (!tidied.parameters.waypoints.empty()) + if (collapse_legs) { std::vector waypoint_legs; waypoint_legs.reserve(sub_matchings[index].indices.size());