Distinguish between offramps and sliproads.
This commit is contained in:
parent
089e60fa1e
commit
3d03797e53
@ -1,3 +1,10 @@
|
|||||||
|
# 5.2
|
||||||
|
Changes from 5.2.0 RC2
|
||||||
|
|
||||||
|
- Guidance:
|
||||||
|
- improved handling of sliproads (emit turns instead of 'take the ramp')
|
||||||
|
BREAKING: modifies the file format with new internal identifiers
|
||||||
|
|
||||||
# 5.2.0 RC1
|
# 5.2.0 RC1
|
||||||
Changes from 5.1.0
|
Changes from 5.1.0
|
||||||
|
|
||||||
|
117
features/guidance/dedicated-turn-roads.feature
Normal file
117
features/guidance/dedicated-turn-roads.feature
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
@routing @guidance
|
||||||
|
Feature: Slipways and Dedicated Turn Lanes
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the profile "car"
|
||||||
|
Given a grid size of 5 meters
|
||||||
|
|
||||||
|
Scenario: Turn Instead of Ramp
|
||||||
|
Given the node map
|
||||||
|
| | | | | e | |
|
||||||
|
| a | b | | | c | d |
|
||||||
|
| | | | h | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | 1 | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | f | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | g | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| abcd | trunk | first |
|
||||||
|
| bhf | trunk_link | |
|
||||||
|
| ecfg | primary | second |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,g | first,second,second | depart,turn right,arrive |
|
||||||
|
| a,1 | first,, | depart,turn slight right,arrive |
|
||||||
|
|
||||||
|
Scenario: Turn Instead of Ramp
|
||||||
|
Given the node map
|
||||||
|
| | | | | e | |
|
||||||
|
| a | b | | | c | d |
|
||||||
|
| | | | h | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | f | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | g | |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| abcd | motorway | first |
|
||||||
|
| bhf | motorway_link | |
|
||||||
|
| efg | primary | second |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,g | first,,second,second | depart,off ramp slight right,merge slight left,arrive |
|
||||||
|
|
||||||
|
Scenario: Inner city expressway with on road
|
||||||
|
Given the node map
|
||||||
|
| a | b | | | | c |
|
||||||
|
| | | | | f | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | d |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | |
|
||||||
|
| | | | | | e |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name |
|
||||||
|
| abc | primary | road |
|
||||||
|
| bfd | trunk_link | |
|
||||||
|
| cde | trunk | trunk |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,e | road,trunk,trunk | depart,turn right,arrive |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario: Slipway Round U-Turn
|
||||||
|
Given the node map
|
||||||
|
| a | | f |
|
||||||
|
| | | |
|
||||||
|
| b | | e |
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
| | g | |
|
||||||
|
| | | |
|
||||||
|
| c | | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway |
|
||||||
|
| abc | primary | road | yes |
|
||||||
|
| bge | primary_link | | yes |
|
||||||
|
| def | primary | road | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,f | road,road,road | depart,continue uturn,arrive |
|
||||||
|
|
||||||
|
Scenario: Slipway Steep U-Turn
|
||||||
|
Given the node map
|
||||||
|
| a | | f |
|
||||||
|
| | | |
|
||||||
|
| b | | e |
|
||||||
|
| | g | |
|
||||||
|
| | | |
|
||||||
|
| | | |
|
||||||
|
| c | | d |
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | highway | name | oneway |
|
||||||
|
| abc | primary | road | yes |
|
||||||
|
| bge | primary_link | | yes |
|
||||||
|
| def | primary | road | yes |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| a,f | road,road,road | depart,continue uturn,arrive |
|
@ -12,8 +12,8 @@
|
|||||||
#include "util/bearing.hpp"
|
#include "util/bearing.hpp"
|
||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/coordinate_calculation.hpp"
|
#include "util/coordinate_calculation.hpp"
|
||||||
#include "util/guidance/toolkit.hpp"
|
|
||||||
#include "util/guidance/entry_class.hpp"
|
#include "util/guidance/entry_class.hpp"
|
||||||
|
#include "util/guidance/toolkit.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
@ -68,9 +68,7 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
StepManeuver maneuver{source_node.location, bearings.first,
|
StepManeuver maneuver{source_node.location, bearings.first,
|
||||||
bearings.second, extractor::guidance::TurnInstruction::NO_TURN(),
|
bearings.second, extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
WaypointType::Depart, 0};
|
WaypointType::Depart, 0};
|
||||||
Intersection intersection{
|
Intersection intersection{source_node.location, std::vector<short>({bearings.second}),
|
||||||
source_node.location,
|
|
||||||
std::vector<short>({bearings.second}),
|
|
||||||
std::vector<bool>({true}), Intersection::NO_INDEX, 0};
|
std::vector<bool>({true}), Intersection::NO_INDEX, 0};
|
||||||
|
|
||||||
if (leg_data.size() > 0)
|
if (leg_data.size() > 0)
|
||||||
@ -96,6 +94,17 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
const auto name = facade.GetNameForID(step_name_id);
|
const auto name = facade.GetNameForID(step_name_id);
|
||||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||||
|
|
||||||
|
steps.push_back(RouteStep{step_name_id,
|
||||||
|
name,
|
||||||
|
NO_ROTARY_NAME,
|
||||||
|
segment_duration / 10.0,
|
||||||
|
distance,
|
||||||
|
path_point.travel_mode,
|
||||||
|
maneuver,
|
||||||
|
leg_geometry.FrontIndex(segment_index),
|
||||||
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
|
{intersection}});
|
||||||
|
|
||||||
if (leg_data_index + 1 < leg_data.size())
|
if (leg_data_index + 1 < leg_data.size())
|
||||||
{
|
{
|
||||||
step_name_id = leg_data[leg_data_index + 1].name_id;
|
step_name_id = leg_data[leg_data_index + 1].name_id;
|
||||||
@ -104,26 +113,26 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
{
|
{
|
||||||
step_name_id = target_node.name_id;
|
step_name_id = target_node.name_id;
|
||||||
}
|
}
|
||||||
steps.push_back(RouteStep{
|
|
||||||
step_name_id, name, NO_ROTARY_NAME, segment_duration / 10.0, distance,
|
|
||||||
path_point.travel_mode, maneuver, leg_geometry.FrontIndex(segment_index),
|
|
||||||
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
|
|
||||||
|
|
||||||
bearings = detail::getIntermediateBearings(leg_geometry, segment_index);
|
bearings = detail::getIntermediateBearings(leg_geometry, segment_index);
|
||||||
const auto entry_class = facade.GetEntryClass(path_point.entry_classid);
|
const auto entry_class = facade.GetEntryClass(path_point.entry_classid);
|
||||||
const auto bearing_class = facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node));
|
const auto bearing_class =
|
||||||
intersection.in = bearing_class.findMatchingBearing(util::bearing::reverseBearing(bearings.first));
|
facade.GetBearingClass(facade.GetBearingClassID(path_point.turn_via_node));
|
||||||
|
intersection.in = bearing_class.findMatchingBearing(
|
||||||
|
util::bearing::reverseBearing(bearings.first));
|
||||||
intersection.out = bearing_class.findMatchingBearing(bearings.second);
|
intersection.out = bearing_class.findMatchingBearing(bearings.second);
|
||||||
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
intersection.location = facade.GetCoordinateOfNode(path_point.turn_via_node);
|
||||||
intersection.bearings.clear();
|
intersection.bearings.clear();
|
||||||
std::copy(bearing_class.getAvailableBearings().begin(), bearing_class.getAvailableBearings().end(),
|
std::copy(bearing_class.getAvailableBearings().begin(),
|
||||||
|
bearing_class.getAvailableBearings().end(),
|
||||||
std::back_inserter(intersection.bearings));
|
std::back_inserter(intersection.bearings));
|
||||||
intersection.entry.clear();
|
intersection.entry.clear();
|
||||||
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
|
for (auto idx : util::irange<std::size_t>(0, intersection.bearings.size()))
|
||||||
{
|
{
|
||||||
intersection.entry.push_back(entry_class.allowsEntry(idx));
|
intersection.entry.push_back(entry_class.allowsEntry(idx));
|
||||||
}
|
}
|
||||||
maneuver = {intersection.location, bearings.first, bearings.second, path_point.turn_instruction, WaypointType::None, 0};
|
maneuver = {intersection.location, bearings.first, bearings.second,
|
||||||
|
path_point.turn_instruction, WaypointType::None, 0};
|
||||||
segment_index++;
|
segment_index++;
|
||||||
segment_duration = 0;
|
segment_duration = 0;
|
||||||
}
|
}
|
||||||
@ -131,10 +140,16 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
const auto distance = leg_geometry.segment_distances[segment_index];
|
const auto distance = leg_geometry.segment_distances[segment_index];
|
||||||
const int duration = segment_duration + target_duration;
|
const int duration = segment_duration + target_duration;
|
||||||
BOOST_ASSERT(duration >= 0);
|
BOOST_ASSERT(duration >= 0);
|
||||||
steps.push_back(RouteStep{
|
steps.push_back(RouteStep{step_name_id,
|
||||||
step_name_id, facade.GetNameForID(step_name_id), NO_ROTARY_NAME, duration / 10.,
|
facade.GetNameForID(step_name_id),
|
||||||
distance, target_mode, maneuver, leg_geometry.FrontIndex(segment_index),
|
NO_ROTARY_NAME,
|
||||||
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
|
duration / 10.,
|
||||||
|
distance,
|
||||||
|
target_mode,
|
||||||
|
maneuver,
|
||||||
|
leg_geometry.FrontIndex(segment_index),
|
||||||
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
|
{intersection}});
|
||||||
}
|
}
|
||||||
// In this case the source + target are on the same edge segment
|
// In this case the source + target are on the same edge segment
|
||||||
else
|
else
|
||||||
@ -148,30 +163,41 @@ std::vector<RouteStep> assembleSteps(const DataFacadeT &facade,
|
|||||||
int duration = target_duration - source_duration;
|
int duration = target_duration - source_duration;
|
||||||
BOOST_ASSERT(duration >= 0);
|
BOOST_ASSERT(duration >= 0);
|
||||||
|
|
||||||
steps.push_back(RouteStep{
|
steps.push_back(RouteStep{source_node.name_id,
|
||||||
source_node.name_id, facade.GetNameForID(source_node.name_id), NO_ROTARY_NAME,
|
facade.GetNameForID(source_node.name_id),
|
||||||
duration / 10., leg_geometry.segment_distances[segment_index], source_mode,
|
NO_ROTARY_NAME,
|
||||||
std::move(maneuver), leg_geometry.FrontIndex(segment_index),
|
duration / 10.,
|
||||||
leg_geometry.BackIndex(segment_index) + 1, {intersection}});
|
leg_geometry.segment_distances[segment_index],
|
||||||
|
source_mode,
|
||||||
|
std::move(maneuver),
|
||||||
|
leg_geometry.FrontIndex(segment_index),
|
||||||
|
leg_geometry.BackIndex(segment_index) + 1,
|
||||||
|
{intersection}});
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
BOOST_ASSERT(segment_index == number_of_segments - 1);
|
||||||
bearings = detail::getArriveBearings(leg_geometry);
|
bearings = detail::getArriveBearings(leg_geometry);
|
||||||
// This step has length zero, the only reason we need it is the target location
|
// This step has length zero, the only reason we need it is the target location
|
||||||
maneuver = {intersection.location, bearings.first, bearings.second, extractor::guidance::TurnInstruction::NO_TURN(), WaypointType::Arrive, 0};
|
maneuver = {intersection.location, bearings.first,
|
||||||
|
bearings.second, extractor::guidance::TurnInstruction::NO_TURN(),
|
||||||
|
WaypointType::Arrive, 0};
|
||||||
intersection = {
|
intersection = {
|
||||||
target_node.location,
|
target_node.location,
|
||||||
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
|
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
|
||||||
std::vector<bool>({true}), 0, Intersection::NO_INDEX};
|
std::vector<bool>({true}), 0, Intersection::NO_INDEX};
|
||||||
|
|
||||||
BOOST_ASSERT(!leg_geometry.locations.empty());
|
BOOST_ASSERT(!leg_geometry.locations.empty());
|
||||||
steps.push_back(RouteStep{target_node.name_id, facade.GetNameForID(target_node.name_id),
|
steps.push_back(RouteStep{target_node.name_id,
|
||||||
NO_ROTARY_NAME, ZERO_DURATION, ZERO_DISTANCE, target_mode,
|
facade.GetNameForID(target_node.name_id),
|
||||||
std::move(maneuver), leg_geometry.locations.size() - 1,
|
NO_ROTARY_NAME,
|
||||||
|
ZERO_DURATION,
|
||||||
|
ZERO_DISTANCE,
|
||||||
|
target_mode,
|
||||||
|
std::move(maneuver),
|
||||||
|
leg_geometry.locations.size() - 1,
|
||||||
leg_geometry.locations.size(),
|
leg_geometry.locations.size(),
|
||||||
{intersection}});
|
{intersection}});
|
||||||
|
|
||||||
|
|
||||||
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.size() == 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().bearings.size() == 1);
|
||||||
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
BOOST_ASSERT(steps.front().intersections.front().entry.size() == 1);
|
||||||
|
@ -47,6 +47,17 @@ inline bool isRampClass(const FunctionalRoadClass road_class)
|
|||||||
road_class == FunctionalRoadClass::TRUNK_LINK;
|
road_class == FunctionalRoadClass::TRUNK_LINK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Links are usually smaller than ramps, but are sometimes tagged
|
||||||
|
// as MOTORWAY_LINK if they exit/enter a motorway/trunk road.
|
||||||
|
inline bool isLinkClass(const FunctionalRoadClass road_class)
|
||||||
|
{
|
||||||
|
return road_class == FunctionalRoadClass::MOTORWAY_LINK ||
|
||||||
|
road_class == FunctionalRoadClass::TRUNK_LINK ||
|
||||||
|
road_class == FunctionalRoadClass::PRIMARY_LINK ||
|
||||||
|
road_class == FunctionalRoadClass::SECONDARY_LINK ||
|
||||||
|
road_class == FunctionalRoadClass::TERTIARY_LINK;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO augment this with all data required for guidance generation
|
// TODO augment this with all data required for guidance generation
|
||||||
struct RoadClassificationData
|
struct RoadClassificationData
|
||||||
{
|
{
|
||||||
|
@ -26,6 +26,8 @@ const double constexpr MAX_ROUNDABOUT_INTERSECTION_RADIUS = 5;
|
|||||||
const double constexpr MAX_ROUNDABOUT_RADIUS = 15; // 30 m diameter as final distinction
|
const double constexpr MAX_ROUNDABOUT_RADIUS = 15; // 30 m diameter as final distinction
|
||||||
const double constexpr INCREASES_BY_FOURTY_PERCENT = 1.4;
|
const double constexpr INCREASES_BY_FOURTY_PERCENT = 1.4;
|
||||||
|
|
||||||
|
const unsigned constexpr MAX_SLIPROAD_THRESHOLD = 250;
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define OSRM_EXTRACTOR_GUIDANCE_MOTORWAY_HANDLER_HPP_
|
#define OSRM_EXTRACTOR_GUIDANCE_MOTORWAY_HANDLER_HPP_
|
||||||
|
|
||||||
#include "extractor/guidance/intersection.hpp"
|
#include "extractor/guidance/intersection.hpp"
|
||||||
|
#include "extractor/guidance/intersection_generator.hpp"
|
||||||
#include "extractor/guidance/intersection_handler.hpp"
|
#include "extractor/guidance/intersection_handler.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
|
|
||||||
@ -25,7 +26,8 @@ class MotorwayHandler : public IntersectionHandler
|
|||||||
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table,
|
const util::NameTable &name_table,
|
||||||
const SuffixTable &street_name_suffix_table);
|
const SuffixTable &street_name_suffix_table,
|
||||||
|
const IntersectionGenerator &intersection_generator);
|
||||||
~MotorwayHandler() override final;
|
~MotorwayHandler() override final;
|
||||||
|
|
||||||
// check whether the handler can actually handle the intersection
|
// check whether the handler can actually handle the intersection
|
||||||
@ -39,10 +41,14 @@ class MotorwayHandler : public IntersectionHandler
|
|||||||
Intersection intersection) const override final;
|
Intersection intersection) const override final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Intersection handleSliproads(const NodeID intersection_node_id,
|
||||||
|
Intersection intersection) const;
|
||||||
Intersection fromMotorway(const EdgeID via_edge, Intersection intersection) const;
|
Intersection fromMotorway(const EdgeID via_edge, Intersection intersection) const;
|
||||||
Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
|
Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
|
||||||
|
|
||||||
Intersection fallback(Intersection intersection) const;
|
Intersection fallback(Intersection intersection) const;
|
||||||
|
|
||||||
|
const IntersectionGenerator &intersection_generator;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
@ -59,6 +59,9 @@ class TurnAnalysis
|
|||||||
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
||||||
Intersection
|
Intersection
|
||||||
setTurnTypes(const NodeID from, const EdgeID via_edge, Intersection intersection) const;
|
setTurnTypes(const NodeID from, const EdgeID via_edge, Intersection intersection) const;
|
||||||
|
|
||||||
|
Intersection handleSliproads(const NodeID intersection_node_id,
|
||||||
|
Intersection intersection) const;
|
||||||
}; // class TurnAnalysis
|
}; // class TurnAnalysis
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
|
@ -20,7 +20,6 @@ namespace detail
|
|||||||
const constexpr uint8_t num_direction_modifiers = 8;
|
const constexpr uint8_t num_direction_modifiers = 8;
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
|
|
||||||
// direction modifiers based on angle
|
// direction modifiers based on angle
|
||||||
namespace DirectionModifier
|
namespace DirectionModifier
|
||||||
{
|
{
|
||||||
@ -54,15 +53,20 @@ const constexpr Enum EnterRotary = 12; // Enter a rotary
|
|||||||
const constexpr Enum EnterAndExitRotary = 13; // Touching a rotary
|
const constexpr Enum EnterAndExitRotary = 13; // Touching a rotary
|
||||||
const constexpr Enum EnterRoundaboutIntersection = 14; // Entering a small Roundabout
|
const constexpr Enum EnterRoundaboutIntersection = 14; // Entering a small Roundabout
|
||||||
const constexpr Enum EnterAndExitRoundaboutIntersection = 15; // Touching a roundabout
|
const constexpr Enum EnterAndExitRoundaboutIntersection = 15; // Touching a roundabout
|
||||||
|
|
||||||
|
// Values below here are silent instructions
|
||||||
const constexpr Enum NoTurn = 16; // end of segment without turn/middle of a segment
|
const constexpr Enum NoTurn = 16; // end of segment without turn/middle of a segment
|
||||||
const constexpr Enum Suppressed = 17; // location that suppresses a turn
|
const constexpr Enum Suppressed = 17; // location that suppresses a turn
|
||||||
const constexpr Enum EnterRoundaboutAtExit = 18; // Entering a small Roundabout at a countable exit
|
const constexpr Enum EnterRoundaboutAtExit = 18; // Entering a small Roundabout at a countable exit
|
||||||
const constexpr Enum ExitRoundabout = 19; // Exiting a small Roundabout
|
const constexpr Enum ExitRoundabout = 19; // Exiting a small Roundabout
|
||||||
const constexpr Enum EnterRotaryAtExit = 20; // Enter A Rotary at a countable exit
|
const constexpr Enum EnterRotaryAtExit = 20; // Enter A Rotary at a countable exit
|
||||||
const constexpr Enum ExitRotary = 21; // Exit a rotary
|
const constexpr Enum ExitRotary = 21; // Exit a rotary
|
||||||
const constexpr Enum EnterRoundaboutIntersectionAtExit = 22; // Entering a small Roundabout at a countable exit
|
const constexpr Enum EnterRoundaboutIntersectionAtExit =
|
||||||
|
22; // Entering a small Roundabout at a countable exit
|
||||||
const constexpr Enum ExitRoundaboutIntersection = 23; // Exiting a small Roundabout
|
const constexpr Enum ExitRoundaboutIntersection = 23; // Exiting a small Roundabout
|
||||||
const constexpr Enum StayOnRoundabout = 24; // Continue on Either a small or a large Roundabout
|
const constexpr Enum StayOnRoundabout = 24; // Continue on Either a small or a large Roundabout
|
||||||
|
const constexpr Enum Sliproad =
|
||||||
|
25; // Something that looks like a ramp, but is actually just a small sliproad
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn angle in 1.40625 degree -> 128 == 180 degree
|
// turn angle in 1.40625 degree -> 128 == 180 degree
|
||||||
@ -87,7 +91,8 @@ struct TurnInstruction
|
|||||||
return TurnInstruction(TurnType::NoTurn, DirectionModifier::UTurn);
|
return TurnInstruction(TurnType::NoTurn, DirectionModifier::UTurn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TurnInstruction REMAIN_ROUNDABOUT(const RoundaboutType, const DirectionModifier::Enum modifier)
|
static TurnInstruction REMAIN_ROUNDABOUT(const RoundaboutType,
|
||||||
|
const DirectionModifier::Enum modifier)
|
||||||
{
|
{
|
||||||
return TurnInstruction(TurnType::StayOnRoundabout, modifier);
|
return TurnInstruction(TurnType::StayOnRoundabout, modifier);
|
||||||
}
|
}
|
||||||
@ -104,8 +109,8 @@ struct TurnInstruction
|
|||||||
static TurnInstruction EXIT_ROUNDABOUT(const RoundaboutType roundabout_type,
|
static TurnInstruction EXIT_ROUNDABOUT(const RoundaboutType roundabout_type,
|
||||||
const DirectionModifier::Enum modifier)
|
const DirectionModifier::Enum modifier)
|
||||||
{
|
{
|
||||||
const constexpr TurnType::Enum exit_instruction[] = {TurnType::Invalid, TurnType::ExitRoundabout,
|
const constexpr TurnType::Enum exit_instruction[] = {
|
||||||
TurnType::ExitRotary,
|
TurnType::Invalid, TurnType::ExitRoundabout, TurnType::ExitRotary,
|
||||||
TurnType::ExitRoundaboutIntersection};
|
TurnType::ExitRoundaboutIntersection};
|
||||||
return {exit_instruction[static_cast<int>(roundabout_type)], modifier};
|
return {exit_instruction[static_cast<int>(roundabout_type)], modifier};
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
#include <limits>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
// OpenStreetMap node ids are higher than 2^32
|
// OpenStreetMap node ids are higher than 2^32
|
||||||
OSRM_STRONG_TYPEDEF(std::uint64_t, OSMNodeID)
|
OSRM_STRONG_TYPEDEF(std::uint64_t, OSMNodeID)
|
||||||
@ -56,6 +56,7 @@ using OSMEdgeID_weak = std::uint64_t;
|
|||||||
|
|
||||||
using NodeID = unsigned int;
|
using NodeID = unsigned int;
|
||||||
using EdgeID = unsigned int;
|
using EdgeID = unsigned int;
|
||||||
|
using NameID = std::uint32_t;
|
||||||
using EdgeWeight = int;
|
using EdgeWeight = int;
|
||||||
|
|
||||||
using BearingClassID = std::uint32_t;
|
using BearingClassID = std::uint32_t;
|
||||||
|
@ -42,7 +42,8 @@ const constexpr char *turn_type_names[] = {
|
|||||||
"on ramp", "off ramp", "fork", "end of road", "notification",
|
"on ramp", "off ramp", "fork", "end of road", "notification",
|
||||||
"roundabout", "roundabout", "rotary", "rotary", "roundabout turn",
|
"roundabout", "roundabout", "rotary", "rotary", "roundabout turn",
|
||||||
"roundabout turn", "invalid", "invalid", "invalid", "invalid",
|
"roundabout turn", "invalid", "invalid", "invalid", "invalid",
|
||||||
"invalid", "invalid", "invalid", "invalid", "invalid"};
|
"invalid", "invalid", "invalid", "invalid", "invalid",
|
||||||
|
"invalid"};
|
||||||
|
|
||||||
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
|
const constexpr char *waypoint_type_names[] = {"invalid", "arrive", "depart"};
|
||||||
|
|
||||||
@ -150,20 +151,19 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
|
|||||||
return step_maneuver;
|
return step_maneuver;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::json::Object
|
util::json::Object makeIntersection(const guidance::Intersection &intersection)
|
||||||
makeIntersection(const guidance::Intersection &intersection)
|
|
||||||
{
|
{
|
||||||
util::json::Object result;
|
util::json::Object result;
|
||||||
util::json::Array bearings;
|
util::json::Array bearings;
|
||||||
util::json::Array entry;
|
util::json::Array entry;
|
||||||
|
|
||||||
bearings.values.reserve(intersection.bearings.size());
|
bearings.values.reserve(intersection.bearings.size());
|
||||||
std::copy(intersection.bearings.begin(), intersection.bearings.end(), std::back_inserter(bearings.values));
|
std::copy(intersection.bearings.begin(), intersection.bearings.end(),
|
||||||
|
std::back_inserter(bearings.values));
|
||||||
|
|
||||||
entry.values.reserve(intersection.entry.size());
|
entry.values.reserve(intersection.entry.size());
|
||||||
std::transform(intersection.entry.begin(), intersection.entry.end(),
|
std::transform(intersection.entry.begin(), intersection.entry.end(),
|
||||||
std::back_inserter(entry.values), [](const bool has_entry) -> util::json::Value
|
std::back_inserter(entry.values), [](const bool has_entry) -> util::json::Value {
|
||||||
{
|
|
||||||
if (has_entry)
|
if (has_entry)
|
||||||
return util::json::True();
|
return util::json::True();
|
||||||
else
|
else
|
||||||
|
@ -41,8 +41,8 @@ void print(const std::vector<RouteStep> &steps)
|
|||||||
int segment = 0;
|
int segment = 0;
|
||||||
for (const auto &step : steps)
|
for (const auto &step : steps)
|
||||||
{
|
{
|
||||||
std::cout << "\t[" << ++segment << "]: " << step.maneuver.instruction.type << " "
|
std::cout << "\t[" << ++segment << "]: " << static_cast<int>(step.maneuver.instruction.type)
|
||||||
<< step.maneuver.instruction.direction_modifier << " "
|
<< " " << static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
|
||||||
<< static_cast<int>(step.maneuver.waypoint_type) << " Duration: " << step.duration
|
<< static_cast<int>(step.maneuver.waypoint_type) << " Duration: " << step.duration
|
||||||
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
|
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
|
||||||
<< step.geometry_end << " exit: " << step.maneuver.exit
|
<< step.geometry_end << " exit: " << step.maneuver.exit
|
||||||
@ -63,6 +63,37 @@ void print(const std::vector<RouteStep> &steps)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute the angle between two bearings on a normal turn circle
|
||||||
|
//
|
||||||
|
// Bearings Angles
|
||||||
|
//
|
||||||
|
// 0 180
|
||||||
|
// 315 45 225 135
|
||||||
|
//
|
||||||
|
// 270 x 90 270 x 90
|
||||||
|
//
|
||||||
|
// 225 135 315 45
|
||||||
|
// 180 0
|
||||||
|
//
|
||||||
|
// A turn from north to north-east offerst bearing 0 and 45 has to be translated
|
||||||
|
// into a turn of 135 degrees. The same holdes for 90 - 135 (east to south
|
||||||
|
// east).
|
||||||
|
// For north, the transformation works by angle = 540 (360 + 180) - exit_bearing
|
||||||
|
// % 360;
|
||||||
|
// All other cases are handled by first rotating both bearings to an
|
||||||
|
// entry_bearing of 0.
|
||||||
|
double turn_angle(const double entry_bearing, const double exit_bearing)
|
||||||
|
{
|
||||||
|
const double offset = 360 - entry_bearing;
|
||||||
|
const double rotated_exit = [](double bearing, const double offset) {
|
||||||
|
bearing += offset;
|
||||||
|
return bearing > 360 ? bearing - 360 : bearing;
|
||||||
|
}(exit_bearing, offset);
|
||||||
|
|
||||||
|
const auto angle = 540 - rotated_exit;
|
||||||
|
return angle > 360 ? angle - 360 : angle;
|
||||||
|
}
|
||||||
|
|
||||||
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
RouteStep forwardInto(RouteStep destination, const RouteStep &source)
|
||||||
{
|
{
|
||||||
// Merge a turn into a silent turn
|
// Merge a turn into a silent turn
|
||||||
@ -232,37 +263,9 @@ void closeOffRoundabout(const bool on_roundabout,
|
|||||||
propagation_step.maneuver.instruction.type ==
|
propagation_step.maneuver.instruction.type ==
|
||||||
TurnType::EnterRoundaboutIntersectionAtExit)
|
TurnType::EnterRoundaboutIntersectionAtExit)
|
||||||
{
|
{
|
||||||
// Compute the angle between two bearings on a normal turn circle
|
|
||||||
//
|
|
||||||
// Bearings Angles
|
|
||||||
//
|
|
||||||
// 0 180
|
|
||||||
// 315 45 225 135
|
|
||||||
//
|
|
||||||
// 270 x 90 270 x 90
|
|
||||||
//
|
|
||||||
// 225 135 315 45
|
|
||||||
// 180 0
|
|
||||||
//
|
|
||||||
// A turn from north to north-east offerst bearing 0 and 45 has to be translated
|
|
||||||
// into a turn of 135 degrees. The same holdes for 90 - 135 (east to south
|
|
||||||
// east).
|
|
||||||
// For north, the transformation works by angle = 540 (360 + 180) - exit_bearing
|
|
||||||
// % 360;
|
|
||||||
// All other cases are handled by first rotating both bearings to an
|
|
||||||
// entry_bearing of 0.
|
|
||||||
BOOST_ASSERT(!propagation_step.intersections.empty());
|
BOOST_ASSERT(!propagation_step.intersections.empty());
|
||||||
const double angle =
|
const double angle =
|
||||||
[](const double entry_bearing, const double exit_bearing) {
|
turn_angle(util::bearing::reverseBearing(
|
||||||
const double offset = 360 - entry_bearing;
|
|
||||||
const double rotated_exit = [](double bearing, const double offset) {
|
|
||||||
bearing += offset;
|
|
||||||
return bearing > 360 ? bearing - 360 : bearing;
|
|
||||||
}(exit_bearing, offset);
|
|
||||||
|
|
||||||
const auto angle = 540 - rotated_exit;
|
|
||||||
return angle > 360 ? angle - 360 : angle;
|
|
||||||
}(util::bearing::reverseBearing(
|
|
||||||
entry_intersection.bearings[entry_intersection.in]),
|
entry_intersection.bearings[entry_intersection.in]),
|
||||||
exit_bearing);
|
exit_bearing);
|
||||||
|
|
||||||
@ -417,6 +420,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
steps[one_back_index].name = steps[two_back_index].name;
|
steps[one_back_index].name = steps[two_back_index].name;
|
||||||
|
steps[one_back_index].name_id = steps[two_back_index].name_id;
|
||||||
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
|
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
|
||||||
steps[one_back_index].maneuver.instruction.direction_modifier =
|
steps[one_back_index].maneuver.instruction.direction_modifier =
|
||||||
DirectionModifier::UTurn;
|
DirectionModifier::UTurn;
|
||||||
@ -580,6 +584,15 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
instruction.direction_modifier == DirectionModifier::Straight);
|
instruction.direction_modifier == DirectionModifier::Straight);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Special case handling: if the phantomnode landed on a sliproad, we
|
||||||
|
// change this into a 'turn' instruction. Sliproads are small ramps
|
||||||
|
// between roads, not ramps.
|
||||||
|
if (steps.size() >= 3 &&
|
||||||
|
steps[steps.size() - 2].maneuver.instruction.type == TurnType::Sliproad)
|
||||||
|
{
|
||||||
|
steps[steps.size() - 2].maneuver.instruction.type = TurnType::Turn;
|
||||||
|
}
|
||||||
|
|
||||||
// first and last instructions are waypoints that cannot be collapsed
|
// first and last instructions are waypoints that cannot be collapsed
|
||||||
for (std::size_t step_index = 2; step_index < steps.size(); ++step_index)
|
for (std::size_t step_index = 2; step_index < steps.size(); ++step_index)
|
||||||
{
|
{
|
||||||
@ -595,9 +608,39 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
|
|||||||
const auto two_back_index = getPreviousIndex(one_back_index);
|
const auto two_back_index = getPreviousIndex(one_back_index);
|
||||||
BOOST_ASSERT(two_back_index < steps.size());
|
BOOST_ASSERT(two_back_index < steps.size());
|
||||||
|
|
||||||
|
// Handle sliproads from motorways in urban areas
|
||||||
|
if (one_back_step.maneuver.instruction.type == TurnType::Sliproad)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Handle possible u-turns between highways that look like slip-roads
|
||||||
|
if (steps[two_back_index].name_id == steps[step_index].name_id &&
|
||||||
|
steps[step_index].name_id != INVALID_NAMEID)
|
||||||
|
{
|
||||||
|
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
|
||||||
|
}
|
||||||
|
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
||||||
|
steps[one_back_index].name_id = steps[step_index].name_id;
|
||||||
|
steps[one_back_index].name = steps[step_index].name;
|
||||||
|
|
||||||
|
const auto exit_intersection = steps[step_index].intersections.front();
|
||||||
|
const auto exit_bearing = exit_intersection.bearings[exit_intersection.out];
|
||||||
|
|
||||||
|
const auto entry_intersection = steps[one_back_index].intersections.front();
|
||||||
|
const auto entry_bearing = entry_intersection.bearings[entry_intersection.in];
|
||||||
|
|
||||||
|
const double angle =
|
||||||
|
turn_angle(util::bearing::reverseBearing(entry_bearing), exit_bearing);
|
||||||
|
steps[one_back_index].maneuver.instruction.direction_modifier =
|
||||||
|
::osrm::util::guidance::getTurnDirection(angle);
|
||||||
|
invalidateStep(steps[step_index]);
|
||||||
|
}
|
||||||
// Due to empty segments, we can get name-changes from A->A
|
// Due to empty segments, we can get name-changes from A->A
|
||||||
// These have to be handled in post-processing
|
// These have to be handled in post-processing
|
||||||
if (isCollapsableInstruction(current_step.maneuver.instruction) &&
|
else if (isCollapsableInstruction(current_step.maneuver.instruction) &&
|
||||||
current_step.name == steps[one_back_index].name)
|
current_step.name == steps[one_back_index].name)
|
||||||
{
|
{
|
||||||
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
|
||||||
|
@ -45,8 +45,10 @@ inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_base
|
|||||||
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
const std::vector<QueryNode> &node_info_list,
|
const std::vector<QueryNode> &node_info_list,
|
||||||
const util::NameTable &name_table,
|
const util::NameTable &name_table,
|
||||||
const SuffixTable &street_name_suffix_table)
|
const SuffixTable &street_name_suffix_table,
|
||||||
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
|
const IntersectionGenerator &intersection_generator)
|
||||||
|
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
|
||||||
|
intersection_generator(intersection_generator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,8 +253,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
|||||||
else if (road.turn.angle < continue_angle)
|
else if (road.turn.angle < continue_angle)
|
||||||
{
|
{
|
||||||
road.turn.instruction = {
|
road.turn.instruction = {
|
||||||
detail::isRampClass(road.turn.eid, node_based_graph)
|
detail::isRampClass(road.turn.eid, node_based_graph) ? TurnType::OffRamp
|
||||||
? TurnType::OffRamp
|
|
||||||
: TurnType::Turn,
|
: TurnType::Turn,
|
||||||
(road.turn.angle < 145) ? DirectionModifier::Right
|
(road.turn.angle < 145) ? DirectionModifier::Right
|
||||||
: DirectionModifier::SlightRight};
|
: DirectionModifier::SlightRight};
|
||||||
@ -260,8 +261,7 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
|
|||||||
else if (road.turn.angle > continue_angle)
|
else if (road.turn.angle > continue_angle)
|
||||||
{
|
{
|
||||||
road.turn.instruction = {
|
road.turn.instruction = {
|
||||||
detail::isRampClass(road.turn.eid, node_based_graph)
|
detail::isRampClass(road.turn.eid, node_based_graph) ? TurnType::OffRamp
|
||||||
? TurnType::OffRamp
|
|
||||||
: TurnType::Turn,
|
: TurnType::Turn,
|
||||||
(road.turn.angle > 215) ? DirectionModifier::Left
|
(road.turn.angle > 215) ? DirectionModifier::Left
|
||||||
: DirectionModifier::SlightLeft};
|
: DirectionModifier::SlightLeft};
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
using osrm::util::guidance::getTurnDirection;
|
using osrm::util::guidance::getTurnDirection;
|
||||||
|
|
||||||
@ -42,8 +42,16 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
|||||||
barrier_nodes,
|
barrier_nodes,
|
||||||
node_info_list,
|
node_info_list,
|
||||||
compressed_edge_container),
|
compressed_edge_container),
|
||||||
roundabout_handler(node_based_graph, node_info_list, compressed_edge_container, name_table, street_name_suffix_table),
|
roundabout_handler(node_based_graph,
|
||||||
motorway_handler(node_based_graph, node_info_list, name_table,street_name_suffix_table),
|
node_info_list,
|
||||||
|
compressed_edge_container,
|
||||||
|
name_table,
|
||||||
|
street_name_suffix_table),
|
||||||
|
motorway_handler(node_based_graph,
|
||||||
|
node_info_list,
|
||||||
|
name_table,
|
||||||
|
street_name_suffix_table,
|
||||||
|
intersection_generator),
|
||||||
turn_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
|
turn_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -73,6 +81,9 @@ std::vector<TurnOperation> TurnAnalysis::getTurns(const NodeID from_nid, const E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle sliproads
|
||||||
|
intersection = handleSliproads(via_eid, std::move(intersection));
|
||||||
|
|
||||||
std::vector<TurnOperation> turns;
|
std::vector<TurnOperation> turns;
|
||||||
for (auto road : intersection)
|
for (auto road : intersection)
|
||||||
if (road.entry_allowed)
|
if (road.entry_allowed)
|
||||||
@ -105,6 +116,88 @@ TurnAnalysis::setTurnTypes(const NodeID from_nid, const EdgeID, Intersection int
|
|||||||
return intersection;
|
return intersection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "Sliproads" occur when we've got a link between two roads (MOTORWAY_LINK, etc), but
|
||||||
|
// the two roads are *also* directly connected shortly afterwards.
|
||||||
|
// In these cases, we tag the turn-type as "sliproad", and then in post-processing
|
||||||
|
// we emit a "turn", instead of "take the ramp"+"merge"
|
||||||
|
Intersection TurnAnalysis::handleSliproads(const EdgeID source_edge_id,
|
||||||
|
Intersection intersection) const
|
||||||
|
{
|
||||||
|
|
||||||
|
auto intersection_node_id = node_based_graph.GetTarget(source_edge_id);
|
||||||
|
|
||||||
|
const auto linkTest = [this](const ConnectedRoad &road) {
|
||||||
|
return isLinkClass(
|
||||||
|
node_based_graph.GetEdgeData(road.turn.eid).road_classification.road_class) &&
|
||||||
|
road.entry_allowed &&
|
||||||
|
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < NARROW_TURN_ANGLE;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool hasRamp =
|
||||||
|
std::find_if(intersection.begin(), intersection.end(), linkTest) != intersection.end();
|
||||||
|
if (!hasRamp)
|
||||||
|
return intersection;
|
||||||
|
|
||||||
|
const auto source_edge_data = node_based_graph.GetEdgeData(source_edge_id);
|
||||||
|
|
||||||
|
// Find the continuation of the intersection we're on
|
||||||
|
auto next_road = std::find_if(
|
||||||
|
intersection.begin(), intersection.end(),
|
||||||
|
[this, source_edge_data](const ConnectedRoad &road) {
|
||||||
|
const auto road_edge_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||||
|
// Test to see if the source edge and the one we're looking at are the same road
|
||||||
|
return road_edge_data.road_classification.road_class ==
|
||||||
|
source_edge_data.road_classification.road_class &&
|
||||||
|
road_edge_data.name_id != INVALID_NAME_ID &&
|
||||||
|
road_edge_data.name_id == source_edge_data.name_id && road.entry_allowed &&
|
||||||
|
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE;
|
||||||
|
});
|
||||||
|
|
||||||
|
const bool hasNext = next_road != intersection.end();
|
||||||
|
|
||||||
|
if (!hasNext)
|
||||||
|
{
|
||||||
|
return intersection;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Threshold check, if the intersection is too far away, don't bother continuing
|
||||||
|
const auto &next_road_data = node_based_graph.GetEdgeData(next_road->turn.eid);
|
||||||
|
if (next_road_data.distance > MAX_SLIPROAD_THRESHOLD)
|
||||||
|
{
|
||||||
|
return intersection;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto next_road_next_intersection =
|
||||||
|
intersection_generator(intersection_node_id, next_road->turn.eid);
|
||||||
|
|
||||||
|
std::unordered_set<NameID> target_road_names;
|
||||||
|
|
||||||
|
for (const auto &road : next_road_next_intersection)
|
||||||
|
{
|
||||||
|
const auto &target_data = node_based_graph.GetEdgeData(road.turn.eid);
|
||||||
|
target_road_names.insert(target_data.name_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &road : intersection)
|
||||||
|
{
|
||||||
|
if (linkTest(road))
|
||||||
|
{
|
||||||
|
auto target_intersection = intersection_generator(intersection_node_id, road.turn.eid);
|
||||||
|
for (const auto &candidate_road : target_intersection)
|
||||||
|
{
|
||||||
|
const auto &candidate_data = node_based_graph.GetEdgeData(candidate_road.turn.eid);
|
||||||
|
if (target_road_names.count(candidate_data.name_id) > 0)
|
||||||
|
{
|
||||||
|
road.turn.instruction.type = TurnType::Sliproad;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return intersection;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace guidance
|
} // namespace guidance
|
||||||
} // namespace extractor
|
} // namespace extractor
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
Loading…
Reference in New Issue
Block a user