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:
Moritz Kobitzsch 2017-09-25 15:37:11 +02:00 committed by Michael Krasnyk
parent 9b044aaa42
commit 2ddd98ee6d
64 changed files with 1610 additions and 1190 deletions

View File

@ -11,6 +11,7 @@
- Exposes `use_threads_number=Number` parameter of `EngineConfig` to limit a number of threads in a TBB internal pool - Exposes `use_threads_number=Number` parameter of `EngineConfig` to limit a number of threads in a TBB internal pool
- Internals - Internals
- MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices - MLD uses a unidirectional Dijkstra for 1-to-N and N-to-1 matrices
- BREAKING: Internal file formats have changed, requiring a new pre-processing run
- Guidance - Guidance
- Fixed some cases of sliproads pre-processing (https://github.com/Project-OSRM/osrm-backend/issues/4348) - Fixed some cases of sliproads pre-processing (https://github.com/Project-OSRM/osrm-backend/issues/4348)
- don't suppress name announcements via sliproad handler - don't suppress name announcements via sliproad handler

View File

@ -12,6 +12,7 @@
#include "customizer/edge_based_graph.hpp" #include "customizer/edge_based_graph.hpp"
#include "extractor/datasources.hpp" #include "extractor/datasources.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp" #include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/intersection_bearings_container.hpp" #include "extractor/intersection_bearings_container.hpp"
@ -337,43 +338,21 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout, void InitializeEdgeBasedNodeDataInformationPointers(storage::DataLayout &layout,
char *memory_ptr) char *memory_ptr)
{ {
const auto via_geometry_list_ptr = const auto edge_based_node_list_ptr = layout.GetBlockPtr<extractor::EdgeBasedNode>(
layout.GetBlockPtr<GeometryID>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST); memory_ptr, storage::DataLayout::EDGE_BASED_NODE_DATA_LIST);
util::vector_view<GeometryID> geometry_ids( util::vector_view<extractor::EdgeBasedNode> edge_based_node_data_list(
via_geometry_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]); edge_based_node_list_ptr,
layout.num_entries[storage::DataLayout::EDGE_BASED_NODE_DATA_LIST]);
const auto name_id_list_ptr = const auto annotation_data_list_ptr =
layout.GetBlockPtr<NameID>(memory_ptr, storage::DataLayout::NAME_ID_LIST); layout.GetBlockPtr<extractor::NodeBasedEdgeAnnotation>(
util::vector_view<NameID> name_ids(name_id_list_ptr, memory_ptr, storage::DataLayout::ANNOTATION_DATA_LIST);
layout.num_entries[storage::DataLayout::NAME_ID_LIST]); util::vector_view<extractor::NodeBasedEdgeAnnotation> annotation_data(
annotation_data_list_ptr,
layout.num_entries[storage::DataLayout::ANNOTATION_DATA_LIST]);
const auto component_id_list_ptr = edge_based_node_data = extractor::EdgeBasedNodeDataView(
layout.GetBlockPtr<ComponentID>(memory_ptr, storage::DataLayout::COMPONENT_ID_LIST); std::move(edge_based_node_data_list), std::move(annotation_data));
util::vector_view<ComponentID> component_ids(
component_id_list_ptr, layout.num_entries[storage::DataLayout::COMPONENT_ID_LIST]);
const auto travel_mode_list_ptr = layout.GetBlockPtr<extractor::TravelMode>(
memory_ptr, storage::DataLayout::TRAVEL_MODE_LIST);
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
const auto classes_list_ptr =
layout.GetBlockPtr<extractor::ClassData>(memory_ptr, storage::DataLayout::CLASSES_LIST);
util::vector_view<extractor::ClassData> classes(
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
auto is_left_hand_driving_ptr = layout.GetBlockPtr<unsigned>(
memory_ptr, storage::DataLayout::IS_LEFT_HAND_DRIVING_LIST);
util::vector_view<bool> is_left_hand_driving(
is_left_hand_driving_ptr,
layout.num_entries[storage::DataLayout::IS_LEFT_HAND_DRIVING_LIST]);
edge_based_node_data = extractor::EdgeBasedNodeDataView(std::move(geometry_ids),
std::move(name_ids),
std::move(component_ids),
std::move(travel_modes),
std::move(classes),
std::move(is_left_hand_driving));
} }
void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr) void InitializeEdgeInformationPointers(storage::DataLayout &layout, char *memory_ptr)
@ -465,7 +444,6 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]); geometries_index_ptr, data_layout.num_entries[storage::DataLayout::GEOMETRIES_INDEX]);
auto num_entries = data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST]; auto num_entries = data_layout.num_entries[storage::DataLayout::GEOMETRIES_NODE_LIST];
auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>( auto geometries_node_list_ptr = data_layout.GetBlockPtr<NodeID>(
memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST); memory_block, storage::DataLayout::GEOMETRIES_NODE_LIST);
util::vector_view<NodeID> geometry_node_list(geometries_node_list_ptr, num_entries); util::vector_view<NodeID> geometry_node_list(geometries_node_list_ptr, num_entries);

View File

@ -14,8 +14,6 @@
#include "extractor/nbg_to_ebg.hpp" #include "extractor/nbg_to_ebg.hpp"
#include "extractor/node_data_container.hpp" #include "extractor/node_data_container.hpp"
#include "extractor/original_edge_data.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/query_node.hpp"
#include "extractor/restriction_index.hpp" #include "extractor/restriction_index.hpp"
#include "extractor/way_restriction_map.hpp" #include "extractor/way_restriction_map.hpp"
@ -26,7 +24,6 @@
#include "util/guidance/entry_class.hpp" #include "util/guidance/entry_class.hpp"
#include "util/name_table.hpp" #include "util/name_table.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/packed_vector.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include "storage/io.hpp" #include "storage/io.hpp"
@ -71,13 +68,12 @@ class EdgeBasedGraphFactory
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete; EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete; EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete;
explicit EdgeBasedGraphFactory(std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph, explicit EdgeBasedGraphFactory(const util::NodeBasedDynamicGraph &node_based_graph,
CompressedEdgeContainer &compressed_edge_container, EdgeBasedNodeDataContainer &node_data_container,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &traffic_lights,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const extractor::PackedOSMIDs &osm_node_ids,
ProfileProperties profile_properties,
const util::NameTable &name_table, const util::NameTable &name_table,
guidance::LaneDescriptionMap &lane_description_map); guidance::LaneDescriptionMap &lane_description_map);
@ -95,7 +91,6 @@ class EdgeBasedGraphFactory
// The following get access functions destroy the content in the factory // The following get access functions destroy the content in the factory
void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges); void GetEdgeBasedEdges(util::DeallocatingVector<EdgeBasedEdge> &edges);
void GetEdgeBasedNodes(EdgeBasedNodeDataContainer &data_container);
void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes); void GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes);
void GetStartPointMarkers(std::vector<bool> &node_is_startpoint); void GetStartPointMarkers(std::vector<bool> &node_is_startpoint);
void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights); void GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &output_node_weights);
@ -144,7 +139,7 @@ class EdgeBasedGraphFactory
//! list of edge based nodes (compressed segments) //! list of edge based nodes (compressed segments)
std::vector<EdgeBasedNodeSegment> m_edge_based_node_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; 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. // 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; std::uint64_t m_number_of_edge_based_nodes;
const std::vector<util::Coordinate> &m_coordinates; const std::vector<util::Coordinate> &m_coordinates;
const extractor::PackedOSMIDs &m_osm_node_ids; const util::NodeBasedDynamicGraph &m_node_based_graph;
std::shared_ptr<util::NodeBasedDynamicGraph> m_node_based_graph;
const std::unordered_set<NodeID> &m_barrier_nodes; const std::unordered_set<NodeID> &m_barrier_nodes;
const std::unordered_set<NodeID> &m_traffic_lights; const std::unordered_set<NodeID> &m_traffic_lights;
CompressedEdgeContainer &m_compressed_edge_container; const CompressedEdgeContainer &m_compressed_edge_container;
ProfileProperties profile_properties;
const util::NameTable &name_table; const util::NameTable &name_table;
guidance::LaneDescriptionMap &lane_description_map; 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 // During the generation of the edge-expanded nodes, we need to also generate duplicates that
// represent state during via-way restrictions (see // represent state during via-way restrictions (see
@ -194,6 +190,8 @@ class EdgeBasedGraphFactory
std::size_t skipped_uturns_counter; std::size_t skipped_uturns_counter;
std::size_t skipped_barrier_turns_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; util::ConcurrentIDMap<util::guidance::BearingClass, BearingClassID> bearing_class_hash;
std::vector<BearingClassID> bearing_class_by_node_based_node; std::vector<BearingClassID> bearing_class_by_node_based_node;
util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID> entry_class_hash; util::ConcurrentIDMap<util::guidance::EntryClass, EntryClassID> entry_class_hash;

View File

@ -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_

View File

@ -28,12 +28,14 @@ class ExtractionContainers
void WriteNodes(storage::io::FileWriter &file_out) const; void WriteNodes(storage::io::FileWriter &file_out) const;
void WriteEdges(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); void WriteCharData(const std::string &file_name);
public: public:
using NodeIDVector = std::vector<OSMNodeID>; using NodeIDVector = std::vector<OSMNodeID>;
using NodeVector = std::vector<QueryNode>; using NodeVector = std::vector<QueryNode>;
using EdgeVector = std::vector<InternalExtractorEdge>; using EdgeVector = std::vector<InternalExtractorEdge>;
using AnnotationDataVector = std::vector<NodeBasedEdgeAnnotation>;
using WayIDStartEndVector = std::vector<FirstAndLastSegmentOfWay>; using WayIDStartEndVector = std::vector<FirstAndLastSegmentOfWay>;
using NameCharData = std::vector<unsigned char>; using NameCharData = std::vector<unsigned char>;
using NameOffsets = std::vector<unsigned>; using NameOffsets = std::vector<unsigned>;
@ -43,6 +45,7 @@ class ExtractionContainers
NodeIDVector used_node_id_list; NodeIDVector used_node_id_list;
NodeVector all_nodes_list; NodeVector all_nodes_list;
EdgeVector all_edges_list; EdgeVector all_edges_list;
AnnotationDataVector all_edges_annotation_data_list;
NameCharData name_char_data; NameCharData name_char_data;
NameOffsets name_offsets; NameOffsets name_offsets;
// an adjacency array containing all turn lane masks // an adjacency array containing all turn lane masks

View File

@ -32,6 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "extractor/edge_based_graph_factory.hpp" #include "extractor/edge_based_graph_factory.hpp"
#include "extractor/extractor_config.hpp" #include "extractor/extractor_config.hpp"
#include "extractor/graph_compressor.hpp" #include "extractor/graph_compressor.hpp"
#include "extractor/packed_osm_ids.hpp"
#include "util/guidance/bearing_class.hpp" #include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp" #include "util/guidance/entry_class.hpp"
@ -61,19 +62,27 @@ class Extractor
std::vector<ConditionalTurnRestriction>> std::vector<ConditionalTurnRestriction>>
ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads); ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads);
std::pair<std::size_t, EdgeID> EdgeID BuildEdgeExpandedGraph(
BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment, // input data
std::vector<util::Coordinate> &coordinates, const util::NodeBasedDynamicGraph &node_based_graph,
extractor::PackedOSMIDs &osm_node_ids, 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, EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments, std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint, std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights, std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list, util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file, const std::string &intersection_class_output_file);
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
guidance::LaneDescriptionMap &turn_lane_map);
void FindComponents(unsigned max_edge_id, void FindComponents(unsigned max_edge_id,
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list, const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
const std::vector<EdgeBasedNodeSegment> &input_node_segments, const std::vector<EdgeBasedNodeSegment> &input_node_segments,
@ -82,11 +91,6 @@ class Extractor
std::vector<bool> node_is_startpoint, std::vector<bool> node_is_startpoint,
const std::vector<util::Coordinate> &coordinates); const std::vector<util::Coordinate> &coordinates);
std::shared_ptr<RestrictionMap> LoadRestrictionMap(); 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. // Writes compressed node based graph and its embedding into a file for osrm-partition to use.
static void WriteCompressedNodeBasedGraph(const std::string &path, static void WriteCompressedNodeBasedGraph(const std::string &path,

View File

@ -78,27 +78,27 @@ inline void writeProfileProperties(const boost::filesystem::path &path,
template <typename EdgeBasedEdgeVector> template <typename EdgeBasedEdgeVector>
void writeEdgeBasedGraph(const boost::filesystem::path &path, 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) const EdgeBasedEdgeVector &edge_based_edge_list)
{ {
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, ""); static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
storage::io::FileWriter writer(path, storage::io::FileWriter::GenerateFingerprint); 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); storage::serialization::write(writer, edge_based_edge_list);
} }
template <typename EdgeBasedEdgeVector> template <typename EdgeBasedEdgeVector>
void readEdgeBasedGraph(const boost::filesystem::path &path, void readEdgeBasedGraph(const boost::filesystem::path &path,
EdgeID &max_edge_id, EdgeID &number_of_edge_based_nodes,
EdgeBasedEdgeVector &edge_based_edge_list) EdgeBasedEdgeVector &edge_based_edge_list)
{ {
static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, ""); static_assert(std::is_same<typename EdgeBasedEdgeVector::value_type, EdgeBasedEdge>::value, "");
storage::io::FileReader reader(path, storage::io::FileReader::VerifyFingerprint); 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); storage::serialization::read(reader, edge_based_edge_list);
} }

View File

@ -29,6 +29,7 @@ class GraphCompressor
std::vector<TurnRestriction> &turn_restrictions, std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions, std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
util::NodeBasedDynamicGraph &graph, util::NodeBasedDynamicGraph &graph,
const std::vector<NodeBasedEdgeAnnotation> &node_data_container,
CompressedEdgeContainer &geometry_compressor); CompressedEdgeContainer &geometry_compressor);
private: private:

View File

@ -225,7 +225,7 @@ class CoordinateExtractor
const std::vector<double> &segment_distances, const std::vector<double> &segment_distances,
const double segment_length, const double segment_length,
const double considered_lane_width, 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, * If the very first coordinate is within lane offsets and the rest offers a near straight line,

View File

@ -16,6 +16,7 @@ class DrivewayHandler final : public IntersectionHandler
public: public:
DrivewayHandler(const IntersectionGenerator &intersection_generator, DrivewayHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table); const SuffixTable &street_name_suffix_table);

View File

@ -38,6 +38,7 @@ class IntersectionGenerator
{ {
public: public:
IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph, IntersectionGenerator(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map, const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
@ -110,6 +111,7 @@ class IntersectionGenerator
private: private:
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const RestrictionMap &restriction_map; const RestrictionMap &restriction_map;
const std::unordered_set<NodeID> &barrier_nodes; const std::unordered_set<NodeID> &barrier_nodes;
const std::vector<util::Coordinate> &coordinates; const std::vector<util::Coordinate> &coordinates;

View File

@ -33,6 +33,7 @@ class IntersectionHandler
{ {
public: public:
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph, IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
@ -50,6 +51,7 @@ class IntersectionHandler
protected: protected:
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const std::vector<util::Coordinate> &coordinates; const std::vector<util::Coordinate> &coordinates;
const util::NameTable &name_table; const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table; const SuffixTable &street_name_suffix_table;
@ -124,7 +126,6 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const IntersectionType &intersection) const const IntersectionType &intersection) const
{ {
using Road = typename IntersectionType::value_type; using Road = typename IntersectionType::value_type;
using EdgeData = osrm::util::NodeBasedDynamicGraph::EdgeData;
using osrm::util::angularDeviation; using osrm::util::angularDeviation;
// no obvious road // no obvious road
@ -135,7 +136,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (intersection.size() == 2) if (intersection.size() == 2)
return 1; 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 // the strategy for picking the most obvious turn involves deciding between
// an overall best candidate and a best candidate that shares the same name // 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; double best_continue_deviation = 180;
/* helper functions */ /* helper functions */
const auto IsContinueRoad = [&](const EdgeData &way_data) { const auto IsContinueRoad = [&](const NodeBasedEdgeAnnotation &way_data) {
return !util::guidance::requiresNameAnnounced( return !util::guidance::requiresNameAnnounced(
in_way_data.name_id, way_data.name_id, name_table, street_name_suffix_table); in_way_data.name_id, way_data.name_id, name_table, street_name_suffix_table);
}; };
auto sameOrHigherPriority = [&in_way_data](const auto &way_data) { auto sameOrHigherPriority = [&](const auto &way_data) {
return way_data.road_classification.GetPriority() <= return way_data.flags.road_classification.GetPriority() <=
in_way_data.road_classification.GetPriority(); in_way_edge.flags.road_classification.GetPriority();
}; };
auto IsLowPriority = [](const auto &way_data) { 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 // 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 // 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 // with the in way. Ideal candidates are of similar road class with the in way
// and are require relatively straight turns. // and are require relatively straight turns.
const auto RoadCompare = [&](const auto &lhs, const auto &rhs) { const auto RoadCompare = [&](const auto &lhs, const auto &rhs) {
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid); const auto &lhs_edge = node_based_graph.GetEdgeData(lhs.eid);
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid); const auto &rhs_edge = node_based_graph.GetEdgeData(rhs.eid);
const auto lhs_deviation = angularDeviation(lhs.angle, STRAIGHT_ANGLE); const auto lhs_deviation = angularDeviation(lhs.angle, STRAIGHT_ANGLE);
const auto rhs_deviation = angularDeviation(rhs.angle, STRAIGHT_ANGLE); const auto rhs_deviation = angularDeviation(rhs.angle, STRAIGHT_ANGLE);
const bool rhs_same_classification = 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 = const bool lhs_same_classification =
lhs_data.road_classification == in_way_data.road_classification; lhs_edge.flags.road_classification == in_way_edge.flags.road_classification;
const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_data); const bool rhs_same_or_higher_priority = sameOrHigherPriority(rhs_edge);
const bool rhs_low_priority = IsLowPriority(rhs_data); const bool rhs_low_priority = IsLowPriority(rhs_edge);
const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_data); const bool lhs_same_or_higher_priority = sameOrHigherPriority(lhs_edge);
const bool lhs_low_priority = IsLowPriority(lhs_data); const bool lhs_low_priority = IsLowPriority(lhs_edge);
auto left_tie = std::tie(lhs.entry_allowed, auto left_tie = std::tie(lhs.entry_allowed,
lhs_same_or_higher_priority, lhs_same_or_higher_priority,
rhs_low_priority, rhs_low_priority,
@ -188,8 +190,10 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
return left_tie > right_tie; return left_tie > right_tie;
}; };
const auto RoadCompareSameName = [&](const auto &lhs, const auto &rhs) { const auto RoadCompareSameName = [&](const auto &lhs, const auto &rhs) {
const EdgeData &lhs_data = node_based_graph.GetEdgeData(lhs.eid); const auto &lhs_data = node_data_container.GetAnnotation(
const EdgeData &rhs_data = node_based_graph.GetEdgeData(rhs.eid); 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 lhs_continues = IsContinueRoad(lhs_data);
const auto rhs_continues = IsContinueRoad(rhs_data); const auto rhs_continues = IsContinueRoad(rhs_data);
const auto left_tie = std::tie(lhs.entry_allowed, lhs_continues); 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 = std::distance(begin(intersection), best_option_it);
best_option_deviation = angularDeviation(intersection[best_option].angle, STRAIGHT_ANGLE); 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 // Unless the in way is also low priority, it is generally undesirable to
// indicate that a low priority road is obvious // indicate that a low priority road is obvious
if (IsLowPriority(best_option_data) && if (IsLowPriority(best_option_edge) &&
best_option_data.road_classification != in_way_data.road_classification) best_option_edge.flags.road_classification != in_way_edge.flags.road_classification)
{ {
best_option = 0; best_option = 0;
best_option_deviation = 180; best_option_deviation = 180;
@ -219,13 +225,13 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto straightest = intersection.findClosestTurn(STRAIGHT_ANGLE); const auto straightest = intersection.findClosestTurn(STRAIGHT_ANGLE);
if (straightest != best_option_it) 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); double straightest_data_deviation = angularDeviation(straightest->angle, STRAIGHT_ANGLE);
const auto deviation_diff = const auto deviation_diff =
std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE; std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE;
const auto not_ramp_class = !straightest_data.road_classification.IsRampClass(); const auto not_ramp_class = !straightest_edge.flags.road_classification.IsRampClass();
const auto not_link_class = !straightest_data.road_classification.IsLinkClass(); const auto not_link_class = !straightest_edge.flags.road_classification.IsLinkClass();
if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class && if (deviation_diff && !IsLowPriority(straightest_edge) && not_ramp_class &&
not_link_class && !IsContinueRoad(best_option_data)) not_link_class && !IsContinueRoad(best_option_data))
{ {
best_option = std::distance(begin(intersection), straightest); best_option = std::distance(begin(intersection), straightest);
@ -240,7 +246,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
auto best_continue_it = auto best_continue_it =
std::min_element(begin(intersection), end(intersection), RoadCompareSameName); 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) || if (IsContinueRoad(best_continue_data) ||
(in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID)) (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 the best angle is going straight but the road is turning, declare no obvious turn
if (0 != best_continue && best_option != best_continue && if (0 != best_continue && best_option != best_continue &&
best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION && best_option_deviation < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
node_based_graph.GetEdgeData(intersection[best_continue].eid).road_classification == best_continue_edge.flags.road_classification == best_option_edge.flags.road_classification)
best_option_data.road_classification)
{ {
return 0; 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 // continue instruction because they share a name with the approaching way
const std::int64_t continue_count = const std::int64_t continue_count =
count_if(++begin(intersection), end(intersection), [&](const auto &way) { 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 = const std::int64_t continue_count_valid =
count_if(++begin(intersection), end(intersection), [&](const auto &way) { 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 // checks if continue candidates are sharp turns
const bool all_continues_are_narrow = [&]() { const bool all_continues_are_narrow = [&]() {
return std::count_if(begin(intersection), end(intersection), [&](const Road &road) { 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); const double &road_angle = angularDeviation(road.angle, STRAIGHT_ANGLE);
return IsContinueRoad(road_data) && (road_angle < NARROW_TURN_ANGLE); return IsContinueRoad(road_data) && (road_angle < NARROW_TURN_ANGLE);
}) == continue_count; }) == continue_count;
@ -296,32 +307,32 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
return true; return true;
// continue data now most certainly exists // 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 // best_continue is obvious by road class
if (obviousByRoadClass(in_way_data.road_classification, if (obviousByRoadClass(in_way_edge.flags.road_classification,
continue_data.road_classification, continue_edge.flags.road_classification,
best_option_data.road_classification)) best_option_edge.flags.road_classification))
return false; return false;
// best_option is obvious by road class // best_option is obvious by road class
if (obviousByRoadClass(in_way_data.road_classification, if (obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_data.road_classification, best_option_edge.flags.road_classification,
continue_data.road_classification)) continue_edge.flags.road_classification))
return true; return true;
// the best_option deviation is very straight and not a ramp // the best_option deviation is very straight and not a ramp
if (best_option_deviation < best_continue_deviation && if (best_option_deviation < best_continue_deviation &&
best_option_deviation < FUZZY_ANGLE_DIFFERENCE && best_option_deviation < FUZZY_ANGLE_DIFFERENCE &&
!best_option_data.road_classification.IsRampClass()) !best_option_edge.flags.road_classification.IsRampClass())
return true; return true;
// the continue road is of a lower priority, while the road continues on the same priority // the continue road is of a lower priority, while the road continues on the same priority
// with a better angle // with a better angle
if (best_option_deviation < best_continue_deviation && if (best_option_deviation < best_continue_deviation &&
in_way_data.road_classification == best_option_data.road_classification && in_way_edge.flags.road_classification == best_option_edge.flags.road_classification &&
continue_data.road_classification.GetPriority() > continue_edge.flags.road_classification.GetPriority() >
best_option_data.road_classification.GetPriority()) best_option_edge.flags.road_classification.GetPriority())
return true; return true;
return false; return false;
@ -335,24 +346,25 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto in_through_candidate = const auto in_through_candidate =
intersection.FindClosestBearing(util::bearing::reverse(road.bearing)); intersection.FindClosestBearing(util::bearing::reverse(road.bearing));
const auto &in_data = node_based_graph.GetEdgeData(in_through_candidate->eid); const auto &in_edge = node_based_graph.GetEdgeData(in_through_candidate->eid);
const auto &out_data = node_based_graph.GetEdgeData(road.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 // by asking for the same class, we ensure that we do not overrule obvious by road-class
// decisions // 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. // 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 // Otherwise other handlers do it better
const bool is_oneway = !in_through_candidate->entry_allowed && road.entry_allowed; const bool is_oneway = !in_through_candidate->entry_allowed && road.entry_allowed;
const bool not_roundabout = const bool not_roundabout = !(in_edge.flags.roundabout || in_edge.flags.circular ||
!(in_data.roundabout || in_data.circular || out_data.roundabout || out_data.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, // 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 // mostly). Since we postulate both classes to be the same, checking one of the two is
// enough // 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 in_deviation = angularDeviation(in_through_candidate->angle, STRAIGHT_ANGLE);
const auto out_deviaiton = angularDeviation(road.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(); const auto index_candidate = (best_option + 1) % intersection.size();
if (index_candidate == 0) if (index_candidate == 0)
return index_candidate; return index_candidate;
const auto &candidate_data = const auto &candidate_edge =
node_based_graph.GetEdgeData(intersection[index_candidate].eid); node_based_graph.GetEdgeData(intersection[index_candidate].eid);
if (obviousByRoadClass(in_way_data.road_classification, if (obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_data.road_classification, best_option_edge.flags.road_classification,
candidate_data.road_classification)) candidate_edge.flags.road_classification))
return (index_candidate + 1) % intersection.size(); return (index_candidate + 1) % intersection.size();
else else
return index_candidate; return index_candidate;
@ -386,11 +398,11 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto index_candidate = best_option - 1; const auto index_candidate = best_option - 1;
if (index_candidate == 0) if (index_candidate == 0)
return index_candidate; return index_candidate;
const auto candidate_data = const auto &candidate_edge =
node_based_graph.GetEdgeData(intersection[index_candidate].eid); node_based_graph.GetEdgeData(intersection[index_candidate].eid);
if (obviousByRoadClass(in_way_data.road_classification, if (obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_data.road_classification, best_option_edge.flags.road_classification,
candidate_data.road_classification)) candidate_edge.flags.road_classification))
return index_candidate - 1; return index_candidate - 1;
else else
return index_candidate; 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) std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best_option; return best_option;
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].eid); const auto &left_edge = node_based_graph.GetEdgeData(intersection[left_index].eid);
const auto &right_data = node_based_graph.GetEdgeData(intersection[right_index].eid); const auto &right_edge = node_based_graph.GetEdgeData(intersection[right_index].eid);
const bool obvious_to_left = const bool obvious_to_left =
left_index == 0 || obviousByRoadClass(in_way_data.road_classification, left_index == 0 || obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_data.road_classification, best_option_edge.flags.road_classification,
left_data.road_classification); left_edge.flags.road_classification);
const bool obvious_to_right = const bool obvious_to_right =
right_index == 0 || obviousByRoadClass(in_way_data.road_classification, right_index == 0 || obviousByRoadClass(in_way_edge.flags.road_classification,
best_option_data.road_classification, best_option_edge.flags.road_classification,
right_data.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 // if the best_option turn isn't narrow, but there is a nearly straight turn, we don't
// consider the turn obvious // 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 distinction rate. If the road category is smaller, its also adjusted. Only
roads of the same priority require the full distinction ratio. 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); node_based_graph.GetEdgeData(intersection[best_option].eid);
const auto adjusted_distinction_ratio = [&]() { const auto adjusted_distinction_ratio = [&]() {
// obviousness by road classes // obviousness by road classes
if (in_way_data.road_classification == best_option_data.road_classification && if (in_way_edge.flags.road_classification ==
best_option_data.road_classification.GetPriority() < best_option_edge.flags.road_classification &&
best_option_edge.flags.road_classification.GetPriority() <
node_based_graph.GetEdgeData(intersection[index].eid) node_based_graph.GetEdgeData(intersection[index].eid)
.road_classification.GetPriority()) .flags.road_classification.GetPriority())
return 0.8 * DISTINCTION_RATIO; return 0.8 * DISTINCTION_RATIO;
// if road classes are the same, we use the full ratio // if road classes are the same, we use the full ratio
else else
@ -472,7 +485,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
} }
else 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) if (std::abs(best_continue_deviation) < 1)
return best_continue; return best_continue;
@ -488,11 +503,12 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (i == best_continue || !intersection[i].entry_allowed) if (i == best_continue || !intersection[i].entry_allowed)
continue; 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 = const bool is_obvious_by_road_class =
obviousByRoadClass(in_way_data.road_classification, obviousByRoadClass(in_way_edge.flags.road_classification,
continue_data.road_classification, continue_edge.flags.road_classification,
turn_data.road_classification); turn_edge.flags.road_classification);
// if the main road is obvious by class, we ignore the current road as a potential // if the main road is obvious by class, we ignore the current road as a potential
// prevention of obviousness // prevention of obviousness
@ -500,9 +516,9 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
continue; continue;
// continuation could be grouped with a straight turn and the turning road is a ramp // 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 && best_continue_deviation < GROUP_ANGLE &&
!continue_data.road_classification.IsRampClass()) !continue_edge.flags.road_classification.IsRampClass())
continue; continue;
// perfectly straight turns prevent obviousness // 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 // 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 // roads. So if there is a road that is enterable in the opposite direction just
// prior, a turn is not obvious // 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 && if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
angularDeviation(comparison_road.angle, continue_road.angle) < angularDeviation(comparison_road.angle, continue_road.angle) <
FUZZY_ANGLE_DIFFERENCE && FUZZY_ANGLE_DIFFERENCE &&
!turn_data.reversed && continue_data.CanCombineWith(turn_data)) !turn_edge_data.reversed && continue_data.CanCombineWith(turn_data))
return 0; return 0;
} }
} }

View File

@ -43,6 +43,7 @@ class IntersectionNormalizer
std::vector<IntersectionNormalizationOperation> performed_merges; std::vector<IntersectionNormalizationOperation> performed_merges;
}; };
IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph, IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &node_coordinates, const std::vector<util::Coordinate> &node_coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,

View File

@ -37,6 +37,7 @@ class MergableRoadDetector
using MergableRoadData = IntersectionShapeData; using MergableRoadData = IntersectionShapeData;
MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph, MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &node_coordinates, const std::vector<util::Coordinate> &node_coordinates,
const IntersectionGenerator &intersection_generator, const IntersectionGenerator &intersection_generator,
const CoordinateExtractor &coordinate_extractor, 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 // 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 // same road. This check tries to identify roads which are the same road in opposite directions
bool EdgeDataSupportsMerge(const util::NodeBasedEdgeData &lhs_edge_data, bool EdgeDataSupportsMerge(const NodeBasedEdgeClassification &lhs_flags,
const util::NodeBasedEdgeData &rhs_edge_data) const; const NodeBasedEdgeClassification &rhs_flags,
const NodeBasedEdgeAnnotation &lhs_edge_annotation,
const NodeBasedEdgeAnnotation &rhs_edge_annotation) const;
// Detect traffic loops. // Detect traffic loops.
// Since OSRM cannot handle loop edges, we cannot directly see a connection between a node and // 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; bool IsLinkRoad(const NodeID intersection_node, const MergableRoadData &road) const;
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const std::vector<util::Coordinate> &node_coordinates; const std::vector<util::Coordinate> &node_coordinates;
const IntersectionGenerator &intersection_generator; const IntersectionGenerator &intersection_generator;
const CoordinateExtractor &coordinate_extractor; const CoordinateExtractor &coordinate_extractor;

View File

@ -24,6 +24,7 @@ class MotorwayHandler : public IntersectionHandler
{ {
public: public:
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph, MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,

View File

@ -28,6 +28,7 @@ class NodeBasedGraphWalker
{ {
public: public:
NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph, NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const IntersectionGenerator &intersection_generator); const IntersectionGenerator &intersection_generator);
/* /*
@ -46,6 +47,7 @@ class NodeBasedGraphWalker
private: private:
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
const IntersectionGenerator &intersection_generator; const IntersectionGenerator &intersection_generator;
}; };
@ -106,7 +108,8 @@ struct SelectRoadByNameOnlyChoiceAndStraightness
boost::optional<EdgeID> operator()(const NodeID nid, boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id, const EdgeID via_edge_id,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph) const; const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
private: private:
const NameID desired_name_id; const NameID desired_name_id;
@ -131,7 +134,8 @@ struct SelectStraightmostRoadByNameAndOnlyChoice
boost::optional<EdgeID> operator()(const NodeID nid, boost::optional<EdgeID> operator()(const NodeID nid,
const EdgeID via_edge_id, const EdgeID via_edge_id,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph) const; const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const;
private: private:
const NameID desired_name_id; const NameID desired_name_id;
@ -201,8 +205,11 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id,
if (next_intersection.size() <= 1) if (next_intersection.size() <= 1)
return {}; return {};
auto next_edge_id = auto next_edge_id = selector(current_node_id,
selector(current_node_id, current_edge_id, next_intersection, node_based_graph); current_edge_id,
next_intersection,
node_based_graph,
node_data_container);
if (!next_edge_id) if (!next_edge_id)
return {}; return {};
@ -224,7 +231,8 @@ struct SkipTrafficSignalBarrierRoadSelector
boost::optional<EdgeID> operator()(const NodeID, boost::optional<EdgeID> operator()(const NodeID,
const EdgeID, const EdgeID,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &) const const util::NodeBasedDynamicGraph &,
const EdgeBasedNodeDataContainer &) const
{ {
if (intersection.isTrafficSignalOrBarrier()) if (intersection.isTrafficSignalOrBarrier())
{ {

View File

@ -7,7 +7,6 @@
#include "extractor/guidance/intersection_generator.hpp" #include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/intersection_handler.hpp" #include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/roundabout_type.hpp" #include "extractor/guidance/roundabout_type.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "util/name_table.hpp" #include "util/name_table.hpp"
@ -41,11 +40,11 @@ class RoundaboutHandler : public IntersectionHandler
{ {
public: public:
RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph, RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container, const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties,
const IntersectionGenerator &intersection_generator); const IntersectionGenerator &intersection_generator);
~RoundaboutHandler() override final = default; ~RoundaboutHandler() override final = default;
@ -86,8 +85,6 @@ class RoundaboutHandler : public IntersectionHandler
qualifiesAsRoundaboutIntersection(const std::unordered_set<NodeID> &roundabout_nodes) const; qualifiesAsRoundaboutIntersection(const std::unordered_set<NodeID> &roundabout_nodes) const;
const CompressedEdgeContainer &compressed_edge_container; const CompressedEdgeContainer &compressed_edge_container;
const ProfileProperties &profile_properties;
const CoordinateExtractor coordinate_extractor; const CoordinateExtractor coordinate_extractor;
}; };

View File

@ -26,6 +26,7 @@ class SliproadHandler final : public IntersectionHandler
public: public:
SliproadHandler(const IntersectionGenerator &intersection_generator, SliproadHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table); const SuffixTable &street_name_suffix_table);

View File

@ -23,6 +23,7 @@ class SuppressModeHandler final : public IntersectionHandler
public: public:
SuppressModeHandler(const IntersectionGenerator &intersection_generator, SuppressModeHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table); const SuffixTable &street_name_suffix_table);

View File

@ -41,13 +41,13 @@ class TurnAnalysis
{ {
public: public:
TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph, TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const RestrictionMap &restriction_map, const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container, const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table);
const ProfileProperties &profile_properties);
/* Full Analysis Process for a single node/edge combination. Use with caution, as the process is /* Full Analysis Process for a single node/edge combination. Use with caution, as the process is
* relatively expensive */ * relatively expensive */

View File

@ -28,6 +28,7 @@ class TurnHandler : public IntersectionHandler
{ {
public: public:
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph, TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,

View File

@ -73,6 +73,7 @@ class TurnLaneHandler
typedef std::vector<TurnLaneData> LaneDataVector; typedef std::vector<TurnLaneData> LaneDataVector;
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph, TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
LaneDescriptionMap &lane_description_map, LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis, const TurnAnalysis &turn_analysis,
util::guidance::LaneDataIdMap &id_map); 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 // we need to be able to look at previous intersections to, in some cases, find the correct turn
// lanes for a turn // lanes for a turn
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
const EdgeBasedNodeDataContainer &node_data_container;
std::vector<std::uint32_t> turn_lane_offsets; std::vector<std::uint32_t> turn_lane_offsets;
std::vector<TurnLaneType::Mask> turn_lane_masks; std::vector<TurnLaneType::Mask> turn_lane_masks;
LaneDescriptionMap &lane_description_map; LaneDescriptionMap &lane_description_map;

View File

@ -58,65 +58,24 @@ struct InternalExtractorEdge
using WeightData = detail::ByEdgeOrByMeterValue; using WeightData = detail::ByEdgeOrByMeterValue;
using DurationData = detail::ByEdgeOrByMeterValue; using DurationData = detail::ByEdgeOrByMeterValue;
explicit InternalExtractorEdge() explicit InternalExtractorEdge() : weight_data(), duration_data() {}
: 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(OSMNodeID source, explicit InternalExtractorEdge(OSMNodeID source,
OSMNodeID target, OSMNodeID target,
NodeID name_id,
WeightData weight_data, WeightData weight_data,
DurationData duration_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) util::Coordinate source_coordinate)
: result(source, : result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
target, duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
name_id, {
0, }
0,
forward, explicit InternalExtractorEdge(NodeBasedEdgeWithOSM edge,
backward, WeightData weight_data,
roundabout, DurationData duration_data,
circular, util::Coordinate source_coordinate)
startpoint, : result(std::move(edge)), weight_data(weight_data), duration_data(duration_data),
restricted, source_coordinate(source_coordinate)
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))
{ {
} }
@ -132,45 +91,13 @@ struct InternalExtractorEdge
// necessary static util functions for stxxl's sorting // necessary static util functions for stxxl's sorting
static InternalExtractorEdge min_osm_value() static InternalExtractorEdge min_osm_value()
{ {
return InternalExtractorEdge(MIN_OSM_NODEID, return InternalExtractorEdge(
MIN_OSM_NODEID, MIN_OSM_NODEID, MIN_OSM_NODEID, WeightData(), DurationData(), util::Coordinate());
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());
} }
static InternalExtractorEdge max_osm_value() static InternalExtractorEdge max_osm_value()
{ {
return InternalExtractorEdge(MAX_OSM_NODEID, return InternalExtractorEdge(
MAX_OSM_NODEID, MAX_OSM_NODEID, MAX_OSM_NODEID, WeightData(), DurationData(), util::Coordinate());
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());
} }
static InternalExtractorEdge min_internal_value() static InternalExtractorEdge min_internal_value()

View File

@ -1,6 +1,9 @@
#ifndef NODE_BASED_EDGE_HPP #ifndef NODE_BASED_EDGE_HPP
#define NODE_BASED_EDGE_HPP #define NODE_BASED_EDGE_HPP
#include <cstdint>
#include <tuple>
#include "extractor/class_data.hpp" #include "extractor/class_data.hpp"
#include "extractor/travel_mode.hpp" #include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
@ -12,68 +15,97 @@ namespace osrm
namespace extractor 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 struct NodeBasedEdge
{ {
NodeBasedEdge(); NodeBasedEdge();
NodeBasedEdge(NodeID source, NodeBasedEdge(NodeID source,
NodeID target, NodeID target,
NodeID name_id,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
bool forward, GeometryID geometry_id,
bool backward, AnnotationID annotation_data,
bool roundabout, NodeBasedEdgeClassification flags);
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);
bool operator<(const NodeBasedEdge &other) const; bool operator<(const NodeBasedEdge &other) const;
NodeID source; // 32 4 NodeID source; // 32 4
NodeID target; // 32 4 NodeID target; // 32 4
NodeID name_id; // 32 4
EdgeWeight weight; // 32 4 EdgeWeight weight; // 32 4
EdgeDuration duration; // 32 4 EdgeDuration duration; // 32 4
std::uint8_t forward : 1; // 1 GeometryID geometry_id; // 32 4
std::uint8_t backward : 1; // 1 AnnotationID annotation_data; // 32 4
std::uint8_t roundabout : 1; // 1 NodeBasedEdgeClassification flags; // 32 4
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
}; };
struct NodeBasedEdgeWithOSM : NodeBasedEdge struct NodeBasedEdgeWithOSM : NodeBasedEdge
{ {
NodeBasedEdgeWithOSM();
NodeBasedEdgeWithOSM(OSMNodeID source, NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target, OSMNodeID target,
NodeID name_id,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
bool forward, GeometryID geometry_id,
bool backward, AnnotationID annotation_data,
bool roundabout, NodeBasedEdgeClassification flags);
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);
OSMNodeID osm_source_id; OSMNodeID osm_source_id;
OSMNodeID osm_target_id; OSMNodeID osm_target_id;
@ -81,36 +113,26 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
// Impl. // Impl.
inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
: forward(false), backward(false), is_split(false), roundabout(false), circular(false),
startpoint(false), restricted(false)
{
}
inline NodeBasedEdge::NodeBasedEdge() inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), duration(0), : source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
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)
{ {
} }
inline NodeBasedEdge::NodeBasedEdge(NodeID source, inline NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target, NodeID target,
NodeID name_id,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
bool forward, GeometryID geometry_id,
bool backward, AnnotationID annotation_data,
bool roundabout, NodeBasedEdgeClassification flags)
bool circular, : source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
bool startpoint, annotation_data(annotation_data), flags(flags)
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))
{ {
} }
@ -122,7 +144,8 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
{ {
if (weight == other.weight) 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; return weight < other.weight;
} }
@ -133,42 +156,22 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source, inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
OSMNodeID target, OSMNodeID target,
NodeID name_id,
EdgeWeight weight, EdgeWeight weight,
EdgeDuration duration, EdgeDuration duration,
bool forward, GeometryID geometry_id,
bool backward, AnnotationID annotation_data,
bool roundabout, NodeBasedEdgeClassification flags)
bool circular, : NodeBasedEdge(
bool startpoint, SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
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)),
osm_source_id(std::move(source)), osm_target_id(std::move(target)) 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, static_assert(sizeof(extractor::NodeBasedEdge) == 28,
"Size of extractor::NodeBasedEdge type is " "Size of extractor::NodeBasedEdge type is "
"bigger than expected. This will influence " "bigger than expected. This will influence "

View File

@ -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_

View File

@ -2,6 +2,8 @@
#define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP #define OSRM_EXTRACTOR_NODE_DATA_CONTAINER_HPP
#include "extractor/class_data.hpp" #include "extractor/class_data.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/node_based_edge.hpp"
#include "extractor/travel_mode.hpp" #include "extractor/travel_mode.hpp"
#include "storage/io_fwd.hpp" #include "storage/io_fwd.hpp"
@ -15,6 +17,10 @@ namespace osrm
{ {
namespace extractor namespace extractor
{ {
class Extractor;
class EdgeBasedGraphFactory;
namespace detail namespace detail
{ {
template <storage::Ownership Ownership> class EdgeBasedNodeDataContainerImpl; 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>; template <typename T> using Vector = util::ViewOrVector<T, Ownership>;
using TravelMode = extractor::TravelMode; using TravelMode = extractor::TravelMode;
// to fill in data on edgeBasedNodes
friend class osrm::extractor::Extractor;
friend class osrm::extractor::EdgeBasedGraphFactory;
public: public:
EdgeBasedNodeDataContainerImpl() = default; EdgeBasedNodeDataContainerImpl() = default;
EdgeBasedNodeDataContainerImpl(std::size_t size) EdgeBasedNodeDataContainerImpl(const NodeID number_of_edge_based_nodes,
: geometry_ids(size), name_ids(size), component_ids(size), travel_modes(size), const AnnotationID number_of_annotations)
classes(size), is_left_hand_driving(size) : nodes(number_of_edge_based_nodes), annotation_data(number_of_annotations)
{ {
} }
EdgeBasedNodeDataContainerImpl(Vector<GeometryID> geometry_ids, EdgeBasedNodeDataContainerImpl(Vector<EdgeBasedNode> nodes,
Vector<NameID> name_ids, Vector<NodeBasedEdgeAnnotation> annotation_data)
Vector<ComponentID> component_ids, : nodes(std::move(nodes)), annotation_data(std::move(annotation_data))
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))
{ {
} }
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]; } TravelMode GetTravelMode(const NodeID node_id) const
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
{ {
return is_left_hand_driving[node_id]; return annotation_data[nodes[node_id].annotation_id].travel_mode;
} }
// Used by EdgeBasedGraphFactory to fill data structure bool IsLeftHandDriving(const NodeID node_id) const
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)
{ {
geometry_ids[node_id] = geometry_id; return annotation_data[nodes[node_id].annotation_id].is_left_hand_driving;
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;
} }
// Used by EdgeBasedGraphFactory to fill data structure NameID GetNameID(const NodeID node_id) const
template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
void SetComponentID(NodeID node_id, ComponentID component_id)
{ {
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, 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>> template <typename = std::enable_if<Ownership == storage::Ownership::Container>>
void Renumber(const std::vector<std::uint32_t> &permutation) void Renumber(const std::vector<std::uint32_t> &permutation)
{ {
util::inplacePermutation(geometry_ids.begin(), geometry_ids.end(), permutation); util::inplacePermutation(nodes.begin(), nodes.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);
} }
// all containers have the exact same size NodeID NumberOfNodes() const { return nodes.size(); }
std::size_t Size() const
// 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()); return annotation_data[annotation];
BOOST_ASSERT(geometry_ids.size() == component_ids.size()); }
BOOST_ASSERT(geometry_ids.size() == travel_modes.size()); NodeBasedEdgeAnnotation const &GetAnnotation(const AnnotationID annotation) const
BOOST_ASSERT(geometry_ids.size() == classes.size()); {
BOOST_ASSERT(geometry_ids.size() == is_left_hand_driving.size()); return annotation_data[annotation];
return geometry_ids.size();
} }
private: private:
Vector<GeometryID> geometry_ids; Vector<EdgeBasedNode> nodes;
Vector<NameID> name_ids; Vector<NodeBasedEdgeAnnotation> annotation_data;
Vector<ComponentID> component_ids;
Vector<TravelMode> travel_modes;
Vector<ClassData> classes;
Vector<bool> is_left_hand_driving;
}; };
} }
@ -141,7 +128,7 @@ using EdgeBasedNodeDataExternalContainer =
using EdgeBasedNodeDataContainer = using EdgeBasedNodeDataContainer =
detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::Container>; detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::Container>;
using EdgeBasedNodeDataView = detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::View>; using EdgeBasedNodeDataView = detail::EdgeBasedNodeDataContainerImpl<storage::Ownership::View>;
} } // namespace extractor
} } // namespace osrm
#endif #endif

View File

@ -96,7 +96,7 @@ class Sol2ScriptingEnvironment final : public ScriptingEnvironment
std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations, std::vector<std::pair<const osmium::Relation &, ExtractionRelation>> &resulting_relations,
std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override; std::vector<InputConditionalTurnRestriction> &resulting_restrictions) override;
bool HasLocationDependentData() const { return !location_dependent_data.empty(); } bool HasLocationDependentData() const override { return !location_dependent_data.empty(); }
private: private:
LuaScriptingContext &GetSol2Context(); LuaScriptingContext &GetSol2Context();

View File

@ -120,24 +120,22 @@ template <storage::Ownership Ownership>
inline void read(storage::io::FileReader &reader, inline void read(storage::io::FileReader &reader,
detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container) detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
{ {
storage::serialization::read(reader, node_data_container.geometry_ids); // read header (separate sizes for both vectors)
storage::serialization::read(reader, node_data_container.name_ids); reader.ReadElementCount64();
storage::serialization::read(reader, node_data_container.component_ids); reader.ReadElementCount64();
storage::serialization::read(reader, node_data_container.travel_modes); // read actual data
storage::serialization::read(reader, node_data_container.classes); storage::serialization::read(reader, node_data_container.nodes);
storage::serialization::read(reader, node_data_container.is_left_hand_driving); storage::serialization::read(reader, node_data_container.annotation_data);
} }
template <storage::Ownership Ownership> template <storage::Ownership Ownership>
inline void write(storage::io::FileWriter &writer, inline void write(storage::io::FileWriter &writer,
const detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container) const detail::EdgeBasedNodeDataContainerImpl<Ownership> &node_data_container)
{ {
storage::serialization::write(writer, node_data_container.geometry_ids); writer.WriteElementCount64(node_data_container.NumberOfNodes());
storage::serialization::write(writer, node_data_container.name_ids); writer.WriteElementCount64(node_data_container.NumberOfAnnotations());
storage::serialization::write(writer, node_data_container.component_ids); storage::serialization::write(writer, node_data_container.nodes);
storage::serialization::write(writer, node_data_container.travel_modes); storage::serialization::write(writer, node_data_container.annotation_data);
storage::serialization::write(writer, node_data_container.classes);
storage::serialization::write(writer, node_data_container.is_left_hand_driving);
} }
inline void read(storage::io::FileReader &reader, NodeRestriction &restriction) inline void read(storage::io::FileReader &reader, NodeRestriction &restriction)

View File

@ -184,14 +184,14 @@ graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
inline DynamicEdgeBasedGraph LoadEdgeBasedGraph(const boost::filesystem::path &path) inline DynamicEdgeBasedGraph LoadEdgeBasedGraph(const boost::filesystem::path &path)
{ {
EdgeID max_node_id; EdgeID number_of_edge_based_nodes;
std::vector<extractor::EdgeBasedEdge> edges; std::vector<extractor::EdgeBasedEdge> edges;
extractor::files::readEdgeBasedGraph(path, max_node_id, edges); extractor::files::readEdgeBasedGraph(path, number_of_edge_based_nodes, edges);
auto directed = splitBidirectionalEdges(edges); auto directed = splitBidirectionalEdges(edges);
auto tidied = prepareEdgesForUsageInGraph<DynamicEdgeBasedGraphEdge>(std::move(directed)); auto tidied = prepareEdgesForUsageInGraph<DynamicEdgeBasedGraphEdge>(std::move(directed));
return DynamicEdgeBasedGraph(max_node_id + 1, std::move(tidied)); return DynamicEdgeBasedGraph(number_of_edge_based_nodes, std::move(tidied));
} }
} // ns partition } // ns partition

View File

@ -19,12 +19,8 @@ namespace storage
const constexpr char CANARY[4] = {'O', 'S', 'R', 'M'}; const constexpr char CANARY[4] = {'O', 'S', 'R', 'M'};
const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA", const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
"GEOMETRY_ID_LIST", "EDGE_BASED_NODE_DATA",
"NAME_ID_LIST", "ANNOTATION_DATA",
"COMPONENT_ID_LIST",
"TRAVEL_MODE_LIST",
"CLASSES_LIST",
"IS_LEFT_HAND_DRIVING_LIST",
"CH_GRAPH_NODE_LIST", "CH_GRAPH_NODE_LIST",
"CH_GRAPH_EDGE_LIST", "CH_GRAPH_EDGE_LIST",
"CH_EDGE_FILTER_0", "CH_EDGE_FILTER_0",
@ -107,12 +103,8 @@ struct DataLayout
enum BlockID enum BlockID
{ {
NAME_CHAR_DATA = 0, NAME_CHAR_DATA = 0,
GEOMETRY_ID_LIST, EDGE_BASED_NODE_DATA_LIST,
NAME_ID_LIST, ANNOTATION_DATA_LIST,
COMPONENT_ID_LIST,
TRAVEL_MODE_LIST,
CLASSES_LIST,
IS_LEFT_HAND_DRIVING_LIST,
CH_GRAPH_NODE_LIST, CH_GRAPH_NODE_LIST,
CH_GRAPH_EDGE_LIST, CH_GRAPH_EDGE_LIST,
CH_EDGE_FILTER_0, CH_EDGE_FILTER_0,

View File

@ -3,6 +3,7 @@
#include "extractor/guidance/intersection.hpp" #include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/turn_lane_data.hpp" #include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/node_data_container.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "engine/guidance/route_step.hpp" #include "engine/guidance/route_step.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
@ -77,7 +78,8 @@ inline void print(const NodeBasedDynamicGraph &node_based_graph,
for (const auto &road : intersection) for (const auto &road : intersection)
{ {
std::cout << "\t" << toString(road) << "\n"; std::cout << "\t" << toString(road) << "\n";
std::cout << "\t\t" << node_based_graph.GetEdgeData(road.eid).road_classification.ToString() std::cout << "\t\t"
<< node_based_graph.GetEdgeData(road.eid).flags.road_classification.ToString()
<< "\n"; << "\n";
} }
std::cout << std::flush; std::cout << std::flush;

View File

@ -223,6 +223,7 @@ template <typename EdgeDataT> class DynamicGraph
unsigned GetNumberOfNodes() const { return number_of_nodes; } unsigned GetNumberOfNodes() const { return number_of_nodes; }
unsigned GetNumberOfEdges() const { return number_of_edges; } unsigned GetNumberOfEdges() const { return number_of_edges; }
auto GetEdgeCapacity() const { return edge_list.size(); }
unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; } unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; }

View File

@ -77,7 +77,7 @@ NodeID loadNodesFromFile(storage::io::FileReader &file_reader,
/** /**
* Reads a .osrm file and produces the edges. * Reads a .osrm file and produces the edges.
*/ */
inline NodeID loadEdgesFromFile(storage::io::FileReader &file_reader, inline EdgeID loadEdgesFromFile(storage::io::FileReader &file_reader,
std::vector<extractor::NodeBasedEdge> &edge_list) std::vector<extractor::NodeBasedEdge> &edge_list)
{ {
auto number_of_edges = file_reader.ReadElementCount64(); auto number_of_edges = file_reader.ReadElementCount64();
@ -104,8 +104,7 @@ inline NodeID loadEdgesFromFile(storage::io::FileReader &file_reader,
const auto &prev_edge = edge_list[i - 1]; const auto &prev_edge = edge_list[i - 1];
BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight"); BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight");
BOOST_ASSERT_MSG(edge.forward, "edge must be oriented in forward direction"); BOOST_ASSERT_MSG(edge.flags.forward, "edge must be oriented in forward direction");
BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible");
BOOST_ASSERT_MSG(edge.source != edge.target, "loaded edges contain a loop"); BOOST_ASSERT_MSG(edge.source != edge.target, "loaded edges contain a loop");
BOOST_ASSERT_MSG(edge.source != prev_edge.source || edge.target != prev_edge.target, BOOST_ASSERT_MSG(edge.source != prev_edge.source || edge.target != prev_edge.target,
@ -117,6 +116,15 @@ inline NodeID loadEdgesFromFile(storage::io::FileReader &file_reader,
return number_of_edges; return number_of_edges;
} }
inline EdgeID loadAnnotationData(storage::io::FileReader &file_reader,
std::vector<extractor::NodeBasedEdgeAnnotation> &metadata)
{
auto const meta_data_count = file_reader.ReadElementCount64();
metadata.resize(meta_data_count);
file_reader.ReadInto(metadata.data(), meta_data_count);
return meta_data_count;
}
} }
} }

View File

@ -74,7 +74,7 @@ std::vector<OutputEdgeT> directedEdgesFromCompressed(const std::vector<InputEdge
for (const auto &input_edge : input_edge_list) for (const auto &input_edge : input_edge_list)
{ {
// edges that are not forward get converted by flipping the end points // edges that are not forward get converted by flipping the end points
BOOST_ASSERT(input_edge.forward); BOOST_ASSERT(input_edge.flags.forward);
edge.source = input_edge.source; edge.source = input_edge.source;
edge.target = input_edge.target; edge.target = input_edge.target;
@ -86,10 +86,10 @@ std::vector<OutputEdgeT> directedEdgesFromCompressed(const std::vector<InputEdge
output_edge_list.push_back(edge); output_edge_list.push_back(edge);
if (!input_edge.is_split) if (!input_edge.flags.is_split)
{ {
std::swap(edge.source, edge.target); std::swap(edge.source, edge.target);
edge.data.reversed = !input_edge.backward; edge.data.reversed = !input_edge.flags.backward;
output_edge_list.push_back(edge); output_edge_list.push_back(edge);
} }
} }

View File

@ -4,12 +4,14 @@
#include "extractor/class_data.hpp" #include "extractor/class_data.hpp"
#include "extractor/guidance/road_classification.hpp" #include "extractor/guidance/road_classification.hpp"
#include "extractor/node_based_edge.hpp" #include "extractor/node_based_edge.hpp"
#include "extractor/node_data_container.hpp"
#include "util/dynamic_graph.hpp" #include "util/dynamic_graph.hpp"
#include "util/graph_utils.hpp" #include "util/graph_utils.hpp"
#include <tbb/parallel_sort.h> #include <tbb/parallel_sort.h>
#include <memory> #include <memory>
#include <utility>
namespace osrm namespace osrm
{ {
@ -19,70 +21,57 @@ namespace util
struct NodeBasedEdgeData struct NodeBasedEdgeData
{ {
NodeBasedEdgeData() NodeBasedEdgeData()
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID), : weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), geometry_id({0, false}),
name_id(std::numeric_limits<unsigned>::max()), reversed(false), roundabout(false), reversed(false), annotation_data(-1)
circular(false), startpoint(false), restricted(false), is_left_hand_driving(false),
travel_mode(TRAVEL_MODE_INACCESSIBLE), lane_description_id(INVALID_LANE_DESCRIPTIONID)
{ {
} }
NodeBasedEdgeData(EdgeWeight weight, NodeBasedEdgeData(EdgeWeight weight,
EdgeWeight duration, EdgeWeight duration,
unsigned edge_id, GeometryID geometry_id,
unsigned name_id,
bool reversed, bool reversed,
bool roundabout, extractor::NodeBasedEdgeClassification flags,
bool circular, AnnotationID annotation_data)
bool startpoint, : weight(weight), duration(duration), geometry_id(geometry_id), reversed(reversed),
bool restricted, flags(flags), annotation_data(annotation_data)
bool is_left_hand_driving,
extractor::TravelMode travel_mode,
extractor::ClassData classes,
const LaneDescriptionID lane_description_id)
: weight(weight), duration(duration), edge_id(edge_id), name_id(name_id),
reversed(reversed), roundabout(roundabout), circular(circular), startpoint(startpoint),
restricted(restricted), is_left_hand_driving(is_left_hand_driving),
travel_mode(travel_mode), classes(classes), lane_description_id(lane_description_id)
{ {
} }
EdgeWeight weight; EdgeWeight weight;
EdgeWeight duration; EdgeWeight duration;
unsigned edge_id; GeometryID geometry_id;
unsigned name_id;
bool reversed : 1; bool reversed : 1;
bool roundabout : 1; extractor::NodeBasedEdgeClassification flags;
bool circular : 1; AnnotationID annotation_data;
bool startpoint : 1;
bool restricted : 1;
bool is_left_hand_driving : 1;
extractor::TravelMode travel_mode : 4;
extractor::ClassData classes;
LaneDescriptionID lane_description_id;
extractor::guidance::RoadClassification road_classification;
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
{
return (reversed == other.reversed) && (roundabout == other.roundabout) &&
(circular == other.circular) && (startpoint == other.startpoint) &&
(travel_mode == other.travel_mode) && (classes == other.classes) &&
(road_classification == other.road_classification) &&
(restricted == other.restricted) &&
(is_left_hand_driving == other.is_left_hand_driving);
}
bool CanCombineWith(const NodeBasedEdgeData &other) const
{
return (name_id == other.name_id) && IsCompatibleTo(other);
}
}; };
// Check if two edge data elements can be compressed into a single edge (i.e. match in terms of
// their meta-data).
inline bool CanBeCompressed(const NodeBasedEdgeData &lhs,
const NodeBasedEdgeData &rhs,
const extractor::EdgeBasedNodeDataContainer &node_data_container)
{
if (!(lhs.flags == rhs.flags))
return false;
auto const &lhs_annotation = node_data_container.GetAnnotation(lhs.annotation_data);
auto const &rhs_annotation = node_data_container.GetAnnotation(rhs.annotation_data);
if (lhs_annotation.is_left_hand_driving != rhs_annotation.is_left_hand_driving)
return false;
if (lhs_annotation.travel_mode != rhs_annotation.travel_mode)
return false;
return lhs_annotation.classes == rhs_annotation.classes;
}
using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>; using NodeBasedDynamicGraph = DynamicGraph<NodeBasedEdgeData>;
/// Factory method to create NodeBasedDynamicGraph from NodeBasedEdges /// Factory method to create NodeBasedDynamicGraph from NodeBasedEdges
/// Since DynamicGraph expects directed edges, we need to insert /// Since DynamicGraph expects directed edges, we need to insert
/// two edges for undirected edges. /// two edges for undirected edges.
inline std::shared_ptr<NodeBasedDynamicGraph> inline NodeBasedDynamicGraph
NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes, NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
const std::vector<extractor::NodeBasedEdge> &input_edge_list) const std::vector<extractor::NodeBasedEdge> &input_edge_list)
{ {
@ -92,16 +81,8 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
const extractor::NodeBasedEdge &input_edge) { const extractor::NodeBasedEdge &input_edge) {
output_edge.data.weight = input_edge.weight; output_edge.data.weight = input_edge.weight;
output_edge.data.duration = input_edge.duration; output_edge.data.duration = input_edge.duration;
output_edge.data.roundabout = input_edge.roundabout; output_edge.data.flags = input_edge.flags;
output_edge.data.circular = input_edge.circular; output_edge.data.annotation_data = input_edge.annotation_data;
output_edge.data.name_id = input_edge.name_id;
output_edge.data.travel_mode = input_edge.travel_mode;
output_edge.data.classes = input_edge.classes;
output_edge.data.startpoint = input_edge.startpoint;
output_edge.data.restricted = input_edge.restricted;
output_edge.data.is_left_hand_driving = input_edge.is_left_hand_driving;
output_edge.data.road_classification = input_edge.road_classification;
output_edge.data.lane_description_id = input_edge.lane_description_id;
BOOST_ASSERT(output_edge.data.weight > 0); BOOST_ASSERT(output_edge.data.weight > 0);
BOOST_ASSERT(output_edge.data.duration > 0); BOOST_ASSERT(output_edge.data.duration > 0);
@ -109,9 +90,7 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
tbb::parallel_sort(edges_list.begin(), edges_list.end()); tbb::parallel_sort(edges_list.begin(), edges_list.end());
auto graph = std::make_shared<NodeBasedDynamicGraph>(number_of_nodes, edges_list); return NodeBasedDynamicGraph(number_of_nodes, edges_list);
return graph;
} }
} }
} }

View File

@ -450,6 +450,11 @@ template <typename T, std::size_t Bits, storage::Ownership Ownership> class Pack
friend void serialization::write<T, Bits, Ownership>(storage::io::FileWriter &writer, friend void serialization::write<T, Bits, Ownership>(storage::io::FileWriter &writer,
const PackedVector &vec); const PackedVector &vec);
inline void swap(PackedVector &other) noexcept
{
std::swap(vec, other.vec);
std::swap(num_elements, other.num_elements);
}
private: private:
void allocate_blocks(std::size_t num_blocks) void allocate_blocks(std::size_t num_blocks)

View File

@ -72,6 +72,7 @@ static const OSMWayID MIN_OSM_WAYID = OSMWayID{std::numeric_limits<OSMWayID::val
using NodeID = std::uint32_t; using NodeID = std::uint32_t;
using EdgeID = std::uint32_t; using EdgeID = std::uint32_t;
using NameID = std::uint32_t; using NameID = std::uint32_t;
using AnnotationID = std::uint32_t;
using EdgeWeight = std::int32_t; using EdgeWeight = std::int32_t;
using EdgeDuration = std::int32_t; using EdgeDuration = std::int32_t;
using SegmentWeight = std::uint32_t; using SegmentWeight = std::uint32_t;

View File

@ -68,7 +68,8 @@ int Contractor::Run()
std::vector<extractor::EdgeBasedEdge> edge_based_edge_list; std::vector<extractor::EdgeBasedEdge> edge_based_edge_list;
updater::Updater updater(config.updater_config); updater::Updater updater(config.updater_config);
EdgeID max_edge_id = updater.LoadAndUpdateEdgeExpandedGraph(edge_based_edge_list, node_weights); EdgeID number_of_edge_based_nodes =
updater.LoadAndUpdateEdgeExpandedGraph(edge_based_edge_list, node_weights);
// Contracting the edge-expanded graph // Contracting the edge-expanded graph
@ -82,7 +83,8 @@ int Contractor::Run()
extractor::ProfileProperties properties; extractor::ProfileProperties properties;
extractor::files::readProfileProperties(config.GetPath(".osrm.properties"), properties); extractor::files::readProfileProperties(config.GetPath(".osrm.properties"), properties);
node_filters = util::excludeFlagsToNodeFilter(max_edge_id + 1, node_data, properties); node_filters =
util::excludeFlagsToNodeFilter(number_of_edge_based_nodes, node_data, properties);
} }
RangebasedCRC32 crc32_calculator; RangebasedCRC32 crc32_calculator;
@ -91,8 +93,8 @@ int Contractor::Run()
QueryGraph query_graph; QueryGraph query_graph;
std::vector<std::vector<bool>> edge_filters; std::vector<std::vector<bool>> edge_filters;
std::vector<std::vector<bool>> cores; std::vector<std::vector<bool>> cores;
std::tie(query_graph, edge_filters, cores) = std::tie(query_graph, edge_filters, cores) = contractExcludableGraph(
contractExcludableGraph(toContractorGraph(max_edge_id + 1, std::move(edge_based_edge_list)), toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)),
std::move(node_weights), std::move(node_weights),
std::move(node_filters), std::move(node_filters),
config.core_factor); config.core_factor);

View File

@ -264,6 +264,9 @@ void CompressedEdgeContainer::InitializeBothwayVector()
unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID r_edge_id) unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID r_edge_id)
{ {
if (!segment_data)
InitializeBothwayVector();
const auto &forward_bucket = GetBucketReference(f_edge_id); const auto &forward_bucket = GetBucketReference(f_edge_id);
const auto &reverse_bucket = GetBucketReference(r_edge_id); const auto &reverse_bucket = GetBucketReference(r_edge_id);

View File

@ -60,19 +60,18 @@ namespace extractor
// Configuration to find representative candidate for turn angle calculations // Configuration to find representative candidate for turn angle calculations
EdgeBasedGraphFactory::EdgeBasedGraphFactory( EdgeBasedGraphFactory::EdgeBasedGraphFactory(
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
CompressedEdgeContainer &compressed_edge_container, EdgeBasedNodeDataContainer &node_data_container,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &traffic_lights,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const extractor::PackedOSMIDs &osm_node_ids,
ProfileProperties profile_properties,
const util::NameTable &name_table, const util::NameTable &name_table,
guidance::LaneDescriptionMap &lane_description_map) guidance::LaneDescriptionMap &lane_description_map)
: m_number_of_edge_based_nodes(0), m_coordinates(coordinates), m_osm_node_ids(osm_node_ids), : m_edge_based_node_container(node_data_container), m_number_of_edge_based_nodes(0),
m_node_based_graph(std::move(node_based_graph)), m_barrier_nodes(barrier_nodes), m_coordinates(coordinates), m_node_based_graph(std::move(node_based_graph)),
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container), m_barrier_nodes(barrier_nodes), m_traffic_lights(traffic_lights),
profile_properties(std::move(profile_properties)), name_table(name_table), m_compressed_edge_container(compressed_edge_container), name_table(name_table),
lane_description_map(lane_description_map) lane_description_map(lane_description_map)
{ {
} }
@ -85,12 +84,6 @@ void EdgeBasedGraphFactory::GetEdgeBasedEdges(
swap(m_edge_based_edge_list, output_edge_list); swap(m_edge_based_edge_list, output_edge_list);
} }
void EdgeBasedGraphFactory::GetEdgeBasedNodes(EdgeBasedNodeDataContainer &data_container)
{
using std::swap; // Koenig swap
swap(data_container, m_edge_based_node_container);
}
void EdgeBasedGraphFactory::GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes) void EdgeBasedGraphFactory::GetEdgeBasedNodeSegments(std::vector<EdgeBasedNodeSegment> &nodes)
{ {
using std::swap; // Koenig swap using std::swap; // Koenig swap
@ -121,21 +114,23 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
BOOST_ASSERT(node_v != SPECIAL_NODEID); BOOST_ASSERT(node_v != SPECIAL_NODEID);
// find forward edge id and // find forward edge id and
const EdgeID edge_id_1 = m_node_based_graph->FindEdge(node_u, node_v); const EdgeID edge_id_1 = m_node_based_graph.FindEdge(node_u, node_v);
BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID); BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID);
const EdgeData &forward_data = m_node_based_graph->GetEdgeData(edge_id_1); const EdgeData &forward_data = m_node_based_graph.GetEdgeData(edge_id_1);
// find reverse edge id and // find reverse edge id and
const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u); const EdgeID edge_id_2 = m_node_based_graph.FindEdge(node_v, node_u);
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID); BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2); const EdgeData &reverse_data = m_node_based_graph.GetEdgeData(edge_id_2);
BOOST_ASSERT(forward_data.edge_id != SPECIAL_NODEID || reverse_data.edge_id != SPECIAL_NODEID); BOOST_ASSERT(nbe_to_ebn_mapping[edge_id_1] != SPECIAL_NODEID ||
nbe_to_ebn_mapping[edge_id_2] != SPECIAL_NODEID);
if (forward_data.edge_id != SPECIAL_NODEID && reverse_data.edge_id == SPECIAL_NODEID) if (nbe_to_ebn_mapping[edge_id_1] != SPECIAL_NODEID &&
m_edge_based_node_weights[forward_data.edge_id] = INVALID_EDGE_WEIGHT; nbe_to_ebn_mapping[edge_id_2] == SPECIAL_NODEID)
m_edge_based_node_weights[nbe_to_ebn_mapping[edge_id_1]] = INVALID_EDGE_WEIGHT;
BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_id_1) == BOOST_ASSERT(m_compressed_edge_container.HasEntryForID(edge_id_1) ==
m_compressed_edge_container.HasEntryForID(edge_id_2)); m_compressed_edge_container.HasEntryForID(edge_id_2));
@ -149,7 +144,8 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
// There should always be some geometry // There should always be some geometry
BOOST_ASSERT(0 != segment_count); BOOST_ASSERT(0 != segment_count);
const unsigned packed_geometry_id = m_compressed_edge_container.ZipEdges(edge_id_1, edge_id_2); // const unsigned packed_geometry_id = m_compressed_edge_container.ZipEdges(edge_id_1,
// edge_id_2);
NodeID current_edge_source_coordinate_id = node_u; NodeID current_edge_source_coordinate_id = node_u;
@ -163,23 +159,18 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
}; };
// Add edge-based node data for forward and reverse nodes indexed by edge_id // Add edge-based node data for forward and reverse nodes indexed by edge_id
BOOST_ASSERT(forward_data.edge_id != SPECIAL_EDGEID); BOOST_ASSERT(nbe_to_ebn_mapping[edge_id_1] != SPECIAL_EDGEID);
m_edge_based_node_container.SetData(forward_data.edge_id, m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_1]].geometry_id =
GeometryID{packed_geometry_id, true}, forward_data.geometry_id;
forward_data.name_id, m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_1]].annotation_id =
forward_data.travel_mode, forward_data.annotation_data;
forward_data.classes, if (nbe_to_ebn_mapping[edge_id_2] != SPECIAL_EDGEID)
forward_data.is_left_hand_driving);
if (reverse_data.edge_id != SPECIAL_EDGEID)
{ {
m_edge_based_node_container.SetData(reverse_data.edge_id, m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_2]].geometry_id =
GeometryID{packed_geometry_id, false}, reverse_data.geometry_id;
reverse_data.name_id, m_edge_based_node_container.nodes[nbe_to_ebn_mapping[edge_id_2]].annotation_id =
reverse_data.travel_mode, reverse_data.annotation_data;
reverse_data.classes,
reverse_data.is_left_hand_driving);
} }
// Add segments of edge-based nodes // Add segments of edge-based nodes
for (const auto i : util::irange(std::size_t{0}, segment_count)) for (const auto i : util::irange(std::size_t{0}, segment_count))
{ {
@ -196,20 +187,21 @@ NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const N
BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id); BOOST_ASSERT(current_edge_target_coordinate_id != current_edge_source_coordinate_id);
// build edges // build edges
m_edge_based_node_segments.emplace_back(edge_id_to_segment_id(forward_data.edge_id), m_edge_based_node_segments.emplace_back(
edge_id_to_segment_id(reverse_data.edge_id), edge_id_to_segment_id(nbe_to_ebn_mapping[edge_id_1]),
edge_id_to_segment_id(nbe_to_ebn_mapping[edge_id_2]),
current_edge_source_coordinate_id, current_edge_source_coordinate_id,
current_edge_target_coordinate_id, current_edge_target_coordinate_id,
i); i);
m_edge_based_node_is_startpoint.push_back( m_edge_based_node_is_startpoint.push_back(forward_data.flags.startpoint ||
(forward_data.startpoint || reverse_data.startpoint)); reverse_data.flags.startpoint);
current_edge_source_coordinate_id = current_edge_target_coordinate_id; current_edge_source_coordinate_id = current_edge_target_coordinate_id;
} }
BOOST_ASSERT(current_edge_source_coordinate_id == node_v); BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
return NBGToEBG{node_u, node_v, forward_data.edge_id, reverse_data.edge_id}; return NBGToEBG{node_u, node_v, nbe_to_ebn_mapping[edge_id_1], nbe_to_ebn_mapping[edge_id_2]};
} }
void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment, void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
@ -225,9 +217,15 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
const WayRestrictionMap &way_restriction_map) const WayRestrictionMap &way_restriction_map)
{ {
TIMER_START(renumber); TIMER_START(renumber);
m_number_of_edge_based_nodes = RenumberEdges() + way_restriction_map.NumberOfDuplicatedNodes(); m_number_of_edge_based_nodes =
LabelEdgeBasedNodes() + way_restriction_map.NumberOfDuplicatedNodes();
TIMER_STOP(renumber); TIMER_STOP(renumber);
// Allocate memory for edge-based nodes
// In addition to the normal edges, allocate enough space for copied edges from
// via-way-restrictions, see calculation above
m_edge_based_node_container.nodes.resize(m_number_of_edge_based_nodes);
TIMER_START(generate_nodes); TIMER_START(generate_nodes);
{ {
auto mapping = GenerateEdgeExpandedNodes(way_restriction_map); auto mapping = GenerateEdgeExpandedNodes(way_restriction_map);
@ -258,19 +256,19 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
/// Renumbers all _forward_ edges and sets the edge_id. /// Renumbers all _forward_ edges and sets the edge_id.
/// A specific numbering is not important. Any unique ID will do. /// A specific numbering is not important. Any unique ID will do.
/// Returns the number of edge-based nodes. /// Returns the number of edge-based nodes.
unsigned EdgeBasedGraphFactory::RenumberEdges() unsigned EdgeBasedGraphFactory::LabelEdgeBasedNodes()
{ {
// heuristic: node-based graph node is a simple intersection with four edges (edge-based nodes) // heuristic: node-based graph node is a simple intersection with four edges (edge-based nodes)
m_edge_based_node_weights.reserve(4 * m_node_based_graph->GetNumberOfNodes()); m_edge_based_node_weights.reserve(4 * m_node_based_graph.GetNumberOfNodes());
nbe_to_ebn_mapping.resize(m_node_based_graph.GetEdgeCapacity(), SPECIAL_NODEID);
// renumber edge based node of outgoing edges // renumber edge based node of outgoing edges
unsigned numbered_edges_count = 0; unsigned numbered_edges_count = 0;
for (const auto current_node : util::irange(0u, m_node_based_graph->GetNumberOfNodes())) for (const auto current_node : util::irange(0u, m_node_based_graph.GetNumberOfNodes()))
{ {
for (const auto current_edge : m_node_based_graph->GetAdjacentEdgeRange(current_node)) for (const auto current_edge : m_node_based_graph.GetAdjacentEdgeRange(current_node))
{ {
EdgeData &edge_data = m_node_based_graph->GetEdgeData(current_edge); const EdgeData &edge_data = m_node_based_graph.GetEdgeData(current_edge);
// only number incoming edges // only number incoming edges
if (edge_data.reversed) if (edge_data.reversed)
{ {
@ -279,11 +277,9 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
m_edge_based_node_weights.push_back(edge_data.weight); m_edge_based_node_weights.push_back(edge_data.weight);
BOOST_ASSERT(numbered_edges_count < m_node_based_graph->GetNumberOfEdges()); BOOST_ASSERT(numbered_edges_count < m_node_based_graph.GetNumberOfEdges());
edge_data.edge_id = numbered_edges_count; nbe_to_ebn_mapping[current_edge] = numbered_edges_count;
++numbered_edges_count; ++numbered_edges_count;
BOOST_ASSERT(SPECIAL_NODEID != edge_data.edge_id);
} }
} }
@ -296,31 +292,25 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
{ {
std::vector<NBGToEBG> mapping; std::vector<NBGToEBG> mapping;
// Allocate memory for edge-based nodes
// In addition to the normal edges, allocate enough space for copied edges from
// via-way-restrictions
m_edge_based_node_container = EdgeBasedNodeDataContainer(m_number_of_edge_based_nodes);
util::Log() << "Generating edge expanded nodes ... "; util::Log() << "Generating edge expanded nodes ... ";
// indicating a normal node within the edge-based graph. This node represents an edge in the // indicating a normal node within the edge-based graph. This node represents an edge in the
// node-based graph // node-based graph
{ {
util::UnbufferedLog log; util::UnbufferedLog log;
util::Percent progress(log, m_node_based_graph->GetNumberOfNodes()); util::Percent progress(log, m_node_based_graph.GetNumberOfNodes());
m_compressed_edge_container.InitializeBothwayVector(); // m_compressed_edge_container.InitializeBothwayVector();
// loop over all edges and generate new set of nodes // loop over all edges and generate new set of nodes
for (const auto nbg_node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes())) for (const auto nbg_node_u : util::irange(0u, m_node_based_graph.GetNumberOfNodes()))
{ {
BOOST_ASSERT(nbg_node_u != SPECIAL_NODEID); BOOST_ASSERT(nbg_node_u != SPECIAL_NODEID);
progress.PrintStatus(nbg_node_u); progress.PrintStatus(nbg_node_u);
for (EdgeID nbg_edge_id : m_node_based_graph->GetAdjacentEdgeRange(nbg_node_u)) for (EdgeID nbg_edge_id : m_node_based_graph.GetAdjacentEdgeRange(nbg_node_u))
{ {
BOOST_ASSERT(nbg_edge_id != SPECIAL_EDGEID); BOOST_ASSERT(nbg_edge_id != SPECIAL_EDGEID);
const EdgeData &nbg_edge_data = m_node_based_graph->GetEdgeData(nbg_edge_id); const NodeID nbg_node_v = m_node_based_graph.GetTarget(nbg_edge_id);
const NodeID nbg_node_v = m_node_based_graph->GetTarget(nbg_edge_id);
BOOST_ASSERT(nbg_node_v != SPECIAL_NODEID); BOOST_ASSERT(nbg_node_v != SPECIAL_NODEID);
BOOST_ASSERT(nbg_node_u != nbg_node_v); BOOST_ASSERT(nbg_node_u != nbg_node_v);
@ -332,7 +322,7 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
} }
// if we found a non-forward edge reverse and try again // if we found a non-forward edge reverse and try again
if (nbg_edge_data.edge_id == SPECIAL_NODEID) if (nbe_to_ebn_mapping[nbg_edge_id] == SPECIAL_NODEID)
{ {
mapping.push_back(InsertEdgeBasedNode(nbg_node_v, nbg_node_u)); mapping.push_back(InsertEdgeBasedNode(nbg_node_v, nbg_node_u));
} }
@ -360,28 +350,21 @@ EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const WayRestrictionMap &way_re
const auto node_u = way.from; const auto node_u = way.from;
const auto node_v = way.to; const auto node_v = way.to;
// we know that the edge exists as non-reversed edge // we know that the edge exists as non-reversed edge
const auto eid = m_node_based_graph->FindEdge(node_u, node_v); const auto eid = m_node_based_graph.FindEdge(node_u, node_v);
BOOST_ASSERT(m_node_based_graph->GetEdgeData(eid).edge_id != SPECIAL_NODEID); BOOST_ASSERT(nbe_to_ebn_mapping[eid] != SPECIAL_NODEID);
// merge edges together into one EdgeBasedNode // merge edges together into one EdgeBasedNode
BOOST_ASSERT(node_u != SPECIAL_NODEID); BOOST_ASSERT(node_u != SPECIAL_NODEID);
BOOST_ASSERT(node_v != SPECIAL_NODEID); BOOST_ASSERT(node_v != SPECIAL_NODEID);
// find node in the edge based graph, we only require one id: // find node in the edge based graph, we only require one id:
const EdgeData &edge_data = m_node_based_graph->GetEdgeData(eid); const EdgeData &edge_data = m_node_based_graph.GetEdgeData(eid);
// what is this ID all about? :( // BOOST_ASSERT(edge_data.edge_id < m_edge_based_node_container.Size());
BOOST_ASSERT(edge_data.edge_id != SPECIAL_NODEID); m_edge_based_node_container.nodes[edge_based_node_id].geometry_id =
edge_data.geometry_id;
BOOST_ASSERT(edge_data.edge_id < m_edge_based_node_container.Size()); m_edge_based_node_container.nodes[edge_based_node_id].annotation_id =
m_edge_based_node_container.SetData( edge_data.annotation_data;
edge_based_node_id,
// fetch the known geometry ID
m_edge_based_node_container.GetGeometryID(static_cast<NodeID>(edge_data.edge_id)),
edge_data.name_id,
edge_data.travel_mode,
edge_data.classes,
edge_data.is_left_hand_driving);
m_edge_based_node_weights.push_back(m_edge_based_node_weights[eid]); m_edge_based_node_weights.push_back(m_edge_based_node_weights[eid]);
@ -431,20 +414,23 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// Three nested loop look super-linear, but we are dealing with a (kind of) // Three nested loop look super-linear, but we are dealing with a (kind of)
// linear number of turns only. // linear number of turns only.
SuffixTable street_name_suffix_table(scripting_environment); SuffixTable street_name_suffix_table(scripting_environment);
guidance::TurnAnalysis turn_analysis(*m_node_based_graph, guidance::TurnAnalysis turn_analysis(m_node_based_graph,
m_edge_based_node_container,
m_coordinates, m_coordinates,
node_restriction_map, node_restriction_map,
m_barrier_nodes, m_barrier_nodes,
m_compressed_edge_container, m_compressed_edge_container,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table);
profile_properties);
util::guidance::LaneDataIdMap lane_data_map; util::guidance::LaneDataIdMap lane_data_map;
guidance::lanes::TurnLaneHandler turn_lane_handler( guidance::lanes::TurnLaneHandler turn_lane_handler(m_node_based_graph,
*m_node_based_graph, lane_description_map, turn_analysis, lane_data_map); m_edge_based_node_container,
lane_description_map,
turn_analysis,
lane_data_map);
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(), bearing_class_by_node_based_node.resize(m_node_based_graph.GetNumberOfNodes(),
std::numeric_limits<std::uint32_t>::max()); std::numeric_limits<std::uint32_t>::max());
// FIXME these need to be tuned in pre-allocated size // FIXME these need to be tuned in pre-allocated size
@ -467,7 +453,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
{ {
util::UnbufferedLog log; util::UnbufferedLog log;
const NodeID node_count = m_node_based_graph->GetNumberOfNodes(); const NodeID node_count = m_node_based_graph.GetNumberOfNodes();
util::Percent progress(log, node_count); util::Percent progress(log, node_count);
// This counter is used to keep track of how far along we've made it // This counter is used to keep track of how far along we've made it
std::uint64_t nodes_completed = 0; std::uint64_t nodes_completed = 0;
@ -550,7 +536,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const auto node_restricted = isRestricted(node_along_road_entering, const auto node_restricted = isRestricted(node_along_road_entering,
node_at_center_of_intersection, node_at_center_of_intersection,
m_node_based_graph->GetTarget(turn.eid), m_node_based_graph.GetTarget(turn.eid),
conditional_restriction_map); conditional_restriction_map);
boost::optional<Conditional> conditional = boost::none; boost::optional<Conditional> conditional = boost::none;
@ -565,10 +551,11 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
conditions}}}; conditions}}};
} }
const EdgeData &edge_data1 = m_node_based_graph->GetEdgeData(node_based_edge_from); const auto &edge_data1 = m_node_based_graph.GetEdgeData(node_based_edge_from);
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(node_based_edge_to); const auto &edge_data2 = m_node_based_graph.GetEdgeData(node_based_edge_to);
BOOST_ASSERT(edge_data1.edge_id != edge_data2.edge_id); BOOST_ASSERT(nbe_to_ebn_mapping[node_based_edge_from] !=
nbe_to_ebn_mapping[node_based_edge_to]);
BOOST_ASSERT(!edge_data1.reversed); BOOST_ASSERT(!edge_data1.reversed);
BOOST_ASSERT(!edge_data2.reversed); BOOST_ASSERT(!edge_data2.reversed);
@ -581,11 +568,13 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// compute weight and duration penalties // compute weight and duration penalties
auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection); auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection);
ExtractionTurn extracted_turn(turn, ExtractionTurn extracted_turn(
turn,
is_traffic_light, is_traffic_light,
edge_data1.restricted, edge_data1.flags.restricted,
edge_data2.restricted, edge_data2.flags.restricted,
edge_data1.is_left_hand_driving); m_edge_based_node_container.GetAnnotation(edge_data1.annotation_data)
.is_left_hand_driving);
scripting_environment.ProcessTurn(extracted_turn); scripting_environment.ProcessTurn(extracted_turn);
// turn penalties are limited to [-2^15, 2^15) which roughly // turn penalties are limited to [-2^15, 2^15) which roughly
@ -594,8 +583,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
boost::numeric_cast<TurnPenalty>(extracted_turn.weight * weight_multiplier); boost::numeric_cast<TurnPenalty>(extracted_turn.weight * weight_multiplier);
auto duration_penalty = boost::numeric_cast<TurnPenalty>(extracted_turn.duration * 10.); auto duration_penalty = boost::numeric_cast<TurnPenalty>(extracted_turn.duration * 10.);
BOOST_ASSERT(SPECIAL_NODEID != edge_data1.edge_id); BOOST_ASSERT(SPECIAL_NODEID != nbe_to_ebn_mapping[node_based_edge_from]);
BOOST_ASSERT(SPECIAL_NODEID != edge_data2.edge_id); BOOST_ASSERT(SPECIAL_NODEID != nbe_to_ebn_mapping[node_based_edge_to]);
// auto turn_id = m_edge_based_edge_list.size(); // auto turn_id = m_edge_based_edge_list.size();
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty); auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
@ -682,15 +671,15 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// `b` by an outgoing edge. Therefore, we have to search all connected edges for // `b` by an outgoing edge. Therefore, we have to search all connected edges for
// edges entering `b` // edges entering `b`
for (const EdgeID outgoing_edge : for (const EdgeID outgoing_edge :
m_node_based_graph->GetAdjacentEdgeRange(node_at_center_of_intersection)) m_node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection))
{ {
const NodeID node_along_road_entering = const NodeID node_along_road_entering =
m_node_based_graph->GetTarget(outgoing_edge); m_node_based_graph.GetTarget(outgoing_edge);
const auto incoming_edge = m_node_based_graph->FindEdge( const auto incoming_edge = m_node_based_graph.FindEdge(
node_along_road_entering, node_at_center_of_intersection); node_along_road_entering, node_at_center_of_intersection);
if (m_node_based_graph->GetEdgeData(incoming_edge).reversed) if (m_node_based_graph.GetEdgeData(incoming_edge).reversed)
continue; continue;
++node_based_edge_counter; ++node_based_edge_counter;
@ -743,10 +732,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
if (!turn.entry_allowed) if (!turn.entry_allowed)
continue; continue;
const EdgeData &edge_data1 =
m_node_based_graph->GetEdgeData(incoming_edge);
const EdgeData &edge_data2 = m_node_based_graph->GetEdgeData(turn.eid);
// In case a way restriction starts at a given location, add a turn onto // In case a way restriction starts at a given location, add a turn onto
// every artificial node eminating here. // every artificial node eminating here.
// //
@ -764,18 +749,19 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// artificial node, we simply have to find a single representative for // artificial node, we simply have to find a single representative for
// the turn. Here we check whether the turn in question is the start of // the turn. Here we check whether the turn in question is the start of
// a via way restriction. If that should be the case, we switch // a via way restriction. If that should be the case, we switch
// edge_data2.edge_id to the ID of the duplicated node associated with // the id of the edge-based-node for the target to the ID of the
// the turn. (e.g. ab via bc switches bc to bc_dup) // duplicated node associated with the turn. (e.g. ab via bc switches bc
// to bc_dup)
auto const target_id = way_restriction_map.RemapIfRestricted( auto const target_id = way_restriction_map.RemapIfRestricted(
edge_data2.edge_id, nbe_to_ebn_mapping[turn.eid],
node_along_road_entering, node_along_road_entering,
node_at_center_of_intersection, node_at_center_of_intersection,
m_node_based_graph->GetTarget(turn.eid), m_node_based_graph.GetTarget(turn.eid),
m_number_of_edge_based_nodes); m_number_of_edge_based_nodes);
{ // scope to forget edge_with_data after { // scope to forget edge_with_data after
const auto edge_with_data_and_condition = const auto edge_with_data_and_condition =
generate_edge(edge_data1.edge_id, generate_edge(nbe_to_ebn_mapping[incoming_edge],
target_id, target_id,
node_along_road_entering, node_along_road_entering,
incoming_edge, incoming_edge,
@ -822,14 +808,13 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
duplicated_node_id; duplicated_node_id;
auto const node_at_end_of_turn = auto const node_at_end_of_turn =
m_node_based_graph->GetTarget(turn.eid); m_node_based_graph.GetTarget(turn.eid);
const auto is_way_restricted = way_restriction_map.IsRestricted( const auto is_way_restricted = way_restriction_map.IsRestricted(
duplicated_node_id, node_at_end_of_turn); duplicated_node_id, node_at_end_of_turn);
if (is_way_restricted) if (is_way_restricted)
{ {
auto const restriction = way_restriction_map.GetRestriction( auto const restriction = way_restriction_map.GetRestriction(
duplicated_node_id, node_at_end_of_turn); duplicated_node_id, node_at_end_of_turn);
@ -837,9 +822,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
continue; continue;
// add into delayed data // add into delayed data
auto edge_with_data_and_condition = generate_edge( auto edge_with_data_and_condition =
NodeID(from_id), generate_edge(NodeID(from_id),
m_node_based_graph->GetEdgeData(turn.eid).edge_id, nbe_to_ebn_mapping[turn.eid],
node_along_road_entering, node_along_road_entering,
incoming_edge, incoming_edge,
node_at_center_of_intersection, node_at_center_of_intersection,
@ -863,7 +848,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
// add a new conditional for the edge we just created // add a new conditional for the edge we just created
buffer->conditionals.push_back( buffer->conditionals.push_back(
{NodeID(from_id), {NodeID(from_id),
m_node_based_graph->GetEdgeData(turn.eid).edge_id, nbe_to_ebn_mapping[turn.eid],
{static_cast<std::uint64_t>(-1), {static_cast<std::uint64_t>(-1),
m_coordinates[node_at_center_of_intersection], m_coordinates[node_at_center_of_intersection],
restriction.condition}}); restriction.condition}});
@ -871,9 +856,9 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
} }
else else
{ {
auto edge_with_data_and_condition = generate_edge( auto edge_with_data_and_condition =
NodeID(from_id), generate_edge(NodeID(from_id),
m_node_based_graph->GetEdgeData(turn.eid).edge_id, nbe_to_ebn_mapping[turn.eid],
node_along_road_entering, node_along_road_entering,
incoming_edge, incoming_edge,
node_at_center_of_intersection, node_at_center_of_intersection,

View File

@ -67,23 +67,26 @@ struct CmpEdgeByInternalSourceTargetAndName
if (lhs.result.target == SPECIAL_NODEID) if (lhs.result.target == SPECIAL_NODEID)
return false; return false;
if (lhs.result.name_id == rhs.result.name_id) auto const lhs_name_id = edge_annotation_data[lhs.result.annotation_data].name_id;
auto const rhs_name_id = edge_annotation_data[rhs.result.annotation_data].name_id;
if (lhs_name_id == rhs_name_id)
return false; return false;
if (lhs.result.name_id == EMPTY_NAMEID) if (lhs_name_id == EMPTY_NAMEID)
return false; return false;
if (rhs.result.name_id == EMPTY_NAMEID) if (rhs_name_id == EMPTY_NAMEID)
return true; return true;
BOOST_ASSERT(!name_offsets.empty() && name_offsets.back() == name_data.size()); BOOST_ASSERT(!name_offsets.empty() && name_offsets.back() == name_data.size());
const oe::ExtractionContainers::NameCharData::const_iterator data = name_data.begin(); const oe::ExtractionContainers::NameCharData::const_iterator data = name_data.begin();
return std::lexicographical_compare(data + name_offsets[lhs.result.name_id], return std::lexicographical_compare(data + name_offsets[lhs_name_id],
data + name_offsets[lhs.result.name_id + 1], data + name_offsets[lhs_name_id + 1],
data + name_offsets[rhs.result.name_id], data + name_offsets[rhs_name_id],
data + name_offsets[rhs.result.name_id + 1]); data + name_offsets[rhs_name_id + 1]);
} }
const oe::ExtractionContainers::AnnotationDataVector &edge_annotation_data;
const oe::ExtractionContainers::NameCharData &name_data; const oe::ExtractionContainers::NameCharData &name_data;
const oe::ExtractionContainers::NameOffsets &name_offsets; const oe::ExtractionContainers::NameOffsets &name_offsets;
}; };
@ -136,6 +139,7 @@ void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environme
all_nodes_list.clear(); // free all_nodes_list before allocation of normal_edges all_nodes_list.clear(); // free all_nodes_list before allocation of normal_edges
all_nodes_list.shrink_to_fit(); all_nodes_list.shrink_to_fit();
WriteEdges(file_out); WriteEdges(file_out);
WriteMetadata(file_out);
PrepareRestrictions(); PrepareRestrictions();
WriteCharData(name_file_name); WriteCharData(name_file_name);
@ -361,7 +365,7 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
util::Coordinate target_coord{node_iterator->lon, node_iterator->lat}; util::Coordinate target_coord{node_iterator->lon, node_iterator->lat};
// flip source and target coordinates if segment is in backward direction only // flip source and target coordinates if segment is in backward direction only
if (!edge_iterator->result.forward && edge_iterator->result.backward) if (!edge_iterator->result.flags.forward && edge_iterator->result.flags.backward)
std::swap(source_coord, target_coord); std::swap(source_coord, target_coord);
const auto distance = const auto distance =
@ -389,9 +393,9 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
std::swap(edge.source, edge.target); std::swap(edge.source, edge.target);
// std::swap does not work with bit-fields // std::swap does not work with bit-fields
bool temp = edge.forward; bool temp = edge.flags.forward;
edge.forward = edge.backward; edge.flags.forward = edge.flags.backward;
edge.backward = temp; edge.flags.backward = temp;
} }
++edge_iterator; ++edge_iterator;
} }
@ -415,7 +419,8 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
std::mutex name_data_mutex; std::mutex name_data_mutex;
tbb::parallel_sort(all_edges_list.begin(), tbb::parallel_sort(all_edges_list.begin(),
all_edges_list.end(), all_edges_list.end(),
CmpEdgeByInternalSourceTargetAndName{name_char_data, name_offsets}); CmpEdgeByInternalSourceTargetAndName{
all_edges_annotation_data_list, name_char_data, name_offsets});
TIMER_STOP(sort_edges_by_renumbered_start); TIMER_STOP(sort_edges_by_renumbered_start);
log << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s"; log << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s";
} }
@ -452,12 +457,12 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
{ {
const auto &result = all_edges_list[i].result; const auto &result = all_edges_list[i].result;
const auto value = std::make_pair(result.weight, result.duration); const auto value = std::make_pair(result.weight, result.duration);
if (result.forward && value < min_forward) if (result.flags.forward && value < min_forward)
{ {
min_forward_idx = i; min_forward_idx = i;
min_forward = value; min_forward = value;
} }
if (result.backward && value < min_backward) if (result.flags.backward && value < min_backward)
{ {
min_backward_idx = i; min_backward_idx = i;
min_backward = value; min_backward = value;
@ -476,9 +481,9 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
if (min_backward_idx == min_forward_idx) if (min_backward_idx == min_forward_idx)
{ {
all_edges_list[min_forward_idx].result.is_split = false; all_edges_list[min_forward_idx].result.flags.is_split = false;
all_edges_list[min_forward_idx].result.forward = true; all_edges_list[min_forward_idx].result.flags.forward = true;
all_edges_list[min_forward_idx].result.backward = true; all_edges_list[min_forward_idx].result.flags.backward = true;
} }
else else
{ {
@ -486,17 +491,17 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
bool has_backward = min_backward_idx != std::numeric_limits<std::size_t>::max(); bool has_backward = min_backward_idx != std::numeric_limits<std::size_t>::max();
if (has_forward) if (has_forward)
{ {
all_edges_list[min_forward_idx].result.forward = true; all_edges_list[min_forward_idx].result.flags.forward = true;
all_edges_list[min_forward_idx].result.backward = false; all_edges_list[min_forward_idx].result.flags.backward = false;
all_edges_list[min_forward_idx].result.is_split = has_backward; all_edges_list[min_forward_idx].result.flags.is_split = has_backward;
} }
if (has_backward) if (has_backward)
{ {
std::swap(all_edges_list[min_backward_idx].result.source, std::swap(all_edges_list[min_backward_idx].result.source,
all_edges_list[min_backward_idx].result.target); all_edges_list[min_backward_idx].result.target);
all_edges_list[min_backward_idx].result.forward = true; all_edges_list[min_backward_idx].result.flags.forward = true;
all_edges_list[min_backward_idx].result.backward = false; all_edges_list[min_backward_idx].result.flags.backward = false;
all_edges_list[min_backward_idx].result.is_split = has_forward; all_edges_list[min_backward_idx].result.flags.is_split = has_forward;
} }
} }
@ -545,10 +550,25 @@ void ExtractionContainers::WriteEdges(storage::io::FileWriter &file_out) const
TIMER_STOP(write_edges); TIMER_STOP(write_edges);
log << "ok, after " << TIMER_SEC(write_edges) << "s"; log << "ok, after " << TIMER_SEC(write_edges) << "s";
log << "Processed " << normal_edges.size() << " edges"; log << " -- Processed " << normal_edges.size() << " edges";
} }
} }
void ExtractionContainers::WriteMetadata(storage::io::FileWriter &file_out) const
{
util::UnbufferedLog log;
log << "Writing way meta-data ... " << std::flush;
TIMER_START(write_meta_data);
file_out.WriteElementCount64(all_edges_annotation_data_list.size());
file_out.WriteFrom(all_edges_annotation_data_list.data(),
all_edges_annotation_data_list.size());
TIMER_STOP(write_meta_data);
log << "ok, after " << TIMER_SEC(write_meta_data) << "s";
log << " -- Metadata contains << " << all_edges_annotation_data_list.size() << " entries.";
}
void ExtractionContainers::WriteNodes(storage::io::FileWriter &file_out) const void ExtractionContainers::WriteNodes(storage::io::FileWriter &file_out) const
{ {
{ {

View File

@ -7,6 +7,7 @@
#include "extractor/extraction_way.hpp" #include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp" #include "extractor/extractor_callbacks.hpp"
#include "extractor/files.hpp" #include "extractor/files.hpp"
#include "extractor/node_based_graph_factory.hpp"
#include "extractor/raster_source.hpp" #include "extractor/raster_source.hpp"
#include "extractor/restriction_filter.hpp" #include "extractor/restriction_filter.hpp"
#include "extractor/restriction_parser.hpp" #include "extractor/restriction_parser.hpp"
@ -209,27 +210,80 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
util::DeallocatingVector<EdgeBasedEdge> edge_based_edge_list; util::DeallocatingVector<EdgeBasedEdge> edge_based_edge_list;
std::vector<bool> node_is_startpoint; std::vector<bool> node_is_startpoint;
std::vector<EdgeWeight> edge_based_node_weights; std::vector<EdgeWeight> edge_based_node_weights;
std::vector<util::Coordinate> coordinates;
extractor::PackedOSMIDs osm_node_ids;
auto graph_size = BuildEdgeExpandedGraph(scripting_environment, // Create a node-based graph from the OSRM file
NodeBasedGraphFactory node_based_graph_factory(config.GetPath(".osrm"),
scripting_environment,
turn_restrictions,
conditional_turn_restrictions);
util::Log() << "Writing nodes for nodes-based and edges-based graphs ...";
auto const &coordinates = node_based_graph_factory.GetCoordinates();
files::writeNodes(
config.GetPath(".osrm.nbg_nodes"), coordinates, node_based_graph_factory.GetOsmNodes());
node_based_graph_factory.ReleaseOsmNodes();
auto const &node_based_graph = node_based_graph_factory.GetGraph();
// The osrm-partition tool requires the compressed node based graph with an embedding.
//
// The `Run` function above re-numbers non-reverse compressed node based graph edges
// to a continuous range so that the nodes in the edge based graph are continuous.
//
// Luckily node based node ids still coincide with the coordinate array.
// That's the reason we can only here write out the final compressed node based graph.
// Dumps to file asynchronously and makes sure we wait for its completion.
std::future<void> compressed_node_based_graph_writing;
BOOST_SCOPE_EXIT_ALL(&)
{
if (compressed_node_based_graph_writing.valid())
compressed_node_based_graph_writing.wait();
};
compressed_node_based_graph_writing = std::async(std::launch::async, [&] {
WriteCompressedNodeBasedGraph(
config.GetPath(".osrm.cnbg").string(), node_based_graph, coordinates);
});
node_based_graph_factory.GetCompressedEdges().PrintStatistics();
const auto &barrier_nodes = node_based_graph_factory.GetBarriers();
const auto &traffic_signals = node_based_graph_factory.GetTrafficSignals();
// stealing the annotation data from the node-based graph
edge_based_nodes_container =
EdgeBasedNodeDataContainer({}, std::move(node_based_graph_factory.GetAnnotationData()));
conditional_turn_restrictions =
removeInvalidRestrictions(std::move(conditional_turn_restrictions), node_based_graph);
const auto number_of_node_based_nodes = node_based_graph.GetNumberOfNodes();
const auto number_of_edge_based_nodes =
BuildEdgeExpandedGraph(node_based_graph,
coordinates, coordinates,
osm_node_ids, node_based_graph_factory.GetCompressedEdges(),
barrier_nodes,
traffic_signals,
turn_restrictions,
conditional_turn_restrictions,
turn_lane_map,
scripting_environment,
edge_based_nodes_container, edge_based_nodes_container,
edge_based_node_segments, edge_based_node_segments,
node_is_startpoint, node_is_startpoint,
edge_based_node_weights, edge_based_node_weights,
edge_based_edge_list, edge_based_edge_list,
config.GetPath(".osrm.icd").string(), config.GetPath(".osrm.icd").string());
turn_restrictions,
conditional_turn_restrictions,
turn_lane_map);
auto number_of_node_based_nodes = graph_size.first;
auto max_edge_id = graph_size.second - 1;
TIMER_STOP(expansion); TIMER_STOP(expansion);
// output the geometry of the node-based graph, needs to be done after the last usage, since it
// destroys internal containers
files::writeSegmentData(config.GetPath(".osrm.geometry"),
*node_based_graph_factory.GetCompressedEdges().ToSegmentData());
util::Log() << "Saving edge-based node weights to file."; util::Log() << "Saving edge-based node weights to file.";
TIMER_START(timer_write_node_weights); TIMER_START(timer_write_node_weights);
{ {
@ -241,8 +295,10 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
util::Log() << "Done writing. (" << TIMER_SEC(timer_write_node_weights) << ")"; util::Log() << "Done writing. (" << TIMER_SEC(timer_write_node_weights) << ")";
util::Log() << "Computing strictly connected components ..."; util::Log() << "Computing strictly connected components ...";
FindComponents( FindComponents(number_of_edge_based_nodes,
max_edge_id, edge_based_edge_list, edge_based_node_segments, edge_based_nodes_container); edge_based_edge_list,
edge_based_node_segments,
edge_based_nodes_container);
util::Log() << "Building r-tree ..."; util::Log() << "Building r-tree ...";
TIMER_START(rtree); TIMER_START(rtree);
@ -250,13 +306,12 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
TIMER_STOP(rtree); TIMER_STOP(rtree);
util::Log() << "Writing nodes for nodes-based and edges-based graphs ...";
files::writeNodes(config.GetPath(".osrm.nbg_nodes"), coordinates, osm_node_ids);
files::writeNodeData(config.GetPath(".osrm.ebg_nodes"), edge_based_nodes_container); files::writeNodeData(config.GetPath(".osrm.ebg_nodes"), edge_based_nodes_container);
util::Log() << "Writing edge-based-graph edges ... " << std::flush; util::Log() << "Writing edge-based-graph edges ... " << std::flush;
TIMER_START(write_edges); TIMER_START(write_edges);
files::writeEdgeBasedGraph(config.GetPath(".osrm.ebg"), max_edge_id, edge_based_edge_list); files::writeEdgeBasedGraph(
config.GetPath(".osrm.ebg"), number_of_edge_based_nodes, edge_based_edge_list);
TIMER_STOP(write_edges); TIMER_STOP(write_edges);
util::Log() << "ok, after " << TIMER_SEC(write_edges) << "s"; util::Log() << "ok, after " << TIMER_SEC(write_edges) << "s";
@ -265,7 +320,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
const auto nodes_per_second = const auto nodes_per_second =
static_cast<std::uint64_t>(number_of_node_based_nodes / TIMER_SEC(expansion)); static_cast<std::uint64_t>(number_of_node_based_nodes / TIMER_SEC(expansion));
const auto edges_per_second = const auto edges_per_second =
static_cast<std::uint64_t>((max_edge_id + 1) / TIMER_SEC(expansion)); static_cast<std::uint64_t>((number_of_edge_based_nodes) / TIMER_SEC(expansion));
util::Log() << "Expansion: " << nodes_per_second << " nodes/sec and " << edges_per_second util::Log() << "Expansion: " << nodes_per_second << " nodes/sec and " << edges_per_second
<< " edges/sec"; << " edges/sec";
@ -492,7 +547,7 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment,
std::move(extraction_containers.conditional_turn_restrictions)); std::move(extraction_containers.conditional_turn_restrictions));
} }
void Extractor::FindComponents(unsigned max_edge_id, void Extractor::FindComponents(unsigned number_of_edge_based_nodes,
const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list, const util::DeallocatingVector<EdgeBasedEdge> &input_edge_list,
const std::vector<EdgeBasedNodeSegment> &input_node_segments, const std::vector<EdgeBasedNodeSegment> &input_node_segments,
EdgeBasedNodeDataContainer &nodes_container) const EdgeBasedNodeDataContainer &nodes_container) const
@ -506,8 +561,8 @@ void Extractor::FindComponents(unsigned max_edge_id,
{ {
BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(edge.data.weight, 1)) > 0, BOOST_ASSERT_MSG(static_cast<unsigned int>(std::max(edge.data.weight, 1)) > 0,
"edge distance < 1"); "edge distance < 1");
BOOST_ASSERT(edge.source <= max_edge_id); BOOST_ASSERT(edge.source < number_of_edge_based_nodes);
BOOST_ASSERT(edge.target <= max_edge_id); BOOST_ASSERT(edge.target < number_of_edge_based_nodes);
if (edge.data.forward) if (edge.data.forward)
{ {
edges.push_back({edge.source, edge.target}); edges.push_back({edge.source, edge.target});
@ -525,8 +580,8 @@ void Extractor::FindComponents(unsigned max_edge_id,
{ {
if (segment.reverse_segment_id.enabled) if (segment.reverse_segment_id.enabled)
{ {
BOOST_ASSERT(segment.forward_segment_id.id <= max_edge_id); BOOST_ASSERT(segment.forward_segment_id.id < number_of_edge_based_nodes);
BOOST_ASSERT(segment.reverse_segment_id.id <= max_edge_id); BOOST_ASSERT(segment.reverse_segment_id.id < number_of_edge_based_nodes);
edges.push_back({segment.forward_segment_id.id, segment.reverse_segment_id.id}); edges.push_back({segment.forward_segment_id.id, segment.reverse_segment_id.id});
edges.push_back({segment.reverse_segment_id.id, segment.forward_segment_id.id}); edges.push_back({segment.reverse_segment_id.id, segment.forward_segment_id.id});
} }
@ -535,98 +590,54 @@ void Extractor::FindComponents(unsigned max_edge_id,
tbb::parallel_sort(edges.begin(), edges.end()); tbb::parallel_sort(edges.begin(), edges.end());
edges.erase(std::unique(edges.begin(), edges.end()), edges.end()); edges.erase(std::unique(edges.begin(), edges.end()), edges.end());
auto uncontracted_graph = UncontractedGraph(max_edge_id + 1, edges); auto uncontracted_graph = UncontractedGraph(number_of_edge_based_nodes, edges);
TarjanSCC<UncontractedGraph> component_search(uncontracted_graph); TarjanSCC<UncontractedGraph> component_search(uncontracted_graph);
component_search.Run(); component_search.Run();
for (NodeID node_id = 0; node_id <= max_edge_id; ++node_id) for (NodeID node_id = 0; node_id < number_of_edge_based_nodes; ++node_id)
{ {
const auto forward_component = component_search.GetComponentID(node_id); const auto forward_component = component_search.GetComponentID(node_id);
const auto component_size = component_search.GetComponentSize(forward_component); const auto component_size = component_search.GetComponentSize(forward_component);
const auto is_tiny = component_size < config.small_component_size; const auto is_tiny = component_size < config.small_component_size;
nodes_container.SetComponentID(node_id, {1 + forward_component, is_tiny}); BOOST_ASSERT(node_id < nodes_container.NumberOfNodes());
nodes_container.nodes[node_id].component_id = {1 + forward_component, is_tiny};
} }
} }
/**
\brief Load node based graph from .osrm file
*/
std::shared_ptr<util::NodeBasedDynamicGraph>
Extractor::LoadNodeBasedGraph(std::unordered_set<NodeID> &barriers,
std::unordered_set<NodeID> &traffic_signals,
std::vector<util::Coordinate> &coordiantes,
extractor::PackedOSMIDs &osm_node_ids)
{
storage::io::FileReader file_reader(config.GetPath(".osrm"),
storage::io::FileReader::VerifyFingerprint);
auto barriers_iter = inserter(barriers, end(barriers));
auto traffic_signals_iter = inserter(traffic_signals, end(traffic_signals));
NodeID number_of_node_based_nodes = util::loadNodesFromFile(
file_reader, barriers_iter, traffic_signals_iter, coordiantes, osm_node_ids);
util::Log() << " - " << barriers.size() << " bollard nodes, " << traffic_signals.size()
<< " traffic lights";
std::vector<NodeBasedEdge> edge_list;
util::loadEdgesFromFile(file_reader, edge_list);
if (edge_list.empty())
{
throw util::exception("Node-based-graph (" + config.GetPath(".osrm").string() +
") contains no edges." + SOURCE_REF);
}
return util::NodeBasedDynamicGraphFromEdges(number_of_node_based_nodes, edge_list);
}
/** /**
\brief Building an edge-expanded graph from node-based input and turn restrictions \brief Building an edge-expanded graph from node-based input and turn restrictions
*/ */
std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
EdgeID Extractor::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_signals,
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, ScriptingEnvironment &scripting_environment,
std::vector<util::Coordinate> &coordinates, // output data
extractor::PackedOSMIDs &osm_node_ids,
EdgeBasedNodeDataContainer &edge_based_nodes_container, EdgeBasedNodeDataContainer &edge_based_nodes_container,
std::vector<EdgeBasedNodeSegment> &edge_based_node_segments, std::vector<EdgeBasedNodeSegment> &edge_based_node_segments,
std::vector<bool> &node_is_startpoint, std::vector<bool> &node_is_startpoint,
std::vector<EdgeWeight> &edge_based_node_weights, std::vector<EdgeWeight> &edge_based_node_weights,
util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list, util::DeallocatingVector<EdgeBasedEdge> &edge_based_edge_list,
const std::string &intersection_class_output_file, const std::string &intersection_class_output_file)
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
guidance::LaneDescriptionMap &turn_lane_map)
{ {
std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_signals;
auto node_based_graph =
LoadNodeBasedGraph(barrier_nodes, traffic_signals, coordinates, osm_node_ids);
CompressedEdgeContainer compressed_edge_container;
GraphCompressor graph_compressor;
graph_compressor.Compress(barrier_nodes,
traffic_signals,
scripting_environment,
turn_restrictions,
conditional_turn_restrictions,
*node_based_graph,
compressed_edge_container);
conditional_turn_restrictions =
removeInvalidRestrictions(std::move(conditional_turn_restrictions), *node_based_graph);
util::NameTable name_table(config.GetPath(".osrm.names").string()); util::NameTable name_table(config.GetPath(".osrm.names").string());
EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph, EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph,
edge_based_nodes_container,
compressed_edge_container, compressed_edge_container,
barrier_nodes, barrier_nodes,
traffic_signals, traffic_signals,
coordinates, coordinates,
osm_node_ids,
scripting_environment.GetProfileProperties(),
name_table, name_table,
turn_lane_map); turn_lane_map);
@ -646,8 +657,6 @@ std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
WayRestrictionMap via_way_restriction_map(conditional_turn_restrictions); WayRestrictionMap via_way_restriction_map(conditional_turn_restrictions);
ConditionalRestrictionMap conditional_node_restriction_map(conditional_node_restrictions, ConditionalRestrictionMap conditional_node_restriction_map(conditional_node_restrictions,
IndexNodeByFromAndVia()); IndexNodeByFromAndVia());
turn_restrictions.clear();
turn_restrictions.shrink_to_fit();
edge_based_graph_factory.Run(scripting_environment, edge_based_graph_factory.Run(scripting_environment,
config.GetPath(".osrm.edges").string(), config.GetPath(".osrm.edges").string(),
@ -664,29 +673,6 @@ std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
}; };
const auto number_of_edge_based_nodes = create_edge_based_edges(); const auto number_of_edge_based_nodes = create_edge_based_edges();
compressed_edge_container.PrintStatistics();
// The osrm-partition tool requires the compressed node based graph with an embedding.
//
// The `Run` function above re-numbers non-reverse compressed node based graph edges
// to a continuous range so that the nodes in the edge based graph are continuous.
//
// Luckily node based node ids still coincide with the coordinate array.
// That's the reason we can only here write out the final compressed node based graph.
// Dumps to file asynchronously and makes sure we wait for its completion.
std::future<void> compressed_node_based_graph_writing;
BOOST_SCOPE_EXIT_ALL(&)
{
if (compressed_node_based_graph_writing.valid())
compressed_node_based_graph_writing.wait();
};
compressed_node_based_graph_writing = std::async(std::launch::async, [&] {
WriteCompressedNodeBasedGraph(
config.GetPath(".osrm.cnbg").string(), *node_based_graph, coordinates);
});
{ {
std::vector<std::uint32_t> turn_lane_offsets; std::vector<std::uint32_t> turn_lane_offsets;
@ -696,17 +682,12 @@ std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
files::writeTurnLaneDescriptions( files::writeTurnLaneDescriptions(
config.GetPath(".osrm.tls"), turn_lane_offsets, turn_lane_masks); config.GetPath(".osrm.tls"), turn_lane_offsets, turn_lane_masks);
} }
files::writeSegmentData(config.GetPath(".osrm.geometry"),
*compressed_edge_container.ToSegmentData());
edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list); edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list);
edge_based_graph_factory.GetEdgeBasedNodes(edge_based_nodes_container);
edge_based_graph_factory.GetEdgeBasedNodeSegments(edge_based_node_segments); edge_based_graph_factory.GetEdgeBasedNodeSegments(edge_based_node_segments);
edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint); edge_based_graph_factory.GetStartPointMarkers(node_is_startpoint);
edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights); edge_based_graph_factory.GetEdgeBasedNodeWeights(edge_based_node_weights);
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();
util::Log() << "Writing Intersection Classification Data"; util::Log() << "Writing Intersection Classification Data";
TIMER_START(write_intersections); TIMER_START(write_intersections);
files::writeIntersections( files::writeIntersections(
@ -717,7 +698,7 @@ std::pair<std::size_t, EdgeID> Extractor::BuildEdgeExpandedGraph(
TIMER_STOP(write_intersections); TIMER_STOP(write_intersections);
util::Log() << "ok, after " << TIMER_SEC(write_intersections) << "s"; util::Log() << "ok, after " << TIMER_SEC(write_intersections) << "s";
return std::make_pair(number_of_node_based_nodes, number_of_edge_based_nodes); return number_of_edge_based_nodes;
} }
/** /**

View File

@ -390,57 +390,67 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
if (in_forward_direction) if (in_forward_direction)
{ // add (forward) segments or (forward,backward) for non-split edges in backward direction { // add (forward) segments or (forward,backward) for non-split edges in backward direction
const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size();
external_memory.all_edges_annotation_data_list.push_back({name_id,
turn_lane_id_forward,
forward_classes,
parsed_way.forward_travel_mode,
parsed_way.is_left_hand_driving});
util::for_each_pair( util::for_each_pair(
nodes.cbegin(), nodes.cbegin(),
nodes.cend(), nodes.cend(),
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
external_memory.all_edges_list.push_back( NodeBasedEdgeWithOSM edge = {
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
name_id, 0, // weight
forward_weight_data, 0, // duration
forward_duration_data, {}, // geometry id
true, static_cast<AnnotationID>(annotation_data_id),
{true,
in_backward_direction && !split_edge, in_backward_direction && !split_edge,
split_edge,
parsed_way.roundabout, parsed_way.roundabout,
parsed_way.circular, parsed_way.circular,
parsed_way.is_startpoint, parsed_way.is_startpoint,
parsed_way.forward_restricted, parsed_way.forward_restricted,
parsed_way.is_left_hand_driving, road_classification}};
split_edge,
parsed_way.forward_travel_mode, external_memory.all_edges_list.push_back(InternalExtractorEdge(
forward_classes, std::move(edge), forward_weight_data, forward_duration_data, {}));
turn_lane_id_forward,
road_classification,
{}));
}); });
} }
if (in_backward_direction && (!in_forward_direction || split_edge)) if (in_backward_direction && (!in_forward_direction || split_edge))
{ // add (backward) segments for split edges or not in forward direction { // add (backward) segments for split edges or not in forward direction
const auto annotation_data_id = external_memory.all_edges_annotation_data_list.size();
external_memory.all_edges_annotation_data_list.push_back({name_id,
turn_lane_id_backward,
backward_classes,
parsed_way.backward_travel_mode,
parsed_way.is_left_hand_driving});
util::for_each_pair( util::for_each_pair(
nodes.cbegin(), nodes.cbegin(),
nodes.cend(), nodes.cend(),
[&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) { [&](const osmium::NodeRef &first_node, const osmium::NodeRef &last_node) {
external_memory.all_edges_list.push_back( NodeBasedEdgeWithOSM edge = {
InternalExtractorEdge(OSMNodeID{static_cast<std::uint64_t>(first_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(first_node.ref())},
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())}, OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
name_id, 0, // weight
backward_weight_data, 0, // duration
backward_duration_data, {}, // geometry id
false, static_cast<AnnotationID>(annotation_data_id),
{false,
true, true,
split_edge,
parsed_way.roundabout, parsed_way.roundabout,
parsed_way.circular, parsed_way.circular,
parsed_way.is_startpoint, parsed_way.is_startpoint,
parsed_way.backward_restricted, parsed_way.backward_restricted,
parsed_way.is_left_hand_driving, road_classification}};
split_edge,
parsed_way.backward_travel_mode, external_memory.all_edges_list.push_back(InternalExtractorEdge(
backward_classes, std::move(edge), backward_weight_data, backward_duration_data, {}));
turn_lane_id_backward,
road_classification,
{}));
}); });
} }

View File

@ -27,6 +27,7 @@ void GraphCompressor::Compress(
std::vector<TurnRestriction> &turn_restrictions, std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions, std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions,
util::NodeBasedDynamicGraph &graph, util::NodeBasedDynamicGraph &graph,
const std::vector<NodeBasedEdgeAnnotation> &node_data_container,
CompressedEdgeContainer &geometry_compressor) CompressedEdgeContainer &geometry_compressor)
{ {
const unsigned original_number_of_nodes = graph.GetNumberOfNodes(); const unsigned original_number_of_nodes = graph.GetNumberOfNodes();
@ -104,6 +105,7 @@ void GraphCompressor::Compress(
BOOST_ASSERT(forward_e2 >= graph.BeginEdges(node_v) && BOOST_ASSERT(forward_e2 >= graph.BeginEdges(node_v) &&
forward_e2 < graph.EndEdges(node_v)); forward_e2 < graph.EndEdges(node_v));
const EdgeID reverse_e2 = graph.BeginEdges(node_v) + 1 - reverse_edge_order; const EdgeID reverse_e2 = graph.BeginEdges(node_v) + 1 - reverse_edge_order;
BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2); BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2);
BOOST_ASSERT(reverse_e2 >= graph.BeginEdges(node_v) && BOOST_ASSERT(reverse_e2 >= graph.BeginEdges(node_v) &&
reverse_e2 < graph.EndEdges(node_v)); reverse_e2 < graph.EndEdges(node_v));
@ -127,6 +129,10 @@ void GraphCompressor::Compress(
const EdgeData &fwd_edge_data1 = graph.GetEdgeData(forward_e1); const EdgeData &fwd_edge_data1 = graph.GetEdgeData(forward_e1);
const EdgeData &rev_edge_data1 = graph.GetEdgeData(reverse_e1); const EdgeData &rev_edge_data1 = graph.GetEdgeData(reverse_e1);
const auto fwd_annotation_data1 = node_data_container[fwd_edge_data1.annotation_data];
const auto fwd_annotation_data2 = node_data_container[fwd_edge_data2.annotation_data];
const auto rev_annotation_data1 = node_data_container[rev_edge_data1.annotation_data];
const auto rev_annotation_data2 = node_data_container[rev_edge_data2.annotation_data];
if (graph.FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID) if (graph.FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID)
{ {
@ -134,20 +140,22 @@ void GraphCompressor::Compress(
} }
// this case can happen if two ways with different names overlap // this case can happen if two ways with different names overlap
if (fwd_edge_data1.name_id != rev_edge_data1.name_id || if ((fwd_annotation_data1.name_id != rev_annotation_data1.name_id) ||
fwd_edge_data2.name_id != rev_edge_data2.name_id) (fwd_annotation_data2.name_id != rev_annotation_data2.name_id))
{ {
continue; continue;
} }
if (fwd_edge_data1.CanCombineWith(fwd_edge_data2) && if ((fwd_edge_data1.flags == fwd_edge_data2.flags) &&
rev_edge_data1.CanCombineWith(rev_edge_data2)) (rev_edge_data1.flags == rev_edge_data2.flags) &&
(fwd_edge_data1.reversed == fwd_edge_data2.reversed) &&
(rev_edge_data1.reversed == rev_edge_data2.reversed) &&
// annotations need to match, except for the lane-id which can differ
fwd_annotation_data1.CanCombineWith(fwd_annotation_data2) &&
rev_annotation_data1.CanCombineWith(rev_annotation_data2))
{ {
BOOST_ASSERT(graph.GetEdgeData(forward_e1).name_id == BOOST_ASSERT(!(graph.GetEdgeData(forward_e1).reversed &&
graph.GetEdgeData(reverse_e1).name_id); graph.GetEdgeData(reverse_e1).reversed));
BOOST_ASSERT(graph.GetEdgeData(forward_e2).name_id ==
graph.GetEdgeData(reverse_e2).name_id);
/* /*
* Remember Lane Data for compressed parts. This handles scenarios where lane-data * Remember Lane Data for compressed parts. This handles scenarios where lane-data
* is * is
@ -175,24 +183,26 @@ void GraphCompressor::Compress(
* just * just
* like a barrier. * like a barrier.
*/ */
const auto selectLaneID = [](const LaneDescriptionID front, const auto selectAnnotation = [&node_data_container](
const LaneDescriptionID back) { const AnnotationID front_annotation, const AnnotationID back_annotation) {
// A lane has tags: u - (front) - v - (back) - w // A lane has tags: u - (front) - v - (back) - w
// During contraction, we keep only one of the tags. Usually the one closer to // During contraction, we keep only one of the tags. Usually the one closer to
// the // the intersection is preferred. If its empty, however, we keep the non-empty
// intersection is preferred. If its empty, however, we keep the non-empty one // one
if (back == INVALID_LANE_DESCRIPTIONID) if (node_data_container[back_annotation].lane_description_id ==
return front; INVALID_LANE_DESCRIPTIONID)
return back; return front_annotation;
return back_annotation;
}; };
graph.GetEdgeData(forward_e1).lane_description_id = selectLaneID(
fwd_edge_data1.lane_description_id, fwd_edge_data2.lane_description_id); graph.GetEdgeData(forward_e1).annotation_data = selectAnnotation(
graph.GetEdgeData(reverse_e1).lane_description_id = selectLaneID( fwd_edge_data1.annotation_data, fwd_edge_data2.annotation_data);
rev_edge_data1.lane_description_id, rev_edge_data2.lane_description_id); graph.GetEdgeData(reverse_e1).annotation_data = selectAnnotation(
graph.GetEdgeData(forward_e2).lane_description_id = selectLaneID( rev_edge_data1.annotation_data, rev_edge_data2.annotation_data);
fwd_edge_data2.lane_description_id, fwd_edge_data1.lane_description_id); graph.GetEdgeData(forward_e2).annotation_data = selectAnnotation(
graph.GetEdgeData(reverse_e2).lane_description_id = selectLaneID( fwd_edge_data2.annotation_data, fwd_edge_data1.annotation_data);
rev_edge_data2.lane_description_id, rev_edge_data1.lane_description_id); graph.GetEdgeData(reverse_e2).annotation_data = selectAnnotation(
rev_edge_data2.annotation_data, rev_edge_data1.annotation_data);
/* /*
// Do not compress edge if it crosses a traffic signal. // Do not compress edge if it crosses a traffic signal.
@ -206,14 +216,15 @@ void GraphCompressor::Compress(
if (has_node_penalty) if (has_node_penalty)
{ {
// we cannot handle this as node penalty, if it depends on turn direction // we cannot handle this as node penalty, if it depends on turn direction
if (fwd_edge_data1.restricted != fwd_edge_data2.restricted) if (fwd_edge_data1.flags.restricted != fwd_edge_data2.flags.restricted)
continue; continue;
// generate an artifical turn for the turn penalty generation // generate an artifical turn for the turn penalty generation
ExtractionTurn extraction_turn(true, ExtractionTurn extraction_turn(
fwd_edge_data1.restricted, true,
fwd_edge_data2.restricted, fwd_edge_data1.flags.restricted,
fwd_edge_data1.is_left_hand_driving); fwd_edge_data2.flags.restricted,
node_data_container[fwd_edge_data1.annotation_data].is_left_hand_driving);
scripting_environment.ProcessTurn(extraction_turn); scripting_environment.ProcessTurn(extraction_turn);
node_duration_penalty = extraction_turn.duration * 10; node_duration_penalty = extraction_turn.duration * 10;

View File

@ -122,7 +122,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
// coordinate set to add a small level of fault tolerance // coordinate set to add a small level of fault tolerance
const constexpr double skipping_inaccuracies_distance = 2; const constexpr double skipping_inaccuracies_distance = 2;
const auto &turn_edge_data = node_based_graph.GetEdgeData(turn_edge); const auto &turn_edge_data = node_based_graph.GetEdgeData(turn_edge).flags;
// roundabouts, check early to avoid other costly checks // roundabouts, check early to avoid other costly checks
if (turn_edge_data.roundabout || turn_edge_data.circular) if (turn_edge_data.roundabout || turn_edge_data.circular)
@ -175,7 +175,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
// the lane count might not always be set. We need to assume a positive number, though. Here we // the lane count might not always be set. We need to assume a positive number, though. Here we
// select the number of lanes to operate on // select the number of lanes to operate on
const auto considered_lanes = const auto considered_lanes =
GetOffsetCorrectionFactor(node_based_graph.GetEdgeData(turn_edge).road_classification) * GetOffsetCorrectionFactor(turn_edge_data.road_classification) *
((intersection_lanes == 0) ? ASSUMED_LANE_COUNT : intersection_lanes); ((intersection_lanes == 0) ? ASSUMED_LANE_COUNT : intersection_lanes);
/* if the very first coordinate along the road is reasonably far away from the road, we assume /* if the very first coordinate along the road is reasonably far away from the road, we assume
@ -644,7 +644,7 @@ bool CoordinateExtractor::IsCurve(const std::vector<util::Coordinate> &coordinat
const std::vector<double> &segment_distances, const std::vector<double> &segment_distances,
const double segment_length, const double segment_length,
const double considered_lane_width, const double considered_lane_width,
const util::NodeBasedEdgeData &edge_data) const const extractor::NodeBasedEdgeClassification &edge_data) const
{ {
BOOST_ASSERT(coordinates.size() > 2); BOOST_ASSERT(coordinates.size() > 2);

View File

@ -14,10 +14,12 @@ namespace guidance
DrivewayHandler::DrivewayHandler(const IntersectionGenerator &intersection_generator, DrivewayHandler::DrivewayHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table) const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph, : IntersectionHandler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
@ -38,13 +40,13 @@ bool DrivewayHandler::canProcess(const NodeID /*nid*/,
const auto from_eid = intersection.getUTurnRoad().eid; const auto from_eid = intersection.getUTurnRoad().eid;
if (intersection.size() <= 2 || if (intersection.size() <= 2 ||
node_based_graph.GetEdgeData(from_eid).road_classification.IsLowPriorityRoadClass()) node_based_graph.GetEdgeData(from_eid).flags.road_classification.IsLowPriorityRoadClass())
return false; return false;
auto low_priority_count = auto low_priority_count =
std::count_if(intersection.begin(), intersection.end(), [this](const auto &road) { std::count_if(intersection.begin(), intersection.end(), [this](const auto &road) {
return node_based_graph.GetEdgeData(road.eid) return node_based_graph.GetEdgeData(road.eid)
.road_classification.IsLowPriorityRoadClass(); .flags.road_classification.IsLowPriorityRoadClass();
}); });
// Process intersection if it has two edges with normal priority and one is the entry edge, // Process intersection if it has two edges with normal priority and one is the entry edge,
@ -58,7 +60,7 @@ operator()(const NodeID nid, const EdgeID source_edge_id, Intersection intersect
auto road = auto road =
std::find_if(intersection.begin() + 1, intersection.end(), [this](const auto &road) { std::find_if(intersection.begin() + 1, intersection.end(), [this](const auto &road) {
return !node_based_graph.GetEdgeData(road.eid) return !node_based_graph.GetEdgeData(road.eid)
.road_classification.IsLowPriorityRoadClass(); .flags.road_classification.IsLowPriorityRoadClass();
}); });
(void)nid; (void)nid;

View File

@ -33,12 +33,13 @@ const constexpr bool USE_HIGH_PRECISION_MODE = !USE_LOW_PRECISION_MODE;
IntersectionGenerator::IntersectionGenerator( IntersectionGenerator::IntersectionGenerator(
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const RestrictionMap &restriction_map, const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container) const CompressedEdgeContainer &compressed_edge_container)
: node_based_graph(node_based_graph), restriction_map(restriction_map), : node_based_graph(node_based_graph), node_data_container(node_data_container),
barrier_nodes(barrier_nodes), coordinates(coordinates), restriction_map(restriction_map), barrier_nodes(barrier_nodes), coordinates(coordinates),
coordinate_extractor(node_based_graph, compressed_edge_container, coordinates) coordinate_extractor(node_based_graph, compressed_edge_container, coordinates)
{ {
} }
@ -69,14 +70,14 @@ IntersectionGenerator::ComputeIntersectionShape(const NodeID node_at_center_of_i
// number of lanes at the intersection changes how far we look down the road // number of lanes at the intersection changes how far we look down the road
const auto edge_range = node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection); const auto edge_range = node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection);
const auto max_lanes_intersection = std::accumulate( const auto max_lanes_intersection =
edge_range.begin(), std::accumulate(edge_range.begin(),
edge_range.end(), edge_range.end(),
std::uint8_t{0}, std::uint8_t{0},
[this](const auto current_max, const auto current_eid) { [this](const auto current_max, const auto current_eid) {
return std::max( return std::max(current_max,
current_max, node_based_graph.GetEdgeData(current_eid)
node_based_graph.GetEdgeData(current_eid).road_classification.GetNumberOfLanes()); .flags.road_classification.GetNumberOfLanes());
}); });
for (const EdgeID edge_connected_to_intersection : for (const EdgeID edge_connected_to_intersection :
@ -265,9 +266,11 @@ IntersectionGenerator::SkipDegreeTwoNodes(const NodeID starting_node, const Edge
query_node = next_node; query_node = next_node;
query_edge = next_edge; query_edge = next_edge;
if (!node_based_graph.GetEdgeData(query_edge) // check if there is a relevant change in the graph
.IsCompatibleTo(node_based_graph.GetEdgeData(next_edge)) || if (!CanBeCompressed(node_based_graph.GetEdgeData(query_edge),
node_based_graph.GetTarget(next_edge) == starting_node) node_based_graph.GetEdgeData(next_edge),
node_data_container) ||
(node_based_graph.GetTarget(next_edge) == starting_node))
break; break;
} }

View File

@ -24,21 +24,38 @@ namespace guidance
namespace detail namespace detail
{ {
inline bool requiresAnnouncement(const EdgeData &from, const EdgeData &to) // TODO check flags!
inline bool requiresAnnouncement(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const EdgeID from,
const EdgeID to)
{ {
return !from.CanCombineWith(to); const auto &from_edge = node_based_graph.GetEdgeData(from);
} const auto &to_edge = node_based_graph.GetEdgeData(to);
if (from_edge.reversed != to_edge.reversed)
return true;
if (!(from_edge.flags == to_edge.flags))
return true;
const auto &annotation_from = node_data_container.GetAnnotation(from_edge.annotation_data);
const auto &annotation_to = node_data_container.GetAnnotation(to_edge.annotation_data);
return !annotation_from.CanCombineWith(annotation_to);
} }
} // namespace detail
IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph, IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator) const IntersectionGenerator &intersection_generator)
: node_based_graph(node_based_graph), coordinates(coordinates), name_table(name_table), : node_based_graph(node_based_graph), node_data_container(node_data_container),
coordinates(coordinates), name_table(name_table),
street_name_suffix_table(street_name_suffix_table), street_name_suffix_table(street_name_suffix_table),
intersection_generator(intersection_generator), intersection_generator(intersection_generator),
graph_walker(node_based_graph, intersection_generator) graph_walker(node_based_graph, node_data_container, intersection_generator)
{ {
} }
@ -48,20 +65,23 @@ TurnType::Enum IntersectionHandler::findBasicTurnType(const EdgeID via_edge,
const ConnectedRoad &road) const const ConnectedRoad &road) const
{ {
const auto &in_data = node_based_graph.GetEdgeData(via_edge); bool on_ramp = node_based_graph.GetEdgeData(via_edge).flags.road_classification.IsRampClass();
const auto &out_data = node_based_graph.GetEdgeData(road.eid); bool onto_ramp = node_based_graph.GetEdgeData(road.eid).flags.road_classification.IsRampClass();
bool on_ramp = in_data.road_classification.IsRampClass();
bool onto_ramp = out_data.road_classification.IsRampClass();
if (!on_ramp && onto_ramp) if (!on_ramp && onto_ramp)
return TurnType::OnRamp; return TurnType::OnRamp;
const auto same_name = !util::guidance::requiresNameAnnounced( const auto &in_name =
in_data.name_id, out_data.name_id, name_table, street_name_suffix_table); node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
.name_id;
const auto &out_name =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id;
if (in_data.name_id != EMPTY_NAMEID && out_data.name_id != EMPTY_NAMEID && same_name) const auto same_name = !util::guidance::requiresNameAnnounced(
in_name, out_name, name_table, street_name_suffix_table);
if (in_name != EMPTY_NAMEID && out_name != EMPTY_NAMEID && same_name)
{ {
return TurnType::Continue; return TurnType::Continue;
} }
@ -86,14 +106,22 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
} }
// handle travel modes: // handle travel modes:
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode; const auto in_mode =
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode; node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
.travel_mode;
const auto out_mode =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.travel_mode;
const auto needs_notification = in_mode != out_mode; const auto needs_notification = in_mode != out_mode;
if (type == TurnType::Turn) if (type == TurnType::Turn)
{ {
const auto &in_data = node_based_graph.GetEdgeData(via_edge); const auto &in_classification = node_based_graph.GetEdgeData(via_edge).flags;
const auto &out_data = node_based_graph.GetEdgeData(road.eid); const auto &in_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(via_edge).annotation_data);
const auto &out_classification = node_based_graph.GetEdgeData(road.eid).flags;
const auto &out_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(road.eid).annotation_data);
if (util::guidance::requiresNameAnnounced( if (util::guidance::requiresNameAnnounced(
in_data.name_id, out_data.name_id, name_table, street_name_suffix_table)) in_data.name_id, out_data.name_id, name_table, street_name_suffix_table))
@ -104,12 +132,12 @@ TurnInstruction IntersectionHandler::getInstructionForObvious(const std::size_t
// We reserve merges for motorway types. All others are considered for simply going // We reserve merges for motorway types. All others are considered for simply going
// straight onto a road. This avoids confusion about merge directions on streets // straight onto a road. This avoids confusion about merge directions on streets
// that could potentially also offer different choices // that could potentially also offer different choices
if (out_data.road_classification.IsMotorwayClass()) if (out_classification.road_classification.IsMotorwayClass())
return {TurnType::Merge, return {TurnType::Merge,
road.angle > STRAIGHT_ANGLE ? DirectionModifier::SlightRight road.angle > STRAIGHT_ANGLE ? DirectionModifier::SlightRight
: DirectionModifier::SlightLeft}; : DirectionModifier::SlightLeft};
else if (in_data.road_classification.IsRampClass() && else if (in_classification.road_classification.IsRampClass() &&
out_data.road_classification.IsRampClass()) out_classification.road_classification.IsRampClass())
{ {
// This check is more a precaution than anything else. Our current travel modes // This check is more a precaution than anything else. Our current travel modes
// cannot reach this, since all ramps are exposing the same travel type. But we // cannot reach this, since all ramps are exposing the same travel type. But we
@ -177,15 +205,20 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
ConnectedRoad &left, ConnectedRoad &left,
ConnectedRoad &right) const ConnectedRoad &right) const
{ {
const auto &in_data = node_based_graph.GetEdgeData(via_edge); const auto &in_data =
const bool low_priority_left = node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data);
node_based_graph.GetEdgeData(left.eid).road_classification.IsLowPriorityRoadClass(); const auto &lhs_classification =
const bool low_priority_right = node_based_graph.GetEdgeData(left.eid).flags.road_classification;
node_based_graph.GetEdgeData(right.eid).road_classification.IsLowPriorityRoadClass(); const auto &lhs_data =
const auto same_mode_left = node_data_container.GetAnnotation(node_based_graph.GetEdgeData(left.eid).annotation_data);
in_data.travel_mode == node_based_graph.GetEdgeData(left.eid).travel_mode; const auto &rhs_classification =
const auto same_mode_right = node_based_graph.GetEdgeData(right.eid).flags.road_classification;
in_data.travel_mode == node_based_graph.GetEdgeData(right.eid).travel_mode; const auto &rhs_data =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(right.eid).annotation_data);
const bool low_priority_left = lhs_classification.IsLowPriorityRoadClass();
const bool low_priority_right = rhs_classification.IsLowPriorityRoadClass();
const auto same_mode_left = in_data.travel_mode == lhs_data.travel_mode;
const auto same_mode_right = in_data.travel_mode == rhs_data.travel_mode;
const auto suppressed_left_type = const auto suppressed_left_type =
same_mode_left ? TurnType::Suppressed : TurnType::Notification; same_mode_left ? TurnType::Suppressed : TurnType::Notification;
const auto suppressed_right_type = const auto suppressed_right_type =
@ -194,8 +227,7 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
angularDeviation(right.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)) angularDeviation(right.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE))
{ {
// left side is actually straight // left side is actually straight
const auto &out_data = node_based_graph.GetEdgeData(left.eid); if (detail::requiresAnnouncement(node_based_graph, node_data_container, via_edge, left.eid))
if (detail::requiresAnnouncement(in_data, out_data))
{ {
if (low_priority_right && !low_priority_left) if (low_priority_right && !low_priority_left)
{ {
@ -230,11 +262,11 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE) angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
{ {
// right side is actually straight // right side is actually straight
const auto &out_data = node_based_graph.GetEdgeData(right.eid);
if (angularDeviation(right.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION && if (angularDeviation(right.angle, STRAIGHT_ANGLE) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION &&
angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE) angularDeviation(left.angle, STRAIGHT_ANGLE) > FUZZY_ANGLE_DIFFERENCE)
{ {
if (detail::requiresAnnouncement(in_data, out_data)) if (detail::requiresAnnouncement(
node_based_graph, node_data_container, via_edge, right.eid))
{ {
if (low_priority_left && !low_priority_right) if (low_priority_left && !low_priority_right)
{ {
@ -304,8 +336,14 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
{ {
// TODO handle low priority road classes in a reasonable way // TODO handle low priority road classes in a reasonable way
const auto suppressed_type = [&](const ConnectedRoad &road) { const auto suppressed_type = [&](const ConnectedRoad &road) {
const auto in_mode = node_based_graph.GetEdgeData(via_edge).travel_mode; const auto in_mode =
const auto out_mode = node_based_graph.GetEdgeData(road.eid).travel_mode; node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
.travel_mode;
const auto out_mode =
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.travel_mode;
return in_mode == out_mode ? TurnType::Suppressed : TurnType::Notification; return in_mode == out_mode ? TurnType::Suppressed : TurnType::Notification;
}; };
@ -314,9 +352,8 @@ void IntersectionHandler::assignFork(const EdgeID via_edge,
left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft}; left.instruction = {TurnType::Fork, DirectionModifier::SlightLeft};
if (angularDeviation(center.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION) if (angularDeviation(center.angle, 180) < MAXIMAL_ALLOWED_NO_TURN_DEVIATION)
{ {
const auto &in_data = node_based_graph.GetEdgeData(via_edge); if (detail::requiresAnnouncement(
const auto &out_data = node_based_graph.GetEdgeData(center.eid); node_based_graph, node_data_container, via_edge, center.eid))
if (detail::requiresAnnouncement(in_data, out_data))
{ {
center.instruction = {TurnType::Fork, DirectionModifier::Straight}; center.instruction = {TurnType::Fork, DirectionModifier::Straight};
} }
@ -371,7 +408,8 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid,
bool IntersectionHandler::isThroughStreet(const std::size_t index, bool IntersectionHandler::isThroughStreet(const std::size_t index,
const Intersection &intersection) const const Intersection &intersection) const
{ {
const auto &data_at_index = node_based_graph.GetEdgeData(intersection[index].eid); const auto &data_at_index = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(intersection[index].eid).annotation_data);
if (data_at_index.name_id == EMPTY_NAMEID) if (data_at_index.name_id == EMPTY_NAMEID)
return false; return false;
@ -383,7 +421,8 @@ bool IntersectionHandler::isThroughStreet(const std::size_t index,
continue; continue;
const auto &road = intersection[road_index]; const auto &road = intersection[road_index];
const auto &road_data = node_based_graph.GetEdgeData(road.eid); const auto &road_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(road.eid).annotation_data);
// roads have a near straight angle (180 degree) // roads have a near straight angle (180 degree)
const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) > const bool is_nearly_straight = angularDeviation(road.angle, intersection[index].angle) >
@ -395,7 +434,8 @@ bool IntersectionHandler::isThroughStreet(const std::size_t index,
data_at_index.name_id, road_data.name_id, name_table, street_name_suffix_table); data_at_index.name_id, road_data.name_id, name_table, street_name_suffix_table);
const bool have_same_category = const bool have_same_category =
data_at_index.road_classification == road_data.road_classification; node_based_graph.GetEdgeData(intersection[index].eid).flags.road_classification ==
node_based_graph.GetEdgeData(road.eid).flags.road_classification;
if (is_nearly_straight && have_same_name && have_same_category) if (is_nearly_straight && have_same_name && have_same_category)
return true; return true;
@ -443,8 +483,10 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons
bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const
{ {
const auto &source_edge_data = node_based_graph.GetEdgeData(source_edge_id); const auto &source_edge_data = node_data_container.GetAnnotation(
const auto &target_edge_data = node_based_graph.GetEdgeData(target_edge_id); node_based_graph.GetEdgeData(source_edge_id).annotation_data);
const auto &target_edge_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(target_edge_id).annotation_data);
return source_edge_data.name_id != EMPTY_NAMEID && // return source_edge_data.name_id != EMPTY_NAMEID && //
target_edge_data.name_id != EMPTY_NAMEID && // target_edge_data.name_id != EMPTY_NAMEID && //

View File

@ -14,13 +14,16 @@ namespace extractor
namespace guidance namespace guidance
{ {
IntersectionNormalizer::IntersectionNormalizer(const util::NodeBasedDynamicGraph &node_based_graph, IntersectionNormalizer::IntersectionNormalizer(
const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator) const IntersectionGenerator &intersection_generator)
: node_based_graph(node_based_graph), intersection_generator(intersection_generator), : node_based_graph(node_based_graph), intersection_generator(intersection_generator),
mergable_road_detector(node_based_graph, mergable_road_detector(node_based_graph,
node_data_container,
coordinates, coordinates,
intersection_generator, intersection_generator,
intersection_generator.GetCoordinateExtractor(), intersection_generator.GetCoordinateExtractor(),

View File

@ -25,13 +25,17 @@ namespace
// check a connected road for equality of a name // check a connected road for equality of a name
inline auto makeCheckRoadForName(const NameID name_id, inline auto makeCheckRoadForName(const NameID name_id,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &suffix_table) const SuffixTable &suffix_table)
{ {
return [name_id, &node_based_graph, &name_table, &suffix_table]( return [name_id, &node_based_graph, &node_data_container, &name_table, &suffix_table](
const MergableRoadDetector::MergableRoadData &road) { const MergableRoadDetector::MergableRoadData &road) {
// since we filter here, we don't want any other name than the one we are looking for // since we filter here, we don't want any other name than the one we are looking for
const auto road_name = node_based_graph.GetEdgeData(road.eid).name_id; const auto road_name =
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id;
if (name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID) if (name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID)
return true; return true;
const auto requires_announcement = const auto requires_announcement =
@ -44,14 +48,16 @@ inline auto makeCheckRoadForName(const NameID name_id,
} }
MergableRoadDetector::MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph, MergableRoadDetector::MergableRoadDetector(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &node_coordinates, const std::vector<util::Coordinate> &node_coordinates,
const IntersectionGenerator &intersection_generator, const IntersectionGenerator &intersection_generator,
const CoordinateExtractor &coordinate_extractor, const CoordinateExtractor &coordinate_extractor,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table) const SuffixTable &street_name_suffix_table)
: node_based_graph(node_based_graph), node_coordinates(node_coordinates), : node_based_graph(node_based_graph), node_data_container(node_data_container),
intersection_generator(intersection_generator), coordinate_extractor(coordinate_extractor), node_coordinates(node_coordinates), intersection_generator(intersection_generator),
name_table(name_table), street_name_suffix_table(street_name_suffix_table) coordinate_extractor(coordinate_extractor), name_table(name_table),
street_name_suffix_table(street_name_suffix_table)
{ {
} }
@ -63,11 +69,14 @@ bool MergableRoadDetector::CanMergeRoad(const NodeID intersection_node,
if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE) if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE)
return false; return false;
const auto &lhs_edge_data = node_based_graph.GetEdgeData(lhs.eid); const auto &lhs_edge = node_based_graph.GetEdgeData(lhs.eid);
const auto &rhs_edge_data = node_based_graph.GetEdgeData(rhs.eid); const auto &rhs_edge = node_based_graph.GetEdgeData(rhs.eid);
const auto &lhs_edge_data = node_data_container.GetAnnotation(lhs_edge.annotation_data);
const auto &rhs_edge_data = node_data_container.GetAnnotation(rhs_edge.annotation_data);
// and they need to describe the same road // and they need to describe the same road
if (!EdgeDataSupportsMerge(lhs_edge_data, rhs_edge_data)) if ((lhs_edge.reversed == rhs_edge.reversed) ||
!EdgeDataSupportsMerge(lhs_edge.flags, rhs_edge.flags, lhs_edge_data, rhs_edge_data))
return false; return false;
/* don't use any circular links, since they mess up detection we jump out early. /* don't use any circular links, since they mess up detection we jump out early.
@ -120,36 +129,36 @@ bool MergableRoadDetector::IsDistinctFrom(const MergableRoadData &lhs,
if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE) if (angularDeviation(lhs.bearing, rhs.bearing) > MERGABLE_ANGLE_DIFFERENCE)
return true; return true;
else // or it cannot have the same name else // or it cannot have the same name
return !HaveIdenticalNames(node_based_graph.GetEdgeData(lhs.eid).name_id, return !HaveIdenticalNames(
node_based_graph.GetEdgeData(rhs.eid).name_id); node_data_container.GetAnnotation(node_based_graph.GetEdgeData(lhs.eid).annotation_data)
.name_id,
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(rhs.eid).annotation_data)
.name_id);
} }
bool MergableRoadDetector::EdgeDataSupportsMerge(const util::NodeBasedEdgeData &lhs_edge_data, bool MergableRoadDetector::EdgeDataSupportsMerge(
const util::NodeBasedEdgeData &rhs_edge_data) const const NodeBasedEdgeClassification &lhs_flags,
const NodeBasedEdgeClassification &rhs_flags,
const NodeBasedEdgeAnnotation &lhs_annotation,
const NodeBasedEdgeAnnotation &rhs_annotation) const
{ {
// roundabouts are special, simply don't hurt them. We might not want to bear the // roundabouts are special, simply don't hurt them. We might not want to bear the
// consequences // consequences
if (lhs_edge_data.roundabout || rhs_edge_data.roundabout) if (lhs_flags.roundabout || rhs_flags.roundabout)
return false;
/* to describe the same road, but in opposite directions (which is what we require for a
* merge), the roads have to feature one reversed and one non-reversed edge
*/
if (lhs_edge_data.reversed == rhs_edge_data.reversed)
return false; return false;
/* The travel mode should be the same for both roads. If we were to merge different travel /* The travel mode should be the same for both roads. If we were to merge different travel
* modes, we would hide information/run the risk of loosing valid choices (e.g. short period * modes, we would hide information/run the risk of loosing valid choices (e.g. short period
* of pushing) * of pushing)
*/ */
if (lhs_edge_data.travel_mode != rhs_edge_data.travel_mode) if (lhs_annotation.travel_mode != rhs_annotation.travel_mode)
return false; return false;
// we require valid names // we require valid names
if (!HaveIdenticalNames(lhs_edge_data.name_id, rhs_edge_data.name_id)) if (!HaveIdenticalNames(lhs_annotation.name_id, rhs_annotation.name_id))
return false; return false;
return lhs_edge_data.road_classification == rhs_edge_data.road_classification; return lhs_flags.road_classification == rhs_flags.road_classification;
} }
bool MergableRoadDetector::IsTrafficLoop(const NodeID intersection_node, bool MergableRoadDetector::IsTrafficLoop(const NodeID intersection_node,
@ -172,9 +181,13 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
* Since both items have the same id, we can `select` based on any setup * Since both items have the same id, we can `select` based on any setup
*/ */
SelectStraightmostRoadByNameAndOnlyChoice selector( SelectStraightmostRoadByNameAndOnlyChoice selector(
node_based_graph.GetEdgeData(lhs.eid).name_id, lhs.bearing, /*requires entry=*/false); node_data_container.GetAnnotation(node_based_graph.GetEdgeData(lhs.eid).annotation_data)
.name_id,
lhs.bearing,
/*requires entry=*/false);
NodeBasedGraphWalker graph_walker(node_based_graph, intersection_generator); NodeBasedGraphWalker graph_walker(
node_based_graph, node_data_container, intersection_generator);
graph_walker.TraverseRoad(intersection_node, lhs.eid, left_accumulator, selector); graph_walker.TraverseRoad(intersection_node, lhs.eid, left_accumulator, selector);
/* if the intersection does not have a right turn, we continue onto the next one once /* if the intersection does not have a right turn, we continue onto the next one once
* (skipping over a single small side street) * (skipping over a single small side street)
@ -231,7 +244,7 @@ bool MergableRoadDetector::IsNarrowTriangle(const NodeID intersection_node,
const auto num_lanes = [this](const MergableRoadData &road) { const auto num_lanes = [this](const MergableRoadData &road) {
return std::max<std::uint8_t>( return std::max<std::uint8_t>(
node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes(), 1); node_based_graph.GetEdgeData(road.eid).flags.road_classification.GetNumberOfLanes(), 1);
}; };
// the width we can bridge at the intersection // the width we can bridge at the intersection
@ -265,11 +278,15 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
return false; return false;
// Find a coordinate following a road that is far away // Find a coordinate following a road that is far away
NodeBasedGraphWalker graph_walker(node_based_graph, intersection_generator); NodeBasedGraphWalker graph_walker(
node_based_graph, node_data_container, intersection_generator);
const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length) { const auto getCoordinatesAlongWay = [&](const EdgeID edge_id, const double max_length) {
LengthLimitedCoordinateAccumulator accumulator(coordinate_extractor, max_length); LengthLimitedCoordinateAccumulator accumulator(coordinate_extractor, max_length);
SelectStraightmostRoadByNameAndOnlyChoice selector( SelectStraightmostRoadByNameAndOnlyChoice selector(
node_based_graph.GetEdgeData(edge_id).name_id, lhs.bearing, /*requires_entry=*/false); node_data_container.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
.name_id,
lhs.bearing,
/*requires_entry=*/false);
graph_walker.TraverseRoad(intersection_node, edge_id, accumulator, selector); graph_walker.TraverseRoad(intersection_node, edge_id, accumulator, selector);
return std::make_pair(accumulator.accumulated_length, accumulator.coordinates); return std::make_pair(accumulator.accumulated_length, accumulator.coordinates);
@ -342,9 +359,9 @@ bool MergableRoadDetector::HaveSameDirection(const NodeID intersection_node,
coordinates_to_the_right.end()); coordinates_to_the_right.end());
const auto lane_count_lhs = std::max<int>( const auto lane_count_lhs = std::max<int>(
1, node_based_graph.GetEdgeData(lhs.eid).road_classification.GetNumberOfLanes()); 1, node_based_graph.GetEdgeData(lhs.eid).flags.road_classification.GetNumberOfLanes());
const auto lane_count_rhs = std::max<int>( const auto lane_count_rhs = std::max<int>(
1, node_based_graph.GetEdgeData(rhs.eid).road_classification.GetNumberOfLanes()); 1, node_based_graph.GetEdgeData(rhs.eid).flags.road_classification.GetNumberOfLanes());
const auto combined_road_width = 0.5 * (lane_count_lhs + lane_count_rhs) * ASSUMED_LANE_WIDTH; const auto combined_road_width = 0.5 * (lane_count_lhs + lane_count_rhs) * ASSUMED_LANE_WIDTH;
const auto constexpr MAXIMAL_ALLOWED_SEPARATION_WIDTH = 8; const auto constexpr MAXIMAL_ALLOWED_SEPARATION_WIDTH = 8;
@ -380,10 +397,16 @@ bool MergableRoadDetector::IsTrafficIsland(const NodeID intersection_node,
// check if all items share a name // check if all items share a name
const auto range = node_based_graph.GetAdjacentEdgeRange(nid); const auto range = node_based_graph.GetAdjacentEdgeRange(nid);
const auto required_name_id = node_based_graph.GetEdgeData(range.front()).name_id; const auto required_name_id =
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(range.front()).annotation_data)
.name_id;
const auto has_required_name = [this, required_name_id](const auto edge_id) { const auto has_required_name = [this, required_name_id](const auto edge_id) {
const auto road_name = node_based_graph.GetEdgeData(edge_id).name_id; const auto road_name =
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(edge_id).annotation_data)
.name_id;
if (required_name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID) if (required_name_id == EMPTY_NAMEID || road_name == EMPTY_NAMEID)
return false; return false;
return !util::guidance::requiresNameAnnounced( return !util::guidance::requiresNameAnnounced(
@ -428,14 +451,19 @@ bool MergableRoadDetector::IsLinkRoad(const NodeID intersection_node,
const auto next_intersection_along_road = intersection_generator.GetConnectedRoads( const auto next_intersection_along_road = intersection_generator.GetConnectedRoads(
next_intersection_parameters.nid, next_intersection_parameters.via_eid); next_intersection_parameters.nid, next_intersection_parameters.via_eid);
const auto extract_name_id = [this](const MergableRoadData &road) { const auto extract_name_id = [this](const MergableRoadData &road) {
return node_based_graph.GetEdgeData(road.eid).name_id; return node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id;
}; };
const auto requested_name_id = extract_name_id(road); const auto requested_name_id = extract_name_id(road);
const auto next_road_along_path = next_intersection_along_road.findClosestTurn( const auto next_road_along_path = next_intersection_along_road.findClosestTurn(
STRAIGHT_ANGLE, STRAIGHT_ANGLE,
makeCheckRoadForName( makeCheckRoadForName(requested_name_id,
requested_name_id, node_based_graph, name_table, street_name_suffix_table)); node_based_graph,
node_data_container,
name_table,
street_name_suffix_table));
// we need to have a continuing road to successfully detect a link road // we need to have a continuing road to successfully detect a link road
if (next_road_along_path == next_intersection_along_road.end()) if (next_road_along_path == next_intersection_along_road.end())
@ -460,9 +488,16 @@ bool MergableRoadDetector::IsLinkRoad(const NodeID intersection_node,
// near straight road that continues // near straight road that continues
return angularDeviation(opposite_of_next_road_along_path->angle, next_road_along_path->angle) >= return angularDeviation(opposite_of_next_road_along_path->angle, next_road_along_path->angle) >=
(STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE) && (STRAIGHT_ANGLE - FUZZY_ANGLE_DIFFERENCE) &&
(node_based_graph.GetEdgeData(next_road_along_path->eid).reversed ==
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid).reversed) &&
EdgeDataSupportsMerge( EdgeDataSupportsMerge(
node_based_graph.GetEdgeData(next_road_along_path->eid), node_based_graph.GetEdgeData(next_road_along_path->eid).flags,
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid)); node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid).flags,
node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(next_road_along_path->eid).annotation_data),
node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(opposite_of_next_road_along_path->eid)
.annotation_data));
} }
} // namespace guidance } // namespace guidance

View File

@ -24,27 +24,29 @@ namespace
inline bool isMotorwayClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph) inline bool isMotorwayClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph)
{ {
return node_based_graph.GetEdgeData(eid).road_classification.IsMotorwayClass(); return node_based_graph.GetEdgeData(eid).flags.road_classification.IsMotorwayClass();
} }
inline RoadClassification roadClass(const ConnectedRoad &road, inline RoadClassification roadClass(const ConnectedRoad &road,
const util::NodeBasedDynamicGraph &graph) const util::NodeBasedDynamicGraph &graph)
{ {
return graph.GetEdgeData(road.eid).road_classification; return graph.GetEdgeData(road.eid).flags.road_classification;
} }
inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph) inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_based_graph)
{ {
return node_based_graph.GetEdgeData(eid).road_classification.IsRampClass(); return node_based_graph.GetEdgeData(eid).flags.road_classification.IsRampClass();
} }
} // namespace } // namespace
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph, MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator) const IntersectionGenerator &intersection_generator)
: IntersectionHandler(node_based_graph, : IntersectionHandler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
@ -101,7 +103,8 @@ operator()(const NodeID, const EdgeID via_eid, Intersection intersection) const
Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection intersection) const Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection intersection) const
{ {
const auto &in_data = node_based_graph.GetEdgeData(via_eid); const auto &in_data =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_eid).annotation_data);
BOOST_ASSERT(isMotorwayClass(via_eid, node_based_graph)); BOOST_ASSERT(isMotorwayClass(via_eid, node_based_graph));
const auto countExitingMotorways = [this](const Intersection &intersection) { const auto countExitingMotorways = [this](const Intersection &intersection) {
@ -121,7 +124,8 @@ Intersection MotorwayHandler::fromMotorway(const EdgeID via_eid, Intersection in
if (!road.entry_allowed) if (!road.entry_allowed)
continue; continue;
const auto &out_data = node_based_graph.GetEdgeData(road.eid); const auto &out_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(road.eid).annotation_data);
const auto same_name = !util::guidance::requiresNameAnnounced( const auto same_name = !util::guidance::requiresNameAnnounced(
in_data.name_id, out_data.name_id, name_table, street_name_suffix_table); in_data.name_id, out_data.name_id, name_table, street_name_suffix_table);
@ -353,8 +357,10 @@ Intersection MotorwayHandler::fromRamp(const EdgeID via_eid, Intersection inters
} }
else if (intersection.size() == 3) else if (intersection.size() == 3)
{ {
const auto &second_intersection_data = node_based_graph.GetEdgeData(intersection[2].eid); const auto &second_intersection_data = node_data_container.GetAnnotation(
const auto &first_intersection_data = node_based_graph.GetEdgeData(intersection[1].eid); node_based_graph.GetEdgeData(intersection[2].eid).annotation_data);
const auto &first_intersection_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(intersection[1].eid).annotation_data);
const auto first_second_same_name = const auto first_second_same_name =
!util::guidance::requiresNameAnnounced(second_intersection_data.name_id, !util::guidance::requiresNameAnnounced(second_intersection_data.name_id,
first_intersection_data.name_id, first_intersection_data.name_id,

View File

@ -15,8 +15,10 @@ namespace guidance
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
NodeBasedGraphWalker::NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph, NodeBasedGraphWalker::NodeBasedGraphWalker(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const IntersectionGenerator &intersection_generator) const IntersectionGenerator &intersection_generator)
: node_based_graph(node_based_graph), intersection_generator(intersection_generator) : node_based_graph(node_based_graph), node_data_container(node_data_container),
intersection_generator(intersection_generator)
{ {
} }
@ -64,21 +66,24 @@ boost::optional<EdgeID> SelectRoadByNameOnlyChoiceAndStraightness::
operator()(const NodeID /*nid*/, operator()(const NodeID /*nid*/,
const EdgeID /*via_edge_id*/, const EdgeID /*via_edge_id*/,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph) const const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const
{ {
BOOST_ASSERT(!intersection.empty()); BOOST_ASSERT(!intersection.empty());
const auto comparator = [this, &node_based_graph](const IntersectionViewData &lhs, const auto comparator = [&](const IntersectionViewData &lhs, const IntersectionViewData &rhs) {
const IntersectionViewData &rhs) {
// the score of an elemnt results in an ranking preferring valid entries, if required over // the score of an elemnt results in an ranking preferring valid entries, if required over
// invalid requested name_ids over non-requested narrow deviations over non-narrow // invalid requested name_ids over non-requested narrow deviations over non-narrow
const auto score = [this, &node_based_graph](const IntersectionViewData &road) { const auto score = [&](const IntersectionViewData &road) {
double result_score = 0; double result_score = 0;
// since angular deviation is limited by 0-180, we add 360 for invalid // since angular deviation is limited by 0-180, we add 360 for invalid
if (requires_entry && !road.entry_allowed) if (requires_entry && !road.entry_allowed)
result_score += 360.; result_score += 360.;
// 180 for undesired name-ids // 180 for undesired name-ids
if (desired_name_id != node_based_graph.GetEdgeData(road.eid).name_id) if (desired_name_id !=
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id)
result_score += 180; result_score += 180;
return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE); return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE);
@ -108,24 +113,27 @@ boost::optional<EdgeID> SelectStraightmostRoadByNameAndOnlyChoice::
operator()(const NodeID /*nid*/, operator()(const NodeID /*nid*/,
const EdgeID /*via_edge_id*/, const EdgeID /*via_edge_id*/,
const IntersectionView &intersection, const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &node_based_graph) const const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container) const
{ {
BOOST_ASSERT(!intersection.empty()); BOOST_ASSERT(!intersection.empty());
if (intersection.size() == 1) if (intersection.size() == 1)
return {}; return {};
const auto comparator = [this, &node_based_graph](const IntersectionViewData &lhs, const auto comparator = [&](const IntersectionViewData &lhs, const IntersectionViewData &rhs) {
const IntersectionViewData &rhs) {
// the score of an elemnt results in an ranking preferring valid entries, if required over // the score of an elemnt results in an ranking preferring valid entries, if required over
// invalid requested name_ids over non-requested narrow deviations over non-narrow // invalid requested name_ids over non-requested narrow deviations over non-narrow
const auto score = [this, &node_based_graph](const IntersectionViewData &road) { const auto score = [&](const IntersectionViewData &road) {
double result_score = 0; double result_score = 0;
// since angular deviation is limited by 0-180, we add 360 for invalid // since angular deviation is limited by 0-180, we add 360 for invalid
if (requires_entry && !road.entry_allowed) if (requires_entry && !road.entry_allowed)
result_score += 360.; result_score += 360.;
// 180 for undesired name-ids // 180 for undesired name-ids
if (desired_name_id != node_based_graph.GetEdgeData(road.eid).name_id) if (desired_name_id !=
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.name_id)
result_score += 180; result_score += 180;
return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE); return result_score + angularDeviation(road.angle, STRAIGHT_ANGLE);
@ -135,10 +143,10 @@ operator()(const NodeID /*nid*/,
}; };
const auto count_desired_name = const auto count_desired_name =
std::count_if(std::begin(intersection), std::count_if(std::begin(intersection), std::end(intersection), [&](const auto &road) {
std::end(intersection), return node_data_container
[this, &node_based_graph](const auto &road) { .GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
return node_based_graph.GetEdgeData(road.eid).name_id == desired_name_id; .name_id == desired_name_id;
}); });
if (count_desired_name > 2) if (count_desired_name > 2)
return {}; return {};
@ -149,7 +157,9 @@ operator()(const NodeID /*nid*/,
const auto is_valid_choice = !requires_entry || min_element->entry_allowed; const auto is_valid_choice = !requires_entry || min_element->entry_allowed;
const auto is_only_choice_with_same_name = const auto is_only_choice_with_same_name =
count_desired_name <= 2 && // <= in case we come from a bridge count_desired_name <= 2 && // <= in case we come from a bridge
node_based_graph.GetEdgeData(min_element->eid).name_id == desired_name_id && node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(min_element->eid).annotation_data)
.name_id == desired_name_id &&
angularDeviation(min_element->angle, STRAIGHT_ANGLE) < 100; // don't do crazy turns angularDeviation(min_element->angle, STRAIGHT_ANGLE) < 100; // don't do crazy turns
const auto has_valid_angle = const auto has_valid_angle =
((intersection.size() == 2 || ((intersection.size() == 2 ||

View File

@ -24,18 +24,19 @@ namespace guidance
{ {
RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph, RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const CompressedEdgeContainer &compressed_edge_container, const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties,
const IntersectionGenerator &intersection_generator) const IntersectionGenerator &intersection_generator)
: IntersectionHandler(node_based_graph, : IntersectionHandler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
intersection_generator), intersection_generator),
compressed_edge_container(compressed_edge_container), profile_properties(profile_properties), compressed_edge_container(compressed_edge_container),
coordinate_extractor(node_based_graph, compressed_edge_container, coordinates) coordinate_extractor(node_based_graph, compressed_edge_container, coordinates)
{ {
} }
@ -70,22 +71,24 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags(
const NodeID from_nid, const EdgeID via_eid, const Intersection &intersection) const const NodeID from_nid, const EdgeID via_eid, const Intersection &intersection) const
{ {
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid); const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid);
bool on_roundabout = in_edge_data.roundabout || in_edge_data.circular; const auto &in_edge_class = in_edge_data.flags;
bool on_roundabout = in_edge_class.roundabout || in_edge_class.circular;
bool can_enter_roundabout = false; bool can_enter_roundabout = false;
bool can_exit_roundabout_separately = false; bool can_exit_roundabout_separately = false;
const bool lhs = in_edge_data.is_left_hand_driving; const bool lhs =
node_data_container.GetAnnotation(in_edge_data.annotation_data).is_left_hand_driving;
const int step = lhs ? -1 : 1; const int step = lhs ? -1 : 1;
for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size(); for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size();
++cnt, idx += step) ++cnt, idx += step)
{ {
const auto &road = intersection[idx]; const auto &road = intersection[idx];
const auto &edge_data = node_based_graph.GetEdgeData(road.eid); const auto &edge = node_based_graph.GetEdgeData(road.eid);
// only check actual outgoing edges // only check actual outgoing edges
if (edge_data.reversed || !road.entry_allowed) if (edge.reversed || !road.entry_allowed)
continue; continue;
if (edge_data.roundabout || edge_data.circular) if (edge.flags.roundabout || edge.flags.circular)
{ {
can_enter_roundabout = true; can_enter_roundabout = true;
} }
@ -108,8 +111,8 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
const EdgeID via_eid, const EdgeID via_eid,
Intersection &intersection) const Intersection &intersection) const
{ {
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid); const auto &in_edge_class = node_based_graph.GetEdgeData(via_eid).flags;
if (in_edge_data.roundabout || in_edge_data.circular) if (in_edge_class.roundabout || in_edge_class.circular)
return; return;
// Find range in which exits that must be invalidated (shaded areas): // Find range in which exits that must be invalidated (shaded areas):
@ -136,10 +139,10 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
auto invalidate_from = intersection.end(), invalidate_to = intersection.end(); auto invalidate_from = intersection.end(), invalidate_to = intersection.end();
for (auto road = intersection.begin(); road != intersection.end(); ++road) for (auto road = intersection.begin(); road != intersection.end(); ++road)
{ {
const auto &edge_data = node_based_graph.GetEdgeData(road->eid); const auto &edge = node_based_graph.GetEdgeData(road->eid);
if (edge_data.roundabout || edge_data.circular) if (edge.flags.roundabout || edge.flags.circular)
{ {
if (edge_data.reversed) if (edge.reversed)
{ {
if (roundabout_entry_first) if (roundabout_entry_first)
{ // invalidate turns in range exit..end { // invalidate turns in range exit..end
@ -166,8 +169,8 @@ void RoundaboutHandler::invalidateExitAgainstDirection(const NodeID from_nid,
// u-turn against the roundabout direction is invalidated. // u-turn against the roundabout direction is invalidated.
for (; invalidate_from != invalidate_to; ++invalidate_from) for (; invalidate_from != invalidate_to; ++invalidate_from)
{ {
const auto &edge_data = node_based_graph.GetEdgeData(invalidate_from->eid); const auto &edge = node_based_graph.GetEdgeData(invalidate_from->eid);
if (!edge_data.roundabout && !edge_data.circular && if (!edge.flags.roundabout && !edge.flags.circular &&
node_based_graph.GetTarget(invalidate_from->eid) != from_nid) node_based_graph.GetTarget(invalidate_from->eid) != from_nid)
{ {
invalidate_from->entry_allowed = false; invalidate_from->entry_allowed = false;
@ -207,8 +210,8 @@ bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
// can only contain a single further road // can only contain a single further road
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node)) for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node))
{ {
const auto edge_data = node_based_graph.GetEdgeData(edge); const auto &edge_data = node_based_graph.GetEdgeData(edge);
if (edge_data.roundabout || edge_data.circular) if (edge_data.flags.roundabout || edge_data.flags.circular)
continue; continue;
// there is a single non-roundabout edge // there is a single non-roundabout edge
@ -222,7 +225,7 @@ bool RoundaboutHandler::qualifiesAsRoundaboutIntersection(
[this](const auto current_max, const auto current_eid) { [this](const auto current_max, const auto current_eid) {
return std::max(current_max, return std::max(current_max,
node_based_graph.GetEdgeData(current_eid) node_based_graph.GetEdgeData(current_eid)
.road_classification.GetNumberOfLanes()); .flags.road_classification.GetNumberOfLanes());
}); });
const auto next_coordinate = const auto next_coordinate =
@ -279,11 +282,12 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
const NodeID node, const bool roundabout, const bool circular) { const NodeID node, const bool roundabout, const bool circular) {
BOOST_ASSERT(roundabout != circular); BOOST_ASSERT(roundabout != circular);
EdgeID continue_edge = SPECIAL_EDGEID; EdgeID continue_edge = SPECIAL_EDGEID;
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node)) for (const auto edge_id : node_based_graph.GetAdjacentEdgeRange(node))
{ {
const auto &edge_data = node_based_graph.GetEdgeData(edge); const auto &edge = node_based_graph.GetEdgeData(edge_id);
if (!edge_data.reversed && (edge_data.circular == circular) && const auto &edge_data = node_data_container.GetAnnotation(edge.annotation_data);
(edge_data.roundabout == roundabout)) if (!edge.reversed && (edge.flags.circular == circular) &&
(edge.flags.roundabout == roundabout))
{ {
if (SPECIAL_EDGEID != continue_edge) if (SPECIAL_EDGEID != continue_edge)
{ {
@ -303,9 +307,9 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
roundabout_name_ids.insert(edge_data.name_id); roundabout_name_ids.insert(edge_data.name_id);
} }
continue_edge = edge; continue_edge = edge_id;
} }
else if (!edge_data.roundabout && !edge_data.circular) else if (!edge.flags.roundabout && !edge.flags.circular)
{ {
// remember all connected road names // remember all connected road names
connected_names.insert(edge_data.name_id); connected_names.insert(edge_data.name_id);
@ -322,7 +326,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(at_node)) for (const auto edge : node_based_graph.GetAdjacentEdgeRange(at_node))
{ {
const auto &edge_data = node_based_graph.GetEdgeData(edge); const auto &edge_data = node_based_graph.GetEdgeData(edge);
if (edge_data.roundabout || edge_data.circular) if (edge_data.flags.roundabout || edge_data.flags.circular)
count++; count++;
} }
return count; return count;
@ -353,7 +357,7 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
bool roundabout = false, circular = false; bool roundabout = false, circular = false;
for (const auto eid : node_based_graph.GetAdjacentEdgeRange(nid)) for (const auto eid : node_based_graph.GetAdjacentEdgeRange(nid))
{ {
const auto data = node_based_graph.GetEdgeData(eid); const auto data = node_based_graph.GetEdgeData(eid).flags;
roundabout |= data.roundabout; roundabout |= data.roundabout;
circular |= data.circular; circular |= data.circular;
} }
@ -435,7 +439,8 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
NodeID node_at_center_of_intersection = node_based_graph.GetTarget(via_eid); NodeID node_at_center_of_intersection = node_based_graph.GetTarget(via_eid);
const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid); const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid);
const bool lhs = in_edge_data.is_left_hand_driving; const bool lhs =
node_data_container.GetAnnotation(in_edge_data.annotation_data).is_left_hand_driving;
const int step = lhs ? -1 : 1; const int step = lhs ? -1 : 1;
if (on_roundabout) if (on_roundabout)
@ -448,7 +453,8 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
{ {
auto &road = intersection[idx]; auto &road = intersection[idx];
auto &turn = road; auto &turn = road;
const auto &out_data = node_based_graph.GetEdgeData(road.eid); const auto &out_data = node_based_graph.GetEdgeData(road.eid).flags;
;
if (out_data.roundabout || out_data.circular) if (out_data.roundabout || out_data.circular)
{ {
// TODO can forks happen in roundabouts? E.g. required lane changes // TODO can forks happen in roundabouts? E.g. required lane changes
@ -471,11 +477,10 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
for (const auto eid : for (const auto eid :
node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection)) node_based_graph.GetAdjacentEdgeRange(node_at_center_of_intersection))
{ {
const auto &data_of_leaving_edge = node_based_graph.GetEdgeData(eid); const auto &leaving_edge = node_based_graph.GetEdgeData(eid);
if (!data_of_leaving_edge.reversed && if (!leaving_edge.reversed && !leaving_edge.flags.roundabout &&
!data_of_leaving_edge.roundabout && !leaving_edge.flags.circular &&
!data_of_leaving_edge.circular && !leaving_edge.flags.road_classification.IsLowPriorityRoadClass())
!data_of_leaving_edge.road_classification.IsLowPriorityRoadClass())
return true; return true;
} }
return false; return false;
@ -511,7 +516,7 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
++cnt, idx += step) ++cnt, idx += step)
{ {
auto &turn = intersection[idx]; auto &turn = intersection[idx];
const auto &out_data = node_based_graph.GetEdgeData(turn.eid); const auto &out_data = node_based_graph.GetEdgeData(turn.eid).flags;
// A roundabout consists of exactly two roads at an intersection. by toggeling this // A roundabout consists of exactly two roads at an intersection. by toggeling this
// flag, we can switch between roads crossing the roundabout and roads that are on the // flag, we can switch between roads crossing the roundabout and roads that are on the

View File

@ -23,10 +23,12 @@ namespace guidance
SliproadHandler::SliproadHandler(const IntersectionGenerator &intersection_generator, SliproadHandler::SliproadHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table) const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph, : IntersectionHandler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
@ -109,7 +111,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
return false; return false;
} }
const auto &road_data = node_based_graph.GetEdgeData(road.eid); const auto &road_data = node_based_graph.GetEdgeData(road.eid).flags;
auto is_roundabout = road_data.roundabout; auto is_roundabout = road_data.roundabout;
@ -156,7 +158,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
for (const auto &road : main_road_intersection->intersection) for (const auto &road : main_road_intersection->intersection)
{ {
const auto &target_data = node_based_graph.GetEdgeData(road.eid); const auto target_annotation_id = node_based_graph.GetEdgeData(road.eid).annotation_data;
const auto &target_data = node_data_container.GetAnnotation(target_annotation_id);
target_road_name_ids.push_back(target_data.name_id); target_road_name_ids.push_back(target_data.name_id);
} }
@ -173,7 +176,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
continue; continue;
auto &sliproad = intersection[road_index]; // this is what we're checking and assigning to auto &sliproad = intersection[road_index]; // this is what we're checking and assigning to
const auto &sliproad_data = node_based_graph.GetEdgeData(sliproad.eid); const auto &sliproad_edge_data = node_based_graph.GetEdgeData(sliproad.eid);
// Intersection is orderd: 0 is UTurn, then from sharp right to sharp left. // Intersection is orderd: 0 is UTurn, then from sharp right to sharp left.
// We already have an obvious index (bc) for going straight-ish. // We already have an obvious index (bc) for going straight-ish.
@ -199,13 +202,13 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
} }
// Discard service and other low priority roads - never Sliproad candidate // Discard service and other low priority roads - never Sliproad candidate
if (sliproad_data.road_classification.IsLowPriorityRoadClass()) if (sliproad_edge_data.flags.road_classification.IsLowPriorityRoadClass())
{ {
continue; continue;
} }
// Incoming-only can never be a Sliproad // Incoming-only can never be a Sliproad
if (sliproad_data.reversed) if (sliproad_edge_data.reversed)
{ {
continue; continue;
} }
@ -350,7 +353,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
continue; continue;
} }
const auto &onto_data = node_based_graph.GetEdgeData(onto.eid); const auto &onto_data = node_based_graph.GetEdgeData(onto.eid).flags;
if (onto_data.roundabout) if (onto_data.roundabout)
{ {
@ -434,7 +437,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// Check sliproads with skew main intersections // Check sliproads with skew main intersections
if (deviation_from_straight > 180. - minimal_crossroad_angle_of_intersection && if (deviation_from_straight > 180. - minimal_crossroad_angle_of_intersection &&
!node_based_graph.GetEdgeData(sliproad.eid).road_classification.IsLinkClass()) !node_based_graph.GetEdgeData(sliproad.eid)
.flags.road_classification.IsLinkClass())
{ {
continue; continue;
} }
@ -449,8 +453,9 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// ` . // ` .
// d // d
// //
const auto area_threshold = std::pow( const auto area_threshold =
scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD, sliproad_data.road_classification), std::pow(scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD,
sliproad_edge_data.flags.road_classification),
2.); 2.);
if (!isValidSliproadArea(area_threshold, if (!isValidSliproadArea(area_threshold,
@ -464,7 +469,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// Check all roads at `d` if one is connected to `c`, is so `bd` is Sliproad. // Check all roads at `d` if one is connected to `c`, is so `bd` is Sliproad.
for (const auto &candidate_road : target_intersection) for (const auto &candidate_road : target_intersection)
{ {
const auto &candidate_data = node_based_graph.GetEdgeData(candidate_road.eid); const auto &candidate_data = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(candidate_road.eid).annotation_data);
// Name mismatch: check roads at `c` and `d` for same name // Name mismatch: check roads at `c` and `d` for same name
const auto name_mismatch = [&](const NameID road_name_id) { const auto name_mismatch = [&](const NameID road_name_id) {
@ -489,15 +495,20 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// Check if main road -> sliproad (non-link) -> candidate road requires two name // Check if main road -> sliproad (non-link) -> candidate road requires two name
// announcements then don't suppress one announcement via sliproad handler // announcements then don't suppress one announcement via sliproad handler
const auto main_road_name_id = node_based_graph.GetEdgeData(main_road.eid).name_id; const auto main_road_name_id =
if (!sliproad_data.road_classification.IsLinkClass() && node_data_container
sliproad_data.name_id != EMPTY_NAMEID && main_road_name_id != EMPTY_NAMEID && .GetAnnotation(node_based_graph.GetEdgeData(main_road.eid).annotation_data)
.name_id;
const auto &sliproad_annotation =
node_data_container.GetAnnotation(sliproad_edge_data.annotation_data);
if (!sliproad_edge_data.flags.road_classification.IsLinkClass() &&
sliproad_annotation.name_id != EMPTY_NAMEID && main_road_name_id != EMPTY_NAMEID &&
candidate_data.name_id != EMPTY_NAMEID && candidate_data.name_id != EMPTY_NAMEID &&
util::guidance::requiresNameAnnounced(main_road_name_id, util::guidance::requiresNameAnnounced(main_road_name_id,
sliproad_data.name_id, sliproad_annotation.name_id,
name_table, name_table,
street_name_suffix_table) && street_name_suffix_table) &&
util::guidance::requiresNameAnnounced(sliproad_data.name_id, util::guidance::requiresNameAnnounced(sliproad_annotation.name_id,
candidate_data.name_id, candidate_data.name_id,
name_table, name_table,
street_name_suffix_table)) street_name_suffix_table))
@ -553,6 +564,8 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
// In those cases the obvious non-Sliproad is now obvious and we discard the Fork turn type. // In those cases the obvious non-Sliproad is now obvious and we discard the Fork turn type.
if (sliproad_found && main_road.instruction.type == TurnType::Fork) if (sliproad_found && main_road.instruction.type == TurnType::Fork)
{ {
const auto &main_data = node_based_graph.GetEdgeData(main_road.eid);
const auto &main_annotation = node_data_container.GetAnnotation(main_data.annotation_data);
if (isSameName(source_edge_id, main_road.eid)) if (isSameName(source_edge_id, main_road.eid))
{ {
if (angularDeviation(main_road.angle, STRAIGHT_ANGLE) < 5) if (angularDeviation(main_road.angle, STRAIGHT_ANGLE) < 5)
@ -562,7 +575,7 @@ operator()(const NodeID /*nid*/, const EdgeID source_edge_id, Intersection inter
intersection[*obvious].instruction.direction_modifier = intersection[*obvious].instruction.direction_modifier =
getTurnDirection(intersection[*obvious].angle); getTurnDirection(intersection[*obvious].angle);
} }
else if (node_based_graph.GetEdgeData(main_road.eid).name_id != EMPTY_NAMEID) else if (main_annotation.name_id != EMPTY_NAMEID)
{ {
intersection[*obvious].instruction.type = TurnType::NewName; intersection[*obvious].instruction.type = TurnType::NewName;
intersection[*obvious].instruction.direction_modifier = intersection[*obvious].instruction.direction_modifier =
@ -644,7 +657,7 @@ bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const Edg
const auto &coordinate_extractor = intersection_generator.GetCoordinateExtractor(); const auto &coordinate_extractor = intersection_generator.GetCoordinateExtractor();
// Base max distance threshold on the current road class we're on // Base max distance threshold on the current road class we're on
const auto &data = node_based_graph.GetEdgeData(onto); const auto &data = node_based_graph.GetEdgeData(onto).flags;
const auto threshold = scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD, // <- scales down const auto threshold = scaledThresholdByRoadClass(MAX_SLIPROAD_THRESHOLD, // <- scales down
data.road_classification); data.road_classification);
@ -662,13 +675,15 @@ bool SliproadHandler::isThroughStreet(const EdgeID from, const IntersectionView
BOOST_ASSERT(from != SPECIAL_EDGEID); BOOST_ASSERT(from != SPECIAL_EDGEID);
BOOST_ASSERT(!intersection.empty()); BOOST_ASSERT(!intersection.empty());
const auto &edge_name_id = node_based_graph.GetEdgeData(from).name_id; const auto from_annotation_id = node_based_graph.GetEdgeData(from).annotation_data;
const auto &edge_name_id = node_data_container.GetAnnotation(from_annotation_id).name_id;
auto first = begin(intersection) + 1; // Skip UTurn road auto first = begin(intersection) + 1; // Skip UTurn road
auto last = end(intersection); auto last = end(intersection);
auto same_name = [&](const auto &road) { auto same_name = [&](const auto &road) {
const auto &road_name_id = node_based_graph.GetEdgeData(road.eid).name_id; const auto annotation_id = node_based_graph.GetEdgeData(road.eid).annotation_data;
const auto &road_name_id = node_data_container.GetAnnotation(annotation_id).name_id;
return edge_name_id != EMPTY_NAMEID && // return edge_name_id != EMPTY_NAMEID && //
road_name_id != EMPTY_NAMEID && // road_name_id != EMPTY_NAMEID && //
@ -683,10 +698,13 @@ bool SliproadHandler::isThroughStreet(const EdgeID from, const IntersectionView
bool SliproadHandler::roadContinues(const EdgeID current, const EdgeID next) const bool SliproadHandler::roadContinues(const EdgeID current, const EdgeID next) const
{ {
const auto &current_data = node_based_graph.GetEdgeData(current); const auto &current_data =
const auto &next_data = node_based_graph.GetEdgeData(next); node_data_container.GetAnnotation(node_based_graph.GetEdgeData(current).annotation_data);
const auto &next_data =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(next).annotation_data);
auto same_road_category = current_data.road_classification == next_data.road_classification; auto same_road_category = node_based_graph.GetEdgeData(current).flags.road_classification ==
node_based_graph.GetEdgeData(next).flags.road_classification;
auto same_travel_mode = current_data.travel_mode == next_data.travel_mode; auto same_travel_mode = current_data.travel_mode == next_data.travel_mode;
auto same_name = current_data.name_id != EMPTY_NAMEID && // auto same_name = current_data.name_id != EMPTY_NAMEID && //
@ -730,22 +748,18 @@ bool SliproadHandler::isValidSliproadArea(const double max_area,
} }
bool SliproadHandler::isValidSliproadLink(const IntersectionViewData &sliproad, bool SliproadHandler::isValidSliproadLink(const IntersectionViewData &sliproad,
const IntersectionViewData &first, const IntersectionViewData & /*first*/,
const IntersectionViewData &second) const const IntersectionViewData &second) const
{ {
// If the sliproad is not a link we don't care // If the Sliproad is not a link we don't care
const auto &sliproad_data = node_based_graph.GetEdgeData(sliproad.eid); const auto &sliproad_data = node_based_graph.GetEdgeData(sliproad.eid).flags;
if (!sliproad_data.road_classification.IsLinkClass()) if (!sliproad_data.road_classification.IsLinkClass())
{ {
return true; return true;
} }
// otherwise the first road leading to the intersection we shortcut
// can be a link or a usual road (ignore the check at this place)
(void)first;
// and the second road coming from the intersection we shortcut must be a non-link // and the second road coming from the intersection we shortcut must be a non-link
const auto &second_road_data = node_based_graph.GetEdgeData(second.eid); const auto &second_road_data = node_based_graph.GetEdgeData(second.eid).flags;
if (second_road_data.road_classification.IsLinkClass()) if (second_road_data.road_classification.IsLinkClass())
{ {
return false; return false;
@ -758,10 +772,15 @@ bool SliproadHandler::allSameMode(const EdgeID from,
const EdgeID sliproad_candidate, const EdgeID sliproad_candidate,
const EdgeID target_road) const const EdgeID target_road) const
{ {
return node_based_graph.GetEdgeData(from).travel_mode == const auto &from_annotation =
node_based_graph.GetEdgeData(sliproad_candidate).travel_mode && node_data_container.GetAnnotation(node_based_graph.GetEdgeData(from).annotation_data);
node_based_graph.GetEdgeData(sliproad_candidate).travel_mode == const auto &sliproad_annotation = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(target_road).travel_mode; node_based_graph.GetEdgeData(sliproad_candidate).annotation_data);
const auto &target_annotation = node_data_container.GetAnnotation(
node_based_graph.GetEdgeData(target_road).annotation_data);
return (from_annotation.travel_mode == sliproad_annotation.travel_mode) &&
(target_annotation.travel_mode == sliproad_annotation.travel_mode);
} }
bool SliproadHandler::canBeTargetOfSliproad(const IntersectionView &intersection) bool SliproadHandler::canBeTargetOfSliproad(const IntersectionView &intersection)

View File

@ -13,10 +13,12 @@ namespace guidance
SuppressModeHandler::SuppressModeHandler(const IntersectionGenerator &intersection_generator, SuppressModeHandler::SuppressModeHandler(const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph, const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table) const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph, : IntersectionHandler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
@ -36,14 +38,18 @@ bool SuppressModeHandler::canProcess(const NodeID,
// If the approach way is not on the suppression blacklist, and not all the exit ways share that // If the approach way is not on the suppression blacklist, and not all the exit ways share that
// mode, there are no ways to suppress by this criteria. // mode, there are no ways to suppress by this criteria.
const auto in_mode = node_based_graph.GetEdgeData(via_eid).travel_mode; const auto in_mode =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_eid).annotation_data)
.travel_mode;
const auto suppress_in_mode = std::find(begin(suppressed), end(suppressed), in_mode); const auto suppress_in_mode = std::find(begin(suppressed), end(suppressed), in_mode);
const auto first = begin(intersection); const auto first = begin(intersection);
const auto last = end(intersection); const auto last = end(intersection);
const auto all_share_mode = std::all_of(first, last, [this, &in_mode](const auto &road) { const auto all_share_mode = std::all_of(first, last, [this, &in_mode](const auto &road) {
return node_based_graph.GetEdgeData(road.eid).travel_mode == in_mode; return node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.travel_mode == in_mode;
}); });
return (suppress_in_mode != end(suppressed)) && all_share_mode; return (suppress_in_mode != end(suppressed)) && all_share_mode;

View File

@ -21,56 +21,61 @@ namespace guidance
using EdgeData = util::NodeBasedDynamicGraph::EdgeData; using EdgeData = util::NodeBasedDynamicGraph::EdgeData;
bool requiresAnnouncement(const EdgeData &from, const EdgeData &to)
{
return !from.CanCombineWith(to);
}
TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph, TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const RestrictionMap &restriction_map, const RestrictionMap &restriction_map,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const CompressedEdgeContainer &compressed_edge_container, const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table)
const ProfileProperties &profile_properties) : node_based_graph(node_based_graph), intersection_generator(node_based_graph,
: node_based_graph(node_based_graph), node_data_container,
intersection_generator( restriction_map,
node_based_graph, restriction_map, barrier_nodes, coordinates, compressed_edge_container), barrier_nodes,
coordinates,
compressed_edge_container),
intersection_normalizer(node_based_graph, intersection_normalizer(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
intersection_generator), intersection_generator),
roundabout_handler(node_based_graph, roundabout_handler(node_based_graph,
node_data_container,
coordinates, coordinates,
compressed_edge_container, compressed_edge_container,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
profile_properties,
intersection_generator), intersection_generator),
motorway_handler(node_based_graph, motorway_handler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
intersection_generator), intersection_generator),
turn_handler(node_based_graph, turn_handler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
intersection_generator), intersection_generator),
sliproad_handler(intersection_generator, sliproad_handler(intersection_generator,
node_based_graph, node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table), street_name_suffix_table),
suppress_mode_handler(intersection_generator, suppress_mode_handler(intersection_generator,
node_based_graph, node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table), street_name_suffix_table),
driveway_handler(intersection_generator, driveway_handler(intersection_generator,
node_based_graph, node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table) street_name_suffix_table)
@ -163,7 +168,7 @@ Intersection TurnAnalysis::AssignTurnTypes(const NodeID node_prior_to_intersecti
node_prior_to_intersection, entering_via_edge, std::move(intersection)); node_prior_to_intersection, entering_via_edge, std::move(intersection));
// Turn On Ramps Into Off Ramps, if we come from a motorway-like road // Turn On Ramps Into Off Ramps, if we come from a motorway-like road
if (node_based_graph.GetEdgeData(entering_via_edge).road_classification.IsMotorwayClass()) if (node_based_graph.GetEdgeData(entering_via_edge).flags.road_classification.IsMotorwayClass())
{ {
std::for_each(intersection.begin(), intersection.end(), [](ConnectedRoad &road) { std::for_each(intersection.begin(), intersection.end(), [](ConnectedRoad &road) {
if (road.instruction.type == TurnType::OnRamp) if (road.instruction.type == TurnType::OnRamp)

View File

@ -111,11 +111,13 @@ std::size_t TurnHandler::Fork::getLeftIndex() const
} }
TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph, TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
const std::vector<util::Coordinate> &coordinates, const std::vector<util::Coordinate> &coordinates,
const util::NameTable &name_table, const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table, const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator) const IntersectionGenerator &intersection_generator)
: IntersectionHandler(node_based_graph, : IntersectionHandler(node_based_graph,
node_data_container,
coordinates, coordinates,
name_table, name_table,
street_name_suffix_table, street_name_suffix_table,
@ -174,12 +176,16 @@ bool TurnHandler::isObviousOfTwo(const EdgeID via_edge,
const ConnectedRoad &road, const ConnectedRoad &road,
const ConnectedRoad &other) const const ConnectedRoad &other) const
{ {
const auto &via_data = node_based_graph.GetEdgeData(via_edge); const auto &via_data =
const auto &road_data = node_based_graph.GetEdgeData(road.eid); node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data);
const auto &other_data = node_based_graph.GetEdgeData(other.eid); const auto &road_data =
const auto &via_classification = via_data.road_classification; node_data_container.GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data);
const auto &road_classification = road_data.road_classification; const auto &via_classification =
const auto &other_classification = other_data.road_classification; node_based_graph.GetEdgeData(via_edge).flags.road_classification;
const auto &road_classification =
node_based_graph.GetEdgeData(road.eid).flags.road_classification;
const auto &other_classification =
node_based_graph.GetEdgeData(other.eid).flags.road_classification;
// if one of the given roads is obvious by class, obviousness is trivial // if one of the given roads is obvious by class, obviousness is trivial
if (obviousByRoadClass(via_classification, road_classification, other_classification)) if (obviousByRoadClass(via_classification, road_classification, other_classification))
@ -335,9 +341,9 @@ Intersection TurnHandler::handleComplexTurn(const EdgeID via_edge, Intersection
if (fork->size == 2) if (fork->size == 2)
{ {
const auto left_classification = const auto left_classification =
node_based_graph.GetEdgeData(fork->getLeft().eid).road_classification; node_based_graph.GetEdgeData(fork->getLeft().eid).flags.road_classification;
const auto right_classification = const auto right_classification =
node_based_graph.GetEdgeData(fork->getRight().eid).road_classification; node_based_graph.GetEdgeData(fork->getRight().eid).flags.road_classification;
if (canBeSeenAsFork(left_classification, right_classification)) if (canBeSeenAsFork(left_classification, right_classification))
{ {
assignFork(via_edge, fork->getLeft(), fork->getRight()); assignFork(via_edge, fork->getLeft(), fork->getRight());
@ -615,26 +621,27 @@ TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const
// incoming edge are compatible by class // incoming edge are compatible by class
bool TurnHandler::isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const bool TurnHandler::isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const
{ {
const auto via_class = node_based_graph.GetEdgeData(intersection[0].eid).road_classification; const auto via_class =
node_based_graph.GetEdgeData(intersection[0].eid).flags.road_classification;
// if any of the considered roads is a link road, it cannot be a fork // if any of the considered roads is a link road, it cannot be a fork
// except if rightmost fork candidate is also a link road // except if rightmost fork candidate is also a link road
const auto is_right_link_class = const auto is_right_link_class =
node_based_graph.GetEdgeData(fork.getRight().eid).road_classification.IsLinkClass(); node_based_graph.GetEdgeData(fork.getRight().eid).flags.road_classification.IsLinkClass();
if (!std::all_of(fork.begin + 1, fork.end, [&](ConnectedRoad &road) { if (!std::all_of(fork.begin + 1, fork.end, [&](ConnectedRoad &road) {
return is_right_link_class == return is_right_link_class ==
node_based_graph.GetEdgeData(road.eid).road_classification.IsLinkClass(); node_based_graph.GetEdgeData(road.eid).flags.road_classification.IsLinkClass();
})) }))
{ {
return false; return false;
} }
return std::all_of(fork.begin, fork.end, [&](ConnectedRoad &base) { return std::all_of(fork.begin, fork.end, [&](ConnectedRoad &base) {
const auto base_class = node_based_graph.GetEdgeData(base.eid).road_classification; const auto base_class = node_based_graph.GetEdgeData(base.eid).flags.road_classification;
// check that there is no turn obvious == check that all turns are non-onvious // check that there is no turn obvious == check that all turns are non-onvious
return std::all_of(fork.begin, fork.end, [&](ConnectedRoad &compare) { return std::all_of(fork.begin, fork.end, [&](ConnectedRoad &compare) {
const auto compare_class = const auto compare_class =
node_based_graph.GetEdgeData(compare.eid).road_classification; node_based_graph.GetEdgeData(compare.eid).flags.road_classification;
return compare.eid == base.eid || return compare.eid == base.eid ||
!(obviousByRoadClass(via_class, base_class, compare_class)); !(obviousByRoadClass(via_class, base_class, compare_class));
}); });
@ -670,8 +677,12 @@ boost::optional<TurnHandler::Fork> TurnHandler::findFork(const EdgeID via_edge,
const auto has_compatible_modes = const auto has_compatible_modes =
std::all_of(fork->begin, fork->end, [&](const auto &road) { std::all_of(fork->begin, fork->end, [&](const auto &road) {
return node_based_graph.GetEdgeData(road.eid).travel_mode == return node_data_container
node_based_graph.GetEdgeData(via_edge).travel_mode; .GetAnnotation(node_based_graph.GetEdgeData(road.eid).annotation_data)
.travel_mode ==
node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data)
.travel_mode;
}); });
if (separated_at_left_side && separated_at_right_side && !has_obvious && if (separated_at_left_side && separated_at_right_side && !has_obvious &&
@ -703,9 +714,10 @@ void TurnHandler::handleDistinctConflict(const EdgeID via_edge,
getTurnDirection(left.angle) == DirectionModifier::SlightLeft || getTurnDirection(left.angle) == DirectionModifier::SlightLeft ||
getTurnDirection(right.angle) == DirectionModifier::SlightRight) getTurnDirection(right.angle) == DirectionModifier::SlightRight)
{ {
const auto left_classification = node_based_graph.GetEdgeData(left.eid).road_classification; const auto left_classification =
node_based_graph.GetEdgeData(left.eid).flags.road_classification;
const auto right_classification = const auto right_classification =
node_based_graph.GetEdgeData(right.eid).road_classification; node_based_graph.GetEdgeData(right.eid).flags.road_classification;
if (left_classification.GetPriority() > right_classification.GetPriority()) if (left_classification.GetPriority() > right_classification.GetPriority())
{ {

View File

@ -34,11 +34,12 @@ std::size_t getNumberOfTurns(const Intersection &intersection)
} // namespace } // namespace
TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph, TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const EdgeBasedNodeDataContainer &node_data_container,
LaneDescriptionMap &lane_description_map, LaneDescriptionMap &lane_description_map,
const TurnAnalysis &turn_analysis, const TurnAnalysis &turn_analysis,
util::guidance::LaneDataIdMap &id_map) util::guidance::LaneDataIdMap &id_map)
: node_based_graph(node_based_graph), lane_description_map(lane_description_map), : node_based_graph(node_based_graph), node_data_container(node_data_container),
turn_analysis(turn_analysis), id_map(id_map) lane_description_map(lane_description_map), turn_analysis(turn_analysis), id_map(id_map)
{ {
std::tie(turn_lane_offsets, turn_lane_masks) = std::tie(turn_lane_offsets, turn_lane_masks) =
transformTurnLaneMapIntoArrays(lane_description_map); transformTurnLaneMapIntoArrays(lane_description_map);
@ -149,7 +150,7 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
LaneDescriptionID &previous_description_id) LaneDescriptionID &previous_description_id)
{ {
// as long as we don't want to emit lanes on roundabout, don't assign them // as long as we don't want to emit lanes on roundabout, don't assign them
if (node_based_graph.GetEdgeData(via_edge).roundabout) if (node_based_graph.GetEdgeData(via_edge).flags.roundabout)
return TurnLaneScenario::NONE; return TurnLaneScenario::NONE;
// really don't touch roundabouts (#2626) // really don't touch roundabouts (#2626)
@ -179,7 +180,9 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
(intersection.size() == 2 && (intersection.size() == 2 &&
((lane_description_id != INVALID_LANE_DESCRIPTIONID && ((lane_description_id != INVALID_LANE_DESCRIPTIONID &&
lane_description_id == lane_description_id ==
node_based_graph.GetEdgeData(intersection[1].eid).lane_description_id) && node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(intersection[1].eid).annotation_data)
.lane_description_id) &&
angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)); angularDeviation(intersection[1].angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE));
if (is_going_straight_and_turns_continue) if (is_going_straight_and_turns_continue)
@ -367,7 +370,8 @@ void TurnLaneHandler::extractLaneData(const EdgeID via_edge,
LaneDescriptionID &lane_description_id, LaneDescriptionID &lane_description_id,
LaneDataVector &lane_data) const LaneDataVector &lane_data) const
{ {
const auto &edge_data = node_based_graph.GetEdgeData(via_edge); const auto &edge_data =
node_data_container.GetAnnotation(node_based_graph.GetEdgeData(via_edge).annotation_data);
lane_description_id = edge_data.lane_description_id; lane_description_id = edge_data.lane_description_id;
// create an empty lane data // create an empty lane data
if (INVALID_LANE_DESCRIPTIONID != lane_description_id) if (INVALID_LANE_DESCRIPTIONID != lane_description_id)
@ -719,9 +723,13 @@ Intersection TurnLaneHandler::handleSliproadTurn(Intersection intersection,
return previous_intersection[sliproad_index + 1]; return previous_intersection[sliproad_index + 1];
}(); }();
const auto main_description_id = const auto main_description_id =
node_based_graph.GetEdgeData(main_road.eid).lane_description_id; node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(main_road.eid).annotation_data)
.lane_description_id;
const auto sliproad_description_id = const auto sliproad_description_id =
node_based_graph.GetEdgeData(sliproad.eid).lane_description_id; node_data_container
.GetAnnotation(node_based_graph.GetEdgeData(sliproad.eid).annotation_data)
.lane_description_id;
if (main_description_id == INVALID_LANE_DESCRIPTIONID || if (main_description_id == INVALID_LANE_DESCRIPTIONID ||
sliproad_description_id == INVALID_LANE_DESCRIPTIONID) sliproad_description_id == INVALID_LANE_DESCRIPTIONID)

View File

@ -0,0 +1,205 @@
#include "extractor/node_based_graph_factory.hpp"
#include "extractor/graph_compressor.hpp"
#include "storage/io.hpp"
#include "util/graph_loader.hpp"
#include "util/log.hpp"
#include <boost/assert.hpp>
namespace osrm
{
namespace extractor
{
NodeBasedGraphFactory::NodeBasedGraphFactory(
const boost::filesystem::path &input_file,
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions)
{
LoadDataFromFile(input_file);
Compress(scripting_environment, turn_restrictions, conditional_turn_restrictions);
CompressGeometry();
CompressAnnotationData();
}
// load the data serialised during the extraction run
void NodeBasedGraphFactory::LoadDataFromFile(const boost::filesystem::path &input_file)
{
// the extraction_containers serialise all data necessary to create the node-based graph into a
// single file, the *.osrm file. It contains nodes, basic information about which of these nodes
// are traffic signals/stop signs. It also contains Edges and purely annotative meta-data
storage::io::FileReader file_reader(input_file, storage::io::FileReader::VerifyFingerprint);
auto barriers_iter = inserter(barriers, end(barriers));
auto traffic_signals_iter = inserter(traffic_signals, end(traffic_signals));
const auto number_of_node_based_nodes = util::loadNodesFromFile(
file_reader, barriers_iter, traffic_signals_iter, coordinates, osm_node_ids);
std::vector<NodeBasedEdge> edge_list;
util::loadEdgesFromFile(file_reader, edge_list);
if (edge_list.empty())
{
throw util::exception("Node-based-graph (" + input_file.string() + ") contains no edges." +
SOURCE_REF);
}
util::loadAnnotationData(file_reader, annotation_data);
// at this point, the data isn't compressed, but since we update the graph in-place, we assign
// it here.
compressed_output_graph =
util::NodeBasedDynamicGraphFromEdges(number_of_node_based_nodes, edge_list);
// check whether the graph is sane
BOOST_ASSERT([this]() {
for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes()))
{
for (EdgeID nbg_edge_id : compressed_output_graph.GetAdjacentEdgeRange(nbg_node_u))
{
// we cannot have invalid edge-ids in the graph
if (nbg_edge_id == SPECIAL_EDGEID)
return false;
const auto nbg_node_v = compressed_output_graph.GetTarget(nbg_edge_id);
auto reverse = compressed_output_graph.FindEdge(nbg_node_v, nbg_node_u);
// found an edge that is reversed in both directions, should be two distinct edges
if (compressed_output_graph.GetEdgeData(nbg_edge_id).reversed &&
compressed_output_graph.GetEdgeData(reverse).reversed)
return false;
}
}
return true;
}());
}
void NodeBasedGraphFactory::Compress(
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<ConditionalTurnRestriction> &conditional_turn_restrictions)
{
GraphCompressor graph_compressor;
graph_compressor.Compress(barriers,
traffic_signals,
scripting_environment,
turn_restrictions,
conditional_turn_restrictions,
compressed_output_graph,
annotation_data,
compressed_edge_container);
}
void NodeBasedGraphFactory::CompressGeometry()
{
for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes()))
{
for (EdgeID nbg_edge_id : compressed_output_graph.GetAdjacentEdgeRange(nbg_node_u))
{
BOOST_ASSERT(nbg_edge_id != SPECIAL_EDGEID);
const auto &nbg_edge_data = compressed_output_graph.GetEdgeData(nbg_edge_id);
const auto nbg_node_v = compressed_output_graph.GetTarget(nbg_edge_id);
BOOST_ASSERT(nbg_node_v != SPECIAL_NODEID);
BOOST_ASSERT(nbg_node_u != nbg_node_v);
// pick only every other edge, since we have every edge as an outgoing
// and incoming egde
if (nbg_node_u >= nbg_node_v)
{
continue;
}
auto from = nbg_node_u, to = nbg_node_v;
// if we found a non-forward edge reverse and try again
if (nbg_edge_data.reversed)
std::swap(from, to);
// find forward edge id and
const EdgeID edge_id_1 = compressed_output_graph.FindEdge(from, to);
BOOST_ASSERT(edge_id_1 != SPECIAL_EDGEID);
// find reverse edge id and
const EdgeID edge_id_2 = compressed_output_graph.FindEdge(to, from);
BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID);
auto packed_geometry_id = compressed_edge_container.ZipEdges(edge_id_1, edge_id_2);
// remember the geometry ID for both edges in the node-based graph
compressed_output_graph.GetEdgeData(edge_id_1).geometry_id = {packed_geometry_id, true};
compressed_output_graph.GetEdgeData(edge_id_2).geometry_id = {packed_geometry_id,
false};
}
}
}
void NodeBasedGraphFactory::CompressAnnotationData()
{
const constexpr AnnotationID INVALID_ANNOTATIONID = -1;
// remap all entries to find which are used
std::vector<AnnotationID> annotation_mapping(annotation_data.size(), INVALID_ANNOTATIONID);
// first we mark entries, by setting their mapping to 0
for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes()))
{
BOOST_ASSERT(nbg_node_u != SPECIAL_NODEID);
for (EdgeID nbg_edge_id : compressed_output_graph.GetAdjacentEdgeRange(nbg_node_u))
{
auto const &edge = compressed_output_graph.GetEdgeData(nbg_edge_id);
annotation_mapping[edge.annotation_data] = 0;
}
}
// now compute a prefix sum on all entries that are 0 to find the new mapping
AnnotationID prefix_sum = 0;
for (std::size_t i = 0; i < annotation_mapping.size(); ++i)
{
if (annotation_mapping[i] == 0)
annotation_mapping[i] = prefix_sum++;
else
{
// flag for removal
annotation_data[i].name_id = INVALID_NAMEID;
}
}
// apply the mapping
for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes()))
{
BOOST_ASSERT(nbg_node_u != SPECIAL_NODEID);
for (EdgeID nbg_edge_id : compressed_output_graph.GetAdjacentEdgeRange(nbg_node_u))
{
auto &edge = compressed_output_graph.GetEdgeData(nbg_edge_id);
edge.annotation_data = annotation_mapping[edge.annotation_data];
BOOST_ASSERT(edge.annotation_data != INVALID_ANNOTATIONID);
}
}
// remove unreferenced entries, shifting other entries to the front
const auto new_end =
std::remove_if(annotation_data.begin(), annotation_data.end(), [&](auto const &data) {
// both elements are considered equal (to remove the second
// one) if the annotation mapping of the second one is
// invalid
return data.name_id == INVALID_NAMEID;
});
const auto old_size = annotation_data.size();
// remove all remaining elements
annotation_data.erase(new_end, annotation_data.end());
util::Log() << " graoh compression removed " << (old_size - annotation_data.size())
<< " annotations of " << old_size;
}
void NodeBasedGraphFactory::ReleaseOsmNodes()
{
// replace with a new vector to release old memory
extractor::PackedOSMIDs().swap(osm_node_ids);
}
} // namespace extractor
} // namespace osrm

View File

@ -218,7 +218,7 @@ int Partitioner::Run(const PartitionConfig &config)
files::writePartition(config.GetPath(".osrm.partition"), mlp); files::writePartition(config.GetPath(".osrm.partition"), mlp);
files::writeCells(config.GetPath(".osrm.cells"), storage); files::writeCells(config.GetPath(".osrm.cells"), storage);
extractor::files::writeEdgeBasedGraph(config.GetPath(".osrm.ebg"), extractor::files::writeEdgeBasedGraph(config.GetPath(".osrm.ebg"),
edge_based_graph.GetNumberOfNodes() - 1, edge_based_graph.GetNumberOfNodes(),
graphToEdges(edge_based_graph)); graphToEdges(edge_based_graph));
TIMER_STOP(writing_mld_data); TIMER_STOP(writing_mld_data);
util::Log() << "MLD data writing took " << TIMER_SEC(writing_mld_data) << " seconds"; util::Log() << "MLD data writing took " << TIMER_SEC(writing_mld_data) << " seconds";

View File

@ -15,6 +15,7 @@
#include "extractor/class_data.hpp" #include "extractor/class_data.hpp"
#include "extractor/compressed_edge_container.hpp" #include "extractor/compressed_edge_container.hpp"
#include "extractor/edge_based_edge.hpp" #include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_node.hpp"
#include "extractor/files.hpp" #include "extractor/files.hpp"
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
#include "extractor/original_edge_data.hpp" #include "extractor/original_edge_data.hpp"
@ -253,13 +254,11 @@ void Storage::PopulateLayout(DataLayout &layout)
io::FileReader nodes_data_file(config.GetPath(".osrm.ebg_nodes"), io::FileReader nodes_data_file(config.GetPath(".osrm.ebg_nodes"),
io::FileReader::VerifyFingerprint); io::FileReader::VerifyFingerprint);
const auto nodes_number = nodes_data_file.ReadElementCount64(); const auto nodes_number = nodes_data_file.ReadElementCount64();
const auto annotations_number = nodes_data_file.ReadElementCount64();
layout.SetBlockSize<NodeID>(DataLayout::GEOMETRY_ID_LIST, nodes_number); layout.SetBlockSize<extractor::EdgeBasedNode>(DataLayout::EDGE_BASED_NODE_DATA_LIST,
layout.SetBlockSize<NameID>(DataLayout::NAME_ID_LIST, nodes_number); nodes_number);
layout.SetBlockSize<ComponentID>(DataLayout::COMPONENT_ID_LIST, nodes_number); layout.SetBlockSize<extractor::NodeBasedEdgeAnnotation>(DataLayout::ANNOTATION_DATA_LIST,
layout.SetBlockSize<extractor::TravelMode>(DataLayout::TRAVEL_MODE_LIST, nodes_number); annotations_number);
layout.SetBlockSize<extractor::ClassData>(DataLayout::CLASSES_LIST, nodes_number);
layout.SetBlockSize<unsigned>(DataLayout::IS_LEFT_HAND_DRIVING_LIST, nodes_number);
} }
if (boost::filesystem::exists(config.GetPath(".osrm.hsgr"))) if (boost::filesystem::exists(config.GetPath(".osrm.hsgr")))
@ -709,43 +708,21 @@ void Storage::PopulateData(const DataLayout &layout, char *memory_ptr)
// Load edge-based nodes data // Load edge-based nodes data
{ {
auto geometry_id_list_ptr = auto edge_based_node_data_list_ptr = layout.GetBlockPtr<extractor::EdgeBasedNode, true>(
layout.GetBlockPtr<GeometryID, true>(memory_ptr, storage::DataLayout::GEOMETRY_ID_LIST); memory_ptr, storage::DataLayout::EDGE_BASED_NODE_DATA_LIST);
util::vector_view<GeometryID> geometry_ids( util::vector_view<extractor::EdgeBasedNode> edge_based_node_data(
geometry_id_list_ptr, layout.num_entries[storage::DataLayout::GEOMETRY_ID_LIST]); edge_based_node_data_list_ptr,
layout.num_entries[storage::DataLayout::EDGE_BASED_NODE_DATA_LIST]);
auto name_id_list_ptr = auto annotation_data_list_ptr =
layout.GetBlockPtr<NameID, true>(memory_ptr, storage::DataLayout::NAME_ID_LIST); layout.GetBlockPtr<extractor::NodeBasedEdgeAnnotation, true>(
util::vector_view<NameID> name_ids(name_id_list_ptr, memory_ptr, storage::DataLayout::ANNOTATION_DATA_LIST);
layout.num_entries[storage::DataLayout::NAME_ID_LIST]); util::vector_view<extractor::NodeBasedEdgeAnnotation> annotation_data(
annotation_data_list_ptr,
layout.num_entries[storage::DataLayout::ANNOTATION_DATA_LIST]);
auto component_ids_ptr = layout.GetBlockPtr<ComponentID, true>( extractor::EdgeBasedNodeDataView node_data(std::move(edge_based_node_data),
memory_ptr, storage::DataLayout::COMPONENT_ID_LIST); std::move(annotation_data));
util::vector_view<ComponentID> component_ids(
component_ids_ptr, layout.num_entries[storage::DataLayout::COMPONENT_ID_LIST]);
auto travel_mode_list_ptr = layout.GetBlockPtr<extractor::TravelMode, true>(
memory_ptr, storage::DataLayout::TRAVEL_MODE_LIST);
util::vector_view<extractor::TravelMode> travel_modes(
travel_mode_list_ptr, layout.num_entries[storage::DataLayout::TRAVEL_MODE_LIST]);
auto classes_list_ptr = layout.GetBlockPtr<extractor::ClassData, true>(
memory_ptr, storage::DataLayout::CLASSES_LIST);
util::vector_view<extractor::ClassData> classes(
classes_list_ptr, layout.num_entries[storage::DataLayout::CLASSES_LIST]);
auto is_left_hand_driving_ptr = layout.GetBlockPtr<unsigned, true>(
memory_ptr, storage::DataLayout::IS_LEFT_HAND_DRIVING_LIST);
util::vector_view<bool> is_left_hand_driving(
is_left_hand_driving_ptr,
layout.num_entries[storage::DataLayout::IS_LEFT_HAND_DRIVING_LIST]);
extractor::EdgeBasedNodeDataView node_data(std::move(geometry_ids),
std::move(name_ids),
std::move(component_ids),
std::move(travel_modes),
std::move(classes),
std::move(is_left_hand_driving));
extractor::files::readNodeData(config.GetPath(".osrm.ebg_nodes"), node_data); extractor::files::readNodeData(config.GetPath(".osrm.ebg_nodes"), node_data);
} }

View File

@ -55,12 +55,12 @@ std::size_t loadGraph(const std::string &path,
continue; continue;
} }
if (input_edge.forward) if (input_edge.flags.forward)
{ {
graph_edge_list.emplace_back(input_edge.source, input_edge.target); graph_edge_list.emplace_back(input_edge.source, input_edge.target);
} }
if (input_edge.backward) if (input_edge.flags.backward)
{ {
graph_edge_list.emplace_back(input_edge.target, input_edge.source); graph_edge_list.emplace_back(input_edge.target, input_edge.source);
} }

View File

@ -524,8 +524,9 @@ Updater::NumNodesAndEdges Updater::LoadAndUpdateEdgeExpandedGraph() const
{ {
std::vector<EdgeWeight> node_weights; std::vector<EdgeWeight> node_weights;
std::vector<extractor::EdgeBasedEdge> edge_based_edge_list; std::vector<extractor::EdgeBasedEdge> edge_based_edge_list;
auto max_edge_id = Updater::LoadAndUpdateEdgeExpandedGraph(edge_based_edge_list, node_weights); auto number_of_edge_based_nodes =
return std::make_tuple(max_edge_id + 1, std::move(edge_based_edge_list)); Updater::LoadAndUpdateEdgeExpandedGraph(edge_based_edge_list, node_weights);
return std::make_tuple(number_of_edge_based_nodes, std::move(edge_based_edge_list));
} }
EdgeID EdgeID
@ -534,12 +535,12 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
{ {
TIMER_START(load_edges); TIMER_START(load_edges);
EdgeID max_edge_id = 0; EdgeID number_of_edge_based_nodes = 0;
std::vector<util::Coordinate> coordinates; std::vector<util::Coordinate> coordinates;
extractor::PackedOSMIDs osm_node_ids; extractor::PackedOSMIDs osm_node_ids;
extractor::files::readEdgeBasedGraph( extractor::files::readEdgeBasedGraph(
config.GetPath(".osrm.ebg"), max_edge_id, edge_based_edge_list); config.GetPath(".osrm.ebg"), number_of_edge_based_nodes, edge_based_edge_list);
extractor::files::readNodes(config.GetPath(".osrm.nbg_nodes"), coordinates, osm_node_ids); extractor::files::readNodes(config.GetPath(".osrm.nbg_nodes"), coordinates, osm_node_ids);
const bool update_conditional_turns = const bool update_conditional_turns =
@ -550,7 +551,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
if (!update_edge_weights && !update_turn_penalties && !update_conditional_turns) if (!update_edge_weights && !update_turn_penalties && !update_conditional_turns)
{ {
saveDatasourcesNames(config); saveDatasourcesNames(config);
return max_edge_id; return number_of_edge_based_nodes;
} }
if (config.segment_speed_lookup_paths.size() + config.turn_penalty_lookup_paths.size() > 255) if (config.segment_speed_lookup_paths.size() + config.turn_penalty_lookup_paths.size() > 255)
@ -838,7 +839,7 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector<extractor::EdgeBasedEdge> &e
TIMER_STOP(load_edges); TIMER_STOP(load_edges);
util::Log() << "Done reading edges in " << TIMER_MSEC(load_edges) << "ms."; util::Log() << "Done reading edges in " << TIMER_MSEC(load_edges) << "ms.";
return max_edge_id; return number_of_edge_based_nodes;
} }
} }
} }

View File

@ -28,23 +28,33 @@ inline InputEdge MakeUnitEdge(const NodeID from, const NodeID to)
{ {
// src, tgt, dist, edge_id, name_id, fwd, bkwd, roundabout, circular, startpoint, local access, // src, tgt, dist, edge_id, name_id, fwd, bkwd, roundabout, circular, startpoint, local access,
// split edge, travel_mode // split edge, travel_mode
return { return {from,
from, // source to,
to, // target
1, // weight 1, // weight
1, // duration 1, // duration
SPECIAL_EDGEID, // edge_id GeometryID{0, false}, // geometry_id
0, // name_id
false, // reversed false, // reversed
false, // roundabout NodeBasedEdgeClassification(), // default flags
false, // circular 0}; // AnnotationID
false, // startpoint }
false, // is_left_hand_driving
true, // split edge bool compatible(Graph const &graph,
TRAVEL_MODE_INACCESSIBLE, // travel_mode const std::vector<NodeBasedEdgeAnnotation> &node_data_container,
0, // classes EdgeID const first,
INVALID_LANE_DESCRIPTIONID // lane_description_id EdgeID second)
}; {
auto const &first_flags = graph.GetEdgeData(first).flags;
auto const &second_flags = graph.GetEdgeData(second).flags;
if (!(first_flags == second_flags))
return false;
if (graph.GetEdgeData(first).reversed != graph.GetEdgeData(second).reversed)
return false;
auto const &first_annotation = node_data_container[graph.GetEdgeData(first).annotation_data];
auto const &second_annotation = node_data_container[graph.GetEdgeData(second).annotation_data];
return first_annotation.CanCombineWith(second_annotation);
} }
} // namespace } // namespace
@ -60,6 +70,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
std::unordered_set<NodeID> traffic_lights; std::unordered_set<NodeID> traffic_lights;
std::vector<TurnRestriction> restrictions; std::vector<TurnRestriction> restrictions;
std::vector<ConditionalTurnRestriction> conditional_restrictions; std::vector<ConditionalTurnRestriction> conditional_restrictions;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
CompressedEdgeContainer container; CompressedEdgeContainer container;
test::MockScriptingEnvironment scripting_environment; test::MockScriptingEnvironment scripting_environment;
@ -72,19 +83,19 @@ BOOST_AUTO_TEST_CASE(long_road_test)
MakeUnitEdge(3, 4), MakeUnitEdge(3, 4),
MakeUnitEdge(4, 3)}; MakeUnitEdge(4, 3)};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[2].data));
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[4].data));
BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[6].data));
Graph graph(5, edges); Graph graph(5, edges);
BOOST_ASSERT(compatible(graph, annotations, 0, 2));
BOOST_ASSERT(compatible(graph, annotations, 2, 4));
BOOST_ASSERT(compatible(graph, annotations, 4, 6));
compressor.Compress(barrier_nodes, compressor.Compress(barrier_nodes,
traffic_lights, traffic_lights,
scripting_environment, scripting_environment,
restrictions, restrictions,
conditional_restrictions, conditional_restrictions,
graph, graph,
annotations,
container); container);
BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID); BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID);
BOOST_CHECK_EQUAL(graph.FindEdge(1, 2), SPECIAL_EDGEID); BOOST_CHECK_EQUAL(graph.FindEdge(1, 2), SPECIAL_EDGEID);
BOOST_CHECK_EQUAL(graph.FindEdge(2, 3), SPECIAL_EDGEID); BOOST_CHECK_EQUAL(graph.FindEdge(2, 3), SPECIAL_EDGEID);
@ -106,6 +117,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
std::vector<TurnRestriction> restrictions; std::vector<TurnRestriction> restrictions;
std::vector<ConditionalTurnRestriction> conditional_restrictions; std::vector<ConditionalTurnRestriction> conditional_restrictions;
CompressedEdgeContainer container; CompressedEdgeContainer container;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
test::MockScriptingEnvironment scripting_environment; test::MockScriptingEnvironment scripting_environment;
std::vector<InputEdge> edges = {MakeUnitEdge(0, 1), std::vector<InputEdge> edges = {MakeUnitEdge(0, 1),
@ -121,26 +133,28 @@ BOOST_AUTO_TEST_CASE(loop_test)
MakeUnitEdge(5, 0), MakeUnitEdge(5, 0),
MakeUnitEdge(5, 4)}; MakeUnitEdge(5, 4)};
BOOST_ASSERT(edges.size() == 12);
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
BOOST_ASSERT(edges[1].data.IsCompatibleTo(edges[2].data));
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data));
BOOST_ASSERT(edges[3].data.IsCompatibleTo(edges[4].data));
BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[5].data));
BOOST_ASSERT(edges[5].data.IsCompatibleTo(edges[6].data));
BOOST_ASSERT(edges[6].data.IsCompatibleTo(edges[7].data));
BOOST_ASSERT(edges[7].data.IsCompatibleTo(edges[8].data));
BOOST_ASSERT(edges[8].data.IsCompatibleTo(edges[9].data));
BOOST_ASSERT(edges[9].data.IsCompatibleTo(edges[10].data));
BOOST_ASSERT(edges[10].data.IsCompatibleTo(edges[11].data));
Graph graph(6, edges); Graph graph(6, edges);
BOOST_ASSERT(edges.size() == 12);
BOOST_ASSERT(compatible(graph, annotations, 0, 1));
BOOST_ASSERT(compatible(graph, annotations, 1, 2));
BOOST_ASSERT(compatible(graph, annotations, 2, 3));
BOOST_ASSERT(compatible(graph, annotations, 3, 4));
BOOST_ASSERT(compatible(graph, annotations, 4, 5));
BOOST_ASSERT(compatible(graph, annotations, 5, 6));
BOOST_ASSERT(compatible(graph, annotations, 6, 7));
BOOST_ASSERT(compatible(graph, annotations, 7, 8));
BOOST_ASSERT(compatible(graph, annotations, 8, 9));
BOOST_ASSERT(compatible(graph, annotations, 9, 10));
BOOST_ASSERT(compatible(graph, annotations, 10, 11));
BOOST_ASSERT(compatible(graph, annotations, 11, 0));
compressor.Compress(barrier_nodes, compressor.Compress(barrier_nodes,
traffic_lights, traffic_lights,
scripting_environment, scripting_environment,
restrictions, restrictions,
conditional_restrictions, conditional_restrictions,
graph, graph,
annotations,
container); container);
BOOST_CHECK_EQUAL(graph.FindEdge(5, 0), SPECIAL_EDGEID); BOOST_CHECK_EQUAL(graph.FindEdge(5, 0), SPECIAL_EDGEID);
@ -163,6 +177,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
std::unordered_set<NodeID> barrier_nodes; std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights; std::unordered_set<NodeID> traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions; std::vector<TurnRestriction> restrictions;
std::vector<ConditionalTurnRestriction> conditional_restrictions; std::vector<ConditionalTurnRestriction> conditional_restrictions;
CompressedEdgeContainer container; CompressedEdgeContainer container;
@ -175,19 +190,20 @@ BOOST_AUTO_TEST_CASE(t_intersection)
MakeUnitEdge(2, 1), MakeUnitEdge(2, 1),
MakeUnitEdge(3, 1)}; MakeUnitEdge(3, 1)};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
BOOST_ASSERT(edges[1].data.IsCompatibleTo(edges[2].data));
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data));
BOOST_ASSERT(edges[3].data.IsCompatibleTo(edges[4].data));
BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[5].data));
Graph graph(4, edges); Graph graph(4, edges);
BOOST_ASSERT(compatible(graph, annotations, 0, 1));
BOOST_ASSERT(compatible(graph, annotations, 1, 2));
BOOST_ASSERT(compatible(graph, annotations, 2, 3));
BOOST_ASSERT(compatible(graph, annotations, 3, 4));
BOOST_ASSERT(compatible(graph, annotations, 4, 5));
compressor.Compress(barrier_nodes, compressor.Compress(barrier_nodes,
traffic_lights, traffic_lights,
scripting_environment, scripting_environment,
restrictions, restrictions,
conditional_restrictions, conditional_restrictions,
graph, graph,
annotations,
container); container);
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID); BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
@ -204,6 +220,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
std::unordered_set<NodeID> barrier_nodes; std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights; std::unordered_set<NodeID> traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(2);
std::vector<TurnRestriction> restrictions; std::vector<TurnRestriction> restrictions;
std::vector<ConditionalTurnRestriction> conditional_restrictions; std::vector<ConditionalTurnRestriction> conditional_restrictions;
CompressedEdgeContainer container; CompressedEdgeContainer container;
@ -211,18 +228,21 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
std::vector<InputEdge> edges = { std::vector<InputEdge> edges = {
MakeUnitEdge(0, 1), MakeUnitEdge(1, 0), MakeUnitEdge(1, 2), MakeUnitEdge(2, 1)}; MakeUnitEdge(0, 1), MakeUnitEdge(1, 0), MakeUnitEdge(1, 2), MakeUnitEdge(2, 1)};
edges[2].data.name_id = edges[3].data.name_id = 1;
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data)); annotations[1].name_id = 1;
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data)); edges[2].data.annotation_data = edges[3].data.annotation_data = 1;
Graph graph(5, edges); Graph graph(5, edges);
BOOST_ASSERT(compatible(graph, annotations, 0, 1));
BOOST_ASSERT(compatible(graph, annotations, 2, 3));
compressor.Compress(barrier_nodes, compressor.Compress(barrier_nodes,
traffic_lights, traffic_lights,
scripting_environment, scripting_environment,
restrictions, restrictions,
conditional_restrictions, conditional_restrictions,
graph, graph,
annotations,
container); container);
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID); BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);
@ -238,6 +258,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
std::unordered_set<NodeID> barrier_nodes; std::unordered_set<NodeID> barrier_nodes;
std::unordered_set<NodeID> traffic_lights; std::unordered_set<NodeID> traffic_lights;
std::vector<NodeBasedEdgeAnnotation> annotations(1);
std::vector<TurnRestriction> restrictions; std::vector<TurnRestriction> restrictions;
std::vector<ConditionalTurnRestriction> conditional_restrictions; std::vector<ConditionalTurnRestriction> conditional_restrictions;
CompressedEdgeContainer container; CompressedEdgeContainer container;
@ -255,6 +276,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
restrictions, restrictions,
conditional_restrictions, conditional_restrictions,
graph, graph,
annotations,
container); container);
BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID); BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID);