diff --git a/features/guidance/roundabout-turn.feature b/features/guidance/roundabout-turn.feature index d62c5fe0a..00b7644a0 100644 --- a/features/guidance/roundabout-turn.feature +++ b/features/guidance/roundabout-turn.feature @@ -243,9 +243,29 @@ Feature: Basic Roundabout | df | | When I route I should get - | waypoints | route | turns | - | a,e | ab,ce,ce | depart,roundabout-exit-1,arrive | - | a,f | ab,df,df | depart,roundabout-exit-2,arrive | + | waypoints | route | turns | + | a,e | ab,ce,ce | depart,roundabout turn right exit-1,arrive | + | a,f | ab,df,df | depart,roundabout turn straight exit-2,arrive | + + Scenario: Collinear in Y + Given the node map + | | a | + | | b | + | e | c | + | | d | + | | f | + + And the ways + | nodes | junction | + | ab | | + | bcdb | roundabout | + | ce | | + | df | | + + When I route I should get + | waypoints | route | turns | + | a,e | ab,ce,ce | depart,roundabout turn right exit-1,arrive | + | a,f | ab,df,df | depart,roundabout turn straight exit-2,arrive | Scenario: Collinear in X,Y Given the node map diff --git a/features/guidance/roundabout.feature b/features/guidance/roundabout.feature index a02c762be..56af30c48 100644 --- a/features/guidance/roundabout.feature +++ b/features/guidance/roundabout.feature @@ -231,43 +231,6 @@ Feature: Basic Roundabout | j,f | jk,ef,ef | depart,roundabout-exit-2,arrive | | j,c | jk,bc,bc | depart,roundabout-exit-3,arrive | - Scenario: Collinear in X - Given the node map - | a | b | c | d | f | - | | | e | | | - - And the ways - | nodes | junction | - | ab | | - | bcdb | roundabout | - | ce | | - | df | | - - When I route I should get - | waypoints | route | turns | - | a,e | ab,ce,ce | depart,roundabout-exit-1,arrive | - | a,f | ab,df,df | depart,roundabout-exit-2,arrive | - - Scenario: Collinear in Y - Given the node map - | | a | - | | b | - | e | c | - | | d | - | | f | - - And the ways - | nodes | junction | - | ab | | - | bcdb | roundabout | - | ce | | - | df | | - - When I route I should get - | waypoints | route | turns | - | a,e | ab,ce,ce | depart,roundabout-exit-1,arrive | - | a,f | ab,df,df | depart,roundabout-exit-2,arrive | - Scenario: Motorway Roundabout #See 39.933742 -75.082345 Given the node map diff --git a/include/extractor/guidance/roundabout_handler.hpp b/include/extractor/guidance/roundabout_handler.hpp index 9aee76975..5fd33dbc1 100644 --- a/include/extractor/guidance/roundabout_handler.hpp +++ b/include/extractor/guidance/roundabout_handler.hpp @@ -13,7 +13,7 @@ #include "util/node_based_graph.hpp" #include "util/typedefs.hpp" -#include +#include #include #include @@ -82,7 +82,8 @@ class RoundaboutHandler : public IntersectionHandler const bool can_exit_roundabout, Intersection intersection) const; - bool qualifiesAsRoundaboutIntersection(const std::set &roundabout_nodes) const; + bool + qualifiesAsRoundaboutIntersection(const std::unordered_set &roundabout_nodes) const; const CompressedEdgeContainer &compressed_edge_container; const ProfileProperties &profile_properties; diff --git a/src/extractor/guidance/roundabout_handler.cpp b/src/extractor/guidance/roundabout_handler.cpp index 4018f261c..2b890e3c3 100644 --- a/src/extractor/guidance/roundabout_handler.cpp +++ b/src/extractor/guidance/roundabout_handler.cpp @@ -8,7 +8,6 @@ #include #include -#include #include @@ -145,7 +144,7 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid, // Processing segregated roads would technically require an angle of the turn to be available // in postprocessing since we correct the turn-angle in turn-generaion. bool RoundaboutHandler::qualifiesAsRoundaboutIntersection( - const std::set &roundabout_nodes) const + const std::unordered_set &roundabout_nodes) const { // translate a node ID into its respective coordinate stored in the node_info_list const auto getCoordinate = [this](const NodeID node) { @@ -262,10 +261,6 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const } return continue_edge; }; - // the roundabout radius has to be the same for all locations we look at it from - // to guarantee this, we search the full roundabout for its vertices - // and select the three smallest ids - std::set roundabout_nodes; // needs to be sorted // this value is a hard abort to deal with potential self-loops const auto countRoundaboutFlags = [&](const NodeID at_node) { @@ -281,6 +276,25 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const return count; }; + const auto getEdgeLength = [&](const NodeID source_node, EdgeID eid) { + double length = 0.; + auto last_coord = getCoordinate(source_node); + const auto &edge_bucket = compressed_edge_container.GetBucketReference(eid); + for (const auto &compressed_edge : edge_bucket) + { + const auto next_coord = getCoordinate(compressed_edge.node_id); + length += util::coordinate_calculation::haversineDistance(last_coord, next_coord); + last_coord = next_coord; + } + return length; + }; + + // the roundabout radius has to be the same for all locations we look at it from + // to guarantee this, we search the full roundabout for its vertices + // and select the three smallest ids + std::unordered_set roundabout_nodes; + double roundabout_length = 0.; + NodeID last_node = nid; while (0 == roundabout_nodes.count(last_node)) { @@ -299,6 +313,8 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const return RoundaboutType::None; } + roundabout_length += getEdgeLength(last_node, eid); + last_node = node_based_graph.GetTarget(eid); if (last_node == nid) @@ -315,31 +331,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const return RoundaboutType::RoundaboutIntersection; } - // calculate the radius of the roundabout/rotary. For two coordinates, we assume a minimal - // circle - // with both vertices right at the other side (so half their distance in meters). - // Otherwise, we construct a circle through the first tree vertices. - const auto getRadius = [&roundabout_nodes, &getCoordinate]() { - auto node_itr = roundabout_nodes.begin(); - if (roundabout_nodes.size() == 2) - { - const auto first = getCoordinate(*node_itr++), second = getCoordinate(*node_itr++); - return 0.5 * util::coordinate_calculation::haversineDistance(first, second); - } - else - { - const auto first = getCoordinate(*node_itr++), second = getCoordinate(*node_itr++), - third = getCoordinate(*node_itr++); - return util::coordinate_calculation::circleRadius(first, second, third); - } - }; - const double radius = getRadius(); - - // check whether the circle computation has gone wrong - // The radius computation can result in infinity, if the three coordinates are non-distinct. - // To stay on the safe side, we say its not a rotary - if (std::isinf(radius)) - return RoundaboutType::Roundabout; + const double radius = roundabout_length / (2 * M_PI); // Looks like a rotary: large roundabout with dedicated name // do we have a dedicated name for the rotary, if not its a roundabout