#ifndef OSRM_EXTRACTOR_TURN_ANALYSIS #define OSRM_EXTRACTOR_TURN_ANALYSIS #include "extractor/guidance/turn_classification.hpp" #include "extractor/guidance/toolkit.hpp" #include "extractor/restriction_map.hpp" #include "extractor/compressed_edge_container.hpp" #include "util/name_table.hpp" #include #include #include #include #include #include namespace osrm { namespace extractor { namespace guidance { // What is exposed to the outside struct TurnOperation final { EdgeID eid; double angle; TurnInstruction instruction; }; // For the turn analysis, we require a full list of all connected roads to determine the outcome. // Invalid turns can influence the perceived angles // // aaa(2)aa // a - bbbbb // aaa(1)aa // // will not be perceived as a turn from (1) -> b, and as a U-turn from (1) -> (2). // In addition, they can influence whether a turn is obvious or not. struct ConnectedRoad final { ConnectedRoad(const TurnOperation turn, const bool entry_allowed = false); TurnOperation turn; bool entry_allowed; // a turn may be relevant to good instructions, even if we cannot take // the road std::string toString() const { std::string result = "[connection] "; result += std::to_string(turn.eid); result += " allows entry: "; result += std::to_string(entry_allowed); result += " angle: "; result += std::to_string(turn.angle); result += " instruction: "; result += std::to_string(static_cast(turn.instruction.type)) + " " + std::to_string(static_cast(turn.instruction.direction_modifier)); return result; } }; class TurnAnalysis { public: TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph, const std::vector &node_info_list, const RestrictionMap &restriction_map, const std::unordered_set &barrier_nodes, const CompressedEdgeContainer &compressed_edge_container, const util::NameTable &name_table); // the entry into the turn analysis std::vector getTurns(const NodeID from_node, const EdgeID via_eid) const; private: const util::NodeBasedDynamicGraph &node_based_graph; const std::vector &node_info_list; const RestrictionMap &restriction_map; const std::unordered_set &barrier_nodes; const CompressedEdgeContainer &compressed_edge_container; const util::NameTable &name_table; // 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. std::vector getConnectedRoads(const NodeID from_node, const EdgeID via_eid) const; // Merge segregated roads to omit invalid turns in favor of treating segregated roads as // one. // This function combines roads the following way: // // * * // * is converted to * // v ^ + // v ^ + // // The treatment results in a straight turn angle of 180ยบ rather than a turn angle of approx // 160 std::vector mergeSegregatedRoads(std::vector intersection) const; // TODO distinguish roundabouts and rotaries // TODO handle bike/walk cases that allow crossing a roundabout! // Processing of roundabouts // Produces instructions to enter/exit a roundabout or to stay on it. // Performs the distinction between roundabout and rotaries. std::vector handleRoundabouts(const bool is_rotary, const EdgeID via_edge, const bool on_roundabout, const bool can_exit_roundabout, std::vector intersection) const; // Indicates a Junction containing a motoryway bool isMotorwayJunction(const EdgeID via_edge, const std::vector &intersection) const; // Decide whether a turn is a turn or a ramp access TurnType findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const; // Get the Instruction for an obvious turn // Instruction will be a silent instruction TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates, const EdgeID via_edge, const ConnectedRoad &candidate) const; // Helper Function that decides between NoTurn or NewName TurnInstruction noTurnOrNewName(const NodeID from, const EdgeID via_edge, const ConnectedRoad &candidate) const; // Basic Turn Handling // Dead end. std::vector handleOneWayTurn(std::vector intersection) const; // Mode Changes, new names... std::vector handleTwoWayTurn(const EdgeID via_edge, std::vector intersection) const; // Forks, T intersections and similar std::vector handleThreeWayTurn(const EdgeID via_edge, std::vector intersection) const; // Handling of turns larger then degree three std::vector handleComplexTurn(const EdgeID via_edge, std::vector intersection) const; // Any Junction containing motorways std::vector handleMotorwayJunction(const EdgeID via_edge, std::vector intersection) const; std::vector handleFromMotorway(const EdgeID via_edge, std::vector intersection) const; std::vector handleMotorwayRamp(const EdgeID via_edge, std::vector intersection) const; // Utility function, setting basic turn types. Prepares for normal turn handling. std::vector setTurnTypes(const NodeID from, const EdgeID via_edge, std::vector intersection) const; // Assignment of specific turn types void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const; void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad ¢er, ConnectedRoad &right) const; void handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const; // Type specific fallbacks std::vector fallbackTurnAssignmentMotorway(std::vector intersection) const; // Classification std::size_t findObviousTurn(const EdgeID via_edge, const std::vector &intersection) const; std::pair findFork(const std::vector &intersection) const; std::vector assignLeftTurns(const EdgeID via_edge, std::vector intersection, const std::size_t starting_at) const; std::vector assignRightTurns(const EdgeID via_edge, std::vector intersection, const std::size_t up_to) const; bool isRotary(const NodeID nid) const; }; // class TurnAnalysis } // namespace guidance } // namespace extractor } // namespace osrm #endif // OSRM_EXTRACTOR_TURN_ANALYSIS