Compare commits

...

92 Commits

Author SHA1 Message Date
Siarhei Fedartsou cc97eb4fd2 Merge branch 'master' into sf-lto 2024-06-09 18:18:40 +02:00
Siarhei Fedartsou b42cd65d57 wip 2024-06-09 17:08:25 +02:00
Siarhei Fedartsou 89435aa87f Add new randomized benchmarks (#6929) 2024-06-09 17:03:24 +02:00
Siarhei Fedartsou 5cbce08092 wip 2024-06-09 13:30:49 +02:00
Siarhei Fedartsou 978ad75bd5 wip 2024-06-09 13:26:22 +02:00
Siarhei Fedartsou 032b0b31d4 wip 2024-06-09 13:11:31 +02:00
Siarhei Fedartsou 465fd4c268 Try to enable LTO by default 2024-06-09 13:08:06 +02:00
Siarhei Fedartsou 3b595db9eb Try to enable LTO by default 2024-06-09 12:56:21 +02:00
Siarhei Fedartsou 196f6dd233 Merge branch 'master' into sf-lto 2024-06-09 12:51:15 +02:00
Siarhei Fedartsou fe704c0905 Try to enable LTO by default 2024-06-09 12:46:46 +02:00
Siarhei Fedartsou d74e6a5e39 Try to enable LTO by default 2024-06-09 12:43:07 +02:00
Siarhei Fedartsou 0cbb23abe1 Fix Windows CI: update conan.cmake and disable unit tests as temporary workaround for OOM issues (#6930) 2024-06-09 09:24:02 +02:00
Siarhei Fedartsou a2915f78c5 Make e2e benchmarks more stable (#6927) 2024-06-08 22:27:12 +02:00
Siarhei Fedartsou 99cb17aed3 Fix bugprone-unused-return-value clang-tidy warning (#6934) 2024-06-08 14:33:24 +02:00
Siarhei Fedartsou 8fd8d0c24a Fix performance-noexcept-move-constructor clang-tidy warning (#6933) 2024-06-08 08:33:54 +02:00
Siarhei Fedartsou c57b0d28b0 Fix performance-noexcept-swap clang-tidy warning (#6931) 2024-06-07 16:18:10 +02:00
Siarhei Fedartsou 523ee762f0 Upgrade to clang-tidy 18 (#6919) 2024-06-06 22:20:38 +02:00
Siarhei Fedartsou feeed75cf1 Add simple benchmarks for osrm-* tools (#6925) 2024-06-06 21:01:34 +02:00
Siarhei Fedartsou c7ee1a59eb Implement end to end benchmark (#6910) 2024-06-05 21:39:10 +02:00
Dennis Luxen 2725202771 Use Lemire's fast check whether to escape a JSON string (#6923) 2024-05-31 19:58:57 +02:00
Siarhei Fedartsou 42fafdcdfe Use custom struct instead of std::pair in QueryHeap (#6921) 2024-05-31 07:06:58 +02:00
Siarhei Fedartsou c8de759cd6 Use std::string_view::starts_with instead of boost::starts_with (#6918) 2024-05-30 21:55:25 +02:00
Siarhei Fedartsou fb9d1cefcc Get rid of boost::math::constants::* and M_PI in favor of std::numbers (#6916) 2024-05-30 19:40:56 +02:00
Dennis Luxen a9b1bd88d3 Remove all core-CH left-overs (#6920)
* Remove all core-CH left-overs

* Fix formatting

* Update CHANGELOG.md
2024-05-30 17:13:44 +02:00
Siarhei Fedartsou 1ff096ac5c Make constants in PackedVector constexpr (#6917) 2024-05-30 15:12:42 +02:00
Dennis Luxen 0ea757ed02 Remove unused header file (#6913) 2024-05-29 09:13:13 +02:00
Dennis Luxen 42cbca0ff0 Move Sol2 to canonical path (#6912) 2024-05-28 21:23:51 +02:00
Siarhei Fedartsou c1ed73126d Use std::variant instead of mapbox::util::variant (#6903) 2024-05-28 18:52:49 +02:00
Siarhei Fedartsou 01b1673c8a Fix CCache usage in GitHub Actions (#6911) 2024-05-28 08:43:23 +02:00
Siarhei Fedartsou d4dc297f75 Add CI job with GCC 14 (#6905) 2024-05-27 09:31:13 +02:00
Siarhei Fedartsou 9aaab7a53f Enable readability-container-contains clang-tidy check (#6909) 2024-05-27 08:33:26 +02:00
Siarhei Fedartsou 1a6f4c44e7 Fix performance-type-promotion-in-math-fn clang-tidy warning (#6908) 2024-05-27 08:33:05 +02:00
Siarhei Fedartsou 163a2cfe3c Bump rapidjson version (#6906) 2024-05-27 08:31:59 +02:00
Siarhei Fedartsou 667fd198ac Use the latest Debian version in Dockerfile (#6904) 2024-05-27 08:30:44 +02:00
Siarhei Fedartsou b7a990d0b5 Use C++20 (#6877) 2024-05-25 18:25:13 +02:00
Dennis Luxen 8306ed8ae3 Remove superflous iostreams include from header files (#6901) 2024-05-25 09:17:45 +02:00
Dennis Luxen 640df69aa1 Remove dead CRC32 processor code (#6900) 2024-05-24 22:43:03 +02:00
Siarhei Fedartsou 8b48e2ccc6 Bump mapbox/variant to version 1.2.0 (#6898) 2024-05-24 20:39:45 +02:00
Dennis Luxen babdced52f Replace GCC-specific attribute with [[nodiscard]] attribute (#6899) 2024-05-24 20:34:04 +02:00
Siarhei Fedartsou 21607e0cb2 Optimise getNetworkDistance in MLD even more (#6884) 2024-05-23 20:46:13 +02:00
Dennis Luxen 24646aada9 Remove outdated warnings (#6894) 2024-05-23 19:39:00 +02:00
Dennis Luxen 51b74a99aa Avoid copy of std::function-based callback in path unpacking (#6895)
* Avoid copy of std::function-based callback in path unpacking

* Fix formatting

* Update CHANGELOG.md
2024-05-23 18:51:51 +02:00
Dennis Luxen ed5003b502 Upgrade CI actions to latest versions (#6893)
* Upgrade actions

* Update remaining actions

* Update CHANGELOG.md

* Update CHANGELOG.md
2024-05-23 14:40:47 +02:00
Dennis Luxen 46dc660801 Replace boost::hash by std::hash (#6892)
* Replace boost::hash by std::hash

* Fix formatting

* Update CHANGELOG.md
2024-05-23 14:35:56 +02:00
Siarhei Fedartsou 73fb53cf36 Add benchmark for route (#6890) 2024-05-23 14:27:43 +02:00
Mugr Rex efe6840d08 Replace boost::optional with std::optional (#6611) 2024-05-22 14:58:07 +02:00
Siarhei Fedartsou d259848456 Optimise R-tree queries in the case of map matching (#6881) 2024-05-20 12:32:40 +02:00
Siarhei Fedartsou 8a82d3929c Improve map matching benchmark (#6885) 2024-05-20 11:15:55 +02:00
Siarhei Fedartsou 89fce286a7 Fix benchmark script for the case if PR has empty description (#6887) 2024-05-20 09:16:53 +02:00
Siarhei Fedartsou 11c7ddc84d Fix failing gcc-13 based CI jobs (#6886)
* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs

* Attempt to fix failing CI on gcc-13 jobs
2024-05-19 19:30:24 +02:00
Siarhei Fedartsou 54e50a67a8 Add benchmarks comparison job (#6880) 2024-05-14 17:14:59 +02:00
Bart Louwers c00c157479 Replace dead link with archive.org link (#6882) 2024-05-14 11:49:49 +02:00
Siarhei Fedartsou ee8e0f890a Optimise path distance calculation in MLD map matching (#6876) 2024-05-11 16:30:43 +02:00
Dennis Luxen 1e2ffee97c Update Makefile: fix typo (#6878) 2024-05-11 09:13:17 +02:00
Michael Bell ffc39b8ad2 Clarify use of forcing routing steps (#6866)
The change clarifies the conditions for forcing routing steps and
simplifies the codebase to support it.

- Makes explicity  the search runtime condition for forcing a routing
step. Namely, the node is a source of the forward and reverse searches,
and it's one of the pre-identified nodes that requires a step to
be forced.
- Consolidate the two lists of force nodes into one. Not only is there
no algorithmic value in separating the nodes by geometric direction,
the  improvements to via-routes with u-turns mean atleast one of these
lists will be empty for any search.
- Rename 'force loop' to 'force step'. This moves the code away
from the original CH-specific language for checking for self-loops
in the case where this condition is met. MLD does not have loops.

Additional cucumber tests are added to cover the logic related to
negative search weights and forcing routing steps on via-route
paths.
2024-05-10 22:00:24 +01:00
Dennis Luxen 70969186f6 Migrate GCC CI jobs to run on GCC 11, 12, and 13 (#6865) 2024-05-10 20:38:32 +02:00
Dennis Luxen dff76d31d5 Remove dead code branches (#6875) 2024-05-10 20:21:41 +02:00
Siarhei Fedartsou 3254686933 Use M1 runner to build arm64 macOS builds (#6868) 2024-05-08 21:08:11 +02:00
Siarhei Fedartsou a6dfff725b Configure GitHub Actions concurrency (#6870) 2024-05-08 10:06:04 +02:00
Dennis Luxen 10237b8761 Update vendored vtzero dependency to v1.1.0 (#6871) 2024-05-07 22:19:48 +02:00
Dennis Luxen 79de092bb2 Upgrade fmt dependency to v10.2.1 (#6869)
* Put fmt into version agnostic subdir

* Add fmt to dependency update script

* Remove manually added fmt

* Squashed 'third_party/fmt/' content from commit e69e5f977

git-subtree-dir: third_party/fmt
git-subtree-split: e69e5f977d458f2650bb346dadf2ad30c5320281
2024-05-07 20:55:55 +02:00
Dennis Luxen 82aa369db3 Remove dead code modernization script (#6863) 2024-05-06 19:09:10 +02:00
Dennis Luxen 0583582772 Remove include that breaks compilation for Boost v1.85.0 (#6856)
* Remove include that breaks compilation for Boost v1.85.0

* Update CHANGELOG.md

* Fix typo

* Fix issues found by newer clang-tidy version

* Add include to boost filesystem to satisfy Windows compiler
2024-05-06 18:52:40 +02:00
Dennis Luxen 99809e105c Upgrade clang compiler in CI builds (#6861) 2024-05-06 18:12:17 +02:00
Dennis Luxen 6d361ced41 Set Windows build to quiet (#6862)
The normal flag generates 290 megabytes of log output for a regular build. Setting it to quiet will reduce this and still print errors.
2024-05-06 17:31:58 +02:00
Dennis Luxen 790fa901c7 Remove stale AppVeyor files (#6860)
* Drop left-overs from deprecated AppVeyor CI build

* Update CHANGELOG.md
2024-05-06 13:48:24 +02:00
Dennis Luxen 7f9d591ab7 Upgrade clang-format to version 15 (#6859) 2024-05-06 09:14:46 +02:00
Michael Bell b503e96a98 Remove force-loop checks for routes with u-turns (#6858)
Each leg of a via-route supporting u-turns does not need to consider
force-loops. Negative weight checks are sufficient to prevent
incorrect results when waypoints are on the same edge.
2024-05-05 21:56:01 +01:00
Dennis Luxen d691af4860 Remove outdated/deprecated CMake policy (#6854) 2024-05-05 22:08:40 +02:00
Dennis Luxen befd9dc5ae Merge pull request #6857 from DennisOSRM/upgrade_js_dependencies
Drop support for NodeJS <= v16
2024-05-05 20:29:16 +02:00
Dennis Luxen 4968d7f9d9 Disable codecov.io upload run since it consistently fails 2024-05-05 16:40:21 +02:00
Dennis Luxen c26f0612d1 Fix typo 2024-05-05 15:24:56 +02:00
Dennis Luxen de41299eda Update CHANGELOG.md 2024-05-05 15:03:12 +02:00
Dennis Luxen c37bbfd07a Migrate GitHub actions from {16, 18} to {28, 20} 2024-05-05 15:01:41 +02:00
Dennis Luxen 0fd1fb2904 Update minimum NodeJS dependency to 18 2024-05-05 14:51:56 +02:00
Matthew Wigginton Bhagat-Conway 7ebd21f39e pass flags into process_segment (#6658)
* pass flags into process_segment

---------

Co-authored-by: Michael Bell <michael@mjjbell.com>
2024-04-06 09:27:42 +01:00
Michael Bell 8ef366e061 Add support for opposite approach request parameter (#6842)
* Added approach on the opposite side of the road.

* Additional test and docs coverage for opposite approach

---------

Co-authored-by: Aleksandrs Saveljevs <Aleksandrs.Saveljevs@gmail.com>
2024-04-03 19:59:15 +01:00
rezashokry 367933fc1a Fix manuever overrides finding bug (#6739)
* sort manuever overrides vector after partition

---------

Co-authored-by: rshokri <reza.shokri@tapsi.cab>
Co-authored-by: Michael Bell <michael@mjjbell.com>
2024-03-24 21:48:28 +00:00
Damiaan Twelker c28ba66039 Increment feature id in tile speed layer (#6726)
* actually increment feature id in tile speed layer

---------

Co-authored-by: Michael Bell <michael@mjjbell.com>
2024-03-24 21:23:36 +00:00
Michael Bell d0e3e2af23 Extract prerelease/build information from package semver (#6839)
* Extract prerelease/build information from package semver

Currently we only extract the major.minor.patch identifiers from
the semver label stored in package.json.

This leads to version information in executables incorrectly
reporting a release version is running on prereleases and special builds.

This commit is a quickfix to extract this information and report it
in version strings.

CMake regex parsing is not sophisticated enough to handle the full semver
regex, so we might need to explore other CMake modules if we want to
strictly parse the label.
2024-03-24 18:33:07 +00:00
martin 8526cc7d45 Replace deprecated std::is_pod (#6717)
* Replace deprecated std::is_pod
2024-03-17 11:49:55 +00:00
Trivikram Kamat 016440fc7e Remove unused AWS SDK for JavaScript v2 (#6730) 2024-03-17 11:37:51 +00:00
Monday 6e77d53946 Correctly handle compressed traffic signals (#6724)
Unidirectional traffic signal segments are currently not compressed.
This means traffic signals which are not on turns can be missed and
not applied the correct penalty.

This commit changes this behaviour to correctly handle the graph
compression. Additional tests are added to ensure there is no
regression for other cases (turns, restrictions).

Co-authored-by: Michael Bell <michael@mjjbell.com>
2024-03-17 11:32:10 +00:00
Frédéric Rodrigo 99875b4d24 Set Maxspeed for Philippines (#6776) 2024-03-16 11:35:25 +00:00
Michael Bell c315a586f7 Delete .github/ISSUE_TEMPLATE/question.md (#6827)
With Discussions now enabled, remove the question issue template to encourage Q&A interaction in the more appropriate place.
2024-03-15 09:35:09 +00:00
Daniel Spasojevic 69c38401bc Update osrm-backend-docker link to point to github hosted repo (#6831) 2024-03-15 10:29:39 +01:00
Michael Bell e219eb9442 Pin Conan revisions correctly (#6828)
* Pin Conan revisions correctly

Conan dependencies are not pinned correctly. This means we're
pulling in a newer onetbb recipe that no longer has a shared
library option.

Following other examples of how to pin revisions with cmake
for conan v1, we correctly pin the expected revisions.

Longer term we should look into
- upgrading to conan v2
- defining the conan config separately from cmakelists.txt
- understanding the need for disabling onetbb shared library support

but for the purposes of reviving CI, this will be sufficient.

* Fix macos CI builds
2024-03-15 09:27:59 +00:00
Daniel Patterson 31e31a63d0 Fix some compilation issues on modern macOS systems (#6709)
* Fix various compiler warnings generated by Apple clang 15, and workaround some boost 1.8 bugs

* Fix formatting.
2023-10-12 23:04:39 +02:00
danieldegroot2 b437ce5b33 Update debug_way.lua (#6713) 2023-10-12 23:03:35 +02:00
Frédéric Rodrigo 5723eaaa6a Added motorway speed limits for Bulgaria (original fix by pl71) (#6698) 2023-09-13 22:01:36 +02:00
Frédéric Rodrigo 0f7b86b099 Install data directory (geojson files) like the profiles directory (#6699) 2023-09-13 22:01:06 +02:00
fenwuyaoji 14dcf91812 add keepalive_timeout flag (#6674)
* add keepalive_timeout flag
2023-08-30 19:06:39 +01:00
828 changed files with 52588 additions and 71920 deletions
+11 -1
View File
@@ -13,6 +13,10 @@ Checks: >
-bugprone-forward-declaration-namespace,
-bugprone-sizeof-expression,
-bugprone-throw-keyword-missing,
-bugprone-chained-comparison,
-bugprone-incorrect-enable-if,
-bugprone-switch-missing-default-case,
-bugprone-empty-catch,
-clang-analyzer-*,
-clang-diagnostic-deprecated-declarations,
-clang-diagnostic-constant-conversion,
@@ -49,11 +53,13 @@ Checks: >
-misc-misplaced-const,
-misc-definitions-in-headers,
-misc-unused-parameters,
-misc-include-cleaner,
modernize-concat-nested-namespaces,
modernize-use-using,
performance-*,
-performance-noexcept-move-constructor,
-performance-no-int-to-ptr,
-performance-enum-size,
-performance-avoid-endl,
readability-*,
-readability-avoid-const-params-in-decls,
-readability-braces-around-statements,
@@ -82,6 +88,10 @@ Checks: >
-readability-make-member-function-const,
-readability-redundant-string-init,
-readability-non-const-parameter,
-readability-redundant-inline-specifier,
-readability-avoid-nested-conditional-operator,
-readability-avoid-return-with-void-value,
-readability-redundant-casting,
-readability-static-accessed-through-instance
WarningsAsErrors: '*'
-5
View File
@@ -1,5 +0,0 @@
---
name: Question
about: Ask a question about OSRM
labels: question
---
+395 -284
View File
@@ -15,10 +15,13 @@ env:
CCACHE_TEMPDIR: /tmp/.ccache-temp
CCACHE_COMPRESS: 1
CASHER_TIME_OUT: 599 # one second less than 10m to avoid 10m timeout error: https://github.com/Project-OSRM/osrm-backend/issues/2742
CCACHE_VERSION: 3.3.1
CMAKE_VERSION: 3.21.2
ENABLE_NODE_BINDINGS: "ON"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
windows-release-node:
needs: format-taginfo-docs
@@ -26,15 +29,14 @@ jobs:
continue-on-error: false
env:
BUILD_TYPE: Release
ENABLE_APPLE_SILICON: "OFF"
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: 16
node-version: 18
- run: node --version
- run: npm --version
- name: Prepare environment
@@ -44,15 +46,32 @@ 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
- name: Build
run: |
.\scripts\ci\windows-build.bat
- name: Run node tests
shell: bash
run: |
./lib/binding/osrm-datastore.exe test/data/ch/monaco.osrm
node test/nodejs/index.js
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_CONAN=ON -DENABLE_NODE_BINDINGS=ON ..
cmake --build . --config Release
# TODO: MSVC goes out of memory when building our tests
# - name: Run tests
# shell: bash
# run: |
# cd build
# cmake --build . --config Release --target tests
# # TODO: run tests
# - name: Run node tests
# shell: bash
# run: |
# ./lib/binding/osrm-extract.exe -p profiles/car.lua test/data/monaco.osm.pbf
# mkdir -p test/data/ch
# cp test/data/monaco.osrm* test/data/ch/
# ./lib/binding/osrm-contract.exe test/data/ch/monaco.osrm
# ./lib/binding/osrm-datastore.exe test/data/ch/monaco.osrm
# node test/nodejs/index.js
- name: Build Node package
shell: bash
run: ./scripts/ci/node_package.sh
@@ -71,15 +90,15 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
format-taginfo-docs:
runs-on: ubuntu-20.04
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: 16
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') }}
@@ -88,7 +107,7 @@ jobs:
- name: Prepare environment
run: |
npm ci --ignore-scripts
clang-format-10 --version
clang-format-15 --version
- name: Run checks
run: |
./scripts/check_taginfo.py taginfo.json profiles/car.lua
@@ -103,9 +122,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
@@ -145,183 +164,178 @@ jobs:
strategy:
matrix:
include:
- name: gcc-9-debug-cov
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Debug
CCOMPILER: gcc-9
CUCUMBER_TIMEOUT: 20000
CXXCOMPILER: g++-9
ENABLE_COVERAGE: ON
# - name: gcc-13-debug-cov
# continue-on-error: false
# node: 20
# runs-on: ubuntu-24.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Debug
# CCOMPILER: gcc-13
# CUCUMBER_TIMEOUT: 20000
# CXXCOMPILER: g++-13
# ENABLE_COVERAGE: ON
- name: gcc-9-debug-asan-ubsan
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Debug
CCOMPILER: gcc-9
CUCUMBER_TIMEOUT: 20000
CXXCOMPILER: g++-9
ENABLE_SANITIZER: ON
TARGET_ARCH: x86_64-asan-ubsan
OSRM_CONNECTION_RETRIES: 10
OSRM_CONNECTION_EXP_BACKOFF_COEF: 1.5
# - name: clang-15-debug-asan-ubsan
# continue-on-error: false
# node: 20
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Debug
# CCOMPILER: clang-15
# CUCUMBER_TIMEOUT: 20000
# CXXCOMPILER: clang++-15
# ENABLE_SANITIZER: ON
# TARGET_ARCH: x86_64-asan-ubsan
# OSRM_CONNECTION_RETRIES: 10
# OSRM_CONNECTION_EXP_BACKOFF_COEF: 1.5
- name: clang-6.0-debug
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Debug
CCOMPILER: clang-6.0
CXXCOMPILER: clang++-6.0
CUCUMBER_TIMEOUT: 60000
# - name: clang-15-release
# continue-on-error: false
# node: 18
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: clang-15
# CXXCOMPILER: clang++-15
# CUCUMBER_TIMEOUT: 60000
- name: clang-15.0-debug-clang-tidy
continue-on-error: false
node: 16
runs-on: ubuntu-22.04
BUILD_TOOLS: ON
BUILD_TYPE: Debug
CCOMPILER: clang-15
CXXCOMPILER: clang++-15
CUCUMBER_TIMEOUT: 60000
ENABLE_CLANG_TIDY: ON
# - name: clang-15-debug
# continue-on-error: false
# node: 18
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Debug
# CCOMPILER: clang-15
# CXXCOMPILER: clang++-15
# CUCUMBER_TIMEOUT: 60000
- name: conan-linux-debug-asan-ubsan
# - name: clang-18-debug-clang-tidy
# continue-on-error: false
# node: 18
# runs-on: ubuntu-24.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Debug
# CCOMPILER: clang-18
# CXXCOMPILER: clang++-18
# CUCUMBER_TIMEOUT: 60000
# ENABLE_CLANG_TIDY: ON
# - name: clang-14-release
# continue-on-error: false
# node: 18
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: clang-14
# CXXCOMPILER: clang++-14
# CUCUMBER_TIMEOUT: 60000
# - name: clang-13-release
# continue-on-error: false
# node: 18
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: clang-13
# CXXCOMPILER: clang++-13
# CUCUMBER_TIMEOUT: 60000
# - name: conan-linux-debug-asan-ubsan
# continue-on-error: false
# node: 18
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: clang-15
# CXXCOMPILER: clang++-15
# ENABLE_CONAN: ON
# ENABLE_SANITIZER: ON
# - name: conan-linux-release
# continue-on-error: false
# node: 18
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: clang-15
# CXXCOMPILER: clang++-15
# ENABLE_CONAN: ON
- name: gcc-14-release
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
node: 20
runs-on: ubuntu-24.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: clang-11
CXXCOMPILER: clang++-11
ENABLE_CONAN: ON
ENABLE_SANITIZER: ON
- name: conan-linux-release
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: clang-6.0
CXXCOMPILER: clang++-6.0
ENABLE_CONAN: ON
- name: gcc-12-release
continue-on-error: false
node: 16
runs-on: ubuntu-22.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-12
CXXCOMPILER: g++-12
ENABLE_BENCHMARKS: ON
CCOMPILER: gcc-14
CXXCOMPILER: g++-14
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
- name: gcc-11-release
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-11
CXXCOMPILER: g++-11
ENABLE_BENCHMARKS: ON
# - name: gcc-13-release
# continue-on-error: false
# node: 20
# runs-on: ubuntu-24.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: gcc-13
# CXXCOMPILER: g++-13
# CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
- name: gcc-10-release
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-10
CXXCOMPILER: g++-10
# - name: gcc-12-release
# continue-on-error: false
# node: 20
# runs-on: ubuntu-22.04
# BUILD_TOOLS: ON
# BUILD_TYPE: Release
# CCOMPILER: gcc-12
# CXXCOMPILER: g++-12
# CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
- name: gcc-9-release
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-9
CXXCOMPILER: g++-9
CXXFLAGS: -Wno-cast-function-type
# - name: conan-linux-release-node
# build_node_package: true
# continue-on-error: false
# node: 20
# runs-on: ubuntu-22.04
# BUILD_TYPE: Release
# CCOMPILER: clang-13
# CXXCOMPILER: clang++-13
# ENABLE_CONAN: ON
# NODE_PACKAGE_TESTS_ONLY: ON
- name: gcc-9-conan-release-i686
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-9
CFLAGS: "-m32 -msse2 -mfpmath=sse"
CXXCOMPILER: g++-9
CXXFLAGS: "-m32 -msse2 -mfpmath=sse"
TARGET_ARCH: i686
ENABLE_CONAN: ON
# - name: conan-linux-debug-node
# build_node_package: true
# continue-on-error: false
# node: 20
# runs-on: ubuntu-22.04
# BUILD_TYPE: Debug
# CCOMPILER: clang-13
# CXXCOMPILER: clang++-13
# ENABLE_CONAN: ON
# NODE_PACKAGE_TESTS_ONLY: ON
- name: gcc-8-release
continue-on-error: false
node: 16
runs-on: ubuntu-20.04
BUILD_TOOLS: ON
BUILD_TYPE: Release
CCOMPILER: gcc-8
CXXCOMPILER: g++-8
CXXFLAGS: -Wno-cast-function-type
- name: conan-linux-release-node
build_node_package: true
continue-on-error: false
node: 18
runs-on: ubuntu-20.04
BUILD_TYPE: Release
CCOMPILER: clang-6.0
CXXCOMPILER: clang++-6.0
ENABLE_CONAN: ON
NODE_PACKAGE_TESTS_ONLY: ON
- name: conan-linux-debug-node
build_node_package: true
continue-on-error: false
node: 18
runs-on: ubuntu-20.04
BUILD_TYPE: Debug
CCOMPILER: clang-6.0
CXXCOMPILER: clang++-6.0
ENABLE_CONAN: ON
NODE_PACKAGE_TESTS_ONLY: ON
- name: conan-macos-x64-release-node
build_node_package: true
continue-on-error: true
node: 18
runs-on: macos-11
BUILD_TYPE: Release
CCOMPILER: clang
CXXCOMPILER: clang++
CUCUMBER_TIMEOUT: 60000
ENABLE_ASSERTIONS: ON
ENABLE_CONAN: ON
- name: conan-macos-arm64-release-node
build_node_package: true
continue-on-error: true
node: 18
runs-on: macos-11
BUILD_TYPE: Release
CCOMPILER: clang
CXXCOMPILER: clang++
CUCUMBER_TIMEOUT: 60000
ENABLE_ASSERTIONS: ON
ENABLE_CONAN: ON
ENABLE_APPLE_SILICON: ON
# - name: conan-macos-x64-release-node
# build_node_package: true
# continue-on-error: true
# node: 20
# runs-on: macos-13 # x86_64
# BUILD_TYPE: Release
# CCOMPILER: clang
# CXXCOMPILER: clang++
# CUCUMBER_TIMEOUT: 60000
# ENABLE_ASSERTIONS: ON
# ENABLE_CONAN: ON
# - name: conan-macos-arm64-release-node
# build_node_package: true
# continue-on-error: true
# node: 20
# runs-on: macos-14 # arm64
# BUILD_TYPE: Release
# CCOMPILER: clang
# CXXCOMPILER: clang++
# CUCUMBER_TIMEOUT: 60000
# ENABLE_ASSERTIONS: ON
# ENABLE_CONAN: ON
name: ${{ matrix.name}}
continue-on-error: ${{ matrix.continue-on-error }}
runs-on: ${{ matrix.runs-on }}
@@ -340,48 +354,50 @@ jobs:
ENABLE_CONAN: ${{ matrix.ENABLE_CONAN }}
ENABLE_SANITIZER: ${{ matrix.ENABLE_SANITIZER }}
NODE_PACKAGE_TESTS_ONLY: ${{ matrix.NODE_PACKAGE_TESTS_ONLY }}
ENABLE_APPLE_SILICON: ${{ matrix.ENABLE_APPLE_SILICON }}
TARGET_ARCH: ${{ matrix.TARGET_ARCH }}
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: v6-conan-${{ matrix.name }}-${{ github.sha }}
key: v9-conan-${{ matrix.name }}-${{ github.sha }}
restore-keys: |
v6-conan-${{ matrix.name }}-
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 }}
restore-keys: |
v4-test-${{ matrix.name }}-
- name: Prepare environment
run: |
echo "CCACHE_DIR=$HOME/.ccache" >> $GITHUB_ENV
mkdir -p $HOME/.ccache
PACKAGE_JSON_VERSION=$(node -e "console.log(require('./package.json').version)")
echo PUBLISH=$([[ "${GITHUB_REF:-}" == "refs/tags/v${PACKAGE_JSON_VERSION}" ]] && echo "On" || echo "Off") >> $GITHUB_ENV
echo "OSRM_INSTALL_DIR=${GITHUB_WORKSPACE}/install-osrm" >> $GITHUB_ENV
@@ -390,6 +406,7 @@ jobs:
# We can only set this after checkout once we know the workspace directory
echo "LSAN_OPTIONS=print_suppressions=0:suppressions=${GITHUB_WORKSPACE}/scripts/ci/leaksanitizer.conf" >> $GITHUB_ENV
echo "UBSAN_OPTIONS=symbolize=1:halt_on_error=1:print_stacktrace=1:suppressions=${GITHUB_WORKSPACE}/scripts/ci/undefinedsanitizer.conf" >> $GITHUB_ENV
echo "ASAN_OPTIONS=print_suppressions=0:suppressions=${GITHUB_WORKSPACE}/scripts/ci/addresssanitizer.conf" >> $GITHUB_ENV
fi
if [[ "${RUNNER_OS}" == "Linux" ]]; then
@@ -397,10 +414,39 @@ jobs:
elif [[ "${RUNNER_OS}" == "macOS" ]]; then
echo "JOBS=$((`sysctl -n hw.ncpu` + 1))" >> $GITHUB_ENV
fi
# See: https://github.com/actions/toolkit/issues/946#issuecomment-1590016041
# We need it to be able to access system folders while restoring cached Boost below
- name: Give tar root ownership
if: runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
run: sudo chown root /bin/tar && sudo chmod u+s /bin/tar
- name: Cache Boost
if: runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
id: cache-boost
uses: actions/cache@v4
with:
path: |
/usr/local/include/boost
/usr/local/lib/libboost*
key: v1-boost-${{ runner.os }}-${{ runner.arch }}-${{ matrix.runs-on }}
restore-keys: |
v1-boost-${{ runner.os }}-${{ runner.arch }}-${{ matrix.runs-on }}
- name: Install Boost
if: steps.cache-boost.outputs.cache-hit != 'true' && runner.os == 'Linux' && matrix.ENABLE_CONAN != 'ON'
run: |
BOOST_VERSION="1.85.0"
BOOST_VERSION_UNDERSCORE="${BOOST_VERSION//./_}"
wget -q https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz
tar xzf boost_${BOOST_VERSION_UNDERSCORE}.tar.gz
cd boost_${BOOST_VERSION_UNDERSCORE}
sudo ./bootstrap.sh
sudo ./b2 install
cd ..
sudo rm -rf boost_${BOOST_VERSION_UNDERSCORE}*
- name: Install dev dependencies
run: |
python3 -m pip install "conan<2.0.0"
python3 -m pip install "conan<2.0.0" || python3 -m pip install "conan<2.0.0" --break-system-packages
# workaround for issue that GitHub Actions seems to not adding it to PATH after https://github.com/actions/runner-images/pull/6499
# and that's why CI cannot find conan executable installed above
@@ -415,34 +461,20 @@ jobs:
brew install ccache
fi
# clang
if [[ "${CCOMPILER}" == "clang-6.0" ]]; then
sudo apt-get update -y && sudo apt-get install clang++-6
elif [[ "${CCOMPILER}" == "clang-15" ]]; then
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-get update -y && sudo apt-get install software-properties-common
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main'
sudo apt-get update -y && sudo apt-get install clang++-15 clang-tidy-15
sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-15 100000
fi
# Linux dev packages
if [ "${TARGET_ARCH}" != "i686" ] && [ "${ENABLE_CONAN}" != "ON" ]; then
if [ "${ENABLE_CONAN}" != "ON" ]; then
sudo apt-get update -y
sudo apt-get install -y libbz2-dev libxml2-dev libzip-dev liblua5.2-dev libboost-all-dev
sudo apt-get install -y libbz2-dev libxml2-dev libzip-dev liblua5.2-dev
if [[ "${CCOMPILER}" != clang-* ]]; then
sudo apt-get install -y ${CXXCOMPILER}
fi
if [[ "${ENABLE_COVERAGE}" == "ON" ]]; then
sudo apt-get install -y lcov
fi
elif [[ $TARGET_ARCH == "i686" ]]; then
source ./scripts/ci/before_install.${TARGET_ARCH}.sh
echo "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig:${PKG_CONFIG_PATH}" >> $GITHUB_ENV
fi
# TBB
TBB_VERSION=2021.3.0
TBB_VERSION=2021.12.0
if [[ "${RUNNER_OS}" == "Linux" ]]; then
TBB_URL="https://github.com/oneapi-src/oneTBB/releases/download/v${TBB_VERSION}/oneapi-tbb-${TBB_VERSION}-lin.tgz"
elif [[ "${RUNNER_OS}" == "macOS" ]]; then
@@ -462,23 +494,19 @@ jobs:
fi
echo "CC=${CCOMPILER}" >> $GITHUB_ENV
echo "CXX=${CXXCOMPILER}" >> $GITHUB_ENV
if [[ "${RUNNER_OS}" == "macOS" ]]; then
# missing from GCC path, needed for conan builds of libiconv, for example.
sudo xcode-select --switch /Library/Developer/CommandLineTools
echo "LIBRARY_PATH=${LIBRARY_PATH}:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib" >> $GITHUB_ENV
echo "CPATH=${CPATH}:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include" >> $GITHUB_ENV
fi
- name: Build and install OSRM
run: |
echo "Using ${JOBS} jobs"
pushd ${OSRM_BUILD_DIR}
# handle Apple Silicon cross compilation
if [[ "${ENABLE_APPLE_SILICON}" == "ON" ]]; then
ARCH=arm64
TARGET="${ARCH}-apple-darwin"
CFLAGS="$CFLAGS --target=$TARGET"
CXXFLAGS="$CXXFLAGS --target=$TARGET"
APPLE_SILICON_FLAGS=(-DCMAKE_C_COMPILER_TARGET="$TARGET" -DCMAKE_CXX_COMPILER_TARGET="$TARGET" -DCMAKE_SYSTEM_PROCESSOR="${ARCH}" -DCMAKE_SYSTEM_NAME="Darwin" -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS")
else
APPLE_SILICON_FLAGS=()
fi
ccache --zero-stats
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \
-DENABLE_CONAN=${ENABLE_CONAN:-OFF} \
-DENABLE_ASSERTIONS=${ENABLE_ASSERTIONS:-OFF} \
@@ -489,15 +517,13 @@ jobs:
-DENABLE_SANITIZER=${ENABLE_SANITIZER:-OFF} \
-DBUILD_TOOLS=${BUILD_TOOLS:-OFF} \
-DENABLE_CCACHE=ON \
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR} \
"${APPLE_SILICON_FLAGS[@]}"
-DCMAKE_INSTALL_PREFIX=${OSRM_INSTALL_DIR}
make --jobs=${JOBS}
if [[ "${NODE_PACKAGE_TESTS_ONLY}" != "ON" && "${ENABLE_APPLE_SILICON}" != "ON" ]]; then
if [[ "${NODE_PACKAGE_TESTS_ONLY}" != "ON" ]]; then
make tests --jobs=${JOBS}
make benchmarks --jobs=${JOBS}
ccache -s
sudo make install
if [[ "${RUNNER_OS}" == "Linux" ]]; then
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${OSRM_INSTALL_DIR}/lib" >> $GITHUB_ENV
@@ -506,14 +532,14 @@ jobs:
fi
popd
- name: Build example
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }}
run: |
mkdir example/build && pushd example/build
cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE}
make --jobs=${JOBS}
popd
- name: Run all tests
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY != 'ON' }}
run: |
make -C test/data benchmark
@@ -524,85 +550,66 @@ jobs:
# All tests assume to be run from the build directory
pushd ${OSRM_BUILD_DIR}
for i in ./unit_tests/*-tests ; do echo Running $i ; $i ; done
if [ -z "${ENABLE_SANITIZER}" ] && [ "$TARGET_ARCH" != "i686" ]; then
if [ -z "${ENABLE_SANITIZER}" ]; then
npm run nodejs-tests
fi
popd
npm test
- name: Run benchmarks
if: ${{ matrix.ENABLE_BENCHMARKS == 'ON' }}
run: |
pushd ${OSRM_BUILD_DIR}
make --jobs=${JOBS} benchmarks
./src/benchmarks/alias-bench
./src/benchmarks/json-render-bench ../src/benchmarks/portugal_to_korea.json
./src/benchmarks/match-bench ../test/data/ch/monaco.osrm
./src/benchmarks/packedvector-bench
./src/benchmarks/rtree-bench ../test/data/monaco.osrm.ramIndex ../test/data/monaco.osrm.fileIndex ../test/data/monaco.osrm.nbg_nodes
popd
- name: Use Node 16
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
uses: actions/setup-node@v3
with:
node-version: 16
- name: Run Node package tests on Node 16
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
run: |
node --version
npm run nodejs-tests
- name: Use Node 18
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
uses: actions/setup-node@v3
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
uses: actions/setup-node@v4
with:
node-version: 18
- name: Run Node package tests on Node 18
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
run: |
node --version
npm run nodejs-tests
- name: Use Node 20
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
uses: actions/setup-node@v4
with:
node-version: 20
- name: Run Node package tests on Node 20
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
run: |
node --version
npm run nodejs-tests
- name: Use Node latest
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
uses: actions/setup-node@v3
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
uses: actions/setup-node@v4
with:
node-version: latest
- name: Run Node package tests on Node-latest
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' && matrix.ENABLE_APPLE_SILICON != 'ON' }}
if: ${{ matrix.NODE_PACKAGE_TESTS_ONLY == 'ON' }}
run: |
node --version
npm run nodejs-tests
- name: Upload test logs
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: logs
path: test/logs/
- name: Generate code coverage
if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
run: |
lcov --directory . --capture --output-file coverage.info # capture coverage info
lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter out system
lcov --list coverage.info #debug info
# Uploading report to CodeCov
- name: Upload code coverage
if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
uses: codecov/codecov-action@v1
with:
files: coverage.info
name: codecov-osrm-backend
fail_ci_if_error: true
verbose: true
- name: Check Apple Silicon binary
if: ${{ matrix.ENABLE_APPLE_SILICON == 'ON' }}
run: |
ARCH=$(file ./lib/binding/node_osrm.node | awk '{printf $NF}')
if [[ "$ARCH" != "arm64" ]]; then
file ./lib/binding/node_osrm.node
>&2 echo "Wrong architecture!"
exit 1
fi
# - name: Generate code coverage
# if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
# run: |
# lcov --directory . --capture --output-file coverage.info # capture coverage info
# lcov --remove coverage.info '/usr/*' --output-file coverage.info # filter out system
# lcov --list coverage.info #debug info
# # Uploading report to CodeCov
# - name: Upload code coverage
# if: ${{ matrix.ENABLE_COVERAGE == 'ON' }}
# uses: codecov/codecov-action@v4
# with:
# files: coverage.info
# name: codecov-osrm-backend
# fail_ci_if_error: true
# verbose: true
- name: Build Node package
if: ${{ matrix.build_node_package }}
run: ./scripts/ci/node_package.sh
@@ -619,9 +626,113 @@ jobs:
omitNameDuringUpdate: true
replacesArtifacts: true
token: ${{ secrets.GITHUB_TOKEN }}
- name: Show CCache statistics
run: |
ccache -p
ccache -s
benchmarks:
if: github.event_name == 'pull_request'
needs: [format-taginfo-docs]
runs-on: ubuntu-22.04
env:
CCOMPILER: gcc-12 #clang-13
CXXCOMPILER: g++-12 #clang++-13
CC: gcc-12 #clang-13
CXX: g++-12 #clang++-13
CXXFLAGS: '-Wno-array-bounds -Wno-uninitialized'
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_REPOSITORY: ${{ github.repository }}
RUN_BIG_BENCHMARK: ${{ contains(github.event.pull_request.labels.*.name, 'Performance') }}
steps:
- name: Enable data.osm.pbf cache
if: ${{ ! env.RUN_BIG_BENCHMARK }}
uses: actions/cache@v4
with:
path: ~/data.osm.pbf
key: v1-data-osm-pbf
restore-keys: |
v1-data-osm-pbf
- name: Enable compiler cache
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@v4
with:
path: ~/.conan
key: v1-conan-benchmarks-${{ github.sha }}
restore-keys: |
v1-conan-benchmarks-
- name: Checkout PR Branch
uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
path: pr
- name: Install dependencies
run: |
python3 -m pip install "conan<2.0.0" "requests==2.31.0" "numpy==1.26.4" #--break-system-packages
sudo apt-get update -y && sudo apt-get install ccache
- name: Prepare data
run: |
if [ "$RUN_BIG_BENCHMARK" = "true" ]; then
rm -rf ~/data.osm.pbf
wget http://download.geofabrik.de/europe/poland-latest.osm.pbf -O ~/data.osm.pbf --quiet
gunzip -c ./pr/test/data/poland_gps_traces.csv.gz > ~/gps_traces.csv
else
if [ ! -f "~/data.osm.pbf" ]; then
wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf -O ~/data.osm.pbf
else
echo "Using cached data.osm.pbf"
fi
gunzip -c ./pr/test/data/berlin_gps_traces.csv.gz > ~/gps_traces.csv
fi
- name: Prepare environment
run: |
echo "CCACHE_DIR=$HOME/.ccache" >> $GITHUB_ENV
mkdir -p $HOME/.ccache
ccache --zero-stats
ccache --max-size=256M
- name: Build PR Branch
run: |
mkdir -p pr/build
cd pr/build
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
make -j$(nproc) benchmarks
cd ..
make -C test/data
- name: Checkout Base Branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
path: base
- name: Build Base Branch
run: |
mkdir base/build
cd base/build
cmake -DENABLE_CONAN=ON -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
make -j$(nproc) benchmarks
cd ..
make -C test/data
- name: Run Benchmarks
run: |
./pr/scripts/ci/run_benchmarks.sh base pr
- name: Post Benchmark Results
run: |
python3 pr/scripts/ci/post_benchmark_results.py base_results pr_results
- name: Show CCache statistics
run: |
ccache -p
ccache -s
ci-complete:
runs-on: ubuntu-22.04
needs: [build-test-publish, docker-image, windows-release-node]
needs: [build-test-publish, docker-image, windows-release-node, benchmarks]
steps:
- run: echo "CI complete"
+38
View File
@@ -1,17 +1,43 @@
# Unreleased
- Changes from 5.27.1
- Features
- REMOVED: Remove all core-CH left-overs [#6920](https://github.com/Project-OSRM/osrm-backend/pull/6920)
- ADDED: Add support for a keepalive_timeout flag. [#6674](https://github.com/Project-OSRM/osrm-backend/pull/6674)
- ADDED: Add support for a default_radius flag. [#6575](https://github.com/Project-OSRM/osrm-backend/pull/6575)
- ADDED: Add support for disabling feature datasets. [#6666](https://github.com/Project-OSRM/osrm-backend/pull/6666)
- 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 clang-format to version 15. [#6919](https://github.com/Project-OSRM/osrm-backend/pull/6919)
- CHANGED: Use Debian Bookworm as base Docker image [#6904](https://github.com/Project-OSRM/osrm-backend/pull/6904)
- 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)
- REMOVED: Drop support of Node 12 & 14. [#6431](https://github.com/Project-OSRM/osrm-backend/pull/6431)
- ADDED: Add 'load directly' mode to default Cucumber test suite. [#6663](https://github.com/Project-OSRM/osrm-backend/pull/6663)
- CHANGED: Fix compilation for Boost 1.85.0 [#6856](https://github.com/Project-OSRM/osrm-backend/pull/6856)
- CHANGED: Drop support for Node 16 [#6855](https://github.com/Project-OSRM/osrm-backend/pull/6855)
- REMOVED: Remove unused AppVeyor files [#6860](https://github.com/Project-OSRM/osrm-backend/pull/6860)
- CHANGED: Upgrade clang-format to version 15 [#6859](https://github.com/Project-OSRM/osrm-backend/pull/6859)
- NodeJS:
- CHANGED: Use node-api instead of NAN. [#6452](https://github.com/Project-OSRM/osrm-backend/pull/6452)
- Misc:
- FIXED: Fix bugprone-unused-return-value clang-tidy warning. [#6934](https://github.com/Project-OSRM/osrm-backend/pull/6934)
- FIXED: Fix performance-noexcept-move-constructor clang-tidy warning. [#6931](https://github.com/Project-OSRM/osrm-backend/pull/6933)
- FIXED: Fix performance-noexcept-swap clang-tidy warning. [#6931](https://github.com/Project-OSRM/osrm-backend/pull/6931)
- CHANGED: Use custom struct instead of std::pair in QueryHeap. [#6921](https://github.com/Project-OSRM/osrm-backend/pull/6921)
- CHANGED: Use std::string_view::starts_with instead of boost::starts_with. [#6918](https://github.com/Project-OSRM/osrm-backend/pull/6918)
- CHANGED: Get rid of boost::math::constants::* and M_PI in favor of std::numbers. [#6916](https://github.com/Project-OSRM/osrm-backend/pull/6916)
- CHANGED: Make constants in PackedVector constexpr. [#6917](https://github.com/Project-OSRM/osrm-backend/pull/6917)
- CHANGED: Use std::variant instead of mapbox::util::variant. [#6903](https://github.com/Project-OSRM/osrm-backend/pull/6903)
- CHANGED: Bump rapidjson to version f9d53419e912910fd8fa57d5705fa41425428c35 [#6906](https://github.com/Project-OSRM/osrm-backend/pull/6906)
- CHANGED: Bump mapbox/variant to version 1.2.0 [#6898](https://github.com/Project-OSRM/osrm-backend/pull/6898)
- 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: 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)
- ADDED: Add support for "unlimited" to be passed as a value for the default-radius and max-matching-radius flags. [#6599](https://github.com/Project-OSRM/osrm-backend/pull/6599)
- CHANGED: Allow -1.0 as unlimited for default_radius value. [#6599](https://github.com/Project-OSRM/osrm-backend/pull/6599)
@@ -30,10 +56,22 @@
- FIXED: Added a variable to preprocessor guard in file osrm-backend/include/util/range_table.hpp to solve build error. [#6596](https://github.com/Project-OSRM/osrm-backend/pull/6596)
- FIXED: Ensure required file check in osrm-routed is correctly enforced. [#6655](https://github.com/Project-OSRM/osrm-backend/pull/6655)
- FIXED: Correct HTTP docs to reflect summary output dependency on steps parameter. [#6655](https://github.com/Project-OSRM/osrm-backend/pull/6655)
- ADDED: Extract prerelease/build information from package semver [#6839](https://github.com/Project-OSRM/osrm-backend/pull/6839)
- Profiles:
- FIXED: Bicycle and foot profiles now don't route on proposed ways [#6615](https://github.com/Project-OSRM/osrm-backend/pull/6615)
- Routing:
- FIXED: Fix adding traffic signal penalties during compression [#6419](https://github.com/Project-OSRM/osrm-backend/pull/6419)
- FIXED: Correctly handle compressed traffic signals. [#6724](https://github.com/Project-OSRM/osrm-backend/pull/6724)
- FIXED: Fix bug when searching for maneuver overrides [#6739](https://github.com/Project-OSRM/osrm-backend/pull/6739)
- 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)
# 5.27.1
- Changes from 5.27.0
- Misc:
+62 -50
View File
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.18)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
@@ -31,7 +31,7 @@ option(ENABLE_ASSERTIONS "Use assertions in release mode" OFF)
option(ENABLE_DEBUG_LOGGING "Use debug logging in release mode" OFF)
option(ENABLE_COVERAGE "Build with coverage instrumentalisation" OFF)
option(ENABLE_SANITIZER "Use memory sanitizer for Debug build" OFF)
option(ENABLE_LTO "Use LTO if available" OFF)
option(ENABLE_LTO "Use LTO if available" ON)
option(ENABLE_FUZZING "Fuzz testing using LLVM's libFuzzer" OFF)
option(ENABLE_NODE_BINDINGS "Build NodeJs bindings" OFF)
option(ENABLE_CLANG_TIDY "Enables clang-tidy checks" OFF)
@@ -42,16 +42,13 @@ if (ENABLE_CLANG_TIDY)
message(FATAL_ERROR "ENABLE_CLANG_TIDY is ON but clang-tidy is not found!")
else()
message(STATUS "Found clang-tidy at ${CLANG_TIDY_COMMAND}")
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};--warnings-as-errors=*")
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND};--warnings-as-errors=*;--header-filter=.*")
endif()
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# be compatible with version handling before cmake 3.x
if (POLICY CMP0048)
cmake_policy(SET CMP0048 OLD)
endif()
if (POLICY CMP0057)
cmake_policy(SET CMP0057 NEW)
endif()
@@ -73,14 +70,17 @@ include(JSONParser)
file(READ "package.json" packagejsonraw)
sbeParseJson(packagejson packagejsonraw)
if (packagejson.version MATCHES "^([0-9]+)\.([0-9]+)\.([0-9]+)")
set(OSRM_VERSION_MAJOR ${CMAKE_MATCH_1})
set(OSRM_VERSION_MINOR ${CMAKE_MATCH_2})
set(OSRM_VERSION_PATCH ${CMAKE_MATCH_3})
# This regex is not strict enough, but the correct one is too complicated for cmake matching.
# https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
if (packagejson.version MATCHES "^([0-9]+)\.([0-9]+)\.([0-9]+)([-+][0-9a-zA-Z.-]+)?$")
set(OSRM_VERSION_MAJOR ${CMAKE_MATCH_1})
set(OSRM_VERSION_MINOR ${CMAKE_MATCH_2})
set(OSRM_VERSION_PATCH ${CMAKE_MATCH_3})
set(OSRM_VERSION_PRERELEASE_BUILD ${CMAKE_MATCH_4})
set(OSRM_VERSION "${OSRM_VERSION_MAJOR}.${OSRM_VERSION_MINOR}.${OSRM_VERSION_PATCH}")
set(OSRM_VERSION packagejson.version)
else()
message(FATAL_ERROR "Version from package.json cannot be parsed, expected semver compatible X.Y.Z, but found ${packagejson.version}")
message(FATAL_ERROR "Version from package.json cannot be parsed, expected semver compatible label, but found ${packagejson.version}")
endif()
if (MSVC)
@@ -115,13 +115,12 @@ include(GNUInstallDirs)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
message(STATUS "Building on a 64 bit system")
else()
message(STATUS "Building on a 32 bit system")
message(FATAL_ERROR "Building on a 32 bit system is not supported")
endif()
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include/)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include/)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/sol2-3.3.0/include)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/variant/include)
include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/third_party/sol2/include)
set(BOOST_COMPONENTS date_time chrono filesystem iostreams program_options regex system thread unit_test_framework)
@@ -151,7 +150,7 @@ add_library(UPDATER OBJECT ${UpdaterGlob})
add_library(STORAGE OBJECT ${StorageGlob})
add_library(ENGINE OBJECT ${EngineGlob})
if (BUILD_ROUTED)
if (BUILD_ROUTED)
add_library(SERVER OBJECT ${ServerGlob})
add_executable(osrm-routed src/tools/routed.cpp $<TARGET_OBJECTS:SERVER> $<TARGET_OBJECTS:UTIL>)
endif()
@@ -223,7 +222,7 @@ endif()
set(MAYBE_COVERAGE_LIBRARIES "")
if (ENABLE_COVERAGE)
if (NOT CMAKE_BUILD_TYPE MATCHES "Debug")
message(ERROR "ENABLE_COVERAGE=ON only make sense with a Debug build")
message(ERROR "ENABLE_COVERAGE=ON only makes sense with a Debug build")
endif()
message(STATUS "Enabling coverage")
set(MAYBE_COVERAGE_LIBRARIES "-lgcov")
@@ -267,7 +266,6 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
add_dependency_defines(-DBOOST_LIB_DIAGNOSTIC)
add_dependency_defines(-D_CRT_SECURE_NO_WARNINGS)
add_dependency_defines(-DNOMINMAX) # avoid min and max macros that can break compilation
add_dependency_defines(-D_USE_MATH_DEFINES) #needed for M_PI with cmath.h
add_dependency_defines(-D_WIN32_WINNT=0x0501)
add_dependency_defines(-DXML_STATIC)
find_library(ws2_32_LIBRARY_PATH ws2_32)
@@ -309,10 +307,10 @@ add_subdirectory(${FLATBUFFERS_SRC_DIR}
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
EXCLUDE_FROM_ALL)
set(FMT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/fmt-9.1.0/include")
set(FMT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/fmt/include")
add_compile_definitions(FMT_HEADER_ONLY)
include_directories(SYSTEM ${FMT_INCLUDE_DIR})
# see https://stackoverflow.com/questions/70898030/boost-link-error-using-conan-find-package
if (MSVC)
@@ -322,22 +320,24 @@ endif()
if(ENABLE_CONAN)
message(STATUS "Installing dependencies via Conan")
# Conan will generate Find*.cmake files to build directory, so we use them with the highest priority
# Conan will generate Find*.cmake files to build directory, so we use them with the highest priority
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_BINARY_DIR})
list(INSERT CMAKE_PREFIX_PATH 0 ${CMAKE_BINARY_DIR})
include(${CMAKE_CURRENT_LIST_DIR}/cmake/conan.cmake)
set(CONAN_BOOST_VERSION "1.79.0#96e4902111a2e343a8ba0aa95391bb58")
set(CONAN_BZIP2_VERSION "1.0.8#d1b2d5816f25865acf978501dff1f897")
set(CONAN_EXPAT_VERSION "2.2.10#916908d4a570ad839edd25322c3268cd")
set(CONAN_LUA_VERSION "5.4.4#3ec62efc37cd0a5d80b9e5cb35277360")
set(CONAN_TBB_VERSION "2021.3.0#507ec17cbd51a84167e143b20d170eea")
conan_check(REQUIRED)
set(CONAN_BOOST_VERSION "1.85.0@#14265ec82b25d91305bbb3b30d3357f8")
set(CONAN_BZIP2_VERSION "1.0.8@#d1b2d5816f25865acf978501dff1f897")
set(CONAN_EXPAT_VERSION "2.2.10@#916908d4a570ad839edd25322c3268cd")
set(CONAN_LUA_VERSION "5.4.4@#3ec62efc37cd0a5d80b9e5cb35277360")
set(CONAN_TBB_VERSION "2021.3.0@#507ec17cbd51a84167e143b20d170eea")
set(CONAN_SYSTEM_INCLUDES ON)
# TODO:
# if we link TBB dynamically osrm-extract.exe finishes on the first access to any TBB symbol
# TODO:
# if we link TBB dynamically osrm-extract.exe finishes on the first access to any TBB symbol
# with exit code = -1073741515, which means that program cannot load required DLL.
if (MSVC)
set(TBB_SHARED False)
@@ -345,14 +345,14 @@ if(ENABLE_CONAN)
set(TBB_SHARED True)
endif()
set(CONAN_ARGS
REQUIRES
set(CONAN_ARGS
REQUIRES
"boost/${CONAN_BOOST_VERSION}"
"bzip2/${CONAN_BZIP2_VERSION}"
"expat/${CONAN_EXPAT_VERSION}"
"lua/${CONAN_LUA_VERSION}"
"onetbb/${CONAN_TBB_VERSION}"
BASIC_SETUP
BASIC_SETUP
GENERATORS cmake_find_package json # json generator generates a conanbuildinfo.json in the build folder so (non-CMake) projects can easily parse OSRM's dependencies
KEEP_RPATHS
NO_OUTPUT_DIRS
@@ -361,6 +361,13 @@ if(ENABLE_CONAN)
boost:without_stacktrace=True # Apple Silicon cross-compilation fails without it
BUILD missing
)
# Enable revisions in the conan config
execute_process(COMMAND ${CONAN_CMD} config set general.revisions_enabled=1 RESULT_VARIABLE RET_CODE)
if(NOT "${RET_CODE}" STREQUAL "0")
message(FATAL_ERROR "Error setting revisions for Conan: '${RET_CODE}'")
endif()
# explicitly say Conan to use x86 dependencies if build for x86 platforms (https://github.com/conan-io/cmake-conan/issues/141)
if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
conan_cmake_run("${CONAN_ARGS};ARCH;x86")
@@ -389,7 +396,7 @@ if(ENABLE_CONAN)
set(Boost_ZLIB_LIBRARY "${Boost_zlib_LIB_TARGETS}")
set(Boost_REGEX_LIBRARY "${Boost_regex_LIB_TARGETS}")
set(Boost_UNIT_TEST_FRAMEWORK_LIBRARY "${Boost_unit_test_framework_LIB_TARGETS}")
find_package(BZip2 REQUIRED)
find_package(EXPAT REQUIRED)
@@ -462,6 +469,9 @@ add_dependency_defines(-DBOOST_SPIRIT_USE_PHOENIX_V3)
add_dependency_defines(-DBOOST_RESULT_OF_USE_DECLTYPE)
add_dependency_defines(-DBOOST_FILESYSTEM_NO_DEPRECATED)
# Workaround for https://github.com/boostorg/phoenix/issues/111
add_dependency_defines(-DBOOST_PHOENIX_STL_TUPLE_H_)
add_definitions(${OSRM_DEFINES})
include_directories(SYSTEM ${DEPENDENCIES_INCLUDE_DIRS})
@@ -595,7 +605,6 @@ if (BUILD_ROUTED)
set_property(TARGET osrm-routed PROPERTY INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()
file(GLOB VariantGlob third_party/variant/include/mapbox/*.hpp)
file(GLOB FlatbuffersGlob third_party/flatbuffers/include/flatbuffers/*.h)
file(GLOB LibraryGlob include/osrm/*.hpp)
file(GLOB ParametersGlob include/engine/api/*_parameters.hpp)
@@ -615,7 +624,6 @@ install(FILES ${ContractorHeader} DESTINATION include/osrm/contractor)
install(FILES ${LibraryGlob} DESTINATION include/osrm)
install(FILES ${ParametersGlob} DESTINATION include/osrm/engine/api)
install(FILES ${ApiHeader} DESTINATION include/osrm/engine/api)
install(FILES ${VariantGlob} DESTINATION include/mapbox)
install(FILES ${FlatbuffersGlob} DESTINATION include/flatbuffers)
install(TARGETS osrm-extract DESTINATION bin)
install(TARGETS osrm-partition DESTINATION bin)
@@ -639,6 +647,10 @@ install(TARGETS osrm_guidance DESTINATION lib)
set(DefaultProfilesDir profiles)
install(DIRECTORY ${DefaultProfilesDir} DESTINATION share/osrm)
# Install data geojson files to /usr/local/share/osrm/data by default
set(DefaultProfilesDir data)
install(DIRECTORY ${DefaultProfilesDir} DESTINATION share/osrm)
# Setup exporting variables for pkgconfig and subproject
#
@@ -733,23 +745,23 @@ if (ENABLE_FUZZING)
add_subdirectory(fuzz)
endif ()
# add headers sanity check target that includes all headers independently
set(check_headers_dir "${PROJECT_BINARY_DIR}/check-headers")
file(GLOB_RECURSE headers_to_check
${PROJECT_BINARY_DIR}/*.hpp
${PROJECT_SOURCE_DIR}/include/*.hpp)
foreach(header ${headers_to_check})
# add headers sanity check target that includes all headers independently
set(check_headers_dir "${PROJECT_BINARY_DIR}/check-headers")
file(GLOB_RECURSE headers_to_check
${PROJECT_BINARY_DIR}/*.hpp
${PROJECT_SOURCE_DIR}/include/*.hpp)
foreach(header ${headers_to_check})
if ("${header}" MATCHES ".*/include/nodejs/.*")
# we do not check NodeJS bindings headers
continue()
endif()
get_filename_component(filename ${header} NAME_WE)
set(filename "${check_headers_dir}/${filename}.cpp")
if (NOT EXISTS ${filename})
file(WRITE ${filename} "#include \"${header}\"\n")
endif()
list(APPEND sources ${filename})
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
get_filename_component(filename ${header} NAME_WE)
set(filename "${check_headers_dir}/${filename}.cpp")
if (NOT EXISTS ${filename})
file(WRITE ${filename} "#include \"${header}\"\n")
endif()
list(APPEND sources ${filename})
endforeach()
add_library(check-headers STATIC EXCLUDE_FROM_ALL ${sources})
set_target_properties(check-headers PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${check_headers_dir})
+1 -1
View File
@@ -10,7 +10,7 @@ You can add a :+1: emoji reaction to the issue if you want to express interest i
# Developer
We use `clang-format` version `3.8` to consistently format the code base. There is a helper script under `scripts/format.sh`.
We use `clang-format` version `15` to consistently format the code base. There is a helper script under `scripts/format.sh`.
The format is automatically checked by the `mason-linux-release` job of a Travis CI build.
To save development time a local hook `.git/hooks/pre-push`
```
+2 -2
View File
@@ -15,12 +15,12 @@ The following services are available via HTTP API, C++ library interface and Nod
To quickly try OSRM use our [demo server](http://map.project-osrm.org) which comes with both the backend and a frontend on top.
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [this guide about mapping for navigation](https://www.mapbox.com/mapping/mapping-for-navigation/).
For a quick introduction about how the road network is represented in OpenStreetMap and how to map specific road network features have a look at [the OSM wiki on routing](https://wiki.openstreetmap.org/wiki/Routing) or [this guide about mapping for navigation](https://web.archive.org/web/20221206013651/https://labs.mapbox.com/mapping/mapping-for-navigation/).
Related [Project-OSRM](https://github.com/Project-OSRM) repositories:
- [osrm-frontend](https://github.com/Project-OSRM/osrm-frontend) - User-facing frontend with map. The demo server runs this on top of the backend
- [osrm-text-instructions](https://github.com/Project-OSRM/osrm-text-instructions) - Text instructions from OSRM route response
- [osrm-backend-docker](https://hub.docker.com/r/osrm/osrm-backend/) - Ready to use Docker images
- [osrm-backend-docker](https://github.com/project-osrm/osrm-backend/pkgs/container/osrm-backend) - Ready to use Docker images
## Documentation
-15
View File
@@ -1,15 +0,0 @@
os: Visual Studio 2019
# clone directory
clone_folder: c:\projects\osrm
platform: x64
# no-op for the time being until someone with access to GitHub checks settings will remove integration with AppVeyor
# https://github.com/Project-OSRM/osrm-backend/pull/6312#issuecomment-1217237055
build_script:
- EXIT 0
branches:
only:
- master
-32
View File
@@ -1,32 +0,0 @@
@ECHO OFF
SETLOCAL
SET EL=0
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SET PLATFORM=x64
SET CONFIGURATION=Release
::SET LOCAL_DEV=1
FOR /F "tokens=*" %%i in ('git rev-parse --abbrev-ref HEAD') do SET APPVEYOR_REPO_BRANCH=%%i
ECHO APPVEYOR_REPO_BRANCH^: %APPVEYOR_REPO_BRANCH%
SET PATH=C:\Program Files\7-Zip;%PATH%
powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
CALL appveyor-build.bat
IF %ERRORLEVEL% NEQ 0 GOTO ERROR
GOTO DONE
:ERROR
ECHO ~~~~~~~~~~~~~~~~~~~~~~ ERROR %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ECHO ERRORLEVEL^: %ERRORLEVEL%
SET EL=%ERRORLEVEL%
:DONE
ECHO ~~~~~~~~~~~~~~~~~~~~~~ DONE %~f0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
EXIT /b %EL%
+1 -1
View File
@@ -55,7 +55,7 @@ function(_get_msvc_ide_version result)
set(${result} 15 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1920 AND MSVC_VERSION VERSION_LESS 1930)
set(${result} 16 PARENT_SCOPE)
elseif(NOT MSVC_VERSION VERSION_LESS 1930 AND MSVC_VERSION VERSION_LESS 1940)
elseif(NOT MSVC_VERSION VERSION_LESS 1930 AND MSVC_VERSION VERSION_LESS 1950)
set(${result} 17 PARENT_SCOPE)
else()
message(FATAL_ERROR "Conan: Unknown MSVC compiler version [${MSVC_VERSION}]")
+8 -15
View File
@@ -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,10 @@ 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)
# these warnings are not enabled by default
# no_warning(name-of-warning)
no_warning(deprecated-comma-subscript)
no_warning(comma-subscript)
no_warning(ambiguous-reversed-operator)
no_warning(restrict)
no_warning(free-nonheap-object)
+8 -7
View File
@@ -1,15 +1,15 @@
FROM debian:bullseye-slim as builder
FROM debian:bookworm-slim as builder
ARG DOCKER_TAG
ARG BUILD_CONCURRENCY
RUN mkdir -p /src && mkdir -p /opt
RUN apt-get update && \
apt-get -y --no-install-recommends install ca-certificates cmake make git gcc g++ libbz2-dev libxml2-dev wget \
libzip-dev libboost1.74-all-dev lua5.4 liblua5.4-dev pkg-config -o APT::Install-Suggests=0 -o APT::Install-Recommends=0
libzip-dev libboost1.81-all-dev lua5.4 liblua5.4-dev pkg-config -o APT::Install-Suggests=0 -o APT::Install-Recommends=0
RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
ldconfig /usr/local/lib && \
git clone --branch v2021.3.0 --single-branch https://github.com/oneapi-src/oneTBB.git && \
git clone --branch v2021.12.0 --single-branch https://github.com/oneapi-src/oneTBB.git && \
cd oneTBB && \
mkdir build && \
cd build && \
@@ -21,6 +21,7 @@ COPY . /src
WORKDIR /src
RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
export CXXFLAGS="-Wno-array-bounds -Wno-uninitialized" && \
echo "Building OSRM ${DOCKER_TAG}" && \
git show --format="%H" | head -n1 > /opt/OSRM_GITSHA && \
echo "Building OSRM gitsha $(cat /opt/OSRM_GITSHA)" && \
@@ -42,15 +43,15 @@ RUN NPROC=${BUILD_CONCURRENCY:-$(nproc)} && \
# Multistage build to reduce image size - https://docs.docker.com/engine/userguide/eng-image/multistage-build/#use-multi-stage-builds
# Only the content below ends up in the image, this helps remove /src from the image (which is large)
FROM debian:bullseye-slim as runstage
FROM debian:bookworm-slim as runstage
COPY --from=builder /usr/local /usr/local
COPY --from=builder /opt /opt
RUN apt-get update && \
apt-get install -y --no-install-recommends libboost-program-options1.74.0 libboost-regex1.74.0 \
libboost-date-time1.74.0 libboost-chrono1.74.0 libboost-filesystem1.74.0 \
libboost-iostreams1.74.0 libboost-system1.74.0 libboost-thread1.74.0 \
apt-get install -y --no-install-recommends libboost-program-options1.81.0 libboost-regex1.81.0 \
libboost-date-time1.81.0 libboost-chrono1.81.0 libboost-filesystem1.81.0 \
libboost-iostreams1.81.0 libboost-system1.81.0 libboost-thread1.81.0 \
expat liblua5.4-0 && \
rm -rf /var/lib/apt/lists/* && \
# add /usr/local/lib to ldconfig to allow loading libraries from there
+2 -2
View File
@@ -35,7 +35,7 @@ To pass parameters to each location some options support an array-like encoding:
|radiuses |`{radius};{radius}[;{radius} ...]` |Limits the search to given radius in meters. |
|generate\_hints |`true` (default), `false` |Adds a Hint to the response which can be used in subsequent requests, see `hints` parameter. |
|hints |`{hint};{hint}[;{hint} ...]` |Hint from previous request to derive position in street network. |
|approaches |`{approach};{approach}[;{approach} ...]` |Keep waypoints on curbside. |
|approaches |`{approach};{approach}[;{approach} ...]` |Restrict the direction on the road network at a waypoint, relative to the input coordinate. |
|exclude |`{class}[,{class}]` |Additive list of classes to avoid, the order does not matter. |
|snapping |`default` (default), `any` |Default snapping avoids is_startpoint (see profile) edges, `any` will snap to any edge in the graph |
|skip_waypoints |`true`, `false` (default) |Removes waypoints from the response. Waypoints are still calculated, but not serialized. Could be useful in case you are interested in some other part of the response and do not want to transfer waste data. |
@@ -47,7 +47,7 @@ Where the elements follow the following format:
|bearing |`{value},{range}` `integer 0 .. 360,integer 0 .. 180` |
|radius |`double >= 0` or `unlimited` (default) |
|hint |Base64 `string` |
|approach |`curb` or `unrestricted` (default) |
|approach |`curb`, `opposite` or `unrestricted` (default) |
|class |A class name determined by the profile or `none`. |
```
+5 -5
View File
@@ -21,7 +21,7 @@ var osrm = new OSRM('network.osrm');
**Parameters**
- `options` **([Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String))** Options for creating an OSRM object or string to the `.osrm` file. (optional, default `{shared_memory:true}`)
- `options.algorithm` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', 'CoreCH' or 'MLD'. Default is 'CH'.
- `options.algorithm` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** The algorithm to use for routing. Can be 'CH', or 'MLD'. Default is 'CH'.
Make sure you prepared the dataset with the correct toolchain.
- `options.shared_memory` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Connects to the persistent shared memory datastore.
This requires you to run `osrm-datastore` prior to creating an `OSRM` object.
@@ -63,7 +63,7 @@ Returns the fastest route between two or more coordinates while visiting the way
- `options.geometries` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Returned route geometry format (influences overview and per step). Can also be `geojson`. (optional, default `polyline`)
- `options.overview` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Add overview geometry either `full`, `simplified` according to highest zoom level it could be display on, or not at all (`false`). (optional, default `simplified`)
- `options.continue_straight` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)?** Forces the route to keep going straight at waypoints and don't do a uturn even if it would be faster. Default value depends on the profile.
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Restrict the direction on the road network at a waypoint, relative to the input coordinate. Can be `null` (unrestricted, default), `curb` or `opposite`.
`null`/`true`/`false`
- `options.waypoints` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Indices to coordinates to treat as waypoints. If not supplied, all coordinates are waypoints. Must include first and last coordinate index.
- `options.format` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Which output format to use, either `json`, or [`flatbuffers`](https://github.com/Project-OSRM/osrm-backend/tree/master/include/engine/api/flatbuffers).
@@ -101,7 +101,7 @@ Note: `coordinates` in the general options only supports a single `{longitude},{
- `options.generate_hints` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Whether or not adds a Hint to the response which can be used in subsequent requests. (optional, default `true`)
- `options.number` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** Number of nearest segments that should be returned.
Must be an integer greater than or equal to `1`. (optional, default `1`)
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Restrict the direction on the road network at a waypoint, relative to the input coordinate. Can be `null` (unrestricted, default), `curb` or `opposite`.
- `options.format` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Which output format to use, either `json`, or [`flatbuffers`](https://github.com/Project-OSRM/osrm-backend/tree/master/include/engine/api/flatbuffers).
- `options.snapping` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Which edges can be snapped to, either `default`, or `any`. `default` only snaps to edges marked by the profile as `is_startpoint`, `any` will allow snapping to any edge in the routing graph.
- `callback` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)**
@@ -141,7 +141,7 @@ Optionally returns distance table.
- `options.sources` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to use
location with given index as source. Default is to use all.
- `options.destinations` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** An array of `index` elements (`0 <= integer < #coordinates`) to use location with given index as destination. Default is to use all.
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Restrict the direction on the road network at a waypoint, relative to the input coordinate.. Can be `null` (unrestricted, default), `curb` or `opposite`.
- `options.fallback_speed` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Replace `null` responses in result with as-the-crow-flies estimates based on `fallback_speed`. Value is in metres/second.
- `options.fallback_coordinate` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Either `input` (default) or `snapped`. If using a `fallback_speed`, use either the user-supplied coordinate (`input`), or the snapped coordinate (`snapped`) for calculating the as-the-crow-flies distance between two points.
- `options.scale_factor` **[Number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?** Multiply the table duration values in the table by this number for more controlled input into a route optimization solver.
@@ -298,7 +298,7 @@ Right now, the following combinations are possible:
- `options.roundtrip` **[Boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Return route is a roundtrip. (optional, default `true`)
- `options.source` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route starts at `any` or `first` coordinate. (optional, default `any`)
- `options.destination` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Return route ends at `any` or `last` coordinate. (optional, default `any`)
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Keep waypoints on curb side. Can be `null` (unrestricted, default) or `curb`.
- `options.approaches` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)?** Restrict the direction on the road network at a waypoint, relative to the input coordinate. Can be `null` (unrestricted, default), `curb` or `opposite`.
- `options.snapping` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** Which edges can be snapped to, either `default`, or `any`. `default` only snaps to edges marked by the profile as `is_startpoint`, `any` will allow snapping to any edge in the routing graph.
- `callback` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)**
+7 -7
View File
@@ -57,15 +57,15 @@ int main(int argc, const char *argv[])
// Execute routing request, this does the heavy lifting
const auto status = osrm.Route(params, result);
auto &json_result = result.get<json::Object>();
auto &json_result = std::get<json::Object>(result);
if (status == Status::Ok)
{
auto &routes = json_result.values["routes"].get<json::Array>();
auto &routes = std::get<json::Array>(json_result.values["routes"]);
// Let's just use the first route
auto &route = routes.values.at(0).get<json::Object>();
const auto distance = route.values["distance"].get<json::Number>().value;
const auto duration = route.values["duration"].get<json::Number>().value;
auto &route = std::get<json::Object>(routes.values.at(0));
const auto distance = std::get<json::Number>(route.values["distance"]).value;
const auto duration = std::get<json::Number>(route.values["duration"]).value;
// Warn users if extract does not contain the default coordinates from above
if (distance == 0 || duration == 0)
@@ -80,8 +80,8 @@ int main(int argc, const char *argv[])
}
else if (status == Status::Error)
{
const auto code = json_result.values["code"].get<json::String>().value;
const auto message = json_result.values["message"].get<json::String>().value;
const auto code = std::get<json::String>(json_result.values["code"]).value;
const auto message = std::get<json::String>(json_result.values["message"]).value;
std::cout << "Code: " << code << "\n";
std::cout << "Message: " << code << "\n";
+162 -42
View File
@@ -32,14 +32,14 @@ Feature: Car - Handle traffic lights
| l | traffic_signals |
When I route I should get
| from | to | time | # |
| from | to | time | # |
| 1 | 2 | 11.1s | no turn with no traffic light |
| 3 | 4 | 13.1s | no turn with traffic light |
| g | j | 18.7s | turn with no traffic light |
| k | n | 20.7s | turn with traffic light |
Scenario: Car - Traffic signal direction
Scenario: Car - Traffic signal direction straight
Given the node map
"""
a-1-b-2-c
@@ -112,14 +112,14 @@ Feature: Car - Handle traffic lights
Scenario: Car - Encounters a traffic light
Scenario: Car - Encounters a traffic light direction
Given the node map
"""
a f k
| | |
b-c-d h-g-i l-m-n
| | |
e j o
a f k p
| | | |
b-c-d h-g-i l-m-n q-r-s
| | | |
e j o t
"""
@@ -131,53 +131,70 @@ Feature: Car - Handle traffic lights
| fgj | primary |
| lmn | primary |
| kmo | primary |
| qrs | primary |
| prt | primary |
And the nodes
| node | highway | traffic_signals:direction |
| g | traffic_signals | forward |
| m | traffic_signals | backward |
| g | traffic_signals | |
| m | traffic_signals | forward |
| r | traffic_signals | backward |
When I route I should get
# Base case
| from | to | time | # |
| a | d | 21.9s | no turn with no traffic light |
| a | e | 22.2s | no turn with traffic light |
| a | b | 18.7s | turn with no traffic light |
| e | b | 21.9s | no turn with no traffic light |
| e | a | 22.2s | no turn with traffic light |
| a | e | 22.2s | no turn with no traffic light |
| a | d | 21.9s | turn with no traffic light |
| e | b | 21.9s | turn with no traffic light |
| e | a | 22.2s | no turn with no traffic light |
| e | d | 18.7s | turn with no traffic light |
| d | e | 21.9s | no turn with no traffic light |
| d | b | 11s | no turn with traffic light |
| d | e | 21.9s | turn with no traffic light |
| d | b | 11s | no turn with no traffic light |
| d | a | 18.7s | turn with no traffic light |
| b | a | 21.9s | no turn with no traffic light |
| b | d | 11s | no turn with traffic light |
| b | a | 21.9s | turn with no traffic light |
| b | d | 11s | no turn with no traffic light |
| b | e | 18.7s | turn with no traffic light |
| f | i | 23.9s | no turn with no traffic light |
# All have traffic lights - 2s penalty
| f | h | 20.7s | turn with traffic light |
| f | j | 24.2s | no turn with traffic light |
| f | h | 20.7s | turn with no traffic light |
| j | h | 21.9s | no turn with no traffic light |
| j | f | 22.2s | no turn with traffic light |
| j | i | 18.7s | turn with no traffic light |
| i | j | 21.9s | no turn with no traffic light |
| i | h | 11s | no turn with traffic light |
| i | f | 18.7s | turn with no traffic light |
| h | f | 23.9s | no turn with no traffic light |
| f | i | 23.9s | turn with traffic light |
| j | h | 23.9s | turn with traffic light |
| j | f | 24.2s | no turn with traffic light |
| j | i | 20.7s | turn with traffic light |
| i | j | 23.9s | turn with traffic light |
| i | h | 13s | no turn with traffic light |
| i | f | 20.7s | turn with traffic light |
| h | f | 23.9s | turn with traffic light |
| h | i | 13s | no turn with traffic light |
| h | j | 20.7s | turn with no traffic light |
| k | n | 21.9s | no turn with no traffic light |
| k | o | 22.2s | no turn with traffic light |
| k | l | 18.7s | turn with no traffic light |
| o | l | 23.9s | no turn with no traffic light |
| o | k | 24.2s | no turn with traffic light |
| o | n | 20.7s | turn with no traffic light |
| n | o | 23.9s | no turn with no traffic light |
| n | l | 13s | no turn with traffic light |
| n | k | 20.7s | turn with no traffic light |
| l | k | 21.9s | no turn with no traffic light |
| l | n | 11s | no turn with traffic light |
| l | o | 18.7s | turn with no traffic light |
| h | j | 20.7s | turn with traffic light |
# Front direction have traffic lights - 2s penalty
| k | l | 20.7s | turn with traffic light |
| k | o | 24.2s | no turn with traffic light |
| k | n | 23.9s | turn with traffic light |
| o | l | 21.9s | turn with no traffic light |
| o | k | 22.2s | no turn with no traffic light |
| o | n | 18.7s | turn with no traffic light |
| n | o | 21.9s | turn with no traffic light |
| n | l | 11s | no turn with no traffic light |
| n | k | 18.7s | turn with no traffic light |
| l | k | 23.9s | turn with traffic light |
| l | n | 13s | no turn with traffic light |
| l | o | 20.7s | turn with traffic light |
# Reverse direction have traffic lights - 2s penalty
| p | q | 18.7s | turn with no traffic light |
| p | t | 22.2s | no turn with no traffic light |
| p | s | 21.9s | turn with no traffic light |
| t | q | 23.9s | turn with traffic light |
| t | p | 24.2s | no turn with traffic light |
| t | s | 20.7s | turn with traffic light |
| s | t | 23.9s | turn with traffic light |
| s | q | 13s | no turn with traffic light |
| s | p | 20.7s | turn with traffic light |
| q | p | 21.9s | turn with no traffic light |
| q | s | 11s | no turn with no traffic light |
| q | t | 18.7s | turn with no traffic light |
Scenario: Traffic Signal Geometry
@@ -343,3 +360,106 @@ Feature: Car - Handle traffic lights
| from | to | route | speed | weights | time | distances | a:datasources | a:nodes | a:speed | a:duration | a:weight |
| a | c | abc,abc | 65 km/h | 22.2,0 | 22.2s | 400m,0m | 1:0 | 1:2:3 | 18:18 | 11.1:11.1 | 11.1:11.1 |
| c | a | abc,abc | 60 km/h | 24.2,0 | 24.2s | 400m,0m | 0:1 | 3:2:1 | 18:18 | 11.1:11.1 | 11.1:11.1 |
Scenario: Car - Traffic signal straight direction with edge compression
Given the node map
"""
a-1-b - c - d-2-e
"""
And the ways
| nodes | highway |
| abcde | primary |
And the nodes
| node | highway | traffic_signals:direction |
| c | traffic_signals | forward |
When I route I should get
| from | to | time | weight | # |
| 1 | 2 | 35.3s | 35.3 | no turn with traffic light |
| 2 | 1 | 33.3s | 33.3 | no turn with no traffic light |
Scenario: Car - Traffic signal turn direction with edge compression
Given the node map
"""
d
|
2
|
a-1-b - c - f
|
e
j
|
4
|
g-3-h - i - k
|
l
"""
And the ways
| nodes | highway |
| abc | primary |
| cf | primary |
| fd | primary |
| fe | primary |
| ghi | primary |
| ik | primary |
| kj | primary |
| kl | primary |
And the nodes
| node | highway | traffic_signals:direction |
| k | traffic_signals | forward |
When I route I should get
| from | to | time | weight | # |
| 1 | 2 | 44.2s | 44.2 | turn with no traffic light |
| 2 | 1 | 41s | 41 | turn with no traffic light |
| 3 | 4 | 46.2s | 46.2 | turn with traffic light |
| 4 | 3 | 41s | 41 | turn with no traffic light |
Scenario: Car - Traffic signal turn direction with turn restriction
Given the node map
"""
d
|
2
|
a-1-b - c - f
|
e
"""
And the ways
| nodes | highway |
| abc | primary |
| cf | primary |
| fd | primary |
| fe | primary |
And the nodes
| node | highway | traffic_signals:direction |
| f | traffic_signals | forward |
And the relations
| type | way:from | way:to | way:via | restriction |
| restriction | abc | fe | cf | no_right_turn |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | df | fc | f | right_turn_only |
When I route I should get
| from | to | time | weight | # |
| 1 | 2 | 46.2s | 46.2 | turn with traffic light |
| 2 | 1 | 41s | 41 | turn with no traffic light |
+24
View File
@@ -154,3 +154,27 @@ Feature: osrm-extract lua ways:get_nodes()
Then it should exit successfully
And stdout should contain "node 42"
And stdout should contain "way 42"
Scenario: osrm-extract flags accessible in process_segment function
Given the profile file
"""
functions = require('testbot')
functions.process_segment = function (profile, segment)
print('segment forward ' .. tostring(segment.flags.forward) .. ' backward ' .. tostring(segment.flags.backward))
end
return functions
"""
And the node map
"""
a b
"""
And the ways
| nodes | oneway |
| ab | yes |
And the data has been saved to disk
When I run "osrm-extract --profile {profile_file} {osm_file}"
Then it should exit successfully
And stdout should contain "segment forward true backward false"
+3
View File
@@ -23,6 +23,7 @@ Feature: osrm-routed command line options: help
And stdout should contain "--max-table-size"
And stdout should contain "--max-matching-size"
And stdout should contain "--default-radius"
And stdout should contain "--keepalive-timeout"
And it should exit successfully
Scenario: osrm-routed - Help, short
@@ -44,6 +45,7 @@ Feature: osrm-routed command line options: help
And stdout should contain "--max-table-size"
And stdout should contain "--max-matching-size"
And stdout should contain "--default-radius"
And stdout should contain "--keepalive-timeout"
And it should exit successfully
Scenario: osrm-routed - Help, long
@@ -65,4 +67,5 @@ Feature: osrm-routed command line options: help
And stdout should contain "--max-table-size"
And stdout should contain "--max-matching-size"
And stdout should contain "--default-radius"
And stdout should contain "--keepalive-timeout"
And it should exit successfully
+362 -16
View File
@@ -38,7 +38,41 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
Scenario: Start End opposite approach, option unrestricted for Start and End
Scenario: Start End same approach, option unrestricted for Start and opposite for End
Given the profile "testbot"
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc |
Scenario: Start End same approach, option opposite for Start and curb for End
Given the profile "testbot"
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | opposite curb | ab,bc,bc |
Scenario: Start End different approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
"""
@@ -56,7 +90,7 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Start End opposite approach, option unrestricted for Start and curb for End
Scenario: Start End different approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
"""
@@ -74,6 +108,43 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
Scenario: Start End different approach, option unrestricted for Start and opposite for End
Given the profile "testbot"
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc,bc |
Scenario: Start End different approach, option curb for Start and opposite for End
Given the profile "testbot"
And the node map
"""
e
a------b------c-----------d
s
"""
And the ways
| nodes |
| ab |
| bc |
| cd |
When I route I should get
| from | to | approaches | route |
| s | e | curb opposite | cd,cd,ab,ab |
###############
# Oneway Test #
@@ -111,10 +182,44 @@ Feature: Approach parameter
| bc | yes |
When I route I should get
| from | to | approaches | route |
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and End
Scenario: Test on oneway segment, Start End same approach, option unrestricted for Start and opposite for End
Given the profile "testbot"
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc |
Scenario: Test on oneway segment, Start End same approach, option opposite for Start and curb for End
Given the profile "testbot"
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | opposite curb | ab,bc |
Scenario: Test on oneway segment, Start End different approach, option unrestricted for Start and End
Given the profile "testbot"
And the node map
"""
@@ -132,7 +237,7 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: Test on oneway segment, Start End opposite approach, option unrestricted for Start and curb for End
Scenario: Test on oneway segment, Start End different approach, option unrestricted for Start and curb for End
Given the profile "testbot"
And the node map
"""
@@ -150,6 +255,42 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
Scenario: Test on oneway segment, Start End different approach, option unrestricted for Start and opposite for End
Given the profile "testbot"
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc |
Scenario: Test on oneway segment, Start End different approach, option curb for Start and opposite for End
Given the profile "testbot"
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes | oneway |
| ab | yes |
| bc | yes |
When I route I should get
| from | to | approaches | route |
| s | e | curb opposite | ab,bc |
##############
# UTurn Test #
##############
@@ -175,6 +316,27 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted curb | |
Scenario: UTurn test, router can find a route because uturn authorized to reach opposite side
Given the profile "testbot"
And the node map
"""
e s
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | bc | bc | c | no_u_turn |
When I route I should get
| from | to | approaches | route |
| s | e | curb opposite | bc,ab,ab |
Scenario: UTurn test, router can find a route because he can use the roundabout
Given the profile "testbot"
@@ -198,8 +360,9 @@ Feature: Approach parameter
| restriction | bc | bc | c | no_u_turn |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
| s | e | opposite curb | ab,bc,bc |
Scenario: Start End same approach, option unrestricted for Start and curb for End, left-hand driving
@@ -228,6 +391,32 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
Scenario: Start End same approach, option unrestricted for Start and opposite for End, left-hand driving
Given the profile file
"""
local functions = require('testbot')
local testbot_process_way = functions.process_way
functions.process_way = function(profile, way, result)
testbot_process_way(profile, way, result)
result.is_left_hand_driving = true
end
return functions
"""
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc,bc |
#######################
# Left-side countries #
@@ -260,9 +449,8 @@ Feature: Approach parameter
"""
And the node map
"""
s
s e
a------b------c
e
"""
And the ways
@@ -271,10 +459,50 @@ Feature: Approach parameter
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
Scenario: [Left-hand-side] Start End opposite approach, option unrestricted for Start and End
Scenario: [Left-hand-side] Start End same approach, option unrestricted for Start and opposite for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s e
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc,bc |
Scenario: [Left-hand-side] Start End same approach, option opposite for Start and curb for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
e s
a------b------c
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | opposite curb | bc,ab,ab |
Scenario: [Left-hand-side] Start End different approach, option unrestricted for Start and End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
@@ -295,15 +523,16 @@ Feature: Approach parameter
| from | to | approaches | route |
| s | e | unrestricted unrestricted | ab,bc |
Scenario: [Left-hand-side] Start End opposite approach, option unrestricted for Start and curb for End
Scenario: [Left-hand-side] Start End different approach, option unrestricted for Start and curb for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s e
s
a------b------c
e
"""
And the ways
@@ -312,5 +541,122 @@ Feature: Approach parameter
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc |
| from | to | approaches | route |
| s | e | unrestricted curb | ab,bc,bc |
Scenario: [Left-hand-side] Start End different approach, option unrestricted for Start and opposite for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | unrestricted opposite | ab,bc |
Scenario: [Left-hand-side] Start End different approach, option curb for Start and opposite for End
Given the profile file "car" initialized with
"""
profile.properties.left_hand_driving = true
"""
And the node map
"""
s
a------b------c
e
"""
And the ways
| nodes |
| ab |
| bc |
When I route I should get
| from | to | approaches | route |
| s | e | curb opposite | ab,bc |
Scenario: Routes with more than two waypoints - uturns allowed
Given the profile "testbot"
And the node map
"""
2 1
a------b------c-----------d
|
3 | 4
e------f------g-----------h
|
|
i
"""
And the ways
| nodes |
| ab |
| bc |
| cd |
| bf |
| ef |
| fg |
| gh |
| ei |
And the query options
| continue_straight | false |
When I route I should get
| waypoints | approaches | locations | # |
| 1,2,3,4 | curb curb curb curb | _,_,_,a,b,f,_,_,i,h,_ | 1,2,2,a,b,f,3,3,i,h,4 (Only u-turn at end of roads) |
| 1,2,3,4 | curb unrestricted unrestricted curb | _,_,_,b,f,_,_,h,_ | 1,2,2,b,f,3,3,h,4 (Can u-turn at 2 and 3) |
| 1,2,3,4 | opposite opposite opposite opposite | _,d,a,_,_,b,f,i,_,_,_ | 1,d,a,2,2,b,f,i,3,3,4 (Only u-turn at end of roads) |
| 1,2,3,4 | opposite unrestricted unrestricted opposite | _,d,_,_,b,f,_,_,_ | 1,d,2,2,b,f,3,3,4 (Can u-turn at 2 and 3) |
Scenario: Routes with more than two waypoints - uturns forbidden
Given the profile "testbot"
And the node map
"""
2 1
a------b------c-----------d
|
3 | 4
e------f------g-----------h
|
|
i
"""
And the ways
| nodes |
| ab |
| bc |
| cd |
| bf |
| ef |
| fg |
| gh |
| ei |
And the query options
| continue_straight | true |
When I route I should get
| waypoints | approaches | locations | # |
| 1,2,3,4 | curb curb curb curb | _,_,_,a,b,f,_,_,i,h,_ | 1,2,2,a,b,f,3,3,i,h,4 (Only u-turn at end of roads) |
| 1,2,3,4 | curb opposite opposite curb | _,a,_,_,b,f,i,_,_,h,_ | 1,a,2,2,b,f,i,3,3,h,4 (switches stops with u-turns) |
| 1,2,3,4 | opposite opposite opposite opposite | _,d,a,_,_,b,f,i,_,_,_ | 1,d,a,2,2,b,f,i,3,3,4 (Only u-turn at end of roads) |
| 1,2,3,4 | opposite curb curb opposite | _,d,_,_,a,b,f,_,_,i,_ | 1,d,2,2,a,b,f,3,3,i,4 (switches stops with u-turns) |
+101
View File
@@ -0,0 +1,101 @@
@routing @testbot @via
Feature: Force routing steps
Background:
Given the profile "testbot"
Scenario: Direct routes with waypoints on same edge
Given the node map
"""
1 2
a-------b
| |
d-------c
| |
e-------f
3 4
"""
And the ways
| nodes | oneway |
| ab | no |
| ad | no |
| bc | no |
| cf | no |
| dc | no |
| de | no |
| ef | yes |
When I route I should get
| waypoints | approaches | weight | route |
| 1,2 | | 20 | ab,ab |
| 1,2 | curb curb | 100 | ab,ad,dc,bc,ab |
| 2,1 | | 20 | ab,ab |
| 2,1 | opposite opposite | 100 | ab,bc,dc,ad,ab |
| 3,4 | | 20 | ef,ef |
| 4,3 | | 100 | ef,cf,dc,de,ef |
Scenario: Via routes with waypoints on same edge
Given the node map
"""
1 2
a-------b
| |
d-5-----c
| |
e-------f
3 4
"""
And the ways
| nodes | oneway |
| ab | no |
| ad | no |
| bc | no |
| cf | no |
| dc | no |
| de | no |
| ef | yes |
When I route I should get
| waypoints | approaches | weight | route |
| 5,1,2 | | 59.8 | dc,ad,ab,ab,ab |
| 5,1,2 | unrestricted curb curb | 180.2 | dc,bc,ab,ab,ab,ad,dc,bc,ab |
| 5,2,1 | | 80.2 | dc,bc,ab,ab,ab |
| 5,2,1 | unrestricted opposite opposite | 159.8 | dc,ad,ab,ab,ab,bc,dc,ad,ab |
| 5,3,4 | | 59.8 | dc,de,ef,ef,ef |
| 5,4,3 | | 159.8 | dc,de,ef,ef,ef,cf,dc,de,ef |
Scenario: [U-turns allowed] Via routes with waypoints on same edge
Given the node map
"""
1 2
a-------b
| |
d-5-----c
| |
e-------f
3 4
"""
And the ways
| nodes | oneway |
| ab | no |
| ad | no |
| bc | no |
| cf | no |
| dc | no |
| de | no |
| ef | yes |
And the query options
| continue_straight | false |
When I route I should get
| waypoints | approaches | weight | route |
| 5,1,2 | | 59.8 | dc,ad,ab,ab,ab |
| 5,1,2 | unrestricted curb curb | 180.2 | dc,bc,ab,ab,ab,ad,dc,bc,ab |
| 5,2,1 | | 79.8 | dc,ad,ab,ab,ab,ab |
| 5,2,1 | unrestricted opposite opposite | 159.8 | dc,ad,ab,ab,ab,bc,dc,ad,ab |
| 5,3,4 | | 59.8 | dc,de,ef,ef,ef |
| 5,4,3 | | 159.8 | dc,de,ef,ef,ef,cf,dc,de,ef |
@@ -61,10 +61,12 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
// Add all non-core edges to container
{
auto non_core_edges = toEdges<QueryEdge>(contractor_graph);
auto new_end =
std::remove_if(non_core_edges.begin(), non_core_edges.end(), [&](const auto &edge) {
return is_shared_core[edge.source] && is_shared_core[edge.target];
});
auto new_end = std::remove_if(non_core_edges.begin(),
non_core_edges.end(),
[&](const auto &edge) {
return is_shared_core[edge.source] &&
is_shared_core[edge.target];
});
non_core_edges.resize(new_end - non_core_edges.begin());
edge_container.Insert(std::move(non_core_edges));
@@ -75,8 +77,8 @@ inline auto contractExcludableGraph(ContractorGraph contractor_graph_,
}
// Extract core graph for further contraction
shared_core_graph = contractor_graph.Filter(
[&is_shared_core](const NodeID node) { return is_shared_core[node]; });
shared_core_graph = contractor_graph.Filter([&is_shared_core](const NodeID node)
{ return is_shared_core[node]; });
}
for (const auto &filter : filters)
@@ -89,37 +89,40 @@ struct ContractedEdgeContainer
// Remove all edges that are contained in the old set of edges and set the appropriate flag.
auto new_end =
std::remove_if(new_edges.begin(), new_edges.end(), [&](const QueryEdge &edge) {
// check if the new edge would be sorted before the currend old edge
// if so it is not contained yet in the set of old edges
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
{
return false;
}
std::remove_if(new_edges.begin(),
new_edges.end(),
[&](const QueryEdge &edge)
{
// check if the new edge would be sorted before the currend old edge
// if so it is not contained yet in the set of old edges
if (edge_iter == edge_end || mergeCompare(edge, *edge_iter))
{
return false;
}
// find the first old edge that is equal or greater then the new edge
while (edge_iter != edge_end && mergeCompare(*edge_iter, edge))
{
BOOST_ASSERT(flags_iter != flags.end());
edge_iter++;
flags_iter++;
}
// find the first old edge that is equal or greater then the new edge
while (edge_iter != edge_end && mergeCompare(*edge_iter, edge))
{
BOOST_ASSERT(flags_iter != flags.end());
edge_iter++;
flags_iter++;
}
// all new edges will be sorted after the old edges
if (edge_iter == edge_end)
{
return false;
}
// all new edges will be sorted after the old edges
if (edge_iter == edge_end)
{
return false;
}
BOOST_ASSERT(edge_iter != edge_end);
if (mergable(edge, *edge_iter))
{
*flags_iter = *flags_iter | flag;
return true;
}
BOOST_ASSERT(mergeCompare(edge, *edge_iter));
return false;
});
BOOST_ASSERT(edge_iter != edge_end);
if (mergable(edge, *edge_iter))
{
*flags_iter = *flags_iter | flag;
return true;
}
BOOST_ASSERT(mergeCompare(edge, *edge_iter));
return false;
});
// append new edges
edges.insert(edges.end(), new_edges.begin(), new_end);
@@ -132,10 +135,10 @@ struct ContractedEdgeContainer
// enforce sorting for next merge step
std::vector<unsigned> ordering(edges_size);
std::iota(ordering.begin(), ordering.end(), 0);
tbb::parallel_sort(
ordering.begin(), ordering.end(), [&](const auto lhs_idx, const auto rhs_idx) {
return mergeCompare(edges[lhs_idx], edges[rhs_idx]);
});
tbb::parallel_sort(ordering.begin(),
ordering.end(),
[&](const auto lhs_idx, const auto rhs_idx)
{ return mergeCompare(edges[lhs_idx], edges[rhs_idx]); });
auto permutation = util::orderingToPermutation(ordering);
util::inplacePermutation(edges.begin(), edges.end(), permutation);
-128
View File
@@ -1,128 +0,0 @@
#ifndef ITERATOR_BASED_CRC32_H
#define ITERATOR_BASED_CRC32_H
#if defined(__x86_64__) && !defined(__MINGW64__)
#include <cpuid.h>
#endif
#include <boost/crc.hpp> // for boost::crc_32_type
#include <iterator>
namespace osrm::contractor
{
class IteratorbasedCRC32
{
public:
bool UsingHardware() const { return use_hardware_implementation; }
IteratorbasedCRC32() : crc(0) { use_hardware_implementation = DetectHardwareSupport(); }
template <class Iterator> unsigned operator()(Iterator iter, const Iterator end)
{
unsigned crc = 0;
while (iter != end)
{
using value_type = typename std::iterator_traits<Iterator>::value_type;
const char *data = reinterpret_cast<const char *>(&(*iter));
if (use_hardware_implementation)
{
crc = ComputeInHardware(data, sizeof(value_type));
}
else
{
crc = ComputeInSoftware(data, sizeof(value_type));
}
++iter;
}
return crc;
}
private:
bool DetectHardwareSupport() const
{
static const int sse42_bit = 0x00100000;
const unsigned ecx = cpuid();
const bool sse42_found = (ecx & sse42_bit) != 0;
return sse42_found;
}
unsigned ComputeInSoftware(const char *str, unsigned len)
{
crc_processor.process_bytes(str, len);
return crc_processor.checksum();
}
// adapted from http://byteworm.com/2010/10/13/crc32/
unsigned ComputeInHardware(const char *str, unsigned len)
{
#if defined(__x86_64__)
unsigned q = len / sizeof(unsigned);
unsigned r = len % sizeof(unsigned);
unsigned *p = (unsigned *)str;
// crc=0;
while (q--)
{
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
: "=S"(crc)
: "0"(crc), "c"(*p));
++p;
}
str = reinterpret_cast<char *>(p);
while (r--)
{
__asm__ __volatile__(".byte 0xf2, 0xf, 0x38, 0xf1, 0xf1;"
: "=S"(crc)
: "0"(crc), "c"(*str));
++str;
}
#else
(void)str;
(void)len;
#endif
return crc;
}
inline unsigned cpuid() const
{
unsigned eax = 0, ebx = 0, ecx = 0, edx = 0;
// on X64 this calls hardware cpuid(.) instr. otherwise a dummy impl.
__get_cpuid(1, &eax, &ebx, &ecx, &edx);
return ecx;
}
#if defined(__MINGW64__) || defined(_MSC_VER) || !defined(__x86_64__)
inline void __get_cpuid(int /*param*/,
unsigned * /*eax*/,
unsigned * /*ebx*/,
unsigned *ecx,
unsigned * /*edx*/) const
{
*ecx = 0;
}
#endif
boost::crc_optimal<32, 0x1EDC6F41, 0x0, 0x0, true, true> crc_processor;
unsigned crc;
bool use_hardware_implementation;
};
struct RangebasedCRC32
{
template <typename Iteratable> unsigned operator()(const Iteratable &iterable)
{
return crc32(std::begin(iterable), std::end(iterable));
}
bool UsingHardware() const { return crc32.UsingHardware(); }
private:
IteratorbasedCRC32 crc32;
};
} // namespace osrm::contractor
#endif /* ITERATOR_BASED_CRC32_H */
+2 -1
View File
@@ -122,7 +122,8 @@ class CellCustomizer
for (std::size_t level = 1; level < partition.GetNumberOfLevels(); ++level)
{
tbb::parallel_for(tbb::blocked_range<std::size_t>(0, partition.GetNumberOfCells(level)),
[&](const tbb::blocked_range<std::size_t> &range) {
[&](const tbb::blocked_range<std::size_t> &range)
{
auto &heap = heaps.local();
for (auto id = range.begin(), end = range.end(); id != end; ++id)
{
+6 -7
View File
@@ -40,10 +40,10 @@ class BaseAPI
util::json::Array waypoints;
waypoints.values.resize(parameters.coordinates.size());
boost::range::transform(
waypoint_candidates,
waypoints.values.begin(),
[this](const PhantomNodeCandidates &candidates) { return MakeWaypoint(candidates); });
boost::range::transform(waypoint_candidates,
waypoints.values.begin(),
[this](const PhantomNodeCandidates &candidates)
{ return MakeWaypoint(candidates); });
return waypoints;
}
@@ -104,9 +104,8 @@ class BaseAPI
std::transform(waypoint_candidates.begin(),
waypoint_candidates.end(),
waypoints.begin(),
[this, builder](const PhantomNodeCandidates &candidates) {
return MakeWaypoint(builder, candidates)->Finish();
});
[this, builder](const PhantomNodeCandidates &candidates)
{ return MakeWaypoint(builder, candidates)->Finish(); });
return builder->CreateVector(waypoints);
}
+4 -2
View File
@@ -52,7 +52,8 @@ namespace osrm::engine::api
* optional per coordinate
* - bearings: limits the search for segments in the road network to given bearing(s) in degree
* towards true north in clockwise direction, optional per coordinate
* - approaches: force the phantom node to start towards the node with the road country side.
* - approaches: force the phantom node to start towards the node with the road country side or
* its opposite
*
* \see OSRM, Coordinate, Hint, Bearing, RouteParameters, TableParameters,
* NearestParameters, TripParameters, MatchParameters and TileParameters
@@ -111,7 +112,8 @@ struct BaseParameters
(approaches.empty() || approaches.size() == coordinates.size()) &&
std::all_of(bearings.begin(),
bearings.end(),
[](const boost::optional<Bearing> &bearing_and_range) {
[](const boost::optional<Bearing> &bearing_and_range)
{
if (bearing_and_range)
{
return bearing_and_range->IsValid();
+2 -3
View File
@@ -2,7 +2,7 @@
#define ENGINE_API_BASE_RESULT_HPP
#include <flatbuffers/flatbuffers.h>
#include <mapbox/variant.hpp>
#include <variant>
#include <string>
@@ -10,8 +10,7 @@
namespace osrm::engine::api
{
using ResultT =
mapbox::util::variant<util::json::Object, std::string, flatbuffers::FlatBufferBuilder>;
using ResultT = std::variant<util::json::Object, std::string, flatbuffers::FlatBufferBuilder>;
} // namespace osrm::engine::api
#endif
+2 -2
View File
@@ -41,7 +41,7 @@ inline bool hasValidLanes(const guidance::IntermediateIntersection &intersection
return intersection.lanes.lanes_in_turn > 0;
}
util::json::Array coordinateToLonLat(const util::Coordinate &coordinate);
util::json::Value coordinateToLonLat(const util::Coordinate &coordinate);
/**
* Ensures that a bearing value is a whole number, and clamped to the range 0-359
@@ -79,7 +79,7 @@ util::json::Object makeGeoJSONGeometry(ForwardIter begin, ForwardIter end)
coordinates.values.push_back(location);
coordinates.values.push_back(location);
}
geojson.values["coordinates"] = std::move(coordinates);
geojson.values["coordinates"] = util::json::Value{std::move(coordinates)};
return geojson;
}
+7 -6
View File
@@ -30,14 +30,14 @@ class MatchAPI final : public RouteAPI
osrm::engine::api::ResultT &response) const
{
BOOST_ASSERT(sub_matchings.size() == sub_routes.size());
if (response.is<flatbuffers::FlatBufferBuilder>())
if (std::holds_alternative<flatbuffers::FlatBufferBuilder>(response))
{
auto &fb_result = response.get<flatbuffers::FlatBufferBuilder>();
auto &fb_result = std::get<flatbuffers::FlatBufferBuilder>(response);
MakeResponse(sub_matchings, sub_routes, fb_result);
}
else
{
auto &json_result = response.get<util::json::Object>();
auto &json_result = std::get<util::json::Object>(response);
MakeResponse(sub_matchings, sub_routes, json_result);
}
}
@@ -52,9 +52,10 @@ class MatchAPI final : public RouteAPI
data_version_string = fb_result.CreateString(data_timestamp);
}
auto response = MakeFBResponse(sub_routes, fb_result, [this, &fb_result, &sub_matchings]() {
return MakeTracepoints(fb_result, sub_matchings);
});
auto response = MakeFBResponse(sub_routes,
fb_result,
[this, &fb_result, &sub_matchings]()
{ return MakeTracepoints(fb_result, sub_matchings); });
if (!data_timestamp.empty())
{
+2 -2
View File
@@ -67,7 +67,7 @@ struct MatchParameters : public RouteParameters
MatchParameters(const std::vector<unsigned> &timestamps_,
GapsType gaps_,
bool tidy_,
Args &&... args_)
Args &&...args_)
: MatchParameters(timestamps_, gaps_, tidy_, {}, std::forward<Args>(args_)...)
{
}
@@ -77,7 +77,7 @@ struct MatchParameters : public RouteParameters
GapsType gaps_,
bool tidy_,
const std::vector<std::size_t> &waypoints_,
Args &&... args_)
Args &&...args_)
: RouteParameters{std::forward<Args>(args_)..., waypoints_}, timestamps{std::move(
timestamps_)},
gaps(gaps_), tidy(tidy_)
+17 -16
View File
@@ -29,14 +29,14 @@ class NearestAPI final : public BaseAPI
BOOST_ASSERT(phantom_nodes.size() == 1);
BOOST_ASSERT(parameters.coordinates.size() == 1);
if (response.is<flatbuffers::FlatBufferBuilder>())
if (std::holds_alternative<flatbuffers::FlatBufferBuilder>(response))
{
auto &fb_result = response.get<flatbuffers::FlatBufferBuilder>();
auto &fb_result = std::get<flatbuffers::FlatBufferBuilder>(response);
MakeResponse(phantom_nodes, fb_result);
}
else
{
auto &json_result = response.get<util::json::Object>();
auto &json_result = std::get<util::json::Object>(response);
MakeResponse(phantom_nodes, json_result);
}
}
@@ -57,20 +57,20 @@ class NearestAPI final : public BaseAPI
{
std::vector<flatbuffers::Offset<fbresult::Waypoint>> waypoints;
waypoints.resize(phantom_nodes.front().size());
std::transform(
phantom_nodes.front().begin(),
phantom_nodes.front().end(),
waypoints.begin(),
[this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance) {
auto &phantom_node = phantom_with_distance.phantom_node;
std::transform(phantom_nodes.front().begin(),
phantom_nodes.front().end(),
waypoints.begin(),
[this, &fb_result](const PhantomNodeWithDistance &phantom_with_distance)
{
auto &phantom_node = phantom_with_distance.phantom_node;
auto node_values = MakeNodes(phantom_node);
fbresult::Uint64Pair nodes{node_values.first, node_values.second};
auto node_values = MakeNodes(phantom_node);
fbresult::Uint64Pair nodes{node_values.first, node_values.second};
auto waypoint = MakeWaypoint(&fb_result, {phantom_node});
waypoint->add_nodes(&nodes);
return waypoint->Finish();
});
auto waypoint = MakeWaypoint(&fb_result, {phantom_node});
waypoint->add_nodes(&nodes);
return waypoint->Finish();
});
waypoints_vector = fb_result.CreateVector(waypoints);
}
@@ -94,7 +94,8 @@ class NearestAPI final : public BaseAPI
std::transform(phantom_nodes.front().begin(),
phantom_nodes.front().end(),
waypoints.values.begin(),
[this](const PhantomNodeWithDistance &phantom_with_distance) {
[this](const PhantomNodeWithDistance &phantom_with_distance)
{
auto &phantom_node = phantom_with_distance.phantom_node;
auto waypoint = MakeWaypoint({phantom_node});
+84 -75
View File
@@ -50,14 +50,14 @@ class RouteAPI : public BaseAPI
{
BOOST_ASSERT(!raw_routes.routes.empty());
if (response.is<flatbuffers::FlatBufferBuilder>())
if (std::holds_alternative<flatbuffers::FlatBufferBuilder>(response))
{
auto &fb_result = response.get<flatbuffers::FlatBufferBuilder>();
auto &fb_result = std::get<flatbuffers::FlatBufferBuilder>(response);
MakeResponse(raw_routes, waypoint_candidates, fb_result);
}
else
{
auto &json_result = response.get<util::json::Object>();
auto &json_result = std::get<util::json::Object>(response);
MakeResponse(raw_routes, waypoint_candidates, json_result);
}
}
@@ -77,9 +77,10 @@ class RouteAPI : public BaseAPI
}
auto response =
MakeFBResponse(raw_routes, fb_result, [this, &waypoint_candidates, &fb_result]() {
return BaseAPI::MakeWaypoints(&fb_result, waypoint_candidates);
});
MakeFBResponse(raw_routes,
fb_result,
[this, &waypoint_candidates, &fb_result]()
{ return BaseAPI::MakeWaypoints(&fb_result, waypoint_candidates); });
if (!data_timestamp.empty())
{
@@ -157,8 +158,8 @@ class RouteAPI : public BaseAPI
}
template <typename ForwardIter>
mapbox::util::variant<flatbuffers::Offset<flatbuffers::String>,
flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>>>
std::variant<flatbuffers::Offset<flatbuffers::String>,
flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>>>
MakeGeometry(flatbuffers::FlatBufferBuilder &builder, ForwardIter begin, ForwardIter end) const
{
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
@@ -171,10 +172,15 @@ class RouteAPI : public BaseAPI
}
std::vector<fbresult::Position> coordinates;
coordinates.resize(std::distance(begin, end));
std::transform(begin, end, coordinates.begin(), [](const Coordinate &c) {
return fbresult::Position{static_cast<float>(util::toFloating(c.lon).__value),
static_cast<float>(util::toFloating(c.lat).__value)};
});
std::transform(begin,
end,
coordinates.begin(),
[](const Coordinate &c)
{
return fbresult::Position{
static_cast<float>(util::toFloating(c.lon).__value),
static_cast<float>(util::toFloating(c.lat).__value)};
});
return builder.CreateVectorOfStructs(coordinates);
}
@@ -354,9 +360,8 @@ class RouteAPI : public BaseAPI
std::transform(leg.steps.begin(),
leg.steps.end(),
legSteps.begin(),
[this, &fb_result, &leg_geometry](auto &step) {
return this->MakeFBStep(fb_result, leg_geometry, step);
});
[this, &fb_result, &leg_geometry](auto &step)
{ return this->MakeFBStep(fb_result, leg_geometry, step); });
}
auto steps_vector = fb_result.CreateVector(legSteps);
@@ -403,8 +408,8 @@ class RouteAPI : public BaseAPI
// Fill geometry
auto overview = MakeOverview(leg_geometries);
mapbox::util::variant<flatbuffers::Offset<flatbuffers::String>,
flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>>>
std::variant<flatbuffers::Offset<flatbuffers::String>,
flatbuffers::Offset<flatbuffers::Vector<const fbresult::Position *>>>
geometry;
if (overview)
{
@@ -421,8 +426,7 @@ class RouteAPI : public BaseAPI
routeObject.add_legs(legs_vector);
if (overview)
{
mapbox::util::apply_visitor(GeometryVisitor<fbresult::RouteObjectBuilder>(routeObject),
geometry);
std::visit(GeometryVisitor<fbresult::RouteObjectBuilder>(routeObject), geometry);
}
return routeObject.Finish();
@@ -438,58 +442,58 @@ class RouteAPI : public BaseAPI
if (requested_annotations & RouteParameters::AnnotationsType::Speed)
{
double prev_speed = 0;
speed =
GetAnnotations<float>(fb_result,
leg_geometry,
[&prev_speed](const guidance::LegGeometry::Annotation &anno) {
if (anno.duration < std::numeric_limits<float>::min())
{
return prev_speed;
}
else
{
auto speed =
round(anno.distance / anno.duration * 10.) / 10.;
prev_speed = speed;
return util::json::clamp_float(speed);
}
});
speed = GetAnnotations<float>(
fb_result,
leg_geometry,
[&prev_speed](const guidance::LegGeometry::Annotation &anno)
{
if (anno.duration < std::numeric_limits<float>::min())
{
return prev_speed;
}
else
{
auto speed = std::round(anno.distance / anno.duration * 10.) / 10.;
prev_speed = speed;
return util::json::clamp_float(speed);
}
});
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> duration;
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
{
duration = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.duration;
});
duration = GetAnnotations<uint32_t>(fb_result,
leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.duration; });
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> distance;
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
{
distance = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.distance;
});
distance = GetAnnotations<uint32_t>(fb_result,
leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.distance; });
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> weight;
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
{
weight = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.weight;
});
weight = GetAnnotations<uint32_t>(fb_result,
leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.weight; });
}
flatbuffers::Offset<flatbuffers::Vector<uint32_t>> datasources;
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
datasources = GetAnnotations<uint32_t>(
fb_result, leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.datasource;
});
datasources = GetAnnotations<uint32_t>(fb_result,
leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.datasource; });
}
std::vector<uint32_t> nodes;
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
@@ -639,7 +643,7 @@ class RouteAPI : public BaseAPI
stepBuilder.add_rotary_pronunciation(rotary_pronunciation_string);
stepBuilder.add_intersections(intersections_vector);
stepBuilder.add_maneuver(maneuver_buffer);
mapbox::util::apply_visitor(GeometryVisitor<fbresult::StepBuilder>(stepBuilder), geometry);
std::visit(GeometryVisitor<fbresult::StepBuilder>(stepBuilder), geometry);
return stepBuilder.Finish();
};
@@ -653,7 +657,8 @@ class RouteAPI : public BaseAPI
step.intersections.begin(),
step.intersections.end(),
intersections.begin(),
[&fb_result, this](const guidance::IntermediateIntersection &intersection) {
[&fb_result, this](const guidance::IntermediateIntersection &intersection)
{
std::vector<flatbuffers::Offset<fbresult::Lane>> lanes;
if (json::detail::hasValidLanes(intersection))
{
@@ -681,11 +686,11 @@ class RouteAPI : public BaseAPI
auto bearings_vector = fb_result.CreateVector(intersection.bearings);
std::vector<flatbuffers::Offset<flatbuffers::String>> classes;
classes.resize(intersection.classes.size());
std::transform(
intersection.classes.begin(),
intersection.classes.end(),
classes.begin(),
[&fb_result](const std::string &cls) { return fb_result.CreateString(cls); });
std::transform(intersection.classes.begin(),
intersection.classes.end(),
classes.begin(),
[&fb_result](const std::string &cls)
{ return fb_result.CreateString(cls); });
auto classes_vector = fb_result.CreateVector(classes);
auto entry_vector = fb_result.CreateVector(intersection.entry);
@@ -720,9 +725,10 @@ class RouteAPI : public BaseAPI
std::vector<util::json::Value> step_geometries;
const auto total_step_count =
std::accumulate(legs.begin(), legs.end(), 0, [](const auto &v, const auto &leg) {
return v + leg.steps.size();
});
std::accumulate(legs.begin(),
legs.end(),
0,
[](const auto &v, const auto &leg) { return v + leg.steps.size(); });
step_geometries.reserve(total_step_count);
for (const auto idx : util::irange<std::size_t>(0UL, legs.size()))
@@ -733,7 +739,8 @@ class RouteAPI : public BaseAPI
legs[idx].steps.begin(),
legs[idx].steps.end(),
std::back_inserter(step_geometries),
[this, &leg_geometry](const guidance::RouteStep &step) {
[this, &leg_geometry](const guidance::RouteStep &step)
{
if (parameters.geometries == RouteParameters::GeometriesType::Polyline)
{
return static_cast<util::json::Value>(json::makePolyline<100000>(
@@ -778,7 +785,9 @@ class RouteAPI : public BaseAPI
{
double prev_speed = 0;
annotation.values["speed"] = GetAnnotations(
leg_geometry, [&prev_speed](const guidance::LegGeometry::Annotation &anno) {
leg_geometry,
[&prev_speed](const guidance::LegGeometry::Annotation &anno)
{
if (anno.duration < std::numeric_limits<double>::min())
{
return prev_speed;
@@ -794,17 +803,17 @@ class RouteAPI : public BaseAPI
if (requested_annotations & RouteParameters::AnnotationsType::Duration)
{
annotation.values["duration"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.duration;
});
annotation.values["duration"] =
GetAnnotations(leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.duration; });
}
if (requested_annotations & RouteParameters::AnnotationsType::Distance)
{
annotation.values["distance"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.distance;
});
annotation.values["distance"] =
GetAnnotations(leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.distance; });
}
if (requested_annotations & RouteParameters::AnnotationsType::Weight)
{
@@ -814,10 +823,10 @@ class RouteAPI : public BaseAPI
}
if (requested_annotations & RouteParameters::AnnotationsType::Datasources)
{
annotation.values["datasources"] = GetAnnotations(
leg_geometry, [](const guidance::LegGeometry::Annotation &anno) {
return anno.datasource;
});
annotation.values["datasources"] =
GetAnnotations(leg_geometry,
[](const guidance::LegGeometry::Annotation &anno)
{ return anno.datasource; });
}
if (requested_annotations & RouteParameters::AnnotationsType::Nodes)
{
+8 -8
View File
@@ -83,7 +83,7 @@ struct RouteParameters : public BaseParameters
const GeometriesType geometries_,
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
Args &&... args_)
Args &&...args_)
// Once we perfectly-forward `args` (see #2990) this constructor can delegate to the one
// below.
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
@@ -101,7 +101,7 @@ struct RouteParameters : public BaseParameters
const GeometriesType geometries_,
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
Args &&... args_)
Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{annotations_},
annotations_type{annotations_ ? AnnotationsType::All : AnnotationsType::None},
@@ -119,7 +119,7 @@ struct RouteParameters : public BaseParameters
const GeometriesType geometries_,
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
Args &&... args_)
Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u},
annotations{annotations_ != AnnotationsType::None}, annotations_type{annotations_},
@@ -137,7 +137,7 @@ struct RouteParameters : public BaseParameters
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
std::vector<std::size_t> waypoints_,
const Args &&... args_)
const Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{annotations_},
annotations_type{annotations_ ? AnnotationsType::All : AnnotationsType::None},
@@ -155,7 +155,7 @@ struct RouteParameters : public BaseParameters
const OverviewType overview_,
const boost::optional<bool> continue_straight_,
std::vector<std::size_t> waypoints_,
Args &&... args_)
Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, steps{steps_}, alternatives{alternatives_},
number_of_alternatives{alternatives_ ? 1u : 0u}, annotations{annotations_ !=
AnnotationsType::None},
@@ -180,9 +180,9 @@ struct RouteParameters : public BaseParameters
const auto coordinates_ok = coordinates.size() >= 2;
const auto base_params_ok = BaseParameters::IsValid();
const auto valid_waypoints =
std::all_of(waypoints.begin(), waypoints.end(), [this](const auto &w) {
return w < coordinates.size();
});
std::all_of(waypoints.begin(),
waypoints.end(),
[this](const auto &w) { return w < coordinates.size(); });
return coordinates_ok && base_params_ok && valid_waypoints;
}
};
+56 -40
View File
@@ -50,14 +50,14 @@ class TableAPI final : public BaseAPI
const std::vector<TableCellRef> &fallback_speed_cells,
osrm::engine::api::ResultT &response) const
{
if (response.is<flatbuffers::FlatBufferBuilder>())
if (std::holds_alternative<flatbuffers::FlatBufferBuilder>(response))
{
auto &fb_result = response.get<flatbuffers::FlatBufferBuilder>();
auto &fb_result = std::get<flatbuffers::FlatBufferBuilder>(response);
MakeResponse(tables, candidates, fallback_speed_cells, fb_result);
}
else
{
auto &json_result = response.get<util::json::Object>();
auto &json_result = std::get<util::json::Object>(response);
MakeResponse(tables, candidates, fallback_speed_cells, json_result);
}
}
@@ -245,9 +245,8 @@ class TableAPI final : public BaseAPI
boost::range::transform(candidates,
std::back_inserter(waypoints),
[this, &builder](const PhantomNodeCandidates &candidates) {
return BaseAPI::MakeWaypoint(&builder, candidates)->Finish();
});
[this, &builder](const PhantomNodeCandidates &candidates)
{ return BaseAPI::MakeWaypoint(&builder, candidates)->Finish(); });
return builder.CreateVector(waypoints);
}
@@ -261,7 +260,8 @@ class TableAPI final : public BaseAPI
boost::range::transform(
indices,
std::back_inserter(waypoints),
[this, &builder, &candidates](const std::size_t idx) {
[this, &builder, &candidates](const std::size_t idx)
{
BOOST_ASSERT(idx < candidates.size());
return BaseAPI::MakeWaypoint(&builder, candidates[idx])->Finish();
});
@@ -274,14 +274,17 @@ class TableAPI final : public BaseAPI
{
std::vector<float> distance_table;
distance_table.resize(values.size());
std::transform(
values.begin(), values.end(), distance_table.begin(), [](const EdgeDuration duration) {
if (duration == MAXIMAL_EDGE_DURATION)
{
return 0.;
}
return from_alias<double>(duration) / 10.;
});
std::transform(values.begin(),
values.end(),
distance_table.begin(),
[](const EdgeDuration duration)
{
if (duration == MAXIMAL_EDGE_DURATION)
{
return 0.;
}
return from_alias<double>(duration) / 10.;
});
return builder.CreateVector(distance_table);
}
@@ -291,14 +294,17 @@ class TableAPI final : public BaseAPI
{
std::vector<float> duration_table;
duration_table.resize(values.size());
std::transform(
values.begin(), values.end(), duration_table.begin(), [](const EdgeDistance distance) {
if (distance == INVALID_EDGE_DISTANCE)
{
return 0.;
}
return std::round(from_alias<double>(distance) * 10) / 10.;
});
std::transform(values.begin(),
values.end(),
duration_table.begin(),
[](const EdgeDistance distance)
{
if (distance == INVALID_EDGE_DISTANCE)
{
return 0.;
}
return std::round(from_alias<double>(distance) * 10) / 10.;
});
return builder.CreateVector(duration_table);
}
@@ -308,11 +314,13 @@ class TableAPI final : public BaseAPI
{
std::vector<uint32_t> fb_table;
fb_table.reserve(fallback_speed_cells.size());
std::for_each(
fallback_speed_cells.begin(), fallback_speed_cells.end(), [&](const auto &cell) {
fb_table.push_back(cell.row);
fb_table.push_back(cell.column);
});
std::for_each(fallback_speed_cells.begin(),
fallback_speed_cells.end(),
[&](const auto &cell)
{
fb_table.push_back(cell.row);
fb_table.push_back(cell.column);
});
return builder.CreateVector(fb_table);
}
@@ -325,9 +333,8 @@ class TableAPI final : public BaseAPI
boost::range::transform(candidates,
std::back_inserter(json_waypoints.values),
[this](const PhantomNodeCandidates &candidates) {
return BaseAPI::MakeWaypoint(candidates);
});
[this](const PhantomNodeCandidates &candidates)
{ return BaseAPI::MakeWaypoint(candidates); });
return json_waypoints;
}
@@ -338,7 +345,8 @@ class TableAPI final : public BaseAPI
json_waypoints.values.reserve(indices.size());
boost::range::transform(indices,
std::back_inserter(json_waypoints.values),
[this, &candidates](const std::size_t idx) {
[this, &candidates](const std::size_t idx)
{
BOOST_ASSERT(idx < candidates.size());
return BaseAPI::MakeWaypoint(candidates[idx]);
});
@@ -359,7 +367,8 @@ class TableAPI final : public BaseAPI
std::transform(row_begin_iterator,
row_end_iterator,
json_row.values.begin(),
[](const EdgeDuration duration) {
[](const EdgeDuration duration)
{
if (duration == MAXIMAL_EDGE_DURATION)
{
return util::json::Value(util::json::Null());
@@ -368,7 +377,8 @@ class TableAPI final : public BaseAPI
return util::json::Value(
util::json::Number(from_alias<double>(duration) / 10.));
});
json_table.values.push_back(std::move(json_row));
json_table.values.push_back(util::json::Value{json_row});
}
return json_table;
}
@@ -387,7 +397,8 @@ class TableAPI final : public BaseAPI
std::transform(row_begin_iterator,
row_end_iterator,
json_row.values.begin(),
[](const EdgeDistance distance) {
[](const EdgeDistance distance)
{
if (distance == INVALID_EDGE_DISTANCE)
{
return util::json::Value(util::json::Null());
@@ -396,7 +407,7 @@ class TableAPI final : public BaseAPI
return util::json::Value(util::json::Number(
std::round(from_alias<double>(distance) * 10) / 10.));
});
json_table.values.push_back(std::move(json_row));
json_table.values.push_back(util::json::Value{json_row});
}
return json_table;
}
@@ -406,11 +417,16 @@ class TableAPI final : public BaseAPI
{
util::json::Array json_table;
std::for_each(
fallback_speed_cells.begin(), fallback_speed_cells.end(), [&](const auto &cell) {
fallback_speed_cells.begin(),
fallback_speed_cells.end(),
[&](const auto &cell)
{
util::json::Array row;
row.values.push_back(util::json::Number(cell.row));
row.values.push_back(util::json::Number(cell.column));
json_table.values.push_back(std::move(row));
util::json::Value jCellRow{util::json::Number(static_cast<double>(cell.row))};
util::json::Value jCellColumn{util::json::Number(static_cast<double>(cell.column))};
row.values.push_back(jCellRow);
row.values.push_back(jCellColumn);
json_table.values.push_back(util::json::Value{row});
});
return json_table;
}
+3 -3
View File
@@ -81,7 +81,7 @@ struct TableParameters : public BaseParameters
template <typename... Args>
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
Args &&... args_)
Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}
{
@@ -91,7 +91,7 @@ struct TableParameters : public BaseParameters
TableParameters(std::vector<std::size_t> sources_,
std::vector<std::size_t> destinations_,
const AnnotationsType annotations_,
Args &&... args_)
Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, annotations{annotations_}
{
@@ -104,7 +104,7 @@ struct TableParameters : public BaseParameters
double fallback_speed_,
FallbackCoordinateType fallback_coordinate_type_,
double scale_factor_,
Args &&... args_)
Args &&...args_)
: BaseParameters{std::forward<Args>(args_)...}, sources{std::move(sources_)},
destinations{std::move(destinations_)}, fallback_speed{fallback_speed_},
fallback_coordinate_type{fallback_coordinate_type_}, annotations{annotations_},
+7 -7
View File
@@ -27,14 +27,14 @@ class TripAPI final : public RouteAPI
{
BOOST_ASSERT(sub_trips.size() == sub_routes.size());
if (response.is<flatbuffers::FlatBufferBuilder>())
if (std::holds_alternative<flatbuffers::FlatBufferBuilder>(response))
{
auto &fb_result = response.get<flatbuffers::FlatBufferBuilder>();
auto &fb_result = std::get<flatbuffers::FlatBufferBuilder>(response);
MakeResponse(sub_trips, sub_routes, candidates, fb_result);
}
else
{
auto &json_result = response.get<util::json::Object>();
auto &json_result = std::get<util::json::Object>(response);
MakeResponse(sub_trips, sub_routes, candidates, json_result);
}
}
@@ -50,10 +50,10 @@ class TripAPI final : public RouteAPI
data_version_string = fb_result.CreateString(data_timestamp);
}
auto response =
MakeFBResponse(sub_routes, fb_result, [this, &fb_result, &sub_trips, &candidates]() {
return MakeWaypoints(fb_result, sub_trips, candidates);
});
auto response = MakeFBResponse(sub_routes,
fb_result,
[this, &fb_result, &sub_trips, &candidates]()
{ return MakeWaypoints(fb_result, sub_trips, candidates); });
if (!data_timestamp.empty())
{
+1 -1
View File
@@ -60,7 +60,7 @@ struct TripParameters : public RouteParameters
TripParameters(SourceType source_,
DestinationType destination_,
bool roundtrip_,
Args &&... args_)
Args &&...args_)
: RouteParameters{std::forward<Args>(args_)...}, source{source_},
destination{destination_}, roundtrip{roundtrip_}
{
+2 -1
View File
@@ -36,7 +36,8 @@ namespace osrm::engine
enum class Approach : std::uint8_t
{
CURB = 0,
UNRESTRICTED = 1
UNRESTRICTED = 1,
OPPOSITE = 2
};
} // namespace osrm::engine
@@ -55,7 +55,7 @@ template <> class AlgorithmDataFacade<CH>
virtual EdgeID FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to,
const std::function<bool(EdgeData)> filter) const = 0;
const std::function<bool(const EdgeData &)> &filter) const = 0;
};
template <> class AlgorithmDataFacade<MLD>
@@ -130,9 +130,10 @@ class ContiguousInternalMemoryAlgorithmDataFacade<CH> : 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<bool(EdgeData)> filter) const override final
EdgeID
FindSmallestEdge(const NodeID edge_based_node_from,
const NodeID edge_based_node_to,
const std::function<bool(const EdgeData &)> &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<PhantomNodeWithDistance>
@@ -440,9 +441,11 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
{
auto indexes = extractor::getClassIndexes(class_data);
std::vector<std::string> classes(indexes.size());
std::transform(indexes.begin(), indexes.end(), classes.begin(), [this](const auto index) {
return m_profile_properties->GetClassName(index);
});
std::transform(indexes.begin(),
indexes.end(),
classes.begin(),
[this](const auto index)
{ return m_profile_properties->GetClassName(index); });
return classes;
}
@@ -600,15 +603,19 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade
auto found_range = std::equal_range(
m_maneuver_overrides.begin(), m_maneuver_overrides.end(), edge_based_node_id, Comp{});
std::for_each(found_range.first, found_range.second, [&](const auto &override) {
std::vector<NodeID> sequence(
m_maneuver_override_node_sequences.begin() + override.node_sequence_offset_begin,
m_maneuver_override_node_sequences.begin() + override.node_sequence_offset_end);
results.push_back(extractor::ManeuverOverride{std::move(sequence),
override.instruction_node,
override.override_type,
override.direction});
});
std::for_each(found_range.first,
found_range.second,
[&](const auto &override)
{
std::vector<NodeID> sequence(m_maneuver_override_node_sequences.begin() +
override.node_sequence_offset_begin,
m_maneuver_override_node_sequences.begin() +
override.node_sequence_offset_end);
results.push_back(extractor::ManeuverOverride{std::move(sequence),
override.instruction_node,
override.override_type,
override.direction});
});
return results;
}
};
+1 -6
View File
@@ -54,14 +54,10 @@ namespace osrm::engine
*
* In addition, shared memory can be used for datasets loaded with osrm-datastore.
*
* You can chose between three algorithms:
* You can chose between two algorithms:
* - Algorithm::CH
* Contraction Hierarchies, extremely fast queries but slow pre-processing. The default right
* now.
* - Algorithm::CoreCH
* Deprecated, to be removed in v6.0
* Contraction Hierachies with partial contraction for faster pre-processing but slower
* queries.
* - Algorithm::MLD
* Multi Level Dijkstra, moderately fast in both pre-processing and query.
*
@@ -74,7 +70,6 @@ struct EngineConfig final
enum class Algorithm
{
CH,
CoreCH, // Deprecated, will be removed in v6.0
MLD
};
+75 -31
View File
@@ -12,6 +12,8 @@
#include "osrm/coordinate.hpp"
#include <boost/optional.hpp>
#include <algorithm>
#include <cmath>
#include <iterator>
@@ -47,12 +49,42 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return rtree.SearchInBox(bbox);
}
std::vector<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const Approach approach,
const double max_distance,
const boost::optional<Bearing> bearing_with_range,
const boost::optional<bool> 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<PhantomNodeWithDistance>
NearestPhantomNodes(const util::Coordinate input_coordinate,
const Approach approach,
const boost::optional<size_t> max_results,
const size_t max_results,
const boost::optional<double> max_distance,
const boost::optional<Bearing> bearing_with_range,
const boost::optional<bool> use_all_edges) const
@@ -60,7 +92,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
auto results = rtree.Nearest(
input_coordinate,
[this, approach, &input_coordinate, &bearing_with_range, &use_all_edges](
const CandidateSegment &segment) {
const CandidateSegment &segment)
{
auto valid = CheckSegmentExclude(segment) &&
CheckApproach(input_coordinate, segment, approach) &&
(use_all_edges ? HasValidEdge(segment, *use_all_edges)
@@ -69,9 +102,10 @@ template <typename RTreeT, typename DataFacadeT> 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) {
return (max_results && num_results >= *max_results) ||
[this, &max_distance, max_results, input_coordinate](const std::size_t num_results,
const CandidateSegment &segment)
{
return (num_results >= max_results) ||
(max_distance && max_distance != -1.0 &&
CheckSegmentDistance(input_coordinate, segment, *max_distance));
});
@@ -107,7 +141,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
&big_component_coord,
&big_component_distance,
&use_all_edges,
&bearing_with_range](const CandidateSegment &segment) {
&bearing_with_range](const CandidateSegment &segment)
{
auto is_big_component = !IsTinyComponent(segment);
auto not_nearest =
has_nearest && segment.fixed_projected_coordinate != nearest_coord;
@@ -159,7 +194,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
return use_candidate;
},
[this, &has_big_component, &max_distance, input_coordinate, &big_component_distance](
const std::size_t /*num_results*/, const CandidateSegment &segment) {
const std::size_t /*num_results*/, const CandidateSegment &segment)
{
auto distance = GetSegmentDistance(input_coordinate, segment);
auto further_than_big_component = distance > big_component_distance;
auto no_more_candidates = has_big_component && further_than_big_component;
@@ -190,13 +226,17 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
PhantomNodeCandidates nearest_phantoms;
PhantomNodeCandidates big_component_phantoms;
const auto add_to_candidates = [this, &input_coordinate](PhantomNodeCandidates &candidates,
const EdgeData data) {
const auto add_to_candidates =
[this, &input_coordinate](PhantomNodeCandidates &candidates, const EdgeData data)
{
auto candidate_it =
std::find_if(candidates.begin(), candidates.end(), [&](const PhantomNode &node) {
return data.forward_segment_id.id == node.forward_segment_id.id &&
data.reverse_segment_id.id == node.reverse_segment_id.id;
});
std::find_if(candidates.begin(),
candidates.end(),
[&](const PhantomNode &node)
{
return data.forward_segment_id.id == node.forward_segment_id.id &&
data.reverse_segment_id.id == node.reverse_segment_id.id;
});
if (candidate_it == candidates.end())
{
// First candidate from this segment
@@ -259,17 +299,20 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
}
};
std::for_each(results.begin(), results.end(), [&](const CandidateSegment &segment) {
if (segment.fixed_projected_coordinate == nearest_coord)
{
add_to_candidates(nearest_phantoms, segment.data);
}
else
{
// Can only be from a big component for the alternative candidates
add_to_candidates(big_component_phantoms, segment.data);
}
});
std::for_each(results.begin(),
results.end(),
[&](const CandidateSegment &segment)
{
if (segment.fixed_projected_coordinate == nearest_coord)
{
add_to_candidates(nearest_phantoms, segment.data);
}
else
{
// Can only be from a big component for the alternative candidates
add_to_candidates(big_component_phantoms, segment.data);
}
});
return std::make_pair(std::move(nearest_phantoms), std::move(big_component_phantoms));
}
@@ -281,9 +324,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
std::transform(results.begin(),
results.end(),
distance_and_phantoms.begin(),
[this, &input_coordinate](const CandidateSegment &segment) {
return MakePhantomNode(input_coordinate, segment.data);
});
[this, &input_coordinate](const CandidateSegment &segment)
{ return MakePhantomNode(input_coordinate, segment.data); });
return distance_and_phantoms;
}
@@ -400,9 +442,8 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
}
// check phantom node segments validity
auto areSegmentsValid = [](auto first, auto last) -> bool {
return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last;
};
auto areSegmentsValid = [](auto first, auto last) -> bool
{ return std::find(first, last, INVALID_SEGMENT_WEIGHT) == last; };
bool is_forward_valid_source =
areSegmentsValid(forward_weights.begin(), forward_weights.end());
bool is_forward_valid_target = areSegmentsValid(
@@ -558,7 +599,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
{
bool isOnewaySegment =
!(segment.data.forward_segment_id.enabled && segment.data.reverse_segment_id.enabled);
if (!isOnewaySegment && approach == Approach::CURB)
if (!isOnewaySegment && (approach == Approach::CURB || approach == Approach::OPPOSITE))
{
// Check the counter clockwise
//
@@ -573,6 +614,9 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
if (datafacade.IsLeftHandDriving(segment.data.forward_segment_id.id))
input_coordinate_is_at_right = !input_coordinate_is_at_right;
if (approach == Approach::OPPOSITE)
input_coordinate_is_at_right = !input_coordinate_is_at_right;
return std::make_pair(input_coordinate_is_at_right, (!input_coordinate_is_at_right));
}
return std::make_pair(true, true);
+37 -28
View File
@@ -43,7 +43,8 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
const bool target_traversed_in_reverse)
{
// merges segments with same name id
const auto collapse_segments = [](std::vector<NamedSegment> &segments) {
const auto collapse_segments = [](std::vector<NamedSegment> &segments)
{
auto out = segments.begin();
auto end = segments.end();
@@ -75,7 +76,8 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
std::transform(route_data.begin(),
route_data.end(),
segments.begin(),
[&index, &facade](const PathData &point) {
[&index, &facade](const PathData &point)
{
return NamedSegment{point.duration_until_turn,
index++,
facade.GetNameIndex(point.from_edge_based_node)};
@@ -87,33 +89,37 @@ std::array<std::uint32_t, SegmentNumber> summarizeRoute(const datafacade::BaseDa
if (target_duration > EdgeDuration{1})
segments.push_back({target_duration, index++, facade.GetNameIndex(target_node_id)});
// this makes sure that the segment with the lowest position comes first
std::sort(
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
return lhs.name_id < rhs.name_id ||
(lhs.name_id == rhs.name_id && lhs.position < rhs.position);
});
std::sort(segments.begin(),
segments.end(),
[](const NamedSegment &lhs, const NamedSegment &rhs)
{
return lhs.name_id < rhs.name_id ||
(lhs.name_id == rhs.name_id && lhs.position < rhs.position);
});
auto new_end = collapse_segments(segments);
segments.resize(new_end - segments.begin());
// Filter out segments with an empty name (name_id == 0)
new_end = std::remove_if(segments.begin(), segments.end(), [](const NamedSegment &segment) {
return segment.name_id == 0;
});
new_end = std::remove_if(segments.begin(),
segments.end(),
[](const NamedSegment &segment) { return segment.name_id == 0; });
segments.resize(new_end - segments.begin());
// sort descending
std::sort(
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
return lhs.duration > rhs.duration ||
(lhs.duration == rhs.duration && lhs.position < rhs.position);
});
std::sort(segments.begin(),
segments.end(),
[](const NamedSegment &lhs, const NamedSegment &rhs)
{
return lhs.duration > rhs.duration ||
(lhs.duration == rhs.duration && lhs.position < rhs.position);
});
// make sure the segments are sorted by position
segments.resize(std::min(segments.size(), SegmentNumber));
std::sort(
segments.begin(), segments.end(), [](const NamedSegment &lhs, const NamedSegment &rhs) {
return lhs.position < rhs.position;
});
std::sort(segments.begin(),
segments.end(),
[](const NamedSegment &lhs, const NamedSegment &rhs)
{ return lhs.position < rhs.position; });
std::array<std::uint32_t, SegmentNumber> summary;
std::fill(summary.begin(), summary.end(), EMPTY_NAMEID);
@@ -138,7 +144,8 @@ inline std::string assembleSummary(const datafacade::BaseDataFacade &facade,
// transform a name_id into a string containing either the name, or -if the name is empty-
// the reference.
const auto name_id_to_string = [&](const NameID name_id) {
const auto name_id_to_string = [&](const NameID name_id)
{
const auto name = facade.GetNameForID(name_id);
if (!name.empty())
return std::string(name);
@@ -178,14 +185,16 @@ inline RouteLeg assembleLeg(const datafacade::BaseDataFacade &facade,
const auto target_weight =
(target_traversed_in_reverse ? target_node.reverse_weight : target_node.forward_weight);
auto duration = std::accumulate(
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
return sum + from_alias<double>(data.duration_until_turn);
});
auto weight = std::accumulate(
route_data.begin(), route_data.end(), 0, [](const double sum, const PathData &data) {
return sum + from_alias<double>(data.weight_until_turn);
});
auto duration = std::accumulate(route_data.begin(),
route_data.end(),
0,
[](const double sum, const PathData &data)
{ return sum + from_alias<double>(data.duration_until_turn); });
auto weight = std::accumulate(route_data.begin(),
route_data.end(),
0,
[](const double sum, const PathData &data)
{ return sum + from_alias<double>(data.weight_until_turn); });
// s
// |
@@ -16,7 +16,7 @@ bool basicCollapsePreconditions(const RouteStepIterator first,
// Staggered intersection are very short zig-zags of a few meters.
// We do not want to announce these short left-rights or right-lefts:
// 
//  
// * -> b a -> *
// | or | becomes a -> b
// a -> * * -> b
@@ -26,7 +26,7 @@ bool isStaggeredIntersection(const RouteStepIterator step_prior_to_intersection,
// Two two turns following close after another, we can announce them as a U-Turn if both end up
// involving the same (segregated) road.
// 
//  
// b < - y
// | will be represented by at x, turn around instead of turn left at x, turn left at y
// a - > x
@@ -42,11 +42,11 @@ bool isNameOszillation(const RouteStepIterator step_prior_to_intersection,
// Sometimes, segments names don't match the perceived turns. We try to detect these additional
// name changes and issue a combined turn.
// 
//  
// | e |
// a - b - c
// d
// 
//  
// can have `a-b` as one name, `b-c-d` as a second. At `b` we would issue a new name, even though
// the road turns right after. The offset would only be there due to the broad road at `e`
bool maneuverPreceededByNameChange(const RouteStepIterator step_prior_to_intersection,
@@ -73,11 +73,11 @@ bool doubleChoiceless(const RouteStepIterator step_entering_intersection,
// Due to obvious detection, sometimes we can have straight turns followed by a different turn right
// next to each other. We combine both turns into one, if the second turn is without choice
// 
//  e
//  
//   e
// a - b - c
// ' d
// 
//  
// with a main road `abd`, the turn `continue straight` at `b` and `turn left at `c` will become a
// `turn left` at `b`
bool straightTurnFollowedByChoiceless(const RouteStepIterator step_entering_intersection,
+3 -5
View File
@@ -1,7 +1,6 @@
#ifndef OSRM_ENGINE_GUIDANCE_COLLAPSE_HPP
#include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include <type_traits>
#include <vector>
@@ -12,16 +11,15 @@ namespace osrm::engine::guidance
// Multiple possible reasons can result in unnecessary/confusing instructions
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
[[nodiscard]] std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
// Multiple possible reasons can result in unnecessary/confusing instructions
// A prime example would be a segregated intersection. Turning around at this
// intersection would result in two instructions to turn left.
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseSegregatedTurnInstructions(std::vector<RouteStep> steps);
[[nodiscard]] std::vector<RouteStep>
collapseSegregatedTurnInstructions(std::vector<RouteStep> steps);
// A combined turn is a set of two instructions that actually form a single turn, as far as we
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots
+11 -10
View File
@@ -3,7 +3,6 @@
#include "guidance/turn_instruction.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include "util/bearing.hpp"
#include "util/guidance/name_announcements.hpp"
@@ -122,9 +121,8 @@ inline bool haveSameMode(const RouteStep &first, const RouteStep &second, const
// alias for readability
inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
{
const auto has_name_or_ref = [](auto const &step) {
return !step.name.empty() || !step.ref.empty();
};
const auto has_name_or_ref = [](auto const &step)
{ return !step.name.empty() || !step.ref.empty(); };
// make sure empty is not involved
if (!has_name_or_ref(lhs) || !has_name_or_ref(rhs))
@@ -151,12 +149,14 @@ inline bool haveSameName(const RouteStep &lhs, const RouteStep &rhs)
// alias for readability, both turn right | left
inline bool areSameSide(const RouteStep &lhs, const RouteStep &rhs)
{
const auto is_left = [](const RouteStep &step) {
const auto is_left = [](const RouteStep &step)
{
return hasModifier(step, osrm::guidance::DirectionModifier::Straight) ||
hasLeftModifier(step.maneuver.instruction);
};
const auto is_right = [](const RouteStep &step) {
const auto is_right = [](const RouteStep &step)
{
return hasModifier(step, osrm::guidance::DirectionModifier::Straight) ||
hasRightModifier(step.maneuver.instruction);
};
@@ -165,8 +165,7 @@ inline bool areSameSide(const RouteStep &lhs, const RouteStep &rhs)
}
// do this after invalidating any steps to compress the step array again
OSRM_ATTR_WARN_UNUSED
inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
[[nodiscard]] inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
{
// finally clean up the post-processed instructions.
// Remove all invalid instructions from the set of instructions.
@@ -174,7 +173,8 @@ inline std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> st
// Two valid NO_TURNs exist in each leg in the form of Depart/Arrive
// keep valid instructions
const auto not_is_valid = [](const RouteStep &step) {
const auto not_is_valid = [](const RouteStep &step)
{
return step.maneuver.instruction == osrm::guidance::TurnInstruction::NO_TURN() &&
step.maneuver.waypoint_type == WaypointType::None;
};
@@ -225,7 +225,8 @@ inline double totalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_
inline bool bearingsAreReversed(const double bearing_in, const double bearing_out)
{
// Nearly perfectly reversed angles have a difference close to 180 degrees (straight)
const double left_turn_angle = [&]() {
const double left_turn_angle = [&]()
{
if (0 <= bearing_out && bearing_out <= bearing_in)
return bearing_in - bearing_out;
return bearing_in + 360 - bearing_out;
+5 -6
View File
@@ -1,10 +1,9 @@
#ifndef OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#define OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#include <vector>
#include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include <vector>
namespace osrm::engine::guidance
{
@@ -14,9 +13,9 @@ namespace osrm::engine::guidance
// we anticipate lane changes emitting only matching lanes early on.
// the second parameter describes the duration that we feel two segments need to be apart to count
// as separate maneuvers.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
const double min_distance_needed_for_lane_change = 200);
[[nodiscard]] std::vector<RouteStep>
anticipateLaneChange(std::vector<RouteStep> steps,
const double min_distance_needed_for_lane_change = 200);
} // namespace osrm::engine::guidance
+8 -12
View File
@@ -5,7 +5,6 @@
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
#include "engine/phantom_node.hpp"
#include "util/attributes.hpp"
#include <vector>
@@ -13,8 +12,7 @@ namespace osrm::engine::guidance
{
// passed as none-reference to modify in-place and move out again
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
[[nodiscard]] std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
// trim initial/final segment of very short length.
// This function uses in/out parameter passing to modify both steps and geometry in place.
@@ -24,23 +22,21 @@ std::vector<RouteStep> handleRoundabouts(std::vector<RouteStep> steps);
void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry);
// assign relative locations to depart/arrive instructions
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
const LegGeometry &geometry,
const PhantomNode &source_node,
const PhantomNode &target_node);
[[nodiscard]] std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
const LegGeometry &geometry,
const PhantomNode &source_node,
const PhantomNode &target_node);
// collapse suppressed instructions remaining into intersections array
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
[[nodiscard]] std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
// postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself.
// If required, we can get both in sync again using this function.
// Move in LegGeometry for modification in place.
OSRM_ATTR_WARN_UNUSED
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps);
[[nodiscard]] LegGeometry resyncGeometry(LegGeometry leg_geometry,
const std::vector<RouteStep> &steps);
/**
* Apply maneuver override relations to the selected route.
@@ -20,14 +20,16 @@ template <typename Iter, typename Fn> inline Fn forEachRoundabout(Iter first, It
{
while (first != last)
{
const auto enter = std::find_if(first, last, [](const RouteStep &step) {
return entersRoundabout(step.maneuver.instruction);
});
const auto enter = std::find_if(first,
last,
[](const RouteStep &step)
{ return entersRoundabout(step.maneuver.instruction); });
// enter has to come before leave, otherwise: faulty data / partial roundabout, skip those
const auto leave = std::find_if(enter, last, [](const RouteStep &step) {
return leavesRoundabout(step.maneuver.instruction);
});
const auto leave = std::find_if(enter,
last,
[](const RouteStep &step)
{ return leavesRoundabout(step.maneuver.instruction); });
// No roundabouts, or partial one (like start / end inside a roundabout)
if (enter == last || leave == last)
@@ -2,7 +2,6 @@
#define OSRM_ENGINE_GUIDANCE_VERBOSITY_REDUCTION_HPP_
#include "engine/guidance/route_step.hpp"
#include "util/attributes.hpp"
#include <vector>
@@ -13,8 +12,7 @@ namespace osrm::engine::guidance
// to announce them. All these that are not collapsed into a single turn (think segregated
// intersection) have to be checked for the length they are active in. If they are active for a
// short distance only, we don't announce them
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps);
[[nodiscard]] std::vector<RouteStep> suppressShortNameSegments(std::vector<RouteStep> steps);
} // namespace osrm::engine::guidance
@@ -6,7 +6,7 @@
#include <utility>
#include <vector>
#include <boost/math/constants/constants.hpp>
#include <numbers>
namespace osrm::engine::map_matching
{
@@ -21,10 +21,8 @@ struct NormalDistribution
// FIXME implement log-probability version since it's faster
double Density(const double val) const
{
using namespace boost::math::constants;
const double x = val - mean;
return 1.0 / (std::sqrt(two_pi<double>()) * standard_deviation) *
return 1.0 / (std::sqrt(2 * std::numbers::pi) * standard_deviation) *
std::exp(-x * x / (standard_deviation * standard_deviation));
}
@@ -4,7 +4,7 @@
#include "util/integer_range.hpp"
#include <boost/assert.hpp>
#include <boost/math/constants/constants.hpp>
#include <numbers>
#include <cmath>
@@ -14,7 +14,7 @@
namespace osrm::engine::map_matching
{
static const double log_2_pi = std::log(2. * boost::math::constants::pi<double>());
static const double log_2_pi = std::log(2. * std::numbers::pi);
static const double IMPOSSIBLE_LOG_PROB = -std::numeric_limits<double>::infinity();
static const double MINIMAL_LOG_PROB = std::numeric_limits<double>::lowest();
static const std::size_t INVALID_STATE = std::numeric_limits<std::size_t>::max();
@@ -2,7 +2,7 @@
#define ENGINE_MAP_MATCHING_CONFIDENCE_HPP
#include "engine/map_matching/bayes_classifier.hpp"
#include <boost/assert.hpp>
#include <cmath>
namespace osrm::engine::map_matching
+4 -4
View File
@@ -259,10 +259,10 @@ inline util::Coordinate candidatesInputLocation(const PhantomNodeCandidates &can
inline bool candidatesHaveComponent(const PhantomNodeCandidates &candidates, uint32_t component_id)
{
return std::any_of(
candidates.begin(), candidates.end(), [component_id](const PhantomNode &node) {
return node.component.id == component_id;
});
return std::any_of(candidates.begin(),
candidates.end(),
[component_id](const PhantomNode &node)
{ return node.component.id == component_id; });
}
struct PhantomEndpoints
+36 -36
View File
@@ -33,10 +33,10 @@ class BasePlugin
bool CheckAllCoordinates(const std::vector<util::Coordinate> &coordinates) const
{
return !std::any_of(
std::begin(coordinates), std::end(coordinates), [](const util::Coordinate coordinate) {
return !coordinate.IsValid();
});
return !std::any_of(std::begin(coordinates),
std::end(coordinates),
[](const util::Coordinate coordinate)
{ return !coordinate.IsValid(); });
}
bool CheckAlgorithms(const api::BaseParameters &params,
@@ -95,7 +95,7 @@ class BasePlugin
const std::string &message,
osrm::engine::api::ResultT &result) const
{
mapbox::util::apply_visitor(ErrorRenderer(code, message), result);
std::visit(ErrorRenderer(code, message), result);
return Status::Error;
}
@@ -105,45 +105,45 @@ class BasePlugin
{
// are all phantoms from a tiny cc?
const auto all_in_same_tiny_component =
[](const std::vector<PhantomCandidateAlternatives> &alts_list) {
return std::any_of(
alts_list.front().first.begin(),
alts_list.front().first.end(),
// For each of the first possible phantoms, check if all other
// positions in the list have a phantom from the same small component.
[&](const PhantomNode &phantom) {
if (!phantom.component.is_tiny)
{
return false;
}
const auto component_id = phantom.component.id;
return std::all_of(
std::next(alts_list.begin()),
std::end(alts_list),
[component_id](const PhantomCandidateAlternatives &alternatives) {
return candidatesHaveComponent(alternatives.first, component_id);
});
});
};
[](const std::vector<PhantomCandidateAlternatives> &alts_list)
{
return std::any_of(
alts_list.front().first.begin(),
alts_list.front().first.end(),
// For each of the first possible phantoms, check if all other
// positions in the list have a phantom from the same small component.
[&](const PhantomNode &phantom)
{
if (!phantom.component.is_tiny)
{
return false;
}
const auto component_id = phantom.component.id;
return std::all_of(
std::next(alts_list.begin()),
std::end(alts_list),
[component_id](const PhantomCandidateAlternatives &alternatives)
{ return candidatesHaveComponent(alternatives.first, component_id); });
});
};
// Move the alternative into the final list
const auto fallback_to_big_component = [](PhantomCandidateAlternatives &alternatives) {
const auto fallback_to_big_component = [](PhantomCandidateAlternatives &alternatives)
{
auto no_big_alternative = alternatives.second.empty();
return no_big_alternative ? std::move(alternatives.first)
: std::move(alternatives.second);
};
// Move the alternative into the final list
const auto use_closed_phantom = [](PhantomCandidateAlternatives &alternatives) {
return std::move(alternatives.first);
};
const auto use_closed_phantom = [](PhantomCandidateAlternatives &alternatives)
{ return std::move(alternatives.first); };
const auto no_alternatives =
std::all_of(alternatives_list.begin(),
alternatives_list.end(),
[](const PhantomCandidateAlternatives &alternatives) {
return alternatives.second.empty();
});
[](const PhantomCandidateAlternatives &alternatives)
{ return alternatives.second.empty(); });
std::vector<PhantomNodeCandidates> snapped_phantoms;
snapped_phantoms.reserve(alternatives_list.size());
@@ -313,12 +313,12 @@ class BasePlugin
alternatives.end(),
coordinates.begin(),
coordinates.end(),
[](const auto &candidates_pair, const auto &coordinate) {
[](const auto &candidates_pair, const auto &coordinate)
{
return std::any_of(candidates_pair.first.begin(),
candidates_pair.first.end(),
[&](const auto &phantom) {
return phantom.input_location == coordinate;
});
[&](const auto &phantom)
{ return phantom.input_location == coordinate; });
});
std::size_t missing_index = std::distance(alternatives.begin(), mismatch.first);
return std::string("Could not find a matching segment for coordinate ") +
+2 -1
View File
@@ -39,7 +39,8 @@ std::string encodePolyline(CoordVectorForwardIter begin, CoordVectorForwardIter
begin,
end,
[&delta_numbers, &current_lat, &current_lon, coordinate_to_polyline](
const util::Coordinate loc) {
const util::Coordinate loc)
{
const int lat_diff =
std::round(static_cast<int>(loc.lat) * coordinate_to_polyline) - current_lat;
const int lon_diff =
@@ -71,24 +71,27 @@ void insertTargetInReverseHeap(Heap &reverse_heap, const PhantomNode &target)
static constexpr bool FORWARD_DIRECTION = true;
static constexpr bool REVERSE_DIRECTION = false;
// Identify nodes in the forward(reverse) search direction that will require loop forcing
// Identify nodes in the forward(reverse) search direction that will require step forcing
// e.g. if source and destination nodes are on the same segment.
std::vector<NodeID> getForwardLoopNodes(const PhantomEndpointCandidates &candidates);
std::vector<NodeID> getForwardLoopNodes(const PhantomCandidatesToTarget &candidates);
std::vector<NodeID> getBackwardLoopNodes(const PhantomEndpointCandidates &candidates);
std::vector<NodeID> getBackwardLoopNodes(const PhantomCandidatesToTarget &candidates);
std::vector<NodeID> getForwardForceNodes(const PhantomEndpointCandidates &candidates);
std::vector<NodeID> getForwardForceNodes(const PhantomCandidatesToTarget &candidates);
std::vector<NodeID> getBackwardForceNodes(const PhantomEndpointCandidates &candidates);
std::vector<NodeID> getBackwardForceNodes(const PhantomCandidatesToTarget &candidates);
// Find the specific phantom node endpoints for a given path from a list of candidates.
PhantomEndpoints endpointsFromCandidates(const PhantomEndpointCandidates &candidates,
const std::vector<NodeID> &path);
template <typename HeapNodeT>
inline bool force_loop(const std::vector<NodeID> &force_nodes, const HeapNodeT &heap_node)
inline bool shouldForceStep(const std::vector<NodeID> &force_nodes,
const HeapNodeT &forward_heap_node,
const HeapNodeT &reverse_heap_node)
{
// if loops are forced, they are so at the source
return !force_nodes.empty() &&
std::find(force_nodes.begin(), force_nodes.end(), heap_node.node) != force_nodes.end() &&
heap_node.data.parent == heap_node.node;
// routing steps are forced when the node is a source of both forward and reverse search heaps.
return forward_heap_node.data.parent == forward_heap_node.node &&
reverse_heap_node.data.parent == reverse_heap_node.node &&
std::find(force_nodes.begin(), force_nodes.end(), forward_heap_node.node) !=
force_nodes.end();
}
template <typename Heap>
@@ -190,8 +193,10 @@ void annotatePath(const FacadeT &facade,
std::vector<SegmentDuration> duration_vector;
std::vector<DatasourceID> datasource_vector;
const auto get_segment_geometry = [&](const auto geometry_index) {
const auto copy = [](auto &vector, const auto range) {
const auto get_segment_geometry = [&](const auto geometry_index)
{
const auto copy = [](auto &vector, const auto range)
{
vector.resize(range.size());
std::copy(range.begin(), range.end(), vector.begin());
};
@@ -112,8 +112,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
NodeID &middle_node_id,
EdgeWeight &upper_bound,
EdgeWeight min_edge_offset,
const std::vector<NodeID> &force_loop_forward_nodes,
const std::vector<NodeID> &force_loop_reverse_nodes)
const std::vector<NodeID> &force_step_nodes)
{
auto heapNode = forward_heap.DeleteMinGetHeapNode();
const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node);
@@ -123,13 +122,13 @@ void routingStep(const DataFacade<Algorithm> &facade,
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
if (new_weight < upper_bound)
{
if (force_loop(force_loop_forward_nodes, heapNode) ||
force_loop(force_loop_reverse_nodes, heapNode) ||
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})
{
// check whether there is a loop present at the node
// Before forcing step, check whether there is a loop present at the node.
// We may find a valid weight path by following the loop.
for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
{
const auto &data = facade.GetEdgeData(edge);
@@ -294,9 +293,9 @@ EdgeDistance calculateEBGNodeAnnotations(const DataFacade<Algorithm> &facade,
// Look for an edge on the forward CH graph (.forward)
EdgeID smaller_edge_id =
facade.FindSmallestEdge(std::get<0>(edge), std::get<1>(edge), [](const auto &data) {
return data.forward;
});
facade.FindSmallestEdge(std::get<0>(edge),
std::get<1>(edge),
[](const auto &data) { return data.forward; });
// If we didn't find one there, the we might be looking at a part of the path that
// was found using the backward search. Here, we flip the node order (.second,
@@ -381,7 +380,8 @@ void unpackPath(const FacadeT &facade,
unpackPath(facade,
packed_path_begin,
packed_path_end,
[&](std::pair<NodeID, NodeID> &edge, const auto &edge_id) {
[&](std::pair<NodeID, NodeID> &edge, const auto &edge_id)
{
BOOST_ASSERT(edge.first == unpacked_nodes.back());
unpacked_nodes.push_back(edge.second);
unpacked_edges.push_back(edge_id);
@@ -420,23 +420,22 @@ void retrievePackedPathFromSingleManyToManyHeap(
// assumes that heaps are already setup correctly.
// ATTENTION: This only works if no additional offset is supplied next to the Phantom Node
// Offsets.
// In case additional offsets are supplied, you might have to force a loop first.
// A forced loop might be necessary, if source and target are on the same segment.
// In case additional offsets are supplied, you might have to force a routing step first.
// A forced step might be necessary, if source and target are on the same segment.
// If this is the case and the offsets of the respective direction are larger for the source
// than the target
// then a force loop is required (e.g. source_phantom.forward_segment_id ==
// then a force step is required (e.g. source_phantom.forward_segment_id ==
// target_phantom.forward_segment_id
// && source_phantom.GetForwardWeightPlusOffset() > target_phantom.GetForwardWeightPlusOffset())
// requires
// a force loop, if the heaps have been initialized with positive offsets.
// a force step, if the heaps have been initialized with positive offsets.
void search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const std::vector<NodeID> &force_loop_forward_node,
const std::vector<NodeID> &force_loop_reverse_node,
const std::vector<NodeID> &force_step_nodes,
const EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT);
template <typename PhantomEndpointT>
@@ -446,8 +445,7 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &packed_leg,
const std::vector<NodeID> &force_loop_forward_node,
const std::vector<NodeID> &force_loop_reverse_node,
const std::vector<NodeID> &force_step_nodes,
const PhantomEndpointT & /*endpoints*/,
const EdgeWeight duration_upper_bound = INVALID_EDGE_WEIGHT)
{
@@ -458,14 +456,13 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
reverse_heap,
weight,
packed_leg,
force_loop_forward_node,
force_loop_reverse_node,
force_step_nodes,
duration_upper_bound);
}
// Requires the heaps for be empty
// If heaps should be adjusted to be initialized outside of this function,
// the addition of force_loop parameters might be required
// the addition of force_step parameters might be required
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<ch::Algorithm> &facade,
SearchEngineData<Algorithm>::QueryHeap &forward_heap,
@@ -11,6 +11,7 @@
#include <boost/assert.hpp>
#include <algorithm>
#include <boost/core/ignore_unused.hpp>
#include <iterator>
#include <limits>
#include <tuple>
@@ -30,7 +31,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
const PhantomNode &source,
const PhantomNode &target)
{
auto level = [&partition, node](const SegmentID &source, const SegmentID &target) {
auto level = [&partition, node](const SegmentID &source, const SegmentID &target)
{
if (source.enabled && target.enabled)
return partition.GetQueryLevel(source.id, target.id, node);
return INVALID_LEVEL_ID;
@@ -59,7 +61,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
endpoint_candidates.source_phantoms.begin(),
endpoint_candidates.source_phantoms.end(),
INVALID_LEVEL_ID,
[&](LevelID current_level, const PhantomNode &source) {
[&](LevelID current_level, const PhantomNode &source)
{
return std::min(
current_level,
getNodeQueryLevel(partition, node, source, endpoint_candidates.target_phantom));
@@ -76,7 +79,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
endpoint_candidates.source_phantoms.begin(),
endpoint_candidates.source_phantoms.end(),
INVALID_LEVEL_ID,
[&](LevelID level_1, const PhantomNode &source) {
[&](LevelID level_1, const PhantomNode &source)
{
return std::min(
level_1,
std::accumulate(endpoint_candidates.target_phantoms.begin(),
@@ -119,7 +123,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
const NodeID node,
const PhantomNodeCandidates &candidates)
{
auto highest_different_level = [&partition, node](const SegmentID &segment) {
auto highest_different_level = [&partition, node](const SegmentID &segment)
{
return segment.enabled ? partition.GetHighestDifferentLevel(segment.id, node)
: INVALID_LEVEL_ID;
};
@@ -128,7 +133,8 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
std::accumulate(candidates.begin(),
candidates.end(),
INVALID_LEVEL_ID,
[&](LevelID current_level, const PhantomNode &phantom_node) {
[&](LevelID current_level, const PhantomNode &phantom_node)
{
auto highest_level =
std::min(highest_different_level(phantom_node.forward_segment_id),
highest_different_level(phantom_node.reverse_segment_id));
@@ -151,9 +157,11 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
// This is equivalent to min_{∀ source, target} partition.GetQueryLevel(source, node, target)
auto init = getNodeQueryLevel(partition, node, candidates_list[phantom_index]);
auto result = std::accumulate(
phantom_indices.begin(), phantom_indices.end(), init, [&](LevelID level, size_t index) {
return std::min(level, getNodeQueryLevel(partition, node, candidates_list[index]));
});
phantom_indices.begin(),
phantom_indices.end(),
init,
[&](LevelID level, size_t index)
{ return std::min(level, getNodeQueryLevel(partition, node, candidates_list[index])); });
return result;
}
} // namespace
@@ -262,11 +270,30 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
return packed_path;
}
template <bool DIRECTION, typename Algorithm, typename... Args>
template <typename Heap>
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 <bool DIRECTION, typename Algorithm, typename Heap, typename... Args>
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
const typename SearchEngineData<Algorithm>::QueryHeap::HeapNode &heapNode,
const Args &... args)
Heap &forward_heap,
const typename Heap::HeapNode &heapNode,
const Args &...args)
{
const auto &partition = facade.GetMultiLevelPartition();
const auto &cells = facade.GetCellStorage();
@@ -274,14 +301,31 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const auto level = getNodeQueryLevel(partition, heapNode.node, args...);
static constexpr auto IS_MAP_MATCHING =
std::is_same_v<typename SearchEngineData<mld::Algorithm>::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());
@@ -291,19 +335,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &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
@@ -312,6 +360,20 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &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());
@@ -321,19 +383,22 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &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;
}
}
}
}
@@ -360,31 +425,32 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
const EdgeWeight to_weight =
heapNode.weight + node_weight + alias_cast<EdgeWeight>(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 <bool DIRECTION, typename Algorithm, typename... Args>
template <bool DIRECTION, typename Algorithm, typename Heap, typename... Args>
void routingStep(const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
Heap &forward_heap,
Heap &reverse_heap,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
const std::vector<NodeID> &force_loop_forward_nodes,
const std::vector<NodeID> &force_loop_reverse_nodes,
const Args &... args)
const std::vector<NodeID> &force_step_nodes,
const Args &...args)
{
const auto heapNode = forward_heap.DeleteMinGetHeapNode();
const auto weight = heapNode.weight;
@@ -402,11 +468,8 @@ void routingStep(const DataFacade<Algorithm> &facade,
auto reverse_weight = reverseHeapNode->weight;
auto path_weight = weight + reverse_weight;
// MLD uses loops forcing only to prune single node paths in forward and/or
// backward direction (there is no need to force loops in MLD but in CH)
if (!force_loop(force_loop_forward_nodes, heapNode) &&
!force_loop(force_loop_reverse_nodes, heapNode) && (path_weight >= EdgeWeight{0}) &&
(path_weight < path_upper_bound))
if (!shouldForceStep(force_step_nodes, heapNode, *reverseHeapNode) &&
(path_weight >= EdgeWeight{0}) && (path_weight < path_upper_bound))
{
middle_node = heapNode.node;
path_upper_bound = path_weight;
@@ -426,23 +489,19 @@ using UnpackedNodes = std::vector<NodeID>;
using UnpackedEdges = std::vector<EdgeID>;
using UnpackedPath = std::tuple<EdgeWeight, UnpackedNodes, UnpackedEdges>;
template <typename Algorithm, typename... Args>
UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const std::vector<NodeID> &force_loop_forward_nodes,
const std::vector<NodeID> &force_loop_reverse_nodes,
EdgeWeight weight_upper_bound,
const Args &... args)
template <typename Algorithm, typename Heap, typename... Args>
std::optional<std::pair<NodeID, EdgeWeight>> runSearch(const DataFacade<Algorithm> &facade,
Heap &forward_heap,
Heap &reverse_heap,
const std::vector<NodeID> &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<NodeID>(), std::vector<EdgeID>());
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);
@@ -456,27 +515,15 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
{
if (!forward_heap.Empty())
{
routingStep<FORWARD_DIRECTION>(facade,
forward_heap,
reverse_heap,
middle,
weight,
force_loop_forward_nodes,
force_loop_reverse_nodes,
args...);
routingStep<FORWARD_DIRECTION>(
facade, forward_heap, reverse_heap, middle, weight, force_step_nodes, args...);
if (!forward_heap.Empty())
forward_heap_min = forward_heap.MinKey();
}
if (!reverse_heap.Empty())
{
routingStep<REVERSE_DIRECTION>(facade,
reverse_heap,
forward_heap,
middle,
weight,
force_loop_reverse_nodes,
force_loop_forward_nodes,
args...);
routingStep<REVERSE_DIRECTION>(
facade, reverse_heap, forward_heap, middle, weight, force_step_nodes, args...);
if (!reverse_heap.Empty())
reverse_heap_min = reverse_heap.MinKey();
}
@@ -484,10 +531,33 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
// No path found for both target nodes?
if (weight >= weight_upper_bound || SPECIAL_NODEID == middle)
{
return {};
}
return {{middle, weight}};
}
template <typename Algorithm, typename... Args>
UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const std::vector<NodeID> &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<NodeID>(), std::vector<EdgeID>());
}
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);
@@ -505,9 +575,7 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
for (auto const &packed_edge : packed_path)
{
NodeID source, target;
bool overlay_edge;
std::tie(source, target, overlay_edge) = packed_edge;
auto [source, target, overlay_edge] = packed_edge;
if (!overlay_edge)
{ // a base graph edge
unpacked_nodes.push_back(target);
@@ -527,21 +595,14 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
forward_heap.Insert(source, {0}, {source});
reverse_heap.Insert(target, {0}, {target});
// TODO: when structured bindings will be allowed change to
// auto [subpath_weight, subpath_source, subpath_target, subpath] = ...
EdgeWeight subpath_weight;
std::vector<NodeID> subpath_nodes;
std::vector<EdgeID> subpath_edges;
std::tie(subpath_weight, subpath_nodes, subpath_edges) =
search(engine_working_data,
facade,
forward_heap,
reverse_heap,
force_loop_forward_nodes,
force_loop_reverse_nodes,
INVALID_EDGE_WEIGHT,
sublevel,
parent_cell_id);
auto [subpath_weight, subpath_nodes, subpath_edges] = search(engine_working_data,
facade,
forward_heap,
reverse_heap,
force_step_nodes,
INVALID_EDGE_WEIGHT,
sublevel,
parent_cell_id);
BOOST_ASSERT(!subpath_edges.empty());
BOOST_ASSERT(subpath_nodes.size() > 1);
BOOST_ASSERT(subpath_nodes.front() == source);
@@ -555,6 +616,31 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
return std::make_tuple(weight, std::move(unpacked_nodes), std::move(unpacked_edges));
}
template <typename Algorithm, typename... Args>
EdgeDistance
searchDistance(SearchEngineData<Algorithm> &,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &reverse_heap,
const std::vector<NodeID> &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 <typename Algorithm, typename PhantomEndpointT>
inline void search(SearchEngineData<Algorithm> &engine_working_data,
@@ -563,8 +649,7 @@ inline void search(SearchEngineData<Algorithm> &engine_working_data,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
EdgeWeight &weight,
std::vector<NodeID> &unpacked_nodes,
const std::vector<NodeID> &force_loop_forward_node,
const std::vector<NodeID> &force_loop_reverse_node,
const std::vector<NodeID> &force_step_nodes,
const PhantomEndpointT &endpoints,
const EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
{
@@ -573,8 +658,7 @@ inline void search(SearchEngineData<Algorithm> &engine_working_data,
facade,
forward_heap,
reverse_heap,
force_loop_forward_node,
force_loop_reverse_node,
force_step_nodes,
weight_upper_bound,
endpoints);
}
@@ -601,7 +685,8 @@ void unpackPath(const FacadeT &facade,
util::for_each_pair(
packed_path_begin,
packed_path_end,
[&facade, &unpacked_nodes, &unpacked_edges](const auto from, const auto to) {
[&facade, &unpacked_nodes, &unpacked_edges](const auto from, const auto to)
{
unpacked_nodes.push_back(to);
unpacked_edges.push_back(facade.FindEdge(from, to));
});
@@ -613,8 +698,8 @@ void unpackPath(const FacadeT &facade,
template <typename Algorithm>
double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
const DataFacade<Algorithm> &facade,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::MapMatchingQueryHeap &reverse_heap,
const PhantomNode &source_phantom,
const PhantomNode &target_phantom,
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
@@ -622,31 +707,50 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
forward_heap.Clear();
reverse_heap.Clear();
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()});
}
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};
insertNodesInHeaps(forward_heap, reverse_heap, endpoints);
EdgeWeight weight = INVALID_EDGE_WEIGHT;
std::vector<NodeID> unpacked_nodes;
std::vector<EdgeID> unpacked_edges;
std::tie(weight, unpacked_nodes, unpacked_edges) = search(engine_working_data,
facade,
forward_heap,
reverse_heap,
{},
{},
weight_upper_bound,
endpoints);
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<double>::max();
}
std::vector<PathData> unpacked_path;
annotatePath(facade, endpoints, unpacked_nodes, unpacked_edges, unpacked_path);
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
return from_alias<double>(distance);
}
} // namespace osrm::engine::routing_algorithms::mld
@@ -19,8 +19,7 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
typename SearchEngineData<Algorithm>::QueryHeap &reverse_heap,
const PhantomEndpointCandidates &candidates,
const EdgeWeight &total_weight,
EdgeWeight &new_total_weight,
EdgeWeight &leg_weight,
std::vector<NodeID> &leg_packed_path)
{
forward_heap.Clear();
@@ -31,14 +30,14 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
if (source.IsValidForwardSource())
{
forward_heap.Insert(source.forward_segment_id.id,
total_weight - source.GetForwardWeightPlusOffset(),
EdgeWeight{0} - source.GetForwardWeightPlusOffset(),
source.forward_segment_id.id);
}
if (source.IsValidReverseSource())
{
forward_heap.Insert(source.reverse_segment_id.id,
total_weight - source.GetReverseWeightPlusOffset(),
EdgeWeight{0} - source.GetReverseWeightPlusOffset(),
source.reverse_segment_id.id);
}
}
@@ -62,10 +61,9 @@ void searchWithUTurn(SearchEngineData<Algorithm> &engine_working_data,
facade,
forward_heap,
reverse_heap,
new_total_weight,
leg_weight,
leg_packed_path,
getForwardLoopNodes(candidates),
getBackwardLoopNodes(candidates),
{},
candidates);
}
@@ -125,8 +123,7 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
reverse_heap,
new_total_weight_to_forward,
leg_packed_path_forward,
getForwardLoopNodes(candidates),
{},
getForwardForceNodes(candidates),
candidates);
}
@@ -165,8 +162,7 @@ void search(SearchEngineData<Algorithm> &engine_working_data,
reverse_heap,
new_total_weight_to_reverse,
leg_packed_path_reverse,
{},
getBackwardLoopNodes(candidates),
getBackwardForceNodes(candidates),
candidates);
}
}
@@ -248,7 +244,8 @@ constructRouteResult(const DataFacade<Algorithm> &facade,
auto source_it =
std::find_if(source_candidates.begin(),
source_candidates.end(),
[&start_node](const auto &source_phantom) {
[&start_node](const auto &source_phantom)
{
return (start_node == source_phantom.forward_segment_id.id ||
start_node == source_phantom.reverse_segment_id.id);
});
@@ -257,7 +254,8 @@ constructRouteResult(const DataFacade<Algorithm> &facade,
auto target_it =
std::find_if(target_candidates.begin(),
target_candidates.end(),
[&end_node](const auto &target_phantom) {
[&end_node](const auto &target_phantom)
{
return (end_node == target_phantom.forward_segment_id.id ||
end_node == target_phantom.reverse_segment_id.id);
});
@@ -302,7 +300,7 @@ shortestPathWithWaypointUTurns(SearchEngineData<Algorithm> &engine_working_data,
PhantomEndpointCandidates search_candidates{waypoint_candidates[i],
waypoint_candidates[i + 1]};
std::vector<NodeID> packed_leg;
EdgeWeight new_total_weight = INVALID_EDGE_WEIGHT;
EdgeWeight leg_weight = INVALID_EDGE_WEIGHT;
// We have a valid path up to this leg
BOOST_ASSERT(total_weight != INVALID_EDGE_WEIGHT);
@@ -311,16 +309,15 @@ shortestPathWithWaypointUTurns(SearchEngineData<Algorithm> &engine_working_data,
forward_heap,
reverse_heap,
search_candidates,
total_weight,
new_total_weight,
leg_weight,
packed_leg);
if (new_total_weight == INVALID_EDGE_WEIGHT)
if (leg_weight == INVALID_EDGE_WEIGHT)
return {};
packed_leg_begin.push_back(total_packed_path.size());
total_packed_path.insert(total_packed_path.end(), packed_leg.begin(), packed_leg.end());
total_weight = new_total_weight;
total_weight += leg_weight;
};
// Add sentinel
@@ -466,16 +463,16 @@ struct route_state
last.total_weight_to_forward.resize(init_candidates.size(), {0});
last.total_weight_to_reverse.resize(init_candidates.size(), {0});
// Initialize routability from source validity.
std::transform(
init_candidates.begin(),
init_candidates.end(),
std::back_inserter(last.reached_forward_node_target),
[](const PhantomNode &phantom_node) { return phantom_node.IsValidForwardSource(); });
std::transform(
init_candidates.begin(),
init_candidates.end(),
std::back_inserter(last.reached_reverse_node_target),
[](const PhantomNode &phantom_node) { return phantom_node.IsValidReverseSource(); });
std::transform(init_candidates.begin(),
init_candidates.end(),
std::back_inserter(last.reached_forward_node_target),
[](const PhantomNode &phantom_node)
{ return phantom_node.IsValidForwardSource(); });
std::transform(init_candidates.begin(),
init_candidates.end(),
std::back_inserter(last.reached_reverse_node_target),
[](const PhantomNode &phantom_node)
{ return phantom_node.IsValidReverseSource(); });
}
bool completeLeg()
@@ -613,15 +610,21 @@ struct route_state
{
// Find the segment from final leg with the shortest path
auto forward_range = util::irange<std::size_t>(0UL, last.total_weight_to_forward.size());
auto forward_min =
std::min_element(forward_range.begin(), forward_range.end(), [&](size_t a, size_t b) {
auto forward_min = std::min_element(
forward_range.begin(),
forward_range.end(),
[&](size_t a, size_t b)
{
return (last.total_weight_to_forward[a] < last.total_weight_to_forward[b] ||
(last.total_weight_to_forward[a] == last.total_weight_to_forward[b] &&
last.total_nodes_to_forward[a] < last.total_nodes_to_forward[b]));
});
auto reverse_range = util::irange<std::size_t>(0UL, last.total_weight_to_reverse.size());
auto reverse_min =
std::min_element(reverse_range.begin(), reverse_range.end(), [&](size_t a, size_t b) {
auto reverse_min = std::min_element(
reverse_range.begin(),
reverse_range.end(),
[&](size_t a, size_t b)
{
return (last.total_weight_to_reverse[a] < last.total_weight_to_reverse[b] ||
(last.total_weight_to_reverse[a] == last.total_weight_to_reverse[b] &&
last.total_nodes_to_reverse[a] < last.total_nodes_to_reverse[b]));
+29 -1
View File
@@ -12,7 +12,6 @@ namespace osrm::engine
// Algorithm-dependent heaps
// - CH algorithms use CH heaps
// - CoreCH algorithms use CH
// - MLD algorithms use MLD heaps
template <typename Algorithm> struct SearchEngineData
@@ -47,6 +46,7 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
util::UnorderedMapStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
static SearchEngineHeapPtr forward_heap_1;
@@ -56,6 +56,10 @@ template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
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 +78,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 +121,27 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
EdgeWeight,
ManyToManyMultiLayerDijkstraHeapData,
util::TwoLevelStorage<NodeID, int>>;
using MapMatchingQueryHeap = util::QueryHeap<NodeID,
NodeID,
EdgeWeight,
MapMatchingMultiLayerDijkstraHeapData,
util::TwoLevelStorage<NodeID, int>>;
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
using MapMatchingHeapPtr = boost::thread_specific_ptr<MapMatchingQueryHeap>;
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);
+3 -3
View File
@@ -27,9 +27,9 @@ inline auto getClassData(const std::size_t index)
inline bool isValidClassName(const std::string &name)
{
return std::find_if_not(name.begin(), name.end(), [](const auto c) {
return std::isalnum(c);
}) == name.end();
return std::find_if_not(name.begin(),
name.end(),
[](const auto c) { return std::isalnum(c); }) == name.end();
}
} // namespace osrm::extractor
@@ -125,9 +125,8 @@ inline std::string canonicalizeStringList(std::string strlist, const std::string
// collapse spaces; this is needed in case we expand "; X" => "; X" above
// but also makes sense to do irregardless of the fact - canonicalizing strings.
const auto spaces = [](unsigned char lhs, unsigned char rhs) {
return ::isspace(lhs) && ::isspace(rhs);
};
const auto spaces = [](unsigned char lhs, unsigned char rhs)
{ return ::isspace(lhs) && ::isspace(rhs); };
auto it = std::unique(begin(strlist), end(strlist), spaces);
strlist.erase(it, end(strlist));
+4 -2
View File
@@ -133,7 +133,8 @@ class ExtractionRelationContainer
(void)res; // prevent unused warning in release
}
auto MergeRefMap = [&](RelationRefMap &source, RelationRefMap &target) {
auto MergeRefMap = [&](RelationRefMap &source, RelationRefMap &target)
{
for (auto it : source)
{
auto &v = target[it.first];
@@ -151,7 +152,8 @@ class ExtractionRelationContainer
const RelationIDList &GetRelations(const OsmIDTyped &member_id) const
{
auto getFromMap = [this](std::uint64_t id,
const RelationRefMap &map) -> const RelationIDList & {
const RelationRefMap &map) -> const RelationIDList &
{
auto it = map.find(id);
if (it != map.end())
return it->second;
+5 -2
View File
@@ -1,6 +1,7 @@
#ifndef OSRM_EXTRACTION_SEGMENT_HPP
#define OSRM_EXTRACTION_SEGMENT_HPP
#include <extractor/node_based_edge.hpp>
#include <util/coordinate.hpp>
namespace osrm::extractor
@@ -12,9 +13,10 @@ struct ExtractionSegment
const osrm::util::Coordinate target_,
double distance_,
double weight_,
double duration_)
double duration_,
const NodeBasedEdgeClassification flags_)
: source(source_), target(target_), distance(distance_), weight(weight_),
duration(duration_)
duration(duration_), flags(flags_)
{
}
@@ -23,6 +25,7 @@ struct ExtractionSegment
const double distance;
double weight;
double duration;
const NodeBasedEdgeClassification flags;
};
} // namespace osrm::extractor
+1 -22
View File
@@ -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 <boost/functional/hash.hpp>
#include <boost/optional/optional_fwd.hpp>
#include <string>
#include <unordered_map>
@@ -18,25 +16,6 @@ class Way;
class Relation;
} // namespace osmium
namespace std
{
template <> struct hash<std::tuple<std::string, std::string, std::string, std::string, std::string>>
{
std::size_t operator()(
const std::tuple<std::string, std::string, std::string, std::string, std::string> &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
{
+2 -1
View File
@@ -453,7 +453,8 @@ void readRawNBGraph(const boost::filesystem::path &path,
coordinates.resize(number_of_nodes);
osm_node_ids.reserve(number_of_nodes);
auto index = 0;
auto decode = [&](const auto &current_node) {
auto decode = [&](const auto &current_node)
{
coordinates[index].lon = current_node.lon;
coordinates[index].lat = current_node.lat;
osm_node_ids.push_back(current_node.node_id);
+1 -1
View File
@@ -24,7 +24,7 @@ class GraphCompressor
public:
void Compress(const std::unordered_set<NodeID> &barrier_nodes,
const TrafficSignals &traffic_signals,
TrafficSignals &traffic_signals,
ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
@@ -7,8 +7,8 @@
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include <mapbox/variant.hpp>
#include <utility>
#include <variant>
namespace osrm::extractor
{
@@ -1,16 +1,15 @@
#ifndef OSRM_EXTRACTOR_INTERSECTION_COORDINATE_EXTRACTOR_HPP_
#define OSRM_EXTRACTOR_INTERSECTION_COORDINATE_EXTRACTOR_HPP_
#include <utility>
#include <vector>
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
#include "util/attributes.hpp"
#include "util/coordinate.hpp"
#include "util/node_based_graph.hpp"
#include <utility>
#include <vector>
namespace osrm::extractor::intersection
{
@@ -27,17 +26,16 @@ class CoordinateExtractor
* Note: The segment between intersection and turn coordinate can be zero, if the OSM modelling
* is unfortunate. See https://github.com/Project-OSRM/osrm-backend/issues/3470
*/
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCoordinateAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node,
const std::uint8_t number_of_in_lanes) const;
[[nodiscard]] util::Coordinate
GetCoordinateAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node,
const std::uint8_t number_of_in_lanes) const;
// Given a set of precomputed coordinates, select the representative coordinate along the road
// that best describes the turn
OSRM_ATTR_WARN_UNUSED
util::Coordinate
[[nodiscard]] util::Coordinate
ExtractRepresentativeCoordinate(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
@@ -47,7 +45,7 @@ class CoordinateExtractor
// instead of finding only a single coordinate, we can also list all coordinates along a
// road.
OSRM_ATTR_WARN_UNUSED std::vector<util::Coordinate>
[[nodiscard]] std::vector<util::Coordinate>
GetCoordinatesAlongRoad(const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
@@ -55,20 +53,18 @@ class CoordinateExtractor
// wrapper in case of normal forward edges (traversed_in_reverse = false, to_node =
// node_based_graph.GetTarget(turn_edge)
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
const EdgeID turn_edge) const;
[[nodiscard]] std::vector<util::Coordinate>
GetForwardCoordinatesAlongRoad(const NodeID from, const EdgeID turn_edge) const;
// a less precise way to compute coordinates along a route. Due to the heavy interaction of
// graph traversal and turn instructions, we often don't care for high precision. We only want
// to check for available connections in order, or find (with room for error) the straightmost
// turn. This function will offer a bit more error potential but allow for much higher
// performance
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
[[nodiscard]] util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
* of them, though.
@@ -90,22 +86,19 @@ class CoordinateExtractor
* The optional length cache needs to store the accumulated distance up to the respective
* coordinate index [0,d(0,1),...]
*/
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate>
[[nodiscard]] std::vector<util::Coordinate>
TrimCoordinatesToLength(std::vector<util::Coordinate> coordinates,
const double desired_length,
const std::vector<double> &length_cache = {}) const;
OSRM_ATTR_WARN_UNUSED
std::vector<double> PrepareLengthCache(const std::vector<util::Coordinate> &coordinates,
const double limit) const;
[[nodiscard]] std::vector<double>
PrepareLengthCache(const std::vector<util::Coordinate> &coordinates, const double limit) const;
/* when looking at a set of coordinates, this function allows trimming the vector to a smaller,
* only containing coordinates up to a given distance along the path. The last coordinate might
* be interpolated
*/
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate>
[[nodiscard]] std::vector<util::Coordinate>
TrimCoordinatesByLengthFront(std::vector<util::Coordinate> coordinates,
const double desired_length) const;
@@ -130,10 +123,9 @@ class CoordinateExtractor
*
* for fixpoint `b`, vector_base `d` and vector_head `e`
*/
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
const util::Coordinate vector_base,
const util::Coordinate vector_head) const;
[[nodiscard]] util::Coordinate GetCorrectedCoordinate(const util::Coordinate fixpoint,
const util::Coordinate vector_base,
const util::Coordinate vector_head) const;
/* generate a uniform vector of coordinates in same range distances
*
@@ -143,8 +135,7 @@ class CoordinateExtractor
* Into:
* x -- x -- x -- x -- x - x
*/
OSRM_ATTR_WARN_UNUSED
std::vector<util::Coordinate>
[[nodiscard]] std::vector<util::Coordinate>
SampleCoordinates(const std::vector<util::Coordinate> &coordinates,
const double length,
const double rate) const;
@@ -26,16 +26,14 @@ namespace osrm::extractor::intersection
inline auto makeCompareAngularDeviation(const double angle)
{
return [angle](const auto &lhs, const auto &rhs) {
return util::angularDeviation(lhs.angle, angle) < util::angularDeviation(rhs.angle, angle);
};
return [angle](const auto &lhs, const auto &rhs)
{ return util::angularDeviation(lhs.angle, angle) < util::angularDeviation(rhs.angle, angle); };
}
inline auto makeExtractLanesForRoad(const util::NodeBasedDynamicGraph &node_based_graph)
{
return [&node_based_graph](const auto &road) {
return node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
};
return [&node_based_graph](const auto &road)
{ return node_based_graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes(); };
}
// When viewing an intersection from an incoming edge, we can transform a shape into a view which
@@ -63,7 +61,10 @@ template <typename Self> struct EnableShapeOps
auto FindClosestBearing(double base_bearing) const
{
return std::min_element(
self()->begin(), self()->end(), [base_bearing](const auto &lhs, const auto &rhs) {
self()->begin(),
self()->end(),
[base_bearing](const auto &lhs, const auto &rhs)
{
return util::angularDeviation(lhs.perceived_bearing, base_bearing) <
util::angularDeviation(rhs.perceived_bearing, base_bearing);
});
@@ -81,7 +82,8 @@ template <typename Self> struct EnableShapeOps
BOOST_ASSERT(!self()->empty());
auto initial = converter(self()->front());
const auto extract_maximal_value = [&initial, converter](const auto &road) {
const auto extract_maximal_value = [&initial, converter](const auto &road)
{
initial = std::max(initial, converter(road));
return false;
};
@@ -191,8 +193,10 @@ template <typename Self> struct EnableIntersectionOps
auto findClosestTurn(const double angle, const UnaryPredicate filter) const
{
BOOST_ASSERT(!self()->empty());
const auto candidate =
boost::range::min_element(*self(), [angle, &filter](const auto &lhs, const auto &rhs) {
const auto candidate = boost::range::min_element(
*self(),
[angle, &filter](const auto &lhs, const auto &rhs)
{
const auto filtered_lhs = filter(lhs), filtered_rhs = filter(rhs);
const auto deviation_lhs = util::angularDeviation(lhs.angle, angle),
deviation_rhs = util::angularDeviation(rhs.angle, angle);
@@ -11,8 +11,8 @@
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <cstdint>
#include <optional>
#include <utility>
namespace osrm::extractor::intersection
@@ -42,10 +42,10 @@ class NodeBasedGraphWalker
* selector not provinding any further edge to traverse)
*/
template <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>> TraverseRoad(NodeID starting_at_node_id,
EdgeID following_edge_id,
accumulator_type &accumulator,
const selector_type &selector) const;
std::optional<std::pair<NodeID, EdgeID>> 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<EdgeID> 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<EdgeID> 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<EdgeID> 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<EdgeID> 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 <class accumulator_type, class selector_type>
boost::optional<std::pair<NodeID, EdgeID>>
std::optional<std::pair<NodeID, EdgeID>>
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<EdgeID> operator()(const NodeID,
const EdgeID,
const IntersectionView &intersection,
const util::NodeBasedDynamicGraph &,
const EdgeBasedNodeDataContainer &) const
std::optional<EdgeID> 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;
}
}
};
+7 -6
View File
@@ -8,10 +8,12 @@
#include "turn_path.hpp"
#include "util/integer_range.hpp"
#include "util/log.hpp"
#include "util/std_hash.hpp"
#include "util/vector_view.hpp"
#include <variant>
#include <algorithm>
#include <boost/functional/hash.hpp>
#include <mapbox/variant.hpp>
namespace osrm::extractor
{
@@ -147,7 +149,6 @@ struct UnresolvedManeuverOverride
namespace std
{
template <> struct hash<osrm::extractor::NodeBasedTurn>
{
using argument_type = osrm::extractor::NodeBasedTurn;
using result_type = std::size_t;
@@ -155,9 +156,9 @@ template <> struct hash<osrm::extractor::NodeBasedTurn>
{
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;
}
@@ -3,7 +3,7 @@
#include "maneuver_override.hpp"
#include <boost/optional.hpp>
#include <optional>
#include <string>
#include <vector>
@@ -55,7 +55,7 @@ class ManeuverOverrideRelationParser
{
public:
ManeuverOverrideRelationParser();
boost::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
std::optional<InputManeuverOverride> TryParse(const osmium::Relation &relation) const;
};
} // namespace osrm::extractor
@@ -39,7 +39,7 @@ class NodeBasedGraphFactory
NodeBasedGraphFactory(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
const TrafficSignals &traffic_signals,
TrafficSignals &traffic_signals,
std::unordered_set<NodeID> &&barriers,
std::vector<util::Coordinate> &&coordinates,
extractor::PackedOSMIDs &&osm_node_ids,
@@ -71,7 +71,7 @@ class NodeBasedGraphFactory
void Compress(ScriptingEnvironment &scripting_environment,
std::vector<TurnRestriction> &turn_restrictions,
std::vector<UnresolvedManeuverOverride> &maneuver_overrides,
const TrafficSignals &traffic_signals);
TrafficSignals &traffic_signals);
// Most ways are bidirectional, making the geometry in forward and backward direction the same,
// except for reversal. We make use of this fact by keeping only one representation of the
+2 -3
View File
@@ -32,9 +32,8 @@ template <typename RestrictionFilter> class NodeRestrictionMap
// Find all restrictions applicable to (from,via,to) turns
auto Restrictions(NodeID from, NodeID via, NodeID to) const
{
const auto turnFilter = [this, to](const auto &restriction) {
return index_filter(restriction) && restriction->IsTurnRestricted(to);
};
const auto turnFilter = [this, to](const auto &restriction)
{ return index_filter(restriction) && restriction->IsTurnRestricted(to); };
return getRange(from, via) | boost::adaptors::filtered(turnFilter);
};
+2 -2
View File
@@ -7,11 +7,11 @@
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <array>
#include <cstdint>
#include <optional>
namespace osrm::extractor
{
@@ -80,7 +80,7 @@ struct ProfileProperties
}
// Check if this classes are excludable
boost::optional<std::size_t> ClassesAreExcludable(ClassData classes) const
std::optional<std::size_t> ClassesAreExcludable(ClassData classes) const
{
auto iter = std::find(excludable_classes.begin(), excludable_classes.end(), classes);
if (iter != excludable_classes.end())
+1 -3
View File
@@ -1,12 +1,10 @@
#ifndef RESTRICTION_HPP
#define RESTRICTION_HPP
#include "turn_path.hpp"
#include "util/coordinate.hpp"
#include "util/opening_hours.hpp"
#include "util/typedefs.hpp"
#include "mapbox/variant.hpp"
#include "turn_path.hpp"
#include <limits>
namespace osrm::extractor
-1
View File
@@ -215,7 +215,6 @@ inline void read(storage::tar::FileReader &reader,
const std::string &name,
detail::NameTableImpl<Ownership> &name_table)
{
std::string buffer;
util::serialization::read(reader, name, name_table.indexed_data);
}
} // namespace osrm::extractor::serialization
+19 -4
View File
@@ -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 <boost/functional/hash.hpp>
#include <unordered_set>
#include <utility>
namespace osrm::extractor
{
@@ -12,12 +13,26 @@ namespace osrm::extractor
struct TrafficSignals
{
std::unordered_set<NodeID> bidirectional_nodes;
std::unordered_set<std::pair<NodeID, NodeID>, boost::hash<std::pair<NodeID, NodeID>>>
unidirectional_segments;
std::unordered_set<std::pair<NodeID, NodeID>> unidirectional_segments;
inline bool HasSignal(NodeID from, NodeID to) const
{
return bidirectional_nodes.count(to) > 0 || unidirectional_segments.count({from, to}) > 0;
return bidirectional_nodes.contains(to) || unidirectional_segments.contains({from, to});
}
void Compress(NodeID from, NodeID via, NodeID to)
{
bidirectional_nodes.erase(via);
if (unidirectional_segments.contains({via, to}))
{
unidirectional_segments.erase({via, to});
unidirectional_segments.insert({from, to});
}
if (unidirectional_segments.contains({via, from}))
{
unidirectional_segments.erase({via, from});
unidirectional_segments.insert({to, from});
}
}
};
} // namespace osrm::extractor
+2 -15
View File
@@ -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 <boost/functional/hash.hpp>
#include <bitset>
#include <cstddef>
#include <cstdint>
@@ -54,19 +53,7 @@ const constexpr Mask merge_to_right = 1u << 10u;
using TurnLaneDescription = std::vector<TurnLaneType::Mask>;
// 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<TurnLaneDescription, LaneDescriptionID, TurnLaneDescription_hash>;
using LaneDescriptionMap = util::ConcurrentIDMap<TurnLaneDescription, LaneDescriptionID>;
using TurnLanesIndexedArray =
std::tuple<std::vector<std::uint32_t>, std::vector<TurnLaneType::Mask>>;
+39 -39
View File
@@ -4,7 +4,7 @@
#include "util/typedefs.hpp"
#include <algorithm>
#include <mapbox/variant.hpp>
#include <variant>
#include <vector>
namespace osrm::extractor
@@ -61,50 +61,50 @@ struct InputViaWayPath
struct InputTurnPath
{
mapbox::util::variant<InputViaNodePath, InputViaWayPath> node_or_way;
std::variant<InputViaNodePath, InputViaWayPath> node_or_way;
TurnPathType Type() const
{
BOOST_ASSERT(node_or_way.which() < TurnPathType::NUM_TURN_PATH_TYPES);
return static_cast<TurnPathType>(node_or_way.which());
BOOST_ASSERT(node_or_way.index() < TurnPathType::NUM_TURN_PATH_TYPES);
return static_cast<TurnPathType>(node_or_way.index());
}
OSMWayID From() const
{
return node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH
? mapbox::util::get<InputViaNodePath>(node_or_way).from
: mapbox::util::get<InputViaWayPath>(node_or_way).from;
return node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH
? std::get<InputViaNodePath>(node_or_way).from
: std::get<InputViaWayPath>(node_or_way).from;
}
OSMWayID To() const
{
return node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH
? mapbox::util::get<InputViaNodePath>(node_or_way).to
: mapbox::util::get<InputViaWayPath>(node_or_way).to;
return node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH
? std::get<InputViaNodePath>(node_or_way).to
: std::get<InputViaWayPath>(node_or_way).to;
}
InputViaWayPath &AsViaWayPath()
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_WAY_TURN_PATH);
return mapbox::util::get<InputViaWayPath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_WAY_TURN_PATH);
return std::get<InputViaWayPath>(node_or_way);
}
const InputViaWayPath &AsViaWayPath() const
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_WAY_TURN_PATH);
return mapbox::util::get<InputViaWayPath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_WAY_TURN_PATH);
return std::get<InputViaWayPath>(node_or_way);
}
InputViaNodePath &AsViaNodePath()
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH);
return mapbox::util::get<InputViaNodePath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH);
return std::get<InputViaNodePath>(node_or_way);
}
const InputViaNodePath &AsViaNodePath() const
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH);
return mapbox::util::get<InputViaNodePath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH);
return std::get<InputViaNodePath>(node_or_way);
}
};
@@ -175,63 +175,63 @@ struct ViaWayPath
// between node/way paths
struct TurnPath
{
mapbox::util::variant<ViaNodePath, ViaWayPath> node_or_way;
std::variant<ViaNodePath, ViaWayPath> node_or_way;
NodeID To() const
{
return node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH
? mapbox::util::get<ViaNodePath>(node_or_way).to
: mapbox::util::get<ViaWayPath>(node_or_way).to;
return node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH
? std::get<ViaNodePath>(node_or_way).to
: std::get<ViaWayPath>(node_or_way).to;
}
NodeID From() const
{
return node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH
? mapbox::util::get<ViaNodePath>(node_or_way).from
: mapbox::util::get<ViaWayPath>(node_or_way).from;
return node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH
? std::get<ViaNodePath>(node_or_way).from
: std::get<ViaWayPath>(node_or_way).from;
}
NodeID FirstVia() const
{
if (node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH)
if (node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH)
{
return mapbox::util::get<ViaNodePath>(node_or_way).via;
return std::get<ViaNodePath>(node_or_way).via;
}
else
{
BOOST_ASSERT(!mapbox::util::get<ViaWayPath>(node_or_way).via.empty());
return mapbox::util::get<ViaWayPath>(node_or_way).via[0];
BOOST_ASSERT(!std::get<ViaWayPath>(node_or_way).via.empty());
return std::get<ViaWayPath>(node_or_way).via[0];
}
}
ViaWayPath &AsViaWayPath()
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_WAY_TURN_PATH);
return mapbox::util::get<ViaWayPath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_WAY_TURN_PATH);
return std::get<ViaWayPath>(node_or_way);
}
const ViaWayPath &AsViaWayPath() const
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_WAY_TURN_PATH);
return mapbox::util::get<ViaWayPath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_WAY_TURN_PATH);
return std::get<ViaWayPath>(node_or_way);
}
ViaNodePath &AsViaNodePath()
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH);
return mapbox::util::get<ViaNodePath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH);
return std::get<ViaNodePath>(node_or_way);
}
const ViaNodePath &AsViaNodePath() const
{
BOOST_ASSERT(node_or_way.which() == TurnPathType::VIA_NODE_TURN_PATH);
return mapbox::util::get<ViaNodePath>(node_or_way);
BOOST_ASSERT(node_or_way.index() == TurnPathType::VIA_NODE_TURN_PATH);
return std::get<ViaNodePath>(node_or_way);
}
TurnPathType Type() const
{
BOOST_ASSERT(node_or_way.which() < TurnPathType::NUM_TURN_PATH_TYPES);
return static_cast<TurnPathType>(node_or_way.which());
BOOST_ASSERT(node_or_way.index() < TurnPathType::NUM_TURN_PATH_TYPES);
return static_cast<TurnPathType>(node_or_way.index());
}
bool operator==(const TurnPath &other) const
+18 -13
View File
@@ -15,11 +15,10 @@
#include <algorithm>
#include <cstddef>
#include <optional>
#include <utility>
#include <vector>
#include <boost/optional.hpp>
namespace osrm::guidance
{
@@ -129,7 +128,7 @@ class IntersectionHandler
// ^ via
//
// For this scenario returns intersection at `b` and `b`.
boost::optional<IntersectionHandler::IntersectionViewAndNode>
std::optional<IntersectionHandler::IntersectionViewAndNode>
getNextIntersection(const NodeID at, const EdgeID via) const;
bool isSameName(const EdgeID source_edge_id, const EdgeID target_edge_id) const;
@@ -187,11 +186,11 @@ IntersectionHandler::IsDistinctNarrowTurn(const EdgeID via_edge,
node_data_container.GetAnnotation(candidate_data.annotation_data);
auto const candidate_deviation = util::angularDeviation(candidate->angle, STRAIGHT_ANGLE);
auto const num_lanes = [](auto const &data) {
return data.flags.road_classification.GetNumberOfLanes();
};
auto const num_lanes = [](auto const &data)
{ return data.flags.road_classification.GetNumberOfLanes(); };
auto const lanes_number_equal = [&](auto const &compare_data) {
auto const lanes_number_equal = [&](auto const &compare_data)
{
// Check if the lanes number is the same going from the inbound edge to the compare road
return num_lanes(compare_data) > 0 && num_lanes(compare_data) == num_lanes(via_edge_data);
};
@@ -210,7 +209,8 @@ IntersectionHandler::IsDistinctNarrowTurn(const EdgeID via_edge,
// check if there are other narrow turns are not considered passing a low category or simply
// a link of the same type as the potentially obvious turn
auto const is_similar_turn = [&](auto const &road) {
auto const is_similar_turn = [&](auto const &road)
{
// 1. Skip the candidate road
if (road.eid == candidate->eid)
{
@@ -405,7 +405,8 @@ IntersectionHandler::IsDistinctWideTurn(const EdgeID via_edge,
// Deviation is larger than NARROW_TURN_ANGLE0 here for the candidate
// check if there is any turn, that might look just as obvious, even though it might not
// be allowed. Entry-allowed isn't considered a valid distinction criterion here
auto const is_similar_turn = [&](auto const &road) {
auto const is_similar_turn = [&](auto const &road)
{
// 1. Skip over our candidate
if (road.eid == candidate->eid)
return false;
@@ -503,7 +504,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
node_data_container.GetAnnotation(via_edge_data.annotation_data);
// implement a filter, taking out all roads of lower class or different names
auto const continues_on_name_with_higher_class = [&](auto const &road) {
auto const continues_on_name_with_higher_class = [&](auto const &road)
{
// it needs to be possible to enter the road
if (!road.entry_allowed)
return true;
@@ -550,7 +552,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
// this check is not part of the main conditions, so that if the turn looks obvious from all
// other perspectives, a mode change will not result in different classification
auto const to_index_if_valid = [&](auto const iterator) -> std::size_t {
auto const to_index_if_valid = [&](auto const iterator) -> std::size_t
{
auto const &from_data = node_based_graph.GetEdgeData(via_edge);
auto const &to_data = node_based_graph.GetEdgeData(iterator->eid);
@@ -577,7 +580,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
// opposed to before, we do not care about name changes, again: this is a filter, so internal
// false/true will be negated for selection
auto const valid_of_higher_or_same_category = [&](auto const &road) {
auto const valid_of_higher_or_same_category = [&](auto const &road)
{
if (!road.entry_allowed)
return true;
@@ -640,7 +644,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
const auto all_roads_have_same_name =
std::all_of(intersection.begin(),
intersection.end(),
[id = via_edge_annotation.name_id, this](auto const &road) {
[id = via_edge_annotation.name_id, this](auto const &road)
{
auto const data_id = node_based_graph.GetEdgeData(road.eid).annotation_data;
auto const name_id = node_data_container.GetAnnotation(data_id).name_id;
return (name_id != EMPTY_NAMEID) && (name_id == id);
+5 -10
View File
@@ -7,7 +7,6 @@
#include "guidance/intersection_handler.hpp"
#include "guidance/is_through_street.hpp"
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp"
#include <vector>
@@ -42,18 +41,14 @@ class MotorwayHandler final : public IntersectionHandler
Intersection intersection) const override final;
private:
OSRM_ATTR_WARN_UNUSED
Intersection handleSliproads(const NodeID intersection_node_id,
Intersection intersection) const;
[[nodiscard]] Intersection handleSliproads(const NodeID intersection_node_id,
Intersection intersection) const;
OSRM_ATTR_WARN_UNUSED
Intersection fromMotorway(const EdgeID via_edge, Intersection intersection) const;
[[nodiscard]] Intersection fromMotorway(const EdgeID via_edge, Intersection intersection) const;
OSRM_ATTR_WARN_UNUSED
Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
[[nodiscard]] Intersection fromRamp(const EdgeID via_edge, Intersection intersection) const;
OSRM_ATTR_WARN_UNUSED
Intersection fallback(Intersection intersection) const;
[[nodiscard]] Intersection fallback(Intersection intersection) const;
};
} // namespace osrm::guidance
+4 -7
View File
@@ -7,8 +7,6 @@
#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include "util/attributes.hpp"
namespace osrm::extractor::guidance
{
@@ -21,8 +19,7 @@ namespace osrm::extractor::guidance
// will be corrected to left|throught, since the final lane is not drivable.
// This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
// represents left|through|through
OSRM_ATTR_WARN_UNUSED
inline std::string
[[nodiscard]] inline std::string
trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
{
if (count_left)
@@ -68,10 +65,10 @@ trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t co
// turn:lanes=left|through|through|right
// vehicle:lanes=yes|yes|no|yes
// bicycle:lanes=yes|no|designated|yes
OSRM_ATTR_WARN_UNUSED
inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
[[nodiscard]] inline std::string applyAccessTokens(std::string lane_string,
const std::string &access_tokens)
{
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
using tokenizer = boost::tokenizer<boost::char_separator<char>>;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(lane_string, sep);
tokenizer access(access_tokens, sep);
+4 -5
View File
@@ -9,10 +9,9 @@
#include "util/node_based_graph.hpp"
#include <optional>
#include <vector>
#include <boost/optional.hpp>
namespace osrm::guidance
{
@@ -43,9 +42,9 @@ class SliproadHandler final : public IntersectionHandler
Intersection intersection) const override final;
private:
boost::optional<std::size_t> getObviousIndexWithSliproads(const EdgeID from,
const Intersection &intersection,
const NodeID at) const;
std::optional<std::size_t> 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;
+3 -6
View File
@@ -17,7 +17,6 @@
#include "guidance/turn_classification.hpp"
#include "guidance/turn_handler.hpp"
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp"
#include <cstdint>
@@ -47,13 +46,11 @@ class TurnAnalysis
/* Full Analysis Process for a single node/edge combination. Use with caution, as the process is
* relatively expensive */
OSRM_ATTR_WARN_UNUSED
Intersection operator()(const NodeID node_prior_to_intersection,
const EdgeID entering_via_edge) const;
[[nodiscard]] Intersection operator()(const NodeID node_prior_to_intersection,
const EdgeID entering_via_edge) const;
// Select turn types based on the intersection shape
OSRM_ATTR_WARN_UNUSED
Intersection
[[nodiscard]] Intersection
AssignTurnTypes(const NodeID from_node,
const EdgeID via_eid,
const extractor::intersection::IntersectionView &intersection) const;
+16 -21
View File
@@ -8,12 +8,10 @@
#include "guidance/intersection_handler.hpp"
#include "guidance/is_through_street.hpp"
#include "util/attributes.hpp"
#include "util/node_based_graph.hpp"
#include <boost/optional.hpp>
#include <cstddef>
#include <optional>
#include <utility>
#include <vector>
@@ -72,41 +70,38 @@ class TurnHandler final : public IntersectionHandler
bool hasObvious(const EdgeID &via_edge, const Fork &fork) const;
boost::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;
std::optional<Fork> findForkCandidatesByGeometry(Intersection &intersection) const;
bool isCompatibleByRoadClass(const Intersection &intersection, const Fork fork) const;
// Dead end.
OSRM_ATTR_WARN_UNUSED
Intersection handleOneWayTurn(Intersection intersection) const;
[[nodiscard]] Intersection handleOneWayTurn(Intersection intersection) const;
// Mode Changes, new names...
OSRM_ATTR_WARN_UNUSED
Intersection handleTwoWayTurn(const EdgeID via_edge, Intersection intersection) const;
[[nodiscard]] Intersection handleTwoWayTurn(const EdgeID via_edge,
Intersection intersection) const;
// Forks, T intersections and similar
OSRM_ATTR_WARN_UNUSED
Intersection handleThreeWayTurn(const EdgeID via_edge, Intersection intersection) const;
[[nodiscard]] Intersection handleThreeWayTurn(const EdgeID via_edge,
Intersection intersection) const;
// Handling of turns larger then degree three
OSRM_ATTR_WARN_UNUSED
Intersection handleComplexTurn(const EdgeID via_edge, Intersection intersection) const;
[[nodiscard]] Intersection handleComplexTurn(const EdgeID via_edge,
Intersection intersection) const;
void
handleDistinctConflict(const EdgeID via_edge, ConnectedRoad &left, ConnectedRoad &right) const;
// Classification
boost::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;
std::optional<Fork> findFork(const EdgeID via_edge, Intersection &intersection) const;
OSRM_ATTR_WARN_UNUSED
Intersection assignLeftTurns(const EdgeID via_edge,
Intersection intersection,
const std::size_t starting_at) const;
[[nodiscard]] Intersection assignLeftTurns(const EdgeID via_edge,
Intersection intersection,
const std::size_t starting_at) const;
OSRM_ATTR_WARN_UNUSED
Intersection assignRightTurns(const EdgeID via_edge,
Intersection intersection,
const std::size_t up_to) const;
[[nodiscard]] Intersection assignRightTurns(const EdgeID via_edge,
Intersection intersection,
const std::size_t up_to) const;
};
} // namespace osrm::guidance
+21 -23
View File
@@ -1,13 +1,13 @@
#ifndef OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#define OSRM_GUIDANCE_TURN_INSTRUCTION_HPP_
#include <algorithm>
#include <cstdint>
#include "guidance/roundabout_type.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp"
#include <algorithm>
#include <array>
#include <cstdint>
namespace osrm::guidance
{
@@ -154,24 +154,23 @@ inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs)
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const constexpr std::array<TurnType::Enum, 13> valid_types = {
TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto *first = valid_types;
const auto *last = first + sizeof(valid_types) / sizeof(valid_types[0]);
return std::find(first, last, instruction.type) != last;
return std::find(valid_types.cbegin(), valid_types.cend(), instruction.type) !=
valid_types.cend();
}
inline bool entersRoundabout(const guidance::TurnInstruction instruction)
@@ -243,8 +242,7 @@ inline guidance::DirectionModifier::Enum getTurnDirection(const double angle)
}
// swaps left <-> right modifier types
OSRM_ATTR_WARN_UNUSED
inline guidance::DirectionModifier::Enum
[[nodiscard]] inline guidance::DirectionModifier::Enum
mirrorDirectionModifier(const guidance::DirectionModifier::Enum modifier)
{
const constexpr guidance::DirectionModifier::Enum results[] = {
+2 -4
View File
@@ -3,14 +3,12 @@
#include "guidance/intersection.hpp"
#include "guidance/turn_lane_data.hpp"
#include "util/attributes.hpp"
namespace osrm::guidance::lanes
{
OSRM_ATTR_WARN_UNUSED
LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
const Intersection &intersection);
[[nodiscard]] LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
const Intersection &intersection);
} // namespace osrm::guidance::lanes
+2 -3
View File
@@ -2,7 +2,6 @@
#define OSRM_GUIDANCE_TURN_LANE_DATA_HPP_
#include "extractor/turn_lane_types.hpp"
#include "util/attributes.hpp"
#include "util/typedefs.hpp"
#include <vector>
@@ -23,8 +22,8 @@ struct TurnLaneData
using LaneDataVector = std::vector<TurnLaneData>;
// convertes a string given in the OSM format into a TurnLaneData vector
OSRM_ATTR_WARN_UNUSED
LaneDataVector laneDataFromDescription(const extractor::TurnLaneDescription &turn_lane_description);
[[nodiscard]] LaneDataVector
laneDataFromDescription(const extractor::TurnLaneDescription &turn_lane_description);
// Locate A Tag in a lane data vector (if multiple tags are set, the first one found is returned)
LaneDataVector::const_iterator findTag(const extractor::TurnLaneType::Mask tag,
+13 -15
View File
@@ -9,7 +9,6 @@
#include "guidance/turn_analysis.hpp"
#include "guidance/turn_lane_data.hpp"
#include "util/attributes.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
@@ -68,8 +67,8 @@ class TurnLaneHandler
~TurnLaneHandler();
OSRM_ATTR_WARN_UNUSED
Intersection assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection);
[[nodiscard]] Intersection
assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection);
private:
mutable std::atomic<std::size_t> count_handled;
@@ -108,24 +107,23 @@ class TurnLaneHandler
const Intersection &intersection) const;
// in case of a simple intersection, assign the lane entries
OSRM_ATTR_WARN_UNUSED
Intersection simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const LaneDescriptionID lane_string_id);
[[nodiscard]] Intersection simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const LaneDescriptionID lane_string_id);
// partition lane data into lane data relevant at current turn and at next turn
OSRM_ATTR_WARN_UNUSED
std::pair<TurnLaneHandler::LaneDataVector, TurnLaneHandler::LaneDataVector> partitionLaneData(
const NodeID at, LaneDataVector turn_lane_data, const Intersection &intersection) const;
[[nodiscard]] std::pair<TurnLaneHandler::LaneDataVector, TurnLaneHandler::LaneDataVector>
partitionLaneData(const NodeID at,
LaneDataVector turn_lane_data,
const Intersection &intersection) const;
// Sliproad turns have a separated lane to the right/left of other depicted lanes. These lanes
// are not necessarily separated clearly from the rest of the way. As a result, we combine both
// lane entries for our output, while performing the matching with the separated lanes only.
OSRM_ATTR_WARN_UNUSED
Intersection handleSliproadTurn(Intersection intersection,
const LaneDescriptionID lane_description_id,
LaneDataVector lane_data,
const Intersection &previous_intersection);
[[nodiscard]] Intersection handleSliproadTurn(Intersection intersection,
const LaneDescriptionID lane_description_id,
LaneDataVector lane_data,
const Intersection &previous_intersection);
// get the lane data for an intersection
void extractLaneData(const EdgeID via_edge,
+6 -7
View File
@@ -5,7 +5,6 @@
#include "guidance/turn_instruction.hpp"
#include "guidance/turn_lane_data.hpp"
#include "util/attributes.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
@@ -34,12 +33,12 @@ findBestMatchForReverse(const extractor::TurnLaneType::Mask leftmost_tag,
bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &lane_data);
// perform a trivial match on the turn lanes
OSRM_ATTR_WARN_UNUSED
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneDescriptionID lane_string_id,
util::guidance::LaneDataIdMap &lane_data_to_id);
[[nodiscard]] Intersection
triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneDescriptionID lane_string_id,
util::guidance::LaneDataIdMap &lane_data_to_id);
} // namespace osrm::guidance::lanes
+2 -2
View File
@@ -29,7 +29,7 @@ struct V8Renderer
for (const auto &keyValue : object.values)
{
Napi::Value child;
mapbox::util::apply_visitor(V8Renderer(env, child), keyValue.second);
std::visit(V8Renderer(env, child), keyValue.second);
obj.Set(keyValue.first, child);
}
out = obj;
@@ -41,7 +41,7 @@ struct V8Renderer
for (auto i = 0u; i < array.values.size(); ++i)
{
Napi::Value child;
mapbox::util::apply_visitor(V8Renderer(env, child), array.values[i]);
std::visit(V8Renderer(env, child), array.values[i]);
a.Set(i, child);
}
out = a;
+15 -15
View File
@@ -24,11 +24,11 @@
#include <boost/optional.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <string>
#include <variant>
#include <vector>
#include <exception>
@@ -51,7 +51,7 @@ struct PluginParameters
bool renderToBuffer = false;
};
using ObjectOrString = typename mapbox::util::variant<osrm::json::Object, std::string>;
using ObjectOrString = typename std::variant<osrm::json::Object, std::string>;
template <typename ResultT> inline Napi::Value render(const Napi::Env &env, const ResultT &result);
@@ -62,18 +62,18 @@ template <> Napi::Value inline render(const Napi::Env &env, const std::string &r
template <> Napi::Value inline render(const Napi::Env &env, const ObjectOrString &result)
{
if (result.is<osrm::json::Object>())
if (std::holds_alternative<osrm::json::Object>(result))
{
// Convert osrm::json object tree into matching v8 object tree
Napi::Value value;
renderToV8(env, value, result.get<osrm::json::Object>());
renderToV8(env, value, std::get<osrm::json::Object>(result));
return value;
}
else
{
// Return the string object as a node Buffer
return Napi::Buffer<char>::Copy(
env, result.get<std::string>().data(), result.get<std::string>().size());
env, std::get<std::string>(result).data(), std::get<std::string>(result).size());
}
}
@@ -96,7 +96,7 @@ inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &r
if (result_status == osrm::Status::Error)
{
throw std::logic_error(code_iter->second.get<osrm::json::String>().value.c_str());
throw std::logic_error(std::get<osrm::json::String>(code_iter->second).value.c_str());
}
result.values.erase(code_iter);
@@ -296,24 +296,19 @@ inline engine_config_ptr argumentsToEngineConfig(const Napi::CallbackInfo &args)
{
engine_config->algorithm = osrm::EngineConfig::Algorithm::CH;
}
else if (algorithm_str == "CoreCH")
{
engine_config->algorithm = osrm::EngineConfig::Algorithm::CH;
}
else if (algorithm_str == "MLD")
{
engine_config->algorithm = osrm::EngineConfig::Algorithm::MLD;
}
else
{
ThrowError(args.Env(), "algorithm option must be one of 'CH', 'CoreCH', or 'MLD'.");
ThrowError(args.Env(), "algorithm option must be one of 'CH', or 'MLD'.");
return engine_config_ptr();
}
}
else if (!algorithm.IsUndefined())
{
ThrowError(args.Env(),
"algorithm option must be a string and one of 'CH', 'CoreCH', or 'MLD'.");
ThrowError(args.Env(), "algorithm option must be a string and one of 'CH', or 'MLD'.");
return engine_config_ptr();
}
@@ -560,6 +555,10 @@ inline bool argumentsToParameter(const Napi::CallbackInfo &args,
{
params->approaches.push_back(osrm::Approach::CURB);
}
else if (approach_str == "opposite")
{
params->approaches.push_back(osrm::Approach::OPPOSITE);
}
else if (approach_str == "unrestricted")
{
params->approaches.push_back(osrm::Approach::UNRESTRICTED);
@@ -567,13 +566,14 @@ inline bool argumentsToParameter(const Napi::CallbackInfo &args,
else
{
ThrowError(args.Env(),
"'approaches' param must be one of [curb, unrestricted]");
"'approaches' param must be one of [curb, opposite, unrestricted]");
return false;
}
}
else
{
ThrowError(args.Env(), "Approach must be a string: [curb, unrestricted] or null");
ThrowError(args.Env(),
"Approach must be a string: [curb, opposite, unrestricted] or null");
return false;
}
}
+11 -8
View File
@@ -65,8 +65,8 @@ inline BisectionGraph makeBisectionGraph(const std::vector<util::Coordinate> &co
result_edges.reserve(edges.size());
// find the end of edges that belong to node_id
const auto advance_edge_itr = [&edges, &result_edges](const std::size_t node_id,
auto edge_itr) {
const auto advance_edge_itr = [&edges, &result_edges](const std::size_t node_id, auto edge_itr)
{
while (edge_itr != edges.end() && edge_itr->source == node_id)
{
result_edges.push_back(edge_itr->Reduce());
@@ -76,9 +76,9 @@ inline BisectionGraph makeBisectionGraph(const std::vector<util::Coordinate> &co
};
// create a bisection node, requires the ID of the node as well as the lower bound to its edges
const auto make_bisection_node = [&edges, &coordinates](const std::size_t node_id,
const auto begin_itr,
const auto end_itr) {
const auto make_bisection_node =
[&edges, &coordinates](const std::size_t node_id, const auto begin_itr, const auto end_itr)
{
std::size_t range_begin = std::distance(edges.begin(), begin_itr);
std::size_t range_end = std::distance(edges.begin(), end_itr);
return BisectionGraph::NodeT(range_begin, range_end, coordinates[node_id], node_id);
@@ -102,9 +102,12 @@ std::vector<BisectionInputEdge> adaptToBisectionEdge(std::vector<InputEdge> edge
std::vector<BisectionInputEdge> result;
result.reserve(edges.size());
std::transform(begin(edges), end(edges), std::back_inserter(result), [](const auto &edge) {
return BisectionInputEdge{edge.source, edge.target};
});
std::transform(begin(edges),
end(edges),
std::back_inserter(result),
[](const auto &edge) {
return BisectionInputEdge{edge.source, edge.target};
});
return result;
}
+6 -3
View File
@@ -298,7 +298,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
auto set_num_nodes_fn,
auto set_boundary_offset_fn,
auto begin,
auto end) {
auto end)
{
BOOST_ASSERT(std::distance(begin, end) > 0);
const auto cell_id = begin->first;
@@ -316,7 +317,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
util::for_each_range(
level_source_boundary.begin(),
level_source_boundary.end(),
[this, insert_cell_boundary](auto begin, auto end) {
[this, insert_cell_boundary](auto begin, auto end)
{
insert_cell_boundary(
source_boundary,
[](auto &cell, auto value) { cell.num_source_nodes = value; },
@@ -327,7 +329,8 @@ template <storage::Ownership Ownership> class CellStorageImpl
util::for_each_range(
level_destination_boundary.begin(),
level_destination_boundary.end(),
[this, insert_cell_boundary](auto begin, auto end) {
[this, insert_cell_boundary](auto begin, auto end)
{
insert_cell_boundary(
destination_boundary,
[](auto &cell, auto value) { cell.num_destination_nodes = value; },
+32 -24
View File
@@ -64,10 +64,13 @@ std::vector<OutputEdgeT> prepareEdgesForUsageInGraph(std::vector<extractor::Edge
// sort into blocks of edges with same source + target
// the we partition by the forward flag to sort all edges with a forward direction first.
// the we sort by weight to ensure the first forward edge is the smallest forward edge
std::sort(begin(edges), end(edges), [](const auto &lhs, const auto &rhs) {
return std::tie(lhs.source, lhs.target, rhs.data.forward, lhs.data.weight) <
std::tie(rhs.source, rhs.target, lhs.data.forward, rhs.data.weight);
});
std::sort(begin(edges),
end(edges),
[](const auto &lhs, const auto &rhs)
{
return std::tie(lhs.source, lhs.target, rhs.data.forward, lhs.data.weight) <
std::tie(rhs.source, rhs.target, lhs.data.forward, rhs.data.weight);
});
std::vector<OutputEdgeT> output_edges;
output_edges.reserve(edges.size());
@@ -77,10 +80,11 @@ std::vector<OutputEdgeT> prepareEdgesForUsageInGraph(std::vector<extractor::Edge
const NodeID source = begin_interval->source;
const NodeID target = begin_interval->target;
auto end_interval =
std::find_if_not(begin_interval, edges.end(), [source, target](const auto &edge) {
return std::tie(edge.source, edge.target) == std::tie(source, target);
});
auto end_interval = std::find_if_not(
begin_interval,
edges.end(),
[source, target](const auto &edge)
{ return std::tie(edge.source, edge.target) == std::tie(source, target); });
BOOST_ASSERT(begin_interval != end_interval);
// remove eigenloops
@@ -144,7 +148,8 @@ graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
auto max_turn_id = tbb::parallel_reduce(
range,
NodeID{0},
[&edge_based_graph](const auto range, NodeID initial) {
[&edge_based_graph](const auto range, NodeID initial)
{
NodeID max_turn_id = initial;
for (auto node = range.begin(); node < range.end(); ++node)
{
@@ -159,26 +164,29 @@ graphToEdges(const DynamicEdgeBasedGraph &edge_based_graph)
[](const NodeID lhs, const NodeID rhs) { return std::max(lhs, rhs); });
std::vector<extractor::EdgeBasedEdge> edges(max_turn_id + 1);
tbb::parallel_for(range, [&](const auto range) {
for (auto node = range.begin(); node < range.end(); ++node)
tbb::parallel_for(
range,
[&](const auto range)
{
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
for (auto node = range.begin(); node < range.end(); ++node)
{
const auto &data = edge_based_graph.GetEdgeData(edge);
// we only need to save the forward edges, since the read method will
// convert from forward to bi-directional edges again
if (data.forward)
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
{
auto target = edge_based_graph.GetTarget(edge);
BOOST_ASSERT(data.turn_id <= max_turn_id);
edges[data.turn_id] = extractor::EdgeBasedEdge{node, target, data};
// only save the forward edge
edges[data.turn_id].data.forward = true;
edges[data.turn_id].data.backward = false;
const auto &data = edge_based_graph.GetEdgeData(edge);
// we only need to save the forward edges, since the read method will
// convert from forward to bi-directional edges again
if (data.forward)
{
auto target = edge_based_graph.GetTarget(edge);
BOOST_ASSERT(data.turn_id <= max_turn_id);
edges[data.turn_id] = extractor::EdgeBasedEdge{node, target, data};
// only save the forward edge
edges[data.turn_id].data.forward = true;
edges[data.turn_id].data.backward = false;
}
}
}
}
});
});
return edges;
}
+13 -10
View File
@@ -159,10 +159,11 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
{
std::vector<LevelID> highest_border_level(edges.size());
std::transform(
edges.begin(), edges.end(), highest_border_level.begin(), [&mlp](const auto &edge) {
return mlp.GetHighestDifferentLevel(edge.source, edge.target);
});
std::transform(edges.begin(),
edges.end(),
highest_border_level.begin(),
[&mlp](const auto &edge)
{ return mlp.GetHighestDifferentLevel(edge.source, edge.target); });
return highest_border_level;
}
@@ -175,7 +176,8 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
tbb::parallel_sort(
permutation.begin(),
permutation.end(),
[&edges, &highest_border_level](const auto &lhs, const auto &rhs) {
[&edges, &highest_border_level](const auto &lhs, const auto &rhs)
{
// sort by source node and then by level in ascending order
return std::tie(edges[lhs].source, highest_border_level[lhs], edges[lhs].target) <
std::tie(edges[rhs].source, highest_border_level[rhs], edges[rhs].target);
@@ -201,11 +203,12 @@ class MultiLevelGraph : public util::StaticGraph<EdgeDataT, Ownership>
auto level_begin = iter;
for (auto level : util::irange<LevelID>(0, mlp.GetNumberOfLevels()))
{
iter = std::find_if(
iter, edge_and_level_end, [node, level](const auto &edge_and_level) {
return boost::get<0>(edge_and_level).source != node ||
boost::get<1>(edge_and_level) != level;
});
iter = std::find_if(iter,
edge_and_level_end,
[node, level](const auto &edge_and_level) {
return boost::get<0>(edge_and_level).source != node ||
boost::get<1>(edge_and_level) != level;
});
EdgeOffset offset = std::distance(level_begin, iter);
node_to_edge_offset.push_back(offset);
}
@@ -207,7 +207,8 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
auto lidx = 0UL;
util::for_each_pair(level_offsets.begin(),
level_offsets.begin() + num_level,
[&](const auto offset, const auto next_offset) {
[&](const auto offset, const auto next_offset)
{
// create mask that has `bits` ones at its LSBs.
// 000011
BOOST_ASSERT(offset <= NUM_PARTITION_BITS);
@@ -274,9 +275,8 @@ template <storage::Ownership Ownership> class MultiLevelPartitionImpl final
{
std::stable_sort(permutation.begin(),
permutation.end(),
[&partition](const auto lhs, const auto rhs) {
return partition[lhs] < partition[rhs];
});
[&partition](const auto lhs, const auto rhs)
{ return partition[lhs] < partition[rhs]; });
}
// top down assign new cell ids

Some files were not shown because too many files have changed in this diff Show More