2014-11-28 06:13:18 -05:00
|
|
|
#ifndef RESTRICTION_HPP
|
|
|
|
#define RESTRICTION_HPP
|
2012-08-27 11:40:59 -04:00
|
|
|
|
2017-05-11 06:13:52 -04:00
|
|
|
#include "util/coordinate.hpp"
|
|
|
|
#include "util/opening_hours.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "util/typedefs.hpp"
|
2014-01-29 05:31:39 -05:00
|
|
|
|
2017-07-27 05:42:13 -04:00
|
|
|
#include "mapbox/variant.hpp"
|
2014-01-29 05:31:39 -05:00
|
|
|
#include <limits>
|
2012-08-27 11:40:59 -04:00
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace extractor
|
|
|
|
{
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
// 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
|
2014-05-07 11:25:35 -04:00
|
|
|
{
|
2017-07-11 08:22:28 -04:00
|
|
|
OSMWayID from;
|
|
|
|
OSMNodeID via;
|
|
|
|
OSMWayID to;
|
2017-07-06 11:09:24 -04:00
|
|
|
};
|
2014-08-26 11:20:40 -04:00
|
|
|
|
2020-12-20 16:59:57 -05:00
|
|
|
// A restriction that uses one or more via-way in between
|
2017-07-06 11:09:24 -04:00
|
|
|
//
|
2020-12-20 16:59:57 -05:00
|
|
|
// e - f - g
|
|
|
|
// |
|
|
|
|
// d
|
2017-07-06 11:09:24 -04:00
|
|
|
// |
|
|
|
|
// a - b - c
|
|
|
|
//
|
2020-12-20 16:59:57 -05:00
|
|
|
// ab via bd,df to fe -- no u turn
|
2017-07-06 11:09:24 -04:00
|
|
|
struct InputWayRestriction
|
|
|
|
{
|
2017-07-11 08:22:28 -04:00
|
|
|
OSMWayID from;
|
2020-12-20 16:59:57 -05:00
|
|
|
std::vector<OSMWayID> via;
|
2017-07-11 08:22:28 -04:00
|
|
|
OSMWayID to;
|
2017-07-06 11:09:24 -04:00
|
|
|
};
|
2017-05-11 06:13:52 -04:00
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
// Outside view of the variant, these are equal to the `which()` results
|
|
|
|
enum RestrictionType
|
|
|
|
{
|
|
|
|
NODE_RESTRICTION = 0,
|
|
|
|
WAY_RESTRICTION = 1,
|
|
|
|
NUM_RESTRICTION_TYPES = 2
|
|
|
|
};
|
2014-05-07 11:25:35 -04:00
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
struct InputTurnRestriction
|
|
|
|
{
|
|
|
|
// keep in the same order as the turn restrictions below
|
2017-07-27 05:42:13 -04:00
|
|
|
mapbox::util::variant<InputNodeRestriction, InputWayRestriction> node_or_way;
|
2017-07-11 08:22:28 -04:00
|
|
|
bool is_only;
|
2020-12-20 16:59:57 -05:00
|
|
|
// We represent conditional and unconditional restrictions with the same structure.
|
|
|
|
// Unconditional restrictions will have empty conditions.
|
|
|
|
std::vector<util::OpeningHours> condition;
|
2017-07-06 11:09:24 -04:00
|
|
|
|
2017-07-11 08:22:28 -04:00
|
|
|
OSMWayID From() const
|
2013-08-14 05:59:46 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
return node_or_way.which() == RestrictionType::NODE_RESTRICTION
|
2017-07-27 05:42:13 -04:00
|
|
|
? mapbox::util::get<InputNodeRestriction>(node_or_way).from
|
|
|
|
: mapbox::util::get<InputWayRestriction>(node_or_way).from;
|
2013-08-14 05:59:46 -04:00
|
|
|
}
|
2012-08-27 11:40:59 -04:00
|
|
|
|
2017-07-11 08:22:28 -04:00
|
|
|
OSMWayID To() const
|
2014-05-07 11:25:35 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
return node_or_way.which() == RestrictionType::NODE_RESTRICTION
|
2017-07-27 05:42:13 -04:00
|
|
|
? mapbox::util::get<InputNodeRestriction>(node_or_way).to
|
|
|
|
: mapbox::util::get<InputWayRestriction>(node_or_way).to;
|
2012-08-27 11:40:59 -04:00
|
|
|
}
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
RestrictionType Type() const
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() < RestrictionType::NUM_RESTRICTION_TYPES);
|
|
|
|
return static_cast<RestrictionType>(node_or_way.which());
|
|
|
|
}
|
|
|
|
|
|
|
|
InputWayRestriction &AsWayRestriction()
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<InputWayRestriction>(node_or_way);
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
2014-08-26 11:35:31 -04:00
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
const InputWayRestriction &AsWayRestriction() const
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<InputWayRestriction>(node_or_way);
|
2014-08-26 11:35:31 -04:00
|
|
|
}
|
2017-07-06 11:09:24 -04:00
|
|
|
|
|
|
|
InputNodeRestriction &AsNodeRestriction()
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<InputNodeRestriction>(node_or_way);
|
2014-08-26 11:35:31 -04:00
|
|
|
}
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
const InputNodeRestriction &AsNodeRestriction() const
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<InputNodeRestriction>(node_or_way);
|
2014-08-26 11:35:31 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
// 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!
|
2020-12-20 16:59:57 -05:00
|
|
|
//
|
|
|
|
// a - b - c
|
|
|
|
// |
|
|
|
|
// d
|
|
|
|
//
|
|
|
|
// ab via b to bd
|
2017-07-06 11:09:24 -04:00
|
|
|
struct NodeRestriction
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
NodeID from;
|
|
|
|
NodeID via;
|
|
|
|
NodeID to;
|
|
|
|
|
|
|
|
// check if all parts of the restriction reference an actual node
|
|
|
|
bool Valid() const
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
return from != SPECIAL_NODEID && to != SPECIAL_NODEID && via != SPECIAL_NODEID;
|
|
|
|
};
|
|
|
|
|
2017-07-11 08:22:28 -04:00
|
|
|
bool operator==(const NodeRestriction &other) const
|
|
|
|
{
|
|
|
|
return std::tie(from, via, to) == std::tie(other.from, other.via, other.to);
|
|
|
|
}
|
2014-08-26 11:35:31 -04:00
|
|
|
};
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
// 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
|
2020-12-20 16:59:57 -05:00
|
|
|
//
|
|
|
|
// e - f - g
|
|
|
|
// |
|
|
|
|
// d
|
|
|
|
// |
|
|
|
|
// a - b - c
|
|
|
|
//
|
|
|
|
// ab via bd,df to fe -- no u turn
|
2017-07-06 11:09:24 -04:00
|
|
|
struct WayRestriction
|
|
|
|
{
|
2020-12-20 16:59:57 -05:00
|
|
|
// A way restriction in OSRM needs to track all nodes that make up the via ways. Whilst most
|
|
|
|
// of these nodes will be removed by compression, some nodes will contain features that need to
|
|
|
|
// be considered when routing (e.g. intersections, nested restrictions, etc).
|
|
|
|
NodeID from;
|
|
|
|
std::vector<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.size() >= 2 &&
|
|
|
|
std::all_of(via.begin(), via.end(), [](NodeID i) { return i != SPECIAL_NODEID; });
|
|
|
|
};
|
2017-07-11 08:22:28 -04:00
|
|
|
|
|
|
|
bool operator==(const WayRestriction &other) const
|
|
|
|
{
|
2020-12-20 16:59:57 -05:00
|
|
|
return std::tie(from, via, to) == std::tie(other.from, other.via, other.to);
|
2017-07-11 08:22:28 -04:00
|
|
|
}
|
2017-07-06 11:09:24 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Wrapper for turn restrictions that gives more information on its type / handles the switch
|
2020-12-20 16:59:57 -05:00
|
|
|
// between node/way restrictions
|
2017-07-06 11:09:24 -04:00
|
|
|
struct TurnRestriction
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
2017-07-06 11:09:24 -04:00
|
|
|
// keep in the same order as the turn restrictions above
|
2017-07-27 05:42:13 -04:00
|
|
|
mapbox::util::variant<NodeRestriction, WayRestriction> node_or_way;
|
2017-07-11 08:22:28 -04:00
|
|
|
bool is_only;
|
2020-12-20 16:59:57 -05:00
|
|
|
// We represent conditional and unconditional restrictions with the same structure.
|
|
|
|
// Unconditional restrictions will have empty conditions.
|
|
|
|
std::vector<util::OpeningHours> condition;
|
2017-07-06 11:09:24 -04:00
|
|
|
|
|
|
|
// construction for NodeRestrictions
|
|
|
|
explicit TurnRestriction(NodeRestriction node_restriction, bool is_only = false)
|
2017-07-11 08:22:28 -04:00
|
|
|
: node_or_way(node_restriction), is_only(is_only)
|
2014-08-26 11:35:31 -04:00
|
|
|
{
|
|
|
|
}
|
2017-07-06 11:09:24 -04:00
|
|
|
|
|
|
|
// construction for WayRestrictions
|
|
|
|
explicit TurnRestriction(WayRestriction way_restriction, bool is_only = false)
|
2017-07-11 08:22:28 -04:00
|
|
|
: node_or_way(way_restriction), is_only(is_only)
|
2017-07-06 11:09:24 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit TurnRestriction()
|
|
|
|
{
|
2020-12-20 16:59:57 -05:00
|
|
|
node_or_way = NodeRestriction{SPECIAL_NODEID, SPECIAL_NODEID, SPECIAL_NODEID};
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
|
|
|
|
2020-12-20 16:59:57 -05:00
|
|
|
NodeID To() const
|
|
|
|
{
|
|
|
|
return node_or_way.which() == RestrictionType::NODE_RESTRICTION
|
|
|
|
? mapbox::util::get<NodeRestriction>(node_or_way).to
|
|
|
|
: mapbox::util::get<WayRestriction>(node_or_way).to;
|
|
|
|
}
|
|
|
|
|
|
|
|
NodeID From() const
|
|
|
|
{
|
|
|
|
return node_or_way.which() == RestrictionType::NODE_RESTRICTION
|
|
|
|
? mapbox::util::get<NodeRestriction>(node_or_way).from
|
|
|
|
: mapbox::util::get<WayRestriction>(node_or_way).from;
|
|
|
|
}
|
|
|
|
|
|
|
|
NodeID FirstVia() const
|
|
|
|
{
|
|
|
|
if (node_or_way.which() == RestrictionType::NODE_RESTRICTION)
|
|
|
|
{
|
|
|
|
return mapbox::util::get<NodeRestriction>(node_or_way).via;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(!mapbox::util::get<WayRestriction>(node_or_way).via.empty());
|
|
|
|
return mapbox::util::get<WayRestriction>(node_or_way).via[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsTurnRestricted(NodeID to) const { return is_only ? To() != to : To() == to; }
|
|
|
|
|
|
|
|
bool IsUnconditional() const { return condition.empty(); }
|
|
|
|
|
2017-07-06 11:09:24 -04:00
|
|
|
WayRestriction &AsWayRestriction()
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<WayRestriction>(node_or_way);
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const WayRestriction &AsWayRestriction() const
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::WAY_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<WayRestriction>(node_or_way);
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
NodeRestriction &AsNodeRestriction()
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<NodeRestriction>(node_or_way);
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const NodeRestriction &AsNodeRestriction() const
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() == RestrictionType::NODE_RESTRICTION);
|
2017-07-27 05:42:13 -04:00
|
|
|
return mapbox::util::get<NodeRestriction>(node_or_way);
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
RestrictionType Type() const
|
|
|
|
{
|
|
|
|
BOOST_ASSERT(node_or_way.which() < RestrictionType::NUM_RESTRICTION_TYPES);
|
|
|
|
return static_cast<RestrictionType>(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();
|
2020-12-20 16:59:57 -05:00
|
|
|
return restriction.Valid();
|
2017-07-06 11:09:24 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto const &restriction = AsNodeRestriction();
|
|
|
|
return restriction.Valid();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-11 08:22:28 -04:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
2017-07-06 11:09:24 -04:00
|
|
|
};
|
2020-11-26 10:21:39 -05:00
|
|
|
} // namespace extractor
|
|
|
|
} // namespace osrm
|
2016-01-05 10:51:13 -05:00
|
|
|
|
2014-11-28 06:13:18 -05:00
|
|
|
#endif // RESTRICTION_HPP
|