From 27420e62ef0efdde3ba4e4eb8c19e902907e63e8 Mon Sep 17 00:00:00 2001 From: Vsevolod Novikov Date: Wed, 10 Feb 2021 11:34:42 +0300 Subject: [PATCH] #5325 show way_ids in annotations - implementation --- include/engine/api/flatbuffers/compile.sh | 3 ++ .../api/flatbuffers/fbresult_generated.h | 24 +++++++++-- include/engine/api/flatbuffers/route.fbs | 1 + include/engine/api/route_api.hpp | 21 +++++++++ include/engine/api/route_parameters.hpp | 3 +- .../contiguous_internalmem_datafacade.hpp | 9 ++++ include/engine/datafacade/datafacade_base.hpp | 7 +++ include/engine/guidance/assemble_geometry.hpp | 5 +++ include/engine/guidance/leg_geometry.hpp | 2 + include/engine/internal_route_result.hpp | 2 + .../routing_algorithms/routing_base.hpp | 7 +++ .../extractor/compressed_edge_container.hpp | 3 +- include/extractor/extractor.hpp | 1 + include/extractor/extractor_callbacks.hpp | 3 ++ include/extractor/internal_extractor_edge.hpp | 3 +- include/extractor/node_based_edge.hpp | 14 +++++- .../extractor/node_based_graph_factory.hpp | 3 +- include/extractor/segment_data_container.hpp | 37 ++++++++++++++-- include/extractor/serialization.hpp | 2 + include/nodejs/node_osrm_support.hpp | 5 +++ .../server/api/route_parameters_grammar.hpp | 6 ++- include/storage/view_factory.hpp | 3 ++ src/extractor/compressed_edge_container.cpp | 43 ++++++++++++++++++- src/extractor/extractor.cpp | 16 ++++++- src/extractor/extractor_callbacks.cpp | 4 ++ src/extractor/node_based_graph_factory.cpp | 7 +-- unit_tests/engine/offline_facade.cpp | 10 +++++ unit_tests/mocks/mock_datafacade.hpp | 10 +++++ 28 files changed, 232 insertions(+), 22 deletions(-) create mode 100755 include/engine/api/flatbuffers/compile.sh diff --git a/include/engine/api/flatbuffers/compile.sh b/include/engine/api/flatbuffers/compile.sh new file mode 100755 index 000000000..b743be665 --- /dev/null +++ b/include/engine/api/flatbuffers/compile.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +../../../../build/flatbuffers-build/flatc --cpp --no-includes --gen-all --gen-object-api fbresult.fbs diff --git a/include/engine/api/flatbuffers/fbresult_generated.h b/include/engine/api/flatbuffers/fbresult_generated.h index f3f05de4a..28198e0fb 100644 --- a/include/engine/api/flatbuffers/fbresult_generated.h +++ b/include/engine/api/flatbuffers/fbresult_generated.h @@ -462,6 +462,7 @@ struct AnnotationT : public flatbuffers::NativeTable { std::vector duration; std::vector datasources; std::vector nodes; + std::vector ways; std::vector weight; std::vector speed; std::unique_ptr metadata; @@ -476,9 +477,10 @@ struct Annotation FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_DURATION = 6, VT_DATASOURCES = 8, VT_NODES = 10, - VT_WEIGHT = 12, - VT_SPEED = 14, - VT_METADATA = 16 + VT_WAYS = 12, + VT_WEIGHT = 14, + VT_SPEED = 16, + VT_METADATA = 18 }; const flatbuffers::Vector *distance() const { return GetPointer *>(VT_DISTANCE); @@ -492,6 +494,9 @@ struct Annotation FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector *nodes() const { return GetPointer *>(VT_NODES); } + const flatbuffers::Vector *ways() const { + return GetPointer *>(VT_WAYS); + } const flatbuffers::Vector *weight() const { return GetPointer *>(VT_WEIGHT); } @@ -511,6 +516,8 @@ struct Annotation FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyVector(datasources()) && VerifyOffset(verifier, VT_NODES) && verifier.VerifyVector(nodes()) && + VerifyOffset(verifier, VT_WAYS) && + verifier.VerifyVector(ways()) && VerifyOffset(verifier, VT_WEIGHT) && verifier.VerifyVector(weight()) && VerifyOffset(verifier, VT_SPEED) && @@ -539,6 +546,9 @@ struct AnnotationBuilder { void add_nodes(flatbuffers::Offset> nodes) { fbb_.AddOffset(Annotation::VT_NODES, nodes); } + void add_ways(flatbuffers::Offset> ways) { + fbb_.AddOffset(Annotation::VT_WAYS, ways); + } void add_weight(flatbuffers::Offset> weight) { fbb_.AddOffset(Annotation::VT_WEIGHT, weight); } @@ -566,6 +576,7 @@ inline flatbuffers::Offset CreateAnnotation( flatbuffers::Offset> duration = 0, flatbuffers::Offset> datasources = 0, flatbuffers::Offset> nodes = 0, + flatbuffers::Offset> ways = 0, flatbuffers::Offset> weight = 0, flatbuffers::Offset> speed = 0, flatbuffers::Offset metadata = 0) { @@ -573,6 +584,7 @@ inline flatbuffers::Offset CreateAnnotation( builder_.add_metadata(metadata); builder_.add_speed(speed); builder_.add_weight(weight); + builder_.add_ways(ways); builder_.add_nodes(nodes); builder_.add_datasources(datasources); builder_.add_duration(duration); @@ -586,6 +598,7 @@ inline flatbuffers::Offset CreateAnnotationDirect( const std::vector *duration = nullptr, const std::vector *datasources = nullptr, const std::vector *nodes = nullptr, + const std::vector *ways = nullptr, const std::vector *weight = nullptr, const std::vector *speed = nullptr, flatbuffers::Offset metadata = 0) { @@ -593,6 +606,7 @@ inline flatbuffers::Offset CreateAnnotationDirect( auto duration__ = duration ? _fbb.CreateVector(*duration) : 0; auto datasources__ = datasources ? _fbb.CreateVector(*datasources) : 0; auto nodes__ = nodes ? _fbb.CreateVector(*nodes) : 0; + auto ways__ = ways ? _fbb.CreateVector(*ways) : 0; auto weight__ = weight ? _fbb.CreateVector(*weight) : 0; auto speed__ = speed ? _fbb.CreateVector(*speed) : 0; return osrm::engine::api::fbresult::CreateAnnotation( @@ -601,6 +615,7 @@ inline flatbuffers::Offset CreateAnnotationDirect( duration__, datasources__, nodes__, + ways__, weight__, speed__, metadata); @@ -1974,6 +1989,7 @@ inline void Annotation::UnPackTo(AnnotationT *_o, const flatbuffers::resolver_fu { auto _e = duration(); if (_e) { _o->duration.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->duration[_i] = _e->Get(_i); } } }; { auto _e = datasources(); if (_e) { _o->datasources.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->datasources[_i] = _e->Get(_i); } } }; { auto _e = nodes(); if (_e) { _o->nodes.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->nodes[_i] = _e->Get(_i); } } }; + { auto _e = ways(); if (_e) { _o->ways.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->ways[_i] = _e->Get(_i); } } }; { auto _e = weight(); if (_e) { _o->weight.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weight[_i] = _e->Get(_i); } } }; { auto _e = speed(); if (_e) { _o->speed.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->speed[_i] = _e->Get(_i); } } }; { auto _e = metadata(); if (_e) _o->metadata = std::unique_ptr(_e->UnPack(_resolver)); }; @@ -1991,6 +2007,7 @@ inline flatbuffers::Offset CreateAnnotation(flatbuffers::FlatBufferB auto _duration = _o->duration.size() ? _fbb.CreateVector(_o->duration) : 0; auto _datasources = _o->datasources.size() ? _fbb.CreateVector(_o->datasources) : 0; auto _nodes = _o->nodes.size() ? _fbb.CreateVector(_o->nodes) : 0; + auto _ways = _o->ways.size() ? _fbb.CreateVector(_o->ways) : 0; auto _weight = _o->weight.size() ? _fbb.CreateVector(_o->weight) : 0; auto _speed = _o->speed.size() ? _fbb.CreateVector(_o->speed) : 0; auto _metadata = _o->metadata ? CreateMetadata(_fbb, _o->metadata.get(), _rehasher) : 0; @@ -2000,6 +2017,7 @@ inline flatbuffers::Offset CreateAnnotation(flatbuffers::FlatBufferB _duration, _datasources, _nodes, + _ways, _weight, _speed, _metadata); diff --git a/include/engine/api/flatbuffers/route.fbs b/include/engine/api/flatbuffers/route.fbs index 902bfa199..f826d5787 100644 --- a/include/engine/api/flatbuffers/route.fbs +++ b/include/engine/api/flatbuffers/route.fbs @@ -10,6 +10,7 @@ table Annotation { duration: [uint]; datasources: [uint]; nodes: [uint]; + ways: [uint]; weight: [uint]; speed: [float]; metadata: Metadata; diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 4990d37c9..e1d4ae597 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -503,7 +503,17 @@ class RouteAPI : public BaseAPI nodes.emplace_back(static_cast(node_id)); } } + std::vector ways; + if (requested_annotations & RouteParameters::AnnotationsType::Ways) + { + ways.reserve(leg_geometry.osm_way_ids.size()); + for (const auto way_id : leg_geometry.osm_way_ids) + { + ways.emplace_back(static_cast(way_id)); + } + } auto nodes_vector = fb_result.CreateVector(nodes); + auto ways_vector = fb_result.CreateVector(ways); // Add any supporting metadata, if needed bool use_metadata = requested_annotations & RouteParameters::AnnotationsType::Datasources; flatbuffers::Offset metadata_buffer; @@ -529,6 +539,7 @@ class RouteAPI : public BaseAPI annotation.add_weight(weight); annotation.add_datasources(datasources); annotation.add_nodes(nodes_vector); + annotation.add_ways(ways_vector); if (use_metadata) { annotation.add_metadata(metadata_buffer); @@ -832,6 +843,16 @@ class RouteAPI : public BaseAPI } annotation.values["nodes"] = std::move(nodes); } + if (requested_annotations & RouteParameters::AnnotationsType::Ways) + { + util::json::Array ways; + ways.values.reserve(leg_geometry.osm_way_ids.size()); + for (const auto way_id : leg_geometry.osm_way_ids) + { + ways.values.push_back(static_cast(way_id)); + } + annotation.values["ways"] = std::move(ways); + } // Add any supporting metadata, if needed if (requested_annotations & RouteParameters::AnnotationsType::Datasources) { diff --git a/include/engine/api/route_parameters.hpp b/include/engine/api/route_parameters.hpp index 8d5dd9ae4..052b7c436 100644 --- a/include/engine/api/route_parameters.hpp +++ b/include/engine/api/route_parameters.hpp @@ -76,7 +76,8 @@ struct RouteParameters : public BaseParameters Weight = 0x08, Datasources = 0x10, Speed = 0x20, - All = Duration | Nodes | Distance | Weight | Datasources | Speed + Ways = 0x40, + All = Duration | Nodes | Distance | Weight | Datasources | Speed | Ways }; RouteParameters() = default; diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 988678331..70b6d2d98 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -251,6 +251,15 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade return segment_data.GetReverseGeometry(id); } + OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID id) const override final + { + return segment_data.GetForwardOSMWayIDs(id); + } + OSMWayReverseRange GetUncompressedReverseWayIDs(const EdgeID id) const override final + { + return segment_data.GetReverseOSMWayIDs(id); + } + DurationForwardRange GetUncompressedForwardDurations(const EdgeID id) const override final { return segment_data.GetForwardDurations(id); diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index b80c93b18..839138643 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -57,6 +57,10 @@ class BaseDataFacade boost::iterator_range; using NodeReverseRange = boost::reversed_range; + using OSMWayForwardRange = + boost::iterator_range; + using OSMWayReverseRange = boost::reversed_range; + using WeightForwardRange = boost::iterator_range; using WeightReverseRange = boost::reversed_range; @@ -85,6 +89,9 @@ class BaseDataFacade virtual ComponentID GetComponentID(const NodeID id) const = 0; + virtual OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID id) const = 0; + virtual OSMWayReverseRange GetUncompressedReverseWayIDs(const EdgeID id) const = 0; + virtual NodeForwardRange GetUncompressedForwardGeometry(const EdgeID id) const = 0; virtual NodeReverseRange GetUncompressedReverseGeometry(const EdgeID id) const = 0; diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 9e3a0deaf..b651fbd07 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -56,9 +56,11 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, reversed_source ? source_node.reverse_segment_id.id : source_node.forward_segment_id.id; const auto source_geometry_id = facade.GetGeometryIndex(source_node_id).id; const auto source_geometry = facade.GetUncompressedForwardGeometry(source_geometry_id); + //const auto source_osm_way_ids = facade.GetUncompressedForwardWayIDs(source_geometry_id); geometry.osm_node_ids.push_back( facade.GetOSMNodeIDOfNode(source_geometry(source_segment_start_coordinate))); + // geometry.osm_way_ids.push_back(source_osm_way_ids(source_segment_start_coordinate))); auto cumulative_distance = 0.; auto current_distance = 0.; @@ -100,6 +102,7 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, path_point.datasource_id}); geometry.locations.push_back(std::move(coordinate)); geometry.osm_node_ids.push_back(osm_node_id); + geometry.osm_way_ids.push_back(path_point.osm_way_id); } } current_distance = @@ -158,8 +161,10 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const auto target_segment_end_coordinate = target_node.fwd_segment_position + (reversed_target ? 0 : 1); const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id); + const auto target_osm_way_ids = facade.GetUncompressedForwardWayIDs(target_geometry_id); geometry.osm_node_ids.push_back( facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate))); + geometry.osm_way_ids.push_back(target_osm_way_ids(target_node.fwd_segment_position)); BOOST_ASSERT(geometry.segment_distances.size() == geometry.segment_offsets.size() - 1); BOOST_ASSERT(geometry.locations.size() > geometry.segment_distances.size()); diff --git a/include/engine/guidance/leg_geometry.hpp b/include/engine/guidance/leg_geometry.hpp index 8374bb992..daccff8fc 100644 --- a/include/engine/guidance/leg_geometry.hpp +++ b/include/engine/guidance/leg_geometry.hpp @@ -33,6 +33,8 @@ struct LegGeometry std::vector segment_distances; // original OSM node IDs for each coordinate std::vector osm_node_ids; + // original OSM way IDs between every pair of nodes + std::vector osm_way_ids; // Per-coordinate metadata struct Annotation diff --git a/include/engine/internal_route_result.hpp b/include/engine/internal_route_result.hpp index 9f5443ffa..6c7193dc5 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -26,6 +26,8 @@ struct PathData { // from edge-based-node id NodeID from_edge_based_node; + // OSM Way ID of the edge immediately followed by via node + OSMWayID osm_way_id; // the internal OSRM id of the OSM node id that is the via node of the turn NodeID turn_via_node; // name of the street that leads to the turn diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index ee564afe2..855c38d24 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -144,6 +144,7 @@ void annotatePath(const FacadeT &facade, // datastructures to hold extracted data from geometry std::vector id_vector; + std::vector osm_way_id_vector; std::vector weight_vector; std::vector duration_vector; std::vector datasource_vector; @@ -157,6 +158,8 @@ void annotatePath(const FacadeT &facade, if (geometry_index.forward) { copy(id_vector, facade.GetUncompressedForwardGeometry(geometry_index.id)); + copy(osm_way_id_vector, facade.GetUncompressedForwardWayIDs(geometry_index.id)); + copy(weight_vector, facade.GetUncompressedForwardWeights(geometry_index.id)); copy(duration_vector, facade.GetUncompressedForwardDurations(geometry_index.id)); copy(datasource_vector, facade.GetUncompressedForwardDatasources(geometry_index.id)); @@ -164,6 +167,8 @@ void annotatePath(const FacadeT &facade, else { copy(id_vector, facade.GetUncompressedReverseGeometry(geometry_index.id)); + copy(osm_way_id_vector, facade.GetUncompressedReverseWayIDs(geometry_index.id)); + copy(weight_vector, facade.GetUncompressedReverseWeights(geometry_index.id)); copy(duration_vector, facade.GetUncompressedReverseDurations(geometry_index.id)); copy(datasource_vector, facade.GetUncompressedReverseDatasources(geometry_index.id)); @@ -213,6 +218,7 @@ void annotatePath(const FacadeT &facade, { unpacked_path.push_back( PathData{*node_from, + osm_way_id_vector[segment_idx], id_vector[segment_idx + 1], name_index, is_segregated, @@ -288,6 +294,7 @@ void annotatePath(const FacadeT &facade, BOOST_ASSERT(facade.GetTravelMode(target_node_id) > 0); unpacked_path.push_back( PathData{target_node_id, + osm_way_id_vector[segment_idx], id_vector[start_index < end_index ? segment_idx + 1 : segment_idx - 1], facade.GetNameIndex(target_node_id), facade.IsSegregated(target_node_id), diff --git a/include/extractor/compressed_edge_container.hpp b/include/extractor/compressed_edge_container.hpp index ec9e1f9ea..904369b0e 100644 --- a/include/extractor/compressed_edge_container.hpp +++ b/include/extractor/compressed_edge_container.hpp @@ -2,6 +2,7 @@ #define GEOMETRY_COMPRESSOR_HPP_ #include "extractor/segment_data_container.hpp" +#include "extractor/node_based_edge.hpp" #include "util/typedefs.hpp" @@ -48,7 +49,7 @@ class CompressedEdgeContainer const SegmentWeight duration); void InitializeBothwayVector(); - unsigned ZipEdges(const unsigned f_edge_pos, const unsigned r_edge_pos); + unsigned ZipEdges(const unsigned f_edge_pos, const unsigned r_edge_pos, OSMWayIDMap &osm_way_id_map); bool HasEntryForID(const EdgeID edge_id) const; bool HasZippedEntryForForwardID(const EdgeID edge_id) const; diff --git a/include/extractor/extractor.hpp b/include/extractor/extractor.hpp index 070a3b4ef..441a4a754 100644 --- a/include/extractor/extractor.hpp +++ b/include/extractor/extractor.hpp @@ -63,6 +63,7 @@ class Extractor ExtractorConfig config; std::tuple, std::vector> ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads); diff --git a/include/extractor/extractor_callbacks.hpp b/include/extractor/extractor_callbacks.hpp index 9939a4963..197f663ad 100644 --- a/include/extractor/extractor_callbacks.hpp +++ b/include/extractor/extractor_callbacks.hpp @@ -2,6 +2,7 @@ #define EXTRACTOR_CALLBACKS_HPP #include "extractor/class_data.hpp" +#include "extractor/node_based_edge.hpp" #include "extractor/turn_lane_types.hpp" #include "util/typedefs.hpp" @@ -69,6 +70,7 @@ class ExtractorCallbacks ExtractionContainers &external_memory; std::unordered_map &classes_map; LaneDescriptionMap &lane_description_map; + OSMWayIDMap &osm_way_id_map; bool fallback_to_duration; bool force_split_edges; @@ -78,6 +80,7 @@ class ExtractorCallbacks explicit ExtractorCallbacks(ExtractionContainers &extraction_containers, std::unordered_map &classes_map, LaneDescriptionMap &lane_description_map, + OSMWayIDMap &osm_way_id_map, const ProfileProperties &properties); ExtractorCallbacks(const ExtractorCallbacks &) = delete; diff --git a/include/extractor/internal_extractor_edge.hpp b/include/extractor/internal_extractor_edge.hpp index c7ee904d9..5000352bb 100644 --- a/include/extractor/internal_extractor_edge.hpp +++ b/include/extractor/internal_extractor_edge.hpp @@ -60,10 +60,11 @@ struct InternalExtractorEdge explicit InternalExtractorEdge(OSMNodeID source, OSMNodeID target, + OSMWayID way, WeightData weight_data, DurationData duration_data, util::Coordinate source_coordinate) - : result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)), + : result(source, target, way, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)), duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate)) { } diff --git a/include/extractor/node_based_edge.hpp b/include/extractor/node_based_edge.hpp index 84a03d0a0..44f198da7 100644 --- a/include/extractor/node_based_edge.hpp +++ b/include/extractor/node_based_edge.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "extractor/class_data.hpp" #include "extractor/travel_mode.hpp" @@ -15,6 +16,12 @@ namespace osrm namespace extractor { +// Intermediate map to lookup OSMWayID by neighbor nbg node pair +// while CompressedEdgeContainer::ZipEdges and store it in the segment data +// to use when building found path annotations +using OSMWayIDMapKey = std::pair; +using OSMWayIDMap = std::map; + // 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 @@ -120,6 +127,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge NodeBasedEdgeWithOSM(OSMNodeID source, OSMNodeID target, + OSMWayID way, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance, @@ -129,6 +137,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge OSMNodeID osm_source_id; OSMNodeID osm_target_id; + OSMWayID osm_way_id; }; // Impl. @@ -178,6 +187,7 @@ inline bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source, OSMNodeID target, + OSMWayID way, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance, @@ -192,12 +202,12 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source, geometry_id, annotation_data, flags), - osm_source_id(std::move(source)), osm_target_id(std::move(target)) + osm_source_id(std::move(source)), osm_target_id(std::move(target)), osm_way_id(std::move(way)) { } inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM() - : osm_source_id(MIN_OSM_NODEID), osm_target_id(MIN_OSM_NODEID) + : osm_source_id(MIN_OSM_NODEID), osm_target_id(MIN_OSM_NODEID), osm_way_id(MIN_OSM_WAYID) { } diff --git a/include/extractor/node_based_graph_factory.hpp b/include/extractor/node_based_graph_factory.hpp index e3fc39583..7b44e7bd6 100644 --- a/include/extractor/node_based_graph_factory.hpp +++ b/include/extractor/node_based_graph_factory.hpp @@ -39,6 +39,7 @@ class NodeBasedGraphFactory // turn the graph into the routing graph to be used with the navigation algorithms. NodeBasedGraphFactory(const boost::filesystem::path &input_file, ScriptingEnvironment &scripting_environment, + OSMWayIDMap &osm_way_id_map, std::vector &turn_restrictions, std::vector &maneuver_overrides); @@ -73,7 +74,7 @@ class NodeBasedGraphFactory // 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(); + void CompressGeometry(OSMWayIDMap &osm_way_id_map); // 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 diff --git a/include/extractor/segment_data_container.hpp b/include/extractor/segment_data_container.hpp index 580c018ed..76d3b5c0a 100644 --- a/include/extractor/segment_data_container.hpp +++ b/include/extractor/segment_data_container.hpp @@ -56,6 +56,7 @@ template class SegmentDataContainerImpl using DirectionalGeometryID = std::uint32_t; using SegmentOffset = std::uint32_t; using SegmentNodeVector = Vector; + using SegmentOSMWayVector = Vector; using SegmentWeightVector = PackedVector; using SegmentDurationVector = PackedVector; using SegmentDatasourceVector = Vector; @@ -64,16 +65,17 @@ template class SegmentDataContainerImpl SegmentDataContainerImpl(Vector index_, SegmentNodeVector nodes_, + SegmentOSMWayVector osm_ways_, SegmentWeightVector fwd_weights_, SegmentWeightVector rev_weights_, SegmentDurationVector fwd_durations_, SegmentDurationVector rev_durations_, SegmentDatasourceVector fwd_datasources_, SegmentDatasourceVector rev_datasources_) - : index(std::move(index_)), nodes(std::move(nodes_)), fwd_weights(std::move(fwd_weights_)), - rev_weights(std::move(rev_weights_)), fwd_durations(std::move(fwd_durations_)), - rev_durations(std::move(rev_durations_)), fwd_datasources(std::move(fwd_datasources_)), - rev_datasources(std::move(rev_datasources_)) + : index(std::move(index_)), nodes(std::move(nodes_)), osm_ways(std::move(osm_ways_)), + fwd_weights(std::move(fwd_weights_)), rev_weights(std::move(rev_weights_)), + fwd_durations(std::move(fwd_durations_)), rev_durations(std::move(rev_durations_)), + fwd_datasources(std::move(fwd_datasources_)), rev_datasources(std::move(rev_datasources_)) { } @@ -90,6 +92,19 @@ template class SegmentDataContainerImpl return boost::adaptors::reverse(GetForwardGeometry(id)); } + auto GetForwardOSMWayIDs(const DirectionalGeometryID id) + { + const auto begin = osm_ways.begin() + index[id]; + const auto end = osm_ways.begin() + index[id + 1] - 1; + + return boost::make_iterator_range(begin, end); + } + + auto GetReverseOSMWayIDs(const DirectionalGeometryID id) + { + return boost::adaptors::reverse(GetForwardOSMWayIDs(id)); + } + auto GetForwardDurations(const DirectionalGeometryID id) { const auto begin = fwd_durations.begin() + index[id] + 1; @@ -151,6 +166,19 @@ template class SegmentDataContainerImpl return boost::adaptors::reverse(GetForwardGeometry(id)); } + auto GetForwardOSMWayIDs(const DirectionalGeometryID id) const + { + const auto begin = osm_ways.cbegin() + index[id]; + const auto end = osm_ways.cbegin() + index[id + 1] - 1; + + return boost::make_iterator_range(begin, end); + } + + auto GetReverseOSMWayIDs(const DirectionalGeometryID id) const + { + return boost::adaptors::reverse(GetForwardOSMWayIDs(id)); + } + auto GetForwardDurations(const DirectionalGeometryID id) const { const auto begin = fwd_durations.cbegin() + index[id] + 1; @@ -214,6 +242,7 @@ template class SegmentDataContainerImpl private: Vector index; SegmentNodeVector nodes; + SegmentOSMWayVector osm_ways; SegmentWeightVector fwd_weights; SegmentWeightVector rev_weights; SegmentDurationVector fwd_durations; diff --git a/include/extractor/serialization.hpp b/include/extractor/serialization.hpp index 363dd9c16..3ec5ae177 100644 --- a/include/extractor/serialization.hpp +++ b/include/extractor/serialization.hpp @@ -84,6 +84,7 @@ inline void read(storage::tar::FileReader &reader, { storage::serialization::read(reader, name + "/index", segment_data.index); storage::serialization::read(reader, name + "/nodes", segment_data.nodes); + storage::serialization::read(reader, name + "/osm_ways", segment_data.osm_ways); util::serialization::read(reader, name + "/forward_weights", segment_data.fwd_weights); util::serialization::read(reader, name + "/reverse_weights", segment_data.rev_weights); util::serialization::read(reader, name + "/forward_durations", segment_data.fwd_durations); @@ -101,6 +102,7 @@ inline void write(storage::tar::FileWriter &writer, { storage::serialization::write(writer, name + "/index", segment_data.index); storage::serialization::write(writer, name + "/nodes", segment_data.nodes); + storage::serialization::write(writer, name + "/osm_ways", segment_data.osm_ways); util::serialization::write(writer, name + "/forward_weights", segment_data.fwd_weights); util::serialization::write(writer, name + "/reverse_weights", segment_data.rev_weights); util::serialization::write(writer, name + "/forward_durations", segment_data.fwd_durations); diff --git a/include/nodejs/node_osrm_support.hpp b/include/nodejs/node_osrm_support.hpp index 400d420a5..cafae9a5d 100644 --- a/include/nodejs/node_osrm_support.hpp +++ b/include/nodejs/node_osrm_support.hpp @@ -762,6 +762,11 @@ inline bool parseCommonParameters(const v8::Local &obj, ParamType &p params->annotations_type = params->annotations_type | osrm::RouteParameters::AnnotationsType::Nodes; } + else if (annotations_str == "ways") + { + params->annotations_type = + params->annotations_type | osrm::RouteParameters::AnnotationsType::Ways; + } else if (annotations_str == "distance") { params->annotations_type = diff --git a/include/server/api/route_parameters_grammar.hpp b/include/server/api/route_parameters_grammar.hpp index df5fb52df..dc005043b 100644 --- a/include/server/api/route_parameters_grammar.hpp +++ b/include/server/api/route_parameters_grammar.hpp @@ -73,8 +73,10 @@ struct RouteParametersGrammar : public BaseParametersGrammar(index, name + "/osm_ways"); + extractor::SegmentDataView::SegmentWeightVector fwd_weight_list( make_vector_view( index, name + "/forward_weights/packed"), @@ -162,6 +164,7 @@ inline auto make_segment_data_view(const SharedDataIndex &index, const std::stri return extractor::SegmentDataView{std::move(geometry_begin_indices), std::move(node_list), + std::move(osm_way_list), std::move(fwd_weight_list), std::move(rev_weight_list), std::move(fwd_duration_list), diff --git a/src/extractor/compressed_edge_container.cpp b/src/extractor/compressed_edge_container.cpp index 7510f85b0..81b2e631c 100644 --- a/src/extractor/compressed_edge_container.cpp +++ b/src/extractor/compressed_edge_container.cpp @@ -262,7 +262,7 @@ void CompressedEdgeContainer::InitializeBothwayVector() segment_data->rev_datasources.reserve(m_compressed_oneway_geometries.size()); } -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, OSMWayIDMap &osm_way_id_map) { if (!segment_data) InitializeBothwayVector(); @@ -279,7 +279,8 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID segment_data->index.emplace_back(segment_data->nodes.size()); const auto &first_node = reverse_bucket.back(); - + auto prev_node_id = first_node.node_id; + auto osm_way_id = SPECIAL_OSM_WAYID; constexpr DatasourceID LUA_SOURCE = 0; segment_data->nodes.emplace_back(first_node.node_id); @@ -297,6 +298,23 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID BOOST_ASSERT(fwd_node.node_id == rev_node.node_id); + auto node_id = fwd_node.node_id; + if( node_id != prev_node_id ) { + auto find_way_id = osm_way_id_map.find( OSMWayIDMapKey(prev_node_id, node_id) ); + if( find_way_id == osm_way_id_map.cend() ) { + find_way_id = osm_way_id_map.find( OSMWayIDMapKey(node_id, prev_node_id) ); + } + if( find_way_id == osm_way_id_map.cend() ) { + util::Log(logERROR) << "OSM Way ID not found for (nbg) nodes, it should never be happened: " << prev_node_id << "<-x->" << node_id; + segment_data->osm_ways.emplace_back(osm_way_id); + } else { + segment_data->osm_ways.emplace_back(osm_way_id = find_way_id->second); + } + } else { + // Special case (artificial lighting signal edge) + segment_data->osm_ways.emplace_back(osm_way_id); + } + segment_data->nodes.emplace_back(fwd_node.node_id); segment_data->fwd_weights.emplace_back(fwd_node.weight); segment_data->rev_weights.emplace_back(rev_node.weight); @@ -304,9 +322,30 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID segment_data->rev_durations.emplace_back(rev_node.duration); segment_data->fwd_datasources.emplace_back(LUA_SOURCE); segment_data->rev_datasources.emplace_back(LUA_SOURCE); + prev_node_id = node_id; } const auto &last_node = forward_bucket.back(); + auto node_id = last_node.node_id; + if( node_id != prev_node_id ) { + auto find_way_id = osm_way_id_map.find( OSMWayIDMapKey(prev_node_id, node_id) ); + if( find_way_id == osm_way_id_map.cend() ) { + find_way_id = osm_way_id_map.find( OSMWayIDMapKey(node_id, prev_node_id) ); + } + if( find_way_id == osm_way_id_map.cend() ) { + util::Log(logERROR) << "OSM Way ID not found for (nbg) nodes, it should never be happened: " << prev_node_id << "<-x->" << node_id; + segment_data->osm_ways.emplace_back(osm_way_id); + } else { + segment_data->osm_ways.emplace_back(osm_way_id = find_way_id->second); + } + } else { + // Special case (artificial lighting signal edge) + segment_data->osm_ways.emplace_back(osm_way_id); + } + + // Make osm_ways vector size the same as + // nodes vector size to use index vector for the both + segment_data->osm_ways.emplace_back(osm_way_id); segment_data->nodes.emplace_back(last_node.node_id); segment_data->fwd_weights.emplace_back(last_node.weight); diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp index 5c5d96a71..641e80b34 100644 --- a/src/extractor/extractor.cpp +++ b/src/extractor/extractor.cpp @@ -215,9 +215,10 @@ int Extractor::run(ScriptingEnvironment &scripting_environment) #endif LaneDescriptionMap turn_lane_map; + OSMWayIDMap osm_way_id_map; std::vector turn_restrictions; std::vector unresolved_maneuver_overrides; - std::tie(turn_lane_map, turn_restrictions, unresolved_maneuver_overrides) = + std::tie(turn_lane_map, osm_way_id_map, turn_restrictions, unresolved_maneuver_overrides) = ParseOSMData(scripting_environment, number_of_threads); // Transform the node-based graph that OSM is based on into an edge-based graph @@ -238,6 +239,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment) // Create a node-based graph from the OSRM file NodeBasedGraphFactory node_based_graph_factory(config.GetPath(".osrm"), scripting_environment, + osm_way_id_map, turn_restrictions, unresolved_maneuver_overrides); @@ -369,7 +371,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment) } std:: - tuple, std::vector> + tuple, std::vector> Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment, const unsigned number_of_threads) { @@ -420,10 +422,12 @@ std:: ExtractionContainers extraction_containers; ExtractorCallbacks::ClassesMap classes_map; LaneDescriptionMap turn_lane_map; + OSMWayIDMap osm_way_id_map; auto extractor_callbacks = std::make_unique(extraction_containers, classes_map, turn_lane_map, + osm_way_id_map, scripting_environment.GetProfileProperties()); // get list of supported relation types @@ -626,10 +630,18 @@ std:: SetExcludableClasses(classes_map, excludable_classes, profile_properties); files::writeProfileProperties(config.GetPath(".osrm.properties").string(), profile_properties); + // Fill OSM Way ID Lookup Map to use it later + for(auto edge: extraction_containers.all_edges_list) { + osm_way_id_map[ + OSMWayIDMapKey(edge.result.source, edge.result.target) + ] = edge.result.osm_way_id; + } + TIMER_STOP(extracting); util::Log() << "extraction finished after " << TIMER_SEC(extracting) << "s"; return std::make_tuple(std::move(turn_lane_map), + std::move(osm_way_id_map), std::move(extraction_containers.turn_restrictions), std::move(extraction_containers.internal_maneuver_overrides)); } diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index de7b28219..4b6bf84e2 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -29,9 +29,11 @@ namespace extractor ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers_, std::unordered_map &classes_map, LaneDescriptionMap &lane_description_map, + OSMWayIDMap &osm_way_id_map, const ProfileProperties &properties) : external_memory(extraction_containers_), classes_map(classes_map), lane_description_map(lane_description_map), + osm_way_id_map(osm_way_id_map), fallback_to_duration(properties.fallback_to_duration), force_split_edges(properties.force_split_edges) { @@ -409,6 +411,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti NodeBasedEdgeWithOSM edge = { OSMNodeID{static_cast(first_node.ref())}, OSMNodeID{static_cast(last_node.ref())}, + OSMWayID{static_cast(input_way.id())}, 0, // weight 0, // duration 0, // distance @@ -445,6 +448,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti NodeBasedEdgeWithOSM edge = { OSMNodeID{static_cast(first_node.ref())}, OSMNodeID{static_cast(last_node.ref())}, + OSMWayID{static_cast(input_way.id())}, 0, // weight 0, // duration 0, // distance diff --git a/src/extractor/node_based_graph_factory.cpp b/src/extractor/node_based_graph_factory.cpp index 51473797d..6ae8dbf94 100644 --- a/src/extractor/node_based_graph_factory.cpp +++ b/src/extractor/node_based_graph_factory.cpp @@ -18,12 +18,13 @@ namespace extractor NodeBasedGraphFactory::NodeBasedGraphFactory( const boost::filesystem::path &input_file, ScriptingEnvironment &scripting_environment, + OSMWayIDMap &osm_way_id_map, std::vector &turn_restrictions, std::vector &maneuver_overrides) { LoadDataFromFile(input_file); Compress(scripting_environment, turn_restrictions, maneuver_overrides); - CompressGeometry(); + CompressGeometry(osm_way_id_map); CompressAnnotationData(); } @@ -93,7 +94,7 @@ void NodeBasedGraphFactory::Compress(ScriptingEnvironment &scripting_environment compressed_edge_container); } -void NodeBasedGraphFactory::CompressGeometry() +void NodeBasedGraphFactory::CompressGeometry(OSMWayIDMap &osm_way_id_map) { for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes())) { @@ -126,7 +127,7 @@ void NodeBasedGraphFactory::CompressGeometry() 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); + auto packed_geometry_id = compressed_edge_container.ZipEdges(edge_id_1, edge_id_2, osm_way_id_map); // 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}; diff --git a/unit_tests/engine/offline_facade.cpp b/unit_tests/engine/offline_facade.cpp index 7c264e176..e6c9d70b0 100644 --- a/unit_tests/engine/offline_facade.cpp +++ b/unit_tests/engine/offline_facade.cpp @@ -166,6 +166,16 @@ class ContiguousInternalMemoryDataFacade return NodeReverseRange(NodeForwardRange()); } + OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID /*id*/) const override + { + return {}; + } + + OSMWayReverseRange GetUncompressedReverseWayIDs(const EdgeID /*id*/) const override + { + return OSMWayReverseRange(OSMWayForwardRange()); + } + TurnPenalty GetWeightPenaltyForEdgeID(const unsigned /*id*/) const override { return INVALID_TURN_PENALTY; diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 4edcb9735..2270bfffd 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -64,6 +64,16 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade { return NodeReverseRange(GetUncompressedForwardGeometry(id)); } + OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID /* id */) const override + { + static OSMWayID data[] = {0, 1, 2, 3}; + static extractor::SegmentDataView::SegmentOSMWayVector ways(data, 4); + return boost::make_iterator_range(ways.cbegin(), ways.cend()); + } + OSMWayReverseRange GetUncompressedReverseWayIDs(const EdgeID id) const override + { + return OSMWayReverseRange(GetUncompressedForwardWayIDs(id)); + } WeightForwardRange GetUncompressedForwardWeights(const EdgeID /* id */) const override { static std::uint64_t data[] = {1, 2, 3};