2016-02-25 08:40:26 -05:00
|
|
|
#ifndef OSRM_EXTRACTOR_TURN_ANALYSIS
|
|
|
|
#define OSRM_EXTRACTOR_TURN_ANALYSIS
|
|
|
|
|
2016-03-23 08:04:23 -04:00
|
|
|
#include "extractor/compressed_edge_container.hpp"
|
2016-03-01 16:30:31 -05:00
|
|
|
#include "extractor/guidance/toolkit.hpp"
|
2016-03-23 08:04:23 -04:00
|
|
|
#include "extractor/guidance/turn_classification.hpp"
|
2016-02-25 08:40:26 -05:00
|
|
|
#include "extractor/restriction_map.hpp"
|
|
|
|
|
2016-03-16 10:47:33 -04:00
|
|
|
#include "util/name_table.hpp"
|
|
|
|
|
2016-03-03 12:30:41 -05:00
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
#include <memory>
|
2016-03-23 08:04:23 -04:00
|
|
|
#include <string>
|
2016-02-25 08:40:26 -05:00
|
|
|
#include <unordered_set>
|
2016-03-23 08:04:23 -04:00
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
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
|
|
|
|
2016-03-17 09:09:09 -04:00
|
|
|
// What is exposed to the outside
|
|
|
|
struct TurnOperation final
|
2016-02-25 08:40:26 -05:00
|
|
|
{
|
2016-03-17 09:09:09 -04:00
|
|
|
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
|
2016-02-25 08:40:26 -05:00
|
|
|
|
|
|
|
std::string toString() const
|
|
|
|
{
|
2016-03-17 09:09:09 -04:00
|
|
|
std::string result = "[connection] ";
|
|
|
|
result += std::to_string(turn.eid);
|
|
|
|
result += " allows entry: ";
|
|
|
|
result += std::to_string(entry_allowed);
|
2016-02-25 08:40:26 -05:00
|
|
|
result += " angle: ";
|
2016-03-17 09:09:09 -04:00
|
|
|
result += std::to_string(turn.angle);
|
2016-02-25 08:40:26 -05:00
|
|
|
result += " instruction: ";
|
2016-03-17 09:09:09 -04:00
|
|
|
result += std::to_string(static_cast<std::int32_t>(turn.instruction.type)) + " " +
|
|
|
|
std::to_string(static_cast<std::int32_t>(turn.instruction.direction_modifier));
|
2016-02-25 08:40:26 -05:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-03-08 06:40:45 -05:00
|
|
|
class TurnAnalysis
|
2016-02-25 12:31:29 -05:00
|
|
|
{
|
2016-03-17 09:09:09 -04:00
|
|
|
|
2016-03-08 06:40:45 -05:00
|
|
|
public:
|
|
|
|
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
|
|
|
const std::vector<QueryNode> &node_info_list,
|
|
|
|
const RestrictionMap &restriction_map,
|
|
|
|
const std::unordered_set<NodeID> &barrier_nodes,
|
2016-03-16 10:47:33 -04:00
|
|
|
const CompressedEdgeContainer &compressed_edge_container,
|
|
|
|
const util::NameTable &name_table);
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// the entry into the turn analysis
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<TurnOperation> getTurns(const NodeID from_node, const EdgeID via_eid) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
private:
|
|
|
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
|
|
|
const std::vector<QueryNode> &node_info_list;
|
|
|
|
const RestrictionMap &restriction_map;
|
|
|
|
const std::unordered_set<NodeID> &barrier_nodes;
|
|
|
|
const CompressedEdgeContainer &compressed_edge_container;
|
2016-03-16 10:47:33 -04:00
|
|
|
const util::NameTable &name_table;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
2016-03-17 09:09:09 -04:00
|
|
|
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
|
|
|
// the
|
2016-03-08 06:40:45 -05:00
|
|
|
// node reached
|
|
|
|
// from `from_node` via `via_eid`
|
|
|
|
// The resulting candidates have to be analysed for their actual instructions later on.
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> getConnectedRoads(const NodeID from_node,
|
2016-03-08 06:40:45 -05:00
|
|
|
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
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> mergeSegregatedRoads(std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// 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.
|
2016-03-23 10:28:53 -04:00
|
|
|
std::vector<ConnectedRoad> handleRoundabouts(const bool is_rotary,
|
|
|
|
const EdgeID via_edge,
|
2016-03-08 06:40:45 -05:00
|
|
|
const bool on_roundabout,
|
|
|
|
const bool can_exit_roundabout,
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Indicates a Junction containing a motoryway
|
2016-03-17 09:09:09 -04:00
|
|
|
bool isMotorwayJunction(const EdgeID via_edge,
|
|
|
|
const std::vector<ConnectedRoad> &intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Decide whether a turn is a turn or a ramp access
|
2016-03-17 09:09:09 -04:00
|
|
|
TurnType findBasicTurnType(const EdgeID via_edge, const ConnectedRoad &candidate) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Get the Instruction for an obvious turn
|
|
|
|
// Instruction will be a silent instruction
|
|
|
|
TurnInstruction getInstructionForObvious(const std::size_t number_of_candidates,
|
2016-03-05 12:17:24 -05:00
|
|
|
const EdgeID via_edge,
|
2016-03-23 08:04:23 -04:00
|
|
|
const bool through_street,
|
2016-03-17 09:09:09 -04:00
|
|
|
const ConnectedRoad &candidate) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Helper Function that decides between NoTurn or NewName
|
|
|
|
TurnInstruction
|
2016-03-17 09:09:09 -04:00
|
|
|
noTurnOrNewName(const NodeID from, const EdgeID via_edge, const ConnectedRoad &candidate) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Basic Turn Handling
|
|
|
|
|
|
|
|
// Dead end.
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> handleOneWayTurn(std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Mode Changes, new names...
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> handleTwoWayTurn(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Forks, T intersections and similar
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> handleThreeWayTurn(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
2016-03-17 09:09:09 -04:00
|
|
|
// Handling of turns larger then degree three
|
|
|
|
std::vector<ConnectedRoad> handleComplexTurn(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Any Junction containing motorways
|
2016-03-23 10:28:53 -04:00
|
|
|
std::vector<ConnectedRoad>
|
|
|
|
handleMotorwayJunction(const EdgeID via_edge, std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> handleFromMotorway(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-02-26 11:33:18 -05:00
|
|
|
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> handleMotorwayRamp(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Utility function, setting basic turn types. Prepares for normal turn handling.
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> setTurnTypes(const NodeID from,
|
2016-03-05 12:17:24 -05:00
|
|
|
const EdgeID via_edge,
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad> intersection) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
|
|
|
// Assignment of specific turn types
|
2016-03-17 09:09:09 -04:00
|
|
|
void assignFork(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
void assignFork(const EdgeID via_edge,
|
2016-03-17 09:09:09 -04:00
|
|
|
ConnectedRoad &left,
|
|
|
|
ConnectedRoad ¢er,
|
|
|
|
ConnectedRoad &right) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
|
2016-03-07 08:52:26 -05:00
|
|
|
void
|
2016-03-17 09:09:09 -04:00
|
|
|
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
|
2016-03-07 08:52:26 -05:00
|
|
|
|
|
|
|
// Type specific fallbacks
|
2016-03-17 09:09:09 -04:00
|
|
|
std::vector<ConnectedRoad>
|
|
|
|
fallbackTurnAssignmentMotorway(std::vector<ConnectedRoad> intersection) const;
|
|
|
|
|
|
|
|
// Classification
|
|
|
|
std::size_t findObviousTurn(const EdgeID via_edge,
|
|
|
|
const std::vector<ConnectedRoad> &intersection) const;
|
|
|
|
std::pair<std::size_t, std::size_t>
|
|
|
|
findFork(const std::vector<ConnectedRoad> &intersection) const;
|
|
|
|
|
|
|
|
std::vector<ConnectedRoad> assignLeftTurns(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection,
|
|
|
|
const std::size_t starting_at) const;
|
|
|
|
std::vector<ConnectedRoad> assignRightTurns(const EdgeID via_edge,
|
|
|
|
std::vector<ConnectedRoad> intersection,
|
|
|
|
const std::size_t up_to) const;
|
2016-03-07 08:52:26 -05:00
|
|
|
|
2016-03-23 10:28:53 -04:00
|
|
|
bool isRotary(const NodeID nid) const;
|
2016-03-08 06:40:45 -05:00
|
|
|
}; // class TurnAnalysis
|
2016-02-26 11:33:18 -05:00
|
|
|
|
2016-03-01 16:30:31 -05:00
|
|
|
} // namespace guidance
|
2016-02-25 08:40:26 -05:00
|
|
|
} // namespace extractor
|
|
|
|
} // namespace osrm
|
|
|
|
|
|
|
|
#endif // OSRM_EXTRACTOR_TURN_ANALYSIS
|