enable suppression name suffix changes
This commit is contained in:
		
							parent
							
								
									fddb035539
								
							
						
					
					
						commit
						a154d71841
					
				| @ -2,6 +2,11 @@ | |||||||
|    - API: |    - API: | ||||||
|      - added roundabout-turn instruction. The instruction indicates a small roundabout that is treated as an intersection |      - added roundabout-turn instruction. The instruction indicates a small roundabout that is treated as an intersection | ||||||
|         (turn right at the roundabout for first exit, go straight at the roundabout...) |         (turn right at the roundabout for first exit, go straight at the roundabout...) | ||||||
|  |      - reduced new name instructions for trivial changes | ||||||
|  |      - combined multiple turns into a single instruction at segregated roads` | ||||||
|  | 
 | ||||||
|  |    - Profile Changes: | ||||||
|  |     - introduced a suffix_list / get_name_suffix_list to specify name suffices to be suppressed in name change announcements | ||||||
| 
 | 
 | ||||||
|    - Infrastructure |    - Infrastructure | ||||||
|     - BREAKING: reordered internal instruction types. This breaks the data format |     - BREAKING: reordered internal instruction types. This breaks the data format | ||||||
|  | |||||||
							
								
								
									
										62
									
								
								features/guidance/suffix-changes.feature
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								features/guidance/suffix-changes.feature
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | @routing  @guidance | ||||||
|  | Feature: Suppress New Names on dedicated Suffices | ||||||
|  | 
 | ||||||
|  |     Background: | ||||||
|  |         Given the profile "car" | ||||||
|  |         Given a grid size of 10 meters | ||||||
|  | 
 | ||||||
|  |     Scenario: Suffix To Suffix | ||||||
|  |         Given the node map | ||||||
|  |             | a |   | b |   | c | | ||||||
|  | 
 | ||||||
|  |         And the ways | ||||||
|  |             | nodes  | name | | ||||||
|  |             | ab     | 42 N | | ||||||
|  |             | bc     | 42 S | | ||||||
|  | 
 | ||||||
|  |        When I route I should get | ||||||
|  |             | waypoints | route     | turns         | | ||||||
|  |             | a,c       | 42 N,42 S | depart,arrive | | ||||||
|  | 
 | ||||||
|  |     Scenario: Suffix To Suffix - Turn | ||||||
|  |         Given the node map | ||||||
|  |             | a |   | b |   | c | | ||||||
|  |             |   |   | d |   |   | | ||||||
|  | 
 | ||||||
|  |         And the ways | ||||||
|  |             | nodes  | name | | ||||||
|  |             | ab     | 42 N | | ||||||
|  |             | bc     | 42 S | | ||||||
|  |             | bd     | 42 E | | ||||||
|  | 
 | ||||||
|  |        When I route I should get | ||||||
|  |             | waypoints | route          | turns                    | | ||||||
|  |             | a,c       | 42 N,42 S      | depart,arrive            | | ||||||
|  |             | a,d       | 42 N,42 E,42 E | depart,turn right,arrive | | ||||||
|  | 
 | ||||||
|  |     Scenario: Suffix To No Suffix | ||||||
|  |         Given the node map | ||||||
|  |             | a |   | b |   | c | | ||||||
|  | 
 | ||||||
|  |         And the ways | ||||||
|  |             | nodes  | name | | ||||||
|  |             | ab     | 42 N | | ||||||
|  |             | bc     | 42   | | ||||||
|  | 
 | ||||||
|  |        When I route I should get | ||||||
|  |             | waypoints | route   | turns         | | ||||||
|  |             | a,c       | 42 N,42 | depart,arrive | | ||||||
|  | 
 | ||||||
|  |     Scenario: No Suffix To Suffix | ||||||
|  |         Given the node map | ||||||
|  |             | a |   | b |   | c | | ||||||
|  | 
 | ||||||
|  |         And the ways | ||||||
|  |             | nodes  | name | | ||||||
|  |             | ab     | 42   | | ||||||
|  |             | bc     | 42 S | | ||||||
|  | 
 | ||||||
|  |        When I route I should get | ||||||
|  |             | waypoints | route   | turns         | | ||||||
|  |             | a,c       | 42,42 S | depart,arrive | | ||||||
|  | 
 | ||||||
| @ -79,7 +79,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade, | |||||||
| 
 | 
 | ||||||
|         // some name changes are not announced in our processing. For these, we have to keep the
 |         // some name changes are not announced in our processing. For these, we have to keep the
 | ||||||
|         // first name on the segment
 |         // first name on the segment
 | ||||||
|         unsigned step_name_id = source_node.name_id; |         auto step_name_id = source_node.name_id; | ||||||
|         for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index) |         for (std::size_t leg_data_index = 0; leg_data_index < leg_data.size(); ++leg_data_index) | ||||||
|         { |         { | ||||||
|             const auto &path_point = leg_data[leg_data_index]; |             const auto &path_point = leg_data[leg_data_index]; | ||||||
|  | |||||||
| @ -65,8 +65,8 @@ inline extractor::guidance::DirectionModifier angleToDirectionModifier(const dou | |||||||
| 
 | 
 | ||||||
| inline double angularDeviation(const double angle, const double from) | inline double angularDeviation(const double angle, const double from) | ||||||
| { | { | ||||||
|         const double deviation = std::abs(angle - from); |     const double deviation = std::abs(angle - from); | ||||||
|             return std::min(360 - deviation, deviation); |     return std::min(360 - deviation, deviation); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace guidance
 | } // namespace guidance
 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| 
 | 
 | ||||||
| #include "extractor/guidance/intersection.hpp" | #include "extractor/guidance/intersection.hpp" | ||||||
| #include "extractor/query_node.hpp" | #include "extractor/query_node.hpp" | ||||||
|  | #include "extractor/suffix_table.hpp" | ||||||
| 
 | 
 | ||||||
| #include "util/name_table.hpp" | #include "util/name_table.hpp" | ||||||
| #include "util/node_based_graph.hpp" | #include "util/node_based_graph.hpp" | ||||||
| @ -26,7 +27,8 @@ class IntersectionHandler | |||||||
|   public: |   public: | ||||||
|     IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph, |     IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                         const std::vector<QueryNode> &node_info_list, |                         const std::vector<QueryNode> &node_info_list, | ||||||
|                         const util::NameTable &name_table); |                         const util::NameTable &name_table, | ||||||
|  |                         const SuffixTable &street_name_suffix_table); | ||||||
|     virtual ~IntersectionHandler(); |     virtual ~IntersectionHandler(); | ||||||
| 
 | 
 | ||||||
|     // check whether the handler can actually handle the intersection
 |     // check whether the handler can actually handle the intersection
 | ||||||
| @ -41,6 +43,7 @@ class IntersectionHandler | |||||||
|     const util::NodeBasedDynamicGraph &node_based_graph; |     const util::NodeBasedDynamicGraph &node_based_graph; | ||||||
|     const std::vector<QueryNode> &node_info_list; |     const std::vector<QueryNode> &node_info_list; | ||||||
|     const util::NameTable &name_table; |     const util::NameTable &name_table; | ||||||
|  |     const SuffixTable &street_name_suffix_table; | ||||||
| 
 | 
 | ||||||
|     // counts the number on allowed entry roads
 |     // counts the number on allowed entry roads
 | ||||||
|     std::size_t countValid(const Intersection &intersection) const; |     std::size_t countValid(const Intersection &intersection) const; | ||||||
|  | |||||||
| @ -24,7 +24,8 @@ class MotorwayHandler : public IntersectionHandler | |||||||
|   public: |   public: | ||||||
|     MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph, |     MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                     const std::vector<QueryNode> &node_info_list, |                     const std::vector<QueryNode> &node_info_list, | ||||||
|                     const util::NameTable &name_table); |                     const util::NameTable &name_table, | ||||||
|  |                     const SuffixTable &street_name_suffix_table); | ||||||
|     ~MotorwayHandler() override final; |     ~MotorwayHandler() override final; | ||||||
| 
 | 
 | ||||||
|     // check whether the handler can actually handle the intersection
 |     // check whether the handler can actually handle the intersection
 | ||||||
|  | |||||||
| @ -40,8 +40,9 @@ class RoundaboutHandler : public IntersectionHandler | |||||||
|   public: |   public: | ||||||
|     RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph, |     RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                       const std::vector<QueryNode> &node_info_list, |                       const std::vector<QueryNode> &node_info_list, | ||||||
|  |                       const CompressedEdgeContainer &compressed_edge_container, | ||||||
|                       const util::NameTable &name_table, |                       const util::NameTable &name_table, | ||||||
|                       const CompressedEdgeContainer &compressed_edge_container); |                       const SuffixTable &street_name_suffix_table); | ||||||
| 
 | 
 | ||||||
|     ~RoundaboutHandler() override final; |     ~RoundaboutHandler() override final; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ | |||||||
| 
 | 
 | ||||||
| #include "extractor/compressed_edge_container.hpp" | #include "extractor/compressed_edge_container.hpp" | ||||||
| #include "extractor/query_node.hpp" | #include "extractor/query_node.hpp" | ||||||
|  | #include "extractor/suffix_table.hpp" | ||||||
| 
 | 
 | ||||||
| #include "extractor/guidance/classification_data.hpp" | #include "extractor/guidance/classification_data.hpp" | ||||||
| #include "extractor/guidance/discrete_angle.hpp" | #include "extractor/guidance/discrete_angle.hpp" | ||||||
| @ -20,6 +21,7 @@ | |||||||
| #include <map> | #include <map> | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
|  | #include <boost/algorithm/string.hpp> | ||||||
| #include <boost/algorithm/string/predicate.hpp> | #include <boost/algorithm/string/predicate.hpp> | ||||||
| 
 | 
 | ||||||
| namespace osrm | namespace osrm | ||||||
| @ -305,7 +307,9 @@ inline bool isDistinct(const DirectionModifier first, const DirectionModifier se | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline bool requiresNameAnnounced(const std::string &from, const std::string &to) | inline bool requiresNameAnnounced(const std::string &from, | ||||||
|  |                                   const std::string &to, | ||||||
|  |                                   const SuffixTable &suffix_table) | ||||||
| { | { | ||||||
|     // FIXME, handle in profile to begin with?
 |     // FIXME, handle in profile to begin with?
 | ||||||
|     // this uses the encoding of references in the profile, which is very BAD
 |     // this uses the encoding of references in the profile, which is very BAD
 | ||||||
| @ -332,12 +336,19 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     const auto getCommonLength = [](const std::string &first, const std::string &second) { | ||||||
|  |         BOOST_ASSERT(first.size() <= second.size()); | ||||||
|  |         const auto mismatch_result = std::mismatch(first.begin(), first.end(), second.begin()); | ||||||
|  |         return std::distance(first.begin(), mismatch_result.first); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     split(from, from_name, from_ref); |     split(from, from_name, from_ref); | ||||||
|     split(to, to_name, to_ref); |     split(to, to_name, to_ref); | ||||||
| 
 | 
 | ||||||
|     // check similarity of names
 |     // check similarity of names
 | ||||||
|     const auto names_are_empty = from_name.empty() && to_name.empty(); |     const auto names_are_empty = from_name.empty() && to_name.empty(); | ||||||
|     const auto name_is_contained = boost::starts_with(from_name,to_name) || boost::starts_with(to_name,from_name); |     const auto name_is_contained = | ||||||
|  |         boost::starts_with(from_name, to_name) || boost::starts_with(to_name, from_name); | ||||||
|     const auto names_are_equal = from_name == to_name || name_is_contained; |     const auto names_are_equal = from_name == to_name || name_is_contained; | ||||||
|     const auto name_is_removed = !from_name.empty() && to_name.empty(); |     const auto name_is_removed = !from_name.empty() && to_name.empty(); | ||||||
|     // references are contained in one another
 |     // references are contained in one another
 | ||||||
| @ -347,9 +358,41 @@ inline bool requiresNameAnnounced(const std::string &from, const std::string &to | |||||||
|         (from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos); |         (from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos); | ||||||
|     const auto ref_is_removed = !from_ref.empty() && to_ref.empty(); |     const auto ref_is_removed = !from_ref.empty() && to_ref.empty(); | ||||||
| 
 | 
 | ||||||
|     const auto obvious_change = |     const auto checkForSuffixChange = [](const std::size_t common_length, const std::string &first, | ||||||
|         (names_are_empty && refs_are_empty) || (names_are_equal && ref_is_contained) || |                                          const std::string &second, | ||||||
|         (names_are_equal && refs_are_empty) || name_is_removed || ref_is_removed; |                                          const SuffixTable &suffix_table) { | ||||||
|  |         if (0 == common_length) | ||||||
|  |             return false; | ||||||
|  | 
 | ||||||
|  |         const auto endsOnSuffix = [](const std::size_t trim_length, | ||||||
|  |                                      const std::string &string_with_possible_suffix, | ||||||
|  |                                      const SuffixTable &suffix_table) { | ||||||
|  |             auto suffix = | ||||||
|  |                 string_with_possible_suffix.size() > trim_length | ||||||
|  |                     ? string_with_possible_suffix.substr( | ||||||
|  |                           trim_length + (string_with_possible_suffix[trim_length] == ' ' ? 1 : 0)) | ||||||
|  |                     : " "; | ||||||
|  |             boost::algorithm::to_lower(suffix); | ||||||
|  |             return suffix.empty() || suffix_table.isSuffix(suffix); | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const auto first_delta_is_suffix = endsOnSuffix(common_length, first, suffix_table); | ||||||
|  |         const auto second_delta_is_suffix = endsOnSuffix(common_length, second, suffix_table); | ||||||
|  | 
 | ||||||
|  |         return first_delta_is_suffix && second_delta_is_suffix; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     const auto common_length = from_name.size() < to_name.size() | ||||||
|  |                                    ? getCommonLength(from_name, to_name) | ||||||
|  |                                    : getCommonLength(to_name, from_name); | ||||||
|  | 
 | ||||||
|  |     const auto is_suffix_change = | ||||||
|  |         checkForSuffixChange(common_length, from_name, to_name, suffix_table); | ||||||
|  | 
 | ||||||
|  |     const auto obvious_change = (names_are_empty && refs_are_empty) || | ||||||
|  |                                 (names_are_equal && ref_is_contained) || | ||||||
|  |                                 (names_are_equal && refs_are_empty) || name_is_removed || | ||||||
|  |                                 ref_is_removed || is_suffix_change; | ||||||
| 
 | 
 | ||||||
|     return !obvious_change; |     return !obvious_change; | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ | |||||||
| #include "extractor/guidance/turn_handler.hpp" | #include "extractor/guidance/turn_handler.hpp" | ||||||
| #include "extractor/query_node.hpp" | #include "extractor/query_node.hpp" | ||||||
| #include "extractor/restriction_map.hpp" | #include "extractor/restriction_map.hpp" | ||||||
|  | #include "extractor/suffix_table.hpp" | ||||||
| 
 | 
 | ||||||
| #include "util/name_table.hpp" | #include "util/name_table.hpp" | ||||||
| #include "util/node_based_graph.hpp" | #include "util/node_based_graph.hpp" | ||||||
| @ -39,7 +40,8 @@ class TurnAnalysis | |||||||
|                  const RestrictionMap &restriction_map, |                  const RestrictionMap &restriction_map, | ||||||
|                  const std::unordered_set<NodeID> &barrier_nodes, |                  const std::unordered_set<NodeID> &barrier_nodes, | ||||||
|                  const CompressedEdgeContainer &compressed_edge_container, |                  const CompressedEdgeContainer &compressed_edge_container, | ||||||
|                  const util::NameTable &name_table); |                  const util::NameTable &name_table, | ||||||
|  |                  const SuffixTable &street_name_suffix_table); | ||||||
| 
 | 
 | ||||||
|     // the entry into the turn analysis
 |     // the entry into the turn analysis
 | ||||||
|     std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const; |     std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const; | ||||||
|  | |||||||
| @ -26,7 +26,8 @@ class TurnHandler : public IntersectionHandler | |||||||
|   public: |   public: | ||||||
|     TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph, |     TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                 const std::vector<QueryNode> &node_info_list, |                 const std::vector<QueryNode> &node_info_list, | ||||||
|                 const util::NameTable &name_table); |                 const util::NameTable &name_table, | ||||||
|  |                 const SuffixTable &street_name_suffix_table); | ||||||
|     ~TurnHandler() override final; |     ~TurnHandler() override final; | ||||||
| 
 | 
 | ||||||
|     // check whether the handler can actually handle the intersection
 |     // check whether the handler can actually handle the intersection
 | ||||||
|  | |||||||
							
								
								
									
										30
									
								
								include/extractor/suffix_table.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/extractor/suffix_table.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | #ifndef OSRM_EXTRACTOR_SUFFIX_LIST_HPP_ | ||||||
|  | #define OSRM_EXTRACTOR_SUFFIX_LIST_HPP_ | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | #include <unordered_set> | ||||||
|  | 
 | ||||||
|  | struct lua_State; | ||||||
|  | 
 | ||||||
|  | namespace osrm | ||||||
|  | { | ||||||
|  | namespace extractor | ||||||
|  | { | ||||||
|  | // A table containing suffixes.
 | ||||||
|  | // At the moment, it is only a front for an unordered set. At some point we might want to make it
 | ||||||
|  | // country dependent and have it behave accordingly
 | ||||||
|  | class SuffixTable final | ||||||
|  | { | ||||||
|  |   public: | ||||||
|  |     SuffixTable(lua_State *lua_state); | ||||||
|  | 
 | ||||||
|  |     // check whether a string is part of the know suffix list
 | ||||||
|  |     bool isSuffix(const std::string &possible_suffix) const; | ||||||
|  | 
 | ||||||
|  |   private: | ||||||
|  |     std::unordered_set<std::string> suffix_set; | ||||||
|  | }; | ||||||
|  | } /* namespace extractor */ | ||||||
|  | } /* namespace osrm */ | ||||||
|  | 
 | ||||||
|  | #endif /* OSRM_EXTRACTOR_SUFFIX_LIST_HPP_ */ | ||||||
| @ -11,6 +11,9 @@ access_tags_hierarchy = { "motorcar", "motor_vehicle", "vehicle", "access" } | |||||||
| service_tag_restricted = { ["parking_aisle"] = true } | service_tag_restricted = { ["parking_aisle"] = true } | ||||||
| restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } | restriction_exception_tags = { "motorcar", "motor_vehicle", "vehicle" } | ||||||
| 
 | 
 | ||||||
|  | -- A list of suffixes to suppress in name change instructions | ||||||
|  | suffix_list = { "N", "NE", "E", "SE", "S", "SW", "W", "NW" } | ||||||
|  | 
 | ||||||
| speed_profile = { | speed_profile = { | ||||||
|   ["motorway"] = 90, |   ["motorway"] = 90, | ||||||
|   ["motorway_link"] = 45, |   ["motorway_link"] = 45, | ||||||
| @ -150,6 +153,12 @@ local max = math.max | |||||||
| 
 | 
 | ||||||
| local speed_reduction = 0.8 | local speed_reduction = 0.8 | ||||||
| 
 | 
 | ||||||
|  | function get_name_suffix_list(vector) | ||||||
|  |   for index,suffix in ipairs(suffix_list) do | ||||||
|  |       vector:Add(suffix) | ||||||
|  |   end | ||||||
|  | end | ||||||
|  | 
 | ||||||
| function get_exceptions(vector) | function get_exceptions(vector) | ||||||
|   for i,v in ipairs(restriction_exception_tags) do |   for i,v in ipairs(restriction_exception_tags) do | ||||||
|     vector:Add(v) |     vector:Add(v) | ||||||
|  | |||||||
| @ -28,6 +28,9 @@ with open(profile_path) as f: | |||||||
| 
 | 
 | ||||||
| n_errors = 0 | n_errors = 0 | ||||||
| for n, line in enumerate(profile): | for n, line in enumerate(profile): | ||||||
|  |     # allow arbitrary suffix lists | ||||||
|  |     if line.strip().startswith("suffix_list"): | ||||||
|  |         continue | ||||||
|     # ignore comments |     # ignore comments | ||||||
|     if line.strip().startswith("--"): |     if line.strip().startswith("--"): | ||||||
|         continue |         continue | ||||||
|  | |||||||
| @ -29,14 +29,26 @@ namespace engine | |||||||
| namespace guidance | namespace guidance | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
|  | namespace | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | // invalidate a step and set its content to nothing
 | ||||||
|  | void invalidateStep(RouteStep &step) | ||||||
|  | { | ||||||
|  |     step = {}; | ||||||
|  |     step.maneuver.instruction = TurnInstruction::NO_TURN(); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| void print(const std::vector<RouteStep> &steps) | void print(const std::vector<RouteStep> &steps) | ||||||
| { | { | ||||||
|     std::cout << "Path\n"; |     std::cout << "Path\n"; | ||||||
|     int segment = 0; |     int segment = 0; | ||||||
|     for (const auto &step : steps) |     for (const auto &step : steps) | ||||||
|     { |     { | ||||||
|         const auto type = static_cast<int>(step.maneuver.instruction.type); |         const auto type = | ||||||
|         const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier); |             static_cast<std::underlying_type<TurnType>::type>(step.maneuver.instruction.type); | ||||||
|  |         const auto modifier = static_cast<std::underlying_type<DirectionModifier>::type>( | ||||||
|  |             step.maneuver.instruction.direction_modifier); | ||||||
| 
 | 
 | ||||||
|         std::cout << "\t[" << ++segment << "]: " << type << " " << modifier |         std::cout << "\t[" << ++segment << "]: " << type << " " << modifier | ||||||
|                   << " Duration: " << step.duration << " Distance: " << step.distance |                   << " Duration: " << step.duration << " Distance: " << step.distance | ||||||
| @ -53,37 +65,6 @@ void print(const std::vector<RouteStep> &steps) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace detail |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| void print(const std::vector<RouteStep> &steps) |  | ||||||
| { |  | ||||||
|     std::cout << "Path\n"; |  | ||||||
|     int segment = 0; |  | ||||||
|     for (const auto &step : steps) |  | ||||||
|     { |  | ||||||
|         const auto type = static_cast<int>(step.maneuver.instruction.type); |  | ||||||
|         const auto modifier = static_cast<int>(step.maneuver.instruction.direction_modifier); |  | ||||||
| 
 |  | ||||||
|         std::cout << "\t[" << ++segment << "]: " << type << " " << modifier |  | ||||||
|                   << " Duration: " << step.duration << " Distance: " << step.distance |  | ||||||
|                   << " Geometry: " << step.geometry_begin << " " << step.geometry_end |  | ||||||
|                   << " exit: " << step.maneuver.exit |  | ||||||
|                   << " Intersections: " << step.maneuver.intersections.size() << " ["; |  | ||||||
| 
 |  | ||||||
|         for (auto intersection : step.maneuver.intersections) |  | ||||||
|             std::cout << "(" << intersection.duration << " " << intersection.distance << ")"; |  | ||||||
| 
 |  | ||||||
|         std::cout << "] name[" << step.name_id << "]: " << step.name << std::endl; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool canMergeTrivially(const RouteStep &destination, const RouteStep &source) |  | ||||||
| { |  | ||||||
|     return destination.maneuver.exit == 0 && destination.name_id == source.name_id && |  | ||||||
|            isSilent(source.maneuver.instruction); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| RouteStep forwardInto(RouteStep destination, const RouteStep &source) | RouteStep forwardInto(RouteStep destination, const RouteStep &source) | ||||||
| { | { | ||||||
|     // Merge a turn into a silent turn
 |     // Merge a turn into a silent turn
 | ||||||
| @ -95,13 +76,6 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source) | |||||||
|     return destination; |     return destination; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // invalidate a step and set its content to nothing
 |  | ||||||
| inline void invalidateStep(RouteStep &step) |  | ||||||
| { |  | ||||||
|     step = {}; |  | ||||||
|     step.maneuver.instruction = TurnInstruction::NO_TURN(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void fixFinalRoundabout(std::vector<RouteStep> &steps) | void fixFinalRoundabout(std::vector<RouteStep> &steps) | ||||||
| { | { | ||||||
|     for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0; |     for (std::size_t propagation_index = steps.size() - 1; propagation_index > 0; | ||||||
| @ -194,7 +168,7 @@ void closeOffRoundabout(const bool on_roundabout, | |||||||
|         BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) || |         BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) || | ||||||
|                      steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout); |                      steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout); | ||||||
|         steps[0].geometry_end = 1; |         steps[0].geometry_end = 1; | ||||||
|         steps[1] = detail::forwardInto(steps[1], steps[0]); |         steps[1] = forwardInto(steps[1], steps[0]); | ||||||
|         steps[0].duration = 0; |         steps[0].duration = 0; | ||||||
|         steps[0].distance = 0; |         steps[0].distance = 0; | ||||||
|         const auto exitToEnter = [](const TurnType type) { |         const auto exitToEnter = [](const TurnType type) { | ||||||
| @ -223,7 +197,7 @@ void closeOffRoundabout(const bool on_roundabout, | |||||||
|              --propagation_index) |              --propagation_index) | ||||||
|         { |         { | ||||||
|             auto &propagation_step = steps[propagation_index]; |             auto &propagation_step = steps[propagation_index]; | ||||||
|             propagation_step = detail::forwardInto(propagation_step, steps[propagation_index + 1]); |             propagation_step = forwardInto(propagation_step, steps[propagation_index + 1]); | ||||||
|             if (entersRoundabout(propagation_step.maneuver.instruction)) |             if (entersRoundabout(propagation_step.maneuver.instruction)) | ||||||
|             { |             { | ||||||
|                 propagation_step.maneuver.exit = step.maneuver.exit; |                 propagation_step.maneuver.exit = step.maneuver.exit; | ||||||
| @ -334,7 +308,7 @@ RouteStep elongate(RouteStep step, const RouteStep &by_step) | |||||||
| // A check whether two instructions can be treated as one. This is only the case for very short
 | // A check whether two instructions can be treated as one. This is only the case for very short
 | ||||||
| // maneuvers that can, in some form, be seen as one. The additional in_step is to find out about
 | // maneuvers that can, in some form, be seen as one. The additional in_step is to find out about
 | ||||||
| // a possible u-turn.
 | // a possible u-turn.
 | ||||||
| inline bool collapsable(const RouteStep &step) | bool collapsable(const RouteStep &step) | ||||||
| { | { | ||||||
|     const constexpr double MAX_COLLAPSE_DISTANCE = 25; |     const constexpr double MAX_COLLAPSE_DISTANCE = 25; | ||||||
|     return step.distance < MAX_COLLAPSE_DISTANCE; |     return step.distance < MAX_COLLAPSE_DISTANCE; | ||||||
| @ -345,6 +319,8 @@ void collapseTurnAt(std::vector<RouteStep> &steps, | |||||||
|                     const std::size_t one_back_index, |                     const std::size_t one_back_index, | ||||||
|                     const std::size_t step_index) |                     const std::size_t step_index) | ||||||
| { | { | ||||||
|  |     BOOST_ASSERT(step_index < steps.size()); | ||||||
|  |     BOOST_ASSERT(one_back_index < steps.size()); | ||||||
|     const auto ¤t_step = steps[step_index]; |     const auto ¤t_step = steps[step_index]; | ||||||
| 
 | 
 | ||||||
|     const auto &one_back_step = steps[one_back_index]; |     const auto &one_back_step = steps[one_back_index]; | ||||||
| @ -357,6 +333,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps, | |||||||
|     // Very Short New Name
 |     // Very Short New Name
 | ||||||
|     if (TurnType::NewName == one_back_step.maneuver.instruction.type) |     if (TurnType::NewName == one_back_step.maneuver.instruction.type) | ||||||
|     { |     { | ||||||
|  |         BOOST_ASSERT(two_back_index < steps.size()); | ||||||
|         if (one_back_step.mode == steps[two_back_index].mode) |         if (one_back_step.mode == steps[two_back_index].mode) | ||||||
|         { |         { | ||||||
|             steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step); |             steps[two_back_index] = elongate(std::move(steps[two_back_index]), one_back_step); | ||||||
| @ -387,6 +364,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps, | |||||||
|                                  current_step.maneuver.bearing_after)) |                                  current_step.maneuver.bearing_after)) | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|  |         BOOST_ASSERT(two_back_index < steps.size()); | ||||||
|         // the simple case is a u-turn that changes directly into the in-name again
 |         // the simple case is a u-turn that changes directly into the in-name again
 | ||||||
|         const bool direct_u_turn = steps[two_back_index].name == current_step.name; |         const bool direct_u_turn = steps[two_back_index].name == current_step.name; | ||||||
| 
 | 
 | ||||||
| @ -420,7 +398,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps, | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace detail
 | } // namespace
 | ||||||
| 
 | 
 | ||||||
| // Post processing can invalidate some instructions. For example StayOnRoundabout
 | // Post processing can invalidate some instructions. For example StayOnRoundabout
 | ||||||
| // is turned into exit counts. These instructions are removed by the following function
 | // is turned into exit counts. These instructions are removed by the following function
 | ||||||
| @ -469,7 +447,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | |||||||
|         into.maneuver.intersections.push_back( |         into.maneuver.intersections.push_back( | ||||||
|             {last_step.duration, last_step.distance, intersection.maneuver.location}); |             {last_step.duration, last_step.distance, intersection.maneuver.location}); | ||||||
| 
 | 
 | ||||||
|         return detail::forwardInto(std::move(into), intersection); |         return forwardInto(std::move(into), intersection); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     // count the exits forward. if enter/exit roundabout happen both, no further treatment is
 |     // count the exits forward. if enter/exit roundabout happen both, no further treatment is
 | ||||||
| @ -484,7 +462,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | |||||||
|         if (entersRoundabout(instruction)) |         if (entersRoundabout(instruction)) | ||||||
|         { |         { | ||||||
|             last_valid_instruction = step_index; |             last_valid_instruction = step_index; | ||||||
|             has_entered_roundabout = detail::setUpRoundabout(step); |             has_entered_roundabout = setUpRoundabout(step); | ||||||
| 
 | 
 | ||||||
|             if (has_entered_roundabout && step_index + 1 < steps.size()) |             if (has_entered_roundabout && step_index + 1 < steps.size()) | ||||||
|                 steps[step_index + 1].maneuver.exit = step.maneuver.exit; |                 steps[step_index + 1].maneuver.exit = step.maneuver.exit; | ||||||
| @ -506,7 +484,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | |||||||
|                 // the first valid instruction
 |                 // the first valid instruction
 | ||||||
|                 last_valid_instruction = 1; |                 last_valid_instruction = 1; | ||||||
|             } |             } | ||||||
|             detail::closeOffRoundabout(has_entered_roundabout, steps, step_index); |             closeOffRoundabout(has_entered_roundabout, steps, step_index); | ||||||
|             has_entered_roundabout = false; |             has_entered_roundabout = false; | ||||||
|             on_roundabout = false; |             on_roundabout = false; | ||||||
|         } |         } | ||||||
| @ -529,7 +507,7 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps) | |||||||
|     // A roundabout without exit translates to enter-roundabout.
 |     // A roundabout without exit translates to enter-roundabout.
 | ||||||
|     if (has_entered_roundabout || on_roundabout) |     if (has_entered_roundabout || on_roundabout) | ||||||
|     { |     { | ||||||
|         detail::fixFinalRoundabout(steps); |         fixFinalRoundabout(steps); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return removeNoTurnInstructions(std::move(steps)); |     return removeNoTurnInstructions(std::move(steps)); | ||||||
| @ -541,6 +519,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps) | |||||||
|     // Get the previous non-invalid instruction
 |     // Get the previous non-invalid instruction
 | ||||||
|     const auto getPreviousIndex = [&steps](std::size_t index) { |     const auto getPreviousIndex = [&steps](std::size_t index) { | ||||||
|         BOOST_ASSERT(index > 0); |         BOOST_ASSERT(index > 0); | ||||||
|  |         BOOST_ASSERT(index < steps.size()); | ||||||
|         --index; |         --index; | ||||||
|         while (index > 0 && steps[index].maneuver.instruction == TurnInstruction::NO_TURN()) |         while (index > 0 && steps[index].maneuver.instruction == TurnInstruction::NO_TURN()) | ||||||
|             --index; |             --index; | ||||||
| @ -553,6 +532,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps) | |||||||
|     { |     { | ||||||
|         const auto ¤t_step = steps[step_index]; |         const auto ¤t_step = steps[step_index]; | ||||||
|         const auto one_back_index = getPreviousIndex(step_index); |         const auto one_back_index = getPreviousIndex(step_index); | ||||||
|  |         BOOST_ASSERT(one_back_index < steps.size()); | ||||||
| 
 | 
 | ||||||
|         // cannot collapse the depart instruction
 |         // cannot collapse the depart instruction
 | ||||||
|         if (one_back_index == 0 || current_step.maneuver.instruction == TurnInstruction::NO_TURN()) |         if (one_back_index == 0 || current_step.maneuver.instruction == TurnInstruction::NO_TURN()) | ||||||
| @ -560,6 +540,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps) | |||||||
| 
 | 
 | ||||||
|         const auto &one_back_step = steps[one_back_index]; |         const auto &one_back_step = steps[one_back_index]; | ||||||
|         const auto two_back_index = getPreviousIndex(one_back_index); |         const auto two_back_index = getPreviousIndex(one_back_index); | ||||||
|  |         BOOST_ASSERT(two_back_index < steps.size()); | ||||||
| 
 | 
 | ||||||
|         // If we look at two consecutive name changes, we can check for a name oszillation.
 |         // If we look at two consecutive name changes, we can check for a name oszillation.
 | ||||||
|         // A name oszillation changes from name A shortly to name B and back to A.
 |         // A name oszillation changes from name A shortly to name B and back to A.
 | ||||||
| @ -574,20 +555,20 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps) | |||||||
|                 if (current_step.mode == one_back_step.mode && |                 if (current_step.mode == one_back_step.mode && | ||||||
|                     one_back_step.mode == steps[two_back_index].mode) |                     one_back_step.mode == steps[two_back_index].mode) | ||||||
|                 { |                 { | ||||||
|                     steps[two_back_index] = detail::elongate( |                     steps[two_back_index] = | ||||||
|                         detail::elongate(std::move(steps[two_back_index]), steps[one_back_index]), |                         elongate(elongate(std::move(steps[two_back_index]), steps[one_back_index]), | ||||||
|                         steps[step_index]); |                                  steps[step_index]); | ||||||
|                     detail::invalidateStep(steps[one_back_index]); |                     invalidateStep(steps[one_back_index]); | ||||||
|                     detail::invalidateStep(steps[step_index]); |                     invalidateStep(steps[step_index]); | ||||||
|                 } |                 } | ||||||
|                 // TODO discuss: we could think about changing the new-name to a pure notification
 |                 // TODO discuss: we could think about changing the new-name to a pure notification
 | ||||||
|                 // about mode changes
 |                 // about mode changes
 | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         else if (detail::collapsable(one_back_step)) |         else if (collapsable(one_back_step)) | ||||||
|         { |         { | ||||||
|             // check for one of the multiple collapse scenarios and, if possible, collapse the turn
 |             // check for one of the multiple collapse scenarios and, if possible, collapse the turn
 | ||||||
|             detail::collapseTurnAt(steps, two_back_index, one_back_index, step_index); |             collapseTurnAt(steps, two_back_index, one_back_index, step_index); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return removeNoTurnInstructions(std::move(steps)); |     return removeNoTurnInstructions(std::move(steps)); | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
| #include "util/simple_logger.hpp" | #include "util/simple_logger.hpp" | ||||||
| #include "util/timing_util.hpp" | #include "util/timing_util.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include "extractor/suffix_table.hpp" | ||||||
| #include "extractor/guidance/toolkit.hpp" | #include "extractor/guidance/toolkit.hpp" | ||||||
| 
 | 
 | ||||||
| #include <boost/assert.hpp> | #include <boost/assert.hpp> | ||||||
| @ -320,8 +321,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( | |||||||
|     // Three nested loop look super-linear, but we are dealing with a (kind of)
 |     // Three nested loop look super-linear, but we are dealing with a (kind of)
 | ||||||
|     // linear number of turns only.
 |     // linear number of turns only.
 | ||||||
|     util::Percent progress(m_node_based_graph->GetNumberOfNodes()); |     util::Percent progress(m_node_based_graph->GetNumberOfNodes()); | ||||||
|  |     SuffixTable street_name_suffix_table(lua_state); | ||||||
|     guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map, |     guidance::TurnAnalysis turn_analysis(*m_node_based_graph, m_node_info_list, *m_restriction_map, | ||||||
|                                          m_barrier_nodes, m_compressed_edge_container, name_table); |                                          m_barrier_nodes, m_compressed_edge_container, name_table, | ||||||
|  |                                          street_name_suffix_table); | ||||||
|     for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes())) |     for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes())) | ||||||
|     { |     { | ||||||
|         progress.printStatus(node_u); |         progress.printStatus(node_u); | ||||||
|  | |||||||
| @ -27,8 +27,10 @@ inline bool requiresAnnouncement(const EdgeData &from, const EdgeData &to) | |||||||
| 
 | 
 | ||||||
| IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph, | IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                                          const std::vector<QueryNode> &node_info_list, |                                          const std::vector<QueryNode> &node_info_list, | ||||||
|                                          const util::NameTable &name_table) |                                          const util::NameTable &name_table, | ||||||
|     : node_based_graph(node_based_graph), node_info_list(node_info_list), name_table(name_table) |                                          const SuffixTable &street_name_suffix_table) | ||||||
|  |     : node_based_graph(node_based_graph), node_info_list(node_info_list), name_table(name_table), | ||||||
|  |       street_name_suffix_table(street_name_suffix_table) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -86,7 +88,8 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t | |||||||
|         const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid); |         const auto &out_data = node_based_graph.GetEdgeData(road.turn.eid); | ||||||
|         if (in_data.name_id != out_data.name_id && |         if (in_data.name_id != out_data.name_id && | ||||||
|             requiresNameAnnounced(name_table.GetNameForID(in_data.name_id), |             requiresNameAnnounced(name_table.GetNameForID(in_data.name_id), | ||||||
|                                   name_table.GetNameForID(out_data.name_id))) |                                   name_table.GetNameForID(out_data.name_id), | ||||||
|  |                                   street_name_suffix_table)) | ||||||
|         { |         { | ||||||
|             // obvious turn onto a through street is a merge
 |             // obvious turn onto a through street is a merge
 | ||||||
|             if (through_street) |             if (through_street) | ||||||
|  | |||||||
| @ -44,8 +44,9 @@ inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_base | |||||||
| 
 | 
 | ||||||
| MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph, | MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                                  const std::vector<QueryNode> &node_info_list, |                                  const std::vector<QueryNode> &node_info_list, | ||||||
|                                  const util::NameTable &name_table) |                                  const util::NameTable &name_table, | ||||||
|     : IntersectionHandler(node_based_graph, node_info_list, name_table) |                                  const SuffixTable &street_name_suffix_table) | ||||||
|  |     : IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -23,9 +23,10 @@ namespace guidance | |||||||
| 
 | 
 | ||||||
| RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph, | RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                                      const std::vector<QueryNode> &node_info_list, |                                      const std::vector<QueryNode> &node_info_list, | ||||||
|  |                                      const CompressedEdgeContainer &compressed_edge_container, | ||||||
|                                      const util::NameTable &name_table, |                                      const util::NameTable &name_table, | ||||||
|                                      const CompressedEdgeContainer &compressed_edge_container) |                                      const SuffixTable &street_name_suffix_table) | ||||||
|     : IntersectionHandler(node_based_graph, node_info_list, name_table), |     : IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table), | ||||||
|       compressed_edge_container(compressed_edge_container) |       compressed_edge_container(compressed_edge_container) | ||||||
| { | { | ||||||
| } | } | ||||||
| @ -142,9 +143,11 @@ bool RoundaboutHandler::qualifiesAsRoundaboutIntersection( | |||||||
|     if (!has_limited_size) |     if (!has_limited_size) | ||||||
|         return false; |         return false; | ||||||
| 
 | 
 | ||||||
|     const bool simple_exits = !std::find_if( roundabout_nodes.begin(), roundabout_nodes.end(), [this]( const NodeID node ){ |     const bool simple_exits = | ||||||
|         return (node_based_graph.GetOutDegree(node) > 3); |         roundabout_nodes.end() == | ||||||
|     }); |         std::find_if(roundabout_nodes.begin(), roundabout_nodes.end(), [this](const NodeID node) { | ||||||
|  |             return (node_based_graph.GetOutDegree(node) > 3); | ||||||
|  |         }); | ||||||
| 
 | 
 | ||||||
|     if (!simple_exits) |     if (!simple_exits) | ||||||
|         return false; |         return false; | ||||||
| @ -219,7 +222,8 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const | |||||||
|                 // roundabout does not keep its name
 |                 // roundabout does not keep its name
 | ||||||
|                 if (roundabout_name_id != 0 && roundabout_name_id != edge_data.name_id && |                 if (roundabout_name_id != 0 && roundabout_name_id != edge_data.name_id && | ||||||
|                     requiresNameAnnounced(name_table.GetNameForID(roundabout_name_id), |                     requiresNameAnnounced(name_table.GetNameForID(roundabout_name_id), | ||||||
|                                           name_table.GetNameForID(edge_data.name_id))) |                                           name_table.GetNameForID(edge_data.name_id), | ||||||
|  |                                           street_name_suffix_table)) | ||||||
|                 { |                 { | ||||||
|                     return SPECIAL_EDGEID; |                     return SPECIAL_EDGEID; | ||||||
|                 } |                 } | ||||||
|  | |||||||
| @ -33,15 +33,16 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph, | |||||||
|                            const RestrictionMap &restriction_map, |                            const RestrictionMap &restriction_map, | ||||||
|                            const std::unordered_set<NodeID> &barrier_nodes, |                            const std::unordered_set<NodeID> &barrier_nodes, | ||||||
|                            const CompressedEdgeContainer &compressed_edge_container, |                            const CompressedEdgeContainer &compressed_edge_container, | ||||||
|                            const util::NameTable &name_table) |                            const util::NameTable &name_table, | ||||||
|  |                            const SuffixTable &street_name_suffix_table) | ||||||
|     : node_based_graph(node_based_graph), intersection_generator(node_based_graph, |     : node_based_graph(node_based_graph), intersection_generator(node_based_graph, | ||||||
|                                                                  restriction_map, |                                                                  restriction_map, | ||||||
|                                                                  barrier_nodes, |                                                                  barrier_nodes, | ||||||
|                                                                  node_info_list, |                                                                  node_info_list, | ||||||
|                                                                  compressed_edge_container), |                                                                  compressed_edge_container), | ||||||
|       roundabout_handler(node_based_graph, node_info_list, name_table, compressed_edge_container), |       roundabout_handler(node_based_graph, node_info_list, compressed_edge_container, name_table, street_name_suffix_table), | ||||||
|       motorway_handler(node_based_graph, node_info_list, name_table), |       motorway_handler(node_based_graph, node_info_list, name_table,street_name_suffix_table), | ||||||
|       turn_handler(node_based_graph, node_info_list, name_table) |       turn_handler(node_based_graph, node_info_list, name_table,street_name_suffix_table) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -24,8 +24,9 @@ namespace guidance | |||||||
| 
 | 
 | ||||||
| TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph, | TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph, | ||||||
|                          const std::vector<QueryNode> &node_info_list, |                          const std::vector<QueryNode> &node_info_list, | ||||||
|                          const util::NameTable &name_table) |                          const util::NameTable &name_table, | ||||||
|     : IntersectionHandler(node_based_graph, node_info_list, name_table) |                          const SuffixTable &street_name_suffix_table) | ||||||
|  |     : IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -406,22 +407,23 @@ Intersection TurnHandler::assignLeftTurns(const EdgeID via_edge, | |||||||
|                                           Intersection intersection, |                                           Intersection intersection, | ||||||
|                                           const std::size_t starting_at) const |                                           const std::size_t starting_at) const | ||||||
| { | { | ||||||
|     BOOST_ASSERT(!intersection.empty()); |  | ||||||
|     BOOST_ASSERT(starting_at <= intersection.size()); |     BOOST_ASSERT(starting_at <= intersection.size()); | ||||||
|     for (auto &road : intersection) |     const auto switch_left_and_right = []( Intersection &intersection ) | ||||||
|         road = mirror(road); |     { | ||||||
|  |         BOOST_ASSERT(!intersection.empty()); | ||||||
| 
 | 
 | ||||||
|     std::reverse(intersection.begin() + 1, intersection.end()); |         for (auto &road : intersection) | ||||||
|  |             road = mirror(std::move(road)); | ||||||
| 
 | 
 | ||||||
|  |         std::reverse(intersection.begin() + 1, intersection.end()); | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     switch_left_and_right(intersection); | ||||||
|     // account for the u-turn in the beginning
 |     // account for the u-turn in the beginning
 | ||||||
|     const auto count = intersection.size() - starting_at + 1; |     const auto count = intersection.size() - starting_at + 1; | ||||||
| 
 |  | ||||||
|     intersection = assignRightTurns(via_edge, std::move(intersection), count); |     intersection = assignRightTurns(via_edge, std::move(intersection), count); | ||||||
|  |     switch_left_and_right(intersection); | ||||||
| 
 | 
 | ||||||
|     std::reverse(intersection.begin() + 1, intersection.end()); |  | ||||||
| 
 |  | ||||||
|     for (auto &road : intersection) |  | ||||||
|         road = mirror(road); |  | ||||||
| 
 | 
 | ||||||
|     return intersection; |     return intersection; | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										48
									
								
								src/extractor/suffix_table.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/extractor/suffix_table.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | #include "extractor/suffix_table.hpp" | ||||||
|  | 
 | ||||||
|  | #include "util/lua_util.hpp" | ||||||
|  | #include "util/simple_logger.hpp" | ||||||
|  | 
 | ||||||
|  | #include <boost/algorithm/string.hpp> | ||||||
|  | #include <boost/assert.hpp> | ||||||
|  | #include <boost/range/adaptor/transformed.hpp> | ||||||
|  | #include <boost/ref.hpp> | ||||||
|  | 
 | ||||||
|  | #include <iterator> | ||||||
|  | #include <vector> | ||||||
|  | 
 | ||||||
|  | namespace osrm | ||||||
|  | { | ||||||
|  | namespace extractor | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | SuffixTable::SuffixTable(lua_State *lua_state) | ||||||
|  | { | ||||||
|  |     BOOST_ASSERT(lua_state != nullptr); | ||||||
|  |     if (!util::luaFunctionExists(lua_state, "get_name_suffix_list")) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     std::vector<std::string> suffixes_vector; | ||||||
|  |     try | ||||||
|  |     { | ||||||
|  |         // call lua profile to compute turn penalty
 | ||||||
|  |         luabind::call_function<void>(lua_state, "get_name_suffix_list", | ||||||
|  |                                      boost::ref(suffixes_vector)); | ||||||
|  |     } | ||||||
|  |     catch (const luabind::error &er) | ||||||
|  |     { | ||||||
|  |         util::SimpleLogger().Write(logWARNING) << er.what(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     for (auto &suffix : suffixes_vector) | ||||||
|  |         boost::algorithm::to_lower(suffix); | ||||||
|  |     suffix_set.insert(std::begin(suffixes_vector), std::end(suffixes_vector)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool SuffixTable::isSuffix(const std::string &possible_suffix) const | ||||||
|  | { | ||||||
|  |     return suffix_set.count(possible_suffix) > 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } /* namespace extractor */ | ||||||
|  | } /* namespace osrm */ | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user