diff --git a/docs/http.md b/docs/http.md index 58d0cd6ef..18dcaae5e 100644 --- a/docs/http.md +++ b/docs/http.md @@ -700,7 +700,7 @@ Annotation of the whole route leg with fine-grained information about each segme - `duration`: The duration between each pair of coordinates, in seconds. Does not include the duration of any turns. - `datasources`: The index of the datasource for the speed between each pair of coordinates. `0` is the default profile, other values are supplied via `--segment-speed-file` to `osrm-contract` or `osrm-customize`. String-like names are in the `metadata.datasource_names` array. - `nodes`: The OSM node ID for each coordinate along the route, excluding the first/last user-supplied coordinates -- `ways`: The OSM way ID for each pair of neighbour nodes in the list of nodes +- `ways`: The OSM way ID for each pair of neighbor nodes in the list of nodes, with a sign. The sign means direction. A positive sign means moving in the direction of the way, while negative means moving in the opposite direction. - `weight`: The weights between each pair of coordinates. Does not include any turn costs. - `speed`: Convenience field, calculation of `distance / duration` rounded to one decimal place - `metadata`: Metadata related to other annotations @@ -715,7 +715,7 @@ Annotation of the whole route leg with fine-grained information about each segme "datasources": [1,0,0,0,1], "metadata": { "datasource_names": ["traffic","lua profile","lua profile","lua profile","traffic"] }, "nodes": [49772551,49772552,49786799,49786800,49786801,49786802], - "ways": [130764281,130764281,6056749,6056749,6056749], + "ways": [130764281,130764281,-6056749,-6056749,-6056749], "weight": [15,15,40,15,15] } ``` diff --git a/include/engine/api/flatbuffers/fbresult_generated.h b/include/engine/api/flatbuffers/fbresult_generated.h index ce09bf4d6..a71d1ef7e 100644 --- a/include/engine/api/flatbuffers/fbresult_generated.h +++ b/include/engine/api/flatbuffers/fbresult_generated.h @@ -462,7 +462,7 @@ struct AnnotationT : public flatbuffers::NativeTable { std::vector duration; std::vector datasources; std::vector nodes; - std::vector ways; + std::vector ways; std::vector weight; std::vector speed; std::unique_ptr metadata; @@ -494,8 +494,8 @@ 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 *ways() const { + return GetPointer *>(VT_WAYS); } const flatbuffers::Vector *weight() const { return GetPointer *>(VT_WEIGHT); @@ -546,7 +546,7 @@ struct AnnotationBuilder { void add_nodes(flatbuffers::Offset> nodes) { fbb_.AddOffset(Annotation::VT_NODES, nodes); } - void add_ways(flatbuffers::Offset> ways) { + void add_ways(flatbuffers::Offset> ways) { fbb_.AddOffset(Annotation::VT_WAYS, ways); } void add_weight(flatbuffers::Offset> weight) { @@ -576,7 +576,7 @@ inline flatbuffers::Offset CreateAnnotation( flatbuffers::Offset> duration = 0, flatbuffers::Offset> datasources = 0, flatbuffers::Offset> nodes = 0, - flatbuffers::Offset> ways = 0, + flatbuffers::Offset> ways = 0, flatbuffers::Offset> weight = 0, flatbuffers::Offset> speed = 0, flatbuffers::Offset metadata = 0) { @@ -598,7 +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 *ways = nullptr, const std::vector *weight = nullptr, const std::vector *speed = nullptr, flatbuffers::Offset metadata = 0) { @@ -606,7 +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 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( diff --git a/include/engine/api/flatbuffers/route.fbs b/include/engine/api/flatbuffers/route.fbs index 8b1542958..bfd69383d 100644 --- a/include/engine/api/flatbuffers/route.fbs +++ b/include/engine/api/flatbuffers/route.fbs @@ -10,7 +10,7 @@ table Annotation { duration: [uint]; datasources: [uint]; nodes: [ulong]; - ways: [ulong]; + ways: [long]; weight: [uint]; speed: [float]; metadata: Metadata; diff --git a/include/engine/api/route_api.hpp b/include/engine/api/route_api.hpp index 7376e6b0f..dadc12442 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -503,13 +503,13 @@ class RouteAPI : public BaseAPI nodes.emplace_back(static_cast(node_id)); } } - std::vector ways; + 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)); + ways.emplace_back(static_cast(way_id)); } } auto nodes_vector = fb_result.CreateVector(nodes); @@ -849,7 +849,7 @@ class RouteAPI : public BaseAPI 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)); + ways.values.push_back(static_cast(way_id)); } annotation.values["ways"] = std::move(ways); } diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index 839138643..3b5a998f3 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -59,7 +59,9 @@ class BaseDataFacade using OSMWayForwardRange = boost::iterator_range; - using OSMWayReverseRange = boost::reversed_range; + using OSMWayNegateForwardRange = + boost::transformed_range, const OSMWayForwardRange>; + using OSMWayReverseRange = boost::reversed_range; using WeightForwardRange = boost::iterator_range; diff --git a/include/engine/guidance/assemble_geometry.hpp b/include/engine/guidance/assemble_geometry.hpp index a9623c209..b4e5028fb 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -161,10 +161,19 @@ 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)); + if (reversed_target) + { + const auto target_osm_way_ids = facade.GetUncompressedReverseWayIDs(target_geometry_id); + geometry.osm_way_ids.push_back( + target_osm_way_ids(target_osm_way_ids.size() - target_node.fwd_segment_position - 1)); + } + else + { + const auto target_osm_way_ids = facade.GetUncompressedForwardWayIDs(target_geometry_id); + 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 daccff8fc..ebbc056e1 100644 --- a/include/engine/guidance/leg_geometry.hpp +++ b/include/engine/guidance/leg_geometry.hpp @@ -34,7 +34,7 @@ struct LegGeometry // 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; + 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 6c7193dc5..c33fb98c0 100644 --- a/include/engine/internal_route_result.hpp +++ b/include/engine/internal_route_result.hpp @@ -27,7 +27,7 @@ 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; + OSMWayIDDir 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 c4a5007fc..4bd564d21 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -144,7 +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 osm_way_id_vector; std::vector weight_vector; std::vector duration_vector; std::vector datasource_vector; diff --git a/include/extractor/node_based_edge.hpp b/include/extractor/node_based_edge.hpp index 09148422a..6da911f71 100644 --- a/include/extractor/node_based_edge.hpp +++ b/include/extractor/node_based_edge.hpp @@ -20,7 +20,7 @@ namespace extractor // 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; +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 diff --git a/include/extractor/segment_data_container.hpp b/include/extractor/segment_data_container.hpp index 76d3b5c0a..cbb6e8b62 100644 --- a/include/extractor/segment_data_container.hpp +++ b/include/extractor/segment_data_container.hpp @@ -10,10 +10,12 @@ #include #include +#include #include #include +#include #include #include @@ -56,7 +58,7 @@ template class SegmentDataContainerImpl using DirectionalGeometryID = std::uint32_t; using SegmentOffset = std::uint32_t; using SegmentNodeVector = Vector; - using SegmentOSMWayVector = Vector; + using SegmentOSMWayVector = Vector; using SegmentWeightVector = PackedVector; using SegmentDurationVector = PackedVector; using SegmentDatasourceVector = Vector; @@ -102,7 +104,9 @@ template class SegmentDataContainerImpl auto GetReverseOSMWayIDs(const DirectionalGeometryID id) { - return boost::adaptors::reverse(GetForwardOSMWayIDs(id)); + // return boost::adaptors::reverse(GetForwardOSMWayIDs(id)); + return boost::adaptors::reverse( + boost::adaptors::transform(GetForwardOSMWayIDs(id), std::negate())); } auto GetForwardDurations(const DirectionalGeometryID id) @@ -176,7 +180,9 @@ template class SegmentDataContainerImpl auto GetReverseOSMWayIDs(const DirectionalGeometryID id) const { - return boost::adaptors::reverse(GetForwardOSMWayIDs(id)); + // return boost::adaptors::reverse(GetForwardOSMWayIDs(id)); + return boost::adaptors::reverse( + boost::adaptors::transform(GetForwardOSMWayIDs(id), std::negate())); } auto GetForwardDurations(const DirectionalGeometryID id) const diff --git a/include/storage/view_factory.hpp b/include/storage/view_factory.hpp index 6780a68a2..ef188b08e 100644 --- a/include/storage/view_factory.hpp +++ b/include/storage/view_factory.hpp @@ -134,7 +134,7 @@ inline auto make_segment_data_view(const SharedDataIndex &index, const std::stri auto num_entries = index.GetBlockEntries(name + "/nodes"); - auto osm_way_list = make_vector_view(index, name + "/osm_ways"); + auto osm_way_list = make_vector_view(index, name + "/osm_ways"); extractor::SegmentDataView::SegmentWeightVector fwd_weight_list( make_vector_view( diff --git a/include/util/typedefs.hpp b/include/util/typedefs.hpp index b3e5a8d46..4b9478e0c 100644 --- a/include/util/typedefs.hpp +++ b/include/util/typedefs.hpp @@ -53,6 +53,7 @@ using OSMNodeID = osrm::Alias; static_assert(std::is_pod(), "OSMNodeID is not a valid alias"); using OSMWayID = osrm::Alias; static_assert(std::is_pod(), "OSMWayID is not a valid alias"); +using OSMWayIDDir = std::int64_t; using DuplicatedNodeID = std::uint64_t; using RestrictionID = std::uint64_t; diff --git a/src/extractor/compressed_edge_container.cpp b/src/extractor/compressed_edge_container.cpp index 92db95896..6c5f9e13b 100644 --- a/src/extractor/compressed_edge_container.cpp +++ b/src/extractor/compressed_edge_container.cpp @@ -282,7 +282,7 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const auto &first_node = reverse_bucket.back(); auto prev_node_id = first_node.node_id; - auto osm_way_id = SPECIAL_OSM_WAYID; + OSMWayIDDir osm_way_id = 0; constexpr DatasourceID LUA_SOURCE = 0; segment_data->nodes.emplace_back(first_node.node_id); @@ -304,21 +304,19 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_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()) + if (find_way_id != osm_way_id_map.cend()) { - find_way_id = osm_way_id_map.find(OSMWayIDMapKey(node_id, prev_node_id)); + segment_data->osm_ways.emplace_back(osm_way_id = find_way_id->second); + util::Log(logDEBUG) << "zipped_geometry_id: " << zipped_geometry_id << " " + << prev_node_id << "->" << node_id << " = " << osm_way_id; } - if (find_way_id == osm_way_id_map.cend()) + else { 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 { @@ -341,21 +339,19 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_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()) + if (find_way_id != osm_way_id_map.cend()) { - find_way_id = osm_way_id_map.find(OSMWayIDMapKey(node_id, prev_node_id)); + segment_data->osm_ways.emplace_back(osm_way_id = find_way_id->second); + util::Log(logDEBUG) << "zipped_geometry_id: " << zipped_geometry_id << " " + << prev_node_id << "->" << node_id << " = " << osm_way_id; } - if (find_way_id == osm_way_id_map.cend()) + else { 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 { diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp index eb9b6829f..e5942e41e 100644 --- a/src/extractor/extractor.cpp +++ b/src/extractor/extractor.cpp @@ -635,8 +635,32 @@ Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment, // 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; + OSMWayIDDir way_id = edge.result.osm_way_id.__value; + OSMNodeID osm_source_id = edge.result.osm_source_id; + OSMNodeID osm_target_id = edge.result.osm_target_id; + if ((edge.result.source < edge.result.target && osm_source_id > osm_target_id) || + (edge.result.source > edge.result.target && osm_source_id < osm_target_id)) + { + // Bogus criteria? + way_id = -way_id; + std::swap(osm_source_id, osm_target_id); + } + if (edge.result.flags.forward) + { + osm_way_id_map[OSMWayIDMapKey(edge.result.source, edge.result.target)] = way_id; + util::Log(logDEBUG) + << "osm_way_id_map: " << edge.result.source << "->" << edge.result.target << " = " + << osm_way_id_map[OSMWayIDMapKey(edge.result.source, edge.result.target)] << " (" + << osm_source_id << "->" << osm_target_id << ")"; + } + if (edge.result.flags.backward) + { + osm_way_id_map[OSMWayIDMapKey(edge.result.target, edge.result.source)] = -way_id; + util::Log(logDEBUG) + << "osm_way_id_map: " << edge.result.target << "->" << edge.result.source << " = " + << osm_way_id_map[OSMWayIDMapKey(edge.result.target, edge.result.source)] << " (" + << osm_target_id << "->" << osm_source_id << ")"; + } } TIMER_STOP(extracting); diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp index 75444061a..dd9e0c1ce 100644 --- a/unit_tests/library/route.cpp +++ b/unit_tests/library/route.cpp @@ -602,7 +602,7 @@ BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_new_api) } using NodePair = std::pair; -using NodePairToWayIDMap = std::map; +using NodePairToWayIDMap = std::map; NodePairToWayIDMap read_node_pair_to_way_id_map(osmium::io::Reader &osm) { @@ -611,11 +611,11 @@ NodePairToWayIDMap read_node_pair_to_way_id_map(osmium::io::Reader &osm) NodePairToWayIDMap ret; void way(const osmium::Way &way) { - auto first = osmium::unsigned_object_id_type(-1); + osmium::unsigned_object_id_type first = 0; for (const auto &n : way.nodes()) { const auto second = n.positive_ref(); - if (first != osmium::unsigned_object_id_type(-1)) + if (first != 0) { ret[{first, second}] = way.id(); } @@ -700,15 +700,20 @@ LonLatVector check_route_annotated_ways(std::vector &coo for (nodes_it++; nodes_it != nodes.cend(); nodes_it++, ways_it++) { osmium::unsigned_object_id_type second = nodes_it->get().value; - osmium::unsigned_object_id_type way_id = ways_it->get().value; + int64_t way_id = ways_it->get().value; auto found = node_pair_to_way_id_map.find(NodePair(first, second)); + auto reverse = false; if (found == node_pair_to_way_id_map.end()) + { + reverse = true; found = node_pair_to_way_id_map.find(NodePair(second, first)); + } BOOST_CHECK_MESSAGE(found != node_pair_to_way_id_map.end(), "The node pair not found: " << first << "<->" << second); - BOOST_CHECK_MESSAGE(found->second == way_id, + int64_t found_way_id = reverse ? -found->second : found->second; + BOOST_CHECK_MESSAGE(found_way_id == way_id, "The node pair way doesn't correspond: " << first << "<->" << second - << "=" << found->second + << "=" << found_way_id << "=?=" << way_id); first = second; } diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 2270bfffd..dad8162f7 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -66,7 +66,7 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade } OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID /* id */) const override { - static OSMWayID data[] = {0, 1, 2, 3}; + static OSMWayIDDir data[] = {0, 1, 2, 3}; static extractor::SegmentDataView::SegmentOSMWayVector ways(data, 4); return boost::make_iterator_range(ways.cbegin(), ways.cend()); }