diff --git a/include/extractor/guidance/have_identical_names.hpp b/include/extractor/guidance/have_identical_names.hpp new file mode 100644 index 000000000..ec8f619dd --- /dev/null +++ b/include/extractor/guidance/have_identical_names.hpp @@ -0,0 +1,27 @@ +#ifndef OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_ +#define OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_ + +#include "extractor/guidance/constants.hpp" +#include "extractor/suffix_table.hpp" +#include "util/name_table.hpp" + +namespace osrm +{ +namespace extractor +{ +namespace guidance +{ + +// check if two name ids can be seen as identical (in presence of refs/others) +// in our case this translates into no name announcement in either direction (lhs->rhs and +// rhs->lhs) +bool HaveIdenticalNames(const NameID lhs, + const NameID rhs, + const util::NameTable &name_table, + const SuffixTable &street_name_suffix_table); + +} // namespace guidance +} // namespace extractor +} // namespace osrm + +#endif /*OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_*/ diff --git a/include/extractor/guidance/intersection.hpp b/include/extractor/guidance/intersection.hpp index faaf37f3a..d4e5967e7 100644 --- a/include/extractor/guidance/intersection.hpp +++ b/include/extractor/guidance/intersection.hpp @@ -293,10 +293,11 @@ struct IntersectionView final : std::vector, // }; // `Intersection` is a relative view of an intersection by an incoming edge. -// `Intersection` are streets at an intersection ordered from from sharp right counter-clockwise to +// `Intersection` are streets at an intersection stored as an ordered list of connected roads +// ordered from sharp right counter-clockwise to // sharp left where `intersection[0]` is _always_ a u-turn -// An intersection is an ordered list of connected roads ordered from from sharp right +// An intersection is an ordered list of connected roads ordered from sharp right // counter-clockwise to sharp left where `intersection[0]` is always a u-turn // // | diff --git a/include/extractor/guidance/intersection_handler.hpp b/include/extractor/guidance/intersection_handler.hpp index 4247aacb6..8fbc6dc59 100644 --- a/include/extractor/guidance/intersection_handler.hpp +++ b/include/extractor/guidance/intersection_handler.hpp @@ -96,9 +96,6 @@ class IntersectionHandler const std::size_t begin, const std::size_t end) const; - // Checks the intersection for a through street connected to `intersection[index]` - bool isThroughStreet(const std::size_t index, const Intersection &intersection) const; - // See `getNextIntersection` struct IntersectionViewAndNode final { diff --git a/include/extractor/guidance/is_through_street.hpp b/include/extractor/guidance/is_through_street.hpp new file mode 100644 index 000000000..c3ee4d183 --- /dev/null +++ b/include/extractor/guidance/is_through_street.hpp @@ -0,0 +1,63 @@ +#ifndef OSRM_EXTRACTOR_GUIDANCE_IS_THROUGH_STREET_HPP_ +#define OSRM_EXTRACTOR_GUIDANCE_IS_THROUGH_STREET_HPP_ + +#include "extractor/guidance/constants.hpp" +#include "extractor/suffix_table.hpp" +#include "util/guidance/name_announcements.hpp" + +using osrm::util::angularDeviation; + +namespace osrm +{ +namespace extractor +{ +namespace guidance +{ + +template +inline bool isThroughStreet(const std::size_t index, + const IntersectionType &intersection, + const util::NodeBasedDynamicGraph &node_based_graph, + const EdgeBasedNodeDataContainer &node_data_container, + const util::NameTable &name_table, + const SuffixTable &street_name_suffix_table) +{ + + const auto &data_at_index = node_data_container.GetAnnotation( + node_based_graph.GetEdgeData(intersection[index].eid).annotation_data); + + if (data_at_index.name_id == EMPTY_NAMEID) + return false; + + // a through street cannot start at our own position -> index 1 + for (std::size_t road_index = 1; road_index < intersection.size(); ++road_index) + { + if (road_index == index) + continue; + + const auto &road = intersection[road_index]; + const auto &road_data = node_data_container.GetAnnotation( + node_based_graph.GetEdgeData(road.eid).annotation_data); + + // roads have a near straight angle (180 degree) + const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) > + (STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE); + + const bool have_same_name = HaveIdenticalNames( + data_at_index.name_id, road_data.name_id, name_table, street_name_suffix_table); + + const bool have_same_category = + node_based_graph.GetEdgeData(intersection[index].eid).flags.road_classification == + node_based_graph.GetEdgeData(road.eid).flags.road_classification; + + if (is_nearly_straight && have_same_name && have_same_category) + return true; + } + return false; +} + +} // namespace guidance +} // namespace extractor +} // namespace osrm + +#endif /*OSRM_EXTRACTOR_GUIDANCE_IS_THROUGH_STREET_HPP_*/ \ No newline at end of file diff --git a/include/extractor/guidance/mergable_road_detector.hpp b/include/extractor/guidance/mergable_road_detector.hpp index adce8e6e9..657327960 100644 --- a/include/extractor/guidance/mergable_road_detector.hpp +++ b/include/extractor/guidance/mergable_road_detector.hpp @@ -3,6 +3,7 @@ #include "extractor/compressed_edge_container.hpp" #include "extractor/guidance/coordinate_extractor.hpp" +#include "extractor/guidance/have_identical_names.hpp" #include "extractor/guidance/intersection.hpp" #include "extractor/guidance/turn_lane_types.hpp" #include "extractor/restriction_index.hpp" @@ -78,11 +79,6 @@ class MergableRoadDetector bool IsDistinctFrom(const MergableRoadData &lhs, const MergableRoadData &rhs) const; private: - // check if two name ids can be seen as identical (in presence of refs/others) - // in our case this translates into no name announcement in either direction (lhs->rhs and - // rhs->lhs) - bool HaveIdenticalNames(const NameID lhs, const NameID rhs) const; - // When it comes to merging roads, we need to find out if two ways actually represent the // same road. This check tries to identify roads which are the same road in opposite directions bool EdgeDataSupportsMerge(const NodeBasedEdgeClassification &lhs_flags, diff --git a/include/extractor/guidance/motorway_handler.hpp b/include/extractor/guidance/motorway_handler.hpp index edf62de26..60494fc8a 100644 --- a/include/extractor/guidance/motorway_handler.hpp +++ b/include/extractor/guidance/motorway_handler.hpp @@ -3,6 +3,7 @@ #include "extractor/guidance/intersection.hpp" #include "extractor/guidance/intersection_handler.hpp" +#include "extractor/guidance/is_through_street.hpp" #include "extractor/query_node.hpp" #include "util/attributes.hpp" diff --git a/include/extractor/guidance/roundabout_handler.hpp b/include/extractor/guidance/roundabout_handler.hpp index b40c12fad..1a7cc96c4 100644 --- a/include/extractor/guidance/roundabout_handler.hpp +++ b/include/extractor/guidance/roundabout_handler.hpp @@ -5,6 +5,7 @@ #include "extractor/guidance/coordinate_extractor.hpp" #include "extractor/guidance/intersection.hpp" #include "extractor/guidance/intersection_handler.hpp" +#include "extractor/guidance/is_through_street.hpp" #include "extractor/guidance/roundabout_type.hpp" #include "extractor/query_node.hpp" diff --git a/include/extractor/guidance/sliproad_handler.hpp b/include/extractor/guidance/sliproad_handler.hpp index 8fb710b7b..9bbaf691d 100644 --- a/include/extractor/guidance/sliproad_handler.hpp +++ b/include/extractor/guidance/sliproad_handler.hpp @@ -3,6 +3,7 @@ #include "extractor/guidance/intersection.hpp" #include "extractor/guidance/intersection_handler.hpp" +#include "extractor/guidance/is_through_street.hpp" #include "extractor/query_node.hpp" #include "util/name_table.hpp" @@ -53,9 +54,6 @@ class SliproadHandler final : public IntersectionHandler // Next intersection from `start` onto `onto` is too far away for a Siproad scenario bool nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const; - // Through street: does a road continue with from's name at the intersection - bool isThroughStreet(const EdgeID from, const IntersectionView &intersection) const; - // Does the road from `current` to `next` continue bool roadContinues(const EdgeID current, const EdgeID next) const; diff --git a/include/extractor/guidance/turn_handler.hpp b/include/extractor/guidance/turn_handler.hpp index b8d5a227e..63c2adcce 100644 --- a/include/extractor/guidance/turn_handler.hpp +++ b/include/extractor/guidance/turn_handler.hpp @@ -3,6 +3,7 @@ #include "extractor/guidance/intersection.hpp" #include "extractor/guidance/intersection_handler.hpp" +#include "extractor/guidance/is_through_street.hpp" #include "extractor/query_node.hpp" #include "util/attributes.hpp" diff --git a/src/extractor/guidance/have_identical_names.cpp b/src/extractor/guidance/have_identical_names.cpp new file mode 100644 index 000000000..e956abff0 --- /dev/null +++ b/src/extractor/guidance/have_identical_names.cpp @@ -0,0 +1,33 @@ +#ifndef OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_ +#define OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_ + +#include "util/guidance/name_announcements.hpp" + +namespace osrm +{ +namespace extractor +{ +namespace guidance +{ + +// check if two name ids can be seen as identical (in presence of refs/others) +// in our case this translates into no name announcement in either direction (lhs->rhs and +// rhs->lhs) +bool HaveIdenticalNames(const NameID lhs, + const NameID rhs, + const util::NameTable &name_table, + const SuffixTable &street_name_suffix_table) +{ + const auto non_empty = (lhs != EMPTY_NAMEID) && (rhs != EMPTY_NAMEID); + + // symmetrical check for announcements + return non_empty && + !util::guidance::requiresNameAnnounced(lhs, rhs, name_table, street_name_suffix_table) && + !util::guidance::requiresNameAnnounced(rhs, lhs, name_table, street_name_suffix_table); +} + +} // namespace guidance +} // namespace extractor +} // namespace osrm + +#endif /*OSRM_EXTRACTOR_GUIDANCE_HAVE_IDENTICAL_NAMES_HPP_*/ diff --git a/src/extractor/guidance/intersection_handler.cpp b/src/extractor/guidance/intersection_handler.cpp index 037375a58..0c466537e 100644 --- a/src/extractor/guidance/intersection_handler.cpp +++ b/src/extractor/guidance/intersection_handler.cpp @@ -418,44 +418,6 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid, } } -bool IntersectionHandler::isThroughStreet(const std::size_t index, - const Intersection &intersection) const -{ - const auto &data_at_index = node_data_container.GetAnnotation( - node_based_graph.GetEdgeData(intersection[index].eid).annotation_data); - - if (data_at_index.name_id == EMPTY_NAMEID) - return false; - - // a through street cannot start at our own position -> index 1 - for (std::size_t road_index = 1; road_index < intersection.size(); ++road_index) - { - if (road_index == index) - continue; - - const auto &road = intersection[road_index]; - const auto &road_data = node_data_container.GetAnnotation( - node_based_graph.GetEdgeData(road.eid).annotation_data); - - // roads have a near straight angle (180 degree) - const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) > - (STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE); - - const bool have_same_name = - road_data.name_id != EMPTY_NAMEID && - !util::guidance::requiresNameAnnounced( - data_at_index.name_id, road_data.name_id, name_table, street_name_suffix_table); - - const bool have_same_category = - node_based_graph.GetEdgeData(intersection[index].eid).flags.road_classification == - node_based_graph.GetEdgeData(road.eid).flags.road_classification; - - if (is_nearly_straight && have_same_name && have_same_category) - return true; - } - return false; -} - boost::optional IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) const { diff --git a/src/extractor/guidance/mergable_road_detector.cpp b/src/extractor/guidance/mergable_road_detector.cpp index 9bb31f708..6184c445a 100644 --- a/src/extractor/guidance/mergable_road_detector.cpp +++ b/src/extractor/guidance/mergable_road_detector.cpp @@ -122,16 +122,6 @@ bool MergableRoadDetector::CanMergeRoad(const NodeID intersection_node, !IsCircularShape(intersection_node, lhs, rhs); } -bool MergableRoadDetector::HaveIdenticalNames(const NameID lhs, const NameID rhs) const -{ - const auto non_empty = (lhs != EMPTY_NAMEID) && (rhs != EMPTY_NAMEID); - - // symmetrical check for announcements - return non_empty && - !util::guidance::requiresNameAnnounced(lhs, rhs, name_table, street_name_suffix_table) && - !util::guidance::requiresNameAnnounced(rhs, lhs, name_table, street_name_suffix_table); -} - bool MergableRoadDetector::IsDistinctFrom(const MergableRoadData &lhs, const MergableRoadData &rhs) const { @@ -143,7 +133,9 @@ bool MergableRoadDetector::IsDistinctFrom(const MergableRoadData &lhs, node_data_container.GetAnnotation(node_based_graph.GetEdgeData(lhs.eid).annotation_data) .name_id, node_data_container.GetAnnotation(node_based_graph.GetEdgeData(rhs.eid).annotation_data) - .name_id); + .name_id, + name_table, + street_name_suffix_table); } bool MergableRoadDetector::EdgeDataSupportsMerge( @@ -165,7 +157,8 @@ bool MergableRoadDetector::EdgeDataSupportsMerge( return false; // we require valid names - if (!HaveIdenticalNames(lhs_annotation.name_id, rhs_annotation.name_id)) + if (!HaveIdenticalNames( + lhs_annotation.name_id, rhs_annotation.name_id, name_table, street_name_suffix_table)) return false; return lhs_flags.road_classification == rhs_flags.road_classification; diff --git a/src/extractor/guidance/motorway_handler.cpp b/src/extractor/guidance/motorway_handler.cpp index c231c6e33..d75881c93 100644 --- a/src/extractor/guidance/motorway_handler.cpp +++ b/src/extractor/guidance/motorway_handler.cpp @@ -239,7 +239,12 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in intersection[1].instruction = getInstructionForObvious(intersection.size(), via_eid, - isThroughStreet(1, intersection), + isThroughStreet(1, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), intersection[1]); } else @@ -253,8 +258,16 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in if (road.angle == continue_angle) { - road.instruction = getInstructionForObvious( - intersection.size(), via_eid, isThroughStreet(1, intersection), road); + road.instruction = + getInstructionForObvious(intersection.size(), + via_eid, + isThroughStreet(1, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), + road); } else if (road.angle < continue_angle) { @@ -353,8 +366,16 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters BOOST_ASSERT(!intersection[0].entry_allowed); BOOST_ASSERT(isMotorwayClass(intersection[1].eid, node_based_graph)); - intersection[1].instruction = getInstructionForObvious( - intersection.size(), via_eid, isThroughStreet(1, intersection), intersection[1]); + intersection[1].instruction = + getInstructionForObvious(intersection.size(), + via_eid, + isThroughStreet(1, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), + intersection[1]); } else if (intersection.size() == 3) { @@ -404,7 +425,12 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters intersection[1].instruction = getInstructionForObvious(intersection.size(), via_eid, - isThroughStreet(1, intersection), + isThroughStreet(1, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), intersection[1]); } } @@ -429,7 +455,12 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters intersection[2].instruction = getInstructionForObvious(intersection.size(), via_eid, - isThroughStreet(2, intersection), + isThroughStreet(2, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), intersection[2]); } } diff --git a/src/extractor/guidance/roundabout_handler.cpp b/src/extractor/guidance/roundabout_handler.cpp index 4439436d5..2c1a07624 100644 --- a/src/extractor/guidance/roundabout_handler.cpp +++ b/src/extractor/guidance/roundabout_handler.cpp @@ -478,8 +478,16 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou if (util::angularDeviation(turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE && crossing_roundabout) { - turn.instruction = getInstructionForObvious( - intersection.size(), via_eid, isThroughStreet(idx, intersection), turn); + turn.instruction = + getInstructionForObvious(intersection.size(), + via_eid, + isThroughStreet(idx, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), + turn); } else { diff --git a/src/extractor/guidance/sliproad_handler.cpp b/src/extractor/guidance/sliproad_handler.cpp index bac792051..ed9d59f49 100644 --- a/src/extractor/guidance/sliproad_handler.cpp +++ b/src/extractor/guidance/sliproad_handler.cpp @@ -344,9 +344,24 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter } // If the sliproad candidate is a through street, we cannot handle it as a sliproad. - if (isThroughStreet(sliproad_edge, target_intersection)) + auto sliproad_in_target_intersection = + std::find_if(begin(target_intersection), + end(target_intersection), + [&](const auto &road) { return road.eid == sliproad_edge; }); + if (sliproad_in_target_intersection != target_intersection.end()) { - continue; + auto index_of_sliproad_in_target_intersection = + sliproad_in_target_intersection - target_intersection.begin(); + + if (isThroughStreet(index_of_sliproad_in_target_intersection, + target_intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table)) + { + continue; + } } // The turn off of the Sliproad has to be obvious and a narrow turn and must not be a @@ -689,32 +704,6 @@ bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const Edg return accumulator.too_far_away; } -bool SliproadHandler::isThroughStreet(const EdgeID from, const IntersectionView &intersection) const -{ - BOOST_ASSERT(from != SPECIAL_EDGEID); - BOOST_ASSERT(!intersection.empty()); - - const auto from_annotation_id = node_based_graph.GetEdgeData(from).annotation_data; - const auto &edge_name_id = node_data_container.GetAnnotation(from_annotation_id).name_id; - - auto first = begin(intersection) + 1; // Skip UTurn road - auto last = end(intersection); - - auto same_name = [&](const auto &road) { - const auto annotation_id = node_based_graph.GetEdgeData(road.eid).annotation_data; - const auto &road_name_id = node_data_container.GetAnnotation(annotation_id).name_id; - - return edge_name_id != EMPTY_NAMEID && // - road_name_id != EMPTY_NAMEID && // - !util::guidance::requiresNameAnnounced(edge_name_id, - road_name_id, - name_table, - street_name_suffix_table); // - }; - - return std::find_if(first, last, same_name) != last; -} - bool SliproadHandler::roadContinues(const EdgeID current, const EdgeID next) const { const auto ¤t_data = diff --git a/src/extractor/guidance/turn_handler.cpp b/src/extractor/guidance/turn_handler.cpp index eda5f4984..27b55404c 100644 --- a/src/extractor/guidance/turn_handler.cpp +++ b/src/extractor/guidance/turn_handler.cpp @@ -287,8 +287,16 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection const auto direction_at_two = getTurnDirection(intersection[2].angle); if (obvious_index == 1) { - intersection[1].instruction = getInstructionForObvious( - 3, via_edge, isThroughStreet(1, intersection), intersection[1]); + intersection[1].instruction = + getInstructionForObvious(3, + via_edge, + isThroughStreet(1, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), + intersection[1]); const auto second_direction = (direction_at_one == direction_at_two && direction_at_two == DirectionModifier::Straight) ? DirectionModifier::SlightLeft @@ -300,8 +308,16 @@ Intersection TurnHandler::handleThreeWayTurn(const EdgeID via_edge, Intersection else { BOOST_ASSERT(obvious_index == 2); - intersection[2].instruction = getInstructionForObvious( - 3, via_edge, isThroughStreet(2, intersection), intersection[2]); + intersection[2].instruction = + getInstructionForObvious(3, + via_edge, + isThroughStreet(2, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), + intersection[2]); const auto first_direction = (direction_at_one == direction_at_two && direction_at_one == DirectionModifier::Straight) ? DirectionModifier::SlightRight @@ -336,7 +352,12 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection intersection[obvious_index].instruction = getInstructionForObvious(intersection.size(), via_edge, - isThroughStreet(obvious_index, intersection), + isThroughStreet(obvious_index, + intersection, + node_based_graph, + node_data_container, + name_table, + street_name_suffix_table), intersection[obvious_index]); // assign left/right turns diff --git a/unit_tests/mocks/mock_scripting_environment.hpp b/unit_tests/mocks/mock_scripting_environment.hpp index 1ca714a10..8ca807717 100644 --- a/unit_tests/mocks/mock_scripting_environment.hpp +++ b/unit_tests/mocks/mock_scripting_environment.hpp @@ -44,7 +44,7 @@ class MockScriptingEnvironment : public extractor::ScriptingEnvironment { } - bool HasLocationDependentData() const { return false; }; + bool HasLocationDependentData() const override { return false; }; }; } // namespace test diff --git a/unit_tests/updater_tests.cpp b/unit_tests/updater_tests.cpp index 1d4ad85d7..72550c773 100644 --- a/unit_tests/updater_tests.cpp +++ b/unit_tests/updater_tests.cpp @@ -1,4 +1,4 @@ -#define BOOST_TEST_MODULE customizer tests +#define BOOST_TEST_MODULE updater tests #include