From c2015a839382cba16bf78d0a8a243c159d4fe2f0 Mon Sep 17 00:00:00 2001 From: Vsevolod Novikov Date: Mon, 15 Feb 2021 14:33:32 +0300 Subject: [PATCH] #5325 unit tests and fixes after tests --- .../routing_algorithms/routing_base.hpp | 1 + src/engine/guidance/post_processing.cpp | 4 + .../engine/collapse_internal_route_result.cpp | 26 +-- unit_tests/library/route.cpp | 164 +++++++++++++++++- 4 files changed, 181 insertions(+), 14 deletions(-) diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index 855c38d24..c4a5007fc 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -194,6 +194,7 @@ void annotatePath(const FacadeT &facade, BOOST_ASSERT(datasource_vector.size() > 0); BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size()); BOOST_ASSERT(duration_vector.size() + 1 == id_vector.size()); + BOOST_ASSERT(osm_way_id_vector.size() + 1 == id_vector.size()); const bool is_first_segment = unpacked_path.empty(); diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index b5a280472..6161845ab 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -281,6 +281,8 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.annotations.begin() + offset); geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(), geometry.osm_node_ids.begin() + offset); + geometry.osm_way_ids.erase(geometry.osm_way_ids.begin(), + geometry.osm_way_ids.begin() + offset); } auto const first_bearing = steps.front().maneuver.bearing_after; @@ -378,6 +380,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.locations.resize(geometry.segment_offsets.back() + 1); geometry.annotations.resize(geometry.segment_offsets.back()); geometry.osm_node_ids.resize(geometry.segment_offsets.back() + 1); + geometry.osm_way_ids.resize(geometry.segment_offsets.back()); BOOST_ASSERT(geometry.segment_distances.back() <= 1); geometry.segment_distances.pop_back(); @@ -415,6 +418,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.locations.pop_back(); geometry.annotations.pop_back(); geometry.osm_node_ids.pop_back(); + geometry.osm_way_ids.pop_back(); geometry.segment_offsets.back()--; // since the last geometry includes the location of arrival, the arrival instruction // geometry overlaps with the previous segment diff --git a/unit_tests/engine/collapse_internal_route_result.cpp b/unit_tests/engine/collapse_internal_route_result.cpp index fc989ba57..52a097b47 100644 --- a/unit_tests/engine/collapse_internal_route_result.cpp +++ b/unit_tests/engine/collapse_internal_route_result.cpp @@ -19,8 +19,8 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result) PhantomNode target; source.forward_segment_id = {1, true}; target.forward_segment_id = {6, true}; - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; InternalRouteResult one_leg_result; one_leg_result.unpacked_path_segments = {{pathy, kathy}}; one_leg_result.segment_end_coordinates = {PhantomNodes{source, target}}; @@ -41,9 +41,9 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) // weight_of_turn, // duration_until_turn, duration_of_turn, turn_instruction, lane_data, travel_mode, classes, // entry_class, datasource_id, pre_turn_bearing, post_turn_bearing, left_hand - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData cathy{0, 0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -73,11 +73,11 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) { - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData qathy{0, 5, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData mathy{0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData qathy{0, 0, 5, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData cathy{0, 0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData mathy{0, 0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -117,9 +117,9 @@ BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) BOOST_AUTO_TEST_CASE(two_legs_to_two_legs) { - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData cathy{0, 0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp index 44fcb877b..cd853f4b0 100644 --- a/unit_tests/library/route.cpp +++ b/unit_tests/library/route.cpp @@ -14,6 +14,12 @@ #include "osrm/osrm.hpp" #include "osrm/route_parameters.hpp" #include "osrm/status.hpp" +#include +#include +#include +#include +#include +#include osrm::Status run_route_json(const osrm::OSRM &osrm, const osrm::RouteParameters ¶ms, @@ -584,7 +590,7 @@ void test_manual_setting_of_annotations_property(bool use_json_only_api) .values["annotation"] .get() .values; - BOOST_CHECK_EQUAL(annotations.size(), 6); + BOOST_CHECK_EQUAL(annotations.size(), 7); } BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_old_api) { @@ -595,6 +601,162 @@ BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_new_api) test_manual_setting_of_annotations_property(false); } +using NodePair = std::pair; +using NodePairToWayIDMap = std::map; + +NodePairToWayIDMap read_node_pair_to_way_id_map(osmium::io::Reader &osm) { + struct H: public osmium::handler::Handler { + NodePairToWayIDMap ret; + void way(const osmium::Way &way) { + auto first = osmium::unsigned_object_id_type(-1); + for( const auto &n: way.nodes() ) { + const auto second = n.positive_ref(); + if( first != osmium::unsigned_object_id_type(-1) ) { + ret[{first, second}] = way.id(); + } + first = second; + } + } + } handler; + osmium::apply(osm, handler); + return std::move(handler.ret); +} + +using LonLat = std::pair; +using LonLatVector = std::vector; + +LonLatVector check_route_annotated_ways( + std::vector &coordinates, + osrm::OSRM &osrm, + NodePairToWayIDMap &node_pair_to_way_id_map, + bool use_steps +) { + LonLatVector ret; + using namespace osrm; + (void) node_pair_to_way_id_map; + RouteParameters params{}; + params.annotations_type = + RouteParameters::AnnotationsType::Nodes | + RouteParameters::AnnotationsType::Ways; + params.steps = use_steps; + params.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; + params.coordinates = coordinates; + + json::Object json_result; + const auto rc = run_route_json(osrm, params, json_result, true); + BOOST_CHECK(rc == Status::Ok); + + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + auto routes = json_result.values["routes"] + .get() + .values; + BOOST_CHECK_EQUAL(routes.size(), 1); + auto route = routes[0]; + + auto geom = route.get() + .values["geometry"] + .get() + .values["coordinates"] + .get() + .values; + + auto legs = route.get() + .values["legs"] + .get() + .values; + for(auto leg: legs) { + if( use_steps ) { + auto steps = leg.get() + .values["steps"] + .get() + .values; + for(auto step: steps) { + auto geom = step.get() + .values["geometry"] + .get() + .values["coordinates"] + .get() + .values; + for(auto gleg: geom) { + auto p = gleg.get().values; + auto lon = p[0].get().value; + auto lat = p[1].get().value; + ret.push_back(LonLat{lon, lat}); + } + } + } + auto annotations = leg.get() + .values["annotation"] + .get() + .values; + BOOST_CHECK_EQUAL(annotations.size(), 2); + + auto nodes = annotations["nodes"] + .get() + .values; + auto ways = annotations["ways"] + .get() + .values; + + BOOST_CHECK_GT(nodes.size(), 1); + BOOST_CHECK_EQUAL(nodes.size() - 1, ways.size()); + auto nodes_it = nodes.cbegin(); + auto ways_it = ways.cbegin(); + osmium::unsigned_object_id_type first = nodes_it->get().value; + for(nodes_it++; nodes_it != nodes.cend(); nodes_it++, ways_it++) { + osmium::unsigned_object_id_type second = nodes_it->get().value; + osmium::unsigned_object_id_type way_id = ways_it->get().value; + auto found = node_pair_to_way_id_map.find(NodePair(first, second)); + if( found == node_pair_to_way_id_map.end() ) + found = node_pair_to_way_id_map.find(NodePair(second, first)); + BOOST_CHECK_MESSAGE( + found != node_pair_to_way_id_map.end(), + "The node pair not found: " << first << "<->" << second + ); + BOOST_CHECK_MESSAGE( + found->second == way_id, + "The node pair way doesn't correspond: " << first << "<->" << second << "=" << found->second << "=?=" << way_id + ); + first = second; + } + } + return ret; +} + +BOOST_AUTO_TEST_CASE(test_route_annotated_ways) +{ + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + osmium::io::Reader osm(OSRM_TEST_DATA_DIR "/monaco.osm.pbf"); + NodePairToWayIDMap node_pair_to_way_id_map = read_node_pair_to_way_id_map(osm); + + auto coordinates = get_split_trace_locations(); + BOOST_TEST_MESSAGE("split_trace_locations without steps"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, false); + BOOST_TEST_MESSAGE("split_trace_locations with steps"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, true); + coordinates = get_locations_in_big_component(); + // auto coords = + BOOST_TEST_MESSAGE("locations_in_big_component without steps"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, false); + BOOST_TEST_MESSAGE("locations_in_big_component with steps"); + auto coords = check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, true); + auto c1 = coords.cbegin(), c2 = coords.cend(); + for( c1++, c2--; c1 != coords.cend() && c2 != coords.cbegin(); c1++, c2--) { + if( c1 == c2 ) + continue; + coordinates = Locations{{Longitude{c1->first},Latitude{c1->second}},{Longitude{c2->first},Latitude{c2->second}}}; + BOOST_TEST_MESSAGE( + "Checking: <" << + osrm::util::toFloating(coordinates[0].lat) << ":" << osrm::util::toFloating(coordinates[0].lon) << "> -> <" << + osrm::util::toFloating(coordinates[1].lat) << ":" << osrm::util::toFloating(coordinates[1].lon) << ">" + ); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, false); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, true); + } +} + BOOST_AUTO_TEST_CASE(test_route_serialize_fb) { auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm");