Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Via way restrictions [WIP] #1828

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions data_structures/restriction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ struct TurnRestriction
struct Bits
{ // mostly unused
Bits()
: is_only(false), uses_via_way(false), unused2(false), unused3(false), unused4(false),
: is_only(false), uses_via_way(false), ignore_write(false), unused3(false), unused4(false),
unused5(false), unused6(false), unused7(false)
{
}

bool is_only : 1;
bool uses_via_way : 1;
bool unused2 : 1;
bool ignore_write : 1;
bool unused3 : 1;
bool unused4 : 1;
bool unused5 : 1;
Expand All @@ -79,7 +79,7 @@ struct TurnRestriction

/**
* This is just a wrapper around TurnRestriction used in the extractor.
*
*
* Could be merged with TurnRestriction. For now the type-destiction makes sense
* as the format in which the restriction is presented in the extractor and in the
* preprocessing is different. (see restriction_parser.cpp)
Expand All @@ -98,6 +98,7 @@ struct InputRestrictionContainer
{
restriction.from.way = SPECIAL_EDGEID;
restriction.to.way = SPECIAL_EDGEID;
restriction.via.way = SPECIAL_EDGEID;
restriction.via.node = SPECIAL_NODEID;
restriction.flags.is_only = is_only;
}
Expand Down Expand Up @@ -131,4 +132,15 @@ struct CmpRestrictionContainerByTo
value_type min_value() const { return InputRestrictionContainer::min_value(); }
};

struct CmpRestrictionContainerByVia
{
using value_type = InputRestrictionContainer;
bool operator()(const InputRestrictionContainer &a, const InputRestrictionContainer &b) const
{
return a.restriction.via.way < b.restriction.via.way;
}
value_type max_value() const { return InputRestrictionContainer::max_value(); }
value_type min_value() const { return InputRestrictionContainer::min_value(); }
};

#endif // RESTRICTION_HPP
155 changes: 126 additions & 29 deletions data_structures/restriction_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,51 +29,117 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

RestrictionMap::RestrictionMap(const std::vector<TurnRestriction> &restriction_list) : m_count(0)
{
RestrictionTarget via_way_target;
std::size_t via_way_index;

// decompose restriction consisting of a start, via and end node into a
// a pair of starting edge and a list of all end nodes
for (auto &restriction : restriction_list)
{
// This downcasting is OK because when this is called, the node IDs have been
// renumbered into internal values, which should be well under 2^32
// This will be a problem if we have more than 2^32 actual restrictions
BOOST_ASSERT(restriction.from.node < std::numeric_limits<NodeID>::max());
BOOST_ASSERT(restriction.via.node < std::numeric_limits<NodeID>::max());
m_restriction_start_nodes.insert(restriction.from.node);
m_no_turn_via_node_set.insert(restriction.via.node);

// This explicit downcasting is also OK for the same reason.
RestrictionSource restriction_source = {static_cast<NodeID>(restriction.from.node), static_cast<NodeID>(restriction.via.node)};

std::size_t index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
if (!restriction.flags.uses_via_way)
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
// This downcasting is OK because when this is called, the node IDs have been
// renumbered into internal values, which should be well under 2^32
// This will be a problem if we have more than 2^32 actual restrictions
BOOST_ASSERT(restriction.from.node < std::numeric_limits<NodeID>::max());
BOOST_ASSERT(restriction.via.node < std::numeric_limits<NodeID>::max());
m_restriction_start_nodes.insert(restriction.from.node);
m_no_turn_via_node_set.insert(restriction.via.node);

// This explicit downcasting is also OK for the same reason.
RestrictionSource restriction_source = {static_cast<NodeID>(restriction.from.node), static_cast<NodeID>(restriction.via.node)};

std::size_t index;
auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
{
index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(index + 1);
m_restriction_map.emplace(restriction_source, index);
}
else
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->is_only)
{
continue;
}
else if (restriction.flags.is_only)
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
}
}
++m_count;
BOOST_ASSERT(restriction.to.node < std::numeric_limits<NodeID>::max());
m_restriction_bucket_list.at(index)
.emplace_back(restriction.to.node, restriction.flags.is_only);
}
else
{
index = restriction_iter->second;
// Map already contains an is_only_*-restriction
if (m_restriction_bucket_list.at(index).begin()->is_only)
// We are parsing the restrictions from the file in order, so we keep track of
// one restriction (and its nodes) at a time (i.e. via_way_target)
if (IsFromWay(restriction))
{
BOOST_ASSERT(via_way_target.via_nodes.size() == 0 && via_way_target.target_node == SPECIAL_NODEID);

m_restriction_start_nodes.insert(restriction.from.node);
m_no_turn_via_node_set.insert(restriction.via.node);

RestrictionSource restriction_source = {static_cast<NodeID>(restriction.from.node), static_cast<NodeID>(restriction.via.node)};

auto restriction_iter = m_restriction_map.find(restriction_source);
if (restriction_iter == m_restriction_map.end())
{
via_way_index = m_restriction_bucket_list.size();
m_restriction_bucket_list.resize(via_way_index + 1);
m_restriction_map.emplace(restriction_source, via_way_index);
}
}
else if (IsViaWay(restriction))
{
continue;
m_no_turn_via_node_set.insert(restriction.via.node);
via_way_target.via_nodes.push_back(restriction.via.node);
}
else if (restriction.flags.is_only)
else if (IsToWay(restriction))
{
// We are going to insert an is_only_*-restriction. There can be only one.
m_count -= m_restriction_bucket_list.at(index).size();
m_restriction_bucket_list.at(index).clear();
BOOST_ASSERT(via_way_targets.via_nodes.size() >= 1);
m_no_turn_via_node_set.insert(restriction.via.node);
m_no_turn_via_node_set.insert(restriction.to.node);

via_way_target.via_nodes.push_back(restriction.via.node);
via_way_target.via_nodes.push_back(restriction.to.node);
m_restriction_bucket_list.at(via_way_index).push_back(via_way_target);
++m_count;
via_way_target.reset();
}
}
++m_count;
BOOST_ASSERT(restriction.to.node < std::numeric_limits<NodeID>::max());
m_restriction_bucket_list.at(index)
.emplace_back(restriction.to.node, restriction.flags.is_only);
}
}

bool RestrictionMap::IsFromWay(const TurnRestriction &restriction) const
{
return restriction.from.node != SPECIAL_NODEID &&
restriction.via.node != SPECIAL_NODEID &&
restriction.to.node == SPECIAL_NODEID;
}

bool RestrictionMap::IsViaWay(const TurnRestriction &restriction) const
{
return restriction.from.node == SPECIAL_NODEID &&
restriction.via.node != SPECIAL_NODEID &&
restriction.to.node == SPECIAL_NODEID;
}

bool RestrictionMap::IsToWay(const TurnRestriction &restriction) const
{
return restriction.from.node == SPECIAL_NODEID &&
restriction.via.node != SPECIAL_NODEID &&
restriction.to.node != SPECIAL_NODEID;
}

bool RestrictionMap::IsViaNode(const NodeID node) const
{
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
Expand Down Expand Up @@ -134,6 +200,37 @@ NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID node_u, const No
return SPECIAL_NODEID;
}

// Checks if a turn restriction is a via way restriction and returns the nodes associated with
// each of the restriction.
std::vector<std::vector<NodeID>> RestrictionMap::CheckForViaWayRestrictions(const NodeID node_u,
const NodeID node_v) const
{
BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID);

std::vector<std::vector<NodeID>> via_way_nodes_list;

if (!IsSourceNode(node_u))
{
return via_way_nodes_list;
}

const auto restriction_iter = m_restriction_map.find({node_u, node_v});
if (restriction_iter != m_restriction_map.end())
{
const unsigned index = restriction_iter->second;
const auto &bucket = m_restriction_bucket_list.at(index);
for (const RestrictionTarget &restriction_target : bucket)
{
if (restriction_target.via_nodes.size())
{
via_way_nodes_list.push_back(restriction_target.via_nodes);
}
}
}
return via_way_nodes_list;
}

// Checks if turn <u,v,w> is actually a turn restriction.
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID node_u,
const NodeID node_v,
Expand Down
34 changes: 33 additions & 1 deletion data_structures/restriction_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <vector>

struct RestrictionSource
Expand All @@ -56,12 +57,30 @@ struct RestrictionTarget
{
NodeID target_node;
bool is_only;
// If restriction is a via_way, via_nodes will be populated with nodes from restriction
std::vector<NodeID> via_nodes;

explicit RestrictionTarget(NodeID target, bool only) : target_node(target), is_only(only) {}

explicit RestrictionTarget() : target_node(SPECIAL_NODEID), is_only(false) {}

void reset()
{
target_node = SPECIAL_NODEID;
is_only = false;
via_nodes.clear();
}

friend inline bool operator==(const RestrictionTarget &lhs, const RestrictionTarget &rhs)
{
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only);
return (lhs.target_node == rhs.target_node && lhs.is_only == rhs.is_only) &&
(lhs.via_nodes.size() == rhs.via_nodes.size()) &&
(std::equal(
lhs.via_nodes.begin(),
lhs.via_nodes.begin() + lhs.via_nodes.size(),
rhs.via_nodes.begin()
)
);
}
};

Expand Down Expand Up @@ -135,15 +154,23 @@ class RestrictionMap

for (RestrictionTarget &restriction_target : bucket)
{
unsigned via_ways_length = restriction_target.via_ways.size();
if (node_v == restriction_target.target_node)
{
restriction_target.target_node = node_w;
}
else if (via_ways_length && node_v == restriction_target.via_ways[via_ways_length - 1])
{
restriction_target.via_ways[via_ways_length - 1] = node_w;
}
}
}
}

bool IsViaNode(const NodeID node) const;
bool IsFromWay(const TurnRestriction &restriction) const;
bool IsViaWay(const TurnRestriction &restriction) const;
bool IsToWay(const TurnRestriction &restriction) const;

// Replaces start edge (v, w) with (u, w). Only start node changes.
void
Expand All @@ -156,6 +183,11 @@ class RestrictionMap
bool
CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const;

// Checks if a turn restriction is a via way restriction and returns the nodes associated with
// the restriction.
std::vector<std::vector<NodeID>>
CheckForViaWayRestrictions(const NodeID node_u, const NodeID node_v) const;

std::size_t size() const { return m_count; }

private:
Expand Down
Loading