diff --git a/.github/workflows/osrm-backend.yml b/.github/workflows/osrm-backend.yml index f1b28b310..ed0407f68 100644 --- a/.github/workflows/osrm-backend.yml +++ b/.github/workflows/osrm-backend.yml @@ -31,11 +31,11 @@ jobs: env: BUILD_TYPE: Release steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - run: pip install "conan<2.0.0" - run: conan --version - run: cmake --version - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 18 - run: node --version @@ -47,7 +47,7 @@ jobs: echo PUBLISH=$([[ "${GITHUB_REF:-}" == "refs/tags/v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off") >> $GITHUB_ENV - run: npm install --ignore-scripts - run: npm link --ignore-scripts - - uses: microsoft/setup-msbuild@v1.1 + - uses: microsoft/setup-msbuild@v2 - name: Build run: | .\scripts\ci\windows-build.bat @@ -76,13 +76,13 @@ jobs: format-taginfo-docs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: Enable Node.js cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} @@ -106,9 +106,9 @@ jobs: continue-on-error: false steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Enable osm.pbf cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: berlin-latest.osm.pbf key: v1-berlin-osm-pbf @@ -151,7 +151,7 @@ jobs: - name: gcc-13-debug-cov continue-on-error: false node: 20 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 BUILD_TOOLS: ON BUILD_TYPE: Debug CCOMPILER: gcc-13 @@ -248,7 +248,7 @@ jobs: - name: gcc-13-release continue-on-error: false node: 20 - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 BUILD_TOOLS: ON BUILD_TYPE: Release CCOMPILER: gcc-13 @@ -342,36 +342,36 @@ jobs: OSRM_CONNECTION_RETRIES: ${{ matrix.OSRM_CONNECTION_RETRIES }} OSRM_CONNECTION_EXP_BACKOFF_COEF: ${{ matrix.OSRM_CONNECTION_EXP_BACKOFF_COEF }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build machine architecture run: uname -m - name: Use Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - name: Enable Node.js cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - name: Enable compiler cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.ccache key: ccache-${{ matrix.name }}-${{ github.sha }} restore-keys: | ccache-${{ matrix.name }}- - name: Enable Conan cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.conan key: v9-conan-${{ matrix.name }}-${{ github.sha }} restore-keys: | v9-conan-${{ matrix.name }}- - name: Enable test cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{github.workspace}}/test/cache key: v4-test-${{ matrix.name }}-${{ github.sha }} @@ -511,7 +511,7 @@ jobs: - name: Use Node 18 if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: Run Node package tests on Node 18 @@ -521,7 +521,7 @@ jobs: npm run nodejs-tests - name: Use Node 20 if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 20 - name: Run Node package tests on Node 20 @@ -531,7 +531,7 @@ jobs: npm run nodejs-tests - name: Use Node latest if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: latest - name: Run Node package tests on Node-latest @@ -541,7 +541,7 @@ jobs: npm run nodejs-tests - name: Upload test logs - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: logs @@ -557,7 +557,7 @@ jobs: # # Uploading report to CodeCov # - name: Upload code coverage # if: ${{ matrix.ENABLE_COVERAGE == 'ON' }} - # uses: codecov/codecov-action@v1 + # uses: codecov/codecov-action@v4 # with: # files: coverage.info # name: codecov-osrm-backend @@ -595,21 +595,21 @@ jobs: GITHUB_REPOSITORY: ${{ github.repository }} steps: - name: Enable compiler cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.ccache key: v1-ccache-benchmarks-${{ github.sha }} restore-keys: | v1-ccache-benchmarks- - name: Enable Conan cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.conan key: v1-conan-benchmarks-${{ github.sha }} restore-keys: | v1-conan-benchmarks- - name: Checkout PR Branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} path: pr @@ -624,7 +624,7 @@ jobs: cd .. make -C test/data - name: Checkout Base Branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.base.ref }} path: base diff --git a/CHANGELOG.md b/CHANGELOG.md index af81aa8d8..fe311ca2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ - ADDED: Add support for opposite approach request parameter. [#6842](https://github.com/Project-OSRM/osrm-backend/pull/6842) - ADDED: Add support for accessing edge flags in `process_segment` [#6658](https://github.com/Project-OSRM/osrm-backend/pull/6658) - Build: + - CHANGED: Upgrade CI actions to latest versions [#6893](https://github.com/Project-OSRM/osrm-backend/pull/6893) + - CHANGED: Remove outdated warnings #6894 [#6894](https://github.com/Project-OSRM/osrm-backend/pull/6894) - ADDED: Add CI job which builds OSRM with gcc 12. [#6455](https://github.com/Project-OSRM/osrm-backend/pull/6455) - CHANGED: Upgrade to clang-tidy 15. [#6439](https://github.com/Project-OSRM/osrm-backend/pull/6439) - CHANGED: Update actions/cache to v3. [#6420](https://github.com/Project-OSRM/osrm-backend/pull/6420) @@ -19,6 +21,9 @@ - NodeJS: - CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452) - Misc: + - CHANGED: Avoid copy of std::function-based callback in path unpacking [#6895](https://github.com/Project-OSRM/osrm-backend/pull/6895) + - CHANGED: Replace boost::hash by std::hash [#6892](https://github.com/Project-OSRM/osrm-backend/pull/6892) + - CHANGED: Partial fix migration from boost::optional to std::optional [#6551](https://github.com/Project-OSRM/osrm-backend/issues/6551) - CHANGED: Replace boost::filesystem with std::filesystem [#6432](https://github.com/Project-OSRM/osrm-backend/pull/6432) - CHANGED: Update Conan Boost version to 1.85.0. [#6868](https://github.com/Project-OSRM/osrm-backend/pull/6868) - FIXED: Fix an error in a RouteParameters AnnotationsType operator overload. [#6646](https://github.com/Project-OSRM/osrm-backend/pull/6646) @@ -49,7 +54,9 @@ - FIXED: Remove force-loop checks for routes with u-turns [#6858](https://github.com/Project-OSRM/osrm-backend/pull/6858) - FIXED: Correctly check runtime search conditions for forcing routing steps [#6866](https://github.com/Project-OSRM/osrm-backend/pull/6866) - Map Matching: + - CHANGED: Optimise path distance calculation in MLD map matching even more. [#6884](https://github.com/Project-OSRM/osrm-backend/pull/6884) - CHANGED: Optimise path distance calculation in MLD map matching. [#6876](https://github.com/Project-OSRM/osrm-backend/pull/6876) + - CHANGED: Optimise R-tree queries in the case of map matching. [#6881](https://github.com/Project-OSRM/osrm-backend/pull/6876) - Debug tiles: - FIXED: Ensure speed layer features have unique ids. [#6726](https://github.com/Project-OSRM/osrm-backend/pull/6726) diff --git a/cmake/warnings.cmake b/cmake/warnings.cmake index ad9cfb086..89040aa0e 100644 --- a/cmake/warnings.cmake +++ b/cmake/warnings.cmake @@ -50,9 +50,7 @@ add_warning(all) add_warning(extra) add_warning(pedantic) add_warning(error) # treat all warnings as errors -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_warning(strict-overflow=2) -elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") add_warning(strict-overflow=1) endif() add_warning(suggest-override) @@ -79,15 +77,5 @@ add_warning(sizeof-array-argument) add_warning(switch-bool) add_warning(tautological-compare) add_warning(trampolines) -no_warning(c++17-extensions) -# TODO: these warnings are not enabled by default, but we consider them as useful and good to enable in the future -no_warning(implicit-int-conversion) -no_warning(implicit-float-conversion) -no_warning(unused-member-function) -no_warning(old-style-cast) -no_warning(non-virtual-dtor) -no_warning(float-conversion) -no_warning(sign-conversion) -no_warning(shorten-64-to-32) -no_warning(padded) -no_warning(missing-noreturn) \ No newline at end of file +# these warnings are not enabled by default +# no_warning(name-of-warning) \ No newline at end of file diff --git a/include/engine/datafacade/algorithm_datafacade.hpp b/include/engine/datafacade/algorithm_datafacade.hpp index 7965784bc..192d024fc 100644 --- a/include/engine/datafacade/algorithm_datafacade.hpp +++ b/include/engine/datafacade/algorithm_datafacade.hpp @@ -55,7 +55,7 @@ template <> class AlgorithmDataFacade virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from, const NodeID edge_based_node_to, - const std::function filter) const = 0; + const std::function &filter) const = 0; }; template <> class AlgorithmDataFacade diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 73cdbba67..7a495e86f 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -130,9 +130,10 @@ class ContiguousInternalMemoryAlgorithmDataFacade : public datafacade::Algor edge_based_node_from, edge_based_node_to, result); } - EdgeID FindSmallestEdge(const NodeID edge_based_node_from, - const NodeID edge_based_node_to, - std::function filter) const override final + EdgeID + FindSmallestEdge(const NodeID edge_based_node_from, + const NodeID edge_based_node_to, + const std::function &filter) const override final { return m_query_graph.FindSmallestEdge(edge_based_node_from, edge_based_node_to, filter); } @@ -375,7 +376,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade BOOST_ASSERT(m_geospatial_query.get()); return m_geospatial_query->NearestPhantomNodes( - input_coordinate, approach, boost::none, max_distance, bearing, use_all_edges); + input_coordinate, approach, max_distance, bearing, use_all_edges); } std::vector diff --git a/include/engine/geospatial_query.hpp b/include/engine/geospatial_query.hpp index b8e43b637..c4efbcbbb 100644 --- a/include/engine/geospatial_query.hpp +++ b/include/engine/geospatial_query.hpp @@ -12,6 +12,8 @@ #include "osrm/coordinate.hpp" +#include + #include #include #include @@ -47,12 +49,42 @@ template class GeospatialQuery return rtree.SearchInBox(bbox); } + std::vector + NearestPhantomNodes(const util::Coordinate input_coordinate, + const Approach approach, + const double max_distance, + const boost::optional bearing_with_range, + const boost::optional use_all_edges) const + { + auto results = rtree.SearchInRange( + input_coordinate, + max_distance, + [this, approach, &input_coordinate, &bearing_with_range, &use_all_edges, max_distance]( + const CandidateSegment &segment) + { + auto invalidDistance = + CheckSegmentDistance(input_coordinate, segment, max_distance); + if (invalidDistance) + { + return std::make_pair(false, false); + } + auto valid = CheckSegmentExclude(segment) && + CheckApproach(input_coordinate, segment, approach) && + (use_all_edges ? HasValidEdge(segment, *use_all_edges) + : HasValidEdge(segment)) && + (bearing_with_range ? CheckSegmentBearing(segment, *bearing_with_range) + : std::make_pair(true, true)); + return valid; + }); + return MakePhantomNodes(input_coordinate, results); + } + // Returns max_results nearest PhantomNodes that are valid within the provided parameters. // Does not filter by small/big component! std::vector NearestPhantomNodes(const util::Coordinate input_coordinate, const Approach approach, - const boost::optional max_results, + const size_t max_results, const boost::optional max_distance, const boost::optional bearing_with_range, const boost::optional use_all_edges) const @@ -70,10 +102,10 @@ template class GeospatialQuery : std::make_pair(true, true)); return valid; }, - [this, &max_distance, &max_results, input_coordinate](const std::size_t num_results, - const CandidateSegment &segment) + [this, &max_distance, max_results, input_coordinate](const std::size_t num_results, + const CandidateSegment &segment) { - return (max_results && num_results >= *max_results) || + return (num_results >= max_results) || (max_distance && max_distance != -1.0 && CheckSegmentDistance(input_coordinate, segment, *max_distance)); }); diff --git a/include/engine/routing_algorithms/routing_base_ch.hpp b/include/engine/routing_algorithms/routing_base_ch.hpp index b3da739de..e2e3b5400 100644 --- a/include/engine/routing_algorithms/routing_base_ch.hpp +++ b/include/engine/routing_algorithms/routing_base_ch.hpp @@ -122,7 +122,7 @@ void routingStep(const DataFacade &facade, const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight; if (new_weight < upper_bound) { - if (shouldForceStep(force_step_nodes, heapNode, reverseHeapNode.get()) || + if (shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) || // in this case we are looking at a bi-directional way where the source // and target phantom are on the same edge based node new_weight < EdgeWeight{0}) diff --git a/include/engine/routing_algorithms/routing_base_mld.hpp b/include/engine/routing_algorithms/routing_base_mld.hpp index b85ce5496..a02d4a095 100644 --- a/include/engine/routing_algorithms/routing_base_mld.hpp +++ b/include/engine/routing_algorithms/routing_base_mld.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -269,10 +270,29 @@ retrievePackedPathFromHeap(const SearchEngineData::QueryHeap &forward return packed_path; } -template +template +void insertOrUpdate(Heap &heap, + const NodeID node, + const EdgeWeight weight, + const typename Heap::DataType &data) +{ + const auto heapNode = heap.GetHeapNodeIfWasInserted(node); + if (!heapNode) + { + heap.Insert(node, weight, data); + } + else if (weight < heapNode->weight) + { + heapNode->data = data; + heapNode->weight = weight; + heap.DecreaseKey(*heapNode); + } +} + +template void relaxOutgoingEdges(const DataFacade &facade, - typename SearchEngineData::QueryHeap &forward_heap, - const typename SearchEngineData::QueryHeap::HeapNode &heapNode, + Heap &forward_heap, + const typename Heap::HeapNode &heapNode, const Args &...args) { const auto &partition = facade.GetMultiLevelPartition(); @@ -281,14 +301,31 @@ void relaxOutgoingEdges(const DataFacade &facade, const auto level = getNodeQueryLevel(partition, heapNode.node, args...); + static constexpr auto IS_MAP_MATCHING = + std::is_same_v::MapMatchingQueryHeap, Heap>; + if (level >= 1 && !heapNode.data.from_clique_arc) { - if (DIRECTION == FORWARD_DIRECTION) + if constexpr (DIRECTION == FORWARD_DIRECTION) { // Shortcuts in forward direction const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); auto destination = cell.GetDestinationNodes().begin(); + auto distance = [&cell, node = heapNode.node ]() -> auto + { + if constexpr (IS_MAP_MATCHING) + { + + return cell.GetOutDistance(node).begin(); + } + else + { + boost::ignore_unused(cell, node); + return 0; + } + } + (); for (auto shortcut_weight : cell.GetOutWeight(heapNode.node)) { BOOST_ASSERT(destination != cell.GetDestinationNodes().end()); @@ -298,19 +335,23 @@ void relaxOutgoingEdges(const DataFacade &facade, { const EdgeWeight to_weight = heapNode.weight + shortcut_weight; BOOST_ASSERT(to_weight >= heapNode.weight); - const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); - if (!toHeapNode) + + if constexpr (IS_MAP_MATCHING) { - forward_heap.Insert(to, to_weight, {heapNode.node, true}); + const EdgeDistance to_distance = heapNode.data.distance + *distance; + insertOrUpdate( + forward_heap, to, to_weight, {heapNode.node, true, to_distance}); } - else if (to_weight < toHeapNode->weight) + else { - toHeapNode->data = {heapNode.node, true}; - toHeapNode->weight = to_weight; - forward_heap.DecreaseKey(*toHeapNode); + insertOrUpdate(forward_heap, to, to_weight, {heapNode.node, true}); } } ++destination; + if constexpr (IS_MAP_MATCHING) + { + ++distance; + } } } else @@ -319,6 +360,20 @@ void relaxOutgoingEdges(const DataFacade &facade, const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, heapNode.node)); auto source = cell.GetSourceNodes().begin(); + auto distance = [&cell, node = heapNode.node ]() -> auto + { + if constexpr (IS_MAP_MATCHING) + { + + return cell.GetInDistance(node).begin(); + } + else + { + boost::ignore_unused(cell, node); + return 0; + } + } + (); for (auto shortcut_weight : cell.GetInWeight(heapNode.node)) { BOOST_ASSERT(source != cell.GetSourceNodes().end()); @@ -328,19 +383,22 @@ void relaxOutgoingEdges(const DataFacade &facade, { const EdgeWeight to_weight = heapNode.weight + shortcut_weight; BOOST_ASSERT(to_weight >= heapNode.weight); - const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); - if (!toHeapNode) + if constexpr (IS_MAP_MATCHING) { - forward_heap.Insert(to, to_weight, {heapNode.node, true}); + const EdgeDistance to_distance = heapNode.data.distance + *distance; + insertOrUpdate( + forward_heap, to, to_weight, {heapNode.node, true, to_distance}); } - else if (to_weight < toHeapNode->weight) + else { - toHeapNode->data = {heapNode.node, true}; - toHeapNode->weight = to_weight; - forward_heap.DecreaseKey(*toHeapNode); + insertOrUpdate(forward_heap, to, to_weight, {heapNode.node, true}); } } ++source; + if constexpr (IS_MAP_MATCHING) + { + ++distance; + } } } } @@ -367,26 +425,28 @@ void relaxOutgoingEdges(const DataFacade &facade, const EdgeWeight to_weight = heapNode.weight + node_weight + alias_cast(turn_penalty); - const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to); - if (!toHeapNode) + if constexpr (IS_MAP_MATCHING) { - forward_heap.Insert(to, to_weight, {heapNode.node, false}); + const auto node_distance = + facade.GetNodeDistance(DIRECTION == FORWARD_DIRECTION ? heapNode.node : to); + + const EdgeDistance to_distance = heapNode.data.distance + node_distance; + insertOrUpdate( + forward_heap, to, to_weight, {heapNode.node, false, to_distance}); } - else if (to_weight < toHeapNode->weight) + else { - toHeapNode->data = {heapNode.node, false}; - toHeapNode->weight = to_weight; - forward_heap.DecreaseKey(*toHeapNode); + insertOrUpdate(forward_heap, to, to_weight, {heapNode.node, false}); } } } } } -template +template void routingStep(const DataFacade &facade, - typename SearchEngineData::QueryHeap &forward_heap, - typename SearchEngineData::QueryHeap &reverse_heap, + Heap &forward_heap, + Heap &reverse_heap, NodeID &middle_node, EdgeWeight &path_upper_bound, const std::vector &force_step_nodes, @@ -408,7 +468,7 @@ void routingStep(const DataFacade &facade, auto reverse_weight = reverseHeapNode->weight; auto path_weight = weight + reverse_weight; - if (!shouldForceStep(force_step_nodes, heapNode, reverseHeapNode.get()) && + if (!shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) && (path_weight >= EdgeWeight{0}) && (path_weight < path_upper_bound)) { middle_node = heapNode.node; @@ -429,22 +489,19 @@ using UnpackedNodes = std::vector; using UnpackedEdges = std::vector; using UnpackedPath = std::tuple; -template -UnpackedPath search(SearchEngineData &engine_working_data, - const DataFacade &facade, - typename SearchEngineData::QueryHeap &forward_heap, - typename SearchEngineData::QueryHeap &reverse_heap, - const std::vector &force_step_nodes, - EdgeWeight weight_upper_bound, - const Args &...args) +template +std::optional> runSearch(const DataFacade &facade, + Heap &forward_heap, + Heap &reverse_heap, + const std::vector &force_step_nodes, + EdgeWeight weight_upper_bound, + const Args &...args) { if (forward_heap.Empty() || reverse_heap.Empty()) { - return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector(), std::vector()); + return {}; } - const auto &partition = facade.GetMultiLevelPartition(); - BOOST_ASSERT(!forward_heap.Empty() && forward_heap.MinKey() < INVALID_EDGE_WEIGHT); BOOST_ASSERT(!reverse_heap.Empty() && reverse_heap.MinKey() < INVALID_EDGE_WEIGHT); @@ -474,10 +531,33 @@ UnpackedPath search(SearchEngineData &engine_working_data, // No path found for both target nodes? if (weight >= weight_upper_bound || SPECIAL_NODEID == middle) + { + return {}; + } + + return {{middle, weight}}; +} + +template +UnpackedPath search(SearchEngineData &engine_working_data, + const DataFacade &facade, + typename SearchEngineData::QueryHeap &forward_heap, + typename SearchEngineData::QueryHeap &reverse_heap, + const std::vector &force_step_nodes, + EdgeWeight weight_upper_bound, + const Args &...args) +{ + auto searchResult = runSearch( + facade, forward_heap, reverse_heap, force_step_nodes, weight_upper_bound, args...); + if (!searchResult) { return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector(), std::vector()); } + auto [middle, weight] = *searchResult; + + const auto &partition = facade.GetMultiLevelPartition(); + // Get packed path as edges {from node ID, to node ID, from_clique_arc} auto packed_path = retrievePackedPathFromHeap(forward_heap, reverse_heap, middle); @@ -536,6 +616,31 @@ UnpackedPath search(SearchEngineData &engine_working_data, return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges)); } +template +EdgeDistance +searchDistance(SearchEngineData &, + const DataFacade &facade, + typename SearchEngineData::MapMatchingQueryHeap &forward_heap, + typename SearchEngineData::MapMatchingQueryHeap &reverse_heap, + const std::vector &force_step_nodes, + EdgeWeight weight_upper_bound, + const Args &...args) +{ + + auto searchResult = runSearch( + facade, forward_heap, reverse_heap, force_step_nodes, weight_upper_bound, args...); + if (!searchResult) + { + return INVALID_EDGE_DISTANCE; + } + + auto [middle, _] = *searchResult; + + auto distance = forward_heap.GetData(middle).distance + reverse_heap.GetData(middle).distance; + + return distance; +} + // Alias to be compatible with the CH-based search template inline void search(SearchEngineData &engine_working_data, @@ -593,8 +698,8 @@ void unpackPath(const FacadeT &facade, template double getNetworkDistance(SearchEngineData &engine_working_data, const DataFacade &facade, - typename SearchEngineData::QueryHeap &forward_heap, - typename SearchEngineData::QueryHeap &reverse_heap, + typename SearchEngineData::MapMatchingQueryHeap &forward_heap, + typename SearchEngineData::MapMatchingQueryHeap &reverse_heap, const PhantomNode &source_phantom, const PhantomNode &target_phantom, EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT) @@ -602,48 +707,49 @@ double getNetworkDistance(SearchEngineData &engine_working_data, forward_heap.Clear(); reverse_heap.Clear(); - const PhantomEndpoints endpoints{source_phantom, target_phantom}; - insertNodesInHeaps(forward_heap, reverse_heap, endpoints); + if (source_phantom.IsValidForwardSource()) + { + forward_heap.Insert(source_phantom.forward_segment_id.id, + EdgeWeight{0} - source_phantom.GetForwardWeightPlusOffset(), + {source_phantom.forward_segment_id.id, + false, + EdgeDistance{0} - source_phantom.GetForwardDistance()}); + } - auto [weight, unpacked_nodes, unpacked_edges] = search( + if (source_phantom.IsValidReverseSource()) + { + forward_heap.Insert(source_phantom.reverse_segment_id.id, + EdgeWeight{0} - source_phantom.GetReverseWeightPlusOffset(), + {source_phantom.reverse_segment_id.id, + false, + EdgeDistance{0} - source_phantom.GetReverseDistance()}); + } + + if (target_phantom.IsValidForwardTarget()) + { + reverse_heap.Insert( + target_phantom.forward_segment_id.id, + target_phantom.GetForwardWeightPlusOffset(), + {target_phantom.forward_segment_id.id, false, target_phantom.GetForwardDistance()}); + } + + if (target_phantom.IsValidReverseTarget()) + { + reverse_heap.Insert( + target_phantom.reverse_segment_id.id, + target_phantom.GetReverseWeightPlusOffset(), + {target_phantom.reverse_segment_id.id, false, target_phantom.GetReverseDistance()}); + } + + const PhantomEndpoints endpoints{source_phantom, target_phantom}; + + auto distance = searchDistance( engine_working_data, facade, forward_heap, reverse_heap, {}, weight_upper_bound, endpoints); - if (weight == INVALID_EDGE_WEIGHT) + if (distance == INVALID_EDGE_DISTANCE) { return std::numeric_limits::max(); } - - BOOST_ASSERT(unpacked_nodes.size() >= 1); - - EdgeDistance distance = {0.0}; - - if (source_phantom.forward_segment_id.id == unpacked_nodes.front()) - { - BOOST_ASSERT(source_phantom.forward_segment_id.enabled); - distance = EdgeDistance{0} - source_phantom.GetForwardDistance(); - } - else if (source_phantom.reverse_segment_id.id == unpacked_nodes.front()) - { - BOOST_ASSERT(source_phantom.reverse_segment_id.enabled); - distance = EdgeDistance{0} - source_phantom.GetReverseDistance(); - } - - for (size_t index = 0; index < unpacked_nodes.size() - 1; ++index) - { - distance += facade.GetNodeDistance(unpacked_nodes[index]); - } - - if (target_phantom.forward_segment_id.id == unpacked_nodes.back()) - { - BOOST_ASSERT(target_phantom.forward_segment_id.enabled); - distance += target_phantom.GetForwardDistance(); - } - else if (target_phantom.reverse_segment_id.id == unpacked_nodes.back()) - { - BOOST_ASSERT(target_phantom.reverse_segment_id.enabled); - distance += target_phantom.GetReverseDistance(); - } - return from_alias(distance); } diff --git a/include/engine/search_engine_data.hpp b/include/engine/search_engine_data.hpp index 2f32b327b..4060ab6b2 100644 --- a/include/engine/search_engine_data.hpp +++ b/include/engine/search_engine_data.hpp @@ -47,6 +47,7 @@ template <> struct SearchEngineData util::UnorderedMapStorage>; using SearchEngineHeapPtr = boost::thread_specific_ptr; + using ManyToManyHeapPtr = boost::thread_specific_ptr; static SearchEngineHeapPtr forward_heap_1; @@ -56,6 +57,10 @@ template <> struct SearchEngineData static SearchEngineHeapPtr forward_heap_3; static SearchEngineHeapPtr reverse_heap_3; static ManyToManyHeapPtr many_to_many_heap; + static SearchEngineHeapPtr map_matching_forward_heap_1; + static SearchEngineHeapPtr map_matching_reverse_heap_1; + + void InitializeOrClearMapMatchingThreadLocalStorage(unsigned number_of_nodes); void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes); @@ -74,6 +79,19 @@ struct MultiLayerDijkstraHeapData MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {} }; +struct MapMatchingMultiLayerDijkstraHeapData +{ + NodeID parent; + bool from_clique_arc; + EdgeDistance distance = {0}; + MapMatchingMultiLayerDijkstraHeapData(NodeID p) : parent(p), from_clique_arc(false) {} + MapMatchingMultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {} + MapMatchingMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeDistance d) + : parent(p), from_clique_arc(from), distance(d) + { + } +}; + struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData { EdgeDuration duration; @@ -104,16 +122,27 @@ template <> struct SearchEngineData EdgeWeight, ManyToManyMultiLayerDijkstraHeapData, util::TwoLevelStorage>; + using MapMatchingQueryHeap = util::QueryHeap>; using SearchEngineHeapPtr = boost::thread_specific_ptr; using ManyToManyHeapPtr = boost::thread_specific_ptr; + using MapMatchingHeapPtr = boost::thread_specific_ptr; static SearchEngineHeapPtr forward_heap_1; static SearchEngineHeapPtr reverse_heap_1; + static MapMatchingHeapPtr map_matching_forward_heap_1; + static MapMatchingHeapPtr map_matching_reverse_heap_1; + static ManyToManyHeapPtr many_to_many_heap; void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes, unsigned number_of_boundary_nodes); + void InitializeOrClearMapMatchingThreadLocalStorage(unsigned number_of_nodes, + unsigned number_of_boundary_nodes); void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes, unsigned number_of_boundary_nodes); diff --git a/include/extractor/extractor_callbacks.hpp b/include/extractor/extractor_callbacks.hpp index 69f53ab2b..83672f549 100644 --- a/include/extractor/extractor_callbacks.hpp +++ b/include/extractor/extractor_callbacks.hpp @@ -3,11 +3,9 @@ #include "extractor/class_data.hpp" #include "extractor/turn_lane_types.hpp" +#include "util/std_hash.hpp" #include "util/typedefs.hpp" -#include -#include - #include #include @@ -18,25 +16,6 @@ class Way; class Relation; } // namespace osmium -namespace std -{ -template <> struct hash> -{ - std::size_t operator()( - const std::tuple &mk) - const noexcept - { - std::size_t seed = 0; - boost::hash_combine(seed, std::get<0>(mk)); - boost::hash_combine(seed, std::get<1>(mk)); - boost::hash_combine(seed, std::get<2>(mk)); - boost::hash_combine(seed, std::get<3>(mk)); - boost::hash_combine(seed, std::get<4>(mk)); - return seed; - } -}; -} // namespace std - namespace osrm::extractor { diff --git a/include/extractor/intersection/node_based_graph_walker.hpp b/include/extractor/intersection/node_based_graph_walker.hpp index 869e934bc..f3915ee9f 100644 --- a/include/extractor/intersection/node_based_graph_walker.hpp +++ b/include/extractor/intersection/node_based_graph_walker.hpp @@ -11,8 +11,8 @@ #include "util/typedefs.hpp" #include -#include #include +#include #include namespace osrm::extractor::intersection @@ -42,10 +42,10 @@ class NodeBasedGraphWalker * selector not provinding any further edge to traverse) */ template - boost::optional> TraverseRoad(NodeID starting_at_node_id, - EdgeID following_edge_id, - accumulator_type &accumulator, - const selector_type &selector) const; + std::optional> TraverseRoad(NodeID starting_at_node_id, + EdgeID following_edge_id, + accumulator_type &accumulator, + const selector_type &selector) const; private: const util::NodeBasedDynamicGraph &node_based_graph; @@ -111,11 +111,11 @@ struct SelectRoadByNameOnlyChoiceAndStraightness * traversal. If no such edge is found, return {} is allowed. Usually you want to choose some * form of obious turn to follow. */ - boost::optional operator()(const NodeID nid, - const EdgeID via_edge_id, - const IntersectionView &intersection, - const util::NodeBasedDynamicGraph &node_based_graph, - const EdgeBasedNodeDataContainer &node_data_container) const; + std::optional operator()(const NodeID nid, + const EdgeID via_edge_id, + const IntersectionView &intersection, + const util::NodeBasedDynamicGraph &node_based_graph, + const EdgeBasedNodeDataContainer &node_data_container) const; private: const NameID desired_name_id; @@ -138,11 +138,11 @@ struct SelectStraightmostRoadByNameAndOnlyChoice * traversal. If no such edge is found, return {} is allowed. Usually you want to choose some * form of obious turn to follow. */ - boost::optional operator()(const NodeID nid, - const EdgeID via_edge_id, - const IntersectionView &intersection, - const util::NodeBasedDynamicGraph &node_based_graph, - const EdgeBasedNodeDataContainer &node_data_container) const; + std::optional operator()(const NodeID nid, + const EdgeID via_edge_id, + const IntersectionView &intersection, + const util::NodeBasedDynamicGraph &node_based_graph, + const EdgeBasedNodeDataContainer &node_data_container) const; private: const NameID desired_name_id; @@ -187,7 +187,7 @@ struct IntersectionFinderAccumulator }; template -boost::optional> +std::optional> NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id, EdgeID current_edge_id, accumulator_type &accumulator, @@ -254,19 +254,19 @@ NodeBasedGraphWalker::TraverseRoad(NodeID current_node_id, struct SkipTrafficSignalBarrierRoadSelector { - boost::optional operator()(const NodeID, - const EdgeID, - const IntersectionView &intersection, - const util::NodeBasedDynamicGraph &, - const EdgeBasedNodeDataContainer &) const + std::optional operator()(const NodeID, + const EdgeID, + const IntersectionView &intersection, + const util::NodeBasedDynamicGraph &, + const EdgeBasedNodeDataContainer &) const { if (intersection.isTrafficSignalOrBarrier()) { - return boost::make_optional(intersection[1].eid); + return std::make_optional(intersection[1].eid); } else { - return boost::none; + return std::nullopt; } } }; diff --git a/include/extractor/maneuver_override.hpp b/include/extractor/maneuver_override.hpp index db647359b..49668f2c1 100644 --- a/include/extractor/maneuver_override.hpp +++ b/include/extractor/maneuver_override.hpp @@ -8,11 +8,13 @@ #include "turn_path.hpp" #include "util/integer_range.hpp" #include "util/log.hpp" +#include "util/std_hash.hpp" #include "util/vector_view.hpp" -#include -#include + #include +#include + namespace osrm::extractor { @@ -147,7 +149,6 @@ struct UnresolvedManeuverOverride namespace std { template <> struct hash - { using argument_type = osrm::extractor::NodeBasedTurn; using result_type = std::size_t; @@ -155,9 +156,9 @@ template <> struct hash { std::size_t seed = 0; - boost::hash_combine(seed, s.from); - boost::hash_combine(seed, s.via); - boost::hash_combine(seed, s.to); + hash_combine(seed, s.from); + hash_combine(seed, s.via); + hash_combine(seed, s.to); return seed; } diff --git a/include/extractor/maneuver_override_relation_parser.hpp b/include/extractor/maneuver_override_relation_parser.hpp index df4b93a3d..c6084ad70 100644 --- a/include/extractor/maneuver_override_relation_parser.hpp +++ b/include/extractor/maneuver_override_relation_parser.hpp @@ -3,7 +3,7 @@ #include "maneuver_override.hpp" -#include +#include #include #include @@ -55,7 +55,7 @@ class ManeuverOverrideRelationParser { public: ManeuverOverrideRelationParser(); - boost::optional TryParse(const osmium::Relation &relation) const; + std::optional TryParse(const osmium::Relation &relation) const; }; } // namespace osrm::extractor diff --git a/include/extractor/profile_properties.hpp b/include/extractor/profile_properties.hpp index 817e7b763..371155b17 100644 --- a/include/extractor/profile_properties.hpp +++ b/include/extractor/profile_properties.hpp @@ -7,11 +7,11 @@ #include #include -#include #include #include #include +#include namespace osrm::extractor { @@ -80,7 +80,7 @@ struct ProfileProperties } // Check if this classes are excludable - boost::optional ClassesAreExcludable(ClassData classes) const + std::optional ClassesAreExcludable(ClassData classes) const { auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes); if (iter != excludable_classes.end()) diff --git a/include/extractor/traffic_signals.hpp b/include/extractor/traffic_signals.hpp index 739b57bcb..febb5d25d 100644 --- a/include/extractor/traffic_signals.hpp +++ b/include/extractor/traffic_signals.hpp @@ -1,10 +1,11 @@ #ifndef OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP #define OSRM_EXTRACTOR_TRAFFIC_SIGNALS_HPP +#include "util/std_hash.hpp" #include "util/typedefs.hpp" -#include #include +#include namespace osrm::extractor { @@ -12,8 +13,7 @@ namespace osrm::extractor struct TrafficSignals { std::unordered_set bidirectional_nodes; - std::unordered_set, boost::hash>> - unidirectional_segments; + std::unordered_set> unidirectional_segments; inline bool HasSignal(NodeID from, NodeID to) const { diff --git a/include/extractor/turn_lane_types.hpp b/include/extractor/turn_lane_types.hpp index 275b6365c..88a124f54 100644 --- a/include/extractor/turn_lane_types.hpp +++ b/include/extractor/turn_lane_types.hpp @@ -3,10 +3,9 @@ #include "util/concurrent_id_map.hpp" #include "util/integer_range.hpp" +#include "util/std_hash.hpp" #include "util/typedefs.hpp" -#include - #include #include #include @@ -54,19 +53,7 @@ const constexpr Mask merge_to_right = 1u << 10u; using TurnLaneDescription = std::vector; -// hash function for TurnLaneDescription -struct TurnLaneDescription_hash -{ - std::size_t operator()(const TurnLaneDescription &lane_description) const - { - std::size_t seed = 0; - boost::hash_range(seed, lane_description.begin(), lane_description.end()); - return seed; - } -}; - -using LaneDescriptionMap = - util::ConcurrentIDMap; +using LaneDescriptionMap = util::ConcurrentIDMap; using TurnLanesIndexedArray = std::tuple, std::vector>; diff --git a/include/guidance/intersection_handler.hpp b/include/guidance/intersection_handler.hpp index b54d82230..5a7068e40 100644 --- a/include/guidance/intersection_handler.hpp +++ b/include/guidance/intersection_handler.hpp @@ -15,11 +15,10 @@ #include #include +#include #include #include -#include - namespace osrm::guidance { @@ -129,7 +128,7 @@ class IntersectionHandler // ^ via // // For this scenario returns intersection at `b` and `b`. - boost::optional + std::optional getNextIntersection(const NodeID at, const EdgeID via) const; bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const; diff --git a/include/guidance/sliproad_handler.hpp b/include/guidance/sliproad_handler.hpp index a75f70a52..533ac4dcf 100644 --- a/include/guidance/sliproad_handler.hpp +++ b/include/guidance/sliproad_handler.hpp @@ -9,10 +9,9 @@ #include "util/node_based_graph.hpp" +#include #include -#include - namespace osrm::guidance { @@ -43,9 +42,9 @@ class SliproadHandler final : public IntersectionHandler Intersection intersection) const override final; private: - boost::optional getObviousIndexWithSliproads(const EdgeID from, - const Intersection &intersection, - const NodeID at) const; + std::optional getObviousIndexWithSliproads(const EdgeID from, + const Intersection &intersection, + const NodeID at) const; // Next intersection from `start` onto `onto` is too far away for a Siproad scenario bool nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const; diff --git a/include/guidance/turn_handler.hpp b/include/guidance/turn_handler.hpp index d3e25c79a..6a5210992 100644 --- a/include/guidance/turn_handler.hpp +++ b/include/guidance/turn_handler.hpp @@ -11,9 +11,8 @@ #include "util/attributes.hpp" #include "util/node_based_graph.hpp" -#include - #include +#include #include #include @@ -72,7 +71,7 @@ class TurnHandler final : public IntersectionHandler bool hasObvious(const EdgeID &via_edge, const Fork &fork) const; - boost::optional findForkCandidatesByGeometry(Intersection &intersection) const; + std::optional findForkCandidatesByGeometry(Intersection &intersection) const; bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const; @@ -96,7 +95,7 @@ class TurnHandler final : public IntersectionHandler handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const; // Classification - boost::optional findFork(const EdgeID via_edge, Intersection &intersection) const; + std::optional findFork(const EdgeID via_edge, Intersection &intersection) const; OSRM_ATTR_WARN_UNUSED Intersection assignLeftTurns(const EdgeID via_edge, diff --git a/include/updater/csv_file_parser.hpp b/include/updater/csv_file_parser.hpp index 17998baf1..bac8d9bfc 100644 --- a/include/updater/csv_file_parser.hpp +++ b/include/updater/csv_file_parser.hpp @@ -39,7 +39,7 @@ template struct CSVFilesParser { } - // Operator returns a lambda function that maps input Key to boost::optional. + // Operator returns a lambda function that maps input Key to std::optional. auto operator()(const std::vector &csv_filenames) const { try diff --git a/include/updater/source.hpp b/include/updater/source.hpp index 72bea7f54..852b21216 100644 --- a/include/updater/source.hpp +++ b/include/updater/source.hpp @@ -3,8 +3,7 @@ #include "util/typedefs.hpp" -#include - +#include #include namespace osrm::updater @@ -12,9 +11,9 @@ namespace osrm::updater template struct LookupTable { - boost::optional operator()(const Key &key) const + std::optional operator()(const Key &key) const { - using Result = boost::optional; + using Result = std::optional; const auto it = std::lower_bound(lookup.begin(), lookup.end(), @@ -50,7 +49,7 @@ struct SpeedSource final { SpeedSource() : speed(0.), rate() {} double speed; - boost::optional rate; + std::optional rate; std::uint8_t source; }; diff --git a/include/util/coordinate_calculation.hpp b/include/util/coordinate_calculation.hpp index 3ab8db076..1013555ed 100644 --- a/include/util/coordinate_calculation.hpp +++ b/include/util/coordinate_calculation.hpp @@ -4,11 +4,11 @@ #include "util/coordinate.hpp" #include -#include #include #include #include +#include #include #include @@ -36,6 +36,13 @@ inline double radToDeg(const double radian) } } // namespace detail +const constexpr static double METERS_PER_DEGREE_LAT = 110567.0; + +inline double metersPerLngDegree(const FixedLatitude lat) +{ + return std::cos(detail::degToRad(static_cast(toFloating(lat)))) * METERS_PER_DEGREE_LAT; +} + //! Takes the squared euclidean distance of the input coordinates. Does not return meters! std::uint64_t squaredEuclideanDistance(const Coordinate lhs, const Coordinate rhs); @@ -102,9 +109,9 @@ double bearing(const Coordinate first_coordinate, const Coordinate second_coordi double computeAngle(const Coordinate first, const Coordinate second, const Coordinate third); // find the center of a circle through three coordinates -boost::optional circleCenter(const Coordinate first_coordinate, - const Coordinate second_coordinate, - const Coordinate third_coordinate); +std::optional circleCenter(const Coordinate first_coordinate, + const Coordinate second_coordinate, + const Coordinate third_coordinate); // find the radius of a circle through three coordinates double circleRadius(const Coordinate first_coordinate, diff --git a/include/util/geojson_debug_policies.hpp b/include/util/geojson_debug_policies.hpp index 3a209db0a..0f25badd0 100644 --- a/include/util/geojson_debug_policies.hpp +++ b/include/util/geojson_debug_policies.hpp @@ -1,6 +1,7 @@ #ifndef OSRM_GEOJSON_DEBUG_POLICIES #define OSRM_GEOJSON_DEBUG_POLICIES +#include #include #include "extractor/query_node.hpp" @@ -9,8 +10,6 @@ #include "util/node_based_graph.hpp" #include "util/typedefs.hpp" -#include - namespace osrm::util { @@ -20,7 +19,7 @@ struct NodeIdVectorToLineString // converts a vector of node ids into a linestring geojson feature util::json::Object operator()(const std::vector &node_ids, - const boost::optional &properties = {}) const; + const std::optional &properties = {}) const; const std::vector &node_coordinates; }; @@ -29,7 +28,7 @@ struct CoordinateVectorToLineString { // converts a vector of node ids into a linestring geojson feature util::json::Object operator()(const std::vector &coordinates, - const boost::optional &properties = {}) const; + const std::optional &properties = {}) const; }; struct NodeIdVectorToMultiPoint @@ -38,7 +37,7 @@ struct NodeIdVectorToMultiPoint // converts a vector of node ids into a linestring geojson feature util::json::Object operator()(const std::vector &node_ids, - const boost::optional &properties = {}) const; + const std::optional &properties = {}) const; const std::vector &node_coordinates; }; @@ -47,7 +46,7 @@ struct CoordinateVectorToMultiPoint { // converts a vector of node ids into a linestring geojson feature util::json::Object operator()(const std::vector &coordinates, - const boost::optional &properties = {}) const; + const std::optional &properties = {}) const; }; } // namespace osrm::util diff --git a/include/util/geojson_debug_policy_toolkit.hpp b/include/util/geojson_debug_policy_toolkit.hpp index 62c1019ef..fcddc21a1 100644 --- a/include/util/geojson_debug_policy_toolkit.hpp +++ b/include/util/geojson_debug_policy_toolkit.hpp @@ -7,8 +7,7 @@ #include #include - -#include +#include namespace osrm::util { @@ -84,7 +83,7 @@ struct NodeIdToCoordinate inline util::json::Object makeFeature(std::string type, util::json::Array coordinates, - const boost::optional &properties = {}) + const std::optional &properties = {}) { util::json::Object result; result.values["type"] = "Feature"; diff --git a/include/util/guidance/bearing_class.hpp b/include/util/guidance/bearing_class.hpp index 9274a305c..1e5fce1eb 100644 --- a/include/util/guidance/bearing_class.hpp +++ b/include/util/guidance/bearing_class.hpp @@ -1,15 +1,14 @@ #ifndef OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_ #define OSRM_UTIL_GUIDANCE_BEARING_CLASS_HPP_ +#include "util/std_hash.hpp" +#include "util/typedefs.hpp" + #include #include #include #include -#include - -#include "util/typedefs.hpp" - namespace osrm::util::guidance { class BearingClass; @@ -62,7 +61,10 @@ namespace std inline size_t hash<::osrm::util::guidance::BearingClass>::operator()( const ::osrm::util::guidance::BearingClass &bearing_class) const { - return boost::hash_value(bearing_class.available_bearings); + std::size_t value = 0; + hash_range( + value, bearing_class.available_bearings.cbegin(), bearing_class.available_bearings.cend()); + return value; } } // namespace std diff --git a/include/util/guidance/turn_lanes.hpp b/include/util/guidance/turn_lanes.hpp index c19a5086c..21126ee16 100644 --- a/include/util/guidance/turn_lanes.hpp +++ b/include/util/guidance/turn_lanes.hpp @@ -1,36 +1,22 @@ #ifndef OSRM_UTIL_GUIDANCE_TURN_LANES_HPP #define OSRM_UTIL_GUIDANCE_TURN_LANES_HPP +#include "util/concurrent_id_map.hpp" +#include "util/std_hash.hpp" +#include "util/typedefs.hpp" + #include #include #include #include #include -#include "util/concurrent_id_map.hpp" -#include "util/typedefs.hpp" - -#include - namespace osrm::util::guidance { class LaneTuple; class LaneTupleIdPair; } // namespace osrm::util::guidance -namespace std -{ -template <> struct hash<::osrm::util::guidance::LaneTuple> -{ - inline std::size_t operator()(const ::osrm::util::guidance::LaneTuple &bearing_class) const; -}; -template <> struct hash<::osrm::util::guidance::LaneTupleIdPair> -{ - inline std::size_t - operator()(const ::osrm::util::guidance::LaneTupleIdPair &bearing_class) const; -}; -} // namespace std - namespace osrm::util::guidance { @@ -61,14 +47,6 @@ class LaneTuple LaneID lanes_in_turn; LaneID first_lane_from_the_right; // is INVALID_LANEID when no lanes present - - friend std::size_t hash_value(const LaneTuple &tup) - { - std::size_t seed{0}; - boost::hash_combine(seed, tup.lanes_in_turn); - boost::hash_combine(seed, tup.first_lane_from_the_right); - return seed; - } }; class LaneTupleIdPair @@ -78,18 +56,36 @@ class LaneTupleIdPair LaneDescriptionID second; bool operator==(const LaneTupleIdPair &other) const; +}; - friend std::size_t hash_value(const LaneTupleIdPair &pair) +using LaneDataIdMap = ConcurrentIDMap; + +} // namespace osrm::util::guidance + +namespace std +{ +template <> struct hash<::osrm::util::guidance::LaneTuple> +{ + inline std::size_t operator()(const ::osrm::util::guidance::LaneTuple &lane_tuple) const { std::size_t seed{0}; - boost::hash_combine(seed, pair.first); - boost::hash_combine(seed, pair.second); + hash_combine(seed, lane_tuple.lanes_in_turn); + hash_combine(seed, lane_tuple.first_lane_from_the_right); return seed; } }; -using LaneDataIdMap = ConcurrentIDMap>; - -} // namespace osrm::util::guidance +template <> struct hash<::osrm::util::guidance::LaneTupleIdPair> +{ + inline std::size_t + operator()(const ::osrm::util::guidance::LaneTupleIdPair &lane_tuple_id_pair) const + { + std::size_t seed{0}; + hash_combine(seed, lane_tuple_id_pair.first); + hash_combine(seed, lane_tuple_id_pair.second); + return seed; + } +}; +} // namespace std #endif /* OSRM_UTIL_GUIDANCE_TURN_LANES_HPP */ diff --git a/include/util/query_heap.hpp b/include/util/query_heap.hpp index 2c27ad745..c9f1fc6c5 100644 --- a/include/util/query_heap.hpp +++ b/include/util/query_heap.hpp @@ -3,12 +3,12 @@ #include #include -#include #include #include #include #include +#include #include #include @@ -290,26 +290,26 @@ class QueryHeap return inserted_nodes[index].node == node; } - boost::optional GetHeapNodeIfWasInserted(const NodeID node) + HeapNode *GetHeapNodeIfWasInserted(const NodeID node) { const auto index = node_index.peek_index(node); if (index >= static_cast(inserted_nodes.size()) || inserted_nodes[index].node != node) { - return {}; + return nullptr; } - return inserted_nodes[index]; + return &inserted_nodes[index]; } - boost::optional GetHeapNodeIfWasInserted(const NodeID node) const + const HeapNode *GetHeapNodeIfWasInserted(const NodeID node) const { const auto index = node_index.peek_index(node); if (index >= static_cast(inserted_nodes.size()) || inserted_nodes[index].node != node) { - return {}; + return nullptr; } - return inserted_nodes[index]; + return &inserted_nodes[index]; } NodeID Min() const diff --git a/include/util/rectangle.hpp b/include/util/rectangle.hpp index 65050f200..aca192446 100644 --- a/include/util/rectangle.hpp +++ b/include/util/rectangle.hpp @@ -3,7 +3,6 @@ #include "util/coordinate.hpp" #include "util/coordinate_calculation.hpp" - #include #include @@ -168,6 +167,18 @@ struct RectangleInt2D min_lat != FixedLatitude{std::numeric_limits::max()} && max_lat != FixedLatitude{std::numeric_limits::min()}; } + + static RectangleInt2D ExpandMeters(const Coordinate &coordinate, const double meters) + { + const double lat_offset = meters / coordinate_calculation::METERS_PER_DEGREE_LAT; + const double lon_offset = + meters / coordinate_calculation::metersPerLngDegree(coordinate.lat); + + return RectangleInt2D{coordinate.lon - toFixed(FloatLongitude{lon_offset}), + coordinate.lon + toFixed(FloatLongitude{lon_offset}), + coordinate.lat - toFixed(FloatLatitude{lat_offset}), + coordinate.lat + toFixed(FloatLatitude{lat_offset})}; + } }; } // namespace osrm::util diff --git a/include/util/static_rtree.hpp b/include/util/static_rtree.hpp index 3f6b1d986..f9d72c144 100644 --- a/include/util/static_rtree.hpp +++ b/include/util/static_rtree.hpp @@ -2,7 +2,6 @@ #define STATIC_RTREE_HPP #include "storage/tar_fwd.hpp" - #include "util/bearing.hpp" #include "util/coordinate_calculation.hpp" #include "util/deallocating_vector.hpp" @@ -11,6 +10,7 @@ #include "util/integer_range.hpp" #include "util/mmap_file.hpp" #include "util/rectangle.hpp" +#include "util/timing_util.hpp" #include "util/typedefs.hpp" #include "util/vector_view.hpp" #include "util/web_mercator.hpp" @@ -487,70 +487,9 @@ class StaticRTree Rectangle needs to be projected!*/ std::vector SearchInBox(const Rectangle &search_rectangle) const { - const Rectangle projected_rectangle{ - search_rectangle.min_lon, - search_rectangle.max_lon, - toFixed(FloatLatitude{ - web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.min_lat)))}), - toFixed(FloatLatitude{ - web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})}; std::vector results; - - std::queue traversal_queue; - traversal_queue.push(TreeIndex{}); - - while (!traversal_queue.empty()) - { - auto const current_tree_index = traversal_queue.front(); - traversal_queue.pop(); - - // If we're at the bottom of the tree, we need to explore the - // element array - if (is_leaf(current_tree_index)) - { - - // Note: irange is [start,finish), so we need to +1 to make sure we visit the - // last - for (const auto current_child_index : child_indexes(current_tree_index)) - { - const auto ¤t_edge = m_objects[current_child_index]; - - // we don't need to project the coordinates here, - // because we use the unprojected rectangle to test against - const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon, - m_coordinate_list[current_edge.v].lon), - std::max(m_coordinate_list[current_edge.u].lon, - m_coordinate_list[current_edge.v].lon), - std::min(m_coordinate_list[current_edge.u].lat, - m_coordinate_list[current_edge.v].lat), - std::max(m_coordinate_list[current_edge.u].lat, - m_coordinate_list[current_edge.v].lat)}; - - // use the _unprojected_ input rectangle here - if (bbox.Intersects(search_rectangle)) - { - results.push_back(current_edge); - } - } - } - else - { - BOOST_ASSERT(current_tree_index.level + 1 < m_tree_level_starts.size()); - - for (const auto child_index : child_indexes(current_tree_index)) - { - const auto &child_rectangle = - m_search_tree[child_index].minimum_bounding_rectangle; - - if (child_rectangle.Intersects(projected_rectangle)) - { - traversal_queue.push(TreeIndex( - current_tree_index.level + 1, - child_index - m_tree_level_starts[current_tree_index.level + 1])); - } - } - } - } + SearchInBox(search_rectangle, + [&results](const auto &edge_data) { results.push_back(edge_data); }); return results; } @@ -565,6 +504,45 @@ class StaticRTree { return num_results >= max_results; }); } + // NB 1: results are not guaranteed to be sorted by distance + // NB 2: maxDistanceMeters is not a hard limit, it's just a way to reduce the number of edges + // returned + template + std::vector SearchInRange(const Coordinate input_coordinate, + double maxDistanceMeters, + const FilterT filter) const + { + auto projected_coordinate = web_mercator::fromWGS84(input_coordinate); + Coordinate fixed_projected_coordinate{projected_coordinate}; + + auto bbox = Rectangle::ExpandMeters(input_coordinate, maxDistanceMeters); + std::vector results; + + SearchInBox( + bbox, + [&results, &filter, fixed_projected_coordinate, this](const EdgeDataT ¤t_edge) + { + const auto projected_u = web_mercator::fromWGS84(m_coordinate_list[current_edge.u]); + const auto projected_v = web_mercator::fromWGS84(m_coordinate_list[current_edge.v]); + + auto [_, projected_nearest] = coordinate_calculation::projectPointOnSegment( + projected_u, projected_v, fixed_projected_coordinate); + + CandidateSegment current_candidate{projected_nearest, current_edge}; + auto use_segment = filter(current_candidate); + if (!use_segment.first && !use_segment.second) + { + return; + } + current_candidate.data.forward_segment_id.enabled &= use_segment.first; + current_candidate.data.reverse_segment_id.enabled &= use_segment.second; + + results.push_back(current_candidate); + }); + + return results; + } + // Return edges in distance order with the coordinate of the closest point on the edge. template std::vector Nearest(const Coordinate input_coordinate, @@ -572,8 +550,10 @@ class StaticRTree const TerminationT terminate) const { std::vector results; + auto projected_coordinate = web_mercator::fromWGS84(input_coordinate); Coordinate fixed_projected_coordinate{projected_coordinate}; + // initialize queue with root element std::priority_queue traversal_queue; traversal_queue.push(QueryCandidate{0, TreeIndex{}}); @@ -631,6 +611,73 @@ class StaticRTree } private: + template + void SearchInBox(const Rectangle &search_rectangle, Callback &&callback) const + { + const Rectangle projected_rectangle{ + search_rectangle.min_lon, + search_rectangle.max_lon, + toFixed(FloatLatitude{ + web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.min_lat)))}), + toFixed(FloatLatitude{ + web_mercator::latToY(toFloating(FixedLatitude(search_rectangle.max_lat)))})}; + std::queue traversal_queue; + traversal_queue.push(TreeIndex{}); + + while (!traversal_queue.empty()) + { + auto const current_tree_index = traversal_queue.front(); + traversal_queue.pop(); + + // If we're at the bottom of the tree, we need to explore the + // element array + if (is_leaf(current_tree_index)) + { + + // Note: irange is [start,finish), so we need to +1 to make sure we visit the + // last + for (const auto current_child_index : child_indexes(current_tree_index)) + { + const auto ¤t_edge = m_objects[current_child_index]; + + // we don't need to project the coordinates here, + // because we use the unprojected rectangle to test against + const Rectangle bbox{std::min(m_coordinate_list[current_edge.u].lon, + m_coordinate_list[current_edge.v].lon), + std::max(m_coordinate_list[current_edge.u].lon, + m_coordinate_list[current_edge.v].lon), + std::min(m_coordinate_list[current_edge.u].lat, + m_coordinate_list[current_edge.v].lat), + std::max(m_coordinate_list[current_edge.u].lat, + m_coordinate_list[current_edge.v].lat)}; + + // use the _unprojected_ input rectangle here + if (bbox.Intersects(search_rectangle)) + { + callback(current_edge); + } + } + } + else + { + BOOST_ASSERT(current_tree_index.level + 1 < m_tree_level_starts.size()); + + for (const auto child_index : child_indexes(current_tree_index)) + { + const auto &child_rectangle = + m_search_tree[child_index].minimum_bounding_rectangle; + + if (child_rectangle.Intersects(projected_rectangle)) + { + traversal_queue.push(TreeIndex( + current_tree_index.level + 1, + child_index - m_tree_level_starts[current_tree_index.level + 1])); + } + } + } + } + } + /** * Iterates over all the objects in a leaf node and inserts them into our * search priority queue. The speed of this function is very much governed diff --git a/include/util/std_hash.hpp b/include/util/std_hash.hpp index 16bf278dc..4f64f940d 100644 --- a/include/util/std_hash.hpp +++ b/include/util/std_hash.hpp @@ -1,7 +1,11 @@ #ifndef STD_HASH_HPP #define STD_HASH_HPP +#include #include +#include +#include +#include // this is largely inspired by boost's hash combine as can be found in // "The C++ Standard Library" 2nd Edition. Nicolai M. Josuttis. 2012. @@ -11,6 +15,14 @@ template void hash_combine(std::size_t &seed, const T &val) seed ^= std::hash()(val) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } +template void hash_range(std::size_t &seed, It first, const It last) +{ + for (; first != last; ++first) + { + hash_combine(seed, *first); + } +} + template void hash_val(std::size_t &seed, const T &val) { hash_combine(seed, val); } template @@ -29,13 +41,39 @@ template std::size_t hash_val(const Types &...args) namespace std { +template struct hash> +{ + template + static auto apply_tuple(const std::tuple &t, std::index_sequence) + { + std::size_t seed = 0; + return ((seed = hash_val(std::get(t), seed)), ...); + } + + auto operator()(const std::tuple &t) const + { + return apply_tuple(t, std::make_index_sequence()); + } +}; + template struct hash> { - size_t operator()(const std::pair &pair) const + std::size_t operator()(const std::pair &pair) const { return hash_val(pair.first, pair.second); } }; + +template struct hash> +{ + auto operator()(const std::vector &lane_description) const + { + std::size_t seed = 0; + hash_range(seed, lane_description.begin(), lane_description.end()); + return seed; + } +}; + } // namespace std #endif // STD_HASH_HPP diff --git a/include/util/timezones.hpp b/include/util/timezones.hpp index 9e8512c90..e144662de 100644 --- a/include/util/timezones.hpp +++ b/include/util/timezones.hpp @@ -5,12 +5,12 @@ #include #include -#include #include #include #include +#include namespace osrm::updater { @@ -34,7 +34,7 @@ class Timezoner Timezoner(const char geojson[], std::time_t utc_time_now); Timezoner(const std::filesystem::path &tz_shapes_filename, std::time_t utc_time_now); - boost::optional operator()(const point_t &point) const; + std::optional operator()(const point_t &point) const; private: void LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t utc_time); diff --git a/include/util/trigonometry_table.hpp b/include/util/trigonometry_table.hpp index eedfe59a5..412674960 100644 --- a/include/util/trigonometry_table.hpp +++ b/include/util/trigonometry_table.hpp @@ -364,7 +364,6 @@ const constexpr double SCALING_FACTOR = 4. / boost::math::constants::pi( inline double atan2_lookup(double y, double x) { - using namespace boost::math::constants; if (std::abs(x) < std::numeric_limits::epsilon()) diff --git a/scripts/ci/post_benchmark_results.py b/scripts/ci/post_benchmark_results.py index 3efd5fcad..a5dc38aa5 100644 --- a/scripts/ci/post_benchmark_results.py +++ b/scripts/ci/post_benchmark_results.py @@ -71,9 +71,9 @@ def main(): benchmark_results = collect_benchmark_results(base_folder, pr_folder) pr_details = get_pr_details(REPO_OWNER, REPO_NAME, PR_NUMBER) - pr_body = pr_details.get('body', '') + # in both cases when there is no PR body or PR body is None fallback to empty string + pr_body = pr_details.get('body', '') or '' - markdown_table = create_markdown_table(benchmark_results) new_benchmark_section = f"\n## Benchmark Results\n{markdown_table}\n" @@ -85,7 +85,7 @@ def main(): flags=re.DOTALL ) else: - updated_body = f"{pr_body}\n\n{new_benchmark_section}" + updated_body = f"{pr_body}\n\n{new_benchmark_section}" if len(pr_body) > 0 else new_benchmark_section update_pr_description(REPO_OWNER, REPO_NAME, PR_NUMBER, updated_body) print("PR description updated successfully.") diff --git a/scripts/ci/run_benchmarks.sh b/scripts/ci/run_benchmarks.sh index 94cf57a57..6aea4e089 100755 --- a/scripts/ci/run_benchmarks.sh +++ b/scripts/ci/run_benchmarks.sh @@ -13,6 +13,8 @@ function run_benchmarks_for_folder { ./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/match_mld.bench" ./$BENCHMARKS_FOLDER/match-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/match_ch.bench" + ./$BENCHMARKS_FOLDER/route-bench "./$FOLDER/test/data/mld/monaco.osrm" mld > "$RESULTS_FOLDER/route_mld.bench" || true # TODO: remove `true` when this benchmark will be merged to master + ./$BENCHMARKS_FOLDER/route-bench "./$FOLDER/test/data/ch/monaco.osrm" ch > "$RESULTS_FOLDER/route_ch.bench" || true # TODO: remove `true` when this benchmark will be merged to master ./$BENCHMARKS_FOLDER/alias-bench > "$RESULTS_FOLDER/alias.bench" ./$BENCHMARKS_FOLDER/json-render-bench "./$FOLDER/src/benchmarks/portugal_to_korea.json" > "$RESULTS_FOLDER/json-render.bench" ./$BENCHMARKS_FOLDER/packedvector-bench > "$RESULTS_FOLDER/packedvector.bench" diff --git a/src/benchmarks/CMakeLists.txt b/src/benchmarks/CMakeLists.txt index 233445c4b..86353dbbf 100644 --- a/src/benchmarks/CMakeLists.txt +++ b/src/benchmarks/CMakeLists.txt @@ -30,6 +30,18 @@ target_link_libraries(match-bench ${TBB_LIBRARIES} ${MAYBE_SHAPEFILE}) +add_executable(route-bench + EXCLUDE_FROM_ALL + route.cpp + $) + +target_link_libraries(route-bench + osrm + ${BOOST_BASE_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${TBB_LIBRARIES} + ${MAYBE_SHAPEFILE}) + add_executable(json-render-bench EXCLUDE_FROM_ALL json_render.cpp @@ -72,5 +84,6 @@ add_custom_target(benchmarks rtree-bench packedvector-bench match-bench + route-bench json-render-bench - alias-bench) + alias-bench) diff --git a/src/benchmarks/match.cpp b/src/benchmarks/match.cpp index caed1a00b..cece7960b 100644 --- a/src/benchmarks/match.cpp +++ b/src/benchmarks/match.cpp @@ -12,13 +12,14 @@ #include +#include #include #include +#include +#include #include #include -#include - int main(int argc, const char *argv[]) try { @@ -214,24 +215,49 @@ try params.coordinates.push_back( FloatCoordinate{FloatLongitude{7.415342330932617}, FloatLatitude{43.733251335381205}}); - TIMER_START(routes); - auto NUM = 100; - for (int i = 0; i < NUM; ++i) + auto run_benchmark = [&](std::optional radiusInMeters) { - engine::api::ResultT result = json::Object(); - const auto rc = osrm.Match(params, result); - auto &json_result = result.get(); - if (rc != Status::Ok || - json_result.values.at("matchings").get().values.size() != 1) + params.radiuses = {}; + if (radiusInMeters) { - return EXIT_FAILURE; + for (size_t index = 0; index < params.coordinates.size(); ++index) + { + params.radiuses.emplace_back(*radiusInMeters); + } } + + TIMER_START(routes); + auto NUM = 100; + for (int i = 0; i < NUM; ++i) + { + engine::api::ResultT result = json::Object(); + const auto rc = osrm.Match(params, result); + auto &json_result = result.get(); + if (rc != Status::Ok || + json_result.values.at("matchings").get().values.size() != 1) + { + throw std::runtime_error{"Couldn't match"}; + } + } + TIMER_STOP(routes); + if (radiusInMeters) + { + std::cout << "Radius " << *radiusInMeters << "m: " << std::endl; + } + else + { + std::cout << "Default radius: " << std::endl; + } + std::cout << (TIMER_MSEC(routes) / NUM) << "ms/req at " << params.coordinates.size() + << " coordinate" << std::endl; + std::cout << (TIMER_MSEC(routes) / NUM / params.coordinates.size()) << "ms/coordinate" + << std::endl; + }; + + for (auto radius : std::vector>{std::nullopt, 5.0, 10.0, 15.0, 30.0}) + { + run_benchmark(radius); } - TIMER_STOP(routes); - std::cout << (TIMER_MSEC(routes) / NUM) << "ms/req at " << params.coordinates.size() - << " coordinate" << std::endl; - std::cout << (TIMER_MSEC(routes) / NUM / params.coordinates.size()) << "ms/coordinate" - << std::endl; return EXIT_SUCCESS; } @@ -239,4 +265,4 @@ catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; -} +} \ No newline at end of file diff --git a/src/benchmarks/route.cpp b/src/benchmarks/route.cpp new file mode 100644 index 000000000..ea95d06fb --- /dev/null +++ b/src/benchmarks/route.cpp @@ -0,0 +1,166 @@ +#include "engine/engine_config.hpp" +#include "util/coordinate.hpp" +#include "util/timing_util.hpp" + +#include "osrm/route_parameters.hpp" + +#include "osrm/coordinate.hpp" +#include "osrm/engine_config.hpp" +#include "osrm/json_container.hpp" + +#include "osrm/osrm.hpp" +#include "osrm/status.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, const char *argv[]) +try +{ + if (argc < 2) + { + std::cerr << "Usage: " << argv[0] << " data.osrm\n"; + return EXIT_FAILURE; + } + + using namespace osrm; + + // Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore + EngineConfig config; + config.storage_config = {argv[1]}; + config.algorithm = (argc > 2 && std::string{argv[2]} == "mld") ? EngineConfig::Algorithm::MLD + : EngineConfig::Algorithm::CH; + config.use_shared_memory = false; + + // Routing machine with several services (such as Route, Table, Nearest, Trip, Match) + OSRM osrm{config}; + + struct Benchmark + { + std::string name; + std::vector coordinates; + RouteParameters::OverviewType overview; + bool steps = false; + std::optional alternatives = std::nullopt; + std::optional radius = std::nullopt; + }; + + auto run_benchmark = [&](const Benchmark &benchmark) + { + RouteParameters params; + params.overview = benchmark.overview; + params.steps = benchmark.steps; + params.coordinates = benchmark.coordinates; + if (benchmark.alternatives) + { + params.alternatives = *benchmark.alternatives; + } + + if (benchmark.radius) + { + params.radiuses = std::vector>( + params.coordinates.size(), boost::make_optional(*benchmark.radius)); + } + + TIMER_START(routes); + auto NUM = 1000; + for (int i = 0; i < NUM; ++i) + { + engine::api::ResultT result = json::Object(); + const auto rc = osrm.Route(params, result); + auto &json_result = result.get(); + if (rc != Status::Ok || json_result.values.find("routes") == json_result.values.end()) + { + throw std::runtime_error{"Couldn't route"}; + } + } + TIMER_STOP(routes); + std::cout << benchmark.name << std::endl; + std::cout << TIMER_MSEC(routes) << "ms" << std::endl; + std::cout << TIMER_MSEC(routes) / NUM << "ms/req" << std::endl; + }; + + std::vector benchmarks = { + {"1000 routes, 3 coordinates, no alternatives, overview=full, steps=true", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.421844922513342}, FloatLatitude{43.73690777888953}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::Full, + true, + std::nullopt}, + {"1000 routes, 2 coordinates, no alternatives, overview=full, steps=true", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::Full, + true, + std::nullopt}, + {"1000 routes, 2 coordinates, 3 alternatives, overview=full, steps=true", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::Full, + true, + 3}, + {"1000 routes, 3 coordinates, no alternatives, overview=false, steps=false", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.421844922513342}, FloatLatitude{43.73690777888953}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::False, + false, + std::nullopt}, + {"1000 routes, 2 coordinates, no alternatives, overview=false, steps=false", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::False, + false, + std::nullopt}, + {"1000 routes, 2 coordinates, 3 alternatives, overview=false, steps=false", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::False, + false, + 3}, + {"1000 routes, 3 coordinates, no alternatives, overview=false, steps=false, radius=750", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.421844922513342}, FloatLatitude{43.73690777888953}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::False, + false, + std::nullopt, + 750}, + {"1000 routes, 2 coordinates, no alternatives, overview=false, steps=false, radius=750", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::False, + false, + std::nullopt, + 750}, + {"1000 routes, 2 coordinates, 3 alternatives, overview=false, steps=false, radius=750", + {{FloatLongitude{7.437602352715465}, FloatLatitude{43.75030522209604}}, + {FloatLongitude{7.412303912230966}, FloatLatitude{43.72851046529198}}}, + RouteParameters::OverviewType::False, + false, + 3, + 750} + + }; + + for (const auto &benchmark : benchmarks) + { + run_benchmark(benchmark); + } + + return EXIT_SUCCESS; +} +catch (const std::exception &e) +{ + std::cerr << "Error: " << e.what() << std::endl; + return EXIT_FAILURE; +} diff --git a/src/engine/routing_algorithms/map_matching.cpp b/src/engine/routing_algorithms/map_matching.cpp index 3bbf96c22..9f8a1d2a5 100644 --- a/src/engine/routing_algorithms/map_matching.cpp +++ b/src/engine/routing_algorithms/map_matching.cpp @@ -49,7 +49,7 @@ inline void initializeHeap(SearchEngineData &engine_working_data, { const auto nodes_number = facade.GetNumberOfNodes(); - engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number); + engine_working_data.InitializeOrClearMapMatchingThreadLocalStorage(nodes_number); } template <> @@ -59,7 +59,8 @@ inline void initializeHeap(SearchEngineData &eng const auto nodes_number = facade.GetNumberOfNodes(); const auto border_nodes_number = facade.GetMaxBorderNodeID() + 1; - engine_working_data.InitializeOrClearFirstThreadLocalStorage(nodes_number, border_nodes_number); + engine_working_data.InitializeOrClearMapMatchingThreadLocalStorage(nodes_number, + border_nodes_number); } } // namespace @@ -144,8 +145,8 @@ SubMatchingList mapMatching(SearchEngineData &engine_working_data, } initializeHeap(engine_working_data, facade); - auto &forward_heap = *engine_working_data.forward_heap_1; - auto &reverse_heap = *engine_working_data.reverse_heap_1; + auto &forward_heap = *engine_working_data.map_matching_forward_heap_1; + auto &reverse_heap = *engine_working_data.map_matching_reverse_heap_1; std::size_t breakage_begin = map_matching::INVALID_STATE; std::vector split_points; diff --git a/src/engine/search_engine_data.cpp b/src/engine/search_engine_data.cpp index a4a2bc5dd..dd1a053e0 100644 --- a/src/engine/search_engine_data.cpp +++ b/src/engine/search_engine_data.cpp @@ -11,8 +11,32 @@ SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_2; SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_2; SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_3; SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_3; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::map_matching_forward_heap_1; +SearchEngineData::SearchEngineHeapPtr SearchEngineData::map_matching_reverse_heap_1; + SearchEngineData::ManyToManyHeapPtr SearchEngineData::many_to_many_heap; +void SearchEngineData::InitializeOrClearMapMatchingThreadLocalStorage(unsigned number_of_nodes) +{ + if (map_matching_forward_heap_1.get()) + { + map_matching_forward_heap_1->Clear(); + } + else + { + map_matching_forward_heap_1.reset(new QueryHeap(number_of_nodes)); + } + + if (map_matching_reverse_heap_1.get()) + { + map_matching_reverse_heap_1->Clear(); + } + else + { + map_matching_reverse_heap_1.reset(new QueryHeap(number_of_nodes)); + } +} + void SearchEngineData::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes) { if (forward_heap_1.get()) @@ -92,8 +116,34 @@ void SearchEngineData::InitializeOrClearManyToManyThreadLocalStorage(unsigne using MLD = routing_algorithms::mld::Algorithm; SearchEngineData::SearchEngineHeapPtr SearchEngineData::forward_heap_1; SearchEngineData::SearchEngineHeapPtr SearchEngineData::reverse_heap_1; +SearchEngineData::MapMatchingHeapPtr SearchEngineData::map_matching_forward_heap_1; +SearchEngineData::MapMatchingHeapPtr SearchEngineData::map_matching_reverse_heap_1; SearchEngineData::ManyToManyHeapPtr SearchEngineData::many_to_many_heap; +void SearchEngineData::InitializeOrClearMapMatchingThreadLocalStorage( + unsigned number_of_nodes, unsigned number_of_boundary_nodes) +{ + if (map_matching_forward_heap_1.get()) + { + map_matching_forward_heap_1->Clear(); + } + else + { + map_matching_forward_heap_1.reset( + new MapMatchingQueryHeap(number_of_nodes, number_of_boundary_nodes)); + } + + if (map_matching_reverse_heap_1.get()) + { + map_matching_reverse_heap_1->Clear(); + } + else + { + map_matching_reverse_heap_1.reset( + new MapMatchingQueryHeap(number_of_nodes, number_of_boundary_nodes)); + } +} + void SearchEngineData::InitializeOrClearFirstThreadLocalStorage( unsigned number_of_nodes, unsigned number_of_boundary_nodes) { diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index a84fdbebe..bc50a031e 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -19,7 +19,6 @@ #include "util/timing_util.hpp" #include -#include #include #include diff --git a/src/extractor/extraction_containers.cpp b/src/extractor/extraction_containers.cpp index bea449390..eed6a3c43 100644 --- a/src/extractor/extraction_containers.cpp +++ b/src/extractor/extraction_containers.cpp @@ -13,6 +13,7 @@ #include "util/for_each_indexed.hpp" #include "util/for_each_pair.hpp" #include "util/log.hpp" +#include "util/std_hash.hpp" #include "util/timing_util.hpp" #include @@ -955,8 +956,7 @@ void ExtractionContainers::PrepareTrafficSignals( TIMER_START(prepare_traffic_signals); std::unordered_set bidirectional; - std::unordered_set, boost::hash>> - unidirectional; + std::unordered_set> unidirectional; for (const auto &osm_node : bidirectional_signal_nodes) { diff --git a/src/extractor/intersection/node_based_graph_walker.cpp b/src/extractor/intersection/node_based_graph_walker.cpp index 3f3b67fb9..c1ee0fc64 100644 --- a/src/extractor/intersection/node_based_graph_walker.cpp +++ b/src/extractor/intersection/node_based_graph_walker.cpp @@ -66,7 +66,7 @@ SelectRoadByNameOnlyChoiceAndStraightness::SelectRoadByNameOnlyChoiceAndStraight { } -boost::optional SelectRoadByNameOnlyChoiceAndStraightness::operator()( +std::optional SelectRoadByNameOnlyChoiceAndStraightness::operator()( const NodeID /*nid*/, const EdgeID /*via_edge_id*/, const IntersectionView &intersection, @@ -118,7 +118,7 @@ SelectStraightmostRoadByNameAndOnlyChoice::SelectStraightmostRoadByNameAndOnlyCh { } -boost::optional SelectStraightmostRoadByNameAndOnlyChoice::operator()( +std::optional SelectStraightmostRoadByNameAndOnlyChoice::operator()( const NodeID /*nid*/, const EdgeID /*via_edge_id*/, const IntersectionView &intersection, @@ -241,7 +241,7 @@ boost::optional SelectStraightmostRoadByNameAndOnlyChoice::operator()( return {}; } - return is_only_choice_with_same_name ? boost::optional(min_element->eid) : boost::none; + return is_only_choice_with_same_name ? std::optional(min_element->eid) : std::nullopt; } // --------------------------------------------------------------------------------- diff --git a/src/extractor/maneuver_override_relation_parser.cpp b/src/extractor/maneuver_override_relation_parser.cpp index 737edf670..a0fcb2d1a 100644 --- a/src/extractor/maneuver_override_relation_parser.cpp +++ b/src/extractor/maneuver_override_relation_parser.cpp @@ -1,9 +1,9 @@ #include "extractor/maneuver_override_relation_parser.hpp" #include "extractor/maneuver_override.hpp" -#include #include +#include #include #include #include @@ -21,7 +21,7 @@ ManeuverOverrideRelationParser::ManeuverOverrideRelationParser() {} * into an InputManeuverOverride object, if the relation is considered * valid (i.e. has the minimum tags we expect). */ -boost::optional +std::optional ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const { @@ -35,7 +35,7 @@ ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const if (osmium::tags::match_none_of(tag_list, filter)) // if it's not a maneuver, continue; { - return boost::none; + return std::nullopt; } // we pretend every restriction is a conditional restriction. If we do not find any restriction, @@ -130,7 +130,7 @@ ManeuverOverrideRelationParser::TryParse(const osmium::Relation &relation) const } else { - return boost::none; + return std::nullopt; } return maneuver_override; } diff --git a/src/guidance/intersection_handler.cpp b/src/guidance/intersection_handler.cpp index 5fe6bc21a..b11597d5f 100644 --- a/src/guidance/intersection_handler.cpp +++ b/src/guidance/intersection_handler.cpp @@ -427,7 +427,7 @@ void IntersectionHandler::assignTrivialTurns(const EdgeID via_eid, } } -boost::optional +std::optional IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) const { // We use the intersection generator to jump over traffic signals, barriers. The intersection @@ -450,7 +450,7 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons if (intersection_parameters.node == SPECIAL_NODEID || intersection_parameters.edge == SPECIAL_EDGEID) { - return boost::none; + return std::nullopt; } auto intersection = extractor::intersection::getConnectedRoads(node_based_graph, @@ -465,11 +465,10 @@ IntersectionHandler::getNextIntersection(const NodeID at, const EdgeID via) cons if (intersection.size() <= 2 || intersection.isTrafficSignalOrBarrier()) { - return boost::none; + return std::nullopt; } - return boost::make_optional( - IntersectionViewAndNode{std::move(intersection), intersection_node}); + return std::make_optional(IntersectionViewAndNode{std::move(intersection), intersection_node}); } bool IntersectionHandler::isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const diff --git a/src/guidance/sliproad_handler.cpp b/src/guidance/sliproad_handler.cpp index 5339ed6c6..90a92801f 100644 --- a/src/guidance/sliproad_handler.cpp +++ b/src/guidance/sliproad_handler.cpp @@ -634,7 +634,7 @@ Intersection SliproadHandler::operator()(const NodeID /*nid*/, // Implementation details -boost::optional SliproadHandler::getObviousIndexWithSliproads( +std::optional SliproadHandler::getObviousIndexWithSliproads( const EdgeID from, const Intersection &intersection, const NodeID at) const { BOOST_ASSERT(from != SPECIAL_EDGEID); @@ -645,14 +645,14 @@ boost::optional SliproadHandler::getObviousIndexWithSliproads( if (index != 0) { - return boost::make_optional(index); + return std::make_optional(index); } // Otherwise check if the road is forking into two and one of them is a Sliproad; // then the non-Sliproad is the obvious one. if (intersection.size() != 3) { - return boost::none; + return std::nullopt; } const auto forking = intersection[1].instruction.type == TurnType::Fork && @@ -660,7 +660,7 @@ boost::optional SliproadHandler::getObviousIndexWithSliproads( if (!forking) { - return boost::none; + return std::nullopt; } const auto first = getNextIntersection(at, intersection.getRightmostRoad().eid); @@ -668,27 +668,27 @@ boost::optional SliproadHandler::getObviousIndexWithSliproads( if (!first || !second) { - return boost::none; + return std::nullopt; } if (first->intersection.isDeadEnd() || second->intersection.isDeadEnd()) { - return boost::none; + return std::nullopt; } // In case of loops at the end of the road, we will arrive back at the intersection // itself. If that is the case, the road is obviously not a sliproad. if (canBeTargetOfSliproad(first->intersection) && at != second->node) { - return boost::make_optional(std::size_t{2}); + return std::make_optional(std::size_t{2}); } if (canBeTargetOfSliproad(second->intersection) && at != first->node) { - return boost::make_optional(std::size_t{1}); + return std::make_optional(std::size_t{1}); } - return boost::none; + return std::nullopt; } bool SliproadHandler::nextIntersectionIsTooFarAway(const NodeID start, const EdgeID onto) const diff --git a/src/guidance/turn_handler.cpp b/src/guidance/turn_handler.cpp index ec77b6356..0a7724360 100644 --- a/src/guidance/turn_handler.cpp +++ b/src/guidance/turn_handler.cpp @@ -6,10 +6,10 @@ #include #include +#include #include #include -#include using osrm::util::angularDeviation; @@ -590,7 +590,7 @@ Intersection TurnHandler::assignRightTurns(const EdgeID via_edge, } // finds a fork candidate by just looking at the geometry and angle of an intersection -boost::optional +std::optional TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const { if (intersection.size() >= 3) @@ -647,7 +647,7 @@ TurnHandler::findForkCandidatesByGeometry(Intersection &intersection) const } } } - return boost::none; + return std::nullopt; } // check if the fork candidates (all roads between left and right) and the @@ -695,8 +695,8 @@ bool TurnHandler::isCompatibleByRoadClass(const Intersection &intersection, cons // Checks whether a three-way-intersection coming from `via_edge` is a fork // with `intersection` as described as in #IntersectionExplanation@intersection_handler.hpp -boost::optional TurnHandler::findFork(const EdgeID via_edge, - Intersection &intersection) const +std::optional TurnHandler::findFork(const EdgeID via_edge, + Intersection &intersection) const { auto fork = findForkCandidatesByGeometry(intersection); if (fork) @@ -740,7 +740,7 @@ boost::optional TurnHandler::findFork(const EdgeID via_edge, } } - return boost::none; + return std::nullopt; } void TurnHandler::handleDistinctConflict(const EdgeID via_edge, diff --git a/src/updater/updater.cpp b/src/updater/updater.cpp index c3ec35f05..165d2387d 100644 --- a/src/updater/updater.cpp +++ b/src/updater/updater.cpp @@ -18,6 +18,7 @@ #include "util/mmap_tar.hpp" #include "util/opening_hours.hpp" #include "util/static_rtree.hpp" +#include "util/std_hash.hpp" #include "util/string_util.hpp" #include "util/timezones.hpp" #include "util/timing_util.hpp" @@ -42,25 +43,6 @@ #include #include -namespace std -{ -template struct hash> -{ - size_t operator()(const std::tuple &t) const - { - return hash_val(std::get<0>(t), std::get<1>(t), std::get<2>(t)); - } -}; - -template struct hash> -{ - size_t operator()(const std::tuple &t) const - { - return hash_val(std::get<0>(t), std::get<1>(t)); - } -}; -} // namespace std - namespace osrm::updater { namespace diff --git a/src/util/coordinate_calculation.cpp b/src/util/coordinate_calculation.cpp index 70a0d2cb4..00c5efbf5 100644 --- a/src/util/coordinate_calculation.cpp +++ b/src/util/coordinate_calculation.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace osrm::util::coordinate_calculation @@ -173,14 +174,14 @@ double computeAngle(const Coordinate first, const Coordinate second, const Coord return angle; } -boost::optional +std::optional circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) { // free after http://paulbourke.net/geometry/circlesphere/ // require three distinct points if (C1 == C2 || C2 == C3 || C1 == C3) { - return boost::none; + return std::nullopt; } // define line through c1, c2 and c2,c3 @@ -195,7 +196,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) (std::abs(C2C1_lat) < std::numeric_limits::epsilon() && std::abs(C3C2_lat) < std::numeric_limits::epsilon())) { - return boost::none; + return std::nullopt; } else if (std::abs(C2C1_lon) < std::numeric_limits::epsilon()) { @@ -233,7 +234,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) // can this ever happen? if (std::abs(C2C1_slope - C3C2_slope) < std::numeric_limits::epsilon()) - return boost::none; + return std::nullopt; const double C1_y = static_cast(toFloating(C1.lat)); const double C1_x = static_cast(toFloating(C1.lon)); @@ -247,7 +248,7 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3) (2 * (C3C2_slope - C2C1_slope)); const double lat = (0.5 * (C1_x + C2_x) - lon) / C2C1_slope + 0.5 * (C1_y + C2_y); if (lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0) - return boost::none; + return std::nullopt; else return Coordinate(FloatLongitude{lon}, FloatLatitude{lat}); } diff --git a/src/util/geojson_debug_policies.cpp b/src/util/geojson_debug_policies.cpp index afdba87ab..9fd2ad60d 100644 --- a/src/util/geojson_debug_policies.cpp +++ b/src/util/geojson_debug_policies.cpp @@ -17,7 +17,7 @@ NodeIdVectorToLineString::NodeIdVectorToLineString( // converts a vector of node ids into a linestring geojson feature util::json::Object NodeIdVectorToLineString::operator()(const std::vector &node_ids, - const boost::optional &properties) const + const std::optional &properties) const { util::json::Array coordinates; std::transform(node_ids.begin(), @@ -37,7 +37,7 @@ NodeIdVectorToMultiPoint::NodeIdVectorToMultiPoint( util::json::Object NodeIdVectorToMultiPoint::operator()(const std::vector &node_ids, - const boost::optional &properties) const + const std::optional &properties) const { util::json::Array coordinates; std::transform(node_ids.begin(), @@ -51,7 +51,7 @@ NodeIdVectorToMultiPoint::operator()(const std::vector &node_ids, //---------------------------------------------------------------- util::json::Object CoordinateVectorToMultiPoint::operator()(const std::vector &input_coordinates, - const boost::optional &properties) const + const std::optional &properties) const { auto coordinates = makeJsonArray(input_coordinates); return makeFeature("MultiPoint", std::move(coordinates), properties); @@ -60,7 +60,7 @@ CoordinateVectorToMultiPoint::operator()(const std::vector &in //---------------------------------------------------------------- util::json::Object CoordinateVectorToLineString::operator()(const std::vector &input_coordinates, - const boost::optional &properties) const + const std::optional &properties) const { auto coordinates = makeJsonArray(input_coordinates); return makeFeature("LineString", std::move(coordinates), properties); diff --git a/src/util/timezones.cpp b/src/util/timezones.cpp index cc0e0f108..3352cfaf0 100644 --- a/src/util/timezones.cpp +++ b/src/util/timezones.cpp @@ -3,14 +3,13 @@ #include "util/geojson_validation.hpp" #include "util/log.hpp" -#include - #include #include #include #include #include +#include #include #include #include @@ -157,7 +156,7 @@ void Timezoner::LoadLocalTimesRTree(rapidjson::Document &geojson, std::time_t ut rtree = rtree_t(polygons); } -boost::optional Timezoner::operator()(const point_t &point) const +std::optional Timezoner::operator()(const point_t &point) const { std::vector result; rtree.query(boost::geometry::index::intersects(point), std::back_inserter(result)); @@ -167,6 +166,6 @@ boost::optional Timezoner::operator()(const point_t &point) const if (boost::geometry::within(point, local_times[index].first)) return local_times[index].second; } - return boost::none; + return std::nullopt; } } // namespace osrm::updater diff --git a/third_party/vtzero/test/mvt-fixtures b/third_party/vtzero/test/mvt-fixtures deleted file mode 160000 index a351144a7..000000000 --- a/third_party/vtzero/test/mvt-fixtures +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a351144a7aa6ca4b826295cd4454cd4ce3a6f71f diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index a0de5a245..dc2541713 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -238,9 +238,10 @@ class MockAlgorithmDataFacade return SPECIAL_EDGEID; } - EdgeID FindSmallestEdge(const NodeID /* from */, - const NodeID /* to */, - std::function /* filter */) const override + EdgeID + FindSmallestEdge(const NodeID /* from */, + const NodeID /* to */, + const std::function & /* filter */) const override { return SPECIAL_EDGEID; } diff --git a/unit_tests/util/bearing.cpp b/unit_tests/util/bearing.cpp index 797b36c34..9643f46c8 100644 --- a/unit_tests/util/bearing.cpp +++ b/unit_tests/util/bearing.cpp @@ -1,7 +1,6 @@ #include "util/bearing.hpp" #include "util/typedefs.hpp" -#include #include BOOST_AUTO_TEST_SUITE(bearing_test) diff --git a/unit_tests/util/json_render.cpp b/unit_tests/util/json_render.cpp index 0fa084846..4d2ce23cf 100644 --- a/unit_tests/util/json_render.cpp +++ b/unit_tests/util/json_render.cpp @@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(test_json_issue_6531) BOOST_CHECK_EQUAL(output, "0.1234567892"); output.clear(); - renderer(123456789123456789); + renderer(123456789123456789.); BOOST_CHECK_EQUAL(output, "1.234567891e+17"); } diff --git a/unit_tests/util/static_rtree.cpp b/unit_tests/util/static_rtree.cpp index d1c4897ac..7d65f816c 100644 --- a/unit_tests/util/static_rtree.cpp +++ b/unit_tests/util/static_rtree.cpp @@ -5,12 +5,12 @@ #include "util/coordinate_calculation.hpp" #include "util/exception.hpp" #include "util/rectangle.hpp" +#include "util/std_hash.hpp" #include "util/typedefs.hpp" #include "../common/temporary_file.hpp" #include "mocks/mock_datafacade.hpp" -#include #include #include @@ -91,20 +91,6 @@ template class LinearSearchNN template struct RandomGraphFixture { - struct TupleHash - { - using argument_type = std::pair; - using result_type = std::size_t; - - result_type operator()(const argument_type &t) const - { - std::size_t val{0}; - boost::hash_combine(val, t.first); - boost::hash_combine(val, t.second); - return val; - } - }; - RandomGraphFixture() { std::mt19937 g(RANDOM_SEED); @@ -121,7 +107,7 @@ template struct RandomGraphFixture std::uniform_int_distribution<> edge_udist(0, coords.size() - 1); - std::unordered_set, TupleHash> used_edges; + std::unordered_set> used_edges; while (edges.size() < NUM_EDGES) { @@ -348,7 +334,13 @@ BOOST_AUTO_TEST_CASE(radius_regression_test) { auto results = query.NearestPhantomNodes( - input, osrm::engine::Approach::UNRESTRICTED, boost::none, 0.01, boost::none, true); + input, osrm::engine::Approach::UNRESTRICTED, 0.01, boost::none, true); + BOOST_CHECK_EQUAL(results.size(), 0); + } + + { + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 1, 0.01, boost::none, true); BOOST_CHECK_EQUAL(results.size(), 0); } } @@ -374,13 +366,25 @@ BOOST_AUTO_TEST_CASE(permissive_edge_snapping) { auto results = query.NearestPhantomNodes( - input, osrm::engine::Approach::UNRESTRICTED, boost::none, 1000, boost::none, false); + input, osrm::engine::Approach::UNRESTRICTED, 1000, boost::none, false); BOOST_CHECK_EQUAL(results.size(), 1); } { auto results = query.NearestPhantomNodes( - input, osrm::engine::Approach::UNRESTRICTED, boost::none, 1000, boost::none, true); + input, osrm::engine::Approach::UNRESTRICTED, 1000, boost::none, true); + BOOST_CHECK_EQUAL(results.size(), 2); + } + + { + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 10, 1000, boost::none, false); + BOOST_CHECK_EQUAL(results.size(), 1); + } + + { + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 10, 1000, boost::none, true); BOOST_CHECK_EQUAL(results.size(), 2); } } @@ -442,27 +446,45 @@ BOOST_AUTO_TEST_CASE(bearing_tests) { auto results = query.NearestPhantomNodes( - input, osrm::engine::Approach::UNRESTRICTED, boost::none, 11000, boost::none, true); + input, osrm::engine::Approach::UNRESTRICTED, 11000, boost::none, true); BOOST_CHECK_EQUAL(results.size(), 2); } { - auto results = query.NearestPhantomNodes(input, - osrm::engine::Approach::UNRESTRICTED, - boost::none, - 11000, - engine::Bearing{270, 10}, - true); + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 10, 11000, boost::none, true); + BOOST_CHECK_EQUAL(results.size(), 2); + } + + { + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 11000, engine::Bearing{270, 10}, true); BOOST_CHECK_EQUAL(results.size(), 0); } { - auto results = query.NearestPhantomNodes(input, - osrm::engine::Approach::UNRESTRICTED, - boost::none, - 11000, - engine::Bearing{45, 10}, - true); + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 10, 11000, engine::Bearing{270, 10}, true); + BOOST_CHECK_EQUAL(results.size(), 0); + } + + { + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 11000, engine::Bearing{45, 10}, true); + BOOST_CHECK_EQUAL(results.size(), 2); + + BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled); + BOOST_CHECK(!results[0].phantom_node.reverse_segment_id.enabled); + BOOST_CHECK_EQUAL(results[0].phantom_node.forward_segment_id.id, 1); + + BOOST_CHECK(!results[1].phantom_node.forward_segment_id.enabled); + BOOST_CHECK(results[1].phantom_node.reverse_segment_id.enabled); + BOOST_CHECK_EQUAL(results[1].phantom_node.reverse_segment_id.id, 1); + } + + { + auto results = query.NearestPhantomNodes( + input, osrm::engine::Approach::UNRESTRICTED, 10, 11000, engine::Bearing{45, 10}, true); BOOST_CHECK_EQUAL(results.size(), 2); BOOST_CHECK(results[0].phantom_node.forward_segment_id.enabled); diff --git a/unit_tests/util/viewport.cpp b/unit_tests/util/viewport.cpp index 3ec1dff39..70a2003af 100644 --- a/unit_tests/util/viewport.cpp +++ b/unit_tests/util/viewport.cpp @@ -2,7 +2,6 @@ using namespace osrm::util; -#include #include #include