simplify passing annotation data through OSRM pipeline using the node-based datastore
- separates node-based graph creation and compression from edge-based graph creation - moves usage of edge-based node data-container to pre-processing as well, unifying access to node-based data - single struct instead of separate vectors for annotation data in engine (single place of modification)
This commit is contained in:
committed by
Michael Krasnyk
parent
9b044aaa42
commit
2ddd98ee6d
@@ -122,7 +122,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
||||
// coordinate set to add a small level of fault tolerance
|
||||
const constexpr double skipping_inaccuracies_distance = 2;
|
||||
|
||||
const auto &turn_edge_data = node_based_graph.GetEdgeData(turn_edge);
|
||||
const auto &turn_edge_data = node_based_graph.GetEdgeData(turn_edge).flags;
|
||||
|
||||
// roundabouts, check early to avoid other costly checks
|
||||
if (turn_edge_data.roundabout || turn_edge_data.circular)
|
||||
@@ -175,7 +175,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
||||
// the lane count might not always be set. We need to assume a positive number, though. Here we
|
||||
// select the number of lanes to operate on
|
||||
const auto considered_lanes =
|
||||
GetOffsetCorrectionFactor(node_based_graph.GetEdgeData(turn_edge).road_classification) *
|
||||
GetOffsetCorrectionFactor(turn_edge_data.road_classification) *
|
||||
((intersection_lanes == 0) ? ASSUMED_LANE_COUNT : intersection_lanes);
|
||||
|
||||
/* if the very first coordinate along the road is reasonably far away from the road, we assume
|
||||
@@ -644,7 +644,7 @@ bool CoordinateExtractor::IsCurve(const std::vector<util::Coordinate> &coordinat
|
||||
const std::vector<double> &segment_distances,
|
||||
const double segment_length,
|
||||
const double considered_lane_width,
|
||||
const util::NodeBasedEdgeData &edge_data) const
|
||||
const extractor::NodeBasedEdgeClassification &edge_data) const
|
||||
{
|
||||
BOOST_ASSERT(coordinates.size() > 2);
|
||||
|
||||
|
||||
@@ -14,10 +14,12 @@ namespace guidance
|
||||
|
||||
DrivewayHandler::DrivewayHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
@@ -38,13 +40,13 @@ bool DrivewayHandler::canProcess(const NodeID /*nid*/,
|
||||
const auto from_eid = intersection.getUTurnRoad().eid;
|
||||
|
||||
if (intersection.size() <= 2 ||
|
||||
node_based_graph.GetEdgeData(from_eid).road_classification.IsLowPriorityRoadClass())
|
||||
node_based_graph.GetEdgeData(from_eid).flags.road_classification.IsLowPriorityRoadClass())
|
||||
return false;
|
||||
|
||||
auto low_priority_count =
|
||||
std::count_if(intersection.begin(), intersection.end(), [this](const auto &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid)
|
||||
.road_classification.IsLowPriorityRoadClass();
|
||||
.flags.road_classification.IsLowPriorityRoadClass();
|
||||
});
|
||||
|
||||
// Process intersection if it has two edges with normal priority and one is the entry edge,
|
||||
@@ -58,7 +60,7 @@ operator()(const NodeID nid, const EdgeID source_edge_id, Intersection intersect
|
||||
auto road =
|
||||
std::find_if(intersection.begin() + 1, intersection.end(), [this](const auto &road) {
|
||||
return !node_based_graph.GetEdgeData(road.eid)
|
||||
.road_classification.IsLowPriorityRoadClass();
|
||||
.flags.road_classification.IsLowPriorityRoadClass();
|
||||
});
|
||||
|
||||
(void)nid;
|
||||
|
||||
@@ -33,12 +33,13 @@ const constexpr bool USE_HIGH_PRECISION_MODE = !USE_LOW_PRECISION_MODE;
|
||||
|
||||
IntersectionGenerator::IntersectionGenerator(
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container)
|
||||
: node_based_graph(node_based_graph), restriction_map(restriction_map),
|
||||
barrier_nodes(barrier_nodes), coordinates(coordinates),
|
||||
: node_based_graph(node_based_graph), node_data_container(node_data_container),
|
||||
restriction_map(restriction_map), barrier_nodes(barrier_nodes), coordinates(coordinates),
|
||||
coordinate_extractor(node_based_graph, compressed_edge_container, coordinates)
|
||||
{
|
||||
}
|
||||
@@ -69,15 +70,15 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
|
||||
|
||||
// number of lanes at the intersection changes how far we look down the road
|
||||
const auto edge_range = node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection);
|
||||
const auto max_lanes_intersection = std::accumulate(
|
||||
edge_range.begin(),
|
||||
edge_range.end(),
|
||||
std::uint8_t{0},
|
||||
[this](const auto current_max, const auto current_eid) {
|
||||
return std::max(
|
||||
current_max,
|
||||
node_based_graph.GetEdgeData(current_eid).road_classification.GetNumberOfLanes());
|
||||
});
|
||||
const auto max_lanes_intersection =
|
||||
std::accumulate(edge_range.begin(),
|
||||
edge_range.end(),
|
||||
std::uint8_t{0},
|
||||
[this](const auto current_max, const auto current_eid) {
|
||||
return std::max(current_max,
|
||||
node_based_graph.GetEdgeData(current_eid)
|
||||
.flags.road_classification.GetNumberOfLanes());
|
||||
});
|
||||
|
||||
for (const EdgeID edge_connected_to_intersection :
|
||||
node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection))
|
||||
@@ -265,9 +266,11 @@ IntersectionGenerator::SkipDegreeTwoNodes(const NodeID starting_node, const Edge
|
||||
query_node = next_node;
|
||||
query_edge = next_edge;
|
||||
|
||||
if (!node_based_graph.GetEdgeData(query_edge)
|
||||
.IsCompatibleTo(node_based_graph.GetEdgeData(next_edge)) ||
|
||||
node_based_graph.GetTarget(next_edge) == starting_node)
|
||||
// check if there is a relevant change in the graph
|
||||
if (!CanBeCompressed(node_based_graph.GetEdgeData(query_edge),
|
||||
node_based_graph.GetEdgeData(next_edge),
|
||||
node_data_container) ||
|
||||
(node_based_graph.GetTarget(next_edge) == starting_node))
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,21 +24,38 @@ namespace guidance
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline bool requiresAnnouncement(const EdgeData &from, const EdgeData &to)
|
||||
// TODO check flags!
|
||||
inline bool requiresAnnouncement(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const EdgeID from,
|
||||
const EdgeID to)
|
||||
{
|
||||
return !from.CanCombineWith(to);
|
||||
}
|
||||
const auto &from_edge = node_based_graph.GetEdgeData(from);
|
||||
const auto &to_edge = node_based_graph.GetEdgeData(to);
|
||||
|
||||
if (from_edge.reversed != to_edge.reversed)
|
||||
return true;
|
||||
|
||||
if (!(from_edge.flags == to_edge.flags))
|
||||
return true;
|
||||
|
||||
const auto &annotation_from = node_data_container.GetAnnotation(from_edge.annotation_data);
|
||||
const auto &annotation_to = node_data_container.GetAnnotation(to_edge.annotation_data);
|
||||
return !annotation_from.CanCombineWith(annotation_to);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
: node_based_graph(node_based_graph), coordinates(coordinates), name_table(name_table),
|
||||
: node_based_graph(node_based_graph), node_data_container(node_data_container),
|
||||
coordinates(coordinates), name_table(name_table),
|
||||
street_name_suffix_table(street_name_suffix_table),
|
||||
intersection_generator(intersection_generator),
|
||||
graph_walker(node_based_graph, intersection_generator)
|
||||
graph_walker(node_based_graph, node_data_container, intersection_generator)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -48,20 +65,23 @@ TurnType::Enum IntersectionHandler::findBasicTurnType(const EdgeID via_edge,
|
||||
const ConnectedRoad &road) const
|
||||
{
|
||||
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
|
||||
bool on_ramp = in_data.road_classification.IsRampClass();
|
||||
|
||||
bool onto_ramp = out_data.road_classification.IsRampClass();
|
||||
bool on_ramp = node_based_graph.GetEdgeData(via_edge).flags.road_classification.IsRampClass();
|
||||
bool onto_ramp = node_based_graph.GetEdgeData(road.eid).flags.road_classification.IsRampClass();
|
||||
|
||||
if (!on_ramp && onto_ramp)
|
||||
return TurnType::OnRamp;
|
||||
|
||||
const auto same_name = !util::guidance::requiresNameAnnounced(
|
||||
in_data.name_id, out_data.name_id, name_table, street_name_suffix_table);
|
||||
const auto &in_name =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
|
||||
.name_id;
|
||||
const auto &out_name =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.name_id;
|
||||
|
||||
if (in_data.name_id != EMPTY_NAMEID && out_data.name_id != EMPTY_NAMEID && same_name)
|
||||
const auto same_name = !util::guidance::requiresNameAnnounced(
|
||||
in_name, out_name, name_table, street_name_suffix_table);
|
||||
|
||||
if (in_name != EMPTY_NAMEID && out_name != EMPTY_NAMEID && same_name)
|
||||
{
|
||||
return TurnType::Continue;
|
||||
}
|
||||
@@ -86,14 +106,22 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
}
|
||||
|
||||
// handle travel modes:
|
||||
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
|
||||
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
|
||||
const auto in_mode =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
|
||||
.travel_mode;
|
||||
const auto out_mode =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.travel_mode;
|
||||
const auto needs_notification = in_mode != out_mode;
|
||||
|
||||
if (type == TurnType::Turn)
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &in_classification = node_based_graph.GetEdgeData(via_edge).flags;
|
||||
const auto &in_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(via_edge).annotation_data);
|
||||
const auto &out_classification = node_based_graph.GetEdgeData(road.eid).flags;
|
||||
const auto &out_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(road.eid).annotation_data);
|
||||
|
||||
if (util::guidance::requiresNameAnnounced(
|
||||
in_data.name_id, out_data.name_id, name_table, street_name_suffix_table))
|
||||
@@ -104,12 +132,12 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
|
||||
// We reserve merges for motorway types. All others are considered for simply going
|
||||
// straight onto a road. This avoids confusion about merge directions on streets
|
||||
// that could potentially also offer different choices
|
||||
if (out_data.road_classification.IsMotorwayClass())
|
||||
if (out_classification.road_classification.IsMotorwayClass())
|
||||
return {TurnType::Merge,
|
||||
road.angle > STRAIGHT_ANGLE ? DirectionModifier::SlightRight
|
||||
: DirectionModifier::SlightLeft};
|
||||
else if (in_data.road_classification.IsRampClass() &&
|
||||
out_data.road_classification.IsRampClass())
|
||||
else if (in_classification.road_classification.IsRampClass() &&
|
||||
out_classification.road_classification.IsRampClass())
|
||||
{
|
||||
// This check is more a precaution than anything else. Our current travel modes
|
||||
// cannot reach this, since all ramps are exposing the same travel type. But we
|
||||
@@ -177,15 +205,20 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
ConnectedRoad &left,
|
||||
ConnectedRoad &right) const
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const bool low_priority_left =
|
||||
node_based_graph.GetEdgeData(left.eid).road_classification.IsLowPriorityRoadClass();
|
||||
const bool low_priority_right =
|
||||
node_based_graph.GetEdgeData(right.eid).road_classification.IsLowPriorityRoadClass();
|
||||
const auto same_mode_left =
|
||||
in_data.travel_mode == node_based_graph.GetEdgeData(left.eid).travel_mode;
|
||||
const auto same_mode_right =
|
||||
in_data.travel_mode == node_based_graph.GetEdgeData(right.eid).travel_mode;
|
||||
const auto &in_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data);
|
||||
const auto &lhs_classification =
|
||||
node_based_graph.GetEdgeData(left.eid).flags.road_classification;
|
||||
const auto &lhs_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(left.eid).annotation_data);
|
||||
const auto &rhs_classification =
|
||||
node_based_graph.GetEdgeData(right.eid).flags.road_classification;
|
||||
const auto &rhs_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(right.eid).annotation_data);
|
||||
const bool low_priority_left = lhs_classification.IsLowPriorityRoadClass();
|
||||
const bool low_priority_right = rhs_classification.IsLowPriorityRoadClass();
|
||||
const auto same_mode_left = in_data.travel_mode == lhs_data.travel_mode;
|
||||
const auto same_mode_right = in_data.travel_mode == rhs_data.travel_mode;
|
||||
const auto suppressed_left_type =
|
||||
same_mode_left ? TurnType::Suppressed : TurnType::Notification;
|
||||
const auto suppressed_right_type =
|
||||
@@ -194,8 +227,7 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
angularDeviation(right.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE))
|
||||
{
|
||||
// left side is actually straight
|
||||
const auto &out_data = node_based_graph.GetEdgeData(left.eid);
|
||||
if (detail::requiresAnnouncement(in_data, out_data))
|
||||
if (detail::requiresAnnouncement(node_based_graph, node_data_container, via_edge, left.eid))
|
||||
{
|
||||
if (low_priority_right && !low_priority_left)
|
||||
{
|
||||
@@ -230,11 +262,11 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
|
||||
{
|
||||
// right side is actually straight
|
||||
const auto &out_data = node_based_graph.GetEdgeData(right.eid);
|
||||
if (angularDeviation(right.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
|
||||
{
|
||||
if (detail::requiresAnnouncement(in_data, out_data))
|
||||
if (detail::requiresAnnouncement(
|
||||
node_based_graph, node_data_container, via_edge, right.eid))
|
||||
{
|
||||
if (low_priority_left && !low_priority_right)
|
||||
{
|
||||
@@ -304,8 +336,14 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
{
|
||||
// TODO handle low priority road classes in a reasonable way
|
||||
const auto suppressed_type = [&](const ConnectedRoad &road) {
|
||||
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode;
|
||||
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode;
|
||||
const auto in_mode =
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
|
||||
.travel_mode;
|
||||
const auto out_mode =
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.travel_mode;
|
||||
return in_mode == out_mode ? TurnType::Suppressed : TurnType::Notification;
|
||||
};
|
||||
|
||||
@@ -314,9 +352,8 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
|
||||
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
|
||||
if (angularDeviation(center.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(center.eid);
|
||||
if (detail::requiresAnnouncement(in_data, out_data))
|
||||
if (detail::requiresAnnouncement(
|
||||
node_based_graph, node_data_container, via_edge, center.eid))
|
||||
{
|
||||
center.instruction = {TurnType::Fork, DirectionModifier::Straight};
|
||||
}
|
||||
@@ -371,7 +408,8 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid,
|
||||
bool IntersectionHandler::isThroughStreet(const std::size_t index,
|
||||
const Intersection &intersection) const
|
||||
{
|
||||
const auto &data_at_index = node_based_graph.GetEdgeData(intersection[index].eid);
|
||||
const auto &data_at_index = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(intersection[index].eid).annotation_data);
|
||||
|
||||
if (data_at_index.name_id == EMPTY_NAMEID)
|
||||
return false;
|
||||
@@ -383,7 +421,8 @@ bool IntersectionHandler::isThroughStreet(const std::size_t index,
|
||||
continue;
|
||||
|
||||
const auto &road = intersection[road_index];
|
||||
const auto &road_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &road_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(road.eid).annotation_data);
|
||||
|
||||
// roads have a near straight angle (180 degree)
|
||||
const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) >
|
||||
@@ -395,7 +434,8 @@ bool IntersectionHandler::isThroughStreet(const std::size_t index,
|
||||
data_at_index.name_id, road_data.name_id, name_table, street_name_suffix_table);
|
||||
|
||||
const bool have_same_category =
|
||||
data_at_index.road_classification == road_data.road_classification;
|
||||
node_based_graph.GetEdgeData(intersection[index].eid).flags.road_classification ==
|
||||
node_based_graph.GetEdgeData(road.eid).flags.road_classification;
|
||||
|
||||
if (is_nearly_straight && have_same_name && have_same_category)
|
||||
return true;
|
||||
@@ -443,8 +483,10 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
|
||||
|
||||
bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const
|
||||
{
|
||||
const auto &source_edge_data = node_based_graph.GetEdgeData(source_edge_id);
|
||||
const auto &target_edge_data = node_based_graph.GetEdgeData(target_edge_id);
|
||||
const auto &source_edge_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(source_edge_id).annotation_data);
|
||||
const auto &target_edge_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(target_edge_id).annotation_data);
|
||||
|
||||
return source_edge_data.name_id != EMPTY_NAMEID && //
|
||||
target_edge_data.name_id != EMPTY_NAMEID && //
|
||||
|
||||
@@ -14,13 +14,16 @@ namespace extractor
|
||||
namespace guidance
|
||||
{
|
||||
|
||||
IntersectionNormalizer::IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
IntersectionNormalizer::IntersectionNormalizer(
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
: node_based_graph(node_based_graph), intersection_generator(intersection_generator),
|
||||
mergable_road_detector(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
intersection_generator,
|
||||
intersection_generator.GetCoordinateExtractor(),
|
||||
|
||||
@@ -25,13 +25,17 @@ namespace
|
||||
// check a connected road for equality of a name
|
||||
inline auto makeCheckRoadForName(const NameID name_id,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &suffix_table)
|
||||
{
|
||||
return [name_id, &node_based_graph, &name_table, &suffix_table](
|
||||
return [name_id, &node_based_graph, &node_data_container, &name_table, &suffix_table](
|
||||
const MergableRoadDetector::MergableRoadData &road) {
|
||||
// since we filter here, we don't want any other name than the one we are looking for
|
||||
const auto road_name = node_based_graph.GetEdgeData(road.eid).name_id;
|
||||
const auto road_name =
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.name_id;
|
||||
if (name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID)
|
||||
return true;
|
||||
const auto requires_announcement =
|
||||
@@ -44,14 +48,16 @@ inline auto makeCheckRoadForName(const NameID name_id,
|
||||
}
|
||||
|
||||
MergableRoadDetector::MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const IntersectionGenerator &intersection_generator,
|
||||
const CoordinateExtractor &coordinate_extractor,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
: node_based_graph(node_based_graph), node_coordinates(node_coordinates),
|
||||
intersection_generator(intersection_generator), coordinate_extractor(coordinate_extractor),
|
||||
name_table(name_table), street_name_suffix_table(street_name_suffix_table)
|
||||
: node_based_graph(node_based_graph), node_data_container(node_data_container),
|
||||
node_coordinates(node_coordinates), intersection_generator(intersection_generator),
|
||||
coordinate_extractor(coordinate_extractor), name_table(name_table),
|
||||
street_name_suffix_table(street_name_suffix_table)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -63,11 +69,14 @@ bool MergableRoadDetector::CanMergeRoad(const NodeID intersection_node,
|
||||
if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE)
|
||||
return false;
|
||||
|
||||
const auto &lhs_edge_data = node_based_graph.GetEdgeData(lhs.eid);
|
||||
const auto &rhs_edge_data = node_based_graph.GetEdgeData(rhs.eid);
|
||||
const auto &lhs_edge = node_based_graph.GetEdgeData(lhs.eid);
|
||||
const auto &rhs_edge = node_based_graph.GetEdgeData(rhs.eid);
|
||||
const auto &lhs_edge_data = node_data_container.GetAnnotation(lhs_edge.annotation_data);
|
||||
const auto &rhs_edge_data = node_data_container.GetAnnotation(rhs_edge.annotation_data);
|
||||
|
||||
// and they need to describe the same road
|
||||
if (!EdgeDataSupportsMerge(lhs_edge_data, rhs_edge_data))
|
||||
if ((lhs_edge.reversed == rhs_edge.reversed) ||
|
||||
!EdgeDataSupportsMerge(lhs_edge.flags, rhs_edge.flags, lhs_edge_data, rhs_edge_data))
|
||||
return false;
|
||||
|
||||
/* don't use any circular links, since they mess up detection we jump out early.
|
||||
@@ -120,36 +129,36 @@ bool MergableRoadDetector::IsDistinctFrom(const MergableRoadData &lhs,
|
||||
if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE)
|
||||
return true;
|
||||
else // or it cannot have the same name
|
||||
return !HaveIdenticalNames(node_based_graph.GetEdgeData(lhs.eid).name_id,
|
||||
node_based_graph.GetEdgeData(rhs.eid).name_id);
|
||||
return !HaveIdenticalNames(
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(lhs.eid).annotation_data)
|
||||
.name_id,
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(rhs.eid).annotation_data)
|
||||
.name_id);
|
||||
}
|
||||
|
||||
bool MergableRoadDetector::EdgeDataSupportsMerge(const util::NodeBasedEdgeData &lhs_edge_data,
|
||||
const util::NodeBasedEdgeData &rhs_edge_data) const
|
||||
bool MergableRoadDetector::EdgeDataSupportsMerge(
|
||||
const NodeBasedEdgeClassification &lhs_flags,
|
||||
const NodeBasedEdgeClassification &rhs_flags,
|
||||
const NodeBasedEdgeAnnotation &lhs_annotation,
|
||||
const NodeBasedEdgeAnnotation &rhs_annotation) const
|
||||
{
|
||||
// roundabouts are special, simply don't hurt them. We might not want to bear the
|
||||
// consequences
|
||||
if (lhs_edge_data.roundabout || rhs_edge_data.roundabout)
|
||||
return false;
|
||||
|
||||
/* to describe the same road, but in opposite directions (which is what we require for a
|
||||
* merge), the roads have to feature one reversed and one non-reversed edge
|
||||
*/
|
||||
if (lhs_edge_data.reversed == rhs_edge_data.reversed)
|
||||
if (lhs_flags.roundabout || rhs_flags.roundabout)
|
||||
return false;
|
||||
|
||||
/* The travel mode should be the same for both roads. If we were to merge different travel
|
||||
* modes, we would hide information/run the risk of loosing valid choices (e.g. short period
|
||||
* of pushing)
|
||||
*/
|
||||
if (lhs_edge_data.travel_mode != rhs_edge_data.travel_mode)
|
||||
if (lhs_annotation.travel_mode != rhs_annotation.travel_mode)
|
||||
return false;
|
||||
|
||||
// we require valid names
|
||||
if (!HaveIdenticalNames(lhs_edge_data.name_id, rhs_edge_data.name_id))
|
||||
if (!HaveIdenticalNames(lhs_annotation.name_id, rhs_annotation.name_id))
|
||||
return false;
|
||||
|
||||
return lhs_edge_data.road_classification == rhs_edge_data.road_classification;
|
||||
return lhs_flags.road_classification == rhs_flags.road_classification;
|
||||
}
|
||||
|
||||
bool MergableRoadDetector::IsTrafficLoop(const NodeID intersection_node,
|
||||
@@ -172,9 +181,13 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
|
||||
* Since both items have the same id, we can `select` based on any setup
|
||||
*/
|
||||
SelectStraightmostRoadByNameAndOnlyChoice selector(
|
||||
node_based_graph.GetEdgeData(lhs.eid).name_id, lhs.bearing, /*requires entry=*/false);
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(lhs.eid).annotation_data)
|
||||
.name_id,
|
||||
lhs.bearing,
|
||||
/*requires entry=*/false);
|
||||
|
||||
NodeBasedGraphWalker graph_walker(node_based_graph, intersection_generator);
|
||||
NodeBasedGraphWalker graph_walker(
|
||||
node_based_graph, node_data_container, intersection_generator);
|
||||
graph_walker.TraverseRoad(intersection_node, lhs.eid, left_accumulator, selector);
|
||||
/* if the intersection does not have a right turn, we continue onto the next one once
|
||||
* (skipping over a single small side street)
|
||||
@@ -231,7 +244,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
|
||||
|
||||
const auto num_lanes = [this](const MergableRoadData &road) {
|
||||
return std::max<std::uint8_t>(
|
||||
node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes(), 1);
|
||||
node_based_graph.GetEdgeData(road.eid).flags.road_classification.GetNumberOfLanes(), 1);
|
||||
};
|
||||
|
||||
// the width we can bridge at the intersection
|
||||
@@ -265,11 +278,15 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
|
||||
return false;
|
||||
|
||||
// Find a coordinate following a road that is far away
|
||||
NodeBasedGraphWalker graph_walker(node_based_graph, intersection_generator);
|
||||
NodeBasedGraphWalker graph_walker(
|
||||
node_based_graph, node_data_container, intersection_generator);
|
||||
const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length) {
|
||||
LengthLimitedCoordinateAccumulator accumulator(coordinate_extractor, max_length);
|
||||
SelectStraightmostRoadByNameAndOnlyChoice selector(
|
||||
node_based_graph.GetEdgeData(edge_id).name_id, lhs.bearing, /*requires_entry=*/false);
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
|
||||
.name_id,
|
||||
lhs.bearing,
|
||||
/*requires_entry=*/false);
|
||||
graph_walker.TraverseRoad(intersection_node, edge_id, accumulator, selector);
|
||||
|
||||
return std::make_pair(accumulator.accumulated_length, accumulator.coordinates);
|
||||
@@ -342,9 +359,9 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
|
||||
coordinates_to_the_right.end());
|
||||
|
||||
const auto lane_count_lhs = std::max<int>(
|
||||
1, node_based_graph.GetEdgeData(lhs.eid).road_classification.GetNumberOfLanes());
|
||||
1, node_based_graph.GetEdgeData(lhs.eid).flags.road_classification.GetNumberOfLanes());
|
||||
const auto lane_count_rhs = std::max<int>(
|
||||
1, node_based_graph.GetEdgeData(rhs.eid).road_classification.GetNumberOfLanes());
|
||||
1, node_based_graph.GetEdgeData(rhs.eid).flags.road_classification.GetNumberOfLanes());
|
||||
|
||||
const auto combined_road_width = 0.5 * (lane_count_lhs + lane_count_rhs) * ASSUMED_LANE_WIDTH;
|
||||
const auto constexpr MAXIMAL_ALLOWED_SEPARATION_WIDTH = 8;
|
||||
@@ -380,10 +397,16 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node,
|
||||
|
||||
// check if all items share a name
|
||||
const auto range = node_based_graph.GetAdjacentEdgeRange(nid);
|
||||
const auto required_name_id = node_based_graph.GetEdgeData(range.front()).name_id;
|
||||
const auto required_name_id =
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(range.front()).annotation_data)
|
||||
.name_id;
|
||||
|
||||
const auto has_required_name = [this, required_name_id](const auto edge_id) {
|
||||
const auto road_name = node_based_graph.GetEdgeData(edge_id).name_id;
|
||||
const auto road_name =
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
|
||||
.name_id;
|
||||
if (required_name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID)
|
||||
return false;
|
||||
return !util::guidance::requiresNameAnnounced(
|
||||
@@ -428,14 +451,19 @@ bool MergableRoadDetector::IsLinkRoad(const NodeID intersection_node,
|
||||
const auto next_intersection_along_road = intersection_generator.GetConnectedRoads(
|
||||
next_intersection_parameters.nid, next_intersection_parameters.via_eid);
|
||||
const auto extract_name_id = [this](const MergableRoadData &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid).name_id;
|
||||
return node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.name_id;
|
||||
};
|
||||
|
||||
const auto requested_name_id = extract_name_id(road);
|
||||
const auto next_road_along_path = next_intersection_along_road.findClosestTurn(
|
||||
STRAIGHT_ANGLE,
|
||||
makeCheckRoadForName(
|
||||
requested_name_id, node_based_graph, name_table, street_name_suffix_table));
|
||||
makeCheckRoadForName(requested_name_id,
|
||||
node_based_graph,
|
||||
node_data_container,
|
||||
name_table,
|
||||
street_name_suffix_table));
|
||||
|
||||
// we need to have a continuing road to successfully detect a link road
|
||||
if (next_road_along_path == next_intersection_along_road.end())
|
||||
@@ -460,9 +488,16 @@ bool MergableRoadDetector::IsLinkRoad(const NodeID intersection_node,
|
||||
// near straight road that continues
|
||||
return angularDeviation(opposite_of_next_road_along_path->angle, next_road_along_path->angle) >=
|
||||
(STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE) &&
|
||||
(node_based_graph.GetEdgeData(next_road_along_path->eid).reversed ==
|
||||
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid).reversed) &&
|
||||
EdgeDataSupportsMerge(
|
||||
node_based_graph.GetEdgeData(next_road_along_path->eid),
|
||||
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid));
|
||||
node_based_graph.GetEdgeData(next_road_along_path->eid).flags,
|
||||
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid).flags,
|
||||
node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(next_road_along_path->eid).annotation_data),
|
||||
node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid)
|
||||
.annotation_data));
|
||||
}
|
||||
|
||||
} // namespace guidance
|
||||
|
||||
@@ -24,27 +24,29 @@ namespace
|
||||
|
||||
inline bool isMotorwayClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
{
|
||||
return node_based_graph.GetEdgeData(eid).road_classification.IsMotorwayClass();
|
||||
return node_based_graph.GetEdgeData(eid).flags.road_classification.IsMotorwayClass();
|
||||
}
|
||||
inline RoadClassification roadClass(const ConnectedRoad &road,
|
||||
const util::NodeBasedDynamicGraph &graph)
|
||||
{
|
||||
return graph.GetEdgeData(road.eid).road_classification;
|
||||
return graph.GetEdgeData(road.eid).flags.road_classification;
|
||||
}
|
||||
|
||||
inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph)
|
||||
{
|
||||
return node_based_graph.GetEdgeData(eid).road_classification.IsRampClass();
|
||||
return node_based_graph.GetEdgeData(eid).flags.road_classification.IsRampClass();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
@@ -101,7 +103,8 @@ operator()(const NodeID, const EdgeID via_eid, Intersection intersection) const
|
||||
|
||||
Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection intersection) const
|
||||
{
|
||||
const auto &in_data = node_based_graph.GetEdgeData(via_eid);
|
||||
const auto &in_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_eid).annotation_data);
|
||||
BOOST_ASSERT(isMotorwayClass(via_eid, node_based_graph));
|
||||
|
||||
const auto countExitingMotorways = [this](const Intersection &intersection) {
|
||||
@@ -121,7 +124,8 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
||||
if (!road.entry_allowed)
|
||||
continue;
|
||||
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &out_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(road.eid).annotation_data);
|
||||
|
||||
const auto same_name = !util::guidance::requiresNameAnnounced(
|
||||
in_data.name_id, out_data.name_id, name_table, street_name_suffix_table);
|
||||
@@ -353,8 +357,10 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
|
||||
}
|
||||
else if (intersection.size() == 3)
|
||||
{
|
||||
const auto &second_intersection_data = node_based_graph.GetEdgeData(intersection[2].eid);
|
||||
const auto &first_intersection_data = node_based_graph.GetEdgeData(intersection[1].eid);
|
||||
const auto &second_intersection_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(intersection[2].eid).annotation_data);
|
||||
const auto &first_intersection_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(intersection[1].eid).annotation_data);
|
||||
const auto first_second_same_name =
|
||||
!util::guidance::requiresNameAnnounced(second_intersection_data.name_id,
|
||||
first_intersection_data.name_id,
|
||||
|
||||
@@ -15,8 +15,10 @@ namespace guidance
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
NodeBasedGraphWalker::NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
: node_based_graph(node_based_graph), intersection_generator(intersection_generator)
|
||||
: node_based_graph(node_based_graph), node_data_container(node_data_container),
|
||||
intersection_generator(intersection_generator)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -64,21 +66,24 @@ boost::optional<EdgeID> SelectRoadByNameOnlyChoiceAndStraightness::
|
||||
operator()(const NodeID /*nid*/,
|
||||
const EdgeID /*via_edge_id*/,
|
||||
const IntersectionView &intersection,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph) const
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container) const
|
||||
{
|
||||
BOOST_ASSERT(!intersection.empty());
|
||||
const auto comparator = [this, &node_based_graph](const IntersectionViewData &lhs,
|
||||
const IntersectionViewData &rhs) {
|
||||
const auto comparator = [&](const IntersectionViewData &lhs, const IntersectionViewData &rhs) {
|
||||
// the score of an elemnt results in an ranking preferring valid entries, if required over
|
||||
// invalid requested name_ids over non-requested narrow deviations over non-narrow
|
||||
const auto score = [this, &node_based_graph](const IntersectionViewData &road) {
|
||||
const auto score = [&](const IntersectionViewData &road) {
|
||||
double result_score = 0;
|
||||
// since angular deviation is limited by 0-180, we add 360 for invalid
|
||||
if (requires_entry && !road.entry_allowed)
|
||||
result_score += 360.;
|
||||
|
||||
// 180 for undesired name-ids
|
||||
if (desired_name_id != node_based_graph.GetEdgeData(road.eid).name_id)
|
||||
if (desired_name_id !=
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.name_id)
|
||||
result_score += 180;
|
||||
|
||||
return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||
@@ -108,24 +113,27 @@ boost::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::
|
||||
operator()(const NodeID /*nid*/,
|
||||
const EdgeID /*via_edge_id*/,
|
||||
const IntersectionView &intersection,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph) const
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container) const
|
||||
{
|
||||
BOOST_ASSERT(!intersection.empty());
|
||||
if (intersection.size() == 1)
|
||||
return {};
|
||||
|
||||
const auto comparator = [this, &node_based_graph](const IntersectionViewData &lhs,
|
||||
const IntersectionViewData &rhs) {
|
||||
const auto comparator = [&](const IntersectionViewData &lhs, const IntersectionViewData &rhs) {
|
||||
// the score of an elemnt results in an ranking preferring valid entries, if required over
|
||||
// invalid requested name_ids over non-requested narrow deviations over non-narrow
|
||||
const auto score = [this, &node_based_graph](const IntersectionViewData &road) {
|
||||
const auto score = [&](const IntersectionViewData &road) {
|
||||
double result_score = 0;
|
||||
// since angular deviation is limited by 0-180, we add 360 for invalid
|
||||
if (requires_entry && !road.entry_allowed)
|
||||
result_score += 360.;
|
||||
|
||||
// 180 for undesired name-ids
|
||||
if (desired_name_id != node_based_graph.GetEdgeData(road.eid).name_id)
|
||||
if (desired_name_id !=
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.name_id)
|
||||
result_score += 180;
|
||||
|
||||
return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||
@@ -135,11 +143,11 @@ operator()(const NodeID /*nid*/,
|
||||
};
|
||||
|
||||
const auto count_desired_name =
|
||||
std::count_if(std::begin(intersection),
|
||||
std::end(intersection),
|
||||
[this, &node_based_graph](const auto &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid).name_id == desired_name_id;
|
||||
});
|
||||
std::count_if(std::begin(intersection), std::end(intersection), [&](const auto &road) {
|
||||
return node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.name_id == desired_name_id;
|
||||
});
|
||||
if (count_desired_name > 2)
|
||||
return {};
|
||||
|
||||
@@ -149,7 +157,9 @@ operator()(const NodeID /*nid*/,
|
||||
const auto is_valid_choice = !requires_entry || min_element->entry_allowed;
|
||||
const auto is_only_choice_with_same_name =
|
||||
count_desired_name <= 2 && // <= in case we come from a bridge
|
||||
node_based_graph.GetEdgeData(min_element->eid).name_id == desired_name_id &&
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(min_element->eid).annotation_data)
|
||||
.name_id == desired_name_id &&
|
||||
angularDeviation(min_element->angle, STRAIGHT_ANGLE) < 100; // don't do crazy turns
|
||||
const auto has_valid_angle =
|
||||
((intersection.size() == 2 ||
|
||||
|
||||
@@ -24,18 +24,19 @@ namespace guidance
|
||||
{
|
||||
|
||||
RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const ProfileProperties &profile_properties,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
intersection_generator),
|
||||
compressed_edge_container(compressed_edge_container), profile_properties(profile_properties),
|
||||
compressed_edge_container(compressed_edge_container),
|
||||
coordinate_extractor(node_based_graph, compressed_edge_container, coordinates)
|
||||
{
|
||||
}
|
||||
@@ -70,22 +71,24 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags(
|
||||
const NodeID from_nid, const EdgeID via_eid, const Intersection &intersection) const
|
||||
{
|
||||
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid);
|
||||
bool on_roundabout = in_edge_data.roundabout || in_edge_data.circular;
|
||||
const auto &in_edge_class = in_edge_data.flags;
|
||||
bool on_roundabout = in_edge_class.roundabout || in_edge_class.circular;
|
||||
bool can_enter_roundabout = false;
|
||||
bool can_exit_roundabout_separately = false;
|
||||
|
||||
const bool lhs = in_edge_data.is_left_hand_driving;
|
||||
const bool lhs =
|
||||
node_data_container.GetAnnotation(in_edge_data.annotation_data).is_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)
|
||||
{
|
||||
const auto &road = intersection[idx];
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &edge = node_based_graph.GetEdgeData(road.eid);
|
||||
// only check actual outgoing edges
|
||||
if (edge_data.reversed || !road.entry_allowed)
|
||||
if (edge.reversed || !road.entry_allowed)
|
||||
continue;
|
||||
|
||||
if (edge_data.roundabout || edge_data.circular)
|
||||
if (edge.flags.roundabout || edge.flags.circular)
|
||||
{
|
||||
can_enter_roundabout = true;
|
||||
}
|
||||
@@ -108,8 +111,8 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
const EdgeID via_eid,
|
||||
Intersection &intersection) const
|
||||
{
|
||||
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid);
|
||||
if (in_edge_data.roundabout || in_edge_data.circular)
|
||||
const auto &in_edge_class = node_based_graph.GetEdgeData(via_eid).flags;
|
||||
if (in_edge_class.roundabout || in_edge_class.circular)
|
||||
return;
|
||||
|
||||
// Find range in which exits that must be invalidated (shaded areas):
|
||||
@@ -136,10 +139,10 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
auto invalidate_from = intersection.end(), invalidate_to = intersection.end();
|
||||
for (auto road = intersection.begin(); road != intersection.end(); ++road)
|
||||
{
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(road->eid);
|
||||
if (edge_data.roundabout || edge_data.circular)
|
||||
const auto &edge = node_based_graph.GetEdgeData(road->eid);
|
||||
if (edge.flags.roundabout || edge.flags.circular)
|
||||
{
|
||||
if (edge_data.reversed)
|
||||
if (edge.reversed)
|
||||
{
|
||||
if (roundabout_entry_first)
|
||||
{ // invalidate turns in range exit..end
|
||||
@@ -166,8 +169,8 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
|
||||
// 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 &&
|
||||
const auto &edge = node_based_graph.GetEdgeData(invalidate_from->eid);
|
||||
if (!edge.flags.roundabout && !edge.flags.circular &&
|
||||
node_based_graph.GetTarget(invalidate_from->eid) != from_nid)
|
||||
{
|
||||
invalidate_from->entry_allowed = false;
|
||||
@@ -207,8 +210,8 @@ bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
|
||||
// can only contain a single further road
|
||||
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const auto edge_data = node_based_graph.GetEdgeData(edge);
|
||||
if (edge_data.roundabout || edge_data.circular)
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(edge);
|
||||
if (edge_data.flags.roundabout || edge_data.flags.circular)
|
||||
continue;
|
||||
|
||||
// there is a single non-roundabout edge
|
||||
@@ -222,7 +225,7 @@ bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
|
||||
[this](const auto current_max, const auto current_eid) {
|
||||
return std::max(current_max,
|
||||
node_based_graph.GetEdgeData(current_eid)
|
||||
.road_classification.GetNumberOfLanes());
|
||||
.flags.road_classification.GetNumberOfLanes());
|
||||
});
|
||||
|
||||
const auto next_coordinate =
|
||||
@@ -279,11 +282,12 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
||||
const NodeID node, const bool roundabout, const bool circular) {
|
||||
BOOST_ASSERT(roundabout != circular);
|
||||
EdgeID continue_edge = SPECIAL_EDGEID;
|
||||
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node))
|
||||
for (const auto edge_id : node_based_graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(edge);
|
||||
if (!edge_data.reversed && (edge_data.circular == circular) &&
|
||||
(edge_data.roundabout == roundabout))
|
||||
const auto &edge = node_based_graph.GetEdgeData(edge_id);
|
||||
const auto &edge_data = node_data_container.GetAnnotation(edge.annotation_data);
|
||||
if (!edge.reversed && (edge.flags.circular == circular) &&
|
||||
(edge.flags.roundabout == roundabout))
|
||||
{
|
||||
if (SPECIAL_EDGEID != continue_edge)
|
||||
{
|
||||
@@ -303,9 +307,9 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
||||
roundabout_name_ids.insert(edge_data.name_id);
|
||||
}
|
||||
|
||||
continue_edge = edge;
|
||||
continue_edge = edge_id;
|
||||
}
|
||||
else if (!edge_data.roundabout && !edge_data.circular)
|
||||
else if (!edge.flags.roundabout && !edge.flags.circular)
|
||||
{
|
||||
// remember all connected road names
|
||||
connected_names.insert(edge_data.name_id);
|
||||
@@ -322,7 +326,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
||||
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(at_node))
|
||||
{
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(edge);
|
||||
if (edge_data.roundabout || edge_data.circular)
|
||||
if (edge_data.flags.roundabout || edge_data.flags.circular)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
@@ -353,7 +357,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
|
||||
bool roundabout = false, circular = false;
|
||||
for (const auto eid : node_based_graph.GetAdjacentEdgeRange(nid))
|
||||
{
|
||||
const auto data = node_based_graph.GetEdgeData(eid);
|
||||
const auto data = node_based_graph.GetEdgeData(eid).flags;
|
||||
roundabout |= data.roundabout;
|
||||
circular |= data.circular;
|
||||
}
|
||||
@@ -435,7 +439,8 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
NodeID node_at_center_of_intersection = node_based_graph.GetTarget(via_eid);
|
||||
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid);
|
||||
|
||||
const bool lhs = in_edge_data.is_left_hand_driving;
|
||||
const bool lhs =
|
||||
node_data_container.GetAnnotation(in_edge_data.annotation_data).is_left_hand_driving;
|
||||
const int step = lhs ? -1 : 1;
|
||||
|
||||
if (on_roundabout)
|
||||
@@ -448,7 +453,8 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
{
|
||||
auto &road = intersection[idx];
|
||||
auto &turn = road;
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid).flags;
|
||||
;
|
||||
if (out_data.roundabout || out_data.circular)
|
||||
{
|
||||
// TODO can forks happen in roundabouts? E.g. required lane changes
|
||||
@@ -471,11 +477,10 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
for (const auto eid :
|
||||
node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection))
|
||||
{
|
||||
const auto &data_of_leaving_edge = node_based_graph.GetEdgeData(eid);
|
||||
if (!data_of_leaving_edge.reversed &&
|
||||
!data_of_leaving_edge.roundabout &&
|
||||
!data_of_leaving_edge.circular &&
|
||||
!data_of_leaving_edge.road_classification.IsLowPriorityRoadClass())
|
||||
const auto &leaving_edge = node_based_graph.GetEdgeData(eid);
|
||||
if (!leaving_edge.reversed && !leaving_edge.flags.roundabout &&
|
||||
!leaving_edge.flags.circular &&
|
||||
!leaving_edge.flags.road_classification.IsLowPriorityRoadClass())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -511,7 +516,7 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
|
||||
++cnt, idx += step)
|
||||
{
|
||||
auto &turn = intersection[idx];
|
||||
const auto &out_data = node_based_graph.GetEdgeData(turn.eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(turn.eid).flags;
|
||||
|
||||
// A roundabout consists of exactly two roads at an intersection. by toggeling this
|
||||
// flag, we can switch between roads crossing the roundabout and roads that are on the
|
||||
|
||||
@@ -23,10 +23,12 @@ namespace guidance
|
||||
|
||||
SliproadHandler::SliproadHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
@@ -109,7 +111,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto &road_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &road_data = node_based_graph.GetEdgeData(road.eid).flags;
|
||||
|
||||
auto is_roundabout = road_data.roundabout;
|
||||
|
||||
@@ -156,7 +158,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
|
||||
for (const auto &road : main_road_intersection->intersection)
|
||||
{
|
||||
const auto &target_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto target_annotation_id = node_based_graph.GetEdgeData(road.eid).annotation_data;
|
||||
const auto &target_data = node_data_container.GetAnnotation(target_annotation_id);
|
||||
target_road_name_ids.push_back(target_data.name_id);
|
||||
}
|
||||
|
||||
@@ -173,7 +176,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
continue;
|
||||
|
||||
auto &sliproad = intersection[road_index]; // this is what we're checking and assigning to
|
||||
const auto &sliproad_data = node_based_graph.GetEdgeData(sliproad.eid);
|
||||
const auto &sliproad_edge_data = node_based_graph.GetEdgeData(sliproad.eid);
|
||||
|
||||
// Intersection is orderd: 0 is UTurn, then from sharp right to sharp left.
|
||||
// We already have an obvious index (bc) for going straight-ish.
|
||||
@@ -199,13 +202,13 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
}
|
||||
|
||||
// Discard service and other low priority roads - never Sliproad candidate
|
||||
if (sliproad_data.road_classification.IsLowPriorityRoadClass())
|
||||
if (sliproad_edge_data.flags.road_classification.IsLowPriorityRoadClass())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Incoming-only can never be a Sliproad
|
||||
if (sliproad_data.reversed)
|
||||
if (sliproad_edge_data.reversed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -350,7 +353,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &onto_data = node_based_graph.GetEdgeData(onto.eid);
|
||||
const auto &onto_data = node_based_graph.GetEdgeData(onto.eid).flags;
|
||||
|
||||
if (onto_data.roundabout)
|
||||
{
|
||||
@@ -434,7 +437,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
|
||||
// Check sliproads with skew main intersections
|
||||
if (deviation_from_straight > 180. - minimal_crossroad_angle_of_intersection &&
|
||||
!node_based_graph.GetEdgeData(sliproad.eid).road_classification.IsLinkClass())
|
||||
!node_based_graph.GetEdgeData(sliproad.eid)
|
||||
.flags.road_classification.IsLinkClass())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -449,9 +453,10 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
// ` .
|
||||
// d
|
||||
//
|
||||
const auto area_threshold = std::pow(
|
||||
scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD, sliproad_data.road_classification),
|
||||
2.);
|
||||
const auto area_threshold =
|
||||
std::pow(scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD,
|
||||
sliproad_edge_data.flags.road_classification),
|
||||
2.);
|
||||
|
||||
if (!isValidSliproadArea(area_threshold,
|
||||
intersection_node_id,
|
||||
@@ -464,7 +469,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
// Check all roads at `d` if one is connected to `c`, is so `bd` is Sliproad.
|
||||
for (const auto &candidate_road : target_intersection)
|
||||
{
|
||||
const auto &candidate_data = node_based_graph.GetEdgeData(candidate_road.eid);
|
||||
const auto &candidate_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(candidate_road.eid).annotation_data);
|
||||
|
||||
// Name mismatch: check roads at `c` and `d` for same name
|
||||
const auto name_mismatch = [&](const NameID road_name_id) {
|
||||
@@ -489,15 +495,20 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
|
||||
// Check if main road -> sliproad (non-link) -> candidate road requires two name
|
||||
// announcements then don't suppress one announcement via sliproad handler
|
||||
const auto main_road_name_id = node_based_graph.GetEdgeData(main_road.eid).name_id;
|
||||
if (!sliproad_data.road_classification.IsLinkClass() &&
|
||||
sliproad_data.name_id != EMPTY_NAMEID && main_road_name_id != EMPTY_NAMEID &&
|
||||
const auto main_road_name_id =
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(main_road.eid).annotation_data)
|
||||
.name_id;
|
||||
const auto &sliproad_annotation =
|
||||
node_data_container.GetAnnotation(sliproad_edge_data.annotation_data);
|
||||
if (!sliproad_edge_data.flags.road_classification.IsLinkClass() &&
|
||||
sliproad_annotation.name_id != EMPTY_NAMEID && main_road_name_id != EMPTY_NAMEID &&
|
||||
candidate_data.name_id != EMPTY_NAMEID &&
|
||||
util::guidance::requiresNameAnnounced(main_road_name_id,
|
||||
sliproad_data.name_id,
|
||||
sliproad_annotation.name_id,
|
||||
name_table,
|
||||
street_name_suffix_table) &&
|
||||
util::guidance::requiresNameAnnounced(sliproad_data.name_id,
|
||||
util::guidance::requiresNameAnnounced(sliproad_annotation.name_id,
|
||||
candidate_data.name_id,
|
||||
name_table,
|
||||
street_name_suffix_table))
|
||||
@@ -553,6 +564,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
// In those cases the obvious non-Sliproad is now obvious and we discard the Fork turn type.
|
||||
if (sliproad_found && main_road.instruction.type == TurnType::Fork)
|
||||
{
|
||||
const auto &main_data = node_based_graph.GetEdgeData(main_road.eid);
|
||||
const auto &main_annotation = node_data_container.GetAnnotation(main_data.annotation_data);
|
||||
if (isSameName(source_edge_id, main_road.eid))
|
||||
{
|
||||
if (angularDeviation(main_road.angle, STRAIGHT_ANGLE) < 5)
|
||||
@@ -562,7 +575,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
|
||||
intersection[*obvious].instruction.direction_modifier =
|
||||
getTurnDirection(intersection[*obvious].angle);
|
||||
}
|
||||
else if (node_based_graph.GetEdgeData(main_road.eid).name_id != EMPTY_NAMEID)
|
||||
else if (main_annotation.name_id != EMPTY_NAMEID)
|
||||
{
|
||||
intersection[*obvious].instruction.type = TurnType::NewName;
|
||||
intersection[*obvious].instruction.direction_modifier =
|
||||
@@ -644,7 +657,7 @@ bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const Edg
|
||||
const auto &coordinate_extractor = intersection_generator.GetCoordinateExtractor();
|
||||
|
||||
// Base max distance threshold on the current road class we're on
|
||||
const auto &data = node_based_graph.GetEdgeData(onto);
|
||||
const auto &data = node_based_graph.GetEdgeData(onto).flags;
|
||||
const auto threshold = scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD, // <- scales down
|
||||
data.road_classification);
|
||||
|
||||
@@ -662,13 +675,15 @@ bool SliproadHandler::isThroughStreet(const EdgeID from, const IntersectionView
|
||||
BOOST_ASSERT(from != SPECIAL_EDGEID);
|
||||
BOOST_ASSERT(!intersection.empty());
|
||||
|
||||
const auto &edge_name_id = node_based_graph.GetEdgeData(from).name_id;
|
||||
const auto from_annotation_id = node_based_graph.GetEdgeData(from).annotation_data;
|
||||
const auto &edge_name_id = node_data_container.GetAnnotation(from_annotation_id).name_id;
|
||||
|
||||
auto first = begin(intersection) + 1; // Skip UTurn road
|
||||
auto last = end(intersection);
|
||||
|
||||
auto same_name = [&](const auto &road) {
|
||||
const auto &road_name_id = node_based_graph.GetEdgeData(road.eid).name_id;
|
||||
const auto annotation_id = node_based_graph.GetEdgeData(road.eid).annotation_data;
|
||||
const auto &road_name_id = node_data_container.GetAnnotation(annotation_id).name_id;
|
||||
|
||||
return edge_name_id != EMPTY_NAMEID && //
|
||||
road_name_id != EMPTY_NAMEID && //
|
||||
@@ -683,10 +698,13 @@ bool SliproadHandler::isThroughStreet(const EdgeID from, const IntersectionView
|
||||
|
||||
bool SliproadHandler::roadContinues(const EdgeID current, const EdgeID next) const
|
||||
{
|
||||
const auto ¤t_data = node_based_graph.GetEdgeData(current);
|
||||
const auto &next_data = node_based_graph.GetEdgeData(next);
|
||||
const auto ¤t_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(current).annotation_data);
|
||||
const auto &next_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(next).annotation_data);
|
||||
|
||||
auto same_road_category = current_data.road_classification == next_data.road_classification;
|
||||
auto same_road_category = node_based_graph.GetEdgeData(current).flags.road_classification ==
|
||||
node_based_graph.GetEdgeData(next).flags.road_classification;
|
||||
auto same_travel_mode = current_data.travel_mode == next_data.travel_mode;
|
||||
|
||||
auto same_name = current_data.name_id != EMPTY_NAMEID && //
|
||||
@@ -730,22 +748,18 @@ bool SliproadHandler::isValidSliproadArea(const double max_area,
|
||||
}
|
||||
|
||||
bool SliproadHandler::isValidSliproadLink(const IntersectionViewData &sliproad,
|
||||
const IntersectionViewData &first,
|
||||
const IntersectionViewData & /*first*/,
|
||||
const IntersectionViewData &second) const
|
||||
{
|
||||
// If the sliproad is not a link we don't care
|
||||
const auto &sliproad_data = node_based_graph.GetEdgeData(sliproad.eid);
|
||||
// If the Sliproad is not a link we don't care
|
||||
const auto &sliproad_data = node_based_graph.GetEdgeData(sliproad.eid).flags;
|
||||
if (!sliproad_data.road_classification.IsLinkClass())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// otherwise the first road leading to the intersection we shortcut
|
||||
// can be a link or a usual road (ignore the check at this place)
|
||||
(void)first;
|
||||
|
||||
// and the second road coming from the intersection we shortcut must be a non-link
|
||||
const auto &second_road_data = node_based_graph.GetEdgeData(second.eid);
|
||||
const auto &second_road_data = node_based_graph.GetEdgeData(second.eid).flags;
|
||||
if (second_road_data.road_classification.IsLinkClass())
|
||||
{
|
||||
return false;
|
||||
@@ -758,10 +772,15 @@ bool SliproadHandler::allSameMode(const EdgeID from,
|
||||
const EdgeID sliproad_candidate,
|
||||
const EdgeID target_road) const
|
||||
{
|
||||
return node_based_graph.GetEdgeData(from).travel_mode ==
|
||||
node_based_graph.GetEdgeData(sliproad_candidate).travel_mode &&
|
||||
node_based_graph.GetEdgeData(sliproad_candidate).travel_mode ==
|
||||
node_based_graph.GetEdgeData(target_road).travel_mode;
|
||||
const auto &from_annotation =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(from).annotation_data);
|
||||
const auto &sliproad_annotation = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(sliproad_candidate).annotation_data);
|
||||
const auto &target_annotation = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(target_road).annotation_data);
|
||||
|
||||
return (from_annotation.travel_mode == sliproad_annotation.travel_mode) &&
|
||||
(target_annotation.travel_mode == sliproad_annotation.travel_mode);
|
||||
}
|
||||
|
||||
bool SliproadHandler::canBeTargetOfSliproad(const IntersectionView &intersection)
|
||||
|
||||
@@ -13,10 +13,12 @@ namespace guidance
|
||||
|
||||
SuppressModeHandler::SuppressModeHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
@@ -36,14 +38,18 @@ bool SuppressModeHandler::canProcess(const NodeID,
|
||||
|
||||
// If the approach way is not on the suppression blacklist, and not all the exit ways share that
|
||||
// mode, there are no ways to suppress by this criteria.
|
||||
const auto in_mode = node_based_graph.GetEdgeData(via_eid).travel_mode;
|
||||
const auto in_mode =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_eid).annotation_data)
|
||||
.travel_mode;
|
||||
const auto suppress_in_mode = std::find(begin(suppressed), end(suppressed), in_mode);
|
||||
|
||||
const auto first = begin(intersection);
|
||||
const auto last = end(intersection);
|
||||
|
||||
const auto all_share_mode = std::all_of(first, last, [this, &in_mode](const auto &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid).travel_mode == in_mode;
|
||||
return node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.travel_mode == in_mode;
|
||||
});
|
||||
|
||||
return (suppress_in_mode != end(suppressed)) && all_share_mode;
|
||||
|
||||
@@ -21,56 +21,61 @@ namespace guidance
|
||||
|
||||
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
||||
|
||||
bool requiresAnnouncement(const EdgeData &from, const EdgeData &to)
|
||||
{
|
||||
return !from.CanCombineWith(to);
|
||||
}
|
||||
|
||||
TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const ProfileProperties &profile_properties)
|
||||
: node_based_graph(node_based_graph),
|
||||
intersection_generator(
|
||||
node_based_graph, restriction_map, barrier_nodes, coordinates, compressed_edge_container),
|
||||
const SuffixTable &street_name_suffix_table)
|
||||
: node_based_graph(node_based_graph), intersection_generator(node_based_graph,
|
||||
node_data_container,
|
||||
restriction_map,
|
||||
barrier_nodes,
|
||||
coordinates,
|
||||
compressed_edge_container),
|
||||
intersection_normalizer(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
intersection_generator),
|
||||
roundabout_handler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
compressed_edge_container,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
profile_properties,
|
||||
intersection_generator),
|
||||
motorway_handler(node_based_graph,
|
||||
node_data_container,
|
||||
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
intersection_generator),
|
||||
turn_handler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
intersection_generator),
|
||||
sliproad_handler(intersection_generator,
|
||||
node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table),
|
||||
suppress_mode_handler(intersection_generator,
|
||||
node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table),
|
||||
driveway_handler(intersection_generator,
|
||||
node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table)
|
||||
@@ -163,7 +168,7 @@ Intersection TurnAnalysis::AssignTurnTypes(const NodeID node_prior_to_intersecti
|
||||
node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
||||
|
||||
// Turn On Ramps Into Off Ramps, if we come from a motorway-like road
|
||||
if (node_based_graph.GetEdgeData(entering_via_edge).road_classification.IsMotorwayClass())
|
||||
if (node_based_graph.GetEdgeData(entering_via_edge).flags.road_classification.IsMotorwayClass())
|
||||
{
|
||||
std::for_each(intersection.begin(), intersection.end(), [](ConnectedRoad &road) {
|
||||
if (road.instruction.type == TurnType::OnRamp)
|
||||
|
||||
@@ -111,11 +111,13 @@ std::size_t TurnHandler::Fork::getLeftIndex() const
|
||||
}
|
||||
|
||||
TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const IntersectionGenerator &intersection_generator)
|
||||
: IntersectionHandler(node_based_graph,
|
||||
node_data_container,
|
||||
coordinates,
|
||||
name_table,
|
||||
street_name_suffix_table,
|
||||
@@ -174,12 +176,16 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
|
||||
const ConnectedRoad &road,
|
||||
const ConnectedRoad &other) const
|
||||
{
|
||||
const auto &via_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &road_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &other_data = node_based_graph.GetEdgeData(other.eid);
|
||||
const auto &via_classification = via_data.road_classification;
|
||||
const auto &road_classification = road_data.road_classification;
|
||||
const auto &other_classification = other_data.road_classification;
|
||||
const auto &via_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data);
|
||||
const auto &road_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data);
|
||||
const auto &via_classification =
|
||||
node_based_graph.GetEdgeData(via_edge).flags.road_classification;
|
||||
const auto &road_classification =
|
||||
node_based_graph.GetEdgeData(road.eid).flags.road_classification;
|
||||
const auto &other_classification =
|
||||
node_based_graph.GetEdgeData(other.eid).flags.road_classification;
|
||||
|
||||
// if one of the given roads is obvious by class, obviousness is trivial
|
||||
if (obviousByRoadClass(via_classification, road_classification, other_classification))
|
||||
@@ -335,9 +341,9 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
|
||||
if (fork->size == 2)
|
||||
{
|
||||
const auto left_classification =
|
||||
node_based_graph.GetEdgeData(fork->getLeft().eid).road_classification;
|
||||
node_based_graph.GetEdgeData(fork->getLeft().eid).flags.road_classification;
|
||||
const auto right_classification =
|
||||
node_based_graph.GetEdgeData(fork->getRight().eid).road_classification;
|
||||
node_based_graph.GetEdgeData(fork->getRight().eid).flags.road_classification;
|
||||
if (canBeSeenAsFork(left_classification, right_classification))
|
||||
{
|
||||
assignFork(via_edge, fork->getLeft(), fork->getRight());
|
||||
@@ -615,26 +621,27 @@ TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const
|
||||
// incoming edge are compatible by class
|
||||
bool TurnHandler::isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const
|
||||
{
|
||||
const auto via_class = node_based_graph.GetEdgeData(intersection[0].eid).road_classification;
|
||||
const auto via_class =
|
||||
node_based_graph.GetEdgeData(intersection[0].eid).flags.road_classification;
|
||||
|
||||
// if any of the considered roads is a link road, it cannot be a fork
|
||||
// except if rightmost fork candidate is also a link road
|
||||
const auto is_right_link_class =
|
||||
node_based_graph.GetEdgeData(fork.getRight().eid).road_classification.IsLinkClass();
|
||||
node_based_graph.GetEdgeData(fork.getRight().eid).flags.road_classification.IsLinkClass();
|
||||
if (!std::all_of(fork.begin + 1, fork.end, [&](ConnectedRoad &road) {
|
||||
return is_right_link_class ==
|
||||
node_based_graph.GetEdgeData(road.eid).road_classification.IsLinkClass();
|
||||
node_based_graph.GetEdgeData(road.eid).flags.road_classification.IsLinkClass();
|
||||
}))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::all_of(fork.begin, fork.end, [&](ConnectedRoad &base) {
|
||||
const auto base_class = node_based_graph.GetEdgeData(base.eid).road_classification;
|
||||
const auto base_class = node_based_graph.GetEdgeData(base.eid).flags.road_classification;
|
||||
// check that there is no turn obvious == check that all turns are non-onvious
|
||||
return std::all_of(fork.begin, fork.end, [&](ConnectedRoad &compare) {
|
||||
const auto compare_class =
|
||||
node_based_graph.GetEdgeData(compare.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(compare.eid).flags.road_classification;
|
||||
return compare.eid == base.eid ||
|
||||
!(obviousByRoadClass(via_class, base_class, compare_class));
|
||||
});
|
||||
@@ -670,8 +677,12 @@ boost::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
|
||||
|
||||
const auto has_compatible_modes =
|
||||
std::all_of(fork->begin, fork->end, [&](const auto &road) {
|
||||
return node_based_graph.GetEdgeData(road.eid).travel_mode ==
|
||||
node_based_graph.GetEdgeData(via_edge).travel_mode;
|
||||
return node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
|
||||
.travel_mode ==
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
|
||||
.travel_mode;
|
||||
});
|
||||
|
||||
if (separated_at_left_side && separated_at_right_side && !has_obvious &&
|
||||
@@ -703,9 +714,10 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
|
||||
getTurnDirection(left.angle) == DirectionModifier::SlightLeft ||
|
||||
getTurnDirection(right.angle) == DirectionModifier::SlightRight)
|
||||
{
|
||||
const auto left_classification = node_based_graph.GetEdgeData(left.eid).road_classification;
|
||||
const auto left_classification =
|
||||
node_based_graph.GetEdgeData(left.eid).flags.road_classification;
|
||||
const auto right_classification =
|
||||
node_based_graph.GetEdgeData(right.eid).road_classification;
|
||||
node_based_graph.GetEdgeData(right.eid).flags.road_classification;
|
||||
|
||||
if (left_classification.GetPriority() > right_classification.GetPriority())
|
||||
{
|
||||
|
||||
@@ -34,11 +34,12 @@ std::size_t getNumberOfTurns(const Intersection &intersection)
|
||||
} // namespace
|
||||
|
||||
TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
LaneDescriptionMap &lane_description_map,
|
||||
const TurnAnalysis &turn_analysis,
|
||||
util::guidance::LaneDataIdMap &id_map)
|
||||
: node_based_graph(node_based_graph), lane_description_map(lane_description_map),
|
||||
turn_analysis(turn_analysis), id_map(id_map)
|
||||
: node_based_graph(node_based_graph), node_data_container(node_data_container),
|
||||
lane_description_map(lane_description_map), turn_analysis(turn_analysis), id_map(id_map)
|
||||
{
|
||||
std::tie(turn_lane_offsets, turn_lane_masks) =
|
||||
transformTurnLaneMapIntoArrays(lane_description_map);
|
||||
@@ -149,7 +150,7 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
LaneDescriptionID &previous_description_id)
|
||||
{
|
||||
// as long as we don't want to emit lanes on roundabout, don't assign them
|
||||
if (node_based_graph.GetEdgeData(via_edge).roundabout)
|
||||
if (node_based_graph.GetEdgeData(via_edge).flags.roundabout)
|
||||
return TurnLaneScenario::NONE;
|
||||
|
||||
// really don't touch roundabouts (#2626)
|
||||
@@ -179,7 +180,9 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
|
||||
(intersection.size() == 2 &&
|
||||
((lane_description_id != INVALID_LANE_DESCRIPTIONID &&
|
||||
lane_description_id ==
|
||||
node_based_graph.GetEdgeData(intersection[1].eid).lane_description_id) &&
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(intersection[1].eid).annotation_data)
|
||||
.lane_description_id) &&
|
||||
angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE));
|
||||
|
||||
if (is_going_straight_and_turns_continue)
|
||||
@@ -367,7 +370,8 @@ void TurnLaneHandler::extractLaneData(const EdgeID via_edge,
|
||||
LaneDescriptionID &lane_description_id,
|
||||
LaneDataVector &lane_data) const
|
||||
{
|
||||
const auto &edge_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &edge_data =
|
||||
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data);
|
||||
lane_description_id = edge_data.lane_description_id;
|
||||
// create an empty lane data
|
||||
if (INVALID_LANE_DESCRIPTIONID != lane_description_id)
|
||||
@@ -719,9 +723,13 @@ Intersection TurnLaneHandler::handleSliproadTurn(Intersection intersection,
|
||||
return previous_intersection[sliproad_index + 1];
|
||||
}();
|
||||
const auto main_description_id =
|
||||
node_based_graph.GetEdgeData(main_road.eid).lane_description_id;
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(main_road.eid).annotation_data)
|
||||
.lane_description_id;
|
||||
const auto sliproad_description_id =
|
||||
node_based_graph.GetEdgeData(sliproad.eid).lane_description_id;
|
||||
node_data_container
|
||||
.GetAnnotation(node_based_graph.GetEdgeData(sliproad.eid).annotation_data)
|
||||
.lane_description_id;
|
||||
|
||||
if (main_description_id == INVALID_LANE_DESCRIPTIONID ||
|
||||
sliproad_description_id == INVALID_LANE_DESCRIPTIONID)
|
||||
|
||||
Reference in New Issue
Block a user