simplify passing annotation data through OSRM pipeline using the node-based datastore
- separates node-based graph creation and compression from edge-based graph creation - moves usage of edge-based node data-container to pre-processing as well, unifying access to node-based data - single struct instead of separate vectors for annotation data in engine (single place of modification)
This commit is contained in:
committed by
Michael Krasnyk
parent
9b044aaa42
commit
2ddd98ee6d
@@ -14,8 +14,6 @@
|
||||
#include "extractor/nbg_to_ebg.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/original_edge_data.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
#include "extractor/restriction_index.hpp"
|
||||
#include "extractor/way_restriction_map.hpp"
|
||||
@@ -26,7 +24,6 @@
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
#include "util/name_table.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
#include "util/packed_vector.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "storage/io.hpp"
|
||||
@@ -71,13 +68,12 @@ class EdgeBasedGraphFactory
|
||||
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
|
||||
EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete;
|
||||
|
||||
explicit EdgeBasedGraphFactory(std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
|
||||
CompressedEdgeContainer &compressed_edge_container,
|
||||
explicit EdgeBasedGraphFactory(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
EdgeBasedNodeDataContainer &node_data_container,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::unordered_set<NodeID> &traffic_lights,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const extractor::PackedOSMIDs &osm_node_ids,
|
||||
ProfileProperties profile_properties,
|
||||
const util::NameTable &name_table,
|
||||
guidance::LaneDescriptionMap &lane_description_map);
|
||||
|
||||
@@ -95,7 +91,6 @@ class EdgeBasedGraphFactory
|
||||
|
||||
// The following get access functions destroy the content in the factory
|
||||
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
|
||||
void GetEdgeBasedNodes(EdgeBasedNodeDataContainer &data_container);
|
||||
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
|
||||
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
|
||||
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
|
||||
@@ -144,7 +139,7 @@ class EdgeBasedGraphFactory
|
||||
|
||||
//! list of edge based nodes (compressed segments)
|
||||
std::vector<EdgeBasedNodeSegment> m_edge_based_node_segments;
|
||||
EdgeBasedNodeDataContainer m_edge_based_node_container;
|
||||
EdgeBasedNodeDataContainer &m_edge_based_node_container;
|
||||
util::DeallocatingVector<EdgeBasedEdge> m_edge_based_edge_list;
|
||||
|
||||
// The number of edge-based nodes is mostly made up out of the edges in the node-based graph.
|
||||
@@ -155,19 +150,20 @@ class EdgeBasedGraphFactory
|
||||
std::uint64_t m_number_of_edge_based_nodes;
|
||||
|
||||
const std::vector<util::Coordinate> &m_coordinates;
|
||||
const extractor::PackedOSMIDs &m_osm_node_ids;
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
|
||||
const util::NodeBasedDynamicGraph &m_node_based_graph;
|
||||
|
||||
const std::unordered_set<NodeID> &m_barrier_nodes;
|
||||
const std::unordered_set<NodeID> &m_traffic_lights;
|
||||
CompressedEdgeContainer &m_compressed_edge_container;
|
||||
|
||||
ProfileProperties profile_properties;
|
||||
const CompressedEdgeContainer &m_compressed_edge_container;
|
||||
|
||||
const util::NameTable &name_table;
|
||||
guidance::LaneDescriptionMap &lane_description_map;
|
||||
|
||||
unsigned RenumberEdges();
|
||||
// In the edge based graph, any traversable (non reversed) edge of the node-based graph forms a
|
||||
// node of the edge-based graph. To be able to name these nodes, we loop over the node-based
|
||||
// graph and create a mapping from edges (node-based) to nodes (edge-based). The mapping is
|
||||
// essentially a prefix-sum over all previous non-reversed edges of the node-based graph.
|
||||
unsigned LabelEdgeBasedNodes();
|
||||
|
||||
// During the generation of the edge-expanded nodes, we need to also generate duplicates that
|
||||
// represent state during via-way restrictions (see
|
||||
@@ -194,6 +190,8 @@ class EdgeBasedGraphFactory
|
||||
std::size_t skipped_uturns_counter;
|
||||
std::size_t skipped_barrier_turns_counter;
|
||||
|
||||
// mapping of node-based edges to edge-based nodes
|
||||
std::vector<NodeID> nbe_to_ebn_mapping;
|
||||
util::ConcurrentIDMap<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
|
||||
std::vector<BearingClassID> bearing_class_by_node_based_node;
|
||||
util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID> entry_class_hash;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef OSRM_EXTRACTOR_EDGE_BASED_NODE_HPP_
|
||||
#define OSRM_EXTRACTOR_EDGE_BASED_NODE_HPP_
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
struct EdgeBasedNode
|
||||
{
|
||||
GeometryID geometry_id;
|
||||
ComponentID component_id;
|
||||
AnnotationID annotation_id;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_EDGE_BASED_NODE_HPP_
|
||||
@@ -28,12 +28,14 @@ class ExtractionContainers
|
||||
|
||||
void WriteNodes(storage::io::FileWriter &file_out) const;
|
||||
void WriteEdges(storage::io::FileWriter &file_out) const;
|
||||
void WriteMetadata(storage::io::FileWriter &file_out) const;
|
||||
void WriteCharData(const std::string &file_name);
|
||||
|
||||
public:
|
||||
using NodeIDVector = std::vector<OSMNodeID>;
|
||||
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>;
|
||||
@@ -43,6 +45,7 @@ class ExtractionContainers
|
||||
NodeIDVector used_node_id_list;
|
||||
NodeVector all_nodes_list;
|
||||
EdgeVector all_edges_list;
|
||||
AnnotationDataVector all_edges_annotation_data_list;
|
||||
NameCharData name_char_data;
|
||||
NameOffsets name_offsets;
|
||||
// an adjacency array containing all turn lane masks
|
||||
|
||||
@@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "extractor/edge_based_graph_factory.hpp"
|
||||
#include "extractor/extractor_config.hpp"
|
||||
#include "extractor/graph_compressor.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
|
||||
#include "util/guidance/bearing_class.hpp"
|
||||
#include "util/guidance/entry_class.hpp"
|
||||
@@ -61,19 +62,27 @@ class Extractor
|
||||
std::vector<ConditionalTurnRestriction>>
|
||||
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
|
||||
|
||||
std::pair<std::size_t, EdgeID>
|
||||
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
extractor::PackedOSMIDs &osm_node_ids,
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
guidance::LaneDescriptionMap &turn_lane_map);
|
||||
EdgeID BuildEdgeExpandedGraph(
|
||||
// input data
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
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,
|
||||
// might have to be updated to add new lane combinations
|
||||
guidance::LaneDescriptionMap &turn_lane_map,
|
||||
// for calculating turn penalties
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
// output data
|
||||
EdgeBasedNodeDataContainer &edge_based_nodes_container,
|
||||
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
|
||||
std::vector<bool> &node_is_startpoint,
|
||||
std::vector<EdgeWeight> &edge_based_node_weights,
|
||||
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
|
||||
const std::string &intersection_class_output_file);
|
||||
|
||||
void FindComponents(unsigned max_edge_id,
|
||||
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
|
||||
const std::vector<EdgeBasedNodeSegment> &input_node_segments,
|
||||
@@ -82,11 +91,6 @@ class Extractor
|
||||
std::vector<bool> node_is_startpoint,
|
||||
const std::vector<util::Coordinate> &coordinates);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
std::shared_ptr<util::NodeBasedDynamicGraph>
|
||||
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||
std::unordered_set<NodeID> &traffic_lights,
|
||||
std::vector<util::Coordinate> &coordinates,
|
||||
extractor::PackedOSMIDs &osm_node_ids);
|
||||
|
||||
// Writes compressed node based graph and its embedding into a file for osrm-partition to use.
|
||||
static void WriteCompressedNodeBasedGraph(const std::string &path,
|
||||
|
||||
@@ -78,27 +78,27 @@ inline void writeProfileProperties(const boost::filesystem::path &path,
|
||||
|
||||
template <typename EdgeBasedEdgeVector>
|
||||
void writeEdgeBasedGraph(const boost::filesystem::path &path,
|
||||
EdgeID const max_edge_id,
|
||||
EdgeID const number_of_edge_based_nodes,
|
||||
const EdgeBasedEdgeVector &edge_based_edge_list)
|
||||
{
|
||||
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
||||
|
||||
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint);
|
||||
|
||||
writer.WriteElementCount64(max_edge_id);
|
||||
writer.WriteElementCount64(number_of_edge_based_nodes);
|
||||
storage::serialization::write(writer, edge_based_edge_list);
|
||||
}
|
||||
|
||||
template <typename EdgeBasedEdgeVector>
|
||||
void readEdgeBasedGraph(const boost::filesystem::path &path,
|
||||
EdgeID &max_edge_id,
|
||||
EdgeID &number_of_edge_based_nodes,
|
||||
EdgeBasedEdgeVector &edge_based_edge_list)
|
||||
{
|
||||
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
|
||||
|
||||
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint);
|
||||
|
||||
max_edge_id = reader.ReadElementCount64();
|
||||
number_of_edge_based_nodes = reader.ReadElementCount64();
|
||||
storage::serialization::read(reader, edge_based_edge_list);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ class GraphCompressor
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
|
||||
util::NodeBasedDynamicGraph &graph,
|
||||
const std::vector<NodeBasedEdgeAnnotation> &node_data_container,
|
||||
CompressedEdgeContainer &geometry_compressor);
|
||||
|
||||
private:
|
||||
|
||||
@@ -225,7 +225,7 @@ class CoordinateExtractor
|
||||
const std::vector<double> &segment_distances,
|
||||
const double segment_length,
|
||||
const double considered_lane_width,
|
||||
const util::NodeBasedEdgeData &edge_data) const;
|
||||
const extractor::NodeBasedEdgeClassification &edge_data) const;
|
||||
|
||||
/*
|
||||
* If the very first coordinate is within lane offsets and the rest offers a near straight line,
|
||||
|
||||
@@ -16,6 +16,7 @@ class DrivewayHandler final : public IntersectionHandler
|
||||
public:
|
||||
DrivewayHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
@@ -38,6 +38,7 @@ class IntersectionGenerator
|
||||
{
|
||||
public:
|
||||
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
@@ -110,6 +111,7 @@ class IntersectionGenerator
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const RestrictionMap &restriction_map;
|
||||
const std::unordered_set<NodeID> &barrier_nodes;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
|
||||
@@ -33,6 +33,7 @@ class IntersectionHandler
|
||||
{
|
||||
public:
|
||||
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
@@ -50,6 +51,7 @@ class IntersectionHandler
|
||||
|
||||
protected:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const std::vector<util::Coordinate> &coordinates;
|
||||
const util::NameTable &name_table;
|
||||
const SuffixTable &street_name_suffix_table;
|
||||
@@ -124,7 +126,6 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
const IntersectionType &intersection) const
|
||||
{
|
||||
using Road = typename IntersectionType::value_type;
|
||||
using EdgeData = osrm::util::NodeBasedDynamicGraph::EdgeData;
|
||||
using osrm::util::angularDeviation;
|
||||
|
||||
// no obvious road
|
||||
@@ -135,7 +136,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
if (intersection.size() == 2)
|
||||
return 1;
|
||||
|
||||
const EdgeData &in_way_data = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &in_way_edge = node_based_graph.GetEdgeData(via_edge);
|
||||
const auto &in_way_data = node_data_container.GetAnnotation(in_way_edge.annotation_data);
|
||||
|
||||
// the strategy for picking the most obvious turn involves deciding between
|
||||
// an overall best candidate and a best candidate that shares the same name
|
||||
@@ -146,35 +148,35 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
double best_continue_deviation = 180;
|
||||
|
||||
/* helper functions */
|
||||
const auto IsContinueRoad = [&](const EdgeData &way_data) {
|
||||
const auto IsContinueRoad = [&](const NodeBasedEdgeAnnotation &way_data) {
|
||||
return !util::guidance::requiresNameAnnounced(
|
||||
in_way_data.name_id, way_data.name_id, name_table, street_name_suffix_table);
|
||||
};
|
||||
auto sameOrHigherPriority = [&in_way_data](const auto &way_data) {
|
||||
return way_data.road_classification.GetPriority() <=
|
||||
in_way_data.road_classification.GetPriority();
|
||||
auto sameOrHigherPriority = [&](const auto &way_data) {
|
||||
return way_data.flags.road_classification.GetPriority() <=
|
||||
in_way_edge.flags.road_classification.GetPriority();
|
||||
};
|
||||
auto IsLowPriority = [](const auto &way_data) {
|
||||
return way_data.road_classification.IsLowPriorityRoadClass();
|
||||
return way_data.flags.road_classification.IsLowPriorityRoadClass();
|
||||
};
|
||||
// These two Compare functions are used for sifting out best option and continue
|
||||
// candidates by evaluating all the ways in an intersection by what they share
|
||||
// with the in way. Ideal candidates are of similar road class with the in way
|
||||
// and are require relatively straight turns.
|
||||
const auto RoadCompare = [&](const auto &lhs, const auto &rhs) {
|
||||
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
|
||||
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
|
||||
const auto &lhs_edge = node_based_graph.GetEdgeData(lhs.eid);
|
||||
const auto &rhs_edge = node_based_graph.GetEdgeData(rhs.eid);
|
||||
const auto lhs_deviation = angularDeviation(lhs.angle, STRAIGHT_ANGLE);
|
||||
const auto rhs_deviation = angularDeviation(rhs.angle, STRAIGHT_ANGLE);
|
||||
|
||||
const bool rhs_same_classification =
|
||||
rhs_data.road_classification == in_way_data.road_classification;
|
||||
rhs_edge.flags.road_classification == in_way_edge.flags.road_classification;
|
||||
const bool lhs_same_classification =
|
||||
lhs_data.road_classification == in_way_data.road_classification;
|
||||
const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_data);
|
||||
const bool rhs_low_priority = IsLowPriority(rhs_data);
|
||||
const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_data);
|
||||
const bool lhs_low_priority = IsLowPriority(lhs_data);
|
||||
lhs_edge.flags.road_classification == in_way_edge.flags.road_classification;
|
||||
const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_edge);
|
||||
const bool rhs_low_priority = IsLowPriority(rhs_edge);
|
||||
const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_edge);
|
||||
const bool lhs_low_priority = IsLowPriority(lhs_edge);
|
||||
auto left_tie = std::tie(lhs.entry_allowed,
|
||||
lhs_same_or_higher_priority,
|
||||
rhs_low_priority,
|
||||
@@ -188,8 +190,10 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
return left_tie > right_tie;
|
||||
};
|
||||
const auto RoadCompareSameName = [&](const auto &lhs, const auto &rhs) {
|
||||
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid);
|
||||
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid);
|
||||
const auto &lhs_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(lhs.eid).annotation_data);
|
||||
const auto &rhs_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(rhs.eid).annotation_data);
|
||||
const auto lhs_continues = IsContinueRoad(lhs_data);
|
||||
const auto rhs_continues = IsContinueRoad(rhs_data);
|
||||
const auto left_tie = std::tie(lhs.entry_allowed, lhs_continues);
|
||||
@@ -204,12 +208,14 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
|
||||
best_option = std::distance(begin(intersection), best_option_it);
|
||||
best_option_deviation = angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE);
|
||||
const auto &best_option_data = node_based_graph.GetEdgeData(intersection[best_option].eid);
|
||||
const auto &best_option_edge = node_based_graph.GetEdgeData(intersection[best_option].eid);
|
||||
const auto &best_option_data =
|
||||
node_data_container.GetAnnotation(best_option_edge.annotation_data);
|
||||
|
||||
// Unless the in way is also low priority, it is generally undesirable to
|
||||
// indicate that a low priority road is obvious
|
||||
if (IsLowPriority(best_option_data) &&
|
||||
best_option_data.road_classification != in_way_data.road_classification)
|
||||
if (IsLowPriority(best_option_edge) &&
|
||||
best_option_edge.flags.road_classification != in_way_edge.flags.road_classification)
|
||||
{
|
||||
best_option = 0;
|
||||
best_option_deviation = 180;
|
||||
@@ -219,13 +225,13 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
const auto straightest = intersection.findClosestTurn(STRAIGHT_ANGLE);
|
||||
if (straightest != best_option_it)
|
||||
{
|
||||
const EdgeData &straightest_data = node_based_graph.GetEdgeData(straightest->eid);
|
||||
const auto &straightest_edge = node_based_graph.GetEdgeData(straightest->eid);
|
||||
double straightest_data_deviation = angularDeviation(straightest->angle, STRAIGHT_ANGLE);
|
||||
const auto deviation_diff =
|
||||
std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE;
|
||||
const auto not_ramp_class = !straightest_data.road_classification.IsRampClass();
|
||||
const auto not_link_class = !straightest_data.road_classification.IsLinkClass();
|
||||
if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class &&
|
||||
const auto not_ramp_class = !straightest_edge.flags.road_classification.IsRampClass();
|
||||
const auto not_link_class = !straightest_edge.flags.road_classification.IsLinkClass();
|
||||
if (deviation_diff && !IsLowPriority(straightest_edge) && not_ramp_class &&
|
||||
not_link_class && !IsContinueRoad(best_option_data))
|
||||
{
|
||||
best_option = std::distance(begin(intersection), straightest);
|
||||
@@ -240,7 +246,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
|
||||
auto best_continue_it =
|
||||
std::min_element(begin(intersection), end(intersection), RoadCompareSameName);
|
||||
const auto best_continue_data = node_based_graph.GetEdgeData(best_continue_it->eid);
|
||||
const auto best_continue_edge = node_based_graph.GetEdgeData(best_continue_it->eid);
|
||||
const auto best_continue_data =
|
||||
node_data_container.GetAnnotation(best_continue_edge.annotation_data);
|
||||
if (IsContinueRoad(best_continue_data) ||
|
||||
(in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID))
|
||||
{
|
||||
@@ -252,8 +260,7 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// if the best angle is going straight but the road is turning, declare no obvious turn
|
||||
if (0 != best_continue && best_option != best_continue &&
|
||||
best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
|
||||
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification ==
|
||||
best_option_data.road_classification)
|
||||
best_continue_edge.flags.road_classification == best_option_edge.flags.road_classification)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -262,17 +269,21 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// continue instruction because they share a name with the approaching way
|
||||
const std::int64_t continue_count =
|
||||
count_if(++begin(intersection), end(intersection), [&](const auto &way) {
|
||||
return IsContinueRoad(node_based_graph.GetEdgeData(way.eid));
|
||||
return IsContinueRoad(node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(way.eid).annotation_data));
|
||||
});
|
||||
const std::int64_t continue_count_valid =
|
||||
count_if(++begin(intersection), end(intersection), [&](const auto &way) {
|
||||
return IsContinueRoad(node_based_graph.GetEdgeData(way.eid)) && way.entry_allowed;
|
||||
return IsContinueRoad(node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(way.eid).annotation_data)) &&
|
||||
way.entry_allowed;
|
||||
});
|
||||
|
||||
// checks if continue candidates are sharp turns
|
||||
const bool all_continues_are_narrow = [&]() {
|
||||
return std::count_if(begin(intersection), end(intersection), [&](const Road &road) {
|
||||
const EdgeData &road_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &road_data = node_data_container.GetAnnotation(
|
||||
node_based_graph.GetEdgeData(road.eid).annotation_data);
|
||||
const double &road_angle = angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||
return IsContinueRoad(road_data) && (road_angle < NARROW_TURN_ANGLE);
|
||||
}) == continue_count;
|
||||
@@ -296,32 +307,32 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
return true;
|
||||
|
||||
// continue data now most certainly exists
|
||||
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
|
||||
const auto &continue_edge = node_based_graph.GetEdgeData(intersection[best_continue].eid);
|
||||
|
||||
// best_continue is obvious by road class
|
||||
if (obviousByRoadClass(in_way_data.road_classification,
|
||||
continue_data.road_classification,
|
||||
best_option_data.road_classification))
|
||||
if (obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
continue_edge.flags.road_classification,
|
||||
best_option_edge.flags.road_classification))
|
||||
return false;
|
||||
|
||||
// best_option is obvious by road class
|
||||
if (obviousByRoadClass(in_way_data.road_classification,
|
||||
best_option_data.road_classification,
|
||||
continue_data.road_classification))
|
||||
if (obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
best_option_edge.flags.road_classification,
|
||||
continue_edge.flags.road_classification))
|
||||
return true;
|
||||
|
||||
// the best_option deviation is very straight and not a ramp
|
||||
if (best_option_deviation < best_continue_deviation &&
|
||||
best_option_deviation < FUZZY_ANGLE_DIFFERENCE &&
|
||||
!best_option_data.road_classification.IsRampClass())
|
||||
!best_option_edge.flags.road_classification.IsRampClass())
|
||||
return true;
|
||||
|
||||
// the continue road is of a lower priority, while the road continues on the same priority
|
||||
// with a better angle
|
||||
if (best_option_deviation < best_continue_deviation &&
|
||||
in_way_data.road_classification == best_option_data.road_classification &&
|
||||
continue_data.road_classification.GetPriority() >
|
||||
best_option_data.road_classification.GetPriority())
|
||||
in_way_edge.flags.road_classification == best_option_edge.flags.road_classification &&
|
||||
continue_edge.flags.road_classification.GetPriority() >
|
||||
best_option_edge.flags.road_classification.GetPriority())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@@ -335,24 +346,25 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
const auto in_through_candidate =
|
||||
intersection.FindClosestBearing(util::bearing::reverse(road.bearing));
|
||||
|
||||
const auto &in_data = node_based_graph.GetEdgeData(in_through_candidate->eid);
|
||||
const auto &out_data = node_based_graph.GetEdgeData(road.eid);
|
||||
const auto &in_edge = node_based_graph.GetEdgeData(in_through_candidate->eid);
|
||||
const auto &out_edge = node_based_graph.GetEdgeData(road.eid);
|
||||
|
||||
// by asking for the same class, we ensure that we do not overrule obvious by road-class
|
||||
// decisions
|
||||
const auto same_class = in_data.road_classification == out_data.road_classification;
|
||||
const auto same_class =
|
||||
in_edge.flags.road_classification == out_edge.flags.road_classification;
|
||||
|
||||
// only if the entry is allowed for one of the two, but not the other, we need to check.
|
||||
// Otherwise other handlers do it better
|
||||
const bool is_oneway = !in_through_candidate->entry_allowed && road.entry_allowed;
|
||||
|
||||
const bool not_roundabout =
|
||||
!(in_data.roundabout || in_data.circular || out_data.roundabout || out_data.circular);
|
||||
const bool not_roundabout = !(in_edge.flags.roundabout || in_edge.flags.circular ||
|
||||
out_edge.flags.roundabout || out_edge.flags.circular);
|
||||
|
||||
// for the purpose of this check, we do not care about low-priority roads (parking lots,
|
||||
// mostly). Since we postulate both classes to be the same, checking one of the two is
|
||||
// enough
|
||||
const bool not_low_priority = !in_data.road_classification.IsLowPriorityRoadClass();
|
||||
const bool not_low_priority = !in_edge.flags.road_classification.IsLowPriorityRoadClass();
|
||||
|
||||
const auto in_deviation = angularDeviation(in_through_candidate->angle, STRAIGHT_ANGLE);
|
||||
const auto out_deviaiton = angularDeviation(road.angle, STRAIGHT_ANGLE);
|
||||
@@ -371,11 +383,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
const auto index_candidate = (best_option + 1) % intersection.size();
|
||||
if (index_candidate == 0)
|
||||
return index_candidate;
|
||||
const auto &candidate_data =
|
||||
const auto &candidate_edge =
|
||||
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
|
||||
if (obviousByRoadClass(in_way_data.road_classification,
|
||||
best_option_data.road_classification,
|
||||
candidate_data.road_classification))
|
||||
if (obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
best_option_edge.flags.road_classification,
|
||||
candidate_edge.flags.road_classification))
|
||||
return (index_candidate + 1) % intersection.size();
|
||||
else
|
||||
return index_candidate;
|
||||
@@ -386,11 +398,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
const auto index_candidate = best_option - 1;
|
||||
if (index_candidate == 0)
|
||||
return index_candidate;
|
||||
const auto candidate_data =
|
||||
const auto &candidate_edge =
|
||||
node_based_graph.GetEdgeData(intersection[index_candidate].eid);
|
||||
if (obviousByRoadClass(in_way_data.road_classification,
|
||||
best_option_data.road_classification,
|
||||
candidate_data.road_classification))
|
||||
if (obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
best_option_edge.flags.road_classification,
|
||||
candidate_edge.flags.road_classification))
|
||||
return index_candidate - 1;
|
||||
else
|
||||
return index_candidate;
|
||||
@@ -407,17 +419,17 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
|
||||
return best_option;
|
||||
|
||||
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid);
|
||||
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid);
|
||||
const auto &left_edge = node_based_graph.GetEdgeData(intersection[left_index].eid);
|
||||
const auto &right_edge = node_based_graph.GetEdgeData(intersection[right_index].eid);
|
||||
|
||||
const bool obvious_to_left =
|
||||
left_index == 0 || obviousByRoadClass(in_way_data.road_classification,
|
||||
best_option_data.road_classification,
|
||||
left_data.road_classification);
|
||||
left_index == 0 || obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
best_option_edge.flags.road_classification,
|
||||
left_edge.flags.road_classification);
|
||||
const bool obvious_to_right =
|
||||
right_index == 0 || obviousByRoadClass(in_way_data.road_classification,
|
||||
best_option_data.road_classification,
|
||||
right_data.road_classification);
|
||||
right_index == 0 || obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
best_option_edge.flags.road_classification,
|
||||
right_edge.flags.road_classification);
|
||||
|
||||
// if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
|
||||
// consider the turn obvious
|
||||
@@ -447,14 +459,15 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
distinction rate. If the road category is smaller, its also adjusted. Only
|
||||
roads of the same priority require the full distinction ratio.
|
||||
*/
|
||||
const auto &best_option_data =
|
||||
const auto &best_option_edge =
|
||||
node_based_graph.GetEdgeData(intersection[best_option].eid);
|
||||
const auto adjusted_distinction_ratio = [&]() {
|
||||
// obviousness by road classes
|
||||
if (in_way_data.road_classification == best_option_data.road_classification &&
|
||||
best_option_data.road_classification.GetPriority() <
|
||||
if (in_way_edge.flags.road_classification ==
|
||||
best_option_edge.flags.road_classification &&
|
||||
best_option_edge.flags.road_classification.GetPriority() <
|
||||
node_based_graph.GetEdgeData(intersection[index].eid)
|
||||
.road_classification.GetPriority())
|
||||
.flags.road_classification.GetPriority())
|
||||
return 0.8 * DISTINCTION_RATIO;
|
||||
// if road classes are the same, we use the full ratio
|
||||
else
|
||||
@@ -472,7 +485,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto &continue_data = node_based_graph.GetEdgeData(intersection[best_continue].eid);
|
||||
const auto &continue_edge = node_based_graph.GetEdgeData(intersection[best_continue].eid);
|
||||
const auto &continue_data =
|
||||
node_data_container.GetAnnotation(continue_edge.annotation_data);
|
||||
if (std::abs(best_continue_deviation) < 1)
|
||||
return best_continue;
|
||||
|
||||
@@ -488,11 +503,12 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
if (i == best_continue || !intersection[i].entry_allowed)
|
||||
continue;
|
||||
|
||||
const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].eid);
|
||||
const auto &turn_edge = node_based_graph.GetEdgeData(intersection[i].eid);
|
||||
const auto &turn_data = node_data_container.GetAnnotation(turn_edge.annotation_data);
|
||||
const bool is_obvious_by_road_class =
|
||||
obviousByRoadClass(in_way_data.road_classification,
|
||||
continue_data.road_classification,
|
||||
turn_data.road_classification);
|
||||
obviousByRoadClass(in_way_edge.flags.road_classification,
|
||||
continue_edge.flags.road_classification,
|
||||
turn_edge.flags.road_classification);
|
||||
|
||||
// if the main road is obvious by class, we ignore the current road as a potential
|
||||
// prevention of obviousness
|
||||
@@ -500,9 +516,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
continue;
|
||||
|
||||
// continuation could be grouped with a straight turn and the turning road is a ramp
|
||||
if (turn_data.road_classification.IsRampClass() &&
|
||||
if (turn_edge.flags.road_classification.IsRampClass() &&
|
||||
best_continue_deviation < GROUP_ANGLE &&
|
||||
!continue_data.road_classification.IsRampClass())
|
||||
!continue_edge.flags.road_classification.IsRampClass())
|
||||
continue;
|
||||
|
||||
// perfectly straight turns prevent obviousness
|
||||
@@ -567,11 +583,13 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
|
||||
// actually represents a near 180 degree different in bearings between the two
|
||||
// roads. So if there is a road that is enterable in the opposite direction just
|
||||
// prior, a turn is not obvious
|
||||
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.eid);
|
||||
const auto &turn_edge_data = node_based_graph.GetEdgeData(comparison_road.eid);
|
||||
const auto &turn_data =
|
||||
node_data_container.GetAnnotation(turn_edge_data.annotation_data);
|
||||
if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
|
||||
angularDeviation(comparison_road.angle, continue_road.angle) <
|
||||
FUZZY_ANGLE_DIFFERENCE &&
|
||||
!turn_data.reversed && continue_data.CanCombineWith(turn_data))
|
||||
!turn_edge_data.reversed && continue_data.CanCombineWith(turn_data))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ class IntersectionNormalizer
|
||||
std::vector<IntersectionNormalizationOperation> performed_merges;
|
||||
};
|
||||
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
|
||||
@@ -37,6 +37,7 @@ class MergableRoadDetector
|
||||
using MergableRoadData = IntersectionShapeData;
|
||||
|
||||
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &node_coordinates,
|
||||
const IntersectionGenerator &intersection_generator,
|
||||
const CoordinateExtractor &coordinate_extractor,
|
||||
@@ -77,8 +78,10 @@ class MergableRoadDetector
|
||||
|
||||
// When it comes to merging roads, we need to find out if two ways actually represent the
|
||||
// same road. This check tries to identify roads which are the same road in opposite directions
|
||||
bool EdgeDataSupportsMerge(const util::NodeBasedEdgeData &lhs_edge_data,
|
||||
const util::NodeBasedEdgeData &rhs_edge_data) const;
|
||||
bool EdgeDataSupportsMerge(const NodeBasedEdgeClassification &lhs_flags,
|
||||
const NodeBasedEdgeClassification &rhs_flags,
|
||||
const NodeBasedEdgeAnnotation &lhs_edge_annotation,
|
||||
const NodeBasedEdgeAnnotation &rhs_edge_annotation) const;
|
||||
|
||||
// Detect traffic loops.
|
||||
// Since OSRM cannot handle loop edges, we cannot directly see a connection between a node and
|
||||
@@ -138,6 +141,7 @@ class MergableRoadDetector
|
||||
bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
|
||||
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const std::vector<util::Coordinate> &node_coordinates;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
const CoordinateExtractor &coordinate_extractor;
|
||||
|
||||
@@ -24,6 +24,7 @@ class MotorwayHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
|
||||
@@ -28,6 +28,7 @@ class NodeBasedGraphWalker
|
||||
{
|
||||
public:
|
||||
NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
/*
|
||||
@@ -46,6 +47,7 @@ class NodeBasedGraphWalker
|
||||
|
||||
private:
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
const IntersectionGenerator &intersection_generator;
|
||||
};
|
||||
|
||||
@@ -106,7 +108,8 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
|
||||
boost::optional<EdgeID> operator()(const NodeID nid,
|
||||
const EdgeID via_edge_id,
|
||||
const IntersectionView &intersection,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph) const;
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container) const;
|
||||
|
||||
private:
|
||||
const NameID desired_name_id;
|
||||
@@ -131,7 +134,8 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
|
||||
boost::optional<EdgeID> operator()(const NodeID nid,
|
||||
const EdgeID via_edge_id,
|
||||
const IntersectionView &intersection,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph) const;
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container) const;
|
||||
|
||||
private:
|
||||
const NameID desired_name_id;
|
||||
@@ -201,8 +205,11 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
|
||||
if (next_intersection.size() <= 1)
|
||||
return {};
|
||||
|
||||
auto next_edge_id =
|
||||
selector(current_node_id, current_edge_id, next_intersection, node_based_graph);
|
||||
auto next_edge_id = selector(current_node_id,
|
||||
current_edge_id,
|
||||
next_intersection,
|
||||
node_based_graph,
|
||||
node_data_container);
|
||||
|
||||
if (!next_edge_id)
|
||||
return {};
|
||||
@@ -224,7 +231,8 @@ struct SkipTrafficSignalBarrierRoadSelector
|
||||
boost::optional<EdgeID> operator()(const NodeID,
|
||||
const EdgeID,
|
||||
const IntersectionView &intersection,
|
||||
const util::NodeBasedDynamicGraph &) const
|
||||
const util::NodeBasedDynamicGraph &,
|
||||
const EdgeBasedNodeDataContainer &) const
|
||||
{
|
||||
if (intersection.isTrafficSignalOrBarrier())
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "extractor/guidance/intersection_generator.hpp"
|
||||
#include "extractor/guidance/intersection_handler.hpp"
|
||||
#include "extractor/guidance/roundabout_type.hpp"
|
||||
#include "extractor/profile_properties.hpp"
|
||||
#include "extractor/query_node.hpp"
|
||||
|
||||
#include "util/name_table.hpp"
|
||||
@@ -41,11 +40,11 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const ProfileProperties &profile_properties,
|
||||
const IntersectionGenerator &intersection_generator);
|
||||
|
||||
~RoundaboutHandler() override final = default;
|
||||
@@ -86,8 +85,6 @@ class RoundaboutHandler : public IntersectionHandler
|
||||
qualifiesAsRoundaboutIntersection(const std::unordered_set<NodeID> &roundabout_nodes) const;
|
||||
|
||||
const CompressedEdgeContainer &compressed_edge_container;
|
||||
const ProfileProperties &profile_properties;
|
||||
|
||||
const CoordinateExtractor coordinate_extractor;
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ class SliproadHandler final : public IntersectionHandler
|
||||
public:
|
||||
SliproadHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
@@ -23,6 +23,7 @@ class SuppressModeHandler final : public IntersectionHandler
|
||||
public:
|
||||
SuppressModeHandler(const IntersectionGenerator &intersection_generator,
|
||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
@@ -41,13 +41,13 @@ class TurnAnalysis
|
||||
{
|
||||
public:
|
||||
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const RestrictionMap &restriction_map,
|
||||
const std::unordered_set<NodeID> &barrier_nodes,
|
||||
const CompressedEdgeContainer &compressed_edge_container,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
const ProfileProperties &profile_properties);
|
||||
const SuffixTable &street_name_suffix_table);
|
||||
|
||||
/* Full Analysis Process for a single node/edge combination. Use with caution, as the process is
|
||||
* relatively expensive */
|
||||
|
||||
@@ -28,6 +28,7 @@ class TurnHandler : public IntersectionHandler
|
||||
{
|
||||
public:
|
||||
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
const std::vector<util::Coordinate> &coordinates,
|
||||
const util::NameTable &name_table,
|
||||
const SuffixTable &street_name_suffix_table,
|
||||
|
||||
@@ -73,6 +73,7 @@ class TurnLaneHandler
|
||||
typedef std::vector<TurnLaneData> LaneDataVector;
|
||||
|
||||
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
|
||||
const EdgeBasedNodeDataContainer &node_data_container,
|
||||
LaneDescriptionMap &lane_description_map,
|
||||
const TurnAnalysis &turn_analysis,
|
||||
util::guidance::LaneDataIdMap &id_map);
|
||||
@@ -88,6 +89,7 @@ class TurnLaneHandler
|
||||
// we need to be able to look at previous intersections to, in some cases, find the correct turn
|
||||
// lanes for a turn
|
||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||
const EdgeBasedNodeDataContainer &node_data_container;
|
||||
std::vector<std::uint32_t> turn_lane_offsets;
|
||||
std::vector<TurnLaneType::Mask> turn_lane_masks;
|
||||
LaneDescriptionMap &lane_description_map;
|
||||
|
||||
@@ -58,65 +58,24 @@ struct InternalExtractorEdge
|
||||
using WeightData = detail::ByEdgeOrByMeterValue;
|
||||
using DurationData = detail::ByEdgeOrByMeterValue;
|
||||
|
||||
explicit InternalExtractorEdge()
|
||||
: result(MIN_OSM_NODEID,
|
||||
MIN_OSM_NODEID,
|
||||
SPECIAL_NODEID,
|
||||
0,
|
||||
0,
|
||||
false, // forward
|
||||
false, // backward
|
||||
false, // roundabout
|
||||
false, // circular
|
||||
true, // can be startpoint
|
||||
false, // local access only
|
||||
false, // is_left_hand_driving
|
||||
false, // split edge
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
0,
|
||||
guidance::TurnLaneType::empty,
|
||||
guidance::RoadClassification()),
|
||||
weight_data(), duration_data()
|
||||
{
|
||||
}
|
||||
explicit InternalExtractorEdge() : weight_data(), duration_data() {}
|
||||
|
||||
explicit InternalExtractorEdge(OSMNodeID source,
|
||||
OSMNodeID target,
|
||||
NodeID name_id,
|
||||
WeightData weight_data,
|
||||
DurationData duration_data,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
bool circular,
|
||||
bool startpoint,
|
||||
bool restricted,
|
||||
bool is_left_hand_driving,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
LaneDescriptionID lane_description,
|
||||
guidance::RoadClassification road_classification,
|
||||
util::Coordinate source_coordinate)
|
||||
: result(source,
|
||||
target,
|
||||
name_id,
|
||||
0,
|
||||
0,
|
||||
forward,
|
||||
backward,
|
||||
roundabout,
|
||||
circular,
|
||||
startpoint,
|
||||
restricted,
|
||||
is_left_hand_driving,
|
||||
is_split,
|
||||
travel_mode,
|
||||
classes,
|
||||
lane_description,
|
||||
std::move(road_classification)),
|
||||
weight_data(std::move(weight_data)), duration_data(std::move(duration_data)),
|
||||
source_coordinate(std::move(source_coordinate))
|
||||
: result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
|
||||
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
|
||||
{
|
||||
}
|
||||
|
||||
explicit InternalExtractorEdge(NodeBasedEdgeWithOSM edge,
|
||||
WeightData weight_data,
|
||||
DurationData duration_data,
|
||||
util::Coordinate source_coordinate)
|
||||
: result(std::move(edge)), weight_data(weight_data), duration_data(duration_data),
|
||||
source_coordinate(source_coordinate)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -132,45 +91,13 @@ struct InternalExtractorEdge
|
||||
// necessary static util functions for stxxl's sorting
|
||||
static InternalExtractorEdge min_osm_value()
|
||||
{
|
||||
return InternalExtractorEdge(MIN_OSM_NODEID,
|
||||
MIN_OSM_NODEID,
|
||||
SPECIAL_NODEID,
|
||||
WeightData(),
|
||||
DurationData(),
|
||||
false, // forward
|
||||
false, // backward
|
||||
false, // roundabout
|
||||
false, // circular
|
||||
true, // can be startpoint
|
||||
false, // local access only
|
||||
false, // is_left_hand_driving
|
||||
false, // split edge
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
0,
|
||||
INVALID_LANE_DESCRIPTIONID,
|
||||
guidance::RoadClassification(),
|
||||
util::Coordinate());
|
||||
return InternalExtractorEdge(
|
||||
MIN_OSM_NODEID, MIN_OSM_NODEID, WeightData(), DurationData(), util::Coordinate());
|
||||
}
|
||||
static InternalExtractorEdge max_osm_value()
|
||||
{
|
||||
return InternalExtractorEdge(MAX_OSM_NODEID,
|
||||
MAX_OSM_NODEID,
|
||||
SPECIAL_NODEID,
|
||||
WeightData(),
|
||||
DurationData(),
|
||||
false, // forward
|
||||
false, // backward
|
||||
false, // roundabout
|
||||
false, // circular
|
||||
true, // can be startpoint
|
||||
false, // local access only
|
||||
false, // is_left_hand_driving
|
||||
false, // split edge
|
||||
TRAVEL_MODE_INACCESSIBLE,
|
||||
0,
|
||||
INVALID_LANE_DESCRIPTIONID,
|
||||
guidance::RoadClassification(),
|
||||
util::Coordinate());
|
||||
return InternalExtractorEdge(
|
||||
MAX_OSM_NODEID, MAX_OSM_NODEID, WeightData(), DurationData(), util::Coordinate());
|
||||
}
|
||||
|
||||
static InternalExtractorEdge min_internal_value()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#ifndef NODE_BASED_EDGE_HPP
|
||||
#define NODE_BASED_EDGE_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
|
||||
#include "extractor/class_data.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
@@ -12,68 +15,97 @@ namespace osrm
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// Flags describing the class of the road. This data is used during creation of graphs/guidance
|
||||
// generation but is not available in annotation/navigation
|
||||
struct NodeBasedEdgeClassification
|
||||
{
|
||||
std::uint8_t forward : 1; // 1
|
||||
std::uint8_t backward : 1; // 1
|
||||
std::uint8_t is_split : 1; // 1
|
||||
std::uint8_t roundabout : 1; // 1
|
||||
std::uint8_t circular : 1; // 1
|
||||
std::uint8_t startpoint : 1; // 1
|
||||
std::uint8_t restricted : 1; // 1
|
||||
guidance::RoadClassification road_classification; // 16 2
|
||||
|
||||
NodeBasedEdgeClassification();
|
||||
|
||||
NodeBasedEdgeClassification(const bool forward,
|
||||
const bool backward,
|
||||
const bool is_split,
|
||||
const bool roundabout,
|
||||
const bool circular,
|
||||
const bool startpoint,
|
||||
const bool restricted,
|
||||
guidance::RoadClassification road_classification)
|
||||
: forward(forward), backward(backward), is_split(is_split), roundabout(roundabout),
|
||||
circular(circular), startpoint(startpoint), restricted(restricted),
|
||||
road_classification(road_classification)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const NodeBasedEdgeClassification &other) const
|
||||
{
|
||||
return (road_classification == other.road_classification) && (forward == other.forward) &&
|
||||
(backward == other.backward) && (is_split) == (other.is_split) &&
|
||||
(roundabout == other.roundabout) && (circular == other.circular) &&
|
||||
(startpoint == other.startpoint) && (restricted == other.restricted);
|
||||
}
|
||||
};
|
||||
|
||||
// Annotative data, used in parts in guidance generation, in parts during navigation (classes) but
|
||||
// mostly for annotation of edges. The entry can be shared between multiple edges and usually
|
||||
// describes features present on OSM ways. This is the place to put specific data that you want to
|
||||
// see as part of the API output but that does not influence navigation
|
||||
struct NodeBasedEdgeAnnotation
|
||||
{
|
||||
NameID name_id; // 32 4
|
||||
LaneDescriptionID lane_description_id; // 16 2
|
||||
ClassData classes; // 8 1
|
||||
TravelMode travel_mode : 4; // 4
|
||||
bool is_left_hand_driving : 1; // 1
|
||||
|
||||
bool CanCombineWith(const NodeBasedEdgeAnnotation &other) const
|
||||
{
|
||||
return (std::tie(name_id, classes, travel_mode, is_left_hand_driving) ==
|
||||
std::tie(other.name_id, other.classes, other.travel_mode, is_left_hand_driving));
|
||||
}
|
||||
};
|
||||
|
||||
struct NodeBasedEdge
|
||||
{
|
||||
NodeBasedEdge();
|
||||
|
||||
NodeBasedEdge(NodeID source,
|
||||
NodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
bool circular,
|
||||
bool startpoint,
|
||||
bool restricted,
|
||||
bool is_left_hand_driving,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification);
|
||||
GeometryID geometry_id,
|
||||
AnnotationID annotation_data,
|
||||
NodeBasedEdgeClassification flags);
|
||||
|
||||
bool operator<(const NodeBasedEdge &other) const;
|
||||
|
||||
NodeID source; // 32 4
|
||||
NodeID target; // 32 4
|
||||
NodeID name_id; // 32 4
|
||||
EdgeWeight weight; // 32 4
|
||||
EdgeDuration duration; // 32 4
|
||||
std::uint8_t forward : 1; // 1
|
||||
std::uint8_t backward : 1; // 1
|
||||
std::uint8_t roundabout : 1; // 1
|
||||
std::uint8_t circular : 1; // 1
|
||||
std::uint8_t startpoint : 1; // 1
|
||||
std::uint8_t restricted : 1; // 1
|
||||
std::uint8_t is_left_hand_driving : 1; // 1
|
||||
std::uint8_t is_split : 1; // 1
|
||||
TravelMode travel_mode : 4; // 4
|
||||
ClassData classes; // 8 1
|
||||
LaneDescriptionID lane_description_id; // 16 2
|
||||
guidance::RoadClassification road_classification; // 16 2
|
||||
NodeID source; // 32 4
|
||||
NodeID target; // 32 4
|
||||
EdgeWeight weight; // 32 4
|
||||
EdgeDuration duration; // 32 4
|
||||
GeometryID geometry_id; // 32 4
|
||||
AnnotationID annotation_data; // 32 4
|
||||
NodeBasedEdgeClassification flags; // 32 4
|
||||
};
|
||||
|
||||
struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
||||
{
|
||||
NodeBasedEdgeWithOSM();
|
||||
|
||||
NodeBasedEdgeWithOSM(OSMNodeID source,
|
||||
OSMNodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
bool circular,
|
||||
bool startpoint,
|
||||
bool restricted,
|
||||
bool is_left_hand_driving,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification);
|
||||
GeometryID geometry_id,
|
||||
AnnotationID annotation_data,
|
||||
NodeBasedEdgeClassification flags);
|
||||
|
||||
OSMNodeID osm_source_id;
|
||||
OSMNodeID osm_target_id;
|
||||
@@ -81,36 +113,26 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
||||
|
||||
// Impl.
|
||||
|
||||
inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
|
||||
: forward(false), backward(false), is_split(false), roundabout(false), circular(false),
|
||||
startpoint(false), restricted(false)
|
||||
{
|
||||
}
|
||||
|
||||
inline NodeBasedEdge::NodeBasedEdge()
|
||||
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), duration(0),
|
||||
forward(false), backward(false), roundabout(false), circular(false), startpoint(true),
|
||||
restricted(false), is_left_hand_driving(false), is_split(false),
|
||||
travel_mode(TRAVEL_MODE_INACCESSIBLE), lane_description_id(INVALID_LANE_DESCRIPTIONID)
|
||||
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
|
||||
{
|
||||
}
|
||||
|
||||
inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
||||
NodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
bool circular,
|
||||
bool startpoint,
|
||||
bool restricted,
|
||||
bool is_left_hand_driving,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification)
|
||||
: source(source), target(target), name_id(name_id), weight(weight), duration(duration),
|
||||
forward(forward), backward(backward), roundabout(roundabout), circular(circular),
|
||||
startpoint(startpoint), restricted(restricted), is_left_hand_driving(is_left_hand_driving),
|
||||
is_split(is_split), travel_mode(travel_mode), classes(classes),
|
||||
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
|
||||
GeometryID geometry_id,
|
||||
AnnotationID annotation_data,
|
||||
NodeBasedEdgeClassification flags)
|
||||
: source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
|
||||
annotation_data(annotation_data), flags(flags)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -122,7 +144,8 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
|
||||
{
|
||||
if (weight == other.weight)
|
||||
{
|
||||
return forward && backward && ((!other.forward) || (!other.backward));
|
||||
return flags.forward && flags.backward &&
|
||||
((!other.flags.forward) || (!other.flags.backward));
|
||||
}
|
||||
return weight < other.weight;
|
||||
}
|
||||
@@ -133,42 +156,22 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
|
||||
|
||||
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
||||
OSMNodeID target,
|
||||
NodeID name_id,
|
||||
EdgeWeight weight,
|
||||
EdgeDuration duration,
|
||||
bool forward,
|
||||
bool backward,
|
||||
bool roundabout,
|
||||
bool circular,
|
||||
bool startpoint,
|
||||
bool restricted,
|
||||
bool is_left_hand_driving,
|
||||
bool is_split,
|
||||
TravelMode travel_mode,
|
||||
ClassData classes,
|
||||
const LaneDescriptionID lane_description_id,
|
||||
guidance::RoadClassification road_classification)
|
||||
: NodeBasedEdge(SPECIAL_NODEID,
|
||||
SPECIAL_NODEID,
|
||||
name_id,
|
||||
weight,
|
||||
duration,
|
||||
forward,
|
||||
backward,
|
||||
roundabout,
|
||||
circular,
|
||||
startpoint,
|
||||
restricted,
|
||||
is_left_hand_driving,
|
||||
is_split,
|
||||
travel_mode,
|
||||
classes,
|
||||
lane_description_id,
|
||||
std::move(road_classification)),
|
||||
GeometryID geometry_id,
|
||||
AnnotationID annotation_data,
|
||||
NodeBasedEdgeClassification flags)
|
||||
: NodeBasedEdge(
|
||||
SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
|
||||
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
||||
{
|
||||
}
|
||||
|
||||
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
|
||||
: osm_source_id(MIN_OSM_NODEID), osm_target_id(MIN_OSM_NODEID)
|
||||
{
|
||||
}
|
||||
|
||||
static_assert(sizeof(extractor::NodeBasedEdge) == 28,
|
||||
"Size of extractor::NodeBasedEdge type is "
|
||||
"bigger than expected. This will influence "
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#ifndef OSRM_EXTRACTOR_NODE_BASED_GRAPH_FACTORY_HPP_
|
||||
#define OSRM_EXTRACTOR_NODE_BASED_GRAPH_FACTORY_HPP_
|
||||
|
||||
#include "extractor/compressed_edge_container.hpp"
|
||||
#include "extractor/node_based_edge.hpp"
|
||||
#include "extractor/node_data_container.hpp"
|
||||
#include "extractor/packed_osm_ids.hpp"
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/node_based_graph.hpp"
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
// Turn the output of the extraction process into a graph that represents junctions as nodes and
|
||||
// ways as edges between these nodes. The graph forms the further input for OSRMs creation of the
|
||||
// edge-based graph and is also the basic concept for annotating paths. All information from ways
|
||||
// that is transferred into the API response is connected to the edges of the node-based graph.
|
||||
//
|
||||
// The input to the graph creation is the set of edges, traffic signals, barriers, meta-data,...
|
||||
// which is generated during extraction and stored within the extraction containers.
|
||||
class NodeBasedGraphFactory
|
||||
{
|
||||
public:
|
||||
// The node-based graph factory loads the *.osrm file and transforms the data within into the
|
||||
// node-based graph to represent the OSM network. This includes geometry compression, annotation
|
||||
// data optimisation and many other aspects. After this step, the edge-based graph factory can
|
||||
// turn the graph into the routing graph to be used with the navigation algorithms.
|
||||
NodeBasedGraphFactory(const boost::filesystem::path &input_file,
|
||||
ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||
|
||||
auto const &GetGraph() const { return compressed_output_graph; }
|
||||
auto const &GetBarriers() const { return barriers; }
|
||||
auto const &GetTrafficSignals() const { return traffic_signals; }
|
||||
auto &GetCompressedEdges() { return compressed_edge_container; }
|
||||
auto &GetCoordinates() { return coordinates; }
|
||||
auto &GetAnnotationData() { return annotation_data; }
|
||||
auto &GetOsmNodes() { return osm_node_ids; }
|
||||
|
||||
// to reduce the memory footprint, the node-based graph factory allows releasing memory after it
|
||||
// might have been used for the last time:
|
||||
void ReleaseOsmNodes();
|
||||
|
||||
private:
|
||||
// Get the information from the *.osrm file (direct product of the extractor callback/extraction
|
||||
// containers) and prepare the graph creation process
|
||||
void LoadDataFromFile(const boost::filesystem::path &input_file);
|
||||
|
||||
// Compress the node-based graph into a compact representation of itself. This removes storing a
|
||||
// single edge for every part of the geometry and might also combine meta-data for multiple
|
||||
// edges into a single representative form
|
||||
void Compress(ScriptingEnvironment &scripting_environment,
|
||||
std::vector<TurnRestriction> &turn_restrictions,
|
||||
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions);
|
||||
|
||||
// Most ways are bidirectional, making the geometry in forward and backward direction the same,
|
||||
// except for reversal. We make use of this fact by keeping only one representation of the
|
||||
// geometry around
|
||||
void CompressGeometry();
|
||||
|
||||
// After graph compression, some of the annotation entries might not be referenced anymore. We
|
||||
// compress the annotation data by relabeling the node-based graph references and removing all
|
||||
// unreferenced entries
|
||||
void CompressAnnotationData();
|
||||
|
||||
// After produce, this will contain a compresse version of the node-based graph
|
||||
util::NodeBasedDynamicGraph compressed_output_graph;
|
||||
// To store the meta-data for the graph that is purely annotative / not used for the navigation
|
||||
// itself. Since the edges of a node-based graph form the nodes of the edge based graphs, we
|
||||
// transform this data into the EdgeBasedNodeDataContainer as output storage.
|
||||
std::vector<NodeBasedEdgeAnnotation> annotation_data;
|
||||
|
||||
// General Information about the graph, not used outside of extractor
|
||||
std::unordered_set<NodeID> barriers;
|
||||
std::unordered_set<NodeID> traffic_signals;
|
||||
|
||||
std::vector<util::Coordinate> coordinates;
|
||||
|
||||
// data to keep in sync with the node-based graph
|
||||
extractor::PackedOSMIDs osm_node_ids;
|
||||
|
||||
// for the compressed geometry
|
||||
extractor::CompressedEdgeContainer compressed_edge_container;
|
||||
};
|
||||
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_EXTRACTOR_NODE_BASED_GRAPH_FACTORY_HPP_
|
||||
@@ -2,6 +2,8 @@
|
||||
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
|
||||
|
||||
#include "extractor/class_data.hpp"
|
||||
#include "extractor/edge_based_node.hpp"
|
||||
#include "extractor/node_based_edge.hpp"
|
||||
#include "extractor/travel_mode.hpp"
|
||||
|
||||
#include "storage/io_fwd.hpp"
|
||||
@@ -15,6 +17,10 @@ namespace osrm
|
||||
{
|
||||
namespace extractor
|
||||
{
|
||||
|
||||
class Extractor;
|
||||
class EdgeBasedGraphFactory;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl;
|
||||
@@ -38,63 +44,47 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
|
||||
using TravelMode = extractor::TravelMode;
|
||||
|
||||
// to fill in data on edgeBasedNodes
|
||||
friend class osrm::extractor::Extractor;
|
||||
friend class osrm::extractor::EdgeBasedGraphFactory;
|
||||
|
||||
public:
|
||||
EdgeBasedNodeDataContainerImpl() = default;
|
||||
|
||||
EdgeBasedNodeDataContainerImpl(std::size_t size)
|
||||
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size),
|
||||
classes(size), is_left_hand_driving(size)
|
||||
EdgeBasedNodeDataContainerImpl(const NodeID number_of_edge_based_nodes,
|
||||
const AnnotationID number_of_annotations)
|
||||
: nodes(number_of_edge_based_nodes), annotation_data(number_of_annotations)
|
||||
{
|
||||
}
|
||||
|
||||
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids,
|
||||
Vector<NameID> name_ids,
|
||||
Vector<ComponentID> component_ids,
|
||||
Vector<TravelMode> travel_modes,
|
||||
Vector<ClassData> classes,
|
||||
Vector<bool> is_left_hand_driving)
|
||||
: geometry_ids(std::move(geometry_ids)), name_ids(std::move(name_ids)),
|
||||
component_ids(std::move(component_ids)), travel_modes(std::move(travel_modes)),
|
||||
classes(std::move(classes)), is_left_hand_driving(std::move(is_left_hand_driving))
|
||||
EdgeBasedNodeDataContainerImpl(Vector<EdgeBasedNode> nodes,
|
||||
Vector<NodeBasedEdgeAnnotation> annotation_data)
|
||||
: nodes(std::move(nodes)), annotation_data(std::move(annotation_data))
|
||||
{
|
||||
}
|
||||
|
||||
GeometryID GetGeometryID(const NodeID node_id) const { return geometry_ids[node_id]; }
|
||||
GeometryID GetGeometryID(const NodeID node_id) const { return nodes[node_id].geometry_id; }
|
||||
|
||||
TravelMode GetTravelMode(const NodeID node_id) const { return travel_modes[node_id]; }
|
||||
ComponentID GetComponentID(const NodeID node_id) const { return nodes[node_id].component_id; }
|
||||
|
||||
NameID GetNameID(const NodeID node_id) const { return name_ids[node_id]; }
|
||||
|
||||
ComponentID GetComponentID(const NodeID node_id) const { return component_ids[node_id]; }
|
||||
|
||||
ClassData GetClassData(const NodeID node_id) const { return classes[node_id]; }
|
||||
|
||||
ClassData IsLeftHandDriving(const NodeID node_id) const
|
||||
TravelMode GetTravelMode(const NodeID node_id) const
|
||||
{
|
||||
return is_left_hand_driving[node_id];
|
||||
return annotation_data[nodes[node_id].annotation_id].travel_mode;
|
||||
}
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void SetData(NodeID node_id,
|
||||
GeometryID geometry_id,
|
||||
NameID name_id,
|
||||
TravelMode travel_mode,
|
||||
ClassData class_data,
|
||||
bool is_left_hand_driving_flag)
|
||||
bool IsLeftHandDriving(const NodeID node_id) const
|
||||
{
|
||||
geometry_ids[node_id] = geometry_id;
|
||||
name_ids[node_id] = name_id;
|
||||
travel_modes[node_id] = travel_mode;
|
||||
classes[node_id] = class_data;
|
||||
is_left_hand_driving[node_id] = is_left_hand_driving_flag;
|
||||
return annotation_data[nodes[node_id].annotation_id].is_left_hand_driving;
|
||||
}
|
||||
|
||||
// Used by EdgeBasedGraphFactory to fill data structure
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void SetComponentID(NodeID node_id, ComponentID component_id)
|
||||
NameID GetNameID(const NodeID node_id) const
|
||||
{
|
||||
component_ids[node_id] = component_id;
|
||||
return annotation_data[nodes[node_id].annotation_id].name_id;
|
||||
}
|
||||
|
||||
ClassData GetClassData(const NodeID node_id) const
|
||||
{
|
||||
return annotation_data[nodes[node_id].annotation_id].classes;
|
||||
}
|
||||
|
||||
friend void serialization::read<Ownership>(storage::io::FileReader &reader,
|
||||
@@ -106,33 +96,30 @@ template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl
|
||||
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
|
||||
void Renumber(const std::vector<std::uint32_t> &permutation)
|
||||
{
|
||||
util::inplacePermutation(geometry_ids.begin(), geometry_ids.end(), permutation);
|
||||
util::inplacePermutation(name_ids.begin(), name_ids.end(), permutation);
|
||||
util::inplacePermutation(component_ids.begin(), component_ids.end(), permutation);
|
||||
util::inplacePermutation(travel_modes.begin(), travel_modes.end(), permutation);
|
||||
util::inplacePermutation(classes.begin(), classes.end(), permutation);
|
||||
util::inplacePermutation(
|
||||
is_left_hand_driving.begin(), is_left_hand_driving.end(), permutation);
|
||||
util::inplacePermutation(nodes.begin(), nodes.end(), permutation);
|
||||
}
|
||||
|
||||
// all containers have the exact same size
|
||||
std::size_t Size() const
|
||||
NodeID NumberOfNodes() const { return nodes.size(); }
|
||||
|
||||
// the number of annotations differs from the number of nodes, since annotations can be shared
|
||||
// between a large set of nodes
|
||||
AnnotationID NumberOfAnnotations() const { return annotation_data.size(); }
|
||||
|
||||
EdgeBasedNode &GetNode(const NodeID node_id) { return nodes[node_id]; }
|
||||
EdgeBasedNode const &GetNode(const NodeID node_id) const { return nodes[node_id]; }
|
||||
|
||||
NodeBasedEdgeAnnotation &GetAnnotation(const AnnotationID annotation)
|
||||
{
|
||||
BOOST_ASSERT(geometry_ids.size() == name_ids.size());
|
||||
BOOST_ASSERT(geometry_ids.size() == component_ids.size());
|
||||
BOOST_ASSERT(geometry_ids.size() == travel_modes.size());
|
||||
BOOST_ASSERT(geometry_ids.size() == classes.size());
|
||||
BOOST_ASSERT(geometry_ids.size() == is_left_hand_driving.size());
|
||||
return geometry_ids.size();
|
||||
return annotation_data[annotation];
|
||||
}
|
||||
NodeBasedEdgeAnnotation const &GetAnnotation(const AnnotationID annotation) const
|
||||
{
|
||||
return annotation_data[annotation];
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<GeometryID> geometry_ids;
|
||||
Vector<NameID> name_ids;
|
||||
Vector<ComponentID> component_ids;
|
||||
Vector<TravelMode> travel_modes;
|
||||
Vector<ClassData> classes;
|
||||
Vector<bool> is_left_hand_driving;
|
||||
Vector<EdgeBasedNode> nodes;
|
||||
Vector<NodeBasedEdgeAnnotation> annotation_data;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -141,7 +128,7 @@ using EdgeBasedNodeDataExternalContainer =
|
||||
using EdgeBasedNodeDataContainer =
|
||||
detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::Container>;
|
||||
using EdgeBasedNodeDataView = detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::View>;
|
||||
}
|
||||
}
|
||||
} // namespace extractor
|
||||
} // namespace osrm
|
||||
|
||||
#endif
|
||||
|
||||
@@ -96,7 +96,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
|
||||
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
|
||||
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
|
||||
|
||||
bool HasLocationDependentData() const { return !location_dependent_data.empty(); }
|
||||
bool HasLocationDependentData() const override { return !location_dependent_data.empty(); }
|
||||
|
||||
private:
|
||||
LuaScriptingContext &GetSol2Context();
|
||||
|
||||
@@ -120,24 +120,22 @@ template <storage::Ownership Ownership>
|
||||
inline void read(storage::io::FileReader &reader,
|
||||
detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
|
||||
{
|
||||
storage::serialization::read(reader, node_data_container.geometry_ids);
|
||||
storage::serialization::read(reader, node_data_container.name_ids);
|
||||
storage::serialization::read(reader, node_data_container.component_ids);
|
||||
storage::serialization::read(reader, node_data_container.travel_modes);
|
||||
storage::serialization::read(reader, node_data_container.classes);
|
||||
storage::serialization::read(reader, node_data_container.is_left_hand_driving);
|
||||
// read header (separate sizes for both vectors)
|
||||
reader.ReadElementCount64();
|
||||
reader.ReadElementCount64();
|
||||
// read actual data
|
||||
storage::serialization::read(reader, node_data_container.nodes);
|
||||
storage::serialization::read(reader, node_data_container.annotation_data);
|
||||
}
|
||||
|
||||
template <storage::Ownership Ownership>
|
||||
inline void write(storage::io::FileWriter &writer,
|
||||
const detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
|
||||
{
|
||||
storage::serialization::write(writer, node_data_container.geometry_ids);
|
||||
storage::serialization::write(writer, node_data_container.name_ids);
|
||||
storage::serialization::write(writer, node_data_container.component_ids);
|
||||
storage::serialization::write(writer, node_data_container.travel_modes);
|
||||
storage::serialization::write(writer, node_data_container.classes);
|
||||
storage::serialization::write(writer, node_data_container.is_left_hand_driving);
|
||||
writer.WriteElementCount64(node_data_container.NumberOfNodes());
|
||||
writer.WriteElementCount64(node_data_container.NumberOfAnnotations());
|
||||
storage::serialization::write(writer, node_data_container.nodes);
|
||||
storage::serialization::write(writer, node_data_container.annotation_data);
|
||||
}
|
||||
|
||||
inline void read(storage::io::FileReader &reader, NodeRestriction &restriction)
|
||||
|
||||
Reference in New Issue
Block a user