check for empty name_id before getting data

This commit is contained in:
karenzshea 2017-11-30 13:10:46 +01:00 committed by Patrick Niklaus
parent 56459d37d1
commit 89080fb2b0
10 changed files with 158 additions and 135 deletions

View File

@ -173,7 +173,7 @@ class RouteAPI : public BaseAPI
guidance::trimShortSegments(steps, leg_geometry); guidance::trimShortSegments(steps, leg_geometry);
leg.steps = guidance::handleRoundabouts(std::move(steps)); leg.steps = guidance::handleRoundabouts(std::move(steps));
leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps), facade); leg.steps = guidance::collapseTurnInstructions(std::move(leg.steps));
leg.steps = guidance::anticipateLaneChange(std::move(leg.steps)); leg.steps = guidance::anticipateLaneChange(std::move(leg.steps));
leg.steps = guidance::buildIntersections(std::move(leg.steps)); leg.steps = guidance::buildIntersections(std::move(leg.steps));
leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps)); leg.steps = guidance::suppressShortNameSegments(std::move(leg.steps));

View File

@ -20,8 +20,7 @@ namespace guidance
// Collapsing such turns into a single turn instruction, we give a clearer // Collapsing such turns into a single turn instruction, we give a clearer
// set of instructionst that is not cluttered by unnecessary turns/name changes. // set of instructionst that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps, std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
const datafacade::BaseDataFacade &facade);
// A combined turn is a set of two instructions that actually form a single turn, as far as we // A combined turn is a set of two instructions that actually form a single turn, as far as we
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots // perceive it. A u-turn consisting of two left turns is one such example. But there are also lots

View File

@ -41,14 +41,14 @@ bool noIntermediaryIntersections(const RouteStep &step)
} }
// Link roads, as far as we are concerned, are short unnamed segments between to named segments. // Link roads, as far as we are concerned, are short unnamed segments between to named segments.
bool isLinkRoad(const RouteStep &link_step, bool isLinkRoad(const RouteStep &pre_link_step,
const std::string &pre_link_step_name, const RouteStep &link_step,
const std::string &post_link_step_name) const RouteStep &post_link_step)
{ {
const constexpr double MAX_LINK_ROAD_LENGTH = 2 * MAX_COLLAPSE_DISTANCE; const constexpr double MAX_LINK_ROAD_LENGTH = 2 * MAX_COLLAPSE_DISTANCE;
const auto is_short = link_step.distance <= MAX_LINK_ROAD_LENGTH; const auto is_short = link_step.distance <= MAX_LINK_ROAD_LENGTH;
const auto unnamed = link_step.name.empty(); const auto unnamed = link_step.name.empty();
const auto between_named = !pre_link_step_name.empty() && !post_link_step_name.empty(); const auto between_named = !pre_link_step.name.empty() && !post_link_step.name.empty();
return is_short && unnamed && between_named && noIntermediaryIntersections(link_step); return is_short && unnamed && between_named && noIntermediaryIntersections(link_step);
} }
@ -163,9 +163,6 @@ bool isStaggeredIntersection(const RouteStepIterator step_prior_to_intersection,
bool isUTurn(const RouteStepIterator step_prior_to_intersection, bool isUTurn(const RouteStepIterator step_prior_to_intersection,
const RouteStepIterator step_entering_intersection, const RouteStepIterator step_entering_intersection,
const RouteStepIterator step_leaving_intersection) const RouteStepIterator step_leaving_intersection)
// const std::string &step_prior_name,
// const std::string &step_entering_name,
// const std::string &step_leaving_name)
{ {
if (!basicCollapsePreconditions( if (!basicCollapsePreconditions(
step_prior_to_intersection, step_entering_intersection, step_leaving_intersection)) step_prior_to_intersection, step_entering_intersection, step_leaving_intersection))
@ -198,9 +195,9 @@ bool isUTurn(const RouteStepIterator step_prior_to_intersection,
const auto only_allowed_turn = (numberOfAllowedTurns(*step_leaving_intersection) == 1) && const auto only_allowed_turn = (numberOfAllowedTurns(*step_leaving_intersection) == 1) &&
noIntermediaryIntersections(*step_entering_intersection); noIntermediaryIntersections(*step_entering_intersection);
return collapsable || isLinkRoad(*step_entering_intersection, return collapsable || isLinkRoad(*step_prior_to_intersection,
step_prior_to_intersection->name, *step_entering_intersection,
step_leaving_intersection->name) || *step_leaving_intersection) ||
only_allowed_turn; only_allowed_turn;
} }

View File

@ -326,7 +326,7 @@ void suppressStep(RouteStep &step_at_turn_location, RouteStep &step_after_turn_l
// OTHER IMPLEMENTATIONS // OTHER IMPLEMENTATIONS
OSRM_ATTR_WARN_UNUSED OSRM_ATTR_WARN_UNUSED
RouteSteps collapseTurnInstructions(RouteSteps steps, const datafacade::BaseDataFacade &facade) RouteSteps collapseTurnInstructions(RouteSteps steps)
{ {
// make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn) // make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn)
BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back())); BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back()));
@ -464,7 +464,6 @@ RouteSteps collapseTurnInstructions(RouteSteps steps, const datafacade::BaseData
if (!hasWaypointType(*previous_step)) if (!hasWaypointType(*previous_step))
{ {
const auto far_back_step = findPreviousTurn(previous_step); const auto far_back_step = findPreviousTurn(previous_step);
const auto far_back_step_name = facade.GetNameForID(far_back_step->name_id).to_string();
// due to name changes, we can find u-turns a bit late. Thats why we check far back as // due to name changes, we can find u-turns a bit late. Thats why we check far back as
// well // well
if (isUTurn(far_back_step, previous_step, current_step)) if (isUTurn(far_back_step, previous_step, current_step))

View File

@ -77,13 +77,13 @@ TurnType::Enum IntersectionHandler::findBasicTurnType(const EdgeID via_edge,
const auto &out_name_id = const auto &out_name_id =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data) node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id; .name_id;
const auto &in_name = name_table.GetNameForID(in_name_id).to_string(); const auto &in_name_empty = name_table.GetNameForID(in_name_id).to_string().empty();
const auto &out_name = name_table.GetNameForID(out_name_id).to_string(); const auto &out_name_empty = name_table.GetNameForID(out_name_id).to_string().empty();
const auto same_name = !util::guidance::requiresNameAnnounced( const auto same_name = !util::guidance::requiresNameAnnounced(
in_name_id, out_name_id, name_table, street_name_suffix_table); in_name_id, out_name_id, name_table, street_name_suffix_table);
if (!in_name.empty() && !out_name.empty() && same_name) if (!in_name_empty && !out_name_empty && same_name)
{ {
return TurnType::Continue; return TurnType::Continue;
} }

View File

@ -23,6 +23,8 @@ namespace guidance
namespace namespace
{ {
// check a connected road for equality of a name // check a connected road for equality of a name
// returns 'true' if no equality because this is used as a filter elsewhere, i.e. filter if fn
// returns 'true'
inline auto makeCheckRoadForName(const NameID name_id, inline auto makeCheckRoadForName(const NameID name_id,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container, const EdgeBasedNodeDataContainer &node_data_container,
@ -36,8 +38,11 @@ inline auto makeCheckRoadForName(const NameID name_id,
node_data_container node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data) .GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id; .name_id;
const auto road_name = name_table.GetNameForID(road_name_id).to_string(); if (name_id == EMPTY_NAMEID || road_name_id == EMPTY_NAMEID)
if (name_id == EMPTY_NAMEID || road_name.empty()) return true;
const auto road_name_empty = name_table.GetNameForID(road_name_id).to_string().empty();
const auto in_name_empty = name_table.GetNameForID(name_id).to_string().empty();
if (in_name_empty || road_name_empty)
return true; return true;
const auto requires_announcement = const auto requires_announcement =
util::guidance::requiresNameAnnounced( util::guidance::requiresNameAnnounced(
@ -465,16 +470,20 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node,
node_data_container node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(range.front()).annotation_data) .GetAnnotation(node_based_graph.GetEdgeData(range.front()).annotation_data)
.name_id; .name_id;
if (required_name_id == EMPTY_NAMEID)
return false;
const auto has_required_name = [this, required_name_id](const auto edge_id) { const auto has_required_name = [this, required_name_id](const auto edge_id) {
const auto road_name_id = const auto road_name_id =
node_data_container node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data) .GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
.name_id; .name_id;
const auto &road_name = name_table.GetNameForID(road_name_id).to_string(); if (road_name_id == EMPTY_NAMEID)
const auto &required_name = name_table.GetNameForID(required_name_id).to_string(); return false;
if (required_name_id == EMPTY_NAMEID || road_name_id == EMPTY_NAMEID || const auto &road_name_empty = name_table.GetNameForID(road_name_id).to_string().empty();
(required_name.empty() && road_name.empty())) const auto &required_name_empty =
name_table.GetNameForID(required_name_id).to_string().empty();
if (required_name_empty && road_name_empty)
return false; return false;
return !util::guidance::requiresNameAnnounced( return !util::guidance::requiresNameAnnounced(
required_name_id, road_name_id, name_table, street_name_suffix_table) || required_name_id, road_name_id, name_table, street_name_suffix_table) ||

View File

@ -361,112 +361,121 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
node_based_graph.GetEdgeData(intersection[2].eid).annotation_data); node_based_graph.GetEdgeData(intersection[2].eid).annotation_data);
const auto &first_intersection_data = node_data_container.GetAnnotation( const auto &first_intersection_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(intersection[1].eid).annotation_data); node_based_graph.GetEdgeData(intersection[1].eid).annotation_data);
const auto first_second_same_name = if (first_intersection_data.name_id == EMPTY_NAMEID ||
!util::guidance::requiresNameAnnounced(second_intersection_data.name_id, second_intersection_data.name_id == EMPTY_NAMEID)
first_intersection_data.name_id,
name_table,
street_name_suffix_table);
// merging onto a passing highway / or two ramps merging onto the same highway
if (num_valid_turns == 1)
{ {
BOOST_ASSERT(!intersection[0].entry_allowed); return fallback(std::move(intersection));
// check order of highways
// 4
// 5 3
//
// 6 2
//
// 7 1
// 0
const auto &first_intersection_name =
name_table.GetNameForID(first_intersection_data.name_id).to_string();
const auto &second_intersection_name =
name_table.GetNameForID(second_intersection_data.name_id).to_string();
if (intersection[1].entry_allowed)
{
if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
!second_intersection_name.empty() && !first_intersection_name.empty() &&
first_second_same_name)
{
// circular order indicates a merge to the left (0-3 onto 4
if (angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) <
2 * NARROW_TURN_ANGLE)
intersection[1].instruction = {TurnType::Merge,
DirectionModifier::SlightLeft};
else // fallback
intersection[1].instruction = {TurnType::Merge,
getTurnDirection(intersection[1].angle)};
}
else // passing by the end of a motorway
{
intersection[1].instruction =
getInstructionForObvious(intersection.size(),
via_eid,
isThroughStreet(1, intersection),
intersection[1]);
}
}
else
{
BOOST_ASSERT(intersection[2].entry_allowed);
if (isMotorwayClass(intersection[2].eid, node_based_graph) &&
!second_intersection_name.empty() && !first_intersection_name.empty() &&
first_second_same_name)
{
// circular order (5-0) onto 4
if (angularDeviation(intersection[2].angle, STRAIGHT_ANGLE) <
2 * NARROW_TURN_ANGLE)
intersection[2].instruction = {TurnType::Merge,
DirectionModifier::SlightRight};
else // fallback
intersection[2].instruction = {TurnType::Merge,
getTurnDirection(intersection[2].angle)};
}
else // passing the end of a highway
{
intersection[2].instruction =
getInstructionForObvious(intersection.size(),
via_eid,
isThroughStreet(2, intersection),
intersection[2]);
}
}
} }
else else
{ {
BOOST_ASSERT(num_valid_turns == 2); const auto first_second_same_name =
// UTurn on ramps is not possible !util::guidance::requiresNameAnnounced(second_intersection_data.name_id,
BOOST_ASSERT(!intersection[0].entry_allowed); first_intersection_data.name_id,
BOOST_ASSERT(intersection[1].entry_allowed); name_table,
BOOST_ASSERT(intersection[2].entry_allowed); street_name_suffix_table);
// two motorways starting at end of ramp (fork)
// M M // merging onto a passing highway / or two ramps merging onto the same highway
// \ / if (num_valid_turns == 1)
// |
// R
if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
isMotorwayClass(intersection[2].eid, node_based_graph))
{ {
assignFork(via_eid, intersection[2], intersection[1]); BOOST_ASSERT(!intersection[0].entry_allowed);
} // check order of highways
else // 4
{ // 5 3
// continued ramp passing motorway entry //
// M R // 6 2
// M R //
// | / // 7 1
// R // 0
if (isMotorwayClass(intersection[1].eid, node_based_graph)) const auto &first_intersection_name =
name_table.GetNameForID(first_intersection_data.name_id).to_string();
const auto &second_intersection_name =
name_table.GetNameForID(second_intersection_data.name_id).to_string();
if (intersection[1].entry_allowed)
{ {
intersection[1].instruction = {TurnType::Turn, DirectionModifier::SlightRight}; if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
intersection[2].instruction = {TurnType::Continue, !second_intersection_name.empty() && !first_intersection_name.empty() &&
DirectionModifier::SlightLeft}; first_second_same_name)
{
// circular order indicates a merge to the left (0-3 onto 4
if (angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) <
2 * NARROW_TURN_ANGLE)
intersection[1].instruction = {TurnType::Merge,
DirectionModifier::SlightLeft};
else // fallback
intersection[1].instruction = {TurnType::Merge,
getTurnDirection(intersection[1].angle)};
}
else // passing by the end of a motorway
{
intersection[1].instruction =
getInstructionForObvious(intersection.size(),
via_eid,
isThroughStreet(1, intersection),
intersection[1]);
}
} }
else else
{
BOOST_ASSERT(intersection[2].entry_allowed);
if (isMotorwayClass(intersection[2].eid, node_based_graph) &&
!second_intersection_name.empty() && !first_intersection_name.empty() &&
first_second_same_name)
{
// circular order (5-0) onto 4
if (angularDeviation(intersection[2].angle, STRAIGHT_ANGLE) <
2 * NARROW_TURN_ANGLE)
intersection[2].instruction = {TurnType::Merge,
DirectionModifier::SlightRight};
else // fallback
intersection[2].instruction = {TurnType::Merge,
getTurnDirection(intersection[2].angle)};
}
else // passing the end of a highway
{
intersection[2].instruction =
getInstructionForObvious(intersection.size(),
via_eid,
isThroughStreet(2, intersection),
intersection[2]);
}
}
}
else
{
BOOST_ASSERT(num_valid_turns == 2);
// UTurn on ramps is not possible
BOOST_ASSERT(!intersection[0].entry_allowed);
BOOST_ASSERT(intersection[1].entry_allowed);
BOOST_ASSERT(intersection[2].entry_allowed);
// two motorways starting at end of ramp (fork)
// M M
// \ /
// |
// R
if (isMotorwayClass(intersection[1].eid, node_based_graph) &&
isMotorwayClass(intersection[2].eid, node_based_graph))
{ {
assignFork(via_eid, intersection[2], intersection[1]); assignFork(via_eid, intersection[2], intersection[1]);
} }
else
{
// continued ramp passing motorway entry
// M R
// M R
// | /
// R
if (isMotorwayClass(intersection[1].eid, node_based_graph))
{
intersection[1].instruction = {TurnType::Turn,
DirectionModifier::SlightRight};
intersection[2].instruction = {TurnType::Continue,
DirectionModifier::SlightLeft};
}
else
{
assignFork(via_eid, intersection[2], intersection[1]);
}
}
} }
} }
} }

View File

@ -295,19 +295,22 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
return SPECIAL_EDGEID; return SPECIAL_EDGEID;
} }
const auto &edge_name = name_table.GetNameForID(edge_data.name_id).to_string(); if (edge_data.name_id != EMPTY_NAMEID)
if (!edge_name.empty())
{ {
const auto &edge_name = name_table.GetNameForID(edge_data.name_id).to_string();
if (!edge_name.empty())
{
const auto announce = [&](unsigned id) { const auto announce = [&](unsigned id) {
return util::guidance::requiresNameAnnounced( return util::guidance::requiresNameAnnounced(
id, edge_data.name_id, name_table, street_name_suffix_table); id, edge_data.name_id, name_table, street_name_suffix_table);
}; };
if (std::all_of(begin(roundabout_name_ids), end(roundabout_name_ids), announce)) if (std::all_of(
roundabout_name_ids.insert(edge_data.name_id); begin(roundabout_name_ids), end(roundabout_name_ids), announce))
roundabout_name_ids.insert(edge_data.name_id);
}
} }
continue_edge = edge_id; continue_edge = edge_id;
} }
else if (!edge.flags.roundabout && !edge.flags.circular) else if (!edge.flags.roundabout && !edge.flags.circular)

View File

@ -474,8 +474,10 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// Name mismatch: check roads at `c` and `d` for same name // Name mismatch: check roads at `c` and `d` for same name
const auto name_mismatch = [&](const NameID road_name_id) { const auto name_mismatch = [&](const NameID road_name_id) {
const auto &road_name = name_table.GetNameForID(road_name_id).to_string(); const auto unnamed =
const auto unnamed = road_name.empty(); road_name_id == EMPTY_NAMEID
? true
: name_table.GetNameForID(road_name_id).to_string().empty();
return unnamed || return unnamed ||
util::guidance::requiresNameAnnounced(road_name_id, // util::guidance::requiresNameAnnounced(road_name_id, //
@ -502,13 +504,15 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
.name_id; .name_id;
const auto &sliproad_annotation = const auto &sliproad_annotation =
node_data_container.GetAnnotation(sliproad_edge_data.annotation_data); node_data_container.GetAnnotation(sliproad_edge_data.annotation_data);
const auto &sliproad_name = const auto &sliproad_name_empty =
name_table.GetNameForID(sliproad_annotation.name_id).to_string(); sliproad_annotation.name_id == EMPTY_NAMEID
? true
: name_table.GetNameForID(sliproad_annotation.name_id).to_string().empty();
const auto &main_road_name = name_table.GetNameForID(main_road_name_id).to_string(); const auto &main_road_name = name_table.GetNameForID(main_road_name_id).to_string();
const auto &candidate_road_name = const auto &candidate_road_name =
name_table.GetNameForID(candidate_data.name_id).to_string(); name_table.GetNameForID(candidate_data.name_id).to_string();
if (!sliproad_edge_data.flags.road_classification.IsLinkClass() && if (!sliproad_edge_data.flags.road_classification.IsLinkClass() &&
!sliproad_name.empty() && !main_road_name.empty() && !candidate_road_name.empty() && !sliproad_name_empty && !main_road_name.empty() && !candidate_road_name.empty() &&
util::guidance::requiresNameAnnounced(main_road_name_id, util::guidance::requiresNameAnnounced(main_road_name_id,
sliproad_annotation.name_id, sliproad_annotation.name_id,
name_table, name_table,

View File

@ -199,8 +199,11 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
const bool turn_is_perfectly_straight = const bool turn_is_perfectly_straight =
angularDeviation(road.angle, STRAIGHT_ANGLE) < std::numeric_limits<double>::epsilon(); angularDeviation(road.angle, STRAIGHT_ANGLE) < std::numeric_limits<double>::epsilon();
const auto &via_name = name_table.GetNameForID(via_data.name_id).to_string(); const auto &via_name_empty =
if (!via_name.empty()) via_data.name_id == EMPTY_NAMEID
? true
: name_table.GetNameForID(via_data.name_id).to_string().empty();
if (!via_name_empty)
{ {
const auto same_name = !util::guidance::requiresNameAnnounced( const auto same_name = !util::guidance::requiresNameAnnounced(
via_data.name_id, road_data.name_id, name_table, street_name_suffix_table); via_data.name_id, road_data.name_id, name_table, street_name_suffix_table);