diff --git a/CHANGELOG.md b/CHANGELOG.md index dc873de0d21..31a05486ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ - CHANGED: Docker build, enabled arm64 build layer [#6172](https://github.com/Project-OSRM/osrm-backend/pull/6172) - CHANGED: Docker build, enabled apt-get update/install caching in separate layer for build phase [#6175](https://github.com/Project-OSRM/osrm-backend/pull/6175) - Routing: + - CHANGED: Lazily generate optional route path data [#6045](https://github.com/Project-OSRM/osrm-backend/pull/6045) - FIXED: Completed support for no_entry and no_exit turn restrictions. [#5988](https://github.com/Project-OSRM/osrm-backend/pull/5988) - ADDED: Add support for non-round-trips with a single fixed endpoint. [#6050](https://github.com/Project-OSRM/osrm-backend/pull/6050) diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 72244c453ac..7b4dfc02f99 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -367,7 +367,7 @@ class RouteAPI : public BaseAPI // To maintain support for uses of the old default constructors, we check // if annotations property was set manually after default construction auto requested_annotations = parameters.annotations_type; - if ((parameters.annotations == true) && + if (parameters.annotations && (parameters.annotations_type == RouteParameters::AnnotationsType::None)) { requested_annotations = RouteParameters::AnnotationsType::All; @@ -497,10 +497,10 @@ class RouteAPI : public BaseAPI std::vector nodes; if (requested_annotations & RouteParameters::AnnotationsType::Nodes) { - nodes.reserve(leg_geometry.osm_node_ids.size()); - for (const auto node_id : leg_geometry.osm_node_ids) + nodes.reserve(leg_geometry.node_ids.size()); + for (const auto node_id : leg_geometry.node_ids) { - nodes.emplace_back(static_cast(node_id)); + nodes.emplace_back(static_cast(facade.GetOSMNodeIDOfNode(node_id))); } } auto nodes_vector = fb_result.CreateVector(nodes); @@ -515,7 +515,7 @@ class RouteAPI : public BaseAPI { const auto name = facade.GetDatasourceName(i); // Length of 0 indicates the first empty name, so we can stop here - if (name.size() == 0) + if (name.empty()) break; names.emplace_back( fb_result.CreateString(std::string(facade.GetDatasourceName(i)))); @@ -763,7 +763,7 @@ class RouteAPI : public BaseAPI // To maintain support for uses of the old default constructors, we check // if annotations property was set manually after default construction auto requested_annotations = parameters.annotations_type; - if ((parameters.annotations == true) && + if (parameters.annotations && (parameters.annotations_type == RouteParameters::AnnotationsType::None)) { requested_annotations = RouteParameters::AnnotationsType::All; @@ -825,10 +825,11 @@ class RouteAPI : public BaseAPI if (requested_annotations & RouteParameters::AnnotationsType::Nodes) { util::json::Array nodes; - nodes.values.reserve(leg_geometry.osm_node_ids.size()); - for (const auto node_id : leg_geometry.osm_node_ids) + nodes.values.reserve(leg_geometry.node_ids.size()); + for (const auto node_id : leg_geometry.node_ids) { - nodes.values.push_back(static_cast(node_id)); + nodes.values.push_back( + static_cast(facade.GetOSMNodeIDOfNode(node_id))); } annotation.values["nodes"] = std::move(nodes); } @@ -842,7 +843,7 @@ class RouteAPI : public BaseAPI { const auto name = facade.GetDatasourceName(i); // Length of 0 indicates the first empty name, so we can stop here - if (name.size() == 0) + if (name.empty()) break; datasource_names.values.push_back(std::string(facade.GetDatasourceName(i))); } @@ -888,81 +889,92 @@ class RouteAPI : public BaseAPI const bool reversed_source = source_traversed_in_reverse[idx]; const bool reversed_target = target_traversed_in_reverse[idx]; - auto leg_geometry = guidance::assembleGeometry(BaseAPI::facade, - path_data, - phantoms.source_phantom, - phantoms.target_phantom, - reversed_source, - reversed_target); auto leg = guidance::assembleLeg(facade, path_data, - leg_geometry, phantoms.source_phantom, phantoms.target_phantom, - reversed_target, - parameters.steps); + reversed_target); - util::Log(logDEBUG) << "Assembling steps " << std::endl; - if (parameters.steps) + guidance::LegGeometry leg_geometry; + + // Generate additional geometry data if request includes turn-by-turn steps, + // overview geometry or route geometry annotations. + // Note that overview geometry and route geometry annotations can return different + // results depending on whether turn-by-turn steps are also requested. + if (parameters.steps || parameters.annotations || + parameters.overview != RouteParameters::OverviewType::False) { - auto steps = guidance::assembleSteps(BaseAPI::facade, - path_data, - leg_geometry, - phantoms.source_phantom, - phantoms.target_phantom, - reversed_source, - reversed_target); - - // Apply maneuver overrides before any other post - // processing is performed - guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry); - - // Collapse segregated steps before others - steps = guidance::collapseSegregatedTurnInstructions(std::move(steps)); - - /* Perform step-based post-processing. - * - * Using post-processing on basis of route-steps for a single leg at a time - * comes at the cost that we cannot count the correct exit for roundabouts. - * We can only emit the exit nr/intersections up to/starting at a part of the leg. - * If a roundabout is not terminated in a leg, we will end up with a - *enter-roundabout - * and exit-roundabout-nr where the exit nr is out of sync with the previous enter. - * - * | S | - * * * - * ----* * ---- - * T - * ----* * ---- - * V * * - * | | - * | | - * - * Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say to - *take - * the second exit, even though counting from S it would be the third. - * For S, we only emit `roundabout` without an exit number, showing that we enter a - *roundabout - * to find a via point. - * The same exit will be emitted, though, if we should start routing at S, making - * the overall response consistent. - * - * ⚠ CAUTION: order of post-processing steps is important - * - handleRoundabouts must be called before collapseTurnInstructions that - * expects post-processed roundabouts - */ - - guidance::trimShortSegments(steps, leg_geometry); - leg.steps = guidance::handleRoundabouts(std::move(steps)); - leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps)); - leg.steps = guidance::anticipateLaneChange(std::move(leg.steps)); - leg.steps = guidance::buildIntersections(std::move(leg.steps)); - leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps)); - leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), - leg_geometry, - phantoms.source_phantom, - phantoms.target_phantom); - leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps); + + leg_geometry = guidance::assembleGeometry(BaseAPI::facade, + path_data, + phantoms.source_phantom, + phantoms.target_phantom, + reversed_source, + reversed_target); + + util::Log(logDEBUG) << "Assembling steps " << std::endl; + if (parameters.steps) + { + leg.summary = guidance::assembleSummary( + facade, path_data, phantoms.target_phantom, reversed_target); + + auto steps = guidance::assembleSteps(BaseAPI::facade, + path_data, + leg_geometry, + phantoms.source_phantom, + phantoms.target_phantom, + reversed_source, + reversed_target); + + // Apply maneuver overrides before any other post + // processing is performed + guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry); + + // Collapse segregated steps before others + steps = guidance::collapseSegregatedTurnInstructions(std::move(steps)); + + /* Perform step-based post-processing. + * + * Using post-processing on basis of route-steps for a single leg at a time + * comes at the cost that we cannot count the correct exit for roundabouts. + * We can only emit the exit nr/intersections up to/starting at a part of the + *leg. If a roundabout is not terminated in a leg, we will end up with a + *enter-roundabout + * and exit-roundabout-nr where the exit nr is out of sync with the previous + *enter. + * + * | S | + * * * + * ----* * ---- + * T + * ----* * ---- + * V * * + * | | + * | | + * + * Coming from S via V to T, we end up with the legs S->V and V->T. V-T will say + *to take the second exit, even though counting from S it would be the third. + * For S, we only emit `roundabout` without an exit number, showing that we + *enter a roundabout to find a via point. The same exit will be emitted, though, + *if we should start routing at S, making the overall response consistent. + * + * ⚠ CAUTION: order of post-processing steps is important + * - handleRoundabouts must be called before collapseTurnInstructions that + * expects post-processed roundabouts + */ + + guidance::trimShortSegments(steps, leg_geometry); + leg.steps = guidance::handleRoundabouts(std::move(steps)); + leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps)); + leg.steps = guidance::anticipateLaneChange(std::move(leg.steps)); + leg.steps = guidance::buildIntersections(std::move(leg.steps)); + leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps)); + leg.steps = guidance::assignRelativeLocations(std::move(leg.steps), + leg_geometry, + phantoms.source_phantom, + phantoms.target_phantom); + leg_geometry = guidance::resyncGeometry(std::move(leg_geometry), leg.steps); + } } leg_geometries.push_back(std::move(leg_geometry)); diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 736c868fd14..ad5d6cbd19f 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -57,8 +57,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id; const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id); - geometry.osm_node_ids.push_back( - facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate))); + geometry.node_ids.push_back(source_geometry(source_segment_start_coordinate)); auto cumulative_distance = 0.; auto current_distance = 0.; @@ -71,7 +70,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, cumulative_distance += current_distance; // all changes to this check have to be matched with assemble_steps - if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) + auto turn_instruction = path_point.turn_edge + ? facade.GetTurnInstructionForEdgeID(*path_point.turn_edge) + : osrm::guidance::TurnInstruction::NO_TURN(); + if (turn_instruction.type != osrm::guidance::TurnType::NoTurn) { geometry.segment_distances.push_back(cumulative_distance); geometry.segment_offsets.push_back(geometry.locations.size()); @@ -79,11 +81,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, } prev_coordinate = coordinate; + const auto node_id = path_point.turn_via_node; - const auto osm_node_id = facade.GetOSMNodeIDOfNode(path_point.turn_via_node); - - if (osm_node_id != geometry.osm_node_ids.back() || - path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) + if (node_id != geometry.node_ids.back() || + turn_instruction.type != osrm::guidance::TurnType::NoTurn) { geometry.annotations.emplace_back(LegGeometry::Annotation{ current_distance, @@ -99,7 +100,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, facade.GetWeightMultiplier(), path_point.datasource_id}); geometry.locations.push_back(std::move(coordinate)); - geometry.osm_node_ids.push_back(osm_node_id); + geometry.node_ids.push_back(node_id); } } current_distance = @@ -158,8 +159,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const auto target_segment_end_coordinate = target_node.fwd_segment_position + (reversed_target ? 0 : 1); const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id); - geometry.osm_node_ids.push_back( - facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate))); + geometry.node_ids.push_back(target_geometry(target_segment_end_coordinate)); BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1); BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size()); diff --git a/include/engine/guidance/assemble_leg.hpp b/include/engine/guidance/assemble_leg.hpp index 0a49ae81ec6..617b317cf58 100644 --- a/include/engine/guidance/assemble_leg.hpp +++ b/include/engine/guidance/assemble_leg.hpp @@ -75,10 +75,14 @@ std::array summarizeRoute(const datafacade::BaseDa std::vector segments(route_data.size()); std::uint32_t index = 0; - std::transform( - route_data.begin(), route_data.end(), segments.begin(), [&index](const PathData &point) { - return NamedSegment{point.duration_until_turn, index++, point.name_id}; - }); + std::transform(route_data.begin(), + route_data.end(), + segments.begin(), + [&index, &facade](const PathData &point) { + return NamedSegment{point.duration_until_turn, + index++, + facade.GetNameIndex(point.from_edge_based_node)}; + }); const auto target_duration = target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration; const auto target_node_id = target_traversed_in_reverse ? target_node.reverse_segment_id.id @@ -124,21 +128,59 @@ std::array summarizeRoute(const datafacade::BaseDa } } // namespace detail +inline std::string assembleSummary(const datafacade::BaseDataFacade &facade, + const std::vector &route_data, + const PhantomNode &target_node, + const bool target_traversed_in_reverse) +{ + auto summary_array = detail::summarizeRoute( + facade, route_data, target_node, target_traversed_in_reverse); + + BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0); + BOOST_ASSERT(summary_array.begin() != summary_array.end()); + + // transform a name_id into a string containing either the name, or -if the name is empty- + // the reference. + const auto name_id_to_string = [&](const NameID name_id) { + const auto name = facade.GetNameForID(name_id); + if (!name.empty()) + return name.to_string(); + else + { + const auto ref = facade.GetRefForID(name_id); + return ref.to_string(); + } + }; + + const auto not_empty = [&](const std::string &name) { return !name.empty(); }; + + const auto summary_names = summary_array | boost::adaptors::transformed(name_id_to_string) | + boost::adaptors::filtered(not_empty); + return boost::algorithm::join(summary_names, ", "); +} + inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade, const std::vector &route_data, - const LegGeometry &leg_geometry, const PhantomNode &source_node, const PhantomNode &target_node, - const bool target_traversed_in_reverse, - const bool needs_summary) + const bool target_traversed_in_reverse) { + auto distance = 0.; + auto prev_coordinate = source_node.location; + for (const auto &path_point : route_data) + { + auto coordinate = facade.GetCoordinateOfNode(path_point.turn_via_node); + distance += util::coordinate_calculation::greatCircleDistance(prev_coordinate, coordinate); + prev_coordinate = coordinate; + } + distance += + util::coordinate_calculation::greatCircleDistance(prev_coordinate, target_node.location); + const auto target_duration = (target_traversed_in_reverse ? target_node.reverse_duration : target_node.forward_duration); const auto target_weight = (target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight); - auto distance = std::accumulate( - leg_geometry.segment_distances.begin(), leg_geometry.segment_distances.end(), 0.); auto duration = std::accumulate( route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) { return sum + data.duration_until_turn; @@ -182,39 +224,10 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade, duration = std::max(0, duration); } - std::string summary; - if (needs_summary) - { - auto summary_array = detail::summarizeRoute( - facade, route_data, target_node, target_traversed_in_reverse); - - BOOST_ASSERT(detail::MAX_USED_SEGMENTS > 0); - BOOST_ASSERT(summary_array.begin() != summary_array.end()); - - // transform a name_id into a string containing either the name, or -if the name is empty- - // the reference. - const auto name_id_to_string = [&](const NameID name_id) { - const auto name = facade.GetNameForID(name_id); - if (!name.empty()) - return name.to_string(); - else - { - const auto ref = facade.GetRefForID(name_id); - return ref.to_string(); - } - }; - - const auto not_empty = [&](const std::string &name) { return !name.empty(); }; - - const auto summary_names = summary_array | boost::adaptors::transformed(name_id_to_string) | - boost::adaptors::filtered(not_empty); - summary = boost::algorithm::join(summary_names, ", "); - } - return RouteLeg{std::round(distance * 10.) / 10., duration / 10., weight / facade.GetWeightMultiplier(), - summary, + "", {}}; } diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index ac65a539f22..97d527c7b91 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -19,6 +19,7 @@ #include #include +#include #include namespace osrm @@ -96,7 +97,7 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa {}, source_classes}; - if (leg_data.size() > 0) + if (!leg_data.empty()) { // PathData saves the information we need of the segment _before_ the turn, // but a RouteStep is with regard to the segment after the turn. @@ -115,7 +116,10 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa segment_weight += path_point.weight_until_turn; // all changes to this check have to be matched with assemble_geometry - if (path_point.turn_instruction.type != osrm::guidance::TurnType::NoTurn) + const auto turn_instruction = + path_point.turn_edge ? facade.GetTurnInstructionForEdgeID(*path_point.turn_edge) + : osrm::guidance::TurnInstruction::NO_TURN(); + if (turn_instruction.type != osrm::guidance::TurnType::NoTurn) { BOOST_ASSERT(segment_weight >= 0); const auto name = facade.GetNameForID(step_name_id); @@ -125,7 +129,13 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa const auto exits = facade.GetExitsForID(step_name_id); const auto distance = leg_geometry.segment_distances[segment_index]; // intersections contain the classes of exiting road - intersection.classes = facade.GetClasses(path_point.classes); + intersection.classes = + facade.GetClasses(facade.GetClassData(path_point.from_edge_based_node)); + + const auto is_left_hand_driving = + facade.IsLeftHandDriving(path_point.from_edge_based_node); + const auto travel_mode = facade.GetTravelMode(path_point.from_edge_based_node); + BOOST_ASSERT(travel_mode > 0); steps.push_back(RouteStep{path_point.from_edge_based_node, step_name_id, @@ -140,17 +150,19 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa segment_duration / 10., distance, segment_weight / weight_multiplier, - path_point.travel_mode, + travel_mode, maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1, {intersection}, - path_point.is_left_hand_driving}); + is_left_hand_driving}); if (leg_data_index + 1 < leg_data.size()) { - step_name_id = leg_data[leg_data_index + 1].name_id; - is_segregated = leg_data[leg_data_index + 1].is_segregated; + step_name_id = + facade.GetNameIndex(leg_data[leg_data_index + 1].from_edge_based_node); + is_segregated = + facade.IsSegregated(leg_data[leg_data_index + 1].from_edge_based_node); } else { @@ -159,20 +171,33 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa } // extract bearings - bearings = std::make_pair( - path_point.pre_turn_bearing.Get(), path_point.post_turn_bearing.Get()); + auto pre_turn_bearing = path_point.turn_edge + ? facade.PreTurnBearing(*path_point.turn_edge) + : osrm::guidance::TurnBearing(0); + auto post_turn_bearing = path_point.turn_edge + ? facade.PostTurnBearing(*path_point.turn_edge) + : osrm::guidance::TurnBearing(0); + bearings = std::make_pair(pre_turn_bearing.Get(), + post_turn_bearing.Get()); const auto bearing_class = facade.GetBearingClass(path_point.turn_via_node); auto bearing_data = bearing_class.getAvailableBearings(); + + util::guidance::LaneTupleIdPair lane_data = {{0, INVALID_LANEID}, + INVALID_LANE_DESCRIPTIONID}; + if (path_point.turn_edge && facade.HasLaneData(*path_point.turn_edge)) + { + lane_data = facade.GetLaneData(*path_point.turn_edge); + } + intersection.in = bearing_class.findMatchingBearing(bearings.first); intersection.out = bearing_class.findMatchingBearing(bearings.second); intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node); intersection.bearings.clear(); intersection.bearings.reserve(bearing_data.size()); - intersection.lanes = path_point.lane_data.first; - intersection.lane_description = - path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID - ? facade.GetTurnDescription(path_point.lane_data.second) - : extractor::TurnLaneDescription(); + intersection.lanes = lane_data.first; + intersection.lane_description = lane_data.second != INVALID_LANE_DESCRIPTIONID + ? facade.GetTurnDescription(lane_data.second) + : extractor::TurnLaneDescription(); // Lanes in turn are bound by total number of lanes at the location BOOST_ASSERT(intersection.lanes.lanes_in_turn <= @@ -183,20 +208,23 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa (!intersection.lane_description.empty() && intersection.lanes.lanes_in_turn != 0)); + auto entry_class = path_point.turn_edge + ? facade.GetEntryClass(*path_point.turn_edge) + : EMPTY_ENTRY_CLASS; std::copy(bearing_data.begin(), bearing_data.end(), std::back_inserter(intersection.bearings)); intersection.entry.clear(); for (auto idx : util::irange(0, intersection.bearings.size())) { - intersection.entry.push_back(path_point.entry_class.allowsEntry(idx)); + intersection.entry.push_back(entry_class.allowsEntry(idx)); } std::int16_t bearing_in_driving_direction = util::bearing::reverse(std::round(bearings.first)); maneuver = {intersection.location, bearing_in_driving_direction, bearings.second, - path_point.turn_instruction, + turn_instruction, WaypointType::None, 0}; segment_index++; @@ -269,7 +297,7 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa leg_geometry.segment_distances[segment_index], weight / weight_multiplier, source_mode, - std::move(maneuver), + maneuver, leg_geometry.FrontIndex(segment_index), leg_geometry.BackIndex(segment_index) + 1, {intersection}, @@ -312,7 +340,7 @@ inline std::vector assembleSteps(const datafacade::BaseDataFacade &fa ZERO_DISTANCE, ZERO_WEIGHT, target_mode, - std::move(maneuver), + maneuver, leg_geometry.locations.size() - 1, leg_geometry.locations.size(), {intersection}, diff --git a/include/engine/guidance/leg_geometry.hpp b/include/engine/guidance/leg_geometry.hpp index 8374bb99261..78ebd42ad84 100644 --- a/include/engine/guidance/leg_geometry.hpp +++ b/include/engine/guidance/leg_geometry.hpp @@ -32,7 +32,7 @@ struct LegGeometry // length of the segment in meters std::vector segment_distances; // original OSM node IDs for each coordinate - std::vector osm_node_ids; + std::vector node_ids; // Per-coordinate metadata struct Annotation diff --git a/include/engine/internal_route_result.hpp b/include/engine/internal_route_result.hpp index 9f5443ffa0f..4ee80ab6a35 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -15,6 +15,7 @@ #include "util/integer_range.hpp" #include "util/typedefs.hpp" +#include #include namespace osrm @@ -28,43 +29,22 @@ struct PathData NodeID from_edge_based_node; // the internal OSRM id of the OSM node id that is the via node of the turn NodeID turn_via_node; - // name of the street that leads to the turn - unsigned name_id; - // segregated edge-based node that leads to the turn - bool is_segregated; // weight that is traveled on the segment until the turn is reached // including the turn weight, if one exists EdgeWeight weight_until_turn; - // If this segment immediately preceeds a turn, then duration_of_turn + // If this segment immediately precedes a turn, then duration_of_turn // will contain the weight of the turn. Otherwise it will be 0. EdgeWeight weight_of_turn; // duration that is traveled on the segment until the turn is reached, - // including a turn if the segment preceeds one. + // including a turn if the segment precedes one. EdgeWeight duration_until_turn; - // If this segment immediately preceeds a turn, then duration_of_turn + // If this segment immediately precedes a turn, then duration_of_turn // will contain the duration of the turn. Otherwise it will be 0. EdgeWeight duration_of_turn; - // instruction to execute at the turn - osrm::guidance::TurnInstruction turn_instruction; - // turn lane data - util::guidance::LaneTupleIdPair lane_data; - // travel mode of the street that leads to the turn - extractor::TravelMode travel_mode : 4; - // user defined classed of the street that leads to the turn - extractor::ClassData classes; - // entry class of the turn, indicating possibility of turns - util::guidance::EntryClass entry_class; - // Source of the speed value on this road segment DatasourceID datasource_id; - - // bearing (as seen from the intersection) pre-turn - osrm::guidance::TurnBearing pre_turn_bearing; - // bearing (as seen from the intersection) post-turn - osrm::guidance::TurnBearing post_turn_bearing; - - // Driving side of the turn - bool is_left_hand_driving; + // If segment precedes a turn, ID of the turn itself + boost::optional turn_edge; }; struct InternalRouteResult diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index c7df59e80f0..59a0113fe8e 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -176,11 +176,6 @@ void annotatePath(const FacadeT &facade, const auto &edge_data = facade.GetEdgeData(*edge); const auto turn_id = edge_data.turn_id; // edge-based graph edge index const auto node_id = *node_from; // edge-based graph node index - const auto name_index = facade.GetNameIndex(node_id); - const bool is_segregated = facade.IsSegregated(node_id); - const auto turn_instruction = facade.GetTurnInstructionForEdgeID(turn_id); - const extractor::TravelMode travel_mode = facade.GetTravelMode(node_id); - const auto classes = facade.GetClassData(node_id); const auto geometry_index = facade.GetGeometryIndex(node_id); get_segment_geometry(geometry_index); @@ -206,45 +201,29 @@ void annotatePath(const FacadeT &facade, } const std::size_t end_index = weight_vector.size(); - bool is_left_hand_driving = facade.IsLeftHandDriving(node_id); - BOOST_ASSERT(start_index < end_index); for (std::size_t segment_idx = start_index; segment_idx < end_index; ++segment_idx) { unpacked_path.push_back( - PathData{*node_from, + PathData{node_id, id_vector[segment_idx + 1], - name_index, - is_segregated, static_cast(weight_vector[segment_idx]), 0, static_cast(duration_vector[segment_idx]), 0, - guidance::TurnInstruction::NO_TURN(), - {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, - travel_mode, - classes, - EMPTY_ENTRY_CLASS, datasource_vector[segment_idx], - osrm::guidance::TurnBearing(0), - osrm::guidance::TurnBearing(0), - is_left_hand_driving}); + boost::none}); } BOOST_ASSERT(unpacked_path.size() > 0); - if (facade.HasLaneData(turn_id)) - unpacked_path.back().lane_data = facade.GetLaneData(turn_id); const auto turn_duration = facade.GetDurationPenaltyForEdgeID(turn_id); const auto turn_weight = facade.GetWeightPenaltyForEdgeID(turn_id); - unpacked_path.back().entry_class = facade.GetEntryClass(turn_id); - unpacked_path.back().turn_instruction = turn_instruction; unpacked_path.back().duration_until_turn += turn_duration; unpacked_path.back().duration_of_turn = turn_duration; unpacked_path.back().weight_until_turn += turn_weight; unpacked_path.back().weight_of_turn = turn_weight; - unpacked_path.back().pre_turn_bearing = facade.PreTurnBearing(turn_id); - unpacked_path.back().post_turn_bearing = facade.PostTurnBearing(turn_id); + unpacked_path.back().turn_edge = turn_id; } std::size_t start_index = 0, end_index = 0; @@ -280,33 +259,22 @@ void annotatePath(const FacadeT &facade, // t: fwd_segment 3 // -> (U, v), (v, w), (w, x) // note that (x, t) is _not_ included but needs to be added later. - bool is_target_left_hand_driving = facade.IsLeftHandDriving(target_node_id); for (std::size_t segment_idx = start_index; segment_idx != end_index; (start_index < end_index ? ++segment_idx : --segment_idx)) { BOOST_ASSERT(segment_idx < static_cast(id_vector.size() - 1)); - BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0); unpacked_path.push_back( PathData{target_node_id, id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], - facade.GetNameIndex(target_node_id), - facade.IsSegregated(target_node_id), static_cast(weight_vector[segment_idx]), 0, static_cast(duration_vector[segment_idx]), 0, - guidance::TurnInstruction::NO_TURN(), - {{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID}, - facade.GetTravelMode(target_node_id), - facade.GetClassData(target_node_id), - EMPTY_ENTRY_CLASS, datasource_vector[segment_idx], - guidance::TurnBearing(0), - guidance::TurnBearing(0), - is_target_left_hand_driving}); + boost::none}); } - if (unpacked_path.size() > 0) + if (!unpacked_path.empty()) { const auto source_weight = start_traversed_in_reverse ? phantom_node_pair.source_phantom.reverse_weight diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index f510e04b0df..ac73e75b762 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -279,8 +279,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.locations.begin() + offset); geometry.annotations.erase(geometry.annotations.begin(), geometry.annotations.begin() + offset); - geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(), - geometry.osm_node_ids.begin() + offset); + geometry.node_ids.erase(geometry.node_ids.begin(), geometry.node_ids.begin() + offset); } auto const first_bearing = steps.front().maneuver.bearing_after; @@ -377,7 +376,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) // remove all the last coordinates from the 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.node_ids.resize(geometry.segment_offsets.back() + 1); BOOST_ASSERT(geometry.segment_distances.back() <= 1); geometry.segment_distances.pop_back(); @@ -414,7 +413,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) // This can happen if the last coordinate snaps to a node in the unpacked geometry geometry.locations.pop_back(); geometry.annotations.pop_back(); - geometry.osm_node_ids.pop_back(); + geometry.node_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 @@ -436,7 +435,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) } BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.locations.size()); - BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.osm_node_ids.size()); + BOOST_ASSERT(geometry.segment_offsets.back() + 1 == geometry.node_ids.size()); BOOST_ASSERT(geometry.segment_offsets.back() == geometry.annotations.size()); BOOST_ASSERT(steps.back().geometry_end == geometry.locations.size()); @@ -541,7 +540,7 @@ std::vector buildIntersections(std::vector steps) { // End of road is a turn that helps to identify the location of a turn. If the turn does - // not pass by any oter intersections, the end-of-road characteristic does not improve + // not pass by any other intersections, the end-of-road characteristic does not improve // the instructions. // Here we reduce the verbosity of our output by reducing end-of-road emissions in cases // where no intersections have been passed in between. diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index edef3d58951..b1f94a7b63b 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -71,7 +71,7 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory( const extractor::LaneDescriptionMap &lane_description_map) : m_edge_based_node_container(node_data_container), m_connectivity_checksum(0), m_number_of_edge_based_nodes(0), m_coordinates(coordinates), - m_node_based_graph(std::move(node_based_graph)), m_barrier_nodes(barrier_nodes), + m_node_based_graph(node_based_graph), m_barrier_nodes(barrier_nodes), m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container), name_table(name_table), segregated_edges(segregated_edges), lane_description_map(lane_description_map) diff --git a/unit_tests/engine/collapse_internal_route_result.cpp b/unit_tests/engine/collapse_internal_route_result.cpp index fc989ba5714..c14fa3967c8 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, 2, 2, 3, 4, 5, 2, boost::none}; + 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}}; @@ -37,13 +37,11 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result) BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) { - // from_edge_based_node, turn_via_node, name_id, is_segregated, weight_until_turn, - // 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}; + // from_edge_based_node, turn_via_node, weight_until_turn, weight_of_turn, + // duration_until_turn, duration_of_turn, datasource_id, turn_edge + PathData pathy{0, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; + PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -73,11 +71,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, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; + PathData qathy{0, 5, 1, 2, 3, 4, 1, boost::none}; + PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none}; + PathData mathy{0, 4, 8, 9, 13, 4, 2, boost::none}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -117,9 +115,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, 2, 2, 3, 4, 5, 2, boost::none}; + PathData kathy{0, 1, 1, 2, 3, 4, 1, boost::none}; + PathData cathy{0, 3, 1, 2, 3, 4, 1, boost::none}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; diff --git a/unit_tests/engine/guidance_assembly.cpp b/unit_tests/engine/guidance_assembly.cpp index 2560fb0466b..10ba1821dd6 100644 --- a/unit_tests/engine/guidance_assembly.cpp +++ b/unit_tests/engine/guidance_assembly.cpp @@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments) {FloatLongitude{-73.981495}, FloatLatitude{40.768275}}}; geometry.segment_offsets = {0, 2}; geometry.segment_distances = {1.9076601161280742}; - geometry.osm_node_ids = {OSMNodeID{0}, OSMNodeID{1}, OSMNodeID{2}}; + geometry.node_ids = {NodeID{0}, NodeID{1}, NodeID{2}}; geometry.annotations = {{1.9076601161280742, 0.2, 0.2, 0}, {0, 0, 0, 0}}; trimShortSegments(steps, geometry); @@ -102,7 +102,7 @@ BOOST_AUTO_TEST_CASE(trim_short_segments) BOOST_CHECK_EQUAL(geometry.segment_offsets.back(), 1); BOOST_CHECK_EQUAL(geometry.annotations.size(), 1); BOOST_CHECK_EQUAL(geometry.locations.size(), 2); - BOOST_CHECK_EQUAL(geometry.osm_node_ids.size(), 2); + BOOST_CHECK_EQUAL(geometry.node_ids.size(), 2); } BOOST_AUTO_TEST_SUITE_END()