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:
Moritz Kobitzsch
2017-09-25 15:37:11 +02:00
committed by Michael Krasnyk
parent 9b044aaa42
commit 2ddd98ee6d
64 changed files with 1610 additions and 1190 deletions
@@ -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);
+5 -3
View File
@@ -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;
}
+86 -44
View File
@@ -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
+13 -7
View File
@@ -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 ||
+38 -33
View File
@@ -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
+54 -35
View File
@@ -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 &current_data = node_based_graph.GetEdgeData(current);
const auto &next_data = node_based_graph.GetEdgeData(next);
const auto &current_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;
+17 -12
View File
@@ -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)
+29 -17
View File
@@ -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())
{
+15 -7
View File
@@ -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)