Handle case of dead-end edges by inserting an invalid turn
This commit is contained in:
parent
a48e5e4804
commit
e53e1cbe0f
@ -817,18 +817,22 @@ std::vector<TurnCandidate> TurnAnalysis::handleOneWayTurn(
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(turn_candidates[0].angle < 0.001);
|
BOOST_ASSERT(turn_candidates[0].angle < 0.001);
|
||||||
(void)from, (void)via_edge;
|
(void)from, (void)via_edge;
|
||||||
if (!turn_candidates[0].valid)
|
|
||||||
{
|
|
||||||
util::SimpleLogger().Write(logWARNING)
|
|
||||||
<< "Graph Broken. Dead end without exit found or missing reverse edge.";
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PRINT_DEBUG_CANDIDATES
|
#if PRINT_DEBUG_CANDIDATES
|
||||||
std::cout << "Basic (one) Turn Candidates:\n";
|
std::cout << "Basic (one) Turn Candidates:\n";
|
||||||
for (auto tc : turn_candidates)
|
for (auto tc : turn_candidates)
|
||||||
std::cout << "\t" << tc.toString() << " "
|
{
|
||||||
<< (int)node_based_graph.GetEdgeData(tc.eid).road_classification.road_class
|
std::cout << "\t" << tc.toString() << " ";
|
||||||
<< " name: " << node_based_graph.GetEdgeData(tc.eid).name_id << std::endl;
|
if (tc.eid != SPECIAL_EDGEID)
|
||||||
|
{
|
||||||
|
std::cout << (int)node_based_graph.GetEdgeData(tc.eid).road_classification.road_class <<
|
||||||
|
"name: " << node_based_graph.GetEdgeData(tc.eid).name_id << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " dead end" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return turn_candidates;
|
return turn_candidates;
|
||||||
}
|
}
|
||||||
@ -1659,87 +1663,84 @@ std::vector<TurnCandidate> TurnAnalysis::getTurnCandidates(const NodeID from_nod
|
|||||||
const NodeID only_restriction_to_node =
|
const NodeID only_restriction_to_node =
|
||||||
restriction_map.CheckForEmanatingIsOnlyTurn(from_node, turn_node);
|
restriction_map.CheckForEmanatingIsOnlyTurn(from_node, turn_node);
|
||||||
const bool is_barrier_node = barrier_nodes.find(turn_node) != barrier_nodes.end();
|
const bool is_barrier_node = barrier_nodes.find(turn_node) != barrier_nodes.end();
|
||||||
|
bool has_uturn_edge = false;
|
||||||
|
|
||||||
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
|
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
|
||||||
{
|
{
|
||||||
bool turn_is_valid = true;
|
// reverse edges are never valid turns because the resulting turn would look like this:
|
||||||
|
// from_node --via_edge--> turn_node <--onto_edge-- to_node
|
||||||
if (node_based_graph.GetEdgeData(onto_edge).reversed)
|
if (node_based_graph.GetEdgeData(onto_edge).reversed)
|
||||||
{
|
{
|
||||||
turn_is_valid = false;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeID to_node = node_based_graph.GetTarget(onto_edge);
|
const NodeID to_node = node_based_graph.GetTarget(onto_edge);
|
||||||
|
|
||||||
if (turn_is_valid && (only_restriction_to_node != SPECIAL_NODEID) &&
|
bool turn_is_valid =
|
||||||
(to_node != only_restriction_to_node))
|
// we are not turning over a barrier
|
||||||
{
|
(!is_barrier_node || from_node == to_node) &&
|
||||||
// We are at an only_-restriction but not at the right turn.
|
// We are at an only_-restriction but not at the right turn.
|
||||||
// ++restricted_turns_counter;
|
(only_restriction_to_node == SPECIAL_NODEID || to_node == only_restriction_to_node) &&
|
||||||
turn_is_valid = false;
|
// the turn is not restricted
|
||||||
}
|
!restriction_map.CheckIfTurnIsRestricted(from_node, turn_node, to_node);
|
||||||
|
|
||||||
if (turn_is_valid)
|
auto angle = 0.;
|
||||||
|
if (from_node == to_node)
|
||||||
{
|
{
|
||||||
if (is_barrier_node)
|
has_uturn_edge = true;
|
||||||
|
if (turn_is_valid && !is_barrier_node)
|
||||||
{
|
{
|
||||||
if (from_node != to_node)
|
// we only add u-turns for dead-end streets.
|
||||||
{
|
if (node_based_graph.GetOutDegree(turn_node) > 1)
|
||||||
// ++skipped_barrier_turns_counter;
|
|
||||||
turn_is_valid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (from_node == to_node && node_based_graph.GetOutDegree(turn_node) > 1)
|
|
||||||
{
|
{
|
||||||
auto number_of_emmiting_bidirectional_edges = 0;
|
auto number_of_emmiting_bidirectional_edges = 0;
|
||||||
for (auto edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
|
for (auto edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
|
||||||
{
|
{
|
||||||
auto target = node_based_graph.GetTarget(edge);
|
auto target = node_based_graph.GetTarget(edge);
|
||||||
auto reverse_edge = node_based_graph.FindEdge(target, turn_node);
|
auto reverse_edge = node_based_graph.FindEdge(target, turn_node);
|
||||||
|
BOOST_ASSERT(reverse_edge != SPECIAL_EDGEID);
|
||||||
if (!node_based_graph.GetEdgeData(reverse_edge).reversed)
|
if (!node_based_graph.GetEdgeData(reverse_edge).reversed)
|
||||||
{
|
{
|
||||||
++number_of_emmiting_bidirectional_edges;
|
++number_of_emmiting_bidirectional_edges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (number_of_emmiting_bidirectional_edges > 1)
|
// is a dead-end
|
||||||
|
turn_is_valid = number_of_emmiting_bidirectional_edges <= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(angle >= 0. && angle < std::numeric_limits<double>::epsilon());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// ++skipped_uturns_counter;
|
|
||||||
turn_is_valid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only add an edge if turn is not a U-turn except when it is
|
|
||||||
// at the end of a dead-end street
|
|
||||||
if (restriction_map.CheckIfTurnIsRestricted(from_node, turn_node, to_node) &&
|
|
||||||
(only_restriction_to_node == SPECIAL_NODEID) && (to_node != only_restriction_to_node))
|
|
||||||
{
|
|
||||||
// We are at an only_-restriction but not at the right turn.
|
|
||||||
// ++restricted_turns_counter;
|
|
||||||
turn_is_valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unpack first node of second segment if packed
|
// unpack first node of second segment if packed
|
||||||
|
|
||||||
const auto first_coordinate = getRepresentativeCoordinate(
|
const auto first_coordinate = getRepresentativeCoordinate(
|
||||||
from_node, turn_node, via_eid, INVERT, compressed_edge_container, node_info_list);
|
from_node, turn_node, via_eid, INVERT, compressed_edge_container, node_info_list);
|
||||||
const auto third_coordinate = getRepresentativeCoordinate(
|
const auto third_coordinate = getRepresentativeCoordinate(
|
||||||
turn_node, to_node, onto_edge, !INVERT, compressed_edge_container, node_info_list);
|
turn_node, to_node, onto_edge, !INVERT, compressed_edge_container, node_info_list);
|
||||||
|
angle = util::coordinate_calculation::computeAngle(
|
||||||
const auto angle = util::coordinate_calculation::computeAngle(
|
|
||||||
first_coordinate, node_info_list[turn_node], third_coordinate);
|
first_coordinate, node_info_list[turn_node], third_coordinate);
|
||||||
|
}
|
||||||
|
|
||||||
turn_candidates.push_back(
|
turn_candidates.push_back(
|
||||||
{onto_edge, turn_is_valid, angle, {TurnType::Invalid, DirectionModifier::UTurn}, 0});
|
{onto_edge, turn_is_valid, angle, {TurnType::Invalid, DirectionModifier::UTurn}, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We hit the case of a street leading into nothing-ness. Since the code here assumes that this will
|
||||||
|
// never happen we add an artificial invalid uturn in this case.
|
||||||
|
if (!has_uturn_edge)
|
||||||
|
{
|
||||||
|
turn_candidates.push_back(
|
||||||
|
{SPECIAL_EDGEID, false, 0., {TurnType::Invalid, DirectionModifier::UTurn}, 0});
|
||||||
|
}
|
||||||
|
|
||||||
const auto ByAngle = [](const TurnCandidate &first, const TurnCandidate second)
|
const auto ByAngle = [](const TurnCandidate &first, const TurnCandidate second)
|
||||||
{
|
{
|
||||||
return first.angle < second.angle;
|
return first.angle < second.angle;
|
||||||
};
|
};
|
||||||
std::sort(std::begin(turn_candidates), std::end(turn_candidates), ByAngle);
|
std::sort(std::begin(turn_candidates), std::end(turn_candidates), ByAngle);
|
||||||
|
|
||||||
|
BOOST_ASSERT(turn_candidates[0].angle >= 0. && turn_candidates[0].angle < std::numeric_limits<double>::epsilon());
|
||||||
|
|
||||||
return mergeSegregatedRoads(from_node, via_eid, std::move(turn_candidates));
|
return mergeSegregatedRoads(from_node, via_eid, std::move(turn_candidates));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user