osrm-backend/include/extractor/restriction.hpp

297 lines
8.7 KiB
C++
Raw Normal View History

#ifndef RESTRICTION_HPP
#define RESTRICTION_HPP
2012-08-27 11:40:59 -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
{
// 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;
};
2014-08-26 11:20:40 -04:00
// A restriction that uses one or more via-way in between
//
// e - f - g
// |
// d
// |
// a - b - c
//
// ab via bd,df to fe -- no u turn
struct InputWayRestriction
{
OSMWayID from;
std::vector<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
2017-07-27 05:42:13 -04:00
mapbox::util::variant<InputNodeRestriction, InputWayRestriction> node_or_way;
bool is_only;
// We represent conditional and unconditional restrictions with the same structure.
// Unconditional restrictions will have empty conditions.
std::vector<util::OpeningHours> condition;
OSMWayID From() const
2013-08-14 05:59:46 -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
OSMWayID To() const
{
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
}
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);
}
const InputWayRestriction &AsWayRestriction() const
{
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);
}
InputNodeRestriction &AsNodeRestriction()
{
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);
}
const InputNodeRestriction &AsNodeRestriction() const
{
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);
}
};
// 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!
//
// a - b - c
// |
// d
//
// ab via b to bd
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
//
// e - f - g
// |
// d
// |
// a - b - c
//
// ab via bd,df to fe -- no u turn
struct WayRestriction
{
// 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; });
};
bool operator==(const WayRestriction &other) const
{
return std::tie(from, via, to) == std::tie(other.from, other.via, other.to);
}
};
// Wrapper for turn restrictions that gives more information on its type / handles the switch
// between node/way restrictions
struct TurnRestriction
{
// 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;
bool is_only;
// We represent conditional and unconditional restrictions with the same structure.
// Unconditional restrictions will have empty conditions.
std::vector<util::OpeningHours> condition;
// 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(const WayRestriction &way_restriction, bool is_only = false)
: node_or_way(way_restriction), is_only(is_only)
{
}
explicit TurnRestriction()
{
node_or_way = NodeRestriction{SPECIAL_NODEID, SPECIAL_NODEID, SPECIAL_NODEID};
}
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(); }
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);
}
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);
}
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);
}
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);
}
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();
return 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();
}
}
};
} // namespace extractor
} // namespace osrm
2016-01-05 10:51:13 -05:00
#endif // RESTRICTION_HPP