diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 38d136978..1b35e02e5 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -152,7 +152,6 @@ class RouteAPI : public BaseAPI leg_geometry.locations.begin() + step.geometry_end)); }); } - return json::makeRoute(route, json::makeRouteLegs(std::move(legs), std::move(step_geometries)), std::move(json_overview)); diff --git a/include/engine/guidance/guidance_toolkit.hpp b/include/engine/guidance/guidance_toolkit.hpp index 2bd121b74..5f68e3574 100644 --- a/include/engine/guidance/guidance_toolkit.hpp +++ b/include/engine/guidance/guidance_toolkit.hpp @@ -171,13 +171,17 @@ inline bool entersRoundabout(const TurnInstruction instruction) return (instruction.type == TurnType::EnterRoundabout || instruction.type == TurnType::EnterRotary || instruction.type == TurnType::EnterRoundaboutAtExit || - instruction.type == TurnType::EnterRotaryAtExit); + instruction.type == TurnType::EnterRotaryAtExit || + instruction.type == TurnType::EnterAndExitRoundabout || + instruction.type == TurnType::EnterAndExitRotary); } inline bool leavesRoundabout(const TurnInstruction instruction) { return (instruction.type == TurnType::ExitRoundabout || - instruction.type == TurnType::ExitRotary); + instruction.type == TurnType::ExitRotary || + instruction.type == TurnType::EnterAndExitRoundabout || + instruction.type == TurnType::EnterAndExitRotary); } inline bool staysOnRoundabout(const TurnInstruction instruction) @@ -384,7 +388,7 @@ inline DirectionModifier bearingToDirectionModifier(const std::string &bearing) inline DirectionModifier bearingToDirectionModifier(const double angle) { - return bearingToDirectionModifier( util::bearing::get(angle) ); + return bearingToDirectionModifier(util::bearing::get(angle)); } inline bool isHighway(FunctionalRoadClass road_class) diff --git a/include/engine/guidance/instruction_symbols.hpp b/include/engine/guidance/instruction_symbols.hpp deleted file mode 100644 index 42ea3fbd5..000000000 --- a/include/engine/guidance/instruction_symbols.hpp +++ /dev/null @@ -1,243 +0,0 @@ -#ifndef OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP -#define OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP - -#include "guidance/turn_instruction.hpp" -#include "guidance/guidance_toolkit.hpp" - -#include "util/simple_logger.hpp" - -namespace osrm -{ -namespace engine -{ -namespace guidance -{ - -enum class InstructionSymbol : unsigned char -{ - NoTurn = 0, - GoStraight, - TurnSlightRight, - TurnRight, - TurnSharpRight, - UTurn, - TurnSharpLeft, - TurnLeft, - TurnSlightLeft, - ReachViaLocation, - HeadOn, - EnterRoundAbout, - LeaveRoundAbout, - StayOnRoundAbout, - StartAtEndOfStreet, - ReachedYourDestination, - NameChanges, - EnterAgainstAllowedDirection, - LeaveAgainstAllowedDirection, - InverseAccessRestrictionFlag = 127, - AccessRestrictionFlag = 128, - AccessRestrictionPenalty = 129 -}; - -inline InstructionSymbol directTranslation(const DirectionModifier direction_modifier) -{ - const constexpr InstructionSymbol translation[] = { - InstructionSymbol::UTurn, InstructionSymbol::TurnSharpRight, - InstructionSymbol::TurnRight, InstructionSymbol::TurnSlightRight, - InstructionSymbol::GoStraight, InstructionSymbol::TurnSlightLeft, - InstructionSymbol::TurnLeft, InstructionSymbol::TurnSharpLeft}; - return translation[direction_modifier]; -} - -inline bool canTranslateDirectly(const TurnType type) -{ - return type == TurnType::Continue // remain on a street - || type == TurnType::NewName // no turn, but name changes - || type == TurnType::Turn // basic turn - || type == TurnType::Ramp // special turn (highway ramp exits) - || type == TurnType::Fork // fork road splitting up - || type == TurnType::EndOfRoad || type == TurnType::Restriction || - type == TurnType::Merge || type == TurnType::Notification; -} - -inline InstructionSymbol getSymbol(const TurnInstruction instruction) -{ - if (canTranslateDirectly(instruction.type)) - { - return directTranslation(instruction.direction_modifier); - } - else if (instruction.type == TurnType::EnterRoundabout || - instruction.type == TurnType::EnterRotary) - { - return InstructionSymbol::EnterRoundAbout; - } - else - { - util::SimpleLogger().Write(logDEBUG) - << "Unreasonable request for symbol: " - << std::to_string(static_cast(instruction.type)) << " " - << std::to_string(static_cast(instruction.direction_modifier)); - return InstructionSymbol::NoTurn; - } -} - -inline InstructionSymbol getLocationSymbol(const LocationType type) -{ - if (type == LocationType::Start) - return InstructionSymbol::HeadOn; - if (type == LocationType::Intermediate) - return InstructionSymbol::ReachViaLocation; - if (type == LocationType::Destination) - return InstructionSymbol::ReachedYourDestination; - return InstructionSymbol::NoTurn; -} - -#if 0 -// shiftable turns to left and right -const constexpr bool shiftable_left[] = {false, false, true, true, true, false, false, true, true}; -const constexpr bool shiftable_right[] = {false, false, true, true, false, false, true, true, true}; - -inline TurnInstruction shiftTurnToLeft(TurnInstruction turn) -{ - BOOST_ASSERT_MSG(static_cast(turn) < 9, - "Shift turn only supports basic turn instructions"); - if (turn > TurnInstruction::TurnSlightLeft) - return turn; - else - return shiftable_left[static_cast(turn)] - ? (static_cast(static_cast(turn) - 1)) - : turn; -} - -inline TurnInstruction shiftTurnToRight(TurnInstruction turn) -{ - BOOST_ASSERT_MSG(static_cast(turn) < 9, - "Shift turn only supports basic turn instructions"); - if (turn > TurnInstruction::TurnSlightLeft) - return turn; - else - return shiftable_right[static_cast(turn)] - ? (static_cast(static_cast(turn) + 1)) - : turn; -} - -inline double angularDeviation(const double angle, const double from) -{ - const double deviation = std::abs(angle - from); - return std::min(360 - deviation, deviation); -} - -inline double getAngularPenalty(const double angle, TurnInstruction instruction) -{ - BOOST_ASSERT_MSG(static_cast(instruction) < 9, - "Angular penalty only supports basic turn instructions"); - const double center[] = {180, 180, 135, 90, 45, - 0, 315, 270, 225}; // centers of turns from getTurnDirection - return angularDeviation(center[static_cast(instruction)], angle); -} - -inline double getTurnConfidence(const double angle, TurnInstruction instruction) -{ - - // special handling of U-Turns and Roundabout - if (instruction >= TurnInstruction::HeadOn || instruction == TurnInstruction::UTurn || - instruction == TurnInstruction::NoTurn || instruction == TurnInstruction::EnterRoundAbout || - instruction == TurnInstruction::StayOnRoundAbout || instruction == TurnInstruction::LeaveRoundAbout ) - return 1.0; - - BOOST_ASSERT_MSG(static_cast(instruction) < 9, - "Turn confidence only supports basic turn instructions"); - const double deviations[] = {10, 10, 35, 50, 45, 0, 45, 50, 35}; - const double difference = getAngularPenalty(angle, instruction); - const double max_deviation = deviations[static_cast(instruction)]; - return 1.0 - (difference / max_deviation) * (difference / max_deviation); -} - -// Translates between angles and their human-friendly directional representation -inline TurnInstruction getTurnDirection(const double angle) -{ - // An angle of zero is a u-turn - // 180 goes perfectly straight - // 0-180 are right turns - // 180-360 are left turns - if (angle > 0 && angle < 60) - return TurnInstruction::TurnSharpRight; - if (angle >= 60 && angle < 140) - return TurnInstruction::TurnRight; - if (angle >= 140 && angle < 170) - return TurnInstruction::TurnSlightRight; - if (angle >= 170 && angle <= 190) - return TurnInstruction::GoStraight; - if (angle > 190 && angle <= 220) - return TurnInstruction::TurnSlightLeft; - if (angle > 220 && angle <= 300) - return TurnInstruction::TurnLeft; - if (angle > 300 && angle < 360) - return TurnInstruction::TurnSharpLeft; - return TurnInstruction::UTurn; -} - -// Decides if a turn is needed to be done for the current instruction -inline bool isTurnNecessary(const TurnInstruction turn_instruction) -{ - if (TurnInstruction::NoTurn == turn_instruction || - TurnInstruction::StayOnRoundAbout == turn_instruction) - { - return false; - } - return true; -} - -inline bool resolve(TurnInstruction &to_resolve, const TurnInstruction neighbor, bool resolve_right) -{ - const auto shifted_turn = - resolve_right ? shiftTurnToRight(to_resolve) : shiftTurnToLeft(to_resolve); - if (shifted_turn == neighbor || shifted_turn == to_resolve) - return false; - - to_resolve = shifted_turn; - return true; -} - -inline bool resolveTransitive(TurnInstruction &first, - TurnInstruction &second, - const TurnInstruction third, - bool resolve_right) -{ - if (resolve(second, third, resolve_right)) - { - first = resolve_right ? shiftTurnToRight(first) : shiftTurnToLeft(first); - return true; - } - return false; -} - -inline bool isSlightTurn(const TurnInstruction turn) -{ - return turn == TurnInstruction::GoStraight || turn == TurnInstruction::TurnSlightRight || - turn == TurnInstruction::TurnSlightLeft || turn == TurnInstruction::NoTurn; -} - -inline bool isSharpTurn(const TurnInstruction turn) -{ - return turn == TurnInstruction::TurnSharpLeft || turn == TurnInstruction::TurnSharpRight; -} - -inline bool isStraight(const TurnInstruction turn) -{ - return turn == TurnInstruction::GoStraight || turn == TurnInstruction::NoTurn; -} - -inline bool isConflict(const TurnInstruction first, const TurnInstruction second) -{ - return first == second || (isStraight(first) && isStraight(second)); -} -} -} -#endif - -} // namespace guidance -} // namespace engine -} // namespace osrm - -#endif /* OSRM_GUIDANCE_INSTRUCTION_SYMBOLS_HPP */ diff --git a/include/engine/guidance/turn_instruction.hpp b/include/engine/guidance/turn_instruction.hpp index 21db10a35..4d34dcd0f 100644 --- a/include/engine/guidance/turn_instruction.hpp +++ b/include/engine/guidance/turn_instruction.hpp @@ -60,9 +60,11 @@ enum TurnType // at the moment we can support 32 turn types, without increasing EndOfRoad, // T intersection EnterRoundabout, // Entering a small Roundabout EnterRoundaboutAtExit, // Entering a small Roundabout at a countable exit + EnterAndExitRoundabout, // Touching a roundabout ExitRoundabout, // Exiting a small Roundabout EnterRotary, // Enter a rotary EnterRotaryAtExit, // Enter A Rotary at a countable exit + EnterAndExitRotary, // Touching a rotary ExitRotary, // Exit a rotary StayOnRoundabout, // Continue on Either a small or a large Roundabout Restriction, // Cross a Barrier, requires barrier penalties instead of full block @@ -82,7 +84,7 @@ inline bool isValidModifier( const TurnType type, const DirectionModifier modifi const constexpr char *turn_type_names[] = {"invalid", "no turn", "waypoint", - "passing intersection", + "invalid", "new name", "continue", "turn", @@ -91,10 +93,12 @@ const constexpr char *turn_type_names[] = {"invalid", "fork", "end of road", "roundabout", - "invalid" + "invalid", + "roundabout", "invalid", "traffic circle", "invalid", + "traffic circle", "invalid", "invalid", "restriction", diff --git a/include/engine/plugins/plugin_base.hpp b/include/engine/plugins/plugin_base.hpp index 6321c95d6..cb1b4c4e9 100644 --- a/include/engine/plugins/plugin_base.hpp +++ b/include/engine/plugins/plugin_base.hpp @@ -267,6 +267,7 @@ class BasePlugin // we didn't found a fitting node, return error if (!phantom_node_pairs[i].first.IsValid(facade.GetNumberOfNodes())) { + //TODO document why? phantom_node_pairs.pop_back(); break; } diff --git a/include/extractor/turn_analysis.hpp b/include/extractor/turn_analysis.hpp index 9853904de..f396c0ef3 100644 --- a/include/extractor/turn_analysis.hpp +++ b/include/extractor/turn_analysis.hpp @@ -41,6 +41,7 @@ struct TurnCandidate namespace turn_analysis { +// the entry into the turn analysis std::vector getTurns(const NodeID from_node, const EdgeID via_eid, @@ -50,6 +51,34 @@ getTurns(const NodeID from_node, const std::unordered_set &barrier_nodes, const CompressedEdgeContainer &compressed_edge_container); +namespace detail +{ + +// Check for restrictions/barriers and generate a list of valid and invalid turns present at the +// node reached +// from `from_node` via `via_eid` +std::vector +getTurnCandidates(const NodeID from_node, + const EdgeID via_eid, + const std::shared_ptr node_based_graph, + const std::vector &node_info_list, + const std::shared_ptr restriction_map, + const std::unordered_set &barrier_nodes, + const CompressedEdgeContainer &compressed_edge_container); + +// handle roundabouts +// TODO distinguish roundabouts and rotaries +std::vector +handleRoundabouts(const NodeID from, + const EdgeID via_edge, + const bool on_roundabout, + const bool can_enter_roundabout, + const bool can_exit_roundabout, + std::vector turn_candidates, + const std::shared_ptr node_based_graph); + +// handle intersections + std::vector setTurnTypes(const NodeID from, const EdgeID via_edge, @@ -84,15 +113,6 @@ suppressTurns(const EdgeID via_eid, std::vector turn_candidates, const std::shared_ptr node_based_graph); -std::vector -getTurnCandidates(const NodeID from_node, - const EdgeID via_eid, - const std::shared_ptr node_based_graph, - const std::vector &node_info_list, - const std::shared_ptr restriction_map, - const std::unordered_set &barrier_nodes, - const CompressedEdgeContainer &compressed_edge_container); - // node_u -- (edge_1) --> node_v -- (edge_2) --> node_w engine::guidance::TurnInstruction AnalyzeTurn(const NodeID node_u, @@ -102,6 +122,7 @@ AnalyzeTurn(const NodeID node_u, const NodeID node_w, const double angle, const std::shared_ptr node_based_graph); +} // namespace detail } // namespace turn_analysis } // namespace extractor } // namespace osrm diff --git a/include/util/coordinate_calculation.hpp b/include/util/coordinate_calculation.hpp index 124805a6e..cd91067f2 100644 --- a/include/util/coordinate_calculation.hpp +++ b/include/util/coordinate_calculation.hpp @@ -3,11 +3,8 @@ #include "util/coordinate.hpp" -#include #include -#include - namespace osrm { namespace util diff --git a/src/engine/api/json_factory.cpp b/src/engine/api/json_factory.cpp index 1bad285ff..6bd49ac7d 100644 --- a/src/engine/api/json_factory.cpp +++ b/src/engine/api/json_factory.cpp @@ -85,7 +85,7 @@ std::string modeToString(const extractor::TravelMode mode) token = "river downstream"; break; case TRAVEL_MODE_ROUTE: - token = "rout"; + token = "route"; break; default: token = "other"; @@ -106,8 +106,8 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver) step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location); step_maneuver.values["bearing_before"] = maneuver.bearing_before; step_maneuver.values["bearing_after"] = maneuver.bearing_after; - if( maneuver.exit != 0 ) - step_maneuver.values["exit"] = maneuver.exit; + if (maneuver.exit != 0) + step_maneuver.values["exit"] = maneuver.exit; return step_maneuver; } @@ -178,7 +178,7 @@ util::json::Array makeRouteLegs(std::vector legs, return json_legs; } -} -} +} // namespace json +} // namespace api } // namespace engine } // namespace osrm diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index d147f1c08..b736a369e 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -84,8 +84,8 @@ void print(const std::vector> &leg_data) std::vector> postProcess(std::vector> leg_data) { - if( leg_data.empty() ) - return leg_data; + if (leg_data.empty()) + return leg_data; #define PRINT_DEBUG 0 unsigned carry_exit = 0; @@ -98,19 +98,19 @@ std::vector> postProcess(std::vector bool on_roundabout = false; for (auto &path_data : leg_data) { - if( not path_data.empty() ) - path_data[0].exit = carry_exit; + if (not path_data.empty()) + path_data[0].exit = carry_exit; for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index) { - if (entersRoundabout(path_data[data_index].turn_instruction) ) + if (entersRoundabout(path_data[data_index].turn_instruction)) { path_data[data_index].exit += 1; on_roundabout = true; } if (isSilent(path_data[data_index].turn_instruction) && - path_data[data_index].turn_instruction != TurnInstruction::NO_TURN()) + path_data[data_index].turn_instruction != TurnInstruction::NO_TURN()) { path_data[data_index].exit += 1; } @@ -118,7 +118,7 @@ std::vector> postProcess(std::vector { if (!on_roundabout) { - BOOST_ASSERT(leg_data[0][0].turn_instruction.type == TurnType::NO_TURN() ); + BOOST_ASSERT(leg_data[0][0].turn_instruction.type == TurnType::NO_TURN()); if (path_data[data_index].turn_instruction.type == ExitRoundabout) leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout; if (path_data[data_index].turn_instruction.type == ExitRotary) @@ -160,15 +160,16 @@ std::vector> postProcess(std::vector { if (entersRoundabout(path_data[data_index - 1].turn_instruction)) { - if( !on_roundabout ) - path_data[data_index-1].exit = 0; + if (!on_roundabout && !leavesRoundabout(path_data[data_index - 1].turn_instruction)) + path_data[data_index - 1].exit = 0; on_roundabout = false; } if (on_roundabout) { path_data[data_index - 2].exit = path_data[data_index - 1].exit; } - if (leavesRoundabout(path_data[data_index - 1].turn_instruction)) + if (leavesRoundabout(path_data[data_index - 1].turn_instruction) && + !entersRoundabout(path_data[data_index - 1].turn_instruction)) { path_data[data_index - 2].exit = path_data[data_index - 1].exit; on_roundabout = true; @@ -191,7 +192,8 @@ std::vector> postProcess(std::vector { for (auto &data : path_data) { - if (isSilent(data.turn_instruction) || leavesRoundabout(data.turn_instruction)) + if (isSilent(data.turn_instruction) || (leavesRoundabout(data.turn_instruction) && + !entersRoundabout(data.turn_instruction))) { data.turn_instruction = TurnInstruction::NO_TURN(); data.exit = 0; diff --git a/src/extractor/turn_analysis.cpp b/src/extractor/turn_analysis.cpp index ec694e088..42d823ceb 100644 --- a/src/extractor/turn_analysis.cpp +++ b/src/extractor/turn_analysis.cpp @@ -43,6 +43,7 @@ using engine::guidance::isSlightTurn; using engine::guidance::isSlightModifier; using engine::guidance::mirrorDirectionModifier; +#define PRINT_DEBUG_CANDIDATES 0 std::vector getTurns(const NodeID from, const EdgeID via_edge, @@ -52,12 +53,36 @@ getTurns(const NodeID from, const std::unordered_set &barrier_nodes, const CompressedEdgeContainer &compressed_edge_container) { - auto turn_candidates = turn_analysis::getTurnCandidates( - from, via_edge, node_based_graph, node_info_list, restriction_map, barrier_nodes, - compressed_edge_container); + auto turn_candidates = + detail::getTurnCandidates(from, via_edge, node_based_graph, node_info_list, restriction_map, + barrier_nodes, compressed_edge_container); + + // main priority: roundabouts + const auto &in_edge_data = node_based_graph->GetEdgeData(via_edge); + bool on_roundabout = in_edge_data.roundabout; + bool can_enter_roundabout = false; + bool can_exit_roundabout = false; + for (const auto &candidate : turn_candidates) + { + if (node_based_graph->GetEdgeData(candidate.eid).roundabout) + { + can_enter_roundabout = true; + } + else + { + can_exit_roundabout = true; + } + } + if (on_roundabout || can_enter_roundabout) + { + return detail::handleRoundabouts(from, via_edge, on_roundabout, can_enter_roundabout, + can_exit_roundabout, std::move(turn_candidates), + node_based_graph); + } + turn_candidates = - turn_analysis::setTurnTypes(from, via_edge, std::move(turn_candidates), node_based_graph); -#define PRINT_DEBUG_CANDIDATES 0 + detail::setTurnTypes(from, via_edge, std::move(turn_candidates), node_based_graph); + #if PRINT_DEBUG_CANDIDATES std::cout << "Initial Candidates:\n"; for (auto tc : turn_candidates) @@ -65,8 +90,8 @@ getTurns(const NodeID from, << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class << std::endl; #endif - turn_candidates = turn_analysis::optimizeCandidates(via_edge, std::move(turn_candidates), - node_based_graph, node_info_list); + turn_candidates = detail::optimizeCandidates(via_edge, std::move(turn_candidates), + node_based_graph, node_info_list); #if PRINT_DEBUG_CANDIDATES std::cout << "Optimized Candidates:\n"; for (auto tc : turn_candidates) @@ -74,8 +99,7 @@ getTurns(const NodeID from, << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class << std::endl; #endif - turn_candidates = - turn_analysis::suppressTurns(via_edge, std::move(turn_candidates), node_based_graph); + turn_candidates = detail::suppressTurns(via_edge, std::move(turn_candidates), node_based_graph); #if PRINT_DEBUG_CANDIDATES std::cout << "Suppressed Candidates:\n"; for (auto tc : turn_candidates) @@ -86,6 +110,93 @@ getTurns(const NodeID from, return turn_candidates; } +namespace detail +{ + +std::vector +handleRoundabouts(const NodeID from, + const EdgeID via_edge, + const bool on_roundabout, + const bool can_enter_roundabout, + const bool can_exit_roundabout, + std::vector turn_candidates, + const std::shared_ptr node_based_graph) +{ + (void)from; + // TODO requires differentiation between roundabouts and rotaries + NodeID node_v = node_based_graph->GetTarget(via_edge); + if (on_roundabout) + { + // Shoule hopefully have only a single exit and continue + // at least for cars. How about bikes? + for (auto &candidate : turn_candidates) + { + const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); + if (out_data.roundabout) + { + // TODO can forks happen in roundabouts? E.g. required lane changes + if (1 == node_based_graph->GetDirectedOutDegree(node_v)) + { + // No turn possible. + candidate.instruction = TurnInstruction::NO_TURN(); + } + else + { + candidate.instruction = + TurnInstruction::REMAIN_ROUNDABOUT(getTurnDirection(candidate.angle)); + } + } + else + { + candidate.instruction = + TurnInstruction::EXIT_ROUNDABOUT(getTurnDirection(candidate.angle)); + } + } +#if PRINT_DEBUG_CANDIDATES + std::cout << "On Roundabout Candidates:\n"; + for (auto tc : turn_candidates) + std::cout << "\t" << tc.toString() << " " + << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class + << std::endl; +#endif + return turn_candidates; + } + else + { + (void)can_enter_roundabout; + BOOST_ASSERT(can_enter_roundabout); + for (auto &candidate : turn_candidates) + { + const auto &out_data = node_based_graph->GetEdgeData(candidate.eid); + if (out_data.roundabout) + { + candidate.instruction = + TurnInstruction::ENTER_ROUNDABOUT(getTurnDirection(candidate.angle)); + if (can_exit_roundabout) + { + if (candidate.instruction.type == TurnType::EnterRotary) + candidate.instruction.type = TurnType::EnterRotaryAtExit; + if (candidate.instruction.type == TurnType::EnterRoundabout) + candidate.instruction.type = TurnType::EnterRoundaboutAtExit; + } + } + else + { + candidate.instruction = {TurnType::EnterAndExitRoundabout, + getTurnDirection(candidate.angle)}; + } + } +#if PRINT_DEBUG_CANDIDATES + std::cout << "Into Roundabout Candidates:\n"; + for (auto tc : turn_candidates) + std::cout << "\t" << tc.toString() << " " + << (int)node_based_graph->GetEdgeData(tc.eid).road_classification.road_class + << std::endl; +#endif + return turn_candidates; + } +} + std::vector setTurnTypes(const NodeID from, const EdgeID via_edge, @@ -839,6 +950,7 @@ AnalyzeTurn(const NodeID node_u, return {TurnType::Turn, getTurnDirection(angle)}; } +} // anemspace detail } // namespace turn_analysis } // namespace extractor -} // namespace osrm +} // nameNspace osrm