calculate roundabout radius from circumference, fix #2716
This commit is contained in:
parent
3d5a53566c
commit
7e2663f2ad
@ -244,8 +244,28 @@ Feature: Basic Roundabout
|
|||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns |
|
| waypoints | route | turns |
|
||||||
| a,e | ab,ce,ce | depart,roundabout-exit-1,arrive |
|
| a,e | ab,ce,ce | depart,roundabout turn right exit-1,arrive |
|
||||||
| a,f | ab,df,df | depart,roundabout-exit-2,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
|
Scenario: Collinear in X,Y
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -231,43 +231,6 @@ Feature: Basic Roundabout
|
|||||||
| j,f | jk,ef,ef | depart,roundabout-exit-2,arrive |
|
| j,f | jk,ef,ef | depart,roundabout-exit-2,arrive |
|
||||||
| j,c | jk,bc,bc | depart,roundabout-exit-3,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
|
Scenario: Motorway Roundabout
|
||||||
#See 39.933742 -75.082345
|
#See 39.933742 -75.082345
|
||||||
Given the node map
|
Given the node map
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -82,7 +82,8 @@ class RoundaboutHandler : public IntersectionHandler
|
|||||||
const bool can_exit_roundabout,
|
const bool can_exit_roundabout,
|
||||||
Intersection intersection) const;
|
Intersection intersection) const;
|
||||||
|
|
||||||
bool qualifiesAsRoundaboutIntersection(const std::set<NodeID> &roundabout_nodes) const;
|
bool
|
||||||
|
qualifiesAsRoundaboutIntersection(const std::unordered_set<NodeID> &roundabout_nodes) const;
|
||||||
|
|
||||||
const CompressedEdgeContainer &compressed_edge_container;
|
const CompressedEdgeContainer &compressed_edge_container;
|
||||||
const ProfileProperties &profile_properties;
|
const ProfileProperties &profile_properties;
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
@ -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
|
// 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.
|
// in postprocessing since we correct the turn-angle in turn-generaion.
|
||||||
bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
|
bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
|
||||||
const std::set<NodeID> &roundabout_nodes) const
|
const std::unordered_set<NodeID> &roundabout_nodes) const
|
||||||
{
|
{
|
||||||
// translate a node ID into its respective coordinate stored in the node_info_list
|
// translate a node ID into its respective coordinate stored in the node_info_list
|
||||||
const auto getCoordinate = [this](const NodeID node) {
|
const auto getCoordinate = [this](const NodeID node) {
|
||||||
@ -262,10 +261,6 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
|||||||
}
|
}
|
||||||
return continue_edge;
|
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<NodeID> roundabout_nodes; // needs to be sorted
|
|
||||||
|
|
||||||
// this value is a hard abort to deal with potential self-loops
|
// this value is a hard abort to deal with potential self-loops
|
||||||
const auto countRoundaboutFlags = [&](const NodeID at_node) {
|
const auto countRoundaboutFlags = [&](const NodeID at_node) {
|
||||||
@ -281,6 +276,25 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
|||||||
return count;
|
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<NodeID> roundabout_nodes;
|
||||||
|
double roundabout_length = 0.;
|
||||||
|
|
||||||
NodeID last_node = nid;
|
NodeID last_node = nid;
|
||||||
while (0 == roundabout_nodes.count(last_node))
|
while (0 == roundabout_nodes.count(last_node))
|
||||||
{
|
{
|
||||||
@ -299,6 +313,8 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
|||||||
return RoundaboutType::None;
|
return RoundaboutType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
roundabout_length += getEdgeLength(last_node, eid);
|
||||||
|
|
||||||
last_node = node_based_graph.GetTarget(eid);
|
last_node = node_based_graph.GetTarget(eid);
|
||||||
|
|
||||||
if (last_node == nid)
|
if (last_node == nid)
|
||||||
@ -315,31 +331,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
|||||||
return RoundaboutType::RoundaboutIntersection;
|
return RoundaboutType::RoundaboutIntersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the radius of the roundabout/rotary. For two coordinates, we assume a minimal
|
const double radius = roundabout_length / (2 * M_PI);
|
||||||
// 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;
|
|
||||||
|
|
||||||
// Looks like a rotary: large roundabout with dedicated name
|
// Looks like a rotary: large roundabout with dedicated name
|
||||||
// do we have a dedicated name for the rotary, if not its a roundabout
|
// do we have a dedicated name for the rotary, if not its a roundabout
|
||||||
|
Loading…
Reference in New Issue
Block a user