add low precision intersection_generator mode for faster graph traversal
This commit is contained in:
parent
b2c27fbd25
commit
a49bd70985
@ -49,6 +49,17 @@ class CoordinateExtractor
|
||||
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
|
||||
const EdgeID turn_edge) const;
|
||||
|
||||
// a less precise way to compute coordinates along a route. Due to the heavy interaction of
|
||||
// graph traversal and turn instructions, we often don't care for high precision. We only want
|
||||
// to check for available connections in order, or find (with room for error) the straightmost
|
||||
// turn. This function will offer a bit more error potential but allow for much higher
|
||||
// performance
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
|
||||
const EdgeID turn_edge,
|
||||
const bool traversed_in_reverse,
|
||||
const NodeID to_node) const;
|
||||
|
||||
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
|
||||
* of them, though.
|
||||
*
|
||||
|
@ -51,8 +51,14 @@ class IntersectionGenerator
|
||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
||||
// the node reached from `from_node` via `via_eid`. The resulting candidates have to be analysed
|
||||
// for their actual instructions later on.
|
||||
// The switch for `use_low_precision_angles` enables a faster mode that will procude less
|
||||
// accurate coordinates. It should be good enough to check order of turns, find striaghtmost
|
||||
// turns. Even good enough to do some simple angle verifications. It is mostly available to
|
||||
// allow for faster graph traversal in the extraction phase.
|
||||
OSRM_ATTR_WARN_UNUSED
|
||||
Intersection GetConnectedRoads(const NodeID from_node, const EdgeID via_eid) const;
|
||||
Intersection GetConnectedRoads(const NodeID from_node,
|
||||
const EdgeID via_eid,
|
||||
const bool use_low_precision_angles = false) const;
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
|
@ -315,6 +315,55 @@ CoordinateExtractor::GetCoordinateAlongRoad(const NodeID intersection_node,
|
||||
.back();
|
||||
}
|
||||
|
||||
util::Coordinate CoordinateExtractor::GetCoordinateCloseToTurn(const NodeID from_node,
|
||||
const EdgeID turn_edge,
|
||||
const bool traversed_in_reverse,
|
||||
const NodeID to_node) const
|
||||
{
|
||||
const auto end_node = traversed_in_reverse ? from_node : to_node;
|
||||
const auto start_node = traversed_in_reverse ? to_node : from_node;
|
||||
if (!compressed_geometries.HasEntryForID(turn_edge))
|
||||
return node_coordinates[end_node];
|
||||
else
|
||||
{
|
||||
const auto &geometry = compressed_geometries.GetBucketReference(turn_edge);
|
||||
|
||||
// the compressed edges contain node ids, we transfer them to coordinates accessing the
|
||||
// node_coordinates array
|
||||
const auto compressedGeometryToCoordinate =
|
||||
[this](const CompressedEdgeContainer::OnewayCompressedEdge &compressed_edge) {
|
||||
return node_coordinates[compressed_edge.node_id];
|
||||
};
|
||||
|
||||
// return the first coordinate that is reasonably far away from the start node
|
||||
const util::Coordinate start_coordinate = node_coordinates[start_node];
|
||||
|
||||
// OSM data has a tendency to include repeated nodes with identical coordinates. To skip
|
||||
// over these, we search for the first coordinate along the path that is at least a meter
|
||||
// away from the first entry
|
||||
const auto far_enough_away = [start_coordinate, compressedGeometryToCoordinate](
|
||||
const CompressedEdgeContainer::OnewayCompressedEdge &compressed_edge) {
|
||||
return util::coordinate_calculation::haversineDistance(
|
||||
compressedGeometryToCoordinate(compressed_edge), start_coordinate) > 1;
|
||||
};
|
||||
|
||||
// find the first coordinate, that is at least unequal to the begin of the edge
|
||||
if (traversed_in_reverse)
|
||||
{
|
||||
const auto far_enough =
|
||||
std::find_if(geometry.rbegin(), geometry.rend(), far_enough_away);
|
||||
return (far_enough != geometry.rend()) ? compressedGeometryToCoordinate(*far_enough)
|
||||
: node_coordinates[end_node];
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto far_enough = std::find_if(geometry.begin(), geometry.end(), far_enough_away);
|
||||
return (far_enough != geometry.end()) ? compressedGeometryToCoordinate(*far_enough)
|
||||
: node_coordinates[end_node];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<util::Coordinate>
|
||||
CoordinateExtractor::GetForwardCoordinatesAlongRoad(const NodeID from, const EdgeID turn_edge) const
|
||||
{
|
||||
|
@ -20,6 +20,12 @@ namespace extractor
|
||||
{
|
||||
namespace guidance
|
||||
{
|
||||
namespace
|
||||
{
|
||||
const constexpr bool USE_LOW_PRECISION_MODE = true;
|
||||
// the inverse of use low precision mode
|
||||
const constexpr bool USE_HIGH_PRECISION_MODE = !USE_LOW_PRECISION_MODE;
|
||||
}
|
||||
|
||||
IntersectionGenerator::IntersectionGenerator(
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
@ -35,14 +41,14 @@ IntersectionGenerator::IntersectionGenerator(
|
||||
|
||||
Intersection IntersectionGenerator::operator()(const NodeID from_node, const EdgeID via_eid) const
|
||||
{
|
||||
return GetConnectedRoads(from_node, via_eid);
|
||||
return GetConnectedRoads(from_node, via_eid, USE_HIGH_PRECISION_MODE);
|
||||
}
|
||||
|
||||
// a
|
||||
// |
|
||||
// |
|
||||
// v
|
||||
// For an intersection from_node --via_edi--> turn_node ----> c
|
||||
// For an intersection from_node --via_eid--> turn_node ----> c
|
||||
// ^
|
||||
// |
|
||||
// |
|
||||
@ -52,7 +58,8 @@ Intersection IntersectionGenerator::operator()(const NodeID from_node, const Edg
|
||||
// but also (from_node, turn_node, a), (from_node, turn_node, b). These turns are
|
||||
// marked as invalid and only needed for intersection classification.
|
||||
Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
const EdgeID via_eid) const
|
||||
const EdgeID via_eid,
|
||||
const bool use_low_precision_angles) const
|
||||
{
|
||||
Intersection intersection;
|
||||
const NodeID turn_node = node_based_graph.GetTarget(via_eid);
|
||||
@ -81,6 +88,17 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
|
||||
const auto intersection_lanes = getLaneCountAtIntersection(turn_node, node_based_graph);
|
||||
|
||||
const auto extract_coordinate = [&](const NodeID from_node,
|
||||
const EdgeID via_eid,
|
||||
const bool traversed_in_reverse,
|
||||
const NodeID to_node) {
|
||||
return use_low_precision_angles
|
||||
? coordinate_extractor.GetCoordinateCloseToTurn(
|
||||
from_node, via_eid, traversed_in_reverse, to_node)
|
||||
: coordinate_extractor.GetCoordinateAlongRoad(
|
||||
from_node, via_eid, traversed_in_reverse, to_node, intersection_lanes);
|
||||
};
|
||||
|
||||
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
|
||||
{
|
||||
BOOST_ASSERT(onto_edge != SPECIAL_EDGEID);
|
||||
@ -105,8 +123,7 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
// The first coordinate (the origin) can depend on the number of lanes turning onto,
|
||||
// just as the target coordinate can. Here we compute the corrected coordinate for the
|
||||
// incoming edge.
|
||||
const auto first_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
|
||||
from_node, via_eid, INVERT, turn_node, intersection_lanes);
|
||||
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
|
||||
|
||||
if (from_node == to_node)
|
||||
{
|
||||
@ -139,8 +156,8 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
{
|
||||
// the default distance we lookahead on a road. This distance prevents small mapping
|
||||
// errors to impact the turn angles.
|
||||
const auto third_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
|
||||
turn_node, onto_edge, !INVERT, to_node, intersection_lanes);
|
||||
const auto third_coordinate =
|
||||
extract_coordinate(turn_node, onto_edge, !INVERT, to_node);
|
||||
|
||||
angle = util::coordinate_calculation::computeAngle(
|
||||
first_coordinate, turn_coordinate, third_coordinate);
|
||||
@ -164,12 +181,7 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
||||
// will never happen we add an artificial invalid uturn in this case.
|
||||
if (!has_uturn_edge)
|
||||
{
|
||||
const auto first_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
|
||||
from_node,
|
||||
via_eid,
|
||||
INVERT,
|
||||
turn_node,
|
||||
node_based_graph.GetEdgeData(via_eid).road_classification.GetNumberOfLanes());
|
||||
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
|
||||
const double bearing =
|
||||
util::coordinate_calculation::bearing(turn_coordinate, first_coordinate);
|
||||
|
||||
|
@ -12,6 +12,11 @@ namespace guidance
|
||||
namespace lanes
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
const constexpr bool USE_LOW_PRECISION_MODE = true;
|
||||
}
|
||||
|
||||
bool findPreviousIntersection(const NodeID node_v,
|
||||
const EdgeID via_edge,
|
||||
const Intersection intersection,
|
||||
@ -50,7 +55,8 @@ bool findPreviousIntersection(const NodeID node_v,
|
||||
// (looking at the reverse direction).
|
||||
const auto node_w = node_based_graph.GetTarget(via_edge);
|
||||
const auto u_turn_at_node_w = intersection[0].eid;
|
||||
const auto node_v_reverse_intersection = intersection_generator(node_w, u_turn_at_node_w);
|
||||
const auto node_v_reverse_intersection =
|
||||
intersection_generator.GetConnectedRoads(node_w, u_turn_at_node_w, USE_LOW_PRECISION_MODE);
|
||||
|
||||
// Continue along the straightmost turn. If there is no straight turn, we cannot find a valid
|
||||
// previous intersection.
|
||||
@ -64,8 +70,8 @@ bool findPreviousIntersection(const NodeID node_v,
|
||||
return false;
|
||||
|
||||
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->eid);
|
||||
const auto node_u_reverse_intersection =
|
||||
intersection_generator(node_v, straightmost_at_v_in_reverse->eid);
|
||||
const auto node_u_reverse_intersection = intersection_generator.GetConnectedRoads(
|
||||
node_v, straightmost_at_v_in_reverse->eid, USE_LOW_PRECISION_MODE);
|
||||
|
||||
// now check that the u-turn at the given intersection connects to via-edge
|
||||
// The u-turn at the now found intersection should, hopefully, represent the previous edge.
|
||||
|
Loading…
Reference in New Issue
Block a user