Merge pull request #3217 from Project-OSRM/refactor/obviousness
Refactor find obvious turn handling
This commit is contained in:
		
						commit
						6d961d4a15
					
				@ -947,16 +947,17 @@ Feature: Collapse
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    #http://www.openstreetmap.org/#map=19/52.48778/13.30024
 | 
					    #http://www.openstreetmap.org/#map=19/52.48778/13.30024
 | 
				
			||||||
    Scenario: Hohenzollerdammbrücke
 | 
					    Scenario: Hohenzollerdammbrücke
 | 
				
			||||||
 | 
					        Given a grid size of 10 meters
 | 
				
			||||||
        Given the node map
 | 
					        Given the node map
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
                  q          s
 | 
					                  q          s
 | 
				
			||||||
                  p          o
 | 
					                  p          o
 | 
				
			||||||
                  ..       . .
 | 
					                  ..        ..
 | 
				
			||||||
                .     .  .      .
 | 
					                 .    .   .    .
 | 
				
			||||||
            j - i - - - h - - - g - f
 | 
					            j - i - - - h - - - g - f
 | 
				
			||||||
                  > k <   > l <
 | 
					                  > k <   > l <
 | 
				
			||||||
            a - b - - - c - - - d - e
 | 
					            a - b - - - c - - - d - e
 | 
				
			||||||
                .     .  .      .
 | 
					                 .    .  .     .
 | 
				
			||||||
                  ..        ..
 | 
					                  ..        ..
 | 
				
			||||||
                  m          n
 | 
					                  m          n
 | 
				
			||||||
                  t          r
 | 
					                  t          r
 | 
				
			||||||
@ -1013,13 +1014,13 @@ Feature: Collapse
 | 
				
			|||||||
            | restriction | ph       | hi     | h        | no_right_turn |
 | 
					            | restriction | ph       | hi     | h        | no_right_turn |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        When I route I should get
 | 
					        When I route I should get
 | 
				
			||||||
            | waypoints | route          | turns                       |
 | 
					            | waypoints | route                 | turns                       | locations |
 | 
				
			||||||
            | a,e       | hohe,hohe      | depart,arrive               |
 | 
					            | a,e       | hohe,hohe             | depart,arrive               | a,e       |
 | 
				
			||||||
            | a,s       | hohe,a100,a100 | depart,on ramp left,arrive  |
 | 
					            | a,s       | hohe,a100,a100        | depart,on ramp left,arrive  | a,b,s     |
 | 
				
			||||||
            | a,t       | hohe,a100,a100 | depart,on ramp right,arrive |
 | 
					            | a,t       | hohe,a100,a100        | depart,on ramp right,arrive | a,b,t     |
 | 
				
			||||||
            | a,j       |                |                             |
 | 
					            | a,j       |                       |                             |           |
 | 
				
			||||||
            | f,j       | hohe,hohe      | depart,arrive               |
 | 
					            | f,j       | hohe,hohe             | depart,arrive               | f,j       |
 | 
				
			||||||
            | a,t       | hohe,a100,a100 | depart,on ramp right,arrive |
 | 
					            | a,t       | hohe,a100,a100        | depart,on ramp right,arrive | a,b,t     |
 | 
				
			||||||
            | f,e       |                |                             |
 | 
					            | f,e       |                       |                             |           |
 | 
				
			||||||
            | q,j       | a100,hohe,hohe | depart,turn right,arrive    |
 | 
					            | q,j       | a100,hohe,hohe        | depart,turn right,arrive    | q,p,j     |
 | 
				
			||||||
            | q,e       | a100,a100,hohe | depart,continue left,arrive |
 | 
					            | q,e       | a100,hohebruecke,hohe | depart,turn left,arrive     | q,p,e     |
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										119
									
								
								features/guidance/low-priority.feature
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								features/guidance/low-priority.feature
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					@routing  @guidance
 | 
				
			||||||
 | 
					Feature: Exceptions for routing onto low-priority roads
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Background:
 | 
				
			||||||
 | 
					        Given the profile "car"
 | 
				
			||||||
 | 
					        Given a grid size of 10 meters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Scenario: Straight onto low-priority: same name
 | 
				
			||||||
 | 
					        Given the node map
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					                c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            a   b d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                e
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        And the ways
 | 
				
			||||||
 | 
					            | nodes  | highway     | name    |
 | 
				
			||||||
 | 
					            | abd    | residential | road    |
 | 
				
			||||||
 | 
					            | eb     | service     | service |
 | 
				
			||||||
 | 
					            | bc     | service     | service |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When I route I should get
 | 
				
			||||||
 | 
					            | waypoints | route            | turns         |
 | 
				
			||||||
 | 
					            | c,e       | service,service  | depart,arrive |
 | 
				
			||||||
 | 
					            | e,c       | service,service  | depart,arrive |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Scenario: Straight onto low-priority: onto and from unnamed
 | 
				
			||||||
 | 
					        Given the node map
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					                c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            a   b d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                e
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        And the ways
 | 
				
			||||||
 | 
					            | nodes  | highway     | name    |
 | 
				
			||||||
 | 
					            | abd    | residential | road    |
 | 
				
			||||||
 | 
					            | eb     | service     |         |
 | 
				
			||||||
 | 
					            | bc     | service     |         |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When I route I should get
 | 
				
			||||||
 | 
					            | waypoints | route | turns         |
 | 
				
			||||||
 | 
					            | e,c       | ,     | depart,arrive |
 | 
				
			||||||
 | 
					            | c,e       | ,     | depart,arrive |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Scenario: Straight onto low-priority: unnamed
 | 
				
			||||||
 | 
					        Given the node map
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					                c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            a   b d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                e
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        And the ways
 | 
				
			||||||
 | 
					            | nodes  | highway     | name    |
 | 
				
			||||||
 | 
					            | abd    | residential | road    |
 | 
				
			||||||
 | 
					            | eb     | service     | service |
 | 
				
			||||||
 | 
					            | bc     | service     |         |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When I route I should get
 | 
				
			||||||
 | 
					            | waypoints | route             | turns                       |
 | 
				
			||||||
 | 
					            | e,c       | service,          | depart,arrive               |
 | 
				
			||||||
 | 
					            | c,e       | ,service,service  | depart,turn straight,arrive |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Scenario: Straight onto low-priority
 | 
				
			||||||
 | 
					        Given the node map
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					            a b c
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        And the ways
 | 
				
			||||||
 | 
					            | nodes  | highway     | name    |
 | 
				
			||||||
 | 
					            | ab     | residential | road    |
 | 
				
			||||||
 | 
					            | bc     | service     | service |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When I route I should get
 | 
				
			||||||
 | 
					            | waypoints | route                | turns                           |
 | 
				
			||||||
 | 
					            | a,c       | road,service,service | depart,new name straight,arrive |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Scenario: Straight onto low-priority, with driveway
 | 
				
			||||||
 | 
					        Given the node map
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					                  f
 | 
				
			||||||
 | 
					            a b   c
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        And the ways
 | 
				
			||||||
 | 
					            | nodes  | highway     | name  |
 | 
				
			||||||
 | 
					            | ab     | residential | road  |
 | 
				
			||||||
 | 
					            | bc     | service     | road  |
 | 
				
			||||||
 | 
					            | bf     | driveway    |       |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When I route I should get
 | 
				
			||||||
 | 
					            | waypoints | route      | turns         |
 | 
				
			||||||
 | 
					            | a,c       | road,road  | depart,arrive |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Scenario: Straight onto low-priority, with driveway
 | 
				
			||||||
 | 
					        Given the node map
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					                  f
 | 
				
			||||||
 | 
					            a b   c
 | 
				
			||||||
 | 
					            """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        And the ways
 | 
				
			||||||
 | 
					            | nodes  | highway     | name  |
 | 
				
			||||||
 | 
					            | ab     | residential | road  |
 | 
				
			||||||
 | 
					            | bc     | service     |       |
 | 
				
			||||||
 | 
					            | bf     | driveway    |       |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       When I route I should get
 | 
				
			||||||
 | 
					            | waypoints | route      | turns                           |
 | 
				
			||||||
 | 
					            | a,c       | road,      | depart,arrive                   |
 | 
				
			||||||
 | 
					            | c,a       | ,road,road | depart,new name straight,arrive |
 | 
				
			||||||
@ -165,6 +165,7 @@ inline bool obviousByRoadClass(const RoadClassification in_classification,
 | 
				
			|||||||
                               const RoadClassification obvious_candidate,
 | 
					                               const RoadClassification obvious_candidate,
 | 
				
			||||||
                               const RoadClassification compare_candidate)
 | 
					                               const RoadClassification compare_candidate)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    // lower numbers are of higher priority
 | 
				
			||||||
    const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
 | 
					    const bool has_high_priority = PRIORITY_DISTINCTION_FACTOR * obvious_candidate.GetPriority() <
 | 
				
			||||||
                                   compare_candidate.GetPriority();
 | 
					                                   compare_candidate.GetPriority();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
#include "extractor/guidance/intersection_handler.hpp"
 | 
					 | 
				
			||||||
#include "extractor/guidance/constants.hpp"
 | 
					#include "extractor/guidance/constants.hpp"
 | 
				
			||||||
 | 
					#include "extractor/guidance/intersection_handler.hpp"
 | 
				
			||||||
#include "extractor/guidance/toolkit.hpp"
 | 
					#include "extractor/guidance/toolkit.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "util/coordinate_calculation.hpp"
 | 
					#include "util/coordinate_calculation.hpp"
 | 
				
			||||||
@ -383,186 +383,210 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
    if (intersection.size() == 2)
 | 
					    if (intersection.size() == 2)
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // at least three roads
 | 
					    const EdgeData &in_way_data = node_based_graph.GetEdgeData(via_edge);
 | 
				
			||||||
    std::size_t best = 0;
 | 
					 | 
				
			||||||
    double best_deviation = 180;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // the strategy for picking the most obvious turn involves deciding between
 | 
				
			||||||
 | 
					    // an overall best candidate and a best candidate that shares the same name
 | 
				
			||||||
 | 
					    // as the in road, i.e. a continue road
 | 
				
			||||||
 | 
					    std::size_t best_option = 0;
 | 
				
			||||||
 | 
					    double best_option_deviation = 180;
 | 
				
			||||||
    std::size_t best_continue = 0;
 | 
					    std::size_t best_continue = 0;
 | 
				
			||||||
    double best_continue_deviation = 180;
 | 
					    double best_continue_deviation = 180;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const EdgeData &in_data = node_based_graph.GetEdgeData(via_edge);
 | 
					    /* helper functions */
 | 
				
			||||||
    const auto in_classification = in_data.road_classification;
 | 
					    const auto IsContinueRoad = [&](const EdgeData &way_data) {
 | 
				
			||||||
 | 
					        return !util::guidance::requiresNameAnnounced(
 | 
				
			||||||
 | 
					            in_way_data.name_id, way_data.name_id, name_table, street_name_suffix_table);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    auto sameOrHigherPriority = [&in_way_data](const auto &way_data) {
 | 
				
			||||||
 | 
					        return way_data.road_classification.GetPriority() <=
 | 
				
			||||||
 | 
					               in_way_data.road_classification.GetPriority();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    auto IsLowPriority = [](const auto &way_data) {
 | 
				
			||||||
 | 
					        return way_data.road_classification.IsLowPriorityRoadClass();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    // These two Compare functions are used for sifting out best option and continue
 | 
				
			||||||
 | 
					    // candidates by evaluating all the ways in an intersection by what they share
 | 
				
			||||||
 | 
					    // with the in way. Ideal candidates are of similar road class with the in way
 | 
				
			||||||
 | 
					    // and are require relatively straight turns.
 | 
				
			||||||
 | 
					    const auto RoadCompare = [&](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
 | 
				
			||||||
 | 
					        const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
 | 
				
			||||||
 | 
					        const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
 | 
				
			||||||
 | 
					        const auto lhs_deviation = angularDeviation(lhs.angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					        const auto rhs_deviation = angularDeviation(rhs.angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (std::size_t i = 1; i < intersection.size(); ++i)
 | 
					        const bool rhs_same_classification =
 | 
				
			||||||
 | 
					            rhs_data.road_classification == in_way_data.road_classification;
 | 
				
			||||||
 | 
					        const bool lhs_same_classification =
 | 
				
			||||||
 | 
					            lhs_data.road_classification == in_way_data.road_classification;
 | 
				
			||||||
 | 
					        const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_data);
 | 
				
			||||||
 | 
					        const bool rhs_low_priority = IsLowPriority(rhs_data);
 | 
				
			||||||
 | 
					        const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_data);
 | 
				
			||||||
 | 
					        const bool lhs_low_priority = IsLowPriority(lhs_data);
 | 
				
			||||||
 | 
					        auto left_tie = std::tie(lhs.entry_allowed,
 | 
				
			||||||
 | 
					                                 lhs_same_or_higher_priority,
 | 
				
			||||||
 | 
					                                 rhs_low_priority,
 | 
				
			||||||
 | 
					                                 rhs_deviation,
 | 
				
			||||||
 | 
					                                 lhs_same_classification);
 | 
				
			||||||
 | 
					        auto right_tie = std::tie(rhs.entry_allowed,
 | 
				
			||||||
 | 
					                                  rhs_same_or_higher_priority,
 | 
				
			||||||
 | 
					                                  lhs_low_priority,
 | 
				
			||||||
 | 
					                                  lhs_deviation,
 | 
				
			||||||
 | 
					                                  rhs_same_classification);
 | 
				
			||||||
 | 
					        return left_tie > right_tie;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const auto RoadCompareSameName = [&](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
 | 
				
			||||||
 | 
					        const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
 | 
				
			||||||
 | 
					        const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
 | 
				
			||||||
 | 
					        const auto lhs_continues = IsContinueRoad(lhs_data);
 | 
				
			||||||
 | 
					        const auto rhs_continues = IsContinueRoad(rhs_data);
 | 
				
			||||||
 | 
					        const auto left_tie = std::tie(lhs.entry_allowed, lhs_continues);
 | 
				
			||||||
 | 
					        const auto right_tie = std::tie(rhs.entry_allowed, rhs_continues);
 | 
				
			||||||
 | 
					        return left_tie > right_tie || (left_tie == right_tie && RoadCompare(lhs, rhs));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto best_option_it = std::min_element(begin(intersection), end(intersection), RoadCompare);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // min element should only return end() when vector is empty
 | 
				
			||||||
 | 
					    BOOST_ASSERT(best_option_it != end(intersection));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    best_option = std::distance(begin(intersection), best_option_it);
 | 
				
			||||||
 | 
					    best_option_deviation = angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					    const auto &best_option_data = node_based_graph.GetEdgeData(intersection[best_option].eid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Unless the in way is also low priority, it is generally undesirable to
 | 
				
			||||||
 | 
					    // indicate that a low priority road is obvious
 | 
				
			||||||
 | 
					    if (IsLowPriority(best_option_data) &&
 | 
				
			||||||
 | 
					        best_option_data.road_classification != in_way_data.road_classification)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const double deviation = angularDeviation(intersection[i].angle, STRAIGHT_ANGLE);
 | 
					        best_option = 0;
 | 
				
			||||||
        if (!intersection[i].entry_allowed)
 | 
					        best_option_deviation = 180;
 | 
				
			||||||
            continue;
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto out_data = node_based_graph.GetEdgeData(intersection[i].eid);
 | 
					    // double check if the way with the lowest deviation from straight is still be better choice
 | 
				
			||||||
        const auto continue_class =
 | 
					    const auto straightest = intersection.findClosestTurn(STRAIGHT_ANGLE);
 | 
				
			||||||
            node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification;
 | 
					    if (straightest != best_option_it)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        const auto same_name = !util::guidance::requiresNameAnnounced(
 | 
					        const EdgeData &straightest_data = node_based_graph.GetEdgeData(straightest->eid);
 | 
				
			||||||
            in_data.name_id, out_data.name_id, name_table, street_name_suffix_table);
 | 
					        double straightest_data_deviation = angularDeviation(straightest->angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					        const auto deviation_diff =
 | 
				
			||||||
        if (same_name && (best_continue == 0 || (continue_class.GetPriority() >
 | 
					            std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE;
 | 
				
			||||||
                                                     out_data.road_classification.GetPriority() &&
 | 
					        const auto not_ramp_class = !straightest_data.road_classification.IsRampClass();
 | 
				
			||||||
                                                 in_classification != continue_class) ||
 | 
					        const auto not_link_class = !straightest_data.road_classification.IsLinkClass();
 | 
				
			||||||
                          (deviation < best_continue_deviation &&
 | 
					        if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class && not_link_class &&
 | 
				
			||||||
                           out_data.road_classification == continue_class) ||
 | 
					            !IsContinueRoad(best_option_data))
 | 
				
			||||||
                          (continue_class != in_classification &&
 | 
					 | 
				
			||||||
                           out_data.road_classification == continue_class)))
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            best_continue_deviation = deviation;
 | 
					            best_option = std::distance(begin(intersection), straightest);
 | 
				
			||||||
            best_continue = i;
 | 
					            best_option_deviation =
 | 
				
			||||||
        }
 | 
					                angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        const auto current_best_class =
 | 
					 | 
				
			||||||
            node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // don't prefer low priority classes
 | 
					 | 
				
			||||||
        if (best != 0 && out_data.road_classification.IsLowPriorityRoadClass() &&
 | 
					 | 
				
			||||||
            !current_best_class.IsLowPriorityRoadClass())
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const bool is_better_choice_by_priority =
 | 
					 | 
				
			||||||
            best == 0 || obviousByRoadClass(in_data.road_classification,
 | 
					 | 
				
			||||||
                                            out_data.road_classification,
 | 
					 | 
				
			||||||
                                            current_best_class);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const bool other_is_better_choice_by_priority =
 | 
					 | 
				
			||||||
            best != 0 && obviousByRoadClass(in_data.road_classification,
 | 
					 | 
				
			||||||
                                            current_best_class,
 | 
					 | 
				
			||||||
                                            out_data.road_classification);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ((!other_is_better_choice_by_priority && deviation < best_deviation) ||
 | 
					 | 
				
			||||||
            is_better_choice_by_priority)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            best_deviation = deviation;
 | 
					 | 
				
			||||||
            best = i;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // We don't consider empty names a valid continue feature. This distinguishes between missing
 | 
					    // No non-low priority roads? Declare no obvious turn
 | 
				
			||||||
    // names and actual continuing roads.
 | 
					    if (best_option == 0)
 | 
				
			||||||
    if (in_data.name_id == EMPTY_NAMEID)
 | 
					 | 
				
			||||||
        best_continue = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (best == 0)
 | 
					 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const std::pair<std::int64_t, std::int64_t> num_continue_names = [&]() {
 | 
					    auto best_continue_it =
 | 
				
			||||||
        std::int64_t count = 0, count_valid = 0;
 | 
					        std::min_element(begin(intersection), end(intersection), RoadCompareSameName);
 | 
				
			||||||
        if (in_data.name_id != EMPTY_NAMEID)
 | 
					    const auto best_continue_data = node_based_graph.GetEdgeData(best_continue_it->eid);
 | 
				
			||||||
        {
 | 
					    if (IsContinueRoad(best_continue_data) || (in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID))
 | 
				
			||||||
            for (std::size_t i = 1; i < intersection.size(); ++i)
 | 
					    {
 | 
				
			||||||
            {
 | 
					        best_continue = std::distance(begin(intersection), best_continue_it);
 | 
				
			||||||
                const auto &road = intersection[i];
 | 
					        best_continue_deviation =
 | 
				
			||||||
                const auto &road_data = node_based_graph.GetEdgeData(road.eid);
 | 
					            angularDeviation(intersection[best_continue].angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const auto same_name = !util::guidance::requiresNameAnnounced(
 | 
					    // if the best angle is going straight but the road is turning, declare no obvious turn
 | 
				
			||||||
                    in_data.name_id, road_data.name_id, name_table, street_name_suffix_table);
 | 
					    if (0 != best_continue && best_option != best_continue &&
 | 
				
			||||||
 | 
					        best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
 | 
				
			||||||
                if (same_name)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    ++count;
 | 
					 | 
				
			||||||
                    if (road.entry_allowed)
 | 
					 | 
				
			||||||
                        ++count_valid;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return std::make_pair(count, count_valid);
 | 
					 | 
				
			||||||
    }();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (0 != best_continue && best != best_continue &&
 | 
					 | 
				
			||||||
        angularDeviation(intersection[best].angle, STRAIGHT_ANGLE) <
 | 
					 | 
				
			||||||
            MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
 | 
					 | 
				
			||||||
        node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification ==
 | 
					        node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification ==
 | 
				
			||||||
            node_based_graph.GetEdgeData(intersection[best].eid).road_classification)
 | 
					            best_option_data.road_classification)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // if the best angle is going straight but the road is turning, we don't name anything
 | 
					 | 
				
			||||||
        // obvious
 | 
					 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // get a count of number of ways from that intersection that qualify to have
 | 
				
			||||||
 | 
					    // continue instruction because they share a name with the approaching way
 | 
				
			||||||
 | 
					    const std::int64_t continue_count =
 | 
				
			||||||
 | 
					        count_if(++begin(intersection), end(intersection), [&](const ConnectedRoad &way) {
 | 
				
			||||||
 | 
					            return IsContinueRoad(node_based_graph.GetEdgeData(way.eid));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    const std::int64_t continue_count_valid =
 | 
				
			||||||
 | 
					        count_if(++begin(intersection), end(intersection), [&](const ConnectedRoad &way) {
 | 
				
			||||||
 | 
					            return IsContinueRoad(node_based_graph.GetEdgeData(way.eid)) && way.entry_allowed;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // checks if continue candidates are sharp turns
 | 
				
			||||||
    const bool all_continues_are_narrow = [&]() {
 | 
					    const bool all_continues_are_narrow = [&]() {
 | 
				
			||||||
        if (in_data.name_id == EMPTY_NAMEID)
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return std::count_if(
 | 
					        return std::count_if(
 | 
				
			||||||
                   intersection.begin() + 1, intersection.end(), [&](const ConnectedRoad &road) {
 | 
					                   begin(intersection), end(intersection), [&](const ConnectedRoad &road) {
 | 
				
			||||||
                       const auto &road_data = node_based_graph.GetEdgeData(road.eid);
 | 
					                       const EdgeData &road_data = node_based_graph.GetEdgeData(road.eid);
 | 
				
			||||||
                       const auto same_name =
 | 
					                       const double &road_angle = angularDeviation(road.angle, STRAIGHT_ANGLE);
 | 
				
			||||||
                           !util::guidance::requiresNameAnnounced(in_data.name_id,
 | 
					                       return IsContinueRoad(road_data) && (road_angle < NARROW_TURN_ANGLE);
 | 
				
			||||||
                                                                  road_data.name_id,
 | 
					                   }) == continue_count;
 | 
				
			||||||
                                                                  name_table,
 | 
					 | 
				
			||||||
                                                                  street_name_suffix_table);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                       return same_name &&
 | 
					 | 
				
			||||||
                              angularDeviation(road.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE;
 | 
					 | 
				
			||||||
                   }) == num_continue_names.first;
 | 
					 | 
				
			||||||
    }();
 | 
					    }();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // has no obvious continued road
 | 
					    // return true if the best_option candidate is more promising than the best_continue candidate
 | 
				
			||||||
    const auto &best_data = node_based_graph.GetEdgeData(intersection[best].eid);
 | 
					    // otherwise return false, the best_continue candidate is more promising
 | 
				
			||||||
 | 
					    const auto best_over_best_continue = [&]() {
 | 
				
			||||||
    const auto check_non_continue = [&]() {
 | 
					 | 
				
			||||||
        // no continue road exists
 | 
					        // no continue road exists
 | 
				
			||||||
        if (best_continue == 0)
 | 
					        if (best_continue == 0)
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // we have multiple continues and not all are narrow (treat all the same)
 | 
					        // we have multiple continues and not all are narrow. This suggests that
 | 
				
			||||||
        if (!all_continues_are_narrow &&
 | 
					        // the continue candidates are ambiguous
 | 
				
			||||||
            (num_continue_names.first >= 2 && intersection.size() >= 4))
 | 
					        if (!all_continues_are_narrow && (continue_count >= 2 && intersection.size() >= 4))
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // if the best continue is not narrow and we also have at least 2 possible choices, the
 | 
					        // if the best continue is not narrow and we also have at least 2 possible choices, the
 | 
				
			||||||
        // intersection size does not matter anymore
 | 
					        // intersection size does not matter anymore
 | 
				
			||||||
        if (num_continue_names.second >= 2 && best_continue_deviation >= 2 * NARROW_TURN_ANGLE)
 | 
					        if (continue_count_valid >= 2 && best_continue_deviation >= 2 * NARROW_TURN_ANGLE)
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // continue data now most certainly exists
 | 
					        // continue data now most certainly exists
 | 
				
			||||||
        const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
 | 
					        const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (obviousByRoadClass(in_data.road_classification,
 | 
					        // best_continue is obvious by road class
 | 
				
			||||||
 | 
					        if (obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
                               continue_data.road_classification,
 | 
					                               continue_data.road_classification,
 | 
				
			||||||
                               best_data.road_classification))
 | 
					                               best_option_data.road_classification))
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (obviousByRoadClass(in_data.road_classification,
 | 
					        // best_option is obvious by road class
 | 
				
			||||||
                               best_data.road_classification,
 | 
					        if (obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
 | 
					                               best_option_data.road_classification,
 | 
				
			||||||
                               continue_data.road_classification))
 | 
					                               continue_data.road_classification))
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // the best deviation is very straight and not a ramp
 | 
					        // the best_option deviation is very straight and not a ramp
 | 
				
			||||||
        if (best_deviation < best_continue_deviation && best_deviation < FUZZY_ANGLE_DIFFERENCE &&
 | 
					        if (best_option_deviation < best_continue_deviation &&
 | 
				
			||||||
            !best_data.road_classification.IsRampClass())
 | 
					            best_option_deviation < FUZZY_ANGLE_DIFFERENCE &&
 | 
				
			||||||
 | 
					            !best_option_data.road_classification.IsRampClass())
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // the continue road is of a lower priority, while the road continues on the same priority
 | 
					        // the continue road is of a lower priority, while the road continues on the same priority
 | 
				
			||||||
        // with a better angle
 | 
					        // with a better angle
 | 
				
			||||||
        if (best_deviation < best_continue_deviation &&
 | 
					        if (best_option_deviation < best_continue_deviation &&
 | 
				
			||||||
            in_data.road_classification == best_data.road_classification &&
 | 
					            in_way_data.road_classification == best_option_data.road_classification &&
 | 
				
			||||||
            continue_data.road_classification.GetPriority() >
 | 
					            continue_data.road_classification.GetPriority() >
 | 
				
			||||||
                best_data.road_classification.GetPriority())
 | 
					                best_option_data.road_classification.GetPriority())
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }();
 | 
					    }();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (check_non_continue)
 | 
					    if (best_over_best_continue)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Find left/right deviation
 | 
					        // Find left/right deviation
 | 
				
			||||||
        // skipping over service roads
 | 
					        // skipping over service roads
 | 
				
			||||||
        const std::size_t left_index = [&]() {
 | 
					        const std::size_t left_index = [&]() {
 | 
				
			||||||
            const auto index_candidate = (best + 1) % intersection.size();
 | 
					            const auto index_candidate = (best_option + 1) % intersection.size();
 | 
				
			||||||
            if (index_candidate == 0)
 | 
					            if (index_candidate == 0)
 | 
				
			||||||
                return index_candidate;
 | 
					                return index_candidate;
 | 
				
			||||||
            const auto &candidate_data =
 | 
					            const auto &candidate_data =
 | 
				
			||||||
                node_based_graph.GetEdgeData(intersection[index_candidate].eid);
 | 
					                node_based_graph.GetEdgeData(intersection[index_candidate].eid);
 | 
				
			||||||
            if (obviousByRoadClass(in_data.road_classification,
 | 
					            if (obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
                                   best_data.road_classification,
 | 
					                                   best_option_data.road_classification,
 | 
				
			||||||
                                   candidate_data.road_classification))
 | 
					                                   candidate_data.road_classification))
 | 
				
			||||||
                return (index_candidate + 1) % intersection.size();
 | 
					                return (index_candidate + 1) % intersection.size();
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
@ -570,14 +594,14 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        }();
 | 
					        }();
 | 
				
			||||||
        const auto right_index = [&]() {
 | 
					        const auto right_index = [&]() {
 | 
				
			||||||
            BOOST_ASSERT(best > 0);
 | 
					            BOOST_ASSERT(best_option > 0);
 | 
				
			||||||
            const auto index_candidate = best - 1;
 | 
					            const auto index_candidate = best_option - 1;
 | 
				
			||||||
            if (index_candidate == 0)
 | 
					            if (index_candidate == 0)
 | 
				
			||||||
                return index_candidate;
 | 
					                return index_candidate;
 | 
				
			||||||
            const auto candidate_data =
 | 
					            const auto candidate_data =
 | 
				
			||||||
                node_based_graph.GetEdgeData(intersection[index_candidate].eid);
 | 
					                node_based_graph.GetEdgeData(intersection[index_candidate].eid);
 | 
				
			||||||
            if (obviousByRoadClass(in_data.road_classification,
 | 
					            if (obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
                                   best_data.road_classification,
 | 
					                                   best_option_data.road_classification,
 | 
				
			||||||
                                   candidate_data.road_classification))
 | 
					                                   candidate_data.road_classification))
 | 
				
			||||||
                return index_candidate - 1;
 | 
					                return index_candidate - 1;
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
@ -589,28 +613,32 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
        const double right_deviation =
 | 
					        const double right_deviation =
 | 
				
			||||||
            angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
 | 
					            angularDeviation(intersection[right_index].angle, STRAIGHT_ANGLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (best_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
 | 
					        // return best_option candidate if it is nearly straight and distinct from the nearest other
 | 
				
			||||||
 | 
					        // out
 | 
				
			||||||
 | 
					        // way
 | 
				
			||||||
 | 
					        if (best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
 | 
				
			||||||
            std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
 | 
					            std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
 | 
				
			||||||
            return best;
 | 
					            return best_option;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid);
 | 
					        const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid);
 | 
				
			||||||
        const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid);
 | 
					        const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const bool obvious_to_left =
 | 
					        const bool obvious_to_left =
 | 
				
			||||||
            left_index == 0 || obviousByRoadClass(in_data.road_classification,
 | 
					            left_index == 0 || obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
                                                  best_data.road_classification,
 | 
					                                                  best_option_data.road_classification,
 | 
				
			||||||
                                                  left_data.road_classification);
 | 
					                                                  left_data.road_classification);
 | 
				
			||||||
        const bool obvious_to_right =
 | 
					        const bool obvious_to_right =
 | 
				
			||||||
            right_index == 0 || obviousByRoadClass(in_data.road_classification,
 | 
					            right_index == 0 || obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
                                                   best_data.road_classification,
 | 
					                                                   best_option_data.road_classification,
 | 
				
			||||||
                                                   right_data.road_classification);
 | 
					                                                   right_data.road_classification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // if the best turn isn't narrow, but there is a nearly straight turn, we don't consider the
 | 
					        // if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
 | 
				
			||||||
 | 
					        // consider the
 | 
				
			||||||
        // turn obvious
 | 
					        // turn obvious
 | 
				
			||||||
        const auto check_narrow = [&intersection, best_deviation](const std::size_t index) {
 | 
					        const auto check_narrow = [&intersection, best_option_deviation](const std::size_t index) {
 | 
				
			||||||
            return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
 | 
					            return angularDeviation(intersection[index].angle, STRAIGHT_ANGLE) <=
 | 
				
			||||||
                       FUZZY_ANGLE_DIFFERENCE &&
 | 
					                       FUZZY_ANGLE_DIFFERENCE &&
 | 
				
			||||||
                   (best_deviation > NARROW_TURN_ANGLE || intersection[index].entry_allowed);
 | 
					                   (best_option_deviation > NARROW_TURN_ANGLE || intersection[index].entry_allowed);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // other narrow turns?
 | 
					        // other narrow turns?
 | 
				
			||||||
@ -620,20 +648,23 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
        if (check_narrow(left_index) && !obvious_to_left)
 | 
					        if (check_narrow(left_index) && !obvious_to_left)
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // check if a turn is distinct enough
 | 
					        // checks if a given way in the intersection is distinct enough from the best_option
 | 
				
			||||||
 | 
					        // candidate
 | 
				
			||||||
        const auto isDistinct = [&](const std::size_t index, const double deviation) {
 | 
					        const auto isDistinct = [&](const std::size_t index, const double deviation) {
 | 
				
			||||||
            /*
 | 
					            /*
 | 
				
			||||||
               If the neighbor is not possible to enter, we allow for a lower
 | 
					               If the neighbor is not possible to enter, we allow for a lower
 | 
				
			||||||
               distinction rate. If the road category is smaller, its also adjusted. Only
 | 
					               distinction rate. If the road category is smaller, its also adjusted. Only
 | 
				
			||||||
               roads of the same priority require the full distinction ratio.
 | 
					               roads of the same priority require the full distinction ratio.
 | 
				
			||||||
             */
 | 
					             */
 | 
				
			||||||
 | 
					            const auto &best_option_data =
 | 
				
			||||||
 | 
					                node_based_graph.GetEdgeData(intersection[best_option].eid);
 | 
				
			||||||
            const auto adjusted_distinction_ratio = [&]() {
 | 
					            const auto adjusted_distinction_ratio = [&]() {
 | 
				
			||||||
                // not allowed competitors are easily distinct
 | 
					                // not allowed competitors are easily distinct
 | 
				
			||||||
                if (!intersection[index].entry_allowed)
 | 
					                if (!intersection[index].entry_allowed)
 | 
				
			||||||
                    return 0.7 * DISTINCTION_RATIO;
 | 
					                    return 0.7 * DISTINCTION_RATIO;
 | 
				
			||||||
                // a bit less obvious are road classes
 | 
					                // a bit less obvious are road classes
 | 
				
			||||||
                else if (in_data.road_classification == best_data.road_classification &&
 | 
					                else if (in_way_data.road_classification == best_option_data.road_classification &&
 | 
				
			||||||
                         best_data.road_classification.GetPriority() <
 | 
					                         best_option_data.road_classification.GetPriority() <
 | 
				
			||||||
                             node_based_graph.GetEdgeData(intersection[index].eid)
 | 
					                             node_based_graph.GetEdgeData(intersection[index].eid)
 | 
				
			||||||
                                 .road_classification.GetPriority())
 | 
					                                 .road_classification.GetPriority())
 | 
				
			||||||
                    return 0.8 * DISTINCTION_RATIO;
 | 
					                    return 0.8 * DISTINCTION_RATIO;
 | 
				
			||||||
@ -641,7 +672,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
                else
 | 
					                else
 | 
				
			||||||
                    return DISTINCTION_RATIO;
 | 
					                    return DISTINCTION_RATIO;
 | 
				
			||||||
            }();
 | 
					            }();
 | 
				
			||||||
            return index == 0 || deviation / best_deviation >= adjusted_distinction_ratio ||
 | 
					            return index == 0 || deviation / best_option_deviation >= adjusted_distinction_ratio ||
 | 
				
			||||||
                   (deviation <= NARROW_TURN_ANGLE && !intersection[index].entry_allowed);
 | 
					                   (deviation <= NARROW_TURN_ANGLE && !intersection[index].entry_allowed);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -649,25 +680,24 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
        const bool distinct_to_right = isDistinct(right_index, right_deviation);
 | 
					        const bool distinct_to_right = isDistinct(right_index, right_deviation);
 | 
				
			||||||
        // Well distinct turn that is nearly straight
 | 
					        // Well distinct turn that is nearly straight
 | 
				
			||||||
        if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
 | 
					        if ((distinct_to_left || obvious_to_left) && (distinct_to_right || obvious_to_right))
 | 
				
			||||||
            return best;
 | 
					            return best_option;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const double deviation =
 | 
					 | 
				
			||||||
            angularDeviation(intersection[best_continue].angle, STRAIGHT_ANGLE);
 | 
					 | 
				
			||||||
        const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
 | 
					        const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
 | 
				
			||||||
        if (std::abs(deviation) < 1)
 | 
					        if (std::abs(best_continue_deviation) < 1)
 | 
				
			||||||
            return best_continue;
 | 
					            return best_continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // check if any other similar best continues exist
 | 
					        // check if any other similar best continues exist
 | 
				
			||||||
        for (std::size_t i = 1; i < intersection.size(); ++i)
 | 
					        std::size_t i, last = intersection.size();
 | 
				
			||||||
 | 
					        for (i = 1; i < last; ++i)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (i == best_continue || !intersection[i].entry_allowed)
 | 
					            if (i == best_continue || !intersection[i].entry_allowed)
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].eid);
 | 
					            const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].eid);
 | 
				
			||||||
            const bool is_obvious_by_road_class =
 | 
					            const bool is_obvious_by_road_class =
 | 
				
			||||||
                obviousByRoadClass(in_data.road_classification,
 | 
					                obviousByRoadClass(in_way_data.road_classification,
 | 
				
			||||||
                                   continue_data.road_classification,
 | 
					                                   continue_data.road_classification,
 | 
				
			||||||
                                   turn_data.road_classification);
 | 
					                                   turn_data.road_classification);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -677,7 +707,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // continuation could be grouped with a straight turn and the turning road is a ramp
 | 
					            // continuation could be grouped with a straight turn and the turning road is a ramp
 | 
				
			||||||
            if (turn_data.road_classification.IsRampClass() && deviation < GROUP_ANGLE)
 | 
					            if (turn_data.road_classification.IsRampClass() &&
 | 
				
			||||||
 | 
					                best_continue_deviation < GROUP_ANGLE &&
 | 
				
			||||||
 | 
					                !continue_data.road_classification.IsRampClass())
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // perfectly straight turns prevent obviousness
 | 
					            // perfectly straight turns prevent obviousness
 | 
				
			||||||
@ -685,9 +717,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
 | 
				
			|||||||
            if (turn_deviation < FUZZY_ANGLE_DIFFERENCE)
 | 
					            if (turn_deviation < FUZZY_ANGLE_DIFFERENCE)
 | 
				
			||||||
                return 0;
 | 
					                return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const auto deviation_ratio = turn_deviation / deviation;
 | 
					            const auto deviation_ratio = turn_deviation / best_continue_deviation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // in comparison to normal devitions, a continue road can offer a smaller distinction
 | 
					            // in comparison to normal deviations, a continue road can offer a smaller distinction
 | 
				
			||||||
            // ratio. Other roads close to the turn angle are not as obvious, if one road continues.
 | 
					            // ratio. Other roads close to the turn angle are not as obvious, if one road continues.
 | 
				
			||||||
            if (deviation_ratio < DISTINCTION_RATIO / 1.5)
 | 
					            if (deviation_ratio < DISTINCTION_RATIO / 1.5)
 | 
				
			||||||
                return 0;
 | 
					                return 0;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user