2016-12-21 06:30:56 -05:00
|
|
|
#include "extractor/guidance/turn_analysis.hpp"
|
2016-07-26 09:00:58 -04:00
|
|
|
#include "extractor/guidance/constants.hpp"
|
|
|
|
#include "extractor/guidance/road_classification.hpp"
|
2016-02-25 08:40:26 -05:00
|
|
|
|
2016-03-03 09:36:03 -05:00
|
|
|
#include "util/coordinate.hpp"
|
2016-03-23 10:28:53 -04:00
|
|
|
#include "util/coordinate_calculation.hpp"
|
2016-02-26 11:33:18 -05:00
|
|
|
|
|
|
|
#include <cstddef>
|
2016-03-23 10:28:53 -04:00
|
|
|
#include <set>
|
2016-05-25 09:24:11 -04:00
|
|
|
#include <unordered_set>
|
2016-12-02 04:53:22 -05:00
|
|
|
#include <utility>
|
2016-02-26 11:33:18 -05:00
|
|
|
|
2016-12-02 04:53:22 -05:00
|
|
|
using osrm::extractor::guidance::getTurnDirection;
|
2016-04-18 07:41:19 -04:00
|
|
|
|
2016-02-25 08:40:26 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace extractor
|
|
|
|
{
|
2016-03-01 16:30:31 -05:00
|
|
|
namespace guidance
|
2016-02-25 08:40:26 -05:00
|
|
|
{
|
|
|
|
|
|
|
|
using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
|
|
|
|
|
2016-03-08 05:30:33 -05:00
|
|
|
bool requiresAnnouncement(const EdgeData &from, const EdgeData &to)
|
2016-03-04 06:17:06 -05:00
|
|
|
{
|
2016-08-08 09:46:33 -04:00
|
|
|
return !from.CanCombineWith(to);
|
2016-03-04 06:17:06 -05:00
|
|
|
}
|
|
|
|
|
2016-03-08 06:40:45 -05:00
|
|
|
TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
const std::vector<util::Coordinate> &coordinates,
|
2016-03-08 06:40:45 -05:00
|
|
|
const RestrictionMap &restriction_map,
|
|
|
|
const std::unordered_set<NodeID> &barrier_nodes,
|
2016-03-16 10:47:33 -04:00
|
|
|
const CompressedEdgeContainer &compressed_edge_container,
|
2016-04-22 05:31:46 -04:00
|
|
|
const util::NameTable &name_table,
|
2016-07-18 09:34:12 -04:00
|
|
|
const SuffixTable &street_name_suffix_table,
|
|
|
|
const ProfileProperties &profile_properties)
|
2017-04-04 19:01:00 -04:00
|
|
|
: node_based_graph(node_based_graph),
|
|
|
|
intersection_generator(
|
|
|
|
node_based_graph, restriction_map, barrier_nodes, coordinates, compressed_edge_container),
|
2016-11-09 10:52:22 -05:00
|
|
|
intersection_normalizer(node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
coordinates,
|
2016-11-09 10:52:22 -05:00
|
|
|
name_table,
|
|
|
|
street_name_suffix_table,
|
|
|
|
intersection_generator),
|
2016-05-25 09:24:11 -04:00
|
|
|
roundabout_handler(node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
coordinates,
|
2016-05-25 09:24:11 -04:00
|
|
|
compressed_edge_container,
|
|
|
|
name_table,
|
2016-07-18 09:34:12 -04:00
|
|
|
street_name_suffix_table,
|
2016-08-15 06:43:26 -04:00
|
|
|
profile_properties,
|
|
|
|
intersection_generator),
|
|
|
|
motorway_handler(node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
coordinates,
|
2016-08-15 06:43:26 -04:00
|
|
|
name_table,
|
|
|
|
street_name_suffix_table,
|
|
|
|
intersection_generator),
|
|
|
|
turn_handler(node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
coordinates,
|
2016-08-15 06:43:26 -04:00
|
|
|
name_table,
|
|
|
|
street_name_suffix_table,
|
|
|
|
intersection_generator),
|
2016-07-04 06:19:49 -04:00
|
|
|
sliproad_handler(intersection_generator,
|
|
|
|
node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
coordinates,
|
2016-07-04 06:19:49 -04:00
|
|
|
name_table,
|
2016-12-07 14:26:34 -05:00
|
|
|
street_name_suffix_table),
|
|
|
|
suppress_mode_handler(intersection_generator,
|
|
|
|
node_based_graph,
|
2017-04-02 19:58:06 -04:00
|
|
|
coordinates,
|
2016-12-07 14:26:34 -05:00
|
|
|
name_table,
|
|
|
|
street_name_suffix_table)
|
2016-03-07 08:52:26 -05:00
|
|
|
{
|
2016-03-23 10:28:53 -04:00
|
|
|
}
|
|
|
|
|
2016-11-18 03:38:26 -05:00
|
|
|
Intersection TurnAnalysis::operator()(const NodeID node_prior_to_intersection,
|
|
|
|
const EdgeID entering_via_edge) const
|
|
|
|
{
|
|
|
|
TurnAnalysis::ShapeResult shape_result =
|
|
|
|
ComputeIntersectionShapes(node_based_graph.GetTarget(entering_via_edge));
|
|
|
|
|
2016-12-06 07:22:51 -05:00
|
|
|
// assign valid flags to normalized_shape
|
2016-11-18 03:38:26 -05:00
|
|
|
const auto intersection_view = intersection_generator.TransformIntersectionShapeIntoView(
|
|
|
|
node_prior_to_intersection,
|
|
|
|
entering_via_edge,
|
2016-12-06 07:22:51 -05:00
|
|
|
shape_result.annotated_normalized_shape.normalized_shape,
|
2016-11-18 03:38:26 -05:00
|
|
|
shape_result.intersection_shape,
|
2016-12-06 07:22:51 -05:00
|
|
|
shape_result.annotated_normalized_shape.performed_merges);
|
2016-11-18 03:38:26 -05:00
|
|
|
|
|
|
|
// assign the turn types to the intersection
|
|
|
|
return AssignTurnTypes(node_prior_to_intersection, entering_via_edge, intersection_view);
|
|
|
|
}
|
|
|
|
|
|
|
|
Intersection TurnAnalysis::AssignTurnTypes(const NodeID node_prior_to_intersection,
|
|
|
|
const EdgeID entering_via_edge,
|
|
|
|
const IntersectionView &intersection_view) const
|
2016-02-25 08:40:26 -05:00
|
|
|
{
|
2016-04-08 06:49:14 -04:00
|
|
|
// Roundabouts are a main priority. If there is a roundabout instruction present, we process the
|
|
|
|
// turn as a roundabout
|
2016-11-18 03:38:26 -05:00
|
|
|
|
|
|
|
// the following lines create a partly invalid intersection object. We might want to refactor
|
|
|
|
// this at some point
|
|
|
|
Intersection intersection;
|
|
|
|
intersection.reserve(intersection_view.size());
|
|
|
|
std::transform(intersection_view.begin(),
|
|
|
|
intersection_view.end(),
|
|
|
|
std::back_inserter(intersection),
|
|
|
|
[&](const IntersectionViewData &data) {
|
|
|
|
return ConnectedRoad(data,
|
|
|
|
{TurnType::Invalid, DirectionModifier::UTurn},
|
|
|
|
INVALID_LANE_DATAID);
|
|
|
|
});
|
2016-12-21 06:30:56 -05:00
|
|
|
|
|
|
|
// Suppress turns on ways between mode types that do not need guidance, think ferry routes.
|
|
|
|
// This handler has to come first and when it triggers we're done with the intersection: there's
|
|
|
|
// nothing left to be done once we suppressed instructions on such routes. Exit early.
|
2016-12-07 14:26:34 -05:00
|
|
|
if (suppress_mode_handler.canProcess(
|
|
|
|
node_prior_to_intersection, entering_via_edge, intersection))
|
|
|
|
{
|
|
|
|
intersection = suppress_mode_handler(
|
|
|
|
node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
|
|
|
|
|
|
|
return intersection;
|
|
|
|
}
|
|
|
|
|
2016-11-18 03:38:26 -05:00
|
|
|
if (roundabout_handler.canProcess(node_prior_to_intersection, entering_via_edge, intersection))
|
2016-02-25 12:31:29 -05:00
|
|
|
{
|
2016-11-18 03:38:26 -05:00
|
|
|
intersection = roundabout_handler(
|
|
|
|
node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
2016-03-07 08:52:26 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-17 09:09:09 -04:00
|
|
|
// set initial defaults for normal turns and modifier based on angle
|
2016-11-18 03:38:26 -05:00
|
|
|
intersection =
|
|
|
|
setTurnTypes(node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
|
|
|
if (motorway_handler.canProcess(
|
|
|
|
node_prior_to_intersection, entering_via_edge, intersection))
|
2016-03-17 09:09:09 -04:00
|
|
|
{
|
2016-11-18 03:38:26 -05:00
|
|
|
intersection = motorway_handler(
|
|
|
|
node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
2016-03-17 09:09:09 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-11-18 03:38:26 -05:00
|
|
|
BOOST_ASSERT(turn_handler.canProcess(
|
|
|
|
node_prior_to_intersection, entering_via_edge, intersection));
|
|
|
|
intersection = turn_handler(
|
|
|
|
node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
2016-03-17 09:09:09 -04:00
|
|
|
}
|
2016-03-07 08:52:26 -05:00
|
|
|
}
|
2016-05-25 09:24:11 -04:00
|
|
|
// Handle sliproads
|
2016-11-18 03:38:26 -05:00
|
|
|
if (sliproad_handler.canProcess(node_prior_to_intersection, entering_via_edge, intersection))
|
|
|
|
intersection = sliproad_handler(
|
|
|
|
node_prior_to_intersection, entering_via_edge, std::move(intersection));
|
2016-05-25 09:24:11 -04:00
|
|
|
|
2016-06-15 08:25:22 -04:00
|
|
|
// Turn On Ramps Into Off Ramps, if we come from a motorway-like road
|
2016-11-18 03:38:26 -05:00
|
|
|
if (node_based_graph.GetEdgeData(entering_via_edge).road_classification.IsMotorwayClass())
|
2016-06-15 08:25:22 -04:00
|
|
|
{
|
|
|
|
std::for_each(intersection.begin(), intersection.end(), [](ConnectedRoad &road) {
|
2016-11-03 05:18:27 -04:00
|
|
|
if (road.instruction.type == TurnType::OnRamp)
|
|
|
|
road.instruction.type = TurnType::OffRamp;
|
2016-06-15 08:25:22 -04:00
|
|
|
});
|
|
|
|
}
|
2016-05-13 13:18:00 -04:00
|
|
|
return intersection;
|
|
|
|
}
|
|
|
|
|
2016-11-18 03:38:26 -05:00
|
|
|
TurnAnalysis::ShapeResult
|
|
|
|
TurnAnalysis::ComputeIntersectionShapes(const NodeID node_at_center_of_intersection) const
|
2016-05-13 13:18:00 -04:00
|
|
|
{
|
2016-11-18 03:38:26 -05:00
|
|
|
ShapeResult intersection_shape;
|
|
|
|
intersection_shape.intersection_shape =
|
|
|
|
intersection_generator.ComputeIntersectionShape(node_at_center_of_intersection);
|
2016-03-17 09:09:09 -04:00
|
|
|
|
2016-12-06 07:22:51 -05:00
|
|
|
intersection_shape.annotated_normalized_shape = intersection_normalizer(
|
|
|
|
node_at_center_of_intersection, intersection_shape.intersection_shape);
|
2016-02-25 08:40:26 -05:00
|
|
|
|
2016-11-18 03:38:26 -05:00
|
|
|
return intersection_shape;
|
2016-04-26 07:27:40 -04:00
|
|
|
}
|
|
|
|
|
2016-04-08 06:49:14 -04:00
|
|
|
// Sets basic turn types as fallback for otherwise unhandled turns
|
2016-11-18 03:38:26 -05:00
|
|
|
Intersection TurnAnalysis::setTurnTypes(const NodeID node_prior_to_intersection,
|
|
|
|
const EdgeID,
|
|
|
|
Intersection intersection) const
|
2016-02-26 11:33:18 -05:00
|
|
|
{
|
2016-03-17 09:09:09 -04:00
|
|
|
for (auto &road : intersection)
|
2016-02-26 11:33:18 -05:00
|
|
|
{
|
2016-03-17 09:09:09 -04:00
|
|
|
if (!road.entry_allowed)
|
2016-02-26 11:33:18 -05:00
|
|
|
continue;
|
2016-03-03 09:36:03 -05:00
|
|
|
|
2016-11-03 05:18:27 -04:00
|
|
|
const EdgeID onto_edge = road.eid;
|
2016-04-08 06:49:14 -04:00
|
|
|
const NodeID to_nid = node_based_graph.GetTarget(onto_edge);
|
2016-02-26 11:33:18 -05:00
|
|
|
|
2017-06-01 05:43:53 -04:00
|
|
|
if (node_prior_to_intersection == to_nid)
|
|
|
|
road.instruction = {TurnType::Continue, DirectionModifier::UTurn};
|
|
|
|
else
|
|
|
|
road.instruction = {TurnType::Turn, getTurnDirection(road.angle)};
|
2016-03-04 06:17:06 -05:00
|
|
|
}
|
2016-03-17 09:09:09 -04:00
|
|
|
return intersection;
|
2016-03-04 06:17:06 -05:00
|
|
|
}
|
|
|
|
|
2016-11-09 10:52:22 -05:00
|
|
|
const IntersectionGenerator &TurnAnalysis::GetIntersectionGenerator() const
|
|
|
|
{
|
|
|
|
return intersection_generator;
|
|
|
|
}
|
2016-05-13 13:18:00 -04:00
|
|
|
|
2016-03-01 16:30:31 -05:00
|
|
|
} // namespace guidance
|
2016-02-25 08:40:26 -05:00
|
|
|
} // namespace extractor
|
2016-02-26 11:33:18 -05:00
|
|
|
} // namespace osrm
|