#ifndef RESTRICTION_HPP #define RESTRICTION_HPP #include "util/coordinate.hpp" #include "util/opening_hours.hpp" #include "util/typedefs.hpp" #include "mapbox/variant.hpp" #include namespace osrm { namespace extractor { // OSM offers two types of restrictions, via node and via-way restrictions. We parse both into the // same input container // // A restriction turning at a single node. This is the most common type of restriction: // // a - b - c // | // d // // ab via b to bd struct InputNodeRestriction { OSMWayID from; OSMNodeID via; OSMWayID to; }; // A restriction that uses a single via-way in between // // f - e - d // | // a - b - c // // ab via be to ef -- no u turn struct InputWayRestriction { OSMWayID from; OSMWayID via; OSMWayID to; }; // Outside view of the variant, these are equal to the `which()` results enum RestrictionType { NODE_RESTRICTION = 0, WAY_RESTRICTION = 1, NUM_RESTRICTION_TYPES = 2 }; struct InputTurnRestriction { // keep in the same order as the turn restrictions below mapbox::util::variant node_or_way; bool is_only; OSMWayID From() const { return node_or_way.which() == RestrictionType::NODE_RESTRICTION ? mapbox::util::get(node_or_way).from : mapbox::util::get(node_or_way).from; } OSMWayID To() const { return node_or_way.which() == RestrictionType::NODE_RESTRICTION ? mapbox::util::get(node_or_way).to : mapbox::util::get(node_or_way).to; } RestrictionType Type() const { BOOST_ASSERT(node_or_way.which() < RestrictionType::NUM_RESTRICTION_TYPES); return static_cast(node_or_way.which()); } InputWayRestriction &AsWayRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); return mapbox::util::get(node_or_way); } const InputWayRestriction &AsWayRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); return mapbox::util::get(node_or_way); } InputNodeRestriction &AsNodeRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); return mapbox::util::get(node_or_way); } const InputNodeRestriction &AsNodeRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); return mapbox::util::get(node_or_way); } }; struct InputConditionalTurnRestriction : InputTurnRestriction { std::vector condition; }; // OSRM manages restrictions based on node IDs which refer to the last node along the edge. Note // that this has the side-effect of not allowing parallel edges! struct NodeRestriction { NodeID from; NodeID via; NodeID to; // check if all parts of the restriction reference an actual node bool Valid() const { return from != SPECIAL_NODEID && to != SPECIAL_NODEID && via != SPECIAL_NODEID; }; bool operator==(const NodeRestriction &other) const { return std::tie(from, via, to) == std::tie(other.from, other.via, other.to); } }; // A way restriction in the context of OSRM requires translation into NodeIDs. This is due to the // compression happening in the graph creation process which would make it difficult to track // way-ids over a series of operations. Having access to the nodes directly allows look-up of the // edges in the processed structures struct WayRestriction { // a way restriction in OSRM is essentially a dual node turn restriction; // // | | // c -x- b // | | // d a // // from ab via bxc to cd: no_uturn // // Technically, we would need only a,b,c,d to describe the full turn in terms of nodes. When // parsing the relation, though, we do not know about the final representation in the node-based // graph for the restriction. In case of a traffic light, for example, we might end up with bxc // not being compressed to bc. For that reason, we need to maintain two node restrictions in // case a way restrction is not fully collapsed NodeRestriction in_restriction; NodeRestriction out_restriction; bool operator==(const WayRestriction &other) const { return std::tie(in_restriction, out_restriction) == std::tie(other.in_restriction, other.out_restriction); } }; // Wrapper for turn restrictions that gives more information on its type / handles the switch // between node/way/multi-way restrictions struct TurnRestriction { // keep in the same order as the turn restrictions above mapbox::util::variant node_or_way; bool is_only; // construction for NodeRestrictions explicit TurnRestriction(NodeRestriction node_restriction, bool is_only = false) : node_or_way(node_restriction), is_only(is_only) { } // construction for WayRestrictions explicit TurnRestriction(WayRestriction way_restriction, bool is_only = false) : node_or_way(way_restriction), is_only(is_only) { } explicit TurnRestriction() { node_or_way = NodeRestriction{SPECIAL_EDGEID, SPECIAL_NODEID, SPECIAL_EDGEID}; } WayRestriction &AsWayRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); return mapbox::util::get(node_or_way); } const WayRestriction &AsWayRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION); return mapbox::util::get(node_or_way); } NodeRestriction &AsNodeRestriction() { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); return mapbox::util::get(node_or_way); } const NodeRestriction &AsNodeRestriction() const { BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION); return mapbox::util::get(node_or_way); } RestrictionType Type() const { BOOST_ASSERT(node_or_way.which() < RestrictionType::NUM_RESTRICTION_TYPES); return static_cast(node_or_way.which()); } // check if all elements of the edge are considered valid bool Valid() const { if (node_or_way.which() == RestrictionType::WAY_RESTRICTION) { auto const &restriction = AsWayRestriction(); return restriction.in_restriction.Valid() && restriction.out_restriction.Valid(); } else { auto const &restriction = AsNodeRestriction(); return restriction.Valid(); } } bool operator==(const TurnRestriction &other) const { if (is_only != other.is_only) return false; if (Type() != other.Type()) return false; if (Type() == RestrictionType::WAY_RESTRICTION) { return AsWayRestriction() == other.AsWayRestriction(); } else { return AsNodeRestriction() == other.AsNodeRestriction(); } } }; struct ConditionalTurnRestriction : TurnRestriction { std::vector condition; }; } } #endif // RESTRICTION_HPP