diff --git a/CHANGELOG.md b/CHANGELOG.md index 0132794d603..52aa7880965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Unreleased - Changes from 5.24.0 + - Features: + - ADDED: a new `ways` subsection in the `annotations` section containing way IDs along the found path, with sign meaning direction [#5325](https://github.com/Project-OSRM/osrm-backend/issues/5325) + - API: + - FIXED: item type for `nodes` section of the `annotations` flatbuffers output format [#5970](https://github.com/Project-OSRM/osrm-backend/issues/5970) - Misc: - FIXED: Upgrade to @mapbox/node-pre-gyp fix various bugs with Node 12/14 [#5991](https://github.com/Project-OSRM/osrm-backend/pull/5991) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6feb6de9aa..857b77b4ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -242,7 +242,7 @@ endif() if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ggdb") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -ggdb") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ggdb") endif() diff --git a/docs/http.md b/docs/http.md index 398aba1aecf..18dcaae5ef5 100644 --- a/docs/http.md +++ b/docs/http.md @@ -208,7 +208,7 @@ In addition to the [general options](#general-options) the following options are |------------|---------------------------------------------|-------------------------------------------------------------------------------| |alternatives|`true`, `false` (default), or Number |Search for alternative routes. Passing a number `alternatives=n` searches for up to `n` alternative routes.\* | |steps |`true`, `false` (default) |Returned route steps for each route leg | -|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | +|annotations |`true`, `false` (default), `nodes`, `ways`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |continue\_straight |`default` (default), `true`, `false` |Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. Default value depends on the profile. | @@ -430,7 +430,7 @@ In addition to the [general options](#general-options) the following options are |------------|------------------------------------------------|------------------------------------------------------------------------------------------| |steps |`true`, `false` (default) |Returned route steps for each route | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | -|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | +|annotations |`true`, `false` (default), `nodes`, `ways`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| |timestamps |`{timestamp};{timestamp}[;{timestamp} ...]` |Timestamps for the input locations in seconds since UNIX epoch. Timestamps need to be monotonically increasing. | |radiuses |`{radius};{radius}[;{radius} ...]` |Standard deviation of GPS precision used for map matching. If applicable use GPS accuracy.| @@ -486,7 +486,7 @@ In addition to the [general options](#general-options) the following options are |source |`any` (default), `first` |Returned route starts at `any` or `first` coordinate | |destination |`any` (default), `last` |Returned route ends at `any` or `last` coordinate | |steps |`true`, `false` (default) |Returned route instructions for each trip | -|annotations |`true`, `false` (default), `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | +|annotations |`true`, `false` (default), `nodes`, `ways`, `distance`, `duration`, `datasources`, `weight`, `speed` |Returns additional metadata for each coordinate along the route geometry. | |geometries |`polyline` (default), `polyline6`, `geojson` |Returned route geometry format (influences overview and per step) | |overview |`simplified` (default), `full`, `false` |Add overview geometry either full, simplified according to highest zoom level it could be display on, or not at all.| @@ -700,6 +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 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 @@ -714,6 +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], "weight": [15,15,40,15,15] } ``` diff --git a/docs/nodejs/api.md b/docs/nodejs/api.md index 9bff3ada8c6..a06ed047067 100644 --- a/docs/nodejs/api.md +++ b/docs/nodejs/api.md @@ -55,7 +55,7 @@ Returns the fastest route between two or more coordinates while visiting the way - `options.alternatives` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** Search for up to this many alternative routes. _Please note that even if alternative routes are requested, a result cannot be guaranteed._ (optional, default `0`) - `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route leg. (optional, default `false`) - - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) + - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `ways`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) - `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`) - `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`) - `options.continue_straight` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile. @@ -215,7 +215,7 @@ if they can not be matched successfully. - `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings. - `options.generate_hints` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Whether or not adds a Hint to the response which can be used in subsequent requests. (optional, default `true`) - `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`) - - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) + - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `ways`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) - `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`) - `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`) - `options.timestamps` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)>?** Timestamp of the input location (integers, UNIX-like timestamp). @@ -282,7 +282,7 @@ Right now, the following combinations are possible: - `options.hints` **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Hints for the coordinate snapping. Array of base64 encoded strings. - `options.generate_hints` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Whether or not adds a Hint to the response which can be used in subsequent requests. (optional, default `true`) - `options.steps` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route steps for each route. (optional, default `false`) - - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) + - `options.annotations` **([Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** An array with strings of `duration`, `nodes`, `ways`, `distance`, `weight`, `datasources`, `speed` or boolean for enabling/disabling all. (optional, default `false`) - `options.geometries` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`) - `options.overview` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` (optional, default `simplified`) - `options.roundtrip` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`) diff --git a/include/engine/api/flatbuffers/compile.sh b/include/engine/api/flatbuffers/compile.sh new file mode 100755 index 00000000000..b743be66568 --- /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 f3f05de4a2c..a71d1ef7e1d 100644 --- a/include/engine/api/flatbuffers/fbresult_generated.h +++ b/include/engine/api/flatbuffers/fbresult_generated.h @@ -461,7 +461,8 @@ struct AnnotationT : public flatbuffers::NativeTable { std::vector distance; std::vector duration; std::vector datasources; - std::vector nodes; + 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); @@ -489,8 +491,11 @@ struct Annotation FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector *datasources() const { return GetPointer *>(VT_DATASOURCES); } - const flatbuffers::Vector *nodes() const { - return GetPointer *>(VT_NODES); + 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) && @@ -536,9 +543,12 @@ struct AnnotationBuilder { void add_datasources(flatbuffers::Offset> datasources) { fbb_.AddOffset(Annotation::VT_DATASOURCES, datasources); } - void add_nodes(flatbuffers::Offset> nodes) { + 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); } @@ -565,7 +575,8 @@ inline flatbuffers::Offset CreateAnnotation( flatbuffers::Offset> distance = 0, flatbuffers::Offset> duration = 0, flatbuffers::Offset> datasources = 0, - flatbuffers::Offset> nodes = 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); @@ -585,14 +597,16 @@ inline flatbuffers::Offset CreateAnnotationDirect( const std::vector *distance = nullptr, const std::vector *duration = nullptr, const std::vector *datasources = nullptr, - const std::vector *nodes = 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) { auto distance__ = distance ? _fbb.CreateVector(*distance) : 0; auto duration__ = duration ? _fbb.CreateVector(*duration) : 0; auto datasources__ = datasources ? _fbb.CreateVector(*datasources) : 0; - auto nodes__ = nodes ? _fbb.CreateVector(*nodes) : 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 902bfa1990b..bfd69383d66 100644 --- a/include/engine/api/flatbuffers/route.fbs +++ b/include/engine/api/flatbuffers/route.fbs @@ -9,7 +9,8 @@ table Annotation { distance: [uint]; duration: [uint]; datasources: [uint]; - nodes: [uint]; + nodes: [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 4990d37c974..aa4a7610e11 100644 --- a/include/engine/api/route_api.hpp +++ b/include/engine/api/route_api.hpp @@ -494,7 +494,7 @@ class RouteAPI : public BaseAPI return anno.datasource; }); } - std::vector nodes; + std::vector nodes; if (requested_annotations & RouteParameters::AnnotationsType::Nodes) { nodes.reserve(leg_geometry.osm_node_ids.size()); @@ -503,7 +503,18 @@ class RouteAPI : public BaseAPI nodes.emplace_back(static_cast(node_id)); } } + std::vector ways; + if (requested_annotations & RouteParameters::AnnotationsType::Ways && + leg_geometry.osm_way_ids.size()) + { + 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 +540,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 +844,17 @@ class RouteAPI : public BaseAPI } annotation.values["nodes"] = std::move(nodes); } + if (requested_annotations & RouteParameters::AnnotationsType::Ways && + leg_geometry.osm_way_ids.size()) + { + 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 8d5dd9ae46c..052b7c436c6 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 9886783312c..ee0e7bf4e4b 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -251,6 +251,19 @@ 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); + } + bool GetUncompressedWayIDsSkipped() const override final + { + return segment_data.GetOSMWaysSkipped(); + } + 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 b80c93b1879..a5199c90154 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -57,6 +57,12 @@ class BaseDataFacade boost::iterator_range; using NodeReverseRange = boost::reversed_range; + using OSMWayForwardRange = + boost::iterator_range; + using OSMWayNegateForwardRange = + boost::transformed_range, const OSMWayForwardRange>; + using OSMWayReverseRange = boost::reversed_range; + using WeightForwardRange = boost::iterator_range; using WeightReverseRange = boost::reversed_range; @@ -85,6 +91,10 @@ 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 bool GetUncompressedWayIDsSkipped() 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 9e3a0deafc5..1bc09c5135e 100644 --- a/include/engine/guidance/assemble_geometry.hpp +++ b/include/engine/guidance/assemble_geometry.hpp @@ -100,6 +100,8 @@ 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); + if (!facade.GetUncompressedWayIDsSkipped()) + geometry.osm_way_ids.push_back(path_point.osm_way_id); } } current_distance = @@ -160,7 +162,20 @@ inline LegGeometry assembleGeometry(const datafacade::BaseDataFacade &facade, const auto target_geometry = facade.GetUncompressedForwardGeometry(target_geometry_id); geometry.osm_node_ids.push_back( facade.GetOSMNodeIDOfNode(target_geometry(target_segment_end_coordinate))); - + if (!facade.GetUncompressedWayIDsSkipped()) + { + 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()); 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 8374bb99261..ebbc056e13f 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 9f5443ffa0f..c33fb98c022 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 + 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 ee564afe207..e9f57398293 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)); @@ -189,6 +194,7 @@ void annotatePath(const FacadeT &facade, BOOST_ASSERT(datasource_vector.size() > 0); BOOST_ASSERT(weight_vector.size() + 1 == id_vector.size()); BOOST_ASSERT(duration_vector.size() + 1 == id_vector.size()); + BOOST_ASSERT(!osm_way_id_vector.size() || osm_way_id_vector.size() + 1 == id_vector.size()); const bool is_first_segment = unpacked_path.empty(); @@ -213,6 +219,7 @@ void annotatePath(const FacadeT &facade, { unpacked_path.push_back( PathData{*node_from, + osm_way_id_vector.size() ? osm_way_id_vector[segment_idx] : 0, id_vector[segment_idx + 1], name_index, is_segregated, @@ -288,6 +295,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.size() ? osm_way_id_vector[segment_idx] : 0, 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 ec9e1f9eaef..597658f754e 100644 --- a/include/extractor/compressed_edge_container.hpp +++ b/include/extractor/compressed_edge_container.hpp @@ -1,6 +1,7 @@ #ifndef GEOMETRY_COMPRESSOR_HPP_ #define GEOMETRY_COMPRESSOR_HPP_ +#include "extractor/node_based_edge.hpp" #include "extractor/segment_data_container.hpp" #include "util/typedefs.hpp" @@ -48,7 +49,9 @@ 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, + const 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 070a3b4ef59..441a4a75482 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 9939a49631c..4b0534c1fb7 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" diff --git a/include/extractor/extractor_config.hpp b/include/extractor/extractor_config.hpp index b3822d587ce..da90abdd310 100644 --- a/include/extractor/extractor_config.hpp +++ b/include/extractor/extractor_config.hpp @@ -70,7 +70,8 @@ struct ExtractorConfig final : storage::IOConfig ".osrm.cnbg", ".osrm.cnbg_to_ebg", ".osrm.maneuver_overrides"}), - requested_num_threads(0), parse_conditionals(false), use_locations_cache(true) + requested_num_threads(0), parse_conditionals(false), use_locations_cache(true), + skip_osm_ways(false) { } @@ -92,6 +93,7 @@ struct ExtractorConfig final : storage::IOConfig bool use_metadata; bool parse_conditionals; bool use_locations_cache; + bool skip_osm_ways; }; } // namespace extractor } // namespace osrm diff --git a/include/extractor/files.hpp b/include/extractor/files.hpp index 6c0445e9b45..b71d97edbaa 100644 --- a/include/extractor/files.hpp +++ b/include/extractor/files.hpp @@ -206,7 +206,9 @@ inline void readSegmentData(const boost::filesystem::path &path, SegmentDataT &s // writes .osrm.geometry template -inline void writeSegmentData(const boost::filesystem::path &path, const SegmentDataT &segment_data) +inline void writeSegmentData(const boost::filesystem::path &path, + bool skip_osm_ways, + const SegmentDataT &segment_data) { static_assert(std::is_same::value || std::is_same::value, @@ -214,7 +216,7 @@ inline void writeSegmentData(const boost::filesystem::path &path, const SegmentD const auto fingerprint = storage::tar::FileWriter::GenerateFingerprint; storage::tar::FileWriter writer{path, fingerprint}; - serialization::write(writer, "/common/segment_data", segment_data); + serialization::write(writer, "/common/segment_data", skip_osm_ways, segment_data); } // reads .osrm.ebg_nodes diff --git a/include/extractor/internal_extractor_edge.hpp b/include/extractor/internal_extractor_edge.hpp index c7ee904d937..5000352bb49 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 84a03d0a09b..6da911f7129 100644 --- a/include/extractor/node_based_edge.hpp +++ b/include/extractor/node_based_edge.hpp @@ -2,6 +2,7 @@ #define NODE_BASED_EDGE_HPP #include +#include #include #include "extractor/class_data.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 e3fc395839e..02c781052ac 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(const 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 580c018ed75..e05e9f78e82 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 @@ -38,6 +40,7 @@ inline void read(storage::tar::FileReader &reader, template inline void write(storage::tar::FileWriter &writer, const std::string &name, + const bool skip_osm_ways, const detail::SegmentDataContainerImpl &segment_data); } // namespace serialization @@ -56,6 +59,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 +68,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 +95,20 @@ 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( + boost::adaptors::transform(GetForwardOSMWayIDs(id), std::negate())); + } + auto GetForwardDurations(const DirectionalGeometryID id) { const auto begin = fwd_durations.begin() + index[id] + 1; @@ -151,6 +170,22 @@ template class SegmentDataContainerImpl return boost::adaptors::reverse(GetForwardGeometry(id)); } + auto GetForwardOSMWayIDs(const DirectionalGeometryID id) const + { + if (GetOSMWaysSkipped()) + return boost::make_iterator_range(osm_ways.cend(), osm_ways.cend()); + 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( + boost::adaptors::transform(GetForwardOSMWayIDs(id), std::negate())); + } + auto GetForwardDurations(const DirectionalGeometryID id) const { const auto begin = fwd_durations.cbegin() + index[id] + 1; @@ -201,6 +236,7 @@ template class SegmentDataContainerImpl auto GetNumberOfGeometries() const { return index.size() - 1; } auto GetNumberOfSegments() const { return fwd_weights.size(); } + auto GetOSMWaysSkipped() const { return osm_ways.size() == 0; } friend void serialization::read(storage::tar::FileReader &reader, @@ -209,11 +245,13 @@ template class SegmentDataContainerImpl friend void serialization::write( storage::tar::FileWriter &writer, const std::string &name, + const bool skip_osm_ways, const detail::SegmentDataContainerImpl &segment_data); 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 363dd9c168e..ddd3090a3d7 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); @@ -97,10 +98,18 @@ inline void read(storage::tar::FileReader &reader, template inline void write(storage::tar::FileWriter &writer, const std::string &name, + const bool skip_osm_ways, const detail::SegmentDataContainerImpl &segment_data) { storage::serialization::write(writer, name + "/index", segment_data.index); storage::serialization::write(writer, name + "/nodes", segment_data.nodes); + if (!skip_osm_ways) + storage::serialization::write(writer, name + "/osm_ways", segment_data.osm_ways); + else + storage::serialization::write( + writer, + name + "/osm_ways", + osrm::util::ViewOrVector()); 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 400d420a52b..cafae9a5d61 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 df5fb52df2d..653ed5df750 100644 --- a/include/server/api/route_parameters_grammar.hpp +++ b/include/server/api/route_parameters_grammar.hpp @@ -73,8 +73,8 @@ 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/include/util/typedefs.hpp b/include/util/typedefs.hpp index b3e5a8d461b..4b9478e0c36 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/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index b5a28047210..34171fd5fc6 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -281,6 +281,8 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.annotations.begin() + offset); geometry.osm_node_ids.erase(geometry.osm_node_ids.begin(), geometry.osm_node_ids.begin() + offset); + geometry.osm_way_ids.erase(geometry.osm_way_ids.begin(), + geometry.osm_way_ids.begin() + offset); } auto const first_bearing = steps.front().maneuver.bearing_after; @@ -378,6 +380,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.locations.resize(geometry.segment_offsets.back() + 1); geometry.annotations.resize(geometry.segment_offsets.back()); geometry.osm_node_ids.resize(geometry.segment_offsets.back() + 1); + geometry.osm_way_ids.resize(geometry.segment_offsets.back()); BOOST_ASSERT(geometry.segment_distances.back() <= 1); geometry.segment_distances.pop_back(); @@ -415,6 +418,7 @@ void trimShortSegments(std::vector &steps, LegGeometry &geometry) geometry.locations.pop_back(); geometry.annotations.pop_back(); geometry.osm_node_ids.pop_back(); + geometry.osm_way_ids.pop_back(); geometry.segment_offsets.back()--; // since the last geometry includes the location of arrival, the arrival instruction // geometry overlaps with the previous segment diff --git a/src/extractor/compressed_edge_container.cpp b/src/extractor/compressed_edge_container.cpp index 7510f85b04e..e3796448944 100644 --- a/src/extractor/compressed_edge_container.cpp +++ b/src/extractor/compressed_edge_container.cpp @@ -262,7 +262,9 @@ 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, + const OSMWayIDMap &osm_way_id_map) { if (!segment_data) InitializeBothwayVector(); @@ -279,7 +281,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; + OSMWayIDDir osm_way_id = 0; constexpr DatasourceID LUA_SOURCE = 0; segment_data->nodes.emplace_back(first_node.node_id); @@ -290,6 +293,31 @@ unsigned CompressedEdgeContainer::ZipEdges(const EdgeID f_edge_id, const EdgeID segment_data->fwd_datasources.emplace_back(LUA_SOURCE); segment_data->rev_datasources.emplace_back(LUA_SOURCE); + auto store_way_id = [&](const NodeID prev_node_id, const NodeID 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()) + { + 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; + } + 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 + { + // Special case (artificial lighting signal edge) + segment_data->osm_ways.emplace_back(osm_way_id); + } + }; + for (std::size_t i = 0; i < forward_bucket.size() - 1; ++i) { const auto &fwd_node = forward_bucket.at(i); @@ -297,6 +325,10 @@ 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; + + store_way_id(prev_node_id, node_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 +336,16 @@ 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; + store_way_id(prev_node_id, node_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 5c5d96a7100..715b796d278 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); @@ -319,6 +321,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment) // 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"), + config.skip_osm_ways, *node_based_graph_factory.GetCompressedEdges().ToSegmentData()); util::Log() << "Saving edge-based node weights to file."; @@ -368,10 +371,12 @@ int Extractor::run(ScriptingEnvironment &scripting_environment) return 0; } -std:: - tuple, std::vector> - Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment, - const unsigned number_of_threads) +std::tuple, + std::vector> +Extractor::ParseOSMData(ScriptingEnvironment &scripting_environment, + const unsigned number_of_threads) { TIMER_START(extracting); @@ -420,6 +425,7 @@ 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, @@ -626,10 +632,42 @@ 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) + { + 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); 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 de7b282193c..35e2f6ec1eb 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -409,6 +409,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 +446,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 51473797d2f..61ee5e5274d 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(const OSMWayIDMap &osm_way_id_map) { for (const auto nbg_node_u : util::irange(0u, compressed_output_graph.GetNumberOfNodes())) { @@ -126,7 +127,8 @@ 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/src/tools/extract.cpp b/src/tools/extract.cpp index 0cd1c7b4f75..7b3073711bb 100644 --- a/src/tools/extract.cpp +++ b/src/tools/extract.cpp @@ -74,7 +74,12 @@ return_code parseArguments(int argc, boost::program_options::bool_switch(&extractor_config.use_locations_cache) ->implicit_value(false) ->default_value(true), - "Use internal nodes locations cache for location-dependent data lookups"); + "Use internal nodes locations cache for location-dependent data lookups")( + "skip-osm-ways", + boost::program_options::bool_switch(&extractor_config.skip_osm_ways) + ->implicit_value(true) + ->default_value(false), + "Skip OSM Way IDs in annotations"); bool dummy; // hidden options, will be allowed on command line, but will not be diff --git a/src/updater/updater.cpp b/src/updater/updater.cpp index 13f10aa2995..c7491560dc3 100644 --- a/src/updater/updater.cpp +++ b/src/updater/updater.cpp @@ -623,7 +623,8 @@ Updater::LoadAndUpdateEdgeExpandedGraph(std::vector &e coordinates, osm_node_ids); // Now save out the updated compressed geometries - extractor::files::writeSegmentData(config.GetPath(".osrm.geometry"), segment_data); + extractor::files::writeSegmentData( + config.GetPath(".osrm.geometry"), segment_data.GetOSMWaysSkipped(), segment_data); TIMER_STOP(segment); util::Log() << "Updating segment data took " << TIMER_MSEC(segment) << "ms."; } diff --git a/unit_tests/engine/collapse_internal_route_result.cpp b/unit_tests/engine/collapse_internal_route_result.cpp index fc989ba5714..52a097b4754 100644 --- a/unit_tests/engine/collapse_internal_route_result.cpp +++ b/unit_tests/engine/collapse_internal_route_result.cpp @@ -19,8 +19,8 @@ BOOST_AUTO_TEST_CASE(unchanged_collapse_route_result) PhantomNode target; source.forward_segment_id = {1, true}; target.forward_segment_id = {6, true}; - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; InternalRouteResult one_leg_result; one_leg_result.unpacked_path_segments = {{pathy, kathy}}; one_leg_result.segment_end_coordinates = {PhantomNodes{source, target}}; @@ -41,9 +41,9 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) // weight_of_turn, // duration_until_turn, duration_of_turn, turn_instruction, lane_data, travel_mode, classes, // entry_class, datasource_id, pre_turn_bearing, post_turn_bearing, left_hand - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData cathy{0, 0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -73,11 +73,11 @@ BOOST_AUTO_TEST_CASE(two_legs_to_one_leg) BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) { - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData qathy{0, 5, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData mathy{0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData qathy{0, 0, 5, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData cathy{0, 0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData mathy{0, 0, 4, 18, false, 8, 9, 13, 4, 2, {}, 4, 2, {}, 2, {3.0}, {1.0}, false}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; @@ -117,9 +117,9 @@ BOOST_AUTO_TEST_CASE(three_legs_to_two_legs) BOOST_AUTO_TEST_CASE(two_legs_to_two_legs) { - PathData pathy{0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; - PathData kathy{0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; - PathData cathy{0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData pathy{0, 0, 2, 17, false, 2, 3, 4, 5, 0, {}, 4, 2, {}, 2, {1.0}, {1.0}, false}; + PathData kathy{0, 0, 1, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; + PathData cathy{0, 0, 3, 16, false, 1, 2, 3, 4, 1, {}, 3, 1, {}, 1, {2.0}, {3.0}, false}; PhantomNode node_1; PhantomNode node_2; PhantomNode node_3; diff --git a/unit_tests/engine/offline_facade.cpp b/unit_tests/engine/offline_facade.cpp index 7c264e17695..394616640e7 100644 --- a/unit_tests/engine/offline_facade.cpp +++ b/unit_tests/engine/offline_facade.cpp @@ -166,6 +166,18 @@ class ContiguousInternalMemoryDataFacade return NodeReverseRange(NodeForwardRange()); } + OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID /*id*/) const override + { + return {}; + } + bool GetUncompressedWayIDsSkipped() const override { return true; } + + OSMWayReverseRange GetUncompressedReverseWayIDs(const EdgeID id) const override + { + return boost::adaptors::reverse(boost::adaptors::transform(GetUncompressedForwardWayIDs(id), + std::negate())); + } + TurnPenalty GetWeightPenaltyForEdgeID(const unsigned /*id*/) const override { return INVALID_TURN_PENALTY; diff --git a/unit_tests/library/route.cpp b/unit_tests/library/route.cpp index 44fcb877b6f..8f112d7903d 100644 --- a/unit_tests/library/route.cpp +++ b/unit_tests/library/route.cpp @@ -14,6 +14,12 @@ #include "osrm/osrm.hpp" #include "osrm/route_parameters.hpp" #include "osrm/status.hpp" +#include +#include +#include +#include +#include +#include osrm::Status run_route_json(const osrm::OSRM &osrm, const osrm::RouteParameters ¶ms, @@ -584,7 +590,7 @@ void test_manual_setting_of_annotations_property(bool use_json_only_api) .values["annotation"] .get() .values; - BOOST_CHECK_EQUAL(annotations.size(), 6); + BOOST_CHECK_EQUAL(annotations.size(), 7); } BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_old_api) { @@ -595,6 +601,158 @@ BOOST_AUTO_TEST_CASE(test_manual_setting_of_annotations_property_new_api) test_manual_setting_of_annotations_property(false); } +using NodePair = std::pair; +using NodePairToWayIDMap = std::map; + +NodePairToWayIDMap read_node_pair_to_way_id_map(osmium::io::Reader &osm) +{ + struct H : public osmium::handler::Handler + { + NodePairToWayIDMap ret; + void way(const osmium::Way &way) + { + osmium::unsigned_object_id_type first = 0; + for (const auto &n : way.nodes()) + { + const auto second = n.positive_ref(); + if (first != 0) + { + ret[{first, second}] = way.id(); + } + first = second; + } + } + } handler; + osmium::apply(osm, handler); + return std::move(handler.ret); +} + +using LonLat = std::pair; +using LonLatVector = std::vector; + +LonLatVector check_route_annotated_ways(std::vector &coordinates, + osrm::OSRM &osrm, + NodePairToWayIDMap &node_pair_to_way_id_map, + bool use_steps) +{ + LonLatVector ret; + using namespace osrm; + (void)node_pair_to_way_id_map; + RouteParameters params{}; + params.annotations_type = + RouteParameters::AnnotationsType::Nodes | RouteParameters::AnnotationsType::Ways; + params.steps = use_steps; + params.geometries = engine::api::RouteParameters::GeometriesType::GeoJSON; + params.coordinates = coordinates; + + json::Object json_result; + const auto rc = run_route_json(osrm, params, json_result, true); + BOOST_CHECK(rc == Status::Ok); + + const auto code = json_result.values.at("code").get().value; + BOOST_CHECK_EQUAL(code, "Ok"); + + auto routes = json_result.values["routes"].get().values; + BOOST_CHECK_EQUAL(routes.size(), 1); + auto route = routes[0]; + + auto geom = route.get() + .values["geometry"] + .get() + .values["coordinates"] + .get() + .values; + + auto legs = route.get().values["legs"].get().values; + for (auto leg : legs) + { + if (use_steps) + { + auto steps = leg.get().values["steps"].get().values; + for (auto step : steps) + { + auto geom = step.get() + .values["geometry"] + .get() + .values["coordinates"] + .get() + .values; + for (auto gleg : geom) + { + auto p = gleg.get().values; + auto lon = p[0].get().value; + auto lat = p[1].get().value; + ret.push_back(LonLat{lon, lat}); + } + } + } + auto annotations = leg.get().values["annotation"].get().values; + BOOST_CHECK_EQUAL(annotations.size(), 2); + + auto nodes = annotations["nodes"].get().values; + auto ways = annotations["ways"].get().values; + + BOOST_CHECK_GT(nodes.size(), 1); + BOOST_CHECK_EQUAL(nodes.size() - 1, ways.size()); + auto nodes_it = nodes.cbegin(); + auto ways_it = ways.cbegin(); + osmium::unsigned_object_id_type first = nodes_it->get().value; + for (nodes_it++; nodes_it != nodes.cend(); nodes_it++, ways_it++) + { + osmium::unsigned_object_id_type second = nodes_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); + 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_way_id + << "=?=" << way_id); + first = second; + } + } + return ret; +} + +BOOST_AUTO_TEST_CASE(test_route_annotated_ways) +{ + auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); + osmium::io::Reader osm(OSRM_TEST_DATA_DIR "/monaco.osm.pbf"); + NodePairToWayIDMap node_pair_to_way_id_map = read_node_pair_to_way_id_map(osm); + + auto coordinates = get_split_trace_locations(); + BOOST_TEST_MESSAGE("split_trace_locations without steps"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, false); + BOOST_TEST_MESSAGE("split_trace_locations with steps"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, true); + coordinates = get_locations_in_big_component(); + BOOST_TEST_MESSAGE("locations_in_big_component without steps"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, false); + BOOST_TEST_MESSAGE("locations_in_big_component with steps"); + auto coords = check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, true); + auto c1 = coords.cbegin(), c2 = coords.cend(); + for (c1++, c2--; c1 != coords.cend() && c2 != coords.cbegin(); c1++, c2--) + { + if (c1 == c2) + continue; + coordinates = Locations{{Longitude{c1->first}, Latitude{c1->second}}, + {Longitude{c2->first}, Latitude{c2->second}}}; + BOOST_TEST_MESSAGE("Checking: <" << osrm::util::toFloating(coordinates[0].lat) << ":" + << osrm::util::toFloating(coordinates[0].lon) << "> -> <" + << osrm::util::toFloating(coordinates[1].lat) << ":" + << osrm::util::toFloating(coordinates[1].lon) << ">"); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, false); + check_route_annotated_ways(coordinates, osrm, node_pair_to_way_id_map, true); + } +} + BOOST_AUTO_TEST_CASE(test_route_serialize_fb) { auto osrm = getOSRM(OSRM_TEST_DATA_DIR "/ch/monaco.osrm"); diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 4edcb97356e..1af3876fcca 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -64,6 +64,18 @@ class MockBaseDataFacade : public engine::datafacade::BaseDataFacade { return NodeReverseRange(GetUncompressedForwardGeometry(id)); } + OSMWayForwardRange GetUncompressedForwardWayIDs(const EdgeID /* id */) const override + { + static OSMWayIDDir data[] = {0, 1, 2, 3}; + static extractor::SegmentDataView::SegmentOSMWayVector ways(data, 4); + return boost::make_iterator_range(ways.cbegin(), ways.cend()); + } + bool GetUncompressedWayIDsSkipped() const override { return false; } + OSMWayReverseRange GetUncompressedReverseWayIDs(const EdgeID id) const override + { + return boost::adaptors::reverse(boost::adaptors::transform(GetUncompressedForwardWayIDs(id), + std::negate())); + } WeightForwardRange GetUncompressedForwardWeights(const EdgeID /* id */) const override { static std::uint64_t data[] = {1, 2, 3};