Fix incorrect exit turn invalidation

This commit is contained in:
Michael Krasnyk 2017-04-27 12:24:31 +02:00 committed by Patrick Niklaus
parent 07c7cb3c6c
commit 19494984eb
2 changed files with 106 additions and 20 deletions

View File

@ -222,6 +222,43 @@ Feature: Basic Roundabout
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-3,arrive |
Scenario: Mixed Entry and Exit - clockwise order
Given the node map
"""
c a
j b f
k e
l h d
g i
"""
And the ways
| nodes | junction | oneway |
| abc | | yes |
| def | | yes |
| ghi | | yes |
| jkl | | yes |
| behkb | roundabout | yes |
When I route I should get
| waypoints | route | turns |
| a,c | abc,abc,abc | depart,roundabout-exit-4,arrive |
| a,l | abc,jkl,jkl | depart,roundabout-exit-3,arrive |
| a,i | abc,ghi,ghi | depart,roundabout-exit-2,arrive |
| a,f | abc,def,def | depart,roundabout-exit-1,arrive |
| d,f | def,def,def | depart,roundabout-exit-4,arrive |
| d,c | def,abc,abc | depart,roundabout-exit-3,arrive |
| d,l | def,jkl,jkl | depart,roundabout-exit-2,arrive |
| d,i | def,ghi,ghi | depart,roundabout-exit-1,arrive |
| g,i | ghi,ghi,ghi | depart,roundabout-exit-4,arrive |
| g,f | ghi,def,def | depart,roundabout-exit-3,arrive |
| g,c | ghi,abc,abc | depart,roundabout-exit-2,arrive |
| g,l | ghi,jkl,jkl | depart,roundabout-exit-1,arrive |
| j,l | jkl,jkl,jkl | depart,roundabout-exit-4,arrive |
| j,i | jkl,ghi,ghi | depart,roundabout-exit-3,arrive |
| j,f | jkl,def,def | depart,roundabout-exit-2,arrive |
| j,c | jkl,abc,abc | depart,roundabout-exit-1,arrive |
Scenario: Mixed Entry and Exit - segregated roads, different names
Given the node map
"""
@ -707,3 +744,27 @@ Feature: Basic Roundabout
When I route I should get
| waypoints | route | turns |
| a,h | ab,ef,ef,fh,fh | depart,roundabout-exit-4,notification slight right,notification straight,arrive |
Scenario: Drive through roundabout
Given the node map
"""
a
b e d f
c
g h
"""
And the ways
| nodes | junction | oneway |
| abcda | roundabout | yes |
| edf | | |
| gch | | yes |
When I route I should get
| waypoints | bearings | route | turns |
| e,f | 90 90 | edf,edf,edf | depart,roundabout-exit-1,arrive |
| e,h | 90 135 | edf,gch,gch | depart,roundabout-exit-2,arrive |
| g,f | 45 90 | gch,edf,edf | depart,roundabout-exit-2,arrive |
| g,h | 45 135 | gch,gch,gch | depart,roundabout-exit-1,arrive |
| e,e | 90 270 | edf,edf,edf | depart,roundabout-exit-3,arrive |

View File

@ -111,32 +111,57 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
if (in_edge_data.roundabout || in_edge_data.circular)
return;
bool past_roundabout_angle = false;
const bool lhs = profile_properties.left_hand_driving;
const int step = lhs ? -1 : 1;
for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size();
++cnt, idx += step)
std::cout << "invalidateExitAgainstDirection\n";
// Find range in which exits that must be invalidated (shaded areas):
// exit..end exit..end begin..exit for ↺ roundabouts
// ⭦ ⭦ ⭩ ⭦
// ⭡⭧ ⭡⭩ ▒ ▒⭨⭡
// ⭡⭦ ⭡⭨▒▒ ▒▒⭡⭨
// ⭧▒▒⭦ ⭧▒▒▒▒ ▒▒⭧
//
// begin..exit begin..exit exit..end for ↻ roundabouts
// ⭨▒▒▒ ⭨▒▒ ⭩ ▒▒⭨
// ⭣⭧▒ ⭣⭩ ▒▒⭣⭧
// ⭣⭦▒ ⭣⭨ ▒⭧⭣
// ⭩ ⭦ ⭩ ⭩
bool roundabout_entry_first = false;
auto invalidate_from = intersection.end(), invalidate_to = intersection.end();
for (auto road = intersection.begin(); road != intersection.end(); ++road)
{
auto &road = intersection[idx];
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
// only check actual outgoing edges
if (edge_data.reversed)
const auto &edge_data = node_based_graph.GetEdgeData(road->eid);
if (edge_data.roundabout || edge_data.circular)
{
// remember whether we have seen the roundabout in-part
if (edge_data.roundabout || edge_data.circular)
past_roundabout_angle = true;
continue;
if (edge_data.reversed)
{
if (roundabout_entry_first)
{ // invalidate turns in range exit..end
invalidate_from = road + 1;
invalidate_to = intersection.end();
}
else
{ // invalidate turns in range begin..exit
invalidate_from = intersection.begin() + 1;
invalidate_to = road;
}
}
else
{
roundabout_entry_first = true;
}
}
}
// Exiting roundabouts at an entry point is technically a data-modelling issue.
// This workaround handles cases in which an exit precedes and entry. The resulting
// u-turn against the roundabout direction is invalidated.
// The sorting of the angles represents a problem for left-sided driving, though.
// Exiting roundabouts at an entry point is technically a data-modelling issue.
// This workaround handles cases in which an exit precedes and entry. The resulting
// u-turn against the roundabout direction is invalidated.
for (; invalidate_from != invalidate_to; ++invalidate_from)
{
const auto &edge_data = node_based_graph.GetEdgeData(invalidate_from->eid);
if (!edge_data.roundabout && !edge_data.circular &&
node_based_graph.GetTarget(road.eid) != from_nid && past_roundabout_angle)
node_based_graph.GetTarget(invalidate_from->eid) != from_nid)
{
road.entry_allowed = false;
invalidate_from->entry_allowed = false;
}
}
}