2016-06-30 03:31:08 -04:00
|
|
|
#include "extractor/guidance/turn_discovery.hpp"
|
2016-07-22 03:08:40 -04:00
|
|
|
#include "extractor/guidance/constants.hpp"
|
2016-12-06 07:22:51 -05:00
|
|
|
#include "util/bearing.hpp"
|
2016-10-20 06:15:36 -04:00
|
|
|
#include "util/coordinate_calculation.hpp"
|
2016-12-02 04:53:22 -05:00
|
|
|
|
|
|
|
using osrm::util::angularDeviation;
|
2016-05-13 13:18:00 -04:00
|
|
|
|
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace extractor
|
|
|
|
{
|
|
|
|
namespace guidance
|
|
|
|
{
|
|
|
|
namespace lanes
|
|
|
|
{
|
|
|
|
|
2016-11-10 10:05:24 -05:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
const constexpr bool USE_LOW_PRECISION_MODE = true;
|
|
|
|
}
|
|
|
|
|
2016-05-13 13:18:00 -04:00
|
|
|
bool findPreviousIntersection(const NodeID node_v,
|
|
|
|
const EdgeID via_edge,
|
2016-11-15 05:21:26 -05:00
|
|
|
const Intersection &intersection,
|
2016-11-09 10:52:22 -05:00
|
|
|
const IntersectionGenerator &intersection_generator,
|
2016-05-13 13:18:00 -04:00
|
|
|
const util::NodeBasedDynamicGraph &node_based_graph,
|
|
|
|
// output parameters
|
|
|
|
NodeID &result_node,
|
|
|
|
EdgeID &result_via_edge,
|
2016-11-18 03:38:26 -05:00
|
|
|
IntersectionView &result_intersection)
|
2016-05-13 13:18:00 -04:00
|
|
|
{
|
|
|
|
/* We need to find the intersection that is located prior to via_edge.
|
|
|
|
|
|
|
|
*
|
|
|
|
* NODE_U -> PREVIOUS_ID -> NODE_V -> VIA_EDGE -> NODE_W:INTERSECTION
|
|
|
|
* NODE_U? <- STRAIGHTMOST <- NODE_V <- UTURN
|
|
|
|
* NODE_U? -> UTURN == PREVIOUSE_ID? -> NODE_V -> VIA_EDGE
|
|
|
|
*
|
|
|
|
* To do so, we first get the intersection atNODE and find the straightmost turn from that
|
|
|
|
* node. This will result in NODE_X. The uturn in the intersection at NODE_X should be
|
|
|
|
* PREVIOUS_ID. To verify that find, we check the intersection using our PREVIOUS_ID candidate
|
|
|
|
* to check the intersection at NODE for via_edge
|
|
|
|
*/
|
|
|
|
const constexpr double COMBINE_DISTANCE_CUTOFF = 30;
|
|
|
|
|
2016-11-09 10:52:22 -05:00
|
|
|
const auto coordinate_extractor = intersection_generator.GetCoordinateExtractor();
|
2016-12-06 07:22:51 -05:00
|
|
|
const auto coordinates_along_via_edge =
|
|
|
|
coordinate_extractor.GetForwardCoordinatesAlongRoad(node_v, via_edge);
|
|
|
|
const auto via_edge_length =
|
|
|
|
util::coordinate_calculation::getLength(coordinates_along_via_edge.begin(),
|
|
|
|
coordinates_along_via_edge.end(),
|
|
|
|
&util::coordinate_calculation::haversineDistance);
|
2016-10-20 06:15:36 -04:00
|
|
|
|
2016-05-13 13:18:00 -04:00
|
|
|
// we check if via-edge is too short. In this case the previous turn cannot influence the turn
|
|
|
|
// at via_edge and the intersection at NODE_W
|
2016-10-20 06:15:36 -04:00
|
|
|
if (via_edge_length > COMBINE_DISTANCE_CUTOFF)
|
2016-05-13 13:18:00 -04:00
|
|
|
return false;
|
|
|
|
|
2017-01-07 08:13:32 -05:00
|
|
|
// Node -> Via_Edge -> Intersection[0 == UTURN] -> reverse_of(via_edge) -> Intersection at
|
|
|
|
// node
|
2016-05-13 13:18:00 -04:00
|
|
|
// (looking at the reverse direction).
|
|
|
|
const auto node_w = node_based_graph.GetTarget(via_edge);
|
2016-11-03 05:18:27 -04:00
|
|
|
const auto u_turn_at_node_w = intersection[0].eid;
|
2016-11-18 03:38:26 -05:00
|
|
|
|
2016-11-15 05:21:26 -05:00
|
|
|
// make sure the ID is actually valid
|
|
|
|
BOOST_ASSERT(node_based_graph.BeginEdges(node_w) <= u_turn_at_node_w &&
|
|
|
|
u_turn_at_node_w <= node_based_graph.EndEdges(node_w));
|
|
|
|
|
|
|
|
// if we can't find the correct road, stop
|
|
|
|
if (node_based_graph.GetTarget(u_turn_at_node_w) != node_v)
|
|
|
|
return false;
|
|
|
|
|
2016-11-10 10:05:24 -05:00
|
|
|
const auto node_v_reverse_intersection =
|
|
|
|
intersection_generator.GetConnectedRoads(node_w, u_turn_at_node_w, USE_LOW_PRECISION_MODE);
|
2016-05-13 13:18:00 -04:00
|
|
|
// Continue along the straightmost turn. If there is no straight turn, we cannot find a valid
|
|
|
|
// previous intersection.
|
|
|
|
const auto straightmost_at_v_in_reverse =
|
2016-11-03 05:18:27 -04:00
|
|
|
node_v_reverse_intersection.findClosestTurn(STRAIGHT_ANGLE);
|
2016-06-30 03:31:08 -04:00
|
|
|
|
|
|
|
// TODO evaluate if narrow turn is the right criterion here... Might be that other angles are
|
|
|
|
// valid
|
2016-12-02 04:53:22 -05:00
|
|
|
if (angularDeviation(straightmost_at_v_in_reverse->angle, STRAIGHT_ANGLE) > GROUP_ANGLE)
|
2016-05-13 13:18:00 -04:00
|
|
|
return false;
|
|
|
|
|
2016-11-03 05:18:27 -04:00
|
|
|
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->eid);
|
2016-11-10 10:05:24 -05:00
|
|
|
const auto node_u_reverse_intersection = intersection_generator.GetConnectedRoads(
|
|
|
|
node_v, straightmost_at_v_in_reverse->eid, USE_LOW_PRECISION_MODE);
|
2016-05-13 13:18:00 -04:00
|
|
|
|
|
|
|
// 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.
|
|
|
|
result_node = node_u;
|
2016-11-03 05:18:27 -04:00
|
|
|
result_via_edge = node_u_reverse_intersection[0].eid;
|
2016-11-15 05:21:26 -05:00
|
|
|
if (node_based_graph.GetTarget(result_via_edge) != node_v)
|
|
|
|
return false;
|
2016-05-13 13:18:00 -04:00
|
|
|
|
|
|
|
// if the edge is not traversable, we obviously don't have a previous intersection or couldn't
|
|
|
|
// find it.
|
|
|
|
if (node_based_graph.GetEdgeData(result_via_edge).reversed)
|
2016-06-30 03:31:08 -04:00
|
|
|
{
|
|
|
|
result_via_edge = SPECIAL_EDGEID;
|
|
|
|
result_node = SPECIAL_NODEID;
|
2016-05-13 13:18:00 -04:00
|
|
|
return false;
|
2016-06-30 03:31:08 -04:00
|
|
|
}
|
2016-05-13 13:18:00 -04:00
|
|
|
|
2016-11-09 10:52:22 -05:00
|
|
|
result_intersection = intersection_generator(node_u, result_via_edge);
|
2016-06-30 03:31:08 -04:00
|
|
|
const auto check_via_edge =
|
|
|
|
result_intersection.end() !=
|
|
|
|
std::find_if(result_intersection.begin(),
|
|
|
|
result_intersection.end(),
|
2016-11-18 03:38:26 -05:00
|
|
|
[via_edge](const IntersectionViewData &road) { return road.eid == via_edge; });
|
2016-06-30 03:31:08 -04:00
|
|
|
|
|
|
|
if (!check_via_edge)
|
|
|
|
{
|
|
|
|
result_via_edge = SPECIAL_EDGEID;
|
|
|
|
result_node = SPECIAL_NODEID;
|
2016-05-13 13:18:00 -04:00
|
|
|
return false;
|
2016-06-30 03:31:08 -04:00
|
|
|
}
|
2016-05-13 13:18:00 -04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace lanes
|
|
|
|
} // namespace guidance
|
|
|
|
} // namespace extractor
|
|
|
|
} // namespace osrm
|