diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 51248a15d..3f278b9b6 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -173,7 +173,7 @@ class RouteAPI : public BaseAPI guidance::trimShortSegments(steps, leg_geometry); leg.steps = guidance::handleRoundabouts(std::move(steps)); - leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps), facade); + 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)); diff --git a/include/engine/guidance/collapse_turns.hpp b/include/engine/guidance/collapse_turns.hpp index 2518038b3..7a15eb0d2 100644 --- a/include/engine/guidance/collapse_turns.hpp +++ b/include/engine/guidance/collapse_turns.hpp @@ -20,8 +20,7 @@ namespace guidance // Collapsing such turns into a single turn instruction, we give a clearer // set of instructionst that is not cluttered by unnecessary turns/name changes. OSRM_ATTR_WARN_UNUSED -std::vector collapseTurnInstructions(std::vector steps, - const datafacade::BaseDataFacade &facade); +std::vector collapseTurnInstructions(std::vector steps); // A combined turn is a set of two instructions that actually form a single turn, as far as we // perceive it. A u-turn consisting of two left turns is one such example. But there are also lots diff --git a/src/engine/guidance/collapse_scenario_detection.cpp b/src/engine/guidance/collapse_scenario_detection.cpp index 4b7c82aff..562b75e5e 100644 --- a/src/engine/guidance/collapse_scenario_detection.cpp +++ b/src/engine/guidance/collapse_scenario_detection.cpp @@ -41,14 +41,14 @@ bool noIntermediaryIntersections(const RouteStep &step) } // Link roads, as far as we are concerned, are short unnamed segments between to named segments. -bool isLinkRoad(const RouteStep &link_step, - const std::string &pre_link_step_name, - const std::string &post_link_step_name) +bool isLinkRoad(const RouteStep &pre_link_step, + const RouteStep &link_step, + const RouteStep &post_link_step) { const constexpr double MAX_LINK_ROAD_LENGTH = 2 * MAX_COLLAPSE_DISTANCE; const auto is_short = link_step.distance <= MAX_LINK_ROAD_LENGTH; const auto unnamed = link_step.name.empty(); - const auto between_named = !pre_link_step_name.empty() && !post_link_step_name.empty(); + const auto between_named = !pre_link_step.name.empty() && !post_link_step.name.empty(); return is_short && unnamed && between_named && noIntermediaryIntersections(link_step); } @@ -163,9 +163,6 @@ bool isStaggeredIntersection(const RouteStepIterator step_prior_to_intersection, bool isUTurn(const RouteStepIterator step_prior_to_intersection, const RouteStepIterator step_entering_intersection, const RouteStepIterator step_leaving_intersection) -// const std::string &step_prior_name, -// const std::string &step_entering_name, -// const std::string &step_leaving_name) { if (!basicCollapsePreconditions( step_prior_to_intersection, step_entering_intersection, step_leaving_intersection)) @@ -198,9 +195,9 @@ bool isUTurn(const RouteStepIterator step_prior_to_intersection, const auto only_allowed_turn = (numberOfAllowedTurns(*step_leaving_intersection) == 1) && noIntermediaryIntersections(*step_entering_intersection); - return collapsable || isLinkRoad(*step_entering_intersection, - step_prior_to_intersection->name, - step_leaving_intersection->name) || + return collapsable || isLinkRoad(*step_prior_to_intersection, + *step_entering_intersection, + *step_leaving_intersection) || only_allowed_turn; } diff --git a/src/engine/guidance/collapse_turns.cpp b/src/engine/guidance/collapse_turns.cpp index 77254f930..96eeb6470 100644 --- a/src/engine/guidance/collapse_turns.cpp +++ b/src/engine/guidance/collapse_turns.cpp @@ -326,7 +326,7 @@ void suppressStep(RouteStep &step_at_turn_location, RouteStep &step_after_turn_l // OTHER IMPLEMENTATIONS OSRM_ATTR_WARN_UNUSED -RouteSteps collapseTurnInstructions(RouteSteps steps, const datafacade::BaseDataFacade &facade) +RouteSteps collapseTurnInstructions(RouteSteps steps) { // make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn) BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back())); @@ -464,7 +464,6 @@ RouteSteps collapseTurnInstructions(RouteSteps steps, const datafacade::BaseData if (!hasWaypointType(*previous_step)) { const auto far_back_step = findPreviousTurn(previous_step); - const auto far_back_step_name = facade.GetNameForID(far_back_step->name_id).to_string(); // due to name changes, we can find u-turns a bit late. Thats why we check far back as // well if (isUTurn(far_back_step, previous_step, current_step)) diff --git a/src/extractor/guidance/intersection_handler.cpp b/src/extractor/guidance/intersection_handler.cpp index eee2ecfad..012ff78ad 100644 --- a/src/extractor/guidance/intersection_handler.cpp +++ b/src/extractor/guidance/intersection_handler.cpp @@ -77,13 +77,13 @@ TurnType::Enum IntersectionHandler::findBasicTurnType(const EdgeID via_edge, const auto &out_name_id = node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data) .name_id; - const auto &in_name = name_table.GetNameForID(in_name_id).to_string(); - const auto &out_name = name_table.GetNameForID(out_name_id).to_string(); + const auto &in_name_empty = name_table.GetNameForID(in_name_id).to_string().empty(); + const auto &out_name_empty = name_table.GetNameForID(out_name_id).to_string().empty(); const auto same_name = !util::guidance::requiresNameAnnounced( in_name_id, out_name_id, name_table, street_name_suffix_table); - if (!in_name.empty() && !out_name.empty() && same_name) + if (!in_name_empty && !out_name_empty && same_name) { return TurnType::Continue; } diff --git a/src/extractor/guidance/mergable_road_detector.cpp b/src/extractor/guidance/mergable_road_detector.cpp index 16bcb937f..fb8a39800 100644 --- a/src/extractor/guidance/mergable_road_detector.cpp +++ b/src/extractor/guidance/mergable_road_detector.cpp @@ -23,6 +23,8 @@ namespace guidance namespace { // check a connected road for equality of a name +// returns 'true' if no equality because this is used as a filter elsewhere, i.e. filter if fn +// returns 'true' inline auto makeCheckRoadForName(const NameID name_id, const util::NodeBasedDynamicGraph &node_based_graph, const EdgeBasedNodeDataContainer &node_data_container, @@ -36,8 +38,11 @@ inline auto makeCheckRoadForName(const NameID name_id, node_data_container .GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data) .name_id; - const auto road_name = name_table.GetNameForID(road_name_id).to_string(); - if (name_id == EMPTY_NAMEID || road_name.empty()) + if (name_id == EMPTY_NAMEID || road_name_id == EMPTY_NAMEID) + return true; + const auto road_name_empty = name_table.GetNameForID(road_name_id).to_string().empty(); + const auto in_name_empty = name_table.GetNameForID(name_id).to_string().empty(); + if (in_name_empty || road_name_empty) return true; const auto requires_announcement = util::guidance::requiresNameAnnounced( @@ -465,16 +470,20 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node, node_data_container .GetAnnotation(node_based_graph.GetEdgeData(range.front()).annotation_data) .name_id; + if (required_name_id == EMPTY_NAMEID) + return false; const auto has_required_name = [this, required_name_id](const auto edge_id) { const auto road_name_id = node_data_container .GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data) .name_id; - const auto &road_name = name_table.GetNameForID(road_name_id).to_string(); - const auto &required_name = name_table.GetNameForID(required_name_id).to_string(); - if (required_name_id == EMPTY_NAMEID || road_name_id == EMPTY_NAMEID || - (required_name.empty() && road_name.empty())) + if (road_name_id == EMPTY_NAMEID) + return false; + const auto &road_name_empty = name_table.GetNameForID(road_name_id).to_string().empty(); + const auto &required_name_empty = + name_table.GetNameForID(required_name_id).to_string().empty(); + if (required_name_empty && road_name_empty) return false; return !util::guidance::requiresNameAnnounced( required_name_id, road_name_id, name_table, street_name_suffix_table) || diff --git a/src/extractor/guidance/motorway_handler.cpp b/src/extractor/guidance/motorway_handler.cpp index e68f4d399..2fd513e56 100644 --- a/src/extractor/guidance/motorway_handler.cpp +++ b/src/extractor/guidance/motorway_handler.cpp @@ -361,112 +361,121 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters node_based_graph.GetEdgeData(intersection[2].eid).annotation_data); const auto &first_intersection_data = node_data_container.GetAnnotation( node_based_graph.GetEdgeData(intersection[1].eid).annotation_data); - const auto first_second_same_name = - !util::guidance::requiresNameAnnounced(second_intersection_data.name_id, - first_intersection_data.name_id, - name_table, - street_name_suffix_table); - - // merging onto a passing highway / or two ramps merging onto the same highway - if (num_valid_turns == 1) + if (first_intersection_data.name_id == EMPTY_NAMEID || + second_intersection_data.name_id == EMPTY_NAMEID) { - BOOST_ASSERT(!intersection[0].entry_allowed); - // check order of highways - // 4 - // 5 3 - // - // 6 2 - // - // 7 1 - // 0 - const auto &first_intersection_name = - name_table.GetNameForID(first_intersection_data.name_id).to_string(); - const auto &second_intersection_name = - name_table.GetNameForID(second_intersection_data.name_id).to_string(); - if (intersection[1].entry_allowed) - { - if (isMotorwayClass(intersection[1].eid, node_based_graph) && - !second_intersection_name.empty() && !first_intersection_name.empty() && - first_second_same_name) - { - // circular order indicates a merge to the left (0-3 onto 4 - if (angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) < - 2 * NARROW_TURN_ANGLE) - intersection[1].instruction = {TurnType::Merge, - DirectionModifier::SlightLeft}; - else // fallback - intersection[1].instruction = {TurnType::Merge, - getTurnDirection(intersection[1].angle)}; - } - else // passing by the end of a motorway - { - intersection[1].instruction = - getInstructionForObvious(intersection.size(), - via_eid, - isThroughStreet(1, intersection), - intersection[1]); - } - } - else - { - BOOST_ASSERT(intersection[2].entry_allowed); - if (isMotorwayClass(intersection[2].eid, node_based_graph) && - !second_intersection_name.empty() && !first_intersection_name.empty() && - first_second_same_name) - { - // circular order (5-0) onto 4 - if (angularDeviation(intersection[2].angle, STRAIGHT_ANGLE) < - 2 * NARROW_TURN_ANGLE) - intersection[2].instruction = {TurnType::Merge, - DirectionModifier::SlightRight}; - else // fallback - intersection[2].instruction = {TurnType::Merge, - getTurnDirection(intersection[2].angle)}; - } - else // passing the end of a highway - { - intersection[2].instruction = - getInstructionForObvious(intersection.size(), - via_eid, - isThroughStreet(2, intersection), - intersection[2]); - } - } + return fallback(std::move(intersection)); } else { - BOOST_ASSERT(num_valid_turns == 2); - // UTurn on ramps is not possible - BOOST_ASSERT(!intersection[0].entry_allowed); - BOOST_ASSERT(intersection[1].entry_allowed); - BOOST_ASSERT(intersection[2].entry_allowed); - // two motorways starting at end of ramp (fork) - // M M - // \ / - // | - // R - if (isMotorwayClass(intersection[1].eid, node_based_graph) && - isMotorwayClass(intersection[2].eid, node_based_graph)) + const auto first_second_same_name = + !util::guidance::requiresNameAnnounced(second_intersection_data.name_id, + first_intersection_data.name_id, + name_table, + street_name_suffix_table); + + // merging onto a passing highway / or two ramps merging onto the same highway + if (num_valid_turns == 1) { - assignFork(via_eid, intersection[2], intersection[1]); - } - else - { - // continued ramp passing motorway entry - // M R - // M R - // | / - // R - if (isMotorwayClass(intersection[1].eid, node_based_graph)) + BOOST_ASSERT(!intersection[0].entry_allowed); + // check order of highways + // 4 + // 5 3 + // + // 6 2 + // + // 7 1 + // 0 + const auto &first_intersection_name = + name_table.GetNameForID(first_intersection_data.name_id).to_string(); + const auto &second_intersection_name = + name_table.GetNameForID(second_intersection_data.name_id).to_string(); + if (intersection[1].entry_allowed) { - intersection[1].instruction = {TurnType::Turn, DirectionModifier::SlightRight}; - intersection[2].instruction = {TurnType::Continue, - DirectionModifier::SlightLeft}; + if (isMotorwayClass(intersection[1].eid, node_based_graph) && + !second_intersection_name.empty() && !first_intersection_name.empty() && + first_second_same_name) + { + // circular order indicates a merge to the left (0-3 onto 4 + if (angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) < + 2 * NARROW_TURN_ANGLE) + intersection[1].instruction = {TurnType::Merge, + DirectionModifier::SlightLeft}; + else // fallback + intersection[1].instruction = {TurnType::Merge, + getTurnDirection(intersection[1].angle)}; + } + else // passing by the end of a motorway + { + intersection[1].instruction = + getInstructionForObvious(intersection.size(), + via_eid, + isThroughStreet(1, intersection), + intersection[1]); + } } else + { + BOOST_ASSERT(intersection[2].entry_allowed); + if (isMotorwayClass(intersection[2].eid, node_based_graph) && + !second_intersection_name.empty() && !first_intersection_name.empty() && + first_second_same_name) + { + // circular order (5-0) onto 4 + if (angularDeviation(intersection[2].angle, STRAIGHT_ANGLE) < + 2 * NARROW_TURN_ANGLE) + intersection[2].instruction = {TurnType::Merge, + DirectionModifier::SlightRight}; + else // fallback + intersection[2].instruction = {TurnType::Merge, + getTurnDirection(intersection[2].angle)}; + } + else // passing the end of a highway + { + intersection[2].instruction = + getInstructionForObvious(intersection.size(), + via_eid, + isThroughStreet(2, intersection), + intersection[2]); + } + } + } + else + { + BOOST_ASSERT(num_valid_turns == 2); + // UTurn on ramps is not possible + BOOST_ASSERT(!intersection[0].entry_allowed); + BOOST_ASSERT(intersection[1].entry_allowed); + BOOST_ASSERT(intersection[2].entry_allowed); + // two motorways starting at end of ramp (fork) + // M M + // \ / + // | + // R + if (isMotorwayClass(intersection[1].eid, node_based_graph) && + isMotorwayClass(intersection[2].eid, node_based_graph)) { assignFork(via_eid, intersection[2], intersection[1]); } + else + { + // continued ramp passing motorway entry + // M R + // M R + // | / + // R + if (isMotorwayClass(intersection[1].eid, node_based_graph)) + { + intersection[1].instruction = {TurnType::Turn, + DirectionModifier::SlightRight}; + intersection[2].instruction = {TurnType::Continue, + DirectionModifier::SlightLeft}; + } + else + { + assignFork(via_eid, intersection[2], intersection[1]); + } + } } } } diff --git a/src/extractor/guidance/roundabout_handler.cpp b/src/extractor/guidance/roundabout_handler.cpp index c91ba7553..bd1c067f7 100644 --- a/src/extractor/guidance/roundabout_handler.cpp +++ b/src/extractor/guidance/roundabout_handler.cpp @@ -295,19 +295,22 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const return SPECIAL_EDGEID; } - const auto &edge_name = name_table.GetNameForID(edge_data.name_id).to_string(); - if (!edge_name.empty()) + if (edge_data.name_id != EMPTY_NAMEID) { + const auto &edge_name = name_table.GetNameForID(edge_data.name_id).to_string(); + if (!edge_name.empty()) + { - const auto announce = [&](unsigned id) { - return util::guidance::requiresNameAnnounced( - id, edge_data.name_id, name_table, street_name_suffix_table); - }; + const auto announce = [&](unsigned id) { + return util::guidance::requiresNameAnnounced( + id, edge_data.name_id, name_table, street_name_suffix_table); + }; - if (std::all_of(begin(roundabout_name_ids), end(roundabout_name_ids), announce)) - roundabout_name_ids.insert(edge_data.name_id); + if (std::all_of( + begin(roundabout_name_ids), end(roundabout_name_ids), announce)) + roundabout_name_ids.insert(edge_data.name_id); + } } - continue_edge = edge_id; } else if (!edge.flags.roundabout && !edge.flags.circular) diff --git a/src/extractor/guidance/sliproad_handler.cpp b/src/extractor/guidance/sliproad_handler.cpp index 2d041d759..6bf245c21 100644 --- a/src/extractor/guidance/sliproad_handler.cpp +++ b/src/extractor/guidance/sliproad_handler.cpp @@ -474,8 +474,10 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter // Name mismatch: check roads at `c` and `d` for same name const auto name_mismatch = [&](const NameID road_name_id) { - const auto &road_name = name_table.GetNameForID(road_name_id).to_string(); - const auto unnamed = road_name.empty(); + const auto unnamed = + road_name_id == EMPTY_NAMEID + ? true + : name_table.GetNameForID(road_name_id).to_string().empty(); return unnamed || util::guidance::requiresNameAnnounced(road_name_id, // @@ -502,13 +504,15 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter .name_id; const auto &sliproad_annotation = node_data_container.GetAnnotation(sliproad_edge_data.annotation_data); - const auto &sliproad_name = - name_table.GetNameForID(sliproad_annotation.name_id).to_string(); + const auto &sliproad_name_empty = + sliproad_annotation.name_id == EMPTY_NAMEID + ? true + : name_table.GetNameForID(sliproad_annotation.name_id).to_string().empty(); const auto &main_road_name = name_table.GetNameForID(main_road_name_id).to_string(); const auto &candidate_road_name = name_table.GetNameForID(candidate_data.name_id).to_string(); if (!sliproad_edge_data.flags.road_classification.IsLinkClass() && - !sliproad_name.empty() && !main_road_name.empty() && !candidate_road_name.empty() && + !sliproad_name_empty && !main_road_name.empty() && !candidate_road_name.empty() && util::guidance::requiresNameAnnounced(main_road_name_id, sliproad_annotation.name_id, name_table, diff --git a/src/extractor/guidance/turn_handler.cpp b/src/extractor/guidance/turn_handler.cpp index 38473afa8..3b9747d37 100644 --- a/src/extractor/guidance/turn_handler.cpp +++ b/src/extractor/guidance/turn_handler.cpp @@ -199,8 +199,11 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge, const bool turn_is_perfectly_straight = angularDeviation(road.angle, STRAIGHT_ANGLE) < std::numeric_limits::epsilon(); - const auto &via_name = name_table.GetNameForID(via_data.name_id).to_string(); - if (!via_name.empty()) + const auto &via_name_empty = + via_data.name_id == EMPTY_NAMEID + ? true + : name_table.GetNameForID(via_data.name_id).to_string().empty(); + if (!via_name_empty) { const auto same_name = !util::guidance::requiresNameAnnounced( via_data.name_id, road_data.name_id, name_table, street_name_suffix_table);