improve sliproad / fork handling

This commit is contained in:
Moritz Kobitzsch
2016-07-04 12:19:49 +02:00
committed by Patrick Niklaus
parent 1309dd2a0f
commit 9e323d2d42
17 changed files with 558 additions and 426 deletions
+7 -131
View File
@@ -49,7 +49,12 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
name_table,
street_name_suffix_table),
motorway_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
turn_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
turn_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
sliproad_handler(intersection_generator,
node_based_graph,
node_info_list,
name_table,
street_name_suffix_table)
{
}
@@ -78,7 +83,7 @@ Intersection TurnAnalysis::assignTurnTypes(const NodeID from_nid,
}
}
// Handle sliproads
intersection = handleSliproads(via_eid, std::move(intersection));
intersection = sliproad_handler(from_nid, via_eid, std::move(intersection));
// Turn On Ramps Into Off Ramps, if we come from a motorway-like road
if (isMotorwayClass(node_based_graph.GetEdgeData(via_eid).road_classification.road_class))
@@ -127,135 +132,6 @@ TurnAnalysis::setTurnTypes(const NodeID from_nid, const EdgeID, Intersection int
return intersection;
}
// "Sliproads" occur when we've got a link between two roads (MOTORWAY_LINK, etc), but
// the two roads are *also* directly connected shortly afterwards.
// In these cases, we tag the turn-type as "sliproad", and then in post-processing
// we emit a "turn", instead of "take the ramp"+"merge"
Intersection TurnAnalysis::handleSliproads(const EdgeID source_edge_id,
Intersection intersection) const
{
auto intersection_node_id = node_based_graph.GetTarget(source_edge_id);
const auto linkTest = [this](const ConnectedRoad &road) {
return !node_based_graph.GetEdgeData(road.turn.eid).roundabout && road.entry_allowed &&
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) <= 2 * NARROW_TURN_ANGLE &&
!hasRoundaboutType(road.turn.instruction);
};
bool hasNarrow =
std::find_if(intersection.begin(), intersection.end(), linkTest) != intersection.end();
if (!hasNarrow)
return intersection;
const auto source_edge_data = node_based_graph.GetEdgeData(source_edge_id);
// Find the continuation of the intersection we're on
auto next_road = std::find_if(
intersection.begin(),
intersection.end(),
[this, source_edge_data](const ConnectedRoad &road) {
const auto road_edge_data = node_based_graph.GetEdgeData(road.turn.eid);
// Test to see if the source edge and the one we're looking at are the same road
return road_edge_data.road_classification.road_class ==
source_edge_data.road_classification.road_class &&
road_edge_data.name_id != EMPTY_NAMEID &&
road_edge_data.name_id == source_edge_data.name_id && road.entry_allowed &&
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE;
});
const bool hasNext = next_road != intersection.end();
if (!hasNext)
{
return intersection;
}
// Threshold check, if the intersection is too far away, don't bother continuing
const auto &next_road_data = node_based_graph.GetEdgeData(next_road->turn.eid);
if (next_road_data.distance > MAX_SLIPROAD_THRESHOLD)
{
return intersection;
}
auto next_intersection_node = node_based_graph.GetTarget(next_road->turn.eid);
const auto next_road_next_intersection = [&]() {
auto intersection = intersection_generator(intersection_node_id, next_road->turn.eid);
auto in_edge = next_road->turn.eid;
//skip over traffic lights
if(intersection.size() == 2)
{
const auto node = node_based_graph.GetTarget(in_edge);
in_edge = intersection[1].turn.eid;
next_intersection_node = node_based_graph.GetTarget(in_edge);
intersection = intersection_generator(node, in_edge);
}
return intersection;
}();
std::unordered_set<NameID> target_road_names;
for (const auto &road : next_road_next_intersection)
{
const auto &target_data = node_based_graph.GetEdgeData(road.turn.eid);
target_road_names.insert(target_data.name_id);
}
for (auto &road : intersection)
{
if (linkTest(road))
{
const auto target_intersection = [&](NodeID node, EdgeID eid) {
auto intersection = intersection_generator(node, eid);
//skip over traffic lights
if(intersection.size() == 2)
{
node = node_based_graph.GetTarget(eid);
eid = intersection[1].turn.eid;
intersection = intersection_generator(node, eid);
}
return intersection;
}(intersection_node_id, road.turn.eid);
for (const auto &candidate_road : target_intersection)
{
const auto &candidate_data = node_based_graph.GetEdgeData(candidate_road.turn.eid);
if (target_road_names.count(candidate_data.name_id) > 0 &&
node_based_graph.GetTarget(candidate_road.turn.eid) == next_intersection_node)
{
road.turn.instruction.type = TurnType::Sliproad;
break;
}
}
}
}
if (next_road->turn.instruction.type == TurnType::Fork)
{
const auto &next_data = node_based_graph.GetEdgeData(next_road->turn.eid);
if (next_data.name_id == source_edge_data.name_id)
{
if (angularDeviation(next_road->turn.angle, STRAIGHT_ANGLE) < 5)
next_road->turn.instruction.type = TurnType::Suppressed;
else
next_road->turn.instruction.type = TurnType::Continue;
next_road->turn.instruction.direction_modifier =
getTurnDirection(next_road->turn.angle);
}
else if (next_data.name_id != EMPTY_NAMEID)
{
next_road->turn.instruction.type = TurnType::NewName;
next_road->turn.instruction.direction_modifier =
getTurnDirection(next_road->turn.angle);
}
else
{
next_road->turn.instruction.type = TurnType::Suppressed;
}
}
return intersection;
}
const IntersectionGenerator &TurnAnalysis::getGenerator() const { return intersection_generator; }
} // namespace guidance