Collapse Staggered Intersections.
Staggered intersection are very short zig-zags of only a few meters.
They are common in rural and exurban areas, especially in the US.
(In addition, these cases could as well be tagging issues)
We do not want to announce these short left-rights or right-lefts:
* -> b a -> *
| or | becomes a -> b
a -> * * -> b
Here is one example:
- https://www.openstreetmap.org/edit#map=20/39.26017/-84.25182
And here are two edge-cases that we don't handle at the moment:
- http://www.openstreetmap.org/edit#map=20/38.87900/-76.98519
- http://www.openstreetmap.org/edit#map=19/45.51056/-122.63462
and probably should not handle since the distance in between is
quite long (roughly 7-15 meters). For these we want to announce
two turns to not confuse the user.
Thanks to @1ec5 for raising this issue and @karenzshea for
providing additional US examples and cultural insights.
This commit is contained in:
committed by
Patrick Niklaus
parent
e8ce119972
commit
b1e309b4eb
@@ -17,6 +17,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
@@ -513,6 +514,33 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Staggered intersection are very short zig-zags of a few meters.
|
||||
// We do not want to announce these short left-rights or right-lefts:
|
||||
//
|
||||
// * -> b a -> *
|
||||
// | or | becomes a -> b
|
||||
// a -> * * -> b
|
||||
//
|
||||
bool isStaggeredIntersection(const RouteStep &previous, const RouteStep ¤t)
|
||||
{
|
||||
// Base decision on distance since the zig-zag is a visual clue.
|
||||
const constexpr auto MAX_STAGGERED_DISTANCE = 3; // debatable, but keep short to be on safe side
|
||||
|
||||
using namespace util::guidance;
|
||||
|
||||
const auto left_right = isLeftTurn(previous.maneuver.instruction) && //
|
||||
isRightTurn(current.maneuver.instruction);
|
||||
const auto right_left = isRightTurn(previous.maneuver.instruction) && //
|
||||
isLeftTurn(current.maneuver.instruction);
|
||||
|
||||
// A RouteStep holds distance/duration from the maneuver to the subsequent step.
|
||||
// We are only interested in the distance between the first and the second.
|
||||
const auto is_short = previous.distance < MAX_STAGGERED_DISTANCE;
|
||||
|
||||
return is_short && (left_right || right_left);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Post processing can invalidate some instructions. For example StayOnRoundabout
|
||||
@@ -753,12 +781,13 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
||||
// A name oszillation changes from name A shortly to name B and back to A.
|
||||
// In these cases, the name change will be suppressed.
|
||||
else if (one_back_index > 0 && compatible(current_step, one_back_step) &&
|
||||
isCollapsableInstruction(current_step.maneuver.instruction) &&
|
||||
isCollapsableInstruction(one_back_step.maneuver.instruction))
|
||||
((isCollapsableInstruction(current_step.maneuver.instruction) &&
|
||||
isCollapsableInstruction(one_back_step.maneuver.instruction)) ||
|
||||
isStaggeredIntersection(one_back_step, current_step)))
|
||||
{
|
||||
const auto two_back_index = getPreviousIndex(one_back_index);
|
||||
BOOST_ASSERT(two_back_index < steps.size());
|
||||
// valid, since one_back is collapsable:
|
||||
// valid, since one_back is collapsable or a turn and therefore not depart:
|
||||
const auto &coming_from_name = steps[two_back_index].name;
|
||||
if (current_step.name == coming_from_name)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user