Add support for multiple via-way restrictions (#5907)
Currently OSRM only supports turn restrictions with a single via-node or one via-way. OSM allows for multiple via-ways to represent longer and more complex restrictions. This PR extends the use of duplicate nodes for representng via-way turn restrictions to also support multi via-way restrictions. Effectively, this increases the edge-based graph size by the number of edges in multi via-way restrictions. However, given the low number of these restrictions it has little effect on total graph size. In addition, we add a new step in the extraction phase that constructs a restriction graph to support more complex relationships between restrictions, such as nested restrictions and overlapping restrictions.
This commit is contained in:
@@ -12,8 +12,8 @@
|
||||
#include "extractor/name_table.hpp"
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/node_restriction_map.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/turn_lane_types.hpp"
|
||||
#include "extractor/way_restriction_map.hpp"
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
#ifndef EXTRACTION_CONTAINERS_HPP
|
||||
#define EXTRACTION_CONTAINERS_HPP
|
||||
|
||||
#include "extractor/first_and_last_segment_of_way.hpp"
|
||||
#include "extractor/internal_extractor_edge.hpp"
|
||||
#include "extractor/nodes_of_way.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
|
||||
#include "storage/tar_fwd.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
@@ -22,9 +24,16 @@ namespace extractor
|
||||
*/
|
||||
class ExtractionContainers
|
||||
{
|
||||
using ReferencedWays = std::unordered_map<OSMWayID, NodesOfWay>;
|
||||
// The relationship between way and nodes is lost during node preparation.
|
||||
// We identify the ways and nodes relevant to restrictions/overrides prior to
|
||||
// node processing so that they can be referenced in the preparation phase.
|
||||
ReferencedWays IdentifyRestrictionWays();
|
||||
ReferencedWays IdentifyManeuverOverrideWays();
|
||||
|
||||
void PrepareNodes();
|
||||
void PrepareManeuverOverrides();
|
||||
void PrepareRestrictions();
|
||||
void PrepareManeuverOverrides(const ReferencedWays &maneuver_override_ways);
|
||||
void PrepareRestrictions(const ReferencedWays &restriction_ways);
|
||||
void PrepareEdges(ScriptingEnvironment &scripting_environment);
|
||||
|
||||
void WriteNodes(storage::tar::FileWriter &file_out) const;
|
||||
@@ -37,9 +46,10 @@ class ExtractionContainers
|
||||
using NodeVector = std::vector<QueryNode>;
|
||||
using EdgeVector = std::vector<InternalExtractorEdge>;
|
||||
using AnnotationDataVector = std::vector<NodeBasedEdgeAnnotation>;
|
||||
using WayIDStartEndVector = std::vector<FirstAndLastSegmentOfWay>;
|
||||
using NameCharData = std::vector<unsigned char>;
|
||||
using NameOffsets = std::vector<unsigned>;
|
||||
using NameOffsets = std::vector<size_t>;
|
||||
using WayIDVector = std::vector<OSMWayID>;
|
||||
using WayNodeIDOffsets = std::vector<size_t>;
|
||||
|
||||
std::vector<OSMNodeID> barrier_nodes;
|
||||
std::vector<OSMNodeID> traffic_signals;
|
||||
@@ -49,20 +59,18 @@ class ExtractionContainers
|
||||
AnnotationDataVector all_edges_annotation_data_list;
|
||||
NameCharData name_char_data;
|
||||
NameOffsets name_offsets;
|
||||
// an adjacency array containing all turn lane masks
|
||||
WayIDStartEndVector way_start_end_id_list;
|
||||
WayIDVector ways_list;
|
||||
// Offsets into used nodes for each way_list entry
|
||||
WayNodeIDOffsets way_node_id_offsets;
|
||||
|
||||
unsigned max_internal_node_id;
|
||||
|
||||
// list of restrictions before we transform them into the output types. Input containers
|
||||
// reference OSMNodeIDs. We can only transform them to the correct internal IDs after we've read
|
||||
// everything. Without a multi-parse approach, we have to remember the output restrictions
|
||||
// before converting them to the internal formats
|
||||
std::vector<InputConditionalTurnRestriction> restrictions_list;
|
||||
|
||||
// turn restrictions split into conditional and unconditional turn restrictions
|
||||
std::vector<ConditionalTurnRestriction> conditional_turn_restrictions;
|
||||
std::vector<TurnRestriction> unconditional_turn_restrictions;
|
||||
// List of restrictions (conditional and unconditional) before we transform them into the
|
||||
// output types. Input containers reference OSMNodeIDs. We can only transform them to the
|
||||
// correct internal IDs after we've read everything. Without a multi-parse approach,
|
||||
// we have to remember the output restrictions before converting them to the internal formats
|
||||
std::vector<InputTurnRestriction> restrictions_list;
|
||||
std::vector<TurnRestriction> turn_restrictions;
|
||||
|
||||
std::vector<InputManeuverOverride> external_maneuver_overrides_list;
|
||||
std::vector<UnresolvedManeuverOverride> internal_maneuver_overrides;
|
||||
|
||||
@@ -42,6 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/guidance/turn_lanes.hpp"
|
||||
|
||||
#include "restriction_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
@@ -63,7 +64,6 @@ class Extractor
|
||||
|
||||
std::tuple<LaneDescriptionMap,
|
||||
std::vector<TurnRestriction>,
|
||||
std::vector<ConditionalTurnRestriction>,
|
||||
std::vector<UnresolvedManeuverOverride>>
|
||||
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
|
||||
|
||||
@@ -74,8 +74,7 @@ class Extractor
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const std::vector<TurnRestriction> &turn_restrictions,
|
||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
const RestrictionGraph &restriction_graph,
|
||||
const std::unordered_set<EdgeID> &segregated_edges,
|
||||
const NameTable &name_table,
|
||||
const std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||
@@ -97,23 +96,16 @@ class Extractor
|
||||
EdgeBasedNodeDataContainer &nodes_container) const;
|
||||
void BuildRTree(std::vector<EdgeBasedNodeSegment> edge_based_node_segments,
|
||||
const std::vector<util::Coordinate> &coordinates);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
|
||||
void WriteConditionalRestrictions(
|
||||
const std::string &path,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||
|
||||
void ProcessGuidanceTurns(
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &edge_based_node_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::vector<TurnRestriction> &turn_restrictions,
|
||||
const std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
const NameTable &name_table,
|
||||
LaneDescriptionMap lane_description_map,
|
||||
ScriptingEnvironment &scripting_environment);
|
||||
void ProcessGuidanceTurns(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &edge_based_node_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const RestrictionGraph &restriction_graph,
|
||||
const NameTable &name_table,
|
||||
LaneDescriptionMap lane_description_map,
|
||||
ScriptingEnvironment &scripting_environment);
|
||||
};
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
@@ -47,7 +47,7 @@ struct ExtractionNode;
|
||||
struct ExtractionWay;
|
||||
struct ExtractionRelation;
|
||||
struct ProfileProperties;
|
||||
struct InputConditionalTurnRestriction;
|
||||
struct InputTurnRestriction;
|
||||
struct InputManeuverOverride;
|
||||
|
||||
/**
|
||||
@@ -87,7 +87,7 @@ class ExtractorCallbacks
|
||||
void ProcessNode(const osmium::Node ¤t_node, const ExtractionNode &result_node);
|
||||
|
||||
// warning: caller needs to take care of synchronization!
|
||||
void ProcessRestriction(const InputConditionalTurnRestriction &restriction);
|
||||
void ProcessRestriction(const InputTurnRestriction &restriction);
|
||||
|
||||
// warning: caller needs to take care of synchronization!
|
||||
void ProcessWay(const osmium::Way ¤t_way, const ExtractionWay &result_way);
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
#ifndef FIRST_AND_LAST_SEGMENT_OF_WAY_HPP
|
||||
#define FIRST_AND_LAST_SEGMENT_OF_WAY_HPP
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct FirstAndLastSegmentOfWay
|
||||
{
|
||||
OSMWayID way_id;
|
||||
OSMNodeID first_segment_source_id;
|
||||
OSMNodeID first_segment_target_id;
|
||||
OSMNodeID last_segment_source_id;
|
||||
OSMNodeID last_segment_target_id;
|
||||
|
||||
FirstAndLastSegmentOfWay()
|
||||
: way_id(SPECIAL_OSM_WAYID), first_segment_source_id(SPECIAL_OSM_NODEID),
|
||||
first_segment_target_id(SPECIAL_OSM_NODEID), last_segment_source_id(SPECIAL_OSM_NODEID),
|
||||
last_segment_target_id(SPECIAL_OSM_NODEID)
|
||||
{
|
||||
}
|
||||
|
||||
FirstAndLastSegmentOfWay(OSMWayID w, OSMNodeID fs, OSMNodeID ft, OSMNodeID ls, OSMNodeID lt)
|
||||
: way_id(std::move(w)), first_segment_source_id(std::move(fs)),
|
||||
first_segment_target_id(std::move(ft)), last_segment_source_id(std::move(ls)),
|
||||
last_segment_target_id(std::move(lt))
|
||||
{
|
||||
}
|
||||
|
||||
static FirstAndLastSegmentOfWay min_value()
|
||||
{
|
||||
return {MIN_OSM_WAYID, MIN_OSM_NODEID, MIN_OSM_NODEID, MIN_OSM_NODEID, MIN_OSM_NODEID};
|
||||
}
|
||||
static FirstAndLastSegmentOfWay max_value()
|
||||
{
|
||||
return {MAX_OSM_WAYID, MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID};
|
||||
}
|
||||
};
|
||||
|
||||
struct FirstAndLastSegmentOfWayCompare
|
||||
{
|
||||
using value_type = FirstAndLastSegmentOfWay;
|
||||
bool operator()(const FirstAndLastSegmentOfWay &a, const FirstAndLastSegmentOfWay &b) const
|
||||
{
|
||||
return a.way_id < b.way_id;
|
||||
}
|
||||
value_type max_value() { return FirstAndLastSegmentOfWay::max_value(); }
|
||||
value_type min_value() { return FirstAndLastSegmentOfWay::min_value(); }
|
||||
};
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* FIRST_AND_LAST_SEGMENT_OF_WAY_HPP */
|
||||
@@ -28,7 +28,6 @@ class GraphCompressor
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
|
||||
util::NodeBasedDynamicGraph &graph,
|
||||
const std::vector<NodeBasedEdgeAnnotation> &node_data_container,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "extractor/intersection/intersection_edge.hpp"
|
||||
#include "extractor/intersection/intersection_view.hpp"
|
||||
#include "extractor/intersection/mergable_road_detector.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/node_restriction_map.hpp"
|
||||
#include "extractor/turn_lane_types.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "extractor/intersection/coordinate_extractor.hpp"
|
||||
#include "extractor/intersection/have_identical_names.hpp"
|
||||
#include "extractor/name_table.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/node_restriction_map.hpp"
|
||||
#include "extractor/turn_lane_types.hpp"
|
||||
|
||||
#include "guidance/intersection.hpp"
|
||||
|
||||
@@ -40,7 +40,6 @@ class NodeBasedGraphFactory
|
||||
NodeBasedGraphFactory(const boost::filesystem::path &input_file,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
||||
|
||||
auto const &GetGraph() const { return compressed_output_graph; }
|
||||
@@ -69,7 +68,6 @@ class NodeBasedGraphFactory
|
||||
// edges into a single representative form
|
||||
void Compress(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
||||
|
||||
// Most ways are bidirectional, making the geometry in forward and backward direction the same,
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#ifndef OSRM_EXTRACTOR_NODE_RESTRICTION_MAP_HPP_
|
||||
#define OSRM_EXTRACTOR_NODE_RESTRICTION_MAP_HPP_
|
||||
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "restriction_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/range/adaptor/filtered.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// Allows easy check for whether a node restriction is present at a given intersection
|
||||
template <typename RestrictionFilter> class NodeRestrictionMap
|
||||
{
|
||||
public:
|
||||
NodeRestrictionMap(const RestrictionGraph &restriction_graph)
|
||||
: restriction_graph(restriction_graph), index_filter(RestrictionFilter{})
|
||||
{
|
||||
}
|
||||
|
||||
// Find all restrictions applicable to (from,via,*) turns
|
||||
auto Restrictions(NodeID from, NodeID via) const
|
||||
{
|
||||
return getRange(from, via) | boost::adaptors::filtered(index_filter);
|
||||
};
|
||||
|
||||
// Find all restrictions applicable to (from,via,to) turns
|
||||
auto Restrictions(NodeID from, NodeID via, NodeID to) const
|
||||
{
|
||||
const auto turnFilter = [this, to](const auto &restriction) {
|
||||
return index_filter(restriction) && restriction->IsTurnRestricted(to);
|
||||
};
|
||||
return getRange(from, via) | boost::adaptors::filtered(turnFilter);
|
||||
};
|
||||
|
||||
private:
|
||||
RestrictionGraph::RestrictionRange getRange(NodeID from, NodeID via) const
|
||||
{
|
||||
const auto start_node_it = restriction_graph.start_edge_to_node.find({from, via});
|
||||
if (start_node_it != restriction_graph.start_edge_to_node.end())
|
||||
{
|
||||
return restriction_graph.GetRestrictions(start_node_it->second);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
const RestrictionGraph &restriction_graph;
|
||||
const RestrictionFilter index_filter;
|
||||
};
|
||||
|
||||
// Restriction filters to use as index defaults
|
||||
struct ConditionalOnly
|
||||
{
|
||||
bool operator()(const TurnRestriction *restriction) const
|
||||
{
|
||||
return !restriction->IsUnconditional();
|
||||
};
|
||||
};
|
||||
|
||||
struct UnconditionalOnly
|
||||
{
|
||||
bool operator()(const TurnRestriction *restriction) const
|
||||
{
|
||||
return restriction->IsUnconditional();
|
||||
};
|
||||
};
|
||||
|
||||
using RestrictionMap = NodeRestrictionMap<UnconditionalOnly>;
|
||||
using ConditionalRestrictionMap = NodeRestrictionMap<ConditionalOnly>;
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_NODE_RESTRICTION_MAP_HPP_
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef NODES_OF_WAY_HPP
|
||||
#define NODES_OF_WAY_HPP
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// NodesOfWay contains the ordered nodes of a way and provides convenience functions for getting
|
||||
// nodes in the first and last segments.
|
||||
struct NodesOfWay
|
||||
{
|
||||
OSMWayID way_id;
|
||||
std::vector<OSMNodeID> node_ids;
|
||||
|
||||
NodesOfWay() : way_id(SPECIAL_OSM_WAYID), node_ids{SPECIAL_OSM_NODEID, SPECIAL_OSM_NODEID} {}
|
||||
|
||||
NodesOfWay(OSMWayID w, std::vector<OSMNodeID> ns) : way_id(w), node_ids(std::move(ns)) {}
|
||||
|
||||
static NodesOfWay min_value() { return {MIN_OSM_WAYID, {MIN_OSM_NODEID, MIN_OSM_NODEID}}; }
|
||||
static NodesOfWay max_value() { return {MAX_OSM_WAYID, {MAX_OSM_NODEID, MAX_OSM_NODEID}}; }
|
||||
|
||||
const OSMNodeID &first_segment_source_id() const
|
||||
{
|
||||
BOOST_ASSERT(!node_ids.empty());
|
||||
return node_ids[0];
|
||||
}
|
||||
|
||||
const OSMNodeID &first_segment_target_id() const
|
||||
{
|
||||
BOOST_ASSERT(node_ids.size() > 1);
|
||||
return node_ids[1];
|
||||
}
|
||||
|
||||
const OSMNodeID &last_segment_source_id() const
|
||||
{
|
||||
BOOST_ASSERT(node_ids.size() > 1);
|
||||
return node_ids[node_ids.size() - 2];
|
||||
}
|
||||
|
||||
const OSMNodeID &last_segment_target_id() const
|
||||
{
|
||||
BOOST_ASSERT(!node_ids.empty());
|
||||
return node_ids[node_ids.size() - 1];
|
||||
}
|
||||
};
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* NODES_OF_WAY_HPP */
|
||||
@@ -30,17 +30,19 @@ struct InputNodeRestriction
|
||||
OSMWayID to;
|
||||
};
|
||||
|
||||
// A restriction that uses a single via-way in between
|
||||
// A restriction that uses one or more via-way in between
|
||||
//
|
||||
// f - e - d
|
||||
// e - f - g
|
||||
// |
|
||||
// d
|
||||
// |
|
||||
// a - b - c
|
||||
//
|
||||
// ab via be to ef -- no u turn
|
||||
// ab via bd,df to fe -- no u turn
|
||||
struct InputWayRestriction
|
||||
{
|
||||
OSMWayID from;
|
||||
OSMWayID via;
|
||||
std::vector<OSMWayID> via;
|
||||
OSMWayID to;
|
||||
};
|
||||
|
||||
@@ -57,6 +59,9 @@ struct InputTurnRestriction
|
||||
// keep in the same order as the turn restrictions below
|
||||
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
|
||||
{
|
||||
@@ -102,13 +107,15 @@ struct InputTurnRestriction
|
||||
return mapbox::util::get<InputNodeRestriction>(node_or_way);
|
||||
}
|
||||
};
|
||||
struct InputConditionalTurnRestriction : InputTurnRestriction
|
||||
{
|
||||
std::vector<util::OpeningHours> 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!
|
||||
//
|
||||
// a - b - c
|
||||
// |
|
||||
// d
|
||||
//
|
||||
// ab via b to bd
|
||||
struct NodeRestriction
|
||||
{
|
||||
NodeID from;
|
||||
@@ -131,39 +138,46 @@ struct NodeRestriction
|
||||
// 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 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;
|
||||
// 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(in_restriction, out_restriction) ==
|
||||
std::tie(other.in_restriction, other.out_restriction);
|
||||
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/multi-way restrictions
|
||||
// between node/way restrictions
|
||||
struct TurnRestriction
|
||||
{
|
||||
// keep in the same order as the turn restrictions above
|
||||
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)
|
||||
@@ -179,9 +193,40 @@ struct TurnRestriction
|
||||
|
||||
explicit TurnRestriction()
|
||||
{
|
||||
node_or_way = NodeRestriction{SPECIAL_EDGEID, SPECIAL_NODEID, SPECIAL_EDGEID};
|
||||
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);
|
||||
@@ -218,7 +263,7 @@ struct TurnRestriction
|
||||
if (node_or_way.which() == RestrictionType::WAY_RESTRICTION)
|
||||
{
|
||||
auto const &restriction = AsWayRestriction();
|
||||
return restriction.in_restriction.Valid() && restriction.out_restriction.Valid();
|
||||
return restriction.Valid();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -245,11 +290,6 @@ struct TurnRestriction
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct ConditionalTurnRestriction : TurnRestriction
|
||||
{
|
||||
std::vector<util::OpeningHours> condition;
|
||||
};
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace extractor
|
||||
struct NodeRestriction;
|
||||
struct TurnRestriction;
|
||||
|
||||
// OSRM stores restrictions in the form node -> node -> node instead of way -> node -> way (or
|
||||
// way->way->way) as it is done in OSM. These restrictions need to match the state of graph
|
||||
// OSRM stores restrictions as node -> [node] -> node instead of way -> node -> way (or
|
||||
// way->[way]->way) as it is done in OSM. These restrictions need to match the state of graph
|
||||
// compression which we perform in the graph compressor that removes certain degree two nodes from
|
||||
// the graph (all but the ones with penalties/barriers, as of the state of writing).
|
||||
// Since this graph compression ins performed after creating the restrictions in the extraction
|
||||
@@ -29,19 +29,22 @@ class RestrictionCompressor
|
||||
{
|
||||
public:
|
||||
RestrictionCompressor(std::vector<TurnRestriction> &restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
std::vector<UnresolvedManeuverOverride> &maneuver_overrides);
|
||||
|
||||
// account for the compression of `from-via-to` into `from-to`
|
||||
void Compress(const NodeID from, const NodeID via, const NodeID to);
|
||||
|
||||
private:
|
||||
// a turn restriction is given as `from star via node to end`. Edges ending at `head` being
|
||||
// A turn restriction is given as `from star via node to end`. Edges ending at `head` being
|
||||
// contracted move the head pointer to their respective head. Edges starting at tail move the
|
||||
// tail values to their respective tails. Way turn restrictions are represented by two
|
||||
// node-restrictions, so we can focus on them alone
|
||||
boost::unordered_multimap<NodeID, NodeRestriction *> starts;
|
||||
boost::unordered_multimap<NodeID, NodeRestriction *> ends;
|
||||
// tail values to their respective tails.
|
||||
// Via nodes that are compressed are removed from the restriction representation.
|
||||
// We do not compress the first and last via nodes of a restriction as they act as
|
||||
// entrance/exit points into the restriction graph. For a node restriction, the first and last
|
||||
// via nodes are the same.
|
||||
boost::unordered_multimap<NodeID, TurnRestriction *> starts;
|
||||
boost::unordered_multimap<NodeID, TurnRestriction *> vias;
|
||||
boost::unordered_multimap<NodeID, TurnRestriction *> ends;
|
||||
|
||||
boost::unordered_multimap<NodeID, NodeBasedTurn *> maneuver_starts;
|
||||
boost::unordered_multimap<NodeID, NodeBasedTurn *> maneuver_ends;
|
||||
|
||||
@@ -14,10 +14,8 @@ namespace extractor
|
||||
// To avoid handling invalid restrictions / creating unnecessary duplicate nodes for via-ways, we do
|
||||
// a pre-flight check for restrictions and remove all invalid restrictions from the data. Use as
|
||||
// `restrictions = removeInvalidRestrictions(std::move(restrictions))`
|
||||
std::vector<ConditionalTurnRestriction>
|
||||
removeInvalidRestrictions(std::vector<ConditionalTurnRestriction>,
|
||||
const util::NodeBasedDynamicGraph &);
|
||||
|
||||
std::vector<TurnRestriction> removeInvalidRestrictions(std::vector<TurnRestriction>,
|
||||
const util::NodeBasedDynamicGraph &);
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
#ifndef OSRM_EXTRACTOR_RESTRICTION_GRAPH_HPP_
|
||||
#define OSRM_EXTRACTOR_RESTRICTION_GRAPH_HPP_
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include "extractor/restriction_filter.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
namespace restriction_graph_details
|
||||
{
|
||||
struct transferBuilder;
|
||||
struct pathBuilder;
|
||||
} // namespace restriction_graph_details
|
||||
|
||||
struct RestrictionEdge
|
||||
{
|
||||
NodeID node_based_to;
|
||||
RestrictionID target;
|
||||
bool is_transfer;
|
||||
};
|
||||
|
||||
struct RestrictionNode
|
||||
{
|
||||
size_t restrictions_begin_idx;
|
||||
size_t num_restrictions;
|
||||
size_t edges_begin_idx;
|
||||
size_t num_edges;
|
||||
};
|
||||
|
||||
/**
|
||||
* The restriction graph is used to represent all possible restrictions within the routing graph.
|
||||
* The graph uses an edge-based node representation. Each node represents a compressed
|
||||
* node-based edge along a restriction path.
|
||||
*
|
||||
* Given a list of turn restrictions, the graph is created in multiple steps.
|
||||
*
|
||||
* INPUT
|
||||
* a -> b -> d: no_e
|
||||
* a -> b -> c: only_d
|
||||
* b -> c -> d: only_f
|
||||
* b -> c: no_g
|
||||
* e -> b -> d: no_g
|
||||
*
|
||||
* Step 1: create a disjoint union of prefix trees for all restriction paths.
|
||||
* The restriction instructions are added to the final node in its path.
|
||||
*
|
||||
* STEP 1
|
||||
* (a,b) -> (b,d,[no_e])
|
||||
* \->(b,c,[only_d])
|
||||
*
|
||||
* (b,c,[no_g]) -> (c,d,[only_f])
|
||||
* (e,b) -> (b,d,[no_g])
|
||||
*
|
||||
* Step 2: add transfers between restriction paths that overlap.
|
||||
* We do this by traversing each restriction path, tracking where the suffix of our current path
|
||||
* matches the prefix of any other. If it does, there's opportunity to transfer to the suffix
|
||||
* restriction path *if* the transfer would not be restricted *and* that edge does not take us
|
||||
* further on our current path. Nested restrictions are also added from any of the suffix paths.
|
||||
*
|
||||
* STEP 2
|
||||
* (a,b) -> (b,d,[no_e])
|
||||
* \->(b,c,[only_d,no_g])
|
||||
* \
|
||||
* (b,c,[no_g]) -> \-> (c,d,[only_f])
|
||||
*
|
||||
* (e,b) -> (b,d,[no_g])
|
||||
* If a transfer applies to multiple suffix paths, we only add the edge to the largest suffix path.
|
||||
* This ensures we correctly track all overlapping paths.
|
||||
*
|
||||
*
|
||||
* Step 3: The nodes are split into
|
||||
* start nodes - compressed edges that are entry points into a restriction path.
|
||||
* via nodes - compressed edges that are intermediate steps along a restriction path.
|
||||
* Start nodes and via nodes are indexed by the compressed node-based edge for easy retrieval
|
||||
*
|
||||
* STEP 3
|
||||
* Start Node Index
|
||||
* (a,b) => (a,b)
|
||||
* (b,c) => (b,c,[no_g])
|
||||
* (e,b) => (e,b)
|
||||
*
|
||||
* Via Nodes Index
|
||||
* (b,c) => (b,c,[only_d,no_g])
|
||||
* (b,d) => (b,d,[no_e]) , (b,d,[no_g])
|
||||
* (c,d) => (c,d,[only_f])
|
||||
*
|
||||
* Duplicate Nodes:
|
||||
* There is a 1-1 mapping between restriction graph via nodes and edge-based-graph duplicate nodes.
|
||||
* This relationship is used in the creation of restrictions in the routing edge-based graph.
|
||||
* */
|
||||
struct RestrictionGraph
|
||||
{
|
||||
friend restriction_graph_details::pathBuilder;
|
||||
friend restriction_graph_details::transferBuilder;
|
||||
friend RestrictionGraph constructRestrictionGraph(const std::vector<TurnRestriction> &);
|
||||
|
||||
using EdgeRange = boost::iterator_range<std::vector<RestrictionEdge>::const_iterator>;
|
||||
using RestrictionRange =
|
||||
boost::iterator_range<std::vector<const TurnRestriction *>::const_iterator>;
|
||||
using EdgeKey = std::pair<NodeID, NodeID>;
|
||||
|
||||
// Helper functions for iterating over node restrictions and edges
|
||||
EdgeRange GetEdges(RestrictionID id) const;
|
||||
RestrictionRange GetRestrictions(RestrictionID id) const;
|
||||
|
||||
// A compressed node-based edge can only have one start node in the restriction graph.
|
||||
boost::unordered_map<EdgeKey, RestrictionID> start_edge_to_node{};
|
||||
// A compressed node-based edge can have multiple via nodes in the restriction graph
|
||||
// (as the compressed edge can appear in paths with different prefixes).
|
||||
boost::unordered_multimap<EdgeKey, RestrictionID> via_edge_to_node{};
|
||||
std::vector<RestrictionNode> nodes;
|
||||
// TODO: Investigate reusing DynamicGraph. Currently it requires specific attributes
|
||||
// (e.g. reversed, weight) that would not make sense for restrictions.
|
||||
std::vector<RestrictionEdge> edges;
|
||||
std::vector<const TurnRestriction *> restrictions;
|
||||
size_t num_via_nodes{};
|
||||
|
||||
private:
|
||||
RestrictionGraph() = default;
|
||||
};
|
||||
|
||||
RestrictionGraph constructRestrictionGraph(const std::vector<TurnRestriction> &turn_restrictions);
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_RESTRICTION_GRAPH_HPP_
|
||||
@@ -1,101 +0,0 @@
|
||||
#ifndef OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
|
||||
#define OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
|
||||
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// allows easy check for whether a node intersection is present at a given intersection
|
||||
template <typename restriction_type> class RestrictionIndex
|
||||
{
|
||||
public:
|
||||
using value_type = restriction_type;
|
||||
|
||||
template <typename extractor_type>
|
||||
RestrictionIndex(std::vector<restriction_type> &restrictions, extractor_type extractor);
|
||||
|
||||
bool IsIndexed(NodeID first, NodeID second) const;
|
||||
|
||||
auto Restrictions(NodeID first, NodeID second) const
|
||||
{
|
||||
return restriction_hash.equal_range(std::make_pair(first, second));
|
||||
};
|
||||
|
||||
auto Size() const { return restriction_hash.size(); }
|
||||
|
||||
private:
|
||||
boost::unordered_multimap<std::pair<NodeID, NodeID>, restriction_type *> restriction_hash;
|
||||
};
|
||||
|
||||
template <typename restriction_type>
|
||||
template <typename extractor_type>
|
||||
RestrictionIndex<restriction_type>::RestrictionIndex(std::vector<restriction_type> &restrictions,
|
||||
extractor_type extractor)
|
||||
{
|
||||
// build a multi-map
|
||||
for (auto &restriction : restrictions)
|
||||
restriction_hash.insert(std::make_pair(extractor(restriction), &restriction));
|
||||
}
|
||||
|
||||
template <typename restriction_type>
|
||||
bool RestrictionIndex<restriction_type>::IsIndexed(const NodeID first, const NodeID second) const
|
||||
{
|
||||
return restriction_hash.count(std::make_pair(first, second));
|
||||
}
|
||||
|
||||
struct IndexNodeByFromAndVia
|
||||
{
|
||||
std::pair<NodeID, NodeID> operator()(const TurnRestriction &restriction)
|
||||
{
|
||||
const auto &node = restriction.AsNodeRestriction();
|
||||
return std::make_pair(node.from, node.via);
|
||||
};
|
||||
};
|
||||
|
||||
// check wheter a turn is restricted within a restriction_index
|
||||
template <typename restriction_map_type>
|
||||
std::pair<bool, typename restriction_map_type::value_type *>
|
||||
isRestricted(const NodeID from,
|
||||
const NodeID via,
|
||||
const NodeID to,
|
||||
const restriction_map_type &restriction_map)
|
||||
{
|
||||
const auto range = restriction_map.Restrictions(from, via);
|
||||
|
||||
// check if a given node_restriction is targeting node
|
||||
const auto to_is_restricted = [to](const auto &pair) {
|
||||
const auto &restriction = *pair.second;
|
||||
if (restriction.Type() == RestrictionType::NODE_RESTRICTION)
|
||||
{
|
||||
auto const &as_node = restriction.AsNodeRestriction();
|
||||
auto const restricted = restriction.is_only ? (to != as_node.to) : (to == as_node.to);
|
||||
|
||||
return restricted;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto itr = std::find_if(range.first, range.second, to_is_restricted);
|
||||
|
||||
if (itr != range.second)
|
||||
return {true, itr->second};
|
||||
else
|
||||
return {false, NULL};
|
||||
}
|
||||
|
||||
using RestrictionMap = RestrictionIndex<TurnRestriction>;
|
||||
using ConditionalRestrictionMap = RestrictionIndex<ConditionalTurnRestriction>;
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_RESTRICTION_INDEX_HPP_
|
||||
@@ -44,8 +44,7 @@ class RestrictionParser
|
||||
RestrictionParser(bool use_turn_restrictions,
|
||||
bool parse_conditionals,
|
||||
std::vector<std::string> &restrictions);
|
||||
boost::optional<InputConditionalTurnRestriction>
|
||||
TryParse(const osmium::Relation &relation) const;
|
||||
boost::optional<InputTurnRestriction> TryParse(const osmium::Relation &relation) const;
|
||||
|
||||
private:
|
||||
bool ShouldIgnoreRestriction(const std::string &except_tag_string) const;
|
||||
|
||||
@@ -68,7 +68,7 @@ class ScriptingEnvironment
|
||||
const ExtractionRelationContainer &relations,
|
||||
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
||||
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions,
|
||||
std::vector<InputTurnRestriction> &resulting_restrictions,
|
||||
std::vector<InputManeuverOverride> &resulting_maneuver_overrides) = 0;
|
||||
|
||||
virtual bool HasLocationDependentData() const = 0;
|
||||
|
||||
@@ -92,7 +92,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
||||
const ExtractionRelationContainer &relations,
|
||||
std::vector<std::pair<const osmium::Node &, ExtractionNode>> &resulting_nodes,
|
||||
std::vector<std::pair<const osmium::Way &, ExtractionWay>> &resulting_ways,
|
||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions,
|
||||
std::vector<InputTurnRestriction> &resulting_restrictions,
|
||||
std::vector<InputManeuverOverride> &resulting_maneuver_overrides) override;
|
||||
|
||||
bool HasLocationDependentData() const override { return !location_dependent_data.empty(); }
|
||||
|
||||
@@ -8,82 +8,66 @@
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include "extractor/restriction.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/restriction_graph.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
// Given the compressed representation of via-way turn restrictions, we provide a fast access into
|
||||
// the restrictions to indicate which turns may be restricted due to a way in between
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// The WayRestrictionMap uses ConditionalTurnRestrictions in general. Most restrictions will have
|
||||
// empty conditions, though.
|
||||
// Given the compressed representation of via-way turn restrictions, we provide a fast access into
|
||||
// the restrictions to indicate which turns may be restricted due to a way in between.
|
||||
class WayRestrictionMap
|
||||
{
|
||||
public:
|
||||
struct ViaWay
|
||||
struct ViaEdge
|
||||
{
|
||||
NodeID from;
|
||||
NodeID to;
|
||||
};
|
||||
WayRestrictionMap(const std::vector<ConditionalTurnRestriction> &conditional_restrictions);
|
||||
WayRestrictionMap(const RestrictionGraph &restriction_graph);
|
||||
|
||||
// Check if an edge between two nodes is a restricted turn. The check needs to be performed to
|
||||
// Check if an edge between two nodes is part of a via-way. The check needs to be performed to
|
||||
// find duplicated nodes during the creation of edge-based-edges
|
||||
bool IsViaWay(const NodeID from, const NodeID to) const;
|
||||
bool IsViaWayEdge(NodeID from, NodeID to) const;
|
||||
|
||||
// Every via-way results in a duplicated node that is required in the edge-based-graph. This
|
||||
// count is essentially the same as the number of valid via-way restrictions (except for
|
||||
// non-only restrictions that share the same in/via combination)
|
||||
// There is a bijection between restriction graph via-nodes and edge-based duplicated nodes.
|
||||
// This counts the number of duplicated nodes contributed by the way restrictions.
|
||||
std::size_t NumberOfDuplicatedNodes() const;
|
||||
|
||||
// Returns a representative for each duplicated node, consisting of the representative ID (first
|
||||
// ID of the nodes restrictions) and the from/to vertices of the via-way
|
||||
// This is used to construct edge based nodes that act as intermediate nodes.
|
||||
std::vector<ViaWay> DuplicatedNodeRepresentatives() const;
|
||||
// For each restriction graph via-node, we return its node-based edge representation (from,to).
|
||||
// This is used to create the duplicate node in the edge based graph.
|
||||
std::vector<ViaEdge> DuplicatedViaEdges() const;
|
||||
|
||||
// Access all duplicated NodeIDs for a set of nodes indicating a via way
|
||||
std::vector<DuplicatedNodeID> DuplicatedNodeIDs(const NodeID from, const NodeID to) const;
|
||||
// Access all duplicated NodeIDs from the restriction graph via-node represented by (from,to)
|
||||
std::vector<DuplicatedNodeID> DuplicatedNodeIDs(NodeID from, NodeID to) const;
|
||||
|
||||
// check whether a turn onto a given node is restricted, when coming from a duplicated node
|
||||
bool IsRestricted(DuplicatedNodeID duplicated_node, const NodeID to) const;
|
||||
// Get the restriction resulting in ^ IsRestricted. Requires IsRestricted to evaluate to true
|
||||
const ConditionalTurnRestriction &GetRestriction(DuplicatedNodeID duplicated_node,
|
||||
const NodeID to) const;
|
||||
// Check whether a turn onto a given node is restricted, when coming from a duplicated node
|
||||
bool IsRestricted(DuplicatedNodeID duplicated_node, NodeID to) const;
|
||||
|
||||
// changes edge_based_node to the correct duplicated_node_id in case node_based_from,
|
||||
// node_based_via, node_based_to can be identified with a restriction group
|
||||
NodeID RemapIfRestricted(const NodeID edge_based_node,
|
||||
const NodeID node_based_from,
|
||||
const NodeID node_based_via,
|
||||
const NodeID node_based_to,
|
||||
const NodeID number_of_edge_based_nodes) const;
|
||||
// Get the restrictions resulting in ^ IsRestricted. Requires IsRestricted to evaluate to true
|
||||
std::vector<const TurnRestriction *> GetRestrictions(DuplicatedNodeID duplicated_node,
|
||||
NodeID to) const;
|
||||
|
||||
// Changes edge_based_node to the correct duplicated_node_id in case node_based_from,
|
||||
// node_based_via, node_based_to can be identified as the start of a way restriction.
|
||||
NodeID RemapIfRestrictionStart(NodeID edge_based_node,
|
||||
NodeID node_based_from,
|
||||
NodeID node_based_via,
|
||||
NodeID node_based_to,
|
||||
NodeID number_of_edge_based_nodes) const;
|
||||
|
||||
// Changes edge_based_node to the correct duplicated_node_id in case node_based_from,
|
||||
// node_based_via, node_based_to can be identified as successive via steps of a way restriction.
|
||||
NodeID RemapIfRestrictionVia(NodeID edge_based_target_node,
|
||||
NodeID edge_based_via_node,
|
||||
NodeID node_based_to,
|
||||
NodeID number_of_edge_based_nodes) const;
|
||||
|
||||
private:
|
||||
DuplicatedNodeID AsDuplicatedNodeID(const RestrictionID restriction_id) const;
|
||||
|
||||
// access all restrictions that have the same starting way and via way. Any duplicated node
|
||||
// represents the same in-way + via-way combination. This vector contains data about all
|
||||
// restrictions and their assigned duplicated nodes. It indicates the minimum restriciton ID
|
||||
// that is represented by the next node. The ID of a node is defined as the position of the
|
||||
// lower bound of the restrictions ID within this array
|
||||
//
|
||||
// a - b
|
||||
// |
|
||||
// y - c - x
|
||||
//
|
||||
// restriction nodes | restriction id
|
||||
// a - b - c - x : 5
|
||||
// a - b - c - y : 6
|
||||
//
|
||||
// EBN: 0 . | 2 | 3 | 4 ...
|
||||
// duplicated node groups: ... | 5 | 7 | ...
|
||||
std::vector<DuplicatedNodeID> duplicated_node_groups;
|
||||
std::vector<ConditionalTurnRestriction> restriction_data;
|
||||
RestrictionIndex<ConditionalTurnRestriction> restriction_starts;
|
||||
const RestrictionGraph &restriction_graph;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/name_table.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/node_restriction_map.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
#include "extractor/turn_lane_types.hpp"
|
||||
#include "extractor/way_restriction_map.hpp"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/intersection/intersection_view.hpp"
|
||||
#include "extractor/name_table.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/node_restriction_map.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
|
||||
#include "guidance/driveway_handler.hpp"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef OSRM_GUIDANCE_TURN_DISCOVERY_HPP_
|
||||
#define OSRM_GUIDANCE_TURN_DISCOVERY_HPP_
|
||||
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/node_restriction_map.hpp"
|
||||
#include "guidance/intersection.hpp"
|
||||
#include "guidance/turn_lane_data.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef FOR_EACH_INDEXED_HPP
|
||||
#define FOR_EACH_INDEXED_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
|
||||
template <typename ForwardIterator, typename Function>
|
||||
void for_each_indexed(ForwardIterator first, ForwardIterator last, Function function)
|
||||
{
|
||||
for (size_t i = 0; first != last; ++first, ++i)
|
||||
{
|
||||
function(i, *first);
|
||||
}
|
||||
}
|
||||
|
||||
template <class ContainerT, typename Function>
|
||||
void for_each_pair(ContainerT &container, Function function)
|
||||
{
|
||||
for_each_indexed(std::begin(container), std::end(container), function);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace osrm
|
||||
|
||||
#endif /* FOR_EACH_INDEXED_HPP */
|
||||
@@ -61,8 +61,8 @@ void inplacePermutation(RandomAccessIterator begin,
|
||||
template <typename IndexT>
|
||||
std::vector<IndexT> orderingToPermutation(const std::vector<IndexT> &ordering)
|
||||
{
|
||||
std::vector<std::uint32_t> permutation(ordering.size());
|
||||
for (auto index : util::irange<std::uint32_t>(0, ordering.size()))
|
||||
std::vector<IndexT> permutation(ordering.size());
|
||||
for (auto index : util::irange<IndexT>(0, ordering.size()))
|
||||
permutation[ordering[index]] = index;
|
||||
|
||||
return permutation;
|
||||
|
||||
@@ -103,6 +103,7 @@ static const NodeID SPECIAL_NODEID = std::numeric_limits<NodeID>::max();
|
||||
static const NodeID SPECIAL_SEGMENTID = std::numeric_limits<NodeID>::max() >> 1;
|
||||
static const NodeID SPECIAL_GEOMETRYID = std::numeric_limits<NodeID>::max() >> 1;
|
||||
static const EdgeID SPECIAL_EDGEID = std::numeric_limits<EdgeID>::max();
|
||||
static const RestrictionID SPECIAL_RESTRICTIONID = std::numeric_limits<RestrictionID>::max();
|
||||
static const NameID INVALID_NAMEID = std::numeric_limits<NameID>::max();
|
||||
static const NameID EMPTY_NAMEID = 0;
|
||||
static const unsigned INVALID_COMPONENTID = 0;
|
||||
|
||||
Reference in New Issue
Block a user