diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index dea263951..138a75baf 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -198,6 +198,7 @@ class RouteAPI : public BaseAPI { util::json::Array durations; util::json::Array distances; + util::json::Array nodes; auto &leg_geometry = leg_geometries[idx]; std::for_each( leg_geometry.annotations.begin(), @@ -206,9 +207,16 @@ class RouteAPI : public BaseAPI durations.values.push_back(step.duration); distances.values.push_back(step.distance); }); + std::for_each( + leg_geometry.osm_node_ids.begin(), + leg_geometry.osm_node_ids.end(), + [this, &nodes](const OSMNodeID &node_id) { + nodes.values.push_back(static_cast(node_id)); + }); util::json::Object annotation; annotation.values["distance"] = std::move(distances); annotation.values["duration"] = std::move(durations); + annotation.values["nodes"] = std::move(nodes); annotations.push_back(std::move(annotation)); } } diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index 411f4c311..22b8ad169 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -67,6 +67,7 @@ class BaseDataFacade // node and edge information access virtual util::Coordinate GetCoordinateOfNode(const unsigned id) const = 0; + virtual OSMNodeID GetOSMNodeIDOfNode(const unsigned id) const = 0; virtual unsigned GetGeometryIndexForEdgeID(const unsigned id) const = 0; diff --git a/include/engine/datafacade/internal_datafacade.hpp b/include/engine/datafacade/internal_datafacade.hpp index c6c341a30..00d7dbc42 100644 --- a/include/engine/datafacade/internal_datafacade.hpp +++ b/include/engine/datafacade/internal_datafacade.hpp @@ -73,6 +73,7 @@ class InternalDataFacade final : public BaseDataFacade std::string m_timestamp; util::ShM::vector m_coordinate_list; + util::ShM::vector m_osmnodeid_list; util::ShM::vector m_via_node_list; util::ShM::vector m_name_ID_list; util::ShM::vector m_turn_instruction_list; @@ -156,10 +157,12 @@ class InternalDataFacade final : public BaseDataFacade unsigned number_of_coordinates = 0; nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned)); m_coordinate_list.resize(number_of_coordinates); + m_osmnodeid_list.resize(number_of_coordinates); for (unsigned i = 0; i < number_of_coordinates; ++i) { nodes_input_stream.read((char *)¤t_node, sizeof(extractor::QueryNode)); m_coordinate_list[i] = util::Coordinate(current_node.lon, current_node.lat); + m_osmnodeid_list[i] = current_node.node_id; BOOST_ASSERT(m_coordinate_list[i].IsValid()); } @@ -438,6 +441,11 @@ class InternalDataFacade final : public BaseDataFacade return m_coordinate_list[id]; } + OSMNodeID GetOSMNodeIDOfNode(const unsigned id) const override final + { + return m_osmnodeid_list[id]; + } + extractor::guidance::TurnInstruction GetTurnInstructionForEdgeID(const unsigned id) const override final { diff --git a/include/engine/datafacade/shared_datafacade.hpp b/include/engine/datafacade/shared_datafacade.hpp index 28ec34b6b..ae5ac425d 100644 --- a/include/engine/datafacade/shared_datafacade.hpp +++ b/include/engine/datafacade/shared_datafacade.hpp @@ -76,6 +76,7 @@ class SharedDataFacade final : public BaseDataFacade extractor::ProfileProperties *m_profile_properties; util::ShM::vector m_coordinate_list; + util::ShM::vector m_osmnodeid_list; util::ShM::vector m_via_node_list; util::ShM::vector m_name_ID_list; util::ShM::vector m_turn_instruction_list; @@ -170,6 +171,11 @@ class SharedDataFacade final : public BaseDataFacade coordinate_list_ptr, data_layout->num_entries[storage::SharedDataLayout::COORDINATE_LIST]); + auto osmnodeid_list_ptr = data_layout->GetBlockPtr( + shared_memory, storage::SharedDataLayout::OSM_NODE_ID_LIST); + m_osmnodeid_list.reset(osmnodeid_list_ptr, + data_layout->num_entries[storage::SharedDataLayout::OSM_NODE_ID_LIST]); + auto travel_mode_list_ptr = data_layout->GetBlockPtr( shared_memory, storage::SharedDataLayout::TRAVEL_MODE); util::ShM::vector travel_mode_list( @@ -471,6 +477,11 @@ class SharedDataFacade final : public BaseDataFacade return m_coordinate_list[id]; } + OSMNodeID GetOSMNodeIDOfNode(const unsigned id) const override final + { + return m_osmnodeid_list[id]; + } + virtual void GetUncompressedGeometry(const EdgeID id, std::vector &result_nodes) const override final { diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index 163044a8f..1c2b5886e 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -43,6 +43,13 @@ LegGeometry assembleGeometry(const DataFacadeT &facade, geometry.segment_offsets.push_back(0); geometry.locations.push_back(source_node.location); + // Need to get the node ID preceding the source phantom node + // TODO: check if this was traversed in reverse? + std::vector reverse_geometry; + facade.GetUncompressedGeometry(source_node.reverse_packed_geometry_id, reverse_geometry); + geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode( + reverse_geometry[reverse_geometry.size() - source_node.fwd_segment_position - 1])); + auto cumulative_distance = 0.; auto current_distance = 0.; auto prev_coordinate = geometry.locations.front(); @@ -65,6 +72,7 @@ LegGeometry assembleGeometry(const DataFacadeT &facade, geometry.annotations.emplace_back( LegGeometry::Annotation{current_distance, path_point.duration_until_turn / 10.}); geometry.locations.push_back(std::move(coordinate)); + geometry.osm_node_ids.push_back(facade.GetOSMNodeIDOfNode(path_point.turn_via_node)); } current_distance = util::coordinate_calculation::haversineDistance(prev_coordinate, target_node.location); @@ -76,6 +84,13 @@ LegGeometry assembleGeometry(const DataFacadeT &facade, geometry.segment_offsets.push_back(geometry.locations.size()); geometry.locations.push_back(target_node.location); + // Need to get the node ID following the destination phantom node + // TODO: check if this was traversed in reverse?? + std::vector forward_geometry; + facade.GetUncompressedGeometry(target_node.forward_packed_geometry_id, forward_geometry); + geometry.osm_node_ids.push_back( + facade.GetOSMNodeIDOfNode(forward_geometry[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()); BOOST_ASSERT(geometry.annotations.size() == geometry.locations.size() - 1); diff --git a/include/engine/guidance/leg_geometry.hpp b/include/engine/guidance/leg_geometry.hpp index d06088aaf..72b0e6570 100644 --- a/include/engine/guidance/leg_geometry.hpp +++ b/include/engine/guidance/leg_geometry.hpp @@ -3,6 +3,7 @@ #include "util/coordinate.hpp" #include "util/integer_range.hpp" +#include "util/typedefs.hpp" #include @@ -30,6 +31,8 @@ struct LegGeometry std::vector segment_offsets; // length of the segment in meters std::vector segment_distances; + // original OSM node IDs for each coordinate + std::vector osm_node_ids; // Per-coordinate metadata struct Annotation diff --git a/include/storage/shared_datatype.hpp b/include/storage/shared_datatype.hpp index 5528a5adb..866fc369a 100644 --- a/include/storage/shared_datatype.hpp +++ b/include/storage/shared_datatype.hpp @@ -28,6 +28,7 @@ struct SharedDataLayout GRAPH_NODE_LIST, GRAPH_EDGE_LIST, COORDINATE_LIST, + OSM_NODE_ID_LIST, TURN_INSTRUCTION, ENTRY_CLASSID, TRAVEL_MODE, diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index 9ea4b8bfa..564904492 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -729,6 +729,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) // fixup the coordinate geometry.locations.erase(geometry.locations.begin()); geometry.annotations.erase(geometry.annotations.begin()); + geometry.osm_node_ids.erase(geometry.osm_node_ids.begin()); // remove the initial distance value geometry.segment_distances.erase(geometry.segment_distances.begin()); @@ -818,6 +819,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) { geometry.locations.pop_back(); geometry.annotations.pop_back(); + geometry.osm_node_ids.pop_back(); geometry.segment_offsets.pop_back(); BOOST_ASSERT(geometry.segment_distances.back() < 1); geometry.segment_distances.pop_back(); diff --git a/src/storage/storage.cpp b/src/storage/storage.cpp index 55e76ccb3..c655a629f 100644 --- a/src/storage/storage.cpp +++ b/src/storage/storage.cpp @@ -244,6 +244,9 @@ int Storage::Run() nodes_input_stream.read((char *)&coordinate_list_size, sizeof(unsigned)); shared_layout_ptr->SetBlockSize(SharedDataLayout::COORDINATE_LIST, coordinate_list_size); + // we'll read a list of OSM node IDs from the same data, so set the same block size: + shared_layout_ptr->SetBlockSize(SharedDataLayout::OSM_NODE_ID_LIST, + coordinate_list_size); // load geometries sizes boost::filesystem::ifstream geometry_input_stream(config.geometries_path, std::ios::binary); @@ -535,12 +538,15 @@ int Storage::Run() // Loading list of coordinates util::Coordinate *coordinates_ptr = shared_layout_ptr->GetBlockPtr( shared_memory_ptr, SharedDataLayout::COORDINATE_LIST); + OSMNodeID *osmnodeid_ptr = shared_layout_ptr->GetBlockPtr( + shared_memory_ptr, SharedDataLayout::OSM_NODE_ID_LIST); extractor::QueryNode current_node; for (unsigned i = 0; i < coordinate_list_size; ++i) { nodes_input_stream.read((char *)¤t_node, sizeof(extractor::QueryNode)); coordinates_ptr[i] = util::Coordinate(current_node.lon, current_node.lat); + osmnodeid_ptr[i] = OSMNodeID(current_node.node_id); } nodes_input_stream.close(); diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 230e782a6..b6915529a 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -50,6 +50,10 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade { return {util::FixedLongitude{0}, util::FixedLatitude{0}}; } + OSMNodeID GetOSMNodeIDOfNode(const unsigned /* id */) const override + { + return OSMNodeID{0}; + } bool EdgeIsCompressed(const unsigned /* id */) const { return false; } unsigned GetGeometryIndexForEdgeID(const unsigned /* id */) const override {